package main import ( "os" "regexp" "strings" "testing" ) // Every user-visible string ships in BOTH languages. That is a project rule, // and until now it was only a rule: seventeen keys had drifted into English // only, among them the whole update panel and two DX-cluster settings, found by // a French operator photographing his own screen. // // A key present in one dictionary and not the other falls back to the key // itself, so the interface shows "clu.spotTtl" where a label belongs — or, as // here, the English text, which reads as deliberate and is not. func TestEveryStringIsInBothLanguages(t *testing.T) { src, err := os.ReadFile("frontend/src/lib/i18n.tsx") if err != nil { t.Fatalf("read i18n.tsx: %v", err) } en := dictKeys(t, string(src), "const en: Dict = {") fr := dictKeys(t, string(src), "const fr: Dict = {") if len(en) == 0 || len(fr) == 0 { t.Fatal("one of the dictionaries came back empty — this test has stopped checking anything") } for k := range en { if !fr[k] { t.Errorf("%q has no French — a French operator sees the English string, or the key itself", k) } } for k := range fr { if !en[k] { t.Errorf("%q exists only in French — an English operator sees the key", k) } } } // dictKeys collects the keys of one dictionary literal: from its opening line // to the closing brace in column 0. func dictKeys(t *testing.T, src, opening string) map[string]bool { t.Helper() i := strings.Index(src, opening) if i < 0 { t.Fatalf("%q not found — the dictionaries have been renamed and this test needs updating", opening) } body := src[i+len(opening):] if j := strings.Index(body, "\n};"); j >= 0 { body = body[:j] } keyRe := regexp.MustCompile(`'([a-zA-Z0-9_.]+)'\s*:`) out := map[string]bool{} for _, m := range keyRe.FindAllStringSubmatch(body, -1) { out[m[1]] = true } return out }