Skip to content

Translations cleanup - #155

Merged
kittendevv merged 5 commits into
kittendevv:mainfrom
Bouni:translations-cleanup
Oct 1, 2026
Merged

kittendevv merged 5 commits into
kittendevv:mainfrom
Bouni:translations-cleanup

Conversation

@Bouni

@Bouni Bouni commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Clean up and sync UI translations

The locale files had drifted from the frontend. Some locales were still keyed for an older UI, so many strings showed in English. Others were missing recently added strings. The key extraction script also missed several kinds of keys, so running it would have deleted translations that are still in use.

What changed

Locale files synced with the frontend

  • Every locale now has exactly the 332 keys the frontend uses, sorted alphabetically like the translations workflow does.
  • de, nl, pt-br were keyed for an older UI. 186 of their keys were no longer used, and 163 keys the current UI needs were missing and fell back to English. The old keys are removed and the missing ones translated.
  • es-ar, es-co, tr each gained the ~40 newer keys they were missing. es-ar also had 52 duplicate keys, which are removed.
  • Six keys that nothing used anymore were removed from all locales (Dark, Light, Demo mode warning, …).

Bug fix: blank names in delete confirmations
In de, nl and pt-br, the delete confirmations for categories, units and tax definitions used {{name}}, but the code passes {{code}}, so the name was always blank. They now use {{code}}.

Portuguese (Brazil) in the language selection
The pt-br translation existed and the backend accepted it, but it wasn't in the settings dropdown. It's there now. "Español (Argentina)" in en.json is also shown in its own language, like the other options.

extract-i18n-keys.js finds all keys

  • It now matches t("key", { params }). The old patterns only matched when ) came right after the key.
  • It recognises keys marked with the new tKey() (see below).
  • It handles escaped quotes in keys.
  • It uses ES module imports, so it runs under plain node too (package.json sets "type": "module").

tKey() marker for keys passed through variables
Some strings are defined in one place and passed to t() later through a variable, so the script couldn't see them: invoice statuses, settings section labels, breadcrumb labels and login error messages. They're now wrapped in tKey("..."), which does nothing at runtime except mark them for the script.

  • Statuses go through a new invoiceStatusLabel() helper instead of capitalizing the raw status where it's displayed.
  • Breadcrumbs now have an explicit "Users" label.

For contributors: if you define a string in one place and pass it to t() later through a variable, wrap it in tKey(). bun run sync-keys will then keep it.

TRANSLATIONS.md is regenerated: 332 keys, all locales complete.

Notes for reviewers

  • The ~200 new translations were written by an AI assistant without native-speaker review. Please have native speakers check them, especially nl, pt-br and tr.
  • Error messages that come from the backend on login and 2FA are still shown as returned. They're only translated if the same text exists as a key, same as before.

Testing

  • bun run sync-keys reports all keys in sync (332 keys, no missing or unused ones).
  • The translations check script passes for all locales.
  • Tested manually in the running app.

🤖 Generated with Claude Code

The "Notes for reviewers" section says plainly that the translations came from an AI and haven't had native-speaker review, so reviewers know what to check. To publish, run git push -u origin translations-cleanup and then open the PR. Or I can push it and open it with gh pr create if you'd like.

Bouni and others added 5 commits October 1, 2026 10:08
Statuses, settings section labels, breadcrumb labels and login errors
are defined in one place and passed to t() later through a variable, so
the key extractor could not see them and would treat them as unused.

Add a tKey() identity function that marks such strings at their
definition, and an invoiceStatusLabel() helper so the dashboard and
invoice detail page no longer build status keys by capitalizing the
raw status. Breadcrumbs also get an explicit "Users" label instead of
relying on the capitalized path segment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Match t("key", { params }) calls; the old patterns required the
  closing parenthesis right after the key and missed them
- Pick up keys marked with tKey()
- Unescape string literals so keys containing quotes match en.json
- Use ES module imports so the script also runs under plain node, as
  package.json declares "type": "module"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
de, nl and pt-br were still keyed for an older version of the UI: 186
of their keys were no longer used, while 163 keys the current UI uses
were missing and fell back to English. es-ar, es-co and tr were each
missing about 40 newer keys, and es-ar contained 52 duplicate keys.

- Remove keys no longer referenced anywhere in the frontend, from all
  locales
- Add missing keys to en.json and translate them for every locale
- Fix the category, unit and tax definition delete confirmations in
  de, nl and pt-br, which used {{name}} although the code passes
  {{code}}, so the name was always blank
- Show "Español (Argentina)" in its own language in en.json, like the
  other language options
- Sort keys, as the translations workflow does

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pt-br translation exists and both frontend and backend accept the
locale, but it was missing from the language dropdown in settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Bouni

Bouni commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@kittendevv This is my first PR where I use AI. I review all changes manually before submitting a PR and I also test everything as good as I can. Hope thats ok for you.

@kittendevv
kittendevv merged commit b6d948a into kittendevv:main Oct 1, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants