Fix locale forwarding for translators
Some checks are pending
Security Scan / security (push) Waiting to run
Test / test (push) Waiting to run

This commit is contained in:
Snider 2026-04-15 03:17:19 +01:00
parent 0d361e537e
commit 6e254de9ba
2 changed files with 56 additions and 7 deletions

View file

@ -31,17 +31,35 @@ func applyLocaleToService(svc Translator, locale string) {
}
if setter, ok := svc.(interface{ SetLanguage(string) error }); ok {
base := locale
for i := 0; i < len(base); i++ {
if base[i] == '-' || base[i] == '_' {
base = base[:i]
break
}
// The built-in i18n service matches best on a base language tag.
// Custom translators should receive the full locale string.
if serviceUsesBaseLanguage(svc) {
locale = baseLanguage(locale)
}
_ = setter.SetLanguage(base)
_ = setter.SetLanguage(locale)
}
}
func serviceUsesBaseLanguage(svc Translator) bool {
t := reflect.TypeOf(svc)
for t != nil && t.Kind() == reflect.Pointer {
t = t.Elem()
}
if t == nil {
return false
}
return t.PkgPath() == "dappco.re/go/core/i18n" && t.Name() == "Service"
}
func baseLanguage(locale string) string {
for i := 0; i < len(locale); i++ {
if locale[i] == '-' || locale[i] == '_' {
return locale[:i]
}
}
return locale
}
// NewContext creates a new rendering context with sensible defaults.
// Usage example: html := Render(Text("welcome"), NewContext("en-GB"))
func NewContext(locale ...string) *Context {

View file

@ -10,10 +10,16 @@ import (
)
type recordingTranslator struct {
lang string
key string
args []any
}
func (r *recordingTranslator) SetLanguage(lang string) error {
r.lang = lang
return nil
}
func (r *recordingTranslator) T(key string, args ...any) string {
r.key = key
r.args = append(r.args[:0], args...)
@ -59,6 +65,18 @@ func TestNewContextWithService_AppliesLocaleToService_Good(t *testing.T) {
}
}
func TestNewContextWithService_ForwardsFullLocaleToTranslator_Good(t *testing.T) {
svc := &recordingTranslator{}
ctx := NewContextWithService(svc, "en-GB")
if ctx == nil {
t.Fatal("NewContextWithService returned nil")
}
if svc.lang != "en-GB" {
t.Fatalf("NewContextWithService forwarded locale = %q, want %q", svc.lang, "en-GB")
}
}
func TestTextNode_UsesMetadataAliasWhenDataNil_Good(t *testing.T) {
svc, _ := i18n.New()
i18n.SetDefault(svc)
@ -143,6 +161,19 @@ func TestContext_SetLocale_AppliesLocale_Good(t *testing.T) {
}
}
func TestContext_SetLocale_ForwardsFullLocaleToTranslator_Good(t *testing.T) {
ctx := NewContextWithService(&recordingTranslator{})
if got := ctx.SetLocale("fr-FR"); got != ctx {
t.Fatal("SetLocale should return the same context for chaining")
}
svc := ctx.service.(*recordingTranslator)
if svc.lang != "fr-FR" {
t.Fatalf("SetLocale forwarded locale = %q, want %q", svc.lang, "fr-FR")
}
}
func TestContext_SetLocale_NilContext_Ugly(t *testing.T) {
var ctx *Context
if got := ctx.SetLocale("en-GB"); got != nil {