P3 M1 test fix: assert go-i18n fallback contract (default text + MessageNotFoundErr)

This commit is contained in:
Muse
2026-10-23 22:08:05 +00:00
parent d70fd38978
commit 1ee07ba73d
+39 -10
View File
@@ -2,6 +2,7 @@ package locale
import ( import (
"embed" "embed"
"errors"
"sync" "sync"
"testing" "testing"
@@ -30,7 +31,12 @@ func parsedTags() map[string]bool {
return out return out
} }
func localize(t *testing.T, lang, key string, templateData map[string]any) string { // localize mirrors how production localizers are built (language
// ensured first, then NewLocalizer) and returns the raw library
// result: go-i18n answers a key missing in the requested language
// with the default language's text AND a MessageNotFoundErr, so
// callers here assert both halves of that contract.
func localize(t *testing.T, lang, key string, templateData map[string]any) (string, error) {
t.Helper() t.Helper()
if err := ensureLanguage(lang); err != nil { if err := ensureLanguage(lang); err != nil {
t.Fatalf("ensureLanguage(%q): %v", lang, err) t.Fatalf("ensureLanguage(%q): %v", lang, err)
@@ -38,7 +44,12 @@ func localize(t *testing.T, lang, key string, templateData map[string]any) strin
i18nMu.RLock() i18nMu.RLock()
loc := i18n.NewLocalizer(i18nBundle, lang) loc := i18n.NewLocalizer(i18nBundle, lang)
i18nMu.RUnlock() i18nMu.RUnlock()
msg, err := loc.Localize(&i18n.LocalizeConfig{MessageID: key, TemplateData: templateData}) return loc.Localize(&i18n.LocalizeConfig{MessageID: key, TemplateData: templateData})
}
func localizeOK(t *testing.T, lang, key string, templateData map[string]any) string {
t.Helper()
msg, err := localize(t, lang, key, templateData)
if err != nil { if err != nil {
t.Fatalf("Localize(%q, %q): %v", lang, key, err) t.Fatalf("Localize(%q, %q): %v", lang, key, err)
} }
@@ -60,10 +71,10 @@ func TestLazyLanguageParsing(t *testing.T) {
t.Fatalf("non-startup languages parsed at init: %v", parsed) t.Fatalf("non-startup languages parsed at init: %v", parsed)
} }
if got := localize(t, "zh-CN", "hello", nil); got != "你好" { if got := localizeOK(t, "zh-CN", "hello", nil); got != "你好" {
t.Fatalf("zh-CN hello = %q, want 你好", got) t.Fatalf("zh-CN hello = %q, want 你好", got)
} }
if got := localize(t, "zh-CN", "greet", map[string]any{"Name": "World"}); got != "你好 World" { if got := localizeOK(t, "zh-CN", "greet", map[string]any{"Name": "World"}); got != "你好 World" {
t.Fatalf("zh-CN greet = %q", got) t.Fatalf("zh-CN greet = %q", got)
} }
parsed = parsedTags() parsed = parsedTags()
@@ -71,13 +82,31 @@ func TestLazyLanguageParsing(t *testing.T) {
t.Fatalf("after zh-CN use, parsed = %v", parsed) t.Fatalf("after zh-CN use, parsed = %v", parsed)
} }
// Missing keys fall back to English, as before. // A key missing in the requested language follows go-i18n's
if got := localize(t, "zh-CN", "only_en", nil); got != "Only in English" { // fallback contract: default-language text plus a
t.Fatalf("fallback = %q, want English text", got) // MessageNotFoundErr — and the production I18n() wrapper maps
// that error to "", exactly as it did when every language was
// parsed eagerly.
msg, err := localize(t, "zh-CN", "only_en", nil)
if msg != "Only in English" {
t.Fatalf("fallback text = %q, want English text", msg)
}
var notFound *i18n.MessageNotFoundErr
if !errors.As(err, &notFound) {
t.Fatalf("fallback err = %v, want MessageNotFoundErr", err)
}
i18nMu.RLock()
LocalizerWeb = i18n.NewLocalizer(i18nBundle, "zh-CN")
i18nMu.RUnlock()
if got := I18n(Web, "only_en"); got != "" {
t.Fatalf("I18n fallback = %q, want \"\" (wrapper error contract)", got)
}
if got := I18n(Web, "hello"); got != "你好" {
t.Fatalf("I18n zh-CN hello = %q, want 你好", got)
} }
// A bare language preference resolves to the regional file. // A bare language preference resolves to the regional file.
if got := localize(t, "fa", "hello", nil); got != "سلام" { if got := localizeOK(t, "fa", "hello", nil); got != "سلام" {
t.Fatalf("fa hello = %q, want سلام", got) t.Fatalf("fa hello = %q, want سلام", got)
} }
if !parsedTags()["fa-IR"] { if !parsedTags()["fa-IR"] {
@@ -96,9 +125,9 @@ func TestLazyLanguageParsing(t *testing.T) {
} }
// An unsupported language parses nothing and still localizes // An unsupported language parses nothing and still localizes
// (in the fallback language) without error. // (in the fallback language, matched directly, so no error).
before := parsedTags() before := parsedTags()
if got := localize(t, "de-DE", "hello", nil); got != "Hello" { if got := localizeOK(t, "de-DE", "hello", nil); got != "Hello" {
t.Fatalf("de-DE hello = %q, want fallback Hello", got) t.Fatalf("de-DE hello = %q, want fallback Hello", got)
} }
after := parsedTags() after := parsedTags()