feat(html): add context locale setter
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
58380d3d87
commit
afa0337bbd
3 changed files with 122 additions and 13 deletions
|
|
@ -21,7 +21,7 @@ func renderToString(_ js.Value, args []js.Value) any {
|
|||
ctx := html.NewContext()
|
||||
|
||||
if len(args) >= 2 {
|
||||
ctx.Locale = args[1].String()
|
||||
ctx.SetLocale(args[1].String())
|
||||
}
|
||||
|
||||
layout := html.NewLayout(variant)
|
||||
|
|
|
|||
61
context.go
61
context.go
|
|
@ -1,6 +1,9 @@
|
|||
package html
|
||||
|
||||
import i18n "dappco.re/go/core/i18n"
|
||||
// Translator provides Text() lookups for a rendering context.
|
||||
type Translator interface {
|
||||
T(key string, args ...any) string
|
||||
}
|
||||
|
||||
// Context carries rendering state through the node tree.
|
||||
type Context struct {
|
||||
|
|
@ -8,7 +11,24 @@ type Context struct {
|
|||
Locale string
|
||||
Entitlements func(feature string) bool
|
||||
Data map[string]any
|
||||
service *i18n.Service
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// NewContext creates a new rendering context with sensible defaults.
|
||||
|
|
@ -18,20 +38,37 @@ func NewContext(locale ...string) *Context {
|
|||
Data: make(map[string]any),
|
||||
}
|
||||
if len(locale) > 0 {
|
||||
ctx.Locale = locale[0]
|
||||
ctx.SetLocale(locale[0])
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
// NewContextWithService creates a rendering context backed by a specific i18n service.
|
||||
// NewContextWithService creates a rendering context backed by a specific translator.
|
||||
// An optional locale may be provided as the second argument.
|
||||
func NewContextWithService(svc *i18n.Service, locale ...string) *Context {
|
||||
ctx := &Context{
|
||||
Data: make(map[string]any),
|
||||
service: svc,
|
||||
}
|
||||
if len(locale) > 0 {
|
||||
ctx.Locale = locale[0]
|
||||
}
|
||||
func NewContextWithService(svc Translator, locale ...string) *Context {
|
||||
ctx := NewContext(locale...)
|
||||
ctx.SetService(svc)
|
||||
return ctx
|
||||
}
|
||||
|
||||
// SetService swaps the translator used by the context.
|
||||
func (ctx *Context) SetService(svc Translator) *Context {
|
||||
if ctx == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx.service = svc
|
||||
applyLocaleToService(svc, ctx.Locale)
|
||||
return ctx
|
||||
}
|
||||
|
||||
// SetLocale updates the context locale and reapplies it to the active translator.
|
||||
func (ctx *Context) SetLocale(locale string) *Context {
|
||||
if ctx == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx.Locale = locale
|
||||
applyLocaleToService(ctx.service, ctx.Locale)
|
||||
return ctx
|
||||
}
|
||||
|
|
|
|||
72
context_test.go
Normal file
72
context_test.go
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
// SPDX-Licence-Identifier: EUPL-1.2
|
||||
|
||||
package html
|
||||
|
||||
import "testing"
|
||||
|
||||
type localeTranslator struct {
|
||||
language string
|
||||
}
|
||||
|
||||
func (t *localeTranslator) T(key string, args ...any) string {
|
||||
if key == "prompt.yes" && t.language == "fr" {
|
||||
return "o"
|
||||
}
|
||||
if key == "prompt.yes" && t.language == "en" {
|
||||
return "y"
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func (t *localeTranslator) SetLanguage(language string) error {
|
||||
t.language = language
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestContext_SetService_AppliesLocale(t *testing.T) {
|
||||
svc := &localeTranslator{}
|
||||
ctx := NewContext("fr-FR")
|
||||
|
||||
if got := ctx.SetService(svc); got != ctx {
|
||||
t.Fatal("SetService should return the same context for chaining")
|
||||
}
|
||||
|
||||
if svc.language != "fr" {
|
||||
t.Fatalf("SetService should apply locale to translator, got %q", svc.language)
|
||||
}
|
||||
|
||||
if got := Text("prompt.yes").Render(ctx); got != "o" {
|
||||
t.Fatalf("SetService locale translation = %q, want %q", got, "o")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContext_SetLocale_AppliesLocale(t *testing.T) {
|
||||
svc := &localeTranslator{}
|
||||
ctx := NewContextWithService(svc)
|
||||
|
||||
if got := ctx.SetLocale("en-GB"); got != ctx {
|
||||
t.Fatal("SetLocale should return the same context for chaining")
|
||||
}
|
||||
|
||||
if svc.language != "en" {
|
||||
t.Fatalf("SetLocale should apply locale to translator, got %q", svc.language)
|
||||
}
|
||||
|
||||
if got := Text("prompt.yes").Render(ctx); got != "y" {
|
||||
t.Fatalf("SetLocale translation = %q, want %q", got, "y")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContext_SetService_NilContext(t *testing.T) {
|
||||
var ctx *Context
|
||||
if got := ctx.SetService(nil); got != nil {
|
||||
t.Fatal("SetService on nil context should return nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContext_SetLocale_NilContext(t *testing.T) {
|
||||
var ctx *Context
|
||||
if got := ctx.SetLocale("en-GB"); got != nil {
|
||||
t.Fatal("SetLocale on nil context should return nil")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue