From a4d234121139b738ea34564cb7da7077e9e678bf Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 4 Apr 2026 00:49:13 +0000 Subject: [PATCH] fix(html): isolate cloned default translators Co-Authored-By: Virgil --- context.go | 1 + context_test.go | 18 ++++++++++++++++++ translator_clone_default.go | 21 +++++++++++++++++++++ translator_clone_js.go | 18 ++++++++++++++++++ 4 files changed, 58 insertions(+) create mode 100644 translator_clone_default.go create mode 100644 translator_clone_js.go diff --git a/context.go b/context.go index bbc04ad..2a82ee2 100644 --- a/context.go +++ b/context.go @@ -35,6 +35,7 @@ func (ctx *Context) Clone() *Context { clone.Data[key] = value } } + clone.service = cloneTranslator(clone.service, clone.Locale) return &clone } diff --git a/context_test.go b/context_test.go index 35408a1..8f79b65 100644 --- a/context_test.go +++ b/context_test.go @@ -175,6 +175,24 @@ func TestContext_CloneCopiesDataWithoutSharingMap(t *testing.T) { } } +func TestContext_CloneDoesNotShareDefaultTranslator(t *testing.T) { + ctx := NewContext("en-GB") + + clone := ctx.Clone() + if clone == nil { + t.Fatal("Clone should return a context") + } + + clone.SetLocale("fr-FR") + + if got := Text("prompt.yes").Render(ctx); got != "y" { + t.Fatalf("Clone should not mutate original default translator, got %q", got) + } + if got := Text("prompt.yes").Render(clone); got != "o" { + t.Fatalf("Clone should keep its own default translator, got %q", got) + } +} + func TestContext_WithDataReturnsClonedContext(t *testing.T) { ctx := NewContext() ctx.SetData("theme", "dark") diff --git a/translator_clone_default.go b/translator_clone_default.go new file mode 100644 index 0000000..8e723cf --- /dev/null +++ b/translator_clone_default.go @@ -0,0 +1,21 @@ +//go:build !js + +// SPDX-Licence-Identifier: EUPL-1.2 + +package html + +import i18n "dappco.re/go/core/i18n" + +func cloneTranslator(svc Translator, locale string) Translator { + if svc == nil { + return nil + } + + if current, ok := svc.(*i18n.Service); ok && current != nil { + clone := &i18n.Service{} + applyLocaleToService(clone, locale) + return clone + } + + return svc +} diff --git a/translator_clone_js.go b/translator_clone_js.go new file mode 100644 index 0000000..531f7db --- /dev/null +++ b/translator_clone_js.go @@ -0,0 +1,18 @@ +//go:build js + +// SPDX-Licence-Identifier: EUPL-1.2 + +package html + +func cloneTranslator(svc Translator, _ string) Translator { + if svc == nil { + return nil + } + + if current, ok := svc.(*defaultTranslator); ok && current != nil { + clone := *current + return &clone + } + + return svc +}