v0.247.0: i18n spike — the dashboard can speak English, Hungarian byte-identical
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:
2026-09-17 14:50:57 +02:00
parent 89dd3e94b1
commit 612c417024
49 changed files with 11734 additions and 248 deletions
+14 -1
View File
@@ -39,6 +39,9 @@ import os
import re
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import i18n_bundle # noqa: E402
HERE = os.path.dirname(os.path.abspath(__file__))
CTRL = os.path.dirname(HERE)
TPL = os.path.join(CTRL, "internal", "web", "templates")
@@ -71,8 +74,18 @@ ALLOWLIST = {
def check(path):
# v0.247.0: bundle values carry template actions ({{.RecoveryAbandonDate}}), so a secret-named
# expression can arrive through a translation. Judge every language's expansion; dedupe.
out = []
for lang in i18n_bundle.LANGS:
for c in _check_src(i18n_bundle.read_template(path, lang)):
if c not in out:
out.append(c)
return out
def _check_src(src):
convictions = []
src = open(path, encoding="utf-8").read()
for m in ACTION.finditer(src):
expr = m.group(1).strip()
# A TEMPLATE comment `{{/* ... */}}` is stripped by html/template and never reaches the