diff --git a/modules/translation/i18n/i18n_test.go b/modules/translation/i18n/i18n_test.go
index ffe69a74df..b364992dfe 100644
--- a/modules/translation/i18n/i18n_test.go
+++ b/modules/translation/i18n/i18n_test.go
@@ -4,6 +4,7 @@
package i18n
import (
+ "html/template"
"strings"
"testing"
@@ -82,6 +83,71 @@ c=22
assert.Equal(t, "22", lang1.TrString("c"))
}
+type stringerPointerReceiver struct {
+ s string
+}
+
+func (s *stringerPointerReceiver) String() string {
+ return s.s
+}
+
+type stringerStructReceiver struct {
+ s string
+}
+
+func (s stringerStructReceiver) String() string {
+ return s.s
+}
+
+type errorStructReceiver struct {
+ s string
+}
+
+func (e errorStructReceiver) Error() string {
+ return e.s
+}
+
+type errorPointerReceiver struct {
+ s string
+}
+
+func (e *errorPointerReceiver) Error() string {
+ return e.s
+}
+
+func TestLocaleWithTemplate(t *testing.T) {
+ ls := NewLocaleStore()
+ assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", []byte(`key=%s`), nil))
+ lang1, _ := ls.Locale("lang1")
+
+ tmpl := template.New("test").Funcs(template.FuncMap{"tr": lang1.TrHTML})
+ tmpl = template.Must(tmpl.Parse(`{{tr "key" .var}}`))
+
+ cases := []struct {
+ in any
+ want string
+ }{
+ {"", "<str>"},
+ {[]byte(""), "[60 98 121 116 101 115 62]"},
+ {template.HTML(""), ""},
+ {stringerPointerReceiver{""}, "{<stringerPointerReceiver>}"},
+ {&stringerPointerReceiver{""}, "<stringerPointerReceiver ptr>"},
+ {stringerStructReceiver{""}, "<stringerStructReceiver>"},
+ {&stringerStructReceiver{""}, "<stringerStructReceiver ptr>"},
+ {errorStructReceiver{""}, "<errorStructReceiver>"},
+ {&errorStructReceiver{""}, "<errorStructReceiver ptr>"},
+ {errorPointerReceiver{""}, "{<errorPointerReceiver>}"},
+ {&errorPointerReceiver{""}, "<errorPointerReceiver ptr>"},
+ }
+
+ buf := &strings.Builder{}
+ for _, c := range cases {
+ buf.Reset()
+ assert.NoError(t, tmpl.Execute(buf, map[string]any{"var": c.in}))
+ assert.Equal(t, c.want, buf.String())
+ }
+}
+
func TestLocaleStoreQuirks(t *testing.T) {
const nl = "\n"
q := func(q1, s string, q2 ...string) string {
diff --git a/modules/translation/i18n/localestore.go b/modules/translation/i18n/localestore.go
index d0b5e05649..44c3fb0c88 100644
--- a/modules/translation/i18n/localestore.go
+++ b/modules/translation/i18n/localestore.go
@@ -136,12 +136,14 @@ func (l *locale) TrHTML(trKey string, trArgs ...any) template.HTML {
args := slices.Clone(trArgs)
for i, v := range args {
switch v := v.(type) {
+ case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, template.HTML:
+ // for most basic types (including template.HTML which is safe), just do nothing and use it
case string:
- args[i] = template.HTML(template.HTMLEscapeString(v))
+ args[i] = template.HTMLEscapeString(v)
case fmt.Stringer:
args[i] = template.HTMLEscapeString(v.String())
- default: // int, float, include template.HTML
- // do nothing, just use it
+ default:
+ args[i] = template.HTMLEscapeString(fmt.Sprint(v))
}
}
return template.HTML(l.TrString(trKey, args...))