[agent/codex:gpt-5.4-mini] Read ~/spec/code/core/go/i18n/RFC.md fully. Find features de... #131

Merged
Virgil merged 1 commit from agent/read---spec-code-core-go-i18n-rfc-md-ful into dev 2026-04-02 06:03:32 +00:00
3 changed files with 135 additions and 21 deletions

View file

@ -18,6 +18,12 @@ type missingKeyHandlersState struct {
type localeRegistration struct {
fsys fs.FS
dir string
id int
}
type localeProviderRegistration struct {
provider LocaleProvider
id int
}
// LocaleProvider supplies one or more locale filesystems to the default service.
@ -26,10 +32,12 @@ type LocaleProvider interface {
}
var (
registeredLocales []localeRegistration
registeredLocaleProviders []LocaleProvider
registeredLocalesMu sync.Mutex
localesLoaded bool
registeredLocales []localeRegistration
registeredLocaleProviders []localeProviderRegistration
registeredLocalesMu sync.Mutex
localesLoaded bool
nextLocaleRegistrationID int
nextLocaleProviderID int
)
// RegisterLocales registers a filesystem containing locale files.
@ -42,12 +50,18 @@ var (
// i18n.RegisterLocales(localeFS, "locales")
// }
func RegisterLocales(fsys fs.FS, dir string) {
reg := localeRegistration{fsys: fsys, dir: dir}
registeredLocalesMu.Lock()
defer registeredLocalesMu.Unlock()
registeredLocales = append(registeredLocales, localeRegistration{fsys: fsys, dir: dir})
if svc := defaultService.Load(); svc != nil {
nextLocaleRegistrationID++
reg.id = nextLocaleRegistrationID
registeredLocales = append(registeredLocales, reg)
svc := defaultService.Load()
registeredLocalesMu.Unlock()
if svc != nil {
if err := svc.LoadFS(fsys, dir); err != nil {
log.Printf("i18n: RegisterLocales failed to load %q: %v", dir, err)
} else {
svc.markLocaleRegistrationLoaded(reg.id)
}
}
}
@ -59,26 +73,41 @@ func RegisterLocaleProvider(provider LocaleProvider) {
if provider == nil {
return
}
reg := localeProviderRegistration{provider: provider}
registeredLocalesMu.Lock()
registeredLocaleProviders = append(registeredLocaleProviders, provider)
nextLocaleProviderID++
reg.id = nextLocaleProviderID
registeredLocaleProviders = append(registeredLocaleProviders, reg)
svc := defaultService.Load()
registeredLocalesMu.Unlock()
if svc := defaultService.Load(); svc != nil {
loadLocaleProvider(svc, provider)
if svc != nil {
loadLocaleProvider(svc, reg)
}
}
func loadRegisteredLocales(svc *Service) {
if svc == nil {
return
}
registeredLocalesMu.Lock()
locales := append([]localeRegistration(nil), registeredLocales...)
providers := append([]LocaleProvider(nil), registeredLocaleProviders...)
providers := append([]localeProviderRegistration(nil), registeredLocaleProviders...)
registeredLocalesMu.Unlock()
for _, reg := range locales {
if svc != nil && svc.hasLocaleRegistrationLoaded(reg.id) {
continue
}
if err := svc.LoadFS(reg.fsys, reg.dir); err != nil {
log.Printf("i18n: loadRegisteredLocales failed to load %q: %v", reg.dir, err)
continue
}
svc.markLocaleRegistrationLoaded(reg.id)
}
for _, provider := range providers {
if svc != nil && svc.hasLocaleProviderLoaded(provider.id) {
continue
}
loadLocaleProvider(svc, provider)
}
@ -87,15 +116,16 @@ func loadRegisteredLocales(svc *Service) {
registeredLocalesMu.Unlock()
}
func loadLocaleProvider(svc *Service, provider LocaleProvider) {
if svc == nil || provider == nil {
func loadLocaleProvider(svc *Service, provider localeProviderRegistration) {
if svc == nil || provider.provider == nil {
return
}
for _, src := range provider.LocaleSources() {
for _, src := range provider.provider.LocaleSources() {
if err := svc.LoadFS(src.FS, src.Dir); err != nil {
log.Printf("i18n: loadLocaleProvider failed to load %q: %v", src.Dir, err)
}
}
svc.markLocaleProviderLoaded(provider.id)
}
// OnMissingKey registers a handler for missing translation keys.

View file

@ -187,6 +187,43 @@ func TestSetDefault_Good_LoadsQueuedRegisteredLocales(t *testing.T) {
assert.Equal(t, "loaded via setdefault", got)
}
func TestSetDefault_Good_LoadsRegisteredLocalesIntoFreshService(t *testing.T) {
registeredLocalesMu.Lock()
savedLocales := registeredLocales
savedProviders := registeredLocaleProviders
savedLoaded := localesLoaded
registeredLocales = nil
registeredLocaleProviders = nil
localesLoaded = false
registeredLocalesMu.Unlock()
defer func() {
registeredLocalesMu.Lock()
registeredLocales = savedLocales
registeredLocaleProviders = savedProviders
localesLoaded = savedLoaded
registeredLocalesMu.Unlock()
}()
fs := fstest.MapFS{
"locales/en.json": &fstest.MapFile{
Data: []byte(`{"fresh.registration": "fresh value"}`),
},
}
RegisterLocales(fs, "locales")
first, err := New()
require.NoError(t, err)
SetDefault(first)
require.Equal(t, "fresh value", first.T("fresh.registration"))
second, err := New()
require.NoError(t, err)
SetDefault(second)
got := second.T("fresh.registration")
assert.Equal(t, "fresh value", got)
}
func TestInit_LoadsRegisteredLocales(t *testing.T) {
// Save and restore global service state.
registeredLocalesMu.Lock()

View file

@ -30,6 +30,8 @@ type Service struct {
formality Formality
location string
handlers []KeyHandler
loadedLocales map[int]struct{}
loadedProviders map[int]struct{}
mu sync.RWMutex
}
@ -102,10 +104,12 @@ func NewWithFS(fsys fs.FS, dir string, opts ...Option) (*Service, error) {
// NewWithLoader creates a new i18n service with a custom loader.
func NewWithLoader(loader Loader, opts ...Option) (*Service, error) {
s := &Service{
loader: loader,
messages: make(map[string]map[string]Message),
fallbackLang: "en",
handlers: DefaultHandlers(),
loader: loader,
messages: make(map[string]map[string]Message),
fallbackLang: "en",
handlers: DefaultHandlers(),
loadedLocales: make(map[int]struct{}),
loadedProviders: make(map[int]struct{}),
}
for _, opt := range opts {
opt(s)
@ -192,10 +196,9 @@ func SetDefault(s *Service) {
return
}
registeredLocalesMu.Lock()
loaded := localesLoaded
hasRegistrations := len(registeredLocales) > 0
hasRegistrations := len(registeredLocales) > 0 || len(registeredLocaleProviders) > 0
registeredLocalesMu.Unlock()
if !loaded && hasRegistrations {
if hasRegistrations {
loadRegisteredLocales(s)
}
}
@ -833,6 +836,50 @@ func (s *Service) AddLoader(loader Loader) error {
return nil
}
func (s *Service) hasLocaleRegistrationLoaded(id int) bool {
s.mu.RLock()
defer s.mu.RUnlock()
if len(s.loadedLocales) == 0 {
return false
}
_, ok := s.loadedLocales[id]
return ok
}
func (s *Service) markLocaleRegistrationLoaded(id int) {
if id == 0 || s == nil {
return
}
s.mu.Lock()
if s.loadedLocales == nil {
s.loadedLocales = make(map[int]struct{})
}
s.loadedLocales[id] = struct{}{}
s.mu.Unlock()
}
func (s *Service) hasLocaleProviderLoaded(id int) bool {
s.mu.RLock()
defer s.mu.RUnlock()
if len(s.loadedProviders) == 0 {
return false
}
_, ok := s.loadedProviders[id]
return ok
}
func (s *Service) markLocaleProviderLoaded(id int) {
if id == 0 || s == nil {
return
}
s.mu.Lock()
if s.loadedProviders == nil {
s.loadedProviders = make(map[int]struct{})
}
s.loadedProviders[id] = struct{}{}
s.mu.Unlock()
}
func translateOK(messageID, value string) bool {
if value == "" {
return false