40 lines
2.5 KiB
Markdown
40 lines
2.5 KiB
Markdown
|
|
---
|
||
|
|
type: ADR
|
||
|
|
id: "0087"
|
||
|
|
title: "JSON locale catalogs with Lara CLI synchronization"
|
||
|
|
status: active
|
||
|
|
date: 2026-04-27
|
||
|
|
supersedes:
|
||
|
|
- "0084"
|
||
|
|
---
|
||
|
|
|
||
|
|
## 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.json` is 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.ts` keeps 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.mjs` verifies that every locale catalog present in the repo matches the English keyset and only contains flat string values.
|
||
|
|
- Legacy stored preferences such as `zh-Hans` are normalized to the canonical `zh-CN` locale.
|
||
|
|
|
||
|
|
## Alternatives considered
|
||
|
|
|
||
|
|
- **Keep TypeScript dictionaries and point Lara at `.ts` files**: 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.
|