diff --git a/docs/forward-api.md b/docs/forward-api.md index 3559576..91ad3a0 100644 --- a/docs/forward-api.md +++ b/docs/forward-api.md @@ -15,6 +15,7 @@ svc := i18n.Default() // Option 2: Explicit creation with options svc, err := i18n.New( + i18n.WithLanguage("en-GB"), i18n.WithFallback("en"), i18n.WithDefaultHandlers(), ) @@ -35,6 +36,7 @@ The service automatically detects the system language from `LANG`, `LC_ALL`, or | Option | Effect | |--------|--------| | `WithFallback("en")` | Set fallback language for missing translations | +| `WithLanguage("fr")` | Set the initial language before the service starts serving | | `WithDefaultHandlers()` | Register the six built-in `i18n.*` namespace handlers | | `WithHandlers(h...)` | Replace handlers entirely | | `WithMode(ModeStrict)` | Panic on missing keys (useful in CI) | diff --git a/docs/i18n/README.md b/docs/i18n/README.md index 67775a9..91c093c 100644 --- a/docs/i18n/README.md +++ b/docs/i18n/README.md @@ -390,6 +390,7 @@ Use functional options when creating a service: ```go svc, err := i18n.New( + i18n.WithLanguage("de-DE"), // Initial language i18n.WithFallback("de-DE"), // Fallback language i18n.WithFormality(i18n.FormalityFormal), // Default formality i18n.WithMode(i18n.ModeStrict), // Missing key mode diff --git a/service.go b/service.go index 80ce55e..1109dba 100644 --- a/service.go +++ b/service.go @@ -22,6 +22,7 @@ type Service struct { messages map[string]map[string]Message // lang -> key -> message currentLang string fallbackLang string + requestedLang string languageExplicit bool availableLangs []language.Tag mode Mode @@ -42,6 +43,15 @@ func WithFallback(lang string) Option { return func(s *Service) { s.fallbackLang = normalizeLanguageTag(lang) } } +// WithLanguage sets an explicit initial language for the service. +// +// The language is applied after the loader has populated the available +// languages, so it can resolve to the best supported tag instead of failing +// during option construction. +func WithLanguage(lang string) Option { + return func(s *Service) { s.requestedLang = normalizeLanguageTag(lang) } +} + // WithFormality sets the default formality level. func WithFormality(f Formality) Option { return func(s *Service) { s.formality = f } @@ -179,6 +189,12 @@ func NewWithLoader(loader Loader, opts ...Option) (*Service, error) { s.currentLang = s.fallbackLang } + if s.requestedLang != "" { + if err := s.SetLanguage(s.requestedLang); err != nil { + return nil, err + } + } + return s, nil } diff --git a/service_test.go b/service_test.go index 2d4db85..d697123 100644 --- a/service_test.go +++ b/service_test.go @@ -1048,6 +1048,7 @@ func TestWithDefaultHandlers_Idempotent(t *testing.T) { func TestServiceWithOptions(t *testing.T) { svc, err := New( WithFallback("en"), + WithLanguage("fr_CA"), WithFormality(FormalityFormal), WithLocation("workspace"), WithMode(ModeCollect), @@ -1069,6 +1070,20 @@ func TestServiceWithOptions(t *testing.T) { if svc.Location() != "workspace" { t.Errorf("Location = %q, want workspace", svc.Location()) } + if got := svc.Language(); got != "fr" { + t.Errorf("Language() = %q, want fr", got) + } +} + +func TestWithLanguage(t *testing.T) { + svc, err := New(WithLanguage("fr_CA")) + if err != nil { + t.Fatalf("New() with WithLanguage() failed: %v", err) + } + + if got := svc.Language(); got != "fr" { + t.Fatalf("Language() = %q, want %q", got, "fr") + } } func TestNewWithFS(t *testing.T) {