chore(translations): add catalog verification script and update localization docs

This commit is contained in:
neon
2026-07-28 18:44:05 +00:00
parent 12ca966a79
commit c2884bd664
7 changed files with 488 additions and 224 deletions
+34 -2
View File
@@ -120,9 +120,40 @@ The shared locale list automatically updates the language picker, server prefere
Create `client/src/locales/<locale>.json` with the exact key structure from `en.json` and English fallback values. Do not add partial catalogs. Crowdin will replace fallback values as translations are completed.
A catalog may instead arrive already translated, for example from a bulk translation pass. That is allowed, but the translations then exist only in Git and Crowdin will overwrite them unless they are imported first. Follow "Seed existing translations into Crowdin" below before enabling export.
Review `client/src/stores/locale.ts` and add browser-locale matching coverage to `client/src/stores/__tests__/locale.spec.ts`, especially for regional variants. Add every CLDR plural category reported for the locale to each ICU plural message and extend the exhaustive ICU runtime tests in `client/src/i18n/icu.spec.ts`.
### 4. Allow Crowdin export and PR delivery
### 4. Seed existing translations into Crowdin
Skip this step when the catalog holds English fallback values. It applies only when the catalog already contains real translations.
Crowdin does not import repository translations on its own, and untranslated strings export as English source text. A pre-translated catalog that is never imported is therefore silently reverted to English by the first export.
Order matters, because merging the `crowdin.yml` change enables export for the language:
1. Pause translation synchronization, or keep the language out of `export_languages` until verification passes.
2. Add the target language in Crowdin.
3. Import the catalog with Crowdin's translation import, allowing translations that match the source so entries such as product names and identifiers are not dropped.
4. Verify, reconcile, and only then enable export.
**The progress percentage does not verify anything.** Crowdin's bulk translation import is lossy: it silently skips entries that the per-string translation endpoint accepts. Observed causes include translations that add punctuation the English source lacks, and ICU messages carrying a plural category the source does not use, such as Spanish or Portuguese `many`. A language can report 96 to 98 percent while real translations are missing, and those gaps export as English over good translations in Git.
Verify by building the export and diffing it against the catalog:
```bash
CROWDIN_TOKEN=... node scripts/crowdin-verify/verify.mjs es-ES es.json
```
The script exits non-zero while any key differs. Pass `--reconcile` to push the remaining strings through the per-string endpoint, which accepts what the bulk import rejected:
```bash
CROWDIN_TOKEN=... node scripts/crowdin-verify/verify.mjs es-ES es.json --reconcile
```
A language is safe to export only when the script reports zero differing keys. Run it for every seeded language before resuming synchronization.
### 5. Allow Crowdin export and PR delivery
Update `crowdin.yml`:
@@ -133,7 +164,7 @@ Update `scripts/classify-crowdin-pr.sh` to allow the new target catalog path. Do
Before merging, add the target language in Crowdin while the current `main` configuration still excludes it from `export_languages`, or pause translation synchronization. Merge the repository support before allowing the first export. After merge, run a manual source and translation sync and confirm that the generated PR changes only explicitly allowed target catalogs.
### 5. Verify the new language
### 6. Verify the new language
Run:
@@ -158,6 +189,7 @@ Then verify manually:
- Representative desktop and mobile screens handle translated text expansion.
- RTL layout, keyboard navigation, focus states, dialogs, menus, and popovers remain usable when applicable.
- A manual Crowdin export produces the expected filename and passes all PR checks.
- For a seeded catalog, `scripts/crowdin-verify/verify.mjs` reports zero differing keys.
Only enable scheduled export for the new language after this manual round trip succeeds.
+10 -2
View File
@@ -51,8 +51,16 @@ pagination limit.
The translation generator reads public Crowdin project statistics and renders
every language the project exposes, so no code change is needed when a language
is added. English is pinned first at 100% as the source language and is
excluded from the average. Up to eight languages render as horizontal bars;
beyond that the chart switches to a vertical bar chart with a fixed height.
excluded from the average, though it renders like any other completed row.
Every language is one horizontal meter row, so the card grows in height as
languages are added rather than switching layout. The label column is measured
from the widest language name and long names are truncated, which keeps the bar
from being squeezed out. Bars carry three progress tiers, listed in a legend on
the card: complete at 100%, in progress at 70% or above, and needs work below
that. Three is the ceiling; a fourth tier would need an amber that sits at
deuteranopia delta-E 1.4 against the orange, which no threshold tuning can
separate.
## Local commands