diff --git a/grammar.go b/grammar.go index 8834a70..38a6609 100644 --- a/grammar.go +++ b/grammar.go @@ -12,21 +12,45 @@ import ( // GetGrammarData returns the grammar data for the specified language. func GetGrammarData(lang string) *GrammarData { + lang = normalizeLanguageTag(lang) + if lang == "" { + return nil + } grammarCacheMu.RLock() defer grammarCacheMu.RUnlock() - return grammarCache[lang] + if data, ok := grammarCache[lang]; ok && data != nil { + return data + } + if base := baseLanguageTag(lang); base != "" { + if data, ok := grammarCache[base]; ok && data != nil { + return data + } + } + return nil } // SetGrammarData sets the grammar data for a language, replacing any existing data. func SetGrammarData(lang string, data *GrammarData) { + lang = normalizeLanguageTag(lang) + if lang == "" { + return + } grammarCacheMu.Lock() defer grammarCacheMu.Unlock() + if data == nil { + delete(grammarCache, lang) + return + } grammarCache[lang] = cloneGrammarData(data) } // MergeGrammarData merges grammar data into the existing data for a language. // New entries are added; existing entries are overwritten per-key. func MergeGrammarData(lang string, data *GrammarData) { + lang = normalizeLanguageTag(lang) + if lang == "" || data == nil { + return + } grammarCacheMu.Lock() defer grammarCacheMu.Unlock() existing := grammarCache[lang] diff --git a/loader_test.go b/loader_test.go index 8007ebc..eeb949a 100644 --- a/loader_test.go +++ b/loader_test.go @@ -454,6 +454,50 @@ func TestMergeGrammarData(t *testing.T) { } } +func TestGrammarDataLanguageTagNormalisation(t *testing.T) { + const rawLang = "tl_PH" + const canonicalLang = "tl-PH" + + originalRaw := GetGrammarData(rawLang) + originalCanonical := GetGrammarData(canonicalLang) + t.Cleanup(func() { + SetGrammarData(rawLang, originalRaw) + SetGrammarData(canonicalLang, originalCanonical) + }) + + SetGrammarData(rawLang, &GrammarData{ + Words: map[string]string{ + "demo": "Demo", + }, + }) + + if got := GetGrammarData(rawLang); got == nil || got.Words["demo"] != "Demo" { + t.Fatalf("GetGrammarData(%q) = %+v, want demo word", rawLang, got) + } + if got := GetGrammarData(canonicalLang); got == nil || got.Words["demo"] != "Demo" { + t.Fatalf("GetGrammarData(%q) = %+v, want demo word", canonicalLang, got) + } + + MergeGrammarData(canonicalLang, &GrammarData{ + Words: map[string]string{ + "api": "API", + }, + }) + + data := GetGrammarData(rawLang) + if data == nil { + t.Fatalf("GetGrammarData(%q) returned nil after merge", rawLang) + } + if data.Words["api"] != "API" { + t.Fatalf("merged word normalisation failed: %+v", data.Words) + } + + SetGrammarData(rawLang, nil) + if got := GetGrammarData(canonicalLang); got != nil { + t.Fatalf("SetGrammarData(%q, nil) did not clear entry: %+v", rawLang, got) + } +} + func TestNewWithLoader_LoadsGrammarOnlyLocale(t *testing.T) { loaderFS := fstest.MapFS{ "fr.json": &fstest.MapFile{