package html // context.go: Translator provides Text() lookups for a rendering context. // Example: type service struct{} // // func (service) T(key string, args ...any) string { return key } // // ctx := NewContextWithService(service{}, "en-GB") type Translator interface { T(key string, args ...any) string } // context.go: Context carries rendering state through the node tree. // Example: NewContext("en-GB") initialises locale-specific rendering state. // Locale and translator selection happen at construction time. type Context struct { Identity string Locale string Entitlements func(feature string) bool Data map[string]any service Translator } func applyLocaleToService(svc Translator, locale string) { if svc == nil || locale == "" { return } 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 } } _ = setter.SetLanguage(base) } } // ensureContextDefaults initialises lazily-created context fields. func ensureContextDefaults(ctx *Context) { if ctx == nil { return } if ctx.Data == nil { ctx.Data = make(map[string]any) } } // normaliseContext ensures render paths always have a usable context. // A nil input is replaced with a fresh default context. func normaliseContext(ctx *Context) *Context { if ctx != nil { ensureContextDefaults(ctx) return ctx } return NewContext() } // context.go: NewContext creates a new rendering context with sensible defaults. // Example: ctx := NewContext("en-GB"). // An optional locale may be provided as the first argument. func NewContext(locale ...string) *Context { ctx := &Context{ Data: make(map[string]any), service: newDefaultTranslator(), } if len(locale) > 0 { ctx.Locale = locale[0] applyLocaleToService(ctx.service, ctx.Locale) } return ctx } // context.go: NewContextWithService creates a rendering context backed by a specific translator. // Example: ctx := NewContextWithService(svc, "fr-FR"). // An optional locale may be provided as the second argument. func NewContextWithService(svc Translator, locale ...string) *Context { ctx := &Context{ Data: make(map[string]any), service: svc, } if len(locale) > 0 { ctx.Locale = locale[0] } applyLocaleToService(ctx.service, ctx.Locale) return ctx }