v0.259.0 — the claim page and the backup warnings answer in the reader's language (R-596, R-598)
gates / gates (push) Successful in 28s

The 2026-09-20 English drill ended one screen short: the claim page was English
and its answers were Hungarian, so a household who mistyped the code from their
e-mail could not tell a typo from a dead code. Fourteen call sites carrying nine
messages now go through s.msg; the backup page's two protection warnings — which
are promises about whether the customer's files are safe — follow the same route.

Hungarian is byte-identical, proved structurally by the go-parity gate against the
frozen base capture and red-proofed on a single added full stop.

data["Title"] was DEAD (claim.html is standalone; .Title is layout.html's) and is
deleted rather than translated — a translated dead field is a permanent false
signal about where the page's title comes from.

Six existing copy-contract tests were kept, not weakened: each now resolves its key
through the real bundle, so it still convicts on a reworded Hungarian sentence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-21 07:45:56 +02:00
parent f6909492cc
commit 0fe04bb6d5
15 changed files with 736 additions and 143 deletions
@@ -7,6 +7,7 @@ import (
"time"
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
"gitea.dooplex.hu/admin/felhom-controller/internal/i18n"
)
// R-517 — the whole-guest tile speaks from SUCCESSES per tier. The BIGNIGHT page read, after a local
@@ -18,6 +19,24 @@ var tvNow = time.Date(2026, 9, 14, 19, 15, 36, 0, time.UTC)
// RED-PROOF (run 2026-09-15, recorded in REPORT.md): with buildTierViews reading a tier's "success"
// from LastAttempt instead of LastSuccess, the shown backup lost its size and this failed at "the
// successful local backup is not the one shown: has=true size=0".
// huMsg is the Hungarian side of buildTierViews' message seam (v0.259.0, R-598). The tier labels
// used to be Hungarian literals inside the builder; they are bundle keys now, and this renders them
// exactly as a Hungarian household's request does — so the label assertions below still compare the
// WORDS, not a key.
func huMsg(t *testing.T) func(string, ...interface{}) string {
t.Helper()
return func(key string, a ...interface{}) string {
b, err := i18n.Shared()
if err != nil {
t.Fatalf("i18n bundle: %v", err)
}
if len(a) == 0 {
return b.Msg("hu", key)
}
return b.Msgf("hu", key, a...)
}
}
func TestBuildTierViews_BignightFailedPBSOnAbsentStorage(t *testing.T) {
v := &guestBackupView{}
tiers := []agentapi.TierBackupState{
@@ -27,7 +46,7 @@ func TestBuildTierViews_BignightFailedPBSOnAbsentStorage(t *testing.T) {
{Target: "felhom-pbs", Storage: "absent",
LastAttempt: &agentapi.TierAttempt{StartedAt: "2026-09-14T19:09:59Z", Success: false, Error: "storage 'felhom-pbs' does not exist"}},
}
buildTierViews(v, tiers, map[string]int64{"local": 86400, "felhom-pbs": 604800}, tvNow)
buildTierViews(v, tiers, map[string]int64{"local": 86400, "felhom-pbs": 604800}, tvNow, huMsg(t))
if v.Offsite {
t.Fatalf("remote tick shown without a PBS success: %+v", v.Tiers)
@@ -55,7 +74,7 @@ func TestBuildTierViews_PBSFailedUnderOldSuccess(t *testing.T) {
LastSuccess: &agentapi.BackupRecord{Success: true, SizeBytes: 20, StartedAt: "2026-08-20T01:00:00Z"},
LastAttempt: &agentapi.TierAttempt{StartedAt: "2026-09-14T02:00:00Z", Success: false}},
}
buildTierViews(v, tiers, map[string]int64{"local": 86400, "felhom-pbs": 604800}, tvNow)
buildTierViews(v, tiers, map[string]int64{"local": 86400, "felhom-pbs": 604800}, tvNow, huMsg(t))
pbs := v.Tiers[1]
if !pbs.HasSuccess || !pbs.FailedAfter || pbs.Current {
t.Fatalf("pbs row: want old success kept, failure shown under it, not current: %+v", pbs)
@@ -72,7 +91,7 @@ func TestBuildTierViews_SuccessFromStorageAfterRestart(t *testing.T) {
{Target: "local", Primary: true, Storage: "present", LastSuccessSource: "storage",
LastSuccess: &agentapi.BackupRecord{Success: true, StartedAt: "2026-09-14T19:03:23Z"}},
}
buildTierViews(v, tiers, map[string]int64{"local": 86400}, tvNow)
buildTierViews(v, tiers, map[string]int64{"local": 86400}, tvNow, huMsg(t))
if !v.HasBackup || v.Due || v.Tiers[0].SizeKnown {
t.Fatalf("after restart: want the local success shown, up to date, size unknown: %+v / due=%v", v.Tiers[0], v.Due)
}