Files
admin 612c417024
gates / gates (push) Successful in 19s
v0.247.0: i18n spike — the dashboard can speak English, Hungarian byte-identical
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
2026-09-17 14:50:57 +02:00

49 lines
1.6 KiB
Python

# -*- coding: utf-8 -*-
"""i18n_bundle.py -- read a dashboard template the way the controller renders it.
Since v0.247.0 a template's copy lives in internal/i18n/locales/<lang>.json and the template carries
`{{T "key"}}` markers, expanded before parsing (internal/i18n/i18n.go). A gate that reads the raw
template no longer sees that copy -- the retrieval-promise gate went STALE the moment the first page
was converted, which is how this module was found to be needed. Gates that judge copy, markup or
template actions call expand()/read_template() so they judge what a household actually receives, in
every language.
The marker pattern is the Go one, character for character (markerRe); an undefined key is left in
place, exactly as the loader leaves it.
"""
import io
import json
import os
import re
_HERE = os.path.dirname(os.path.abspath(__file__))
LOCALES = os.path.join(_HERE, "..", "internal", "i18n", "locales")
LANGS = ("hu", "en")
MARKER = re.compile(r'\{\{\s*T\s+"([A-Za-z0-9_.\-]+)"\s*\}\}')
_cache = {}
def load(lang):
if lang not in _cache:
p = os.path.join(LOCALES, lang + ".json")
_cache[lang] = json.load(io.open(p, encoding="utf-8")) if os.path.exists(p) else {}
return _cache[lang]
def expand(text, lang):
hu, own = load("hu"), load(lang)
def rep(m):
k = m.group(1)
if k in own:
return own[k]
if k in hu:
return hu[k]
return m.group(0)
return MARKER.sub(rep, text)
def read_template(path, lang="hu"):
return expand(io.open(path, encoding="utf-8").read(), lang)