[agent/codex:gpt-5.4-mini] Read ~/spec/code/core/go/i18n/RFC.md fully. Find ONE feature... #39
3 changed files with 82 additions and 14 deletions
|
|
@ -110,6 +110,43 @@ func TestInit_LoadsRegisteredLocales(t *testing.T) {
|
|||
assert.Equal(t, "loaded on init", got)
|
||||
}
|
||||
|
||||
func TestInit_ReDetectsRegisteredLocales(t *testing.T) {
|
||||
t.Setenv("LANG", "de_DE.UTF-8")
|
||||
|
||||
registeredLocalesMu.Lock()
|
||||
savedLocales := registeredLocales
|
||||
savedLoaded := localesLoaded
|
||||
registeredLocales = nil
|
||||
localesLoaded = false
|
||||
registeredLocalesMu.Unlock()
|
||||
|
||||
defaultOnce = sync.Once{}
|
||||
defaultService.Store(nil)
|
||||
|
||||
defer func() {
|
||||
registeredLocalesMu.Lock()
|
||||
registeredLocales = savedLocales
|
||||
localesLoaded = savedLoaded
|
||||
registeredLocalesMu.Unlock()
|
||||
defaultService.Store(nil)
|
||||
defaultOnce = sync.Once{}
|
||||
}()
|
||||
|
||||
fs := fstest.MapFS{
|
||||
"locales/de.json": &fstest.MapFile{
|
||||
Data: []byte(`{"hello": "hallo"}`),
|
||||
},
|
||||
}
|
||||
RegisterLocales(fs, "locales")
|
||||
|
||||
require.NoError(t, Init())
|
||||
|
||||
svc := Default()
|
||||
require.NotNil(t, svc)
|
||||
assert.Contains(t, svc.Language(), "de")
|
||||
assert.Equal(t, "hallo", svc.T("hello"))
|
||||
}
|
||||
|
||||
func TestLoadRegisteredLocales_Good(t *testing.T) {
|
||||
svc, err := New()
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -105,8 +105,11 @@ func detectLanguage(supported []language.Tag) string {
|
|||
return ""
|
||||
}
|
||||
matcher := language.NewMatcher(supported)
|
||||
bestMatch, _, confidence := matcher.Match(parsedLang)
|
||||
bestMatch, bestIndex, confidence := matcher.Match(parsedLang)
|
||||
if confidence >= language.Low {
|
||||
if bestIndex >= 0 && bestIndex < len(supported) {
|
||||
return supported[bestIndex].String()
|
||||
}
|
||||
return bestMatch.String()
|
||||
}
|
||||
return ""
|
||||
|
|
|
|||
54
service.go
54
service.go
|
|
@ -16,16 +16,17 @@ import (
|
|||
|
||||
// Service provides grammar-aware internationalisation.
|
||||
type Service struct {
|
||||
loader Loader
|
||||
messages map[string]map[string]Message // lang -> key -> message
|
||||
currentLang string
|
||||
fallbackLang string
|
||||
availableLangs []language.Tag
|
||||
mode Mode
|
||||
debug bool
|
||||
formality Formality
|
||||
handlers []KeyHandler
|
||||
mu sync.RWMutex
|
||||
loader Loader
|
||||
messages map[string]map[string]Message // lang -> key -> message
|
||||
currentLang string
|
||||
fallbackLang string
|
||||
languageExplicit bool
|
||||
availableLangs []language.Tag
|
||||
mode Mode
|
||||
debug bool
|
||||
formality Formality
|
||||
handlers []KeyHandler
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// Option configures a Service during construction.
|
||||
|
|
@ -222,11 +223,16 @@ func (s *Service) SetLanguage(lang string) error {
|
|||
return log.E("Service.SetLanguage", "no languages available", nil)
|
||||
}
|
||||
matcher := language.NewMatcher(s.availableLangs)
|
||||
bestMatch, _, confidence := matcher.Match(requestedLang)
|
||||
bestMatch, bestIndex, confidence := matcher.Match(requestedLang)
|
||||
if confidence == language.No {
|
||||
return log.E("Service.SetLanguage", "unsupported language: "+lang, nil)
|
||||
}
|
||||
s.currentLang = bestMatch.String()
|
||||
if bestIndex >= 0 && bestIndex < len(s.availableLangs) {
|
||||
s.currentLang = s.availableLangs[bestIndex].String()
|
||||
} else {
|
||||
s.currentLang = bestMatch.String()
|
||||
}
|
||||
s.languageExplicit = true
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -571,6 +577,7 @@ func (s *Service) AddLoader(loader Loader) error {
|
|||
}
|
||||
s.mu.Unlock()
|
||||
}
|
||||
s.autoDetectLanguage()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -578,7 +585,17 @@ func (s *Service) AddLoader(loader Loader) error {
|
|||
// Deprecated: Use AddLoader(NewFSLoader(fsys, dir)) instead for proper grammar handling.
|
||||
func (s *Service) LoadFS(fsys fs.FS, dir string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
defer func() {
|
||||
s.mu.Unlock()
|
||||
if s.languageExplicit {
|
||||
return
|
||||
}
|
||||
if detected := detectLanguage(s.availableLangs); detected != "" {
|
||||
s.mu.Lock()
|
||||
s.currentLang = detected
|
||||
s.mu.Unlock()
|
||||
}
|
||||
}()
|
||||
entries, err := fs.ReadDir(fsys, dir)
|
||||
if err != nil {
|
||||
return log.E("Service.LoadFS", "read locales directory", err)
|
||||
|
|
@ -605,3 +622,14 @@ func (s *Service) LoadFS(fsys fs.FS, dir string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) autoDetectLanguage() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.languageExplicit {
|
||||
return
|
||||
}
|
||||
if detected := detectLanguage(s.availableLangs); detected != "" {
|
||||
s.currentLang = detected
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue