diff --git a/service.go b/service.go index e30e0e9..74e06eb 100644 --- a/service.go +++ b/service.go @@ -136,12 +136,28 @@ func NewWithLoader(loader Loader, opts ...Option) (*Service, error) { return nil, log.E("NewWithLoader", "load locale: "+lang, err) } lang = normalizeLanguageTag(lang) - s.messages[lang] = messages + _, seen := s.messages[lang] + + if existing, ok := s.messages[lang]; ok { + if existing == nil { + existing = make(map[string]Message) + s.messages[lang] = existing + } + maps.Copy(existing, messages) + } else { + s.messages[lang] = messages + } if grammarDataHasContent(grammar) { - SetGrammarData(lang, grammar) + if seen { + MergeGrammarData(lang, grammar) + } else { + SetGrammarData(lang, grammar) + } } tag := language.Make(lang) - s.availableLangs = append(s.availableLangs, tag) + if !slices.Contains(s.availableLangs, tag) { + s.availableLangs = append(s.availableLangs, tag) + } } if detected := detectLanguage(s.availableLangs); detected != "" { diff --git a/service_test.go b/service_test.go index 9b623ad..7220500 100644 --- a/service_test.go +++ b/service_test.go @@ -57,6 +57,31 @@ func (underscoreLangLoader) Load(lang string) (map[string]Message, *GrammarData, }, nil, nil } +type duplicateLangLoader struct{} + +func (duplicateLangLoader) Languages() []string { + return []string{"en_US", "en-US"} +} + +func (duplicateLangLoader) Load(lang string) (map[string]Message, *GrammarData, error) { + switch lang { + case "en_US": + return map[string]Message{ + "first.key": {Text: "first"}, + }, &GrammarData{ + Words: map[string]string{"pkg": "package"}, + }, nil + case "en-US": + return map[string]Message{ + "second.key": {Text: "second"}, + }, &GrammarData{ + Words: map[string]string{"api": "API"}, + }, nil + default: + return map[string]Message{}, nil, nil + } +} + func TestNewService(t *testing.T) { svc, err := New() if err != nil { @@ -240,6 +265,35 @@ func TestNewWithLoaderNormalisesLanguageTags(t *testing.T) { } } +func TestNewWithLoaderMergesCanonicalDuplicateLanguages(t *testing.T) { + svc, err := NewWithLoader(duplicateLangLoader{}) + if err != nil { + t.Fatalf("NewWithLoader() failed: %v", err) + } + + if err := svc.SetLanguage("en-US"); err != nil { + t.Fatalf("SetLanguage(en-US) failed: %v", err) + } + + if got, want := svc.T("first.key"), "first"; got != want { + t.Fatalf("T(first.key) = %q, want %q", got, want) + } + if got, want := svc.T("second.key"), "second"; got != want { + t.Fatalf("T(second.key) = %q, want %q", got, want) + } + + data := GetGrammarData("en-US") + if data == nil { + t.Fatal("GetGrammarData(en-US) returned nil") + } + if got, want := data.Words["pkg"], "package"; got != want { + t.Fatalf("grammar word pkg = %q, want %q", got, want) + } + if got, want := data.Words["api"], "API"; got != want { + t.Fatalf("grammar word api = %q, want %q", got, want) + } +} + func TestServiceTPluralMessage(t *testing.T) { svc, err := New() if err != nil {