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
@@ -7,6 +7,7 @@ import (
"testing"
"gitea.dooplex.hu/admin/felhom-controller/internal/config"
"gitea.dooplex.hu/admin/felhom-controller/internal/i18n"
"gitea.dooplex.hu/admin/felhom-controller/internal/stacks"
)
@@ -39,8 +40,20 @@ func TestRouteUnpublished(t *testing.T) {
// unregistered func or a template syntax error introduced by the F5 edits.
func TestTemplatesParseWithFuncmap(t *testing.T) {
s := &Server{cfg: &config.Config{}}
if _, err := template.New("").Funcs(s.templateFuncMap()).ParseFS(templateFS, "templates/*.html"); err != nil {
t.Fatalf("templates failed to parse with funcmap: %v", err)
// v0.247.0: templates carry {{T}} markers and are parsed per language after i18n expansion — the
// production path is parseTemplateSet, so parse exactly that, for every supported language.
b, err := i18n.Shared()
if err != nil {
t.Fatal(err)
}
for _, lang := range i18n.Supported {
funcs := s.templateFuncMap()
for n, fn := range s.localeFuncs(lang) {
funcs[n] = fn
}
if _, _, err := parseTemplateSet(b, lang, funcs); err != nil {
t.Fatalf("templates (%s) failed to parse with funcmap: %v", lang, err)
}
}
}