feat(ui): locale persistence + i18n completeness guards (F3)
Tests · UI / test (push) Waiting to run
Tests · UI / test (pull_request) Successful in 2m11s

An audit found the client already i18n-first: one hard-coded UI string
(the battle-scene aria-label, now keyed) and en/ru already share an
identical 692-key set.

- Persist the locale: i18n.setLocale writes localStorage (galaxy-locale)
  and the store boots from stored > browser detection > default, so a
  language switch survives reloads.
- tests/i18n-completeness.test.ts: en/ru key-set parity, non-empty
  values, and locale persistence.
- Docs: ui/docs/i18n.md; mark F3 done in ui/PLAN-finalize.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ilia Denisov
2026-05-22 08:48:13 +02:00
parent c56050f5dd
commit 1e62837c68
7 changed files with 107 additions and 10 deletions
+11 -1
View File
@@ -69,7 +69,17 @@ axe-core scan; full keyboard reachability with visible focus.
Tests: axe-core integration tests on every top-level view; Playwright
keyboard-only navigation.
## F3 — Localisation completeness
## F3 — Localisation completeness — done
An audit found the client already i18n-first (the single hard-coded UI
string, the battle-scene `aria-label`, is now keyed); en/ru already have
identical key sets (692 keys). Added locale **persistence** to the i18n
store (`localStorage` `galaxy-locale`: stored choice > browser detection
> default) so a switch survives reloads, and
`tests/i18n-completeness.test.ts` enforcing en/ru key-set parity,
non-empty values, and persistence. A noisy literal-text lint was
deliberately skipped — the structural parity test plus the i18n-first
convention cover drift. Docs: `ui/docs/i18n.md`.
(From Phase 35.) Goal: every visible string is translated (en + ru).