612c417024
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
49 lines
1.6 KiB
Python
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)
|