From d5060197f529f68774c173769d98283c04755f95 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 04:41:24 +0000 Subject: [PATCH] feat(i18n): add base language message fallback Co-Authored-By: Virgil --- service.go | 8 +++++++- service_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/service.go b/service.go index 0b87025..969d72d 100644 --- a/service.go +++ b/service.go @@ -375,11 +375,17 @@ func (s *Service) T(messageID string, args ...any) string { return result } -// resolveDirect performs exact-key lookup in the current language and fallback language. +// resolveDirect performs exact-key lookup in the current language, its base +// language tag, and then the configured fallback language. func (s *Service) resolveDirect(messageID string, data any) string { if text := s.tryResolve(s.currentLang, messageID, data); text != "" { return text } + if base := baseLanguageTag(s.currentLang); base != "" && base != s.currentLang { + if text := s.tryResolve(base, messageID, data); text != "" { + return text + } + } return s.tryResolve(s.fallbackLang, messageID, data) } diff --git a/service_test.go b/service_test.go index 6eb0a3a..7443c4d 100644 --- a/service_test.go +++ b/service_test.go @@ -5,6 +5,16 @@ import ( "testing/fstest" ) +type messageBaseFallbackLoader struct{} + +func (messageBaseFallbackLoader) Languages() []string { + return []string{"en-GB", "en", "fr"} +} + +func (messageBaseFallbackLoader) Load(lang string) (map[string]Message, *GrammarData, error) { + return map[string]Message{}, nil, nil +} + func TestNewService(t *testing.T) { svc, err := New() if err != nil { @@ -244,6 +254,29 @@ func TestServiceFallback(t *testing.T) { } } +func TestServiceMessageFallbackUsesBaseLanguageTagBeforeConfiguredFallback(t *testing.T) { + svc, err := NewWithLoader(messageBaseFallbackLoader{}) + if err != nil { + t.Fatalf("NewWithLoader() failed: %v", err) + } + + svc.AddMessages("en", map[string]string{ + "greeting": "hello", + }) + svc.AddMessages("fr", map[string]string{ + "greeting": "bonjour", + }) + + if err := svc.SetLanguage("en-GB"); err != nil { + t.Fatalf("SetLanguage(en-GB) failed: %v", err) + } + svc.SetFallback("fr") + + if got := svc.T("greeting"); got != "hello" { + t.Fatalf("T(greeting) = %q, want %q", got, "hello") + } +} + func TestServiceDebug(t *testing.T) { svc, err := New() if err != nil { -- 2.45.3