v0.247.0: i18n spike — the dashboard can speak English, Hungarian byte-identical
gates / gates (push) Successful in 19s
gates / gates (push) Successful in 19s
Message bundles (internal/i18n) expanded into templates before parsing, one template set per language. Launcher, /backups, /apps/<slug> and the layout converted; household language setting, POST /settings/language, ?lang= override, report field. Parity test against fixtures captured from unconverted templates; copy gates read templates expanded; new i18n_missing_gate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -1,3 +1,45 @@
|
||||
## v0.247.0 — the dashboard can speak English: mechanism proven on three pages, Hungarian byte-identical (2026-09-17, i18n spike)
|
||||
|
||||
**MinAgent: 0.131.0** (unchanged — nothing here talks to the agent). **No hub release needed:** the
|
||||
report gains an additive `language` field the hub stores raw and does not read yet.
|
||||
|
||||
**Nothing changes for a household.** Hungarian stays the default and the only language shown; the
|
||||
switch appears only on an English page or a request carrying `?lang=`.
|
||||
|
||||
- **Mechanism — a flat message bundle, expanded BEFORE the template is parsed.**
|
||||
`internal/i18n/locales/{hu,en}.json` (embedded; hu authoritative). Converted templates carry
|
||||
`{{T "key"}}` markers; `loadTemplates` parses one template set per language after `i18n.Expand` has
|
||||
replaced them, so the Hungarian set is parsed from the same bytes, in the same escaping contexts, as
|
||||
before. Chosen over `golang.org/x/text/message` because the inventory found no gender and only
|
||||
count-plurals (English `key.one`/`key.other`; Hungarian has one form), and over a runtime `T` func
|
||||
because the contextual escaper would change Hungarian bytes (`+`, `'`, `"`) and need per-context
|
||||
handling inside `<script>`. A key missing in English shows Hungarian and is counted; an undefined key
|
||||
fails the template load.
|
||||
- **Three pages + the layout converted:** the launcher, `/backups`, `/apps/<slug>`, and `layout.html`
|
||||
(menu, banners, the layout's delete/remove modals) — 252 markers, 235 Hungarian keys, all translated.
|
||||
Go-side copy on those pages: page titles (`TitleKey`), and English overrides for `stateLabel`,
|
||||
`timeAgo`, `timeAgoStr`, `nextRunLabel`, `statusText`. `<html lang>` follows the language.
|
||||
- **The setting:** `settings.json` `language` (`hu`|`en`, empty = hu); `POST /settings/language`;
|
||||
`?lang=` per-request override (never persisted); reported to the hub as `"language"` at all four
|
||||
report build sites.
|
||||
- **Gates.** New `i18n_missing_gate.py` (keys exist, no orphans, English gap and formal „ön" count are
|
||||
ratchets, no "please"/"kindly"). **Found while converting:** the retrieval-promise gate went STALE the
|
||||
moment copy moved to the bundle, and the emoji / native-confirm / secret-in-markup gates went BLIND
|
||||
to it — they now read templates expanded (`scripts/i18n_bundle.py`); mojibake scans the bundles.
|
||||
Decoys for all of it in `test_gate_decoys.py`; the HEAD versions of the emoji and retrieval gates
|
||||
were run against the bundle decoys and passed them.
|
||||
- **Tools:** `scripts/i18n_extract.py` converts a template. Its first pass missed eight ASCII-only
|
||||
Hungarian strings; they were found by eye and the word list extended.
|
||||
|
||||
**Tests, each red-proofed (seen failing, then passing):** `TestI18nParity` — 14 fixture states
|
||||
captured from a clean worktree of `origin/main` 89dd3e94b1de; one changed byte in hu.json fails it
|
||||
naming the page and line. `TestI18nEnglishPages` — no Hungarian template copy, raw key, marker or new
|
||||
empty element on the English render; removing one English key fails it. `TestLanguageSwitch_EndToEnd`
|
||||
(real router: hidden for Hungarian, `?lang=` door, save, 400 on `de`, back to hidden) — fails with
|
||||
`addLanguageData` removed. `TestI18nJSContextValuesAreSafe` — fails on a quote in a JS-context English
|
||||
value. `TestBundleParametersMatchAcrossLanguages` — fails when English drops `{{.RecoveryAbandonDate}}`.
|
||||
`TestLocaleFuncsHungarianBundleMatchesFuncMap` — fails when hu.json's state word differs from the funcmap.
|
||||
|
||||
## v0.246.0 — an interrupted restore is told, and the recovery-code reminder waits until the box can take it (2026-09-17, R-550 / R-546)
|
||||
|
||||
**MinAgent: 0.131.0** (unchanged — the readiness check reads the escrow preflight, served since agent
|
||||
|
||||
Reference in New Issue
Block a user