How to validate translation completeness for all tier-1 locales, both locally and in CI.
Overview
Section titled “Overview”The locale key parity check ensures every translation key present in the
reference locale (en) also exists in all other tier-1 locales (en, pt).
It runs automatically in CI on every push or PR that touches locale files.
Locale file conventions
Section titled “Locale file conventions”Locale files live in apps/dashboard/src/locales/ and follow a two-pattern
naming convention that mirrors the i18next namespace loading strategy:
| File | Namespace | Locale |
|---|---|---|
en.json | common | en |
pt.json | common | pt |
people.en.json | people | en |
people.pt.json | people | pt |
To add a new namespace foo for locale en, create foo.en.json.
The check script discovers all *.json files automatically.
Running locally
Section titled “Running locally”# From repo root — exits 0 if all tier-1 locales are completenode scripts/check-locale-keys.mjs
# Verbose: also prints extra keys present in non-reference localesnode scripts/check-locale-keys.mjs --verbose
# Via the root package.json shortcutpnpm locale:checkExample passing output
Section titled “Example passing output”Locale key parity check Locales dir : .../apps/dashboard/src/locales Reference : en Tier-1 : en, pt Namespaces : common, people
[common] 34 keys in reference (en) ✓ pt — complete (34 keys)
[people] 33 keys in reference (en) ✓ pt — complete (33 keys)
OK All tier-1 locales are complete (67 keys checked).Example failing output
Section titled “Example failing output” [common] 34 keys in reference (en) ✗ pt — 2 missing key(s): - common.admin - common.switch_workspace
FAIL 2 missing key(s) detected across tier-1 locales.CI workflow
Section titled “CI workflow”The check runs as a GitHub Actions job (locale-key-parity) defined in
.github/workflows/locale-check.yml. It is triggered on:
- push or pull_request — whenever files under
apps/dashboard/src/locales/**or the script itself change. - workflow_dispatch — manual trigger from the GitHub Actions tab.
The job requires no pnpm install because the script has no external dependencies (pure Node.js built-ins only).
Adding a new translation key
Section titled “Adding a new translation key”- Add the key to the reference locale file (
en.jsonor{namespace}.en.json). - Add the key with a translated value to every other tier-1 locale file.
- Run
pnpm locale:checklocally to confirm parity before pushing.
Missing a step will cause CI to fail with a message listing the exact key path and locale.
Adding a new tier-1 locale
Section titled “Adding a new tier-1 locale”- Create the locale JSON files for every namespace:
apps/dashboard/src/locales/{locale}.jsonapps/dashboard/src/locales/{namespace}.{locale}.jsonfor each namespace
- Add the locale code to
SUPPORTED_LOCALESinapps/dashboard/src/lib/locale.ts. - Add the locale code to the
TIER1_LOCALESarray inscripts/check-locale-keys.mjs. - Register the locale metadata via
registerLocale()inlocale.ts.
Tier-1 vs non-tier-1 locales
Section titled “Tier-1 vs non-tier-1 locales”Currently, all supported locales are tier-1:
| Locale | Code | Tier |
|---|---|---|
| English | en | 1 — reference |
| Portuguese | pt | 1 — strict |
Tier-1 locales must be 100% complete. If a future locale is added with only
partial coverage, lower it to a non-tier-1 tier by not including it in
TIER1_LOCALES — the script will skip the missing-key check for that locale.