feat(i18n): ship Spanish

Register es next to ru (selector shows EN | ES | RU) and complete the
catalog against the current English: the 13 messages added since #602,
the "many" plural form Intl.PluralRules('es') selects for exact millions,
and fixes where the English had changed (e.g. "hace hace" in LIVE ·
updated, minutes written as metres). Terminology made consistent (buque,
aeronave, incendio activo); key names stay in English. Meir's wording is
kept everywhere else. Adds docs/translations/es.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
German KhokhlovandClaude Opus 5.5 committed 2026-10-12 14:33:43 +04:00
1 parent 47cfdb823e
commit 70936b58b9
9 files changed
+180 -51

No files matched your search

+2 -2
View File
@@ -3011,7 +3011,7 @@ test:track` 43 tracking invariants · headless QA harnesses under
### Interface localization (October 2026)
Shipped locales: **en** (source and fallback) and **ru**. The code lives in
Shipped locales: **en** (source and fallback), **es** and **ru**. The code lives in
`src/i18n/`. How to mark UI text: [`docs/I18N.md`](./I18N.md); translator workflow:
[`docs/TRANSLATORS.md`](./TRANSLATORS.md).
@@ -3022,7 +3022,7 @@ Shipped locales: **en** (source and fallback) and **ru**. The code lives in
value). English has no catalog; every other locale is
`src/i18n/locales/<code>.json`, and a missing entry falls back to English.
- **Locale choice.** `?lang=` (one-shot) → stored choice (`gev:locale:v1`) →
`navigator.languages` → English. The EN/RU switch in the Visual Presets dock
`navigator.languages` → English. The language switch in the Visual Presets dock
stores the choice and reloads, so nothing re-renders live.
- **Gate.** `npm run i18n` (and `src/i18n/catalog.test.mjs` under `npm test`)
extracts every message and fails on missing, unused, placeholder-mismatched or