2.5 KiB
2.5 KiB
type, id, title, status, date, supersedes
| type | id | title | status | date | supersedes | |
|---|---|---|---|---|---|---|
| ADR | 0087 | JSON locale catalogs with Lara CLI synchronization | active | 2026-04-27 |
|
Context
ADR-0084 established an app-owned localization layer in src/lib/i18n.ts with English fallback and hand-maintained TypeScript dictionaries. That was enough for the first localized UI surface, but it does not scale well to a broader locale matrix or machine-assisted translation workflows.
We now want Tolaria to support a wider set of locales and to automate translation updates with Lara CLI while keeping the runtime dependency-light and preserving the existing English fallback behavior.
Decision
Tolaria will keep its app-owned runtime localization layer, but the translation source-of-truth moves to flat JSON catalogs in src/lib/locales/.
src/lib/locales/en.jsonis the canonical source catalog.- Additional locale files use one JSON file per locale code (for example
zh-CN.json,fr-FR.json). src/lib/i18n.tskeeps fallback, interpolation, locale resolution, and props-down locale wiring, but it now loads locale catalogs from JSON files instead of TypeScript objects.- Lara CLI configuration lives in
lara.yaml, and translation runs happen through repo scripts (pnpm l10n:translate,pnpm l10n:translate:force). scripts/validate-locales.mjsverifies that every locale catalog present in the repo matches the English keyset and only contains flat string values.- Legacy stored preferences such as
zh-Hansare normalized to the canonicalzh-CNlocale.
Alternatives considered
- Keep TypeScript dictionaries and point Lara at
.tsfiles: possible, but JSON is the more standard interchange format for translation tooling and keeps diffs simpler for translators and reviewers. - Adopt a full frontend i18n framework now: rejected because Tolaria already has working locale propagation and fallback behavior, and the immediate need is better content management plus translation automation.
- Store translated strings outside the app repo: rejected because Tolaria's chrome localization should stay versioned with the app code that consumes it.
Consequences
- Translators and automation tools now work against plain JSON catalogs instead of editing source code.
- The runtime keeps English fallback behavior, so a missing locale file or missing key does not break app chrome.
- Locale additions become a data/config change first: add the locale metadata, run Lara, review JSON output, then ship.
- Localization work now has a dedicated validation step that can run in CI or before commit.