feat(html): support count context in Text
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 00:24:17 +01:00
parent 61adbd55c5
commit 7679d2ded5
4 changed files with 133 additions and 3 deletions

View file

@ -65,6 +65,45 @@ func TestTextNode_Render_Good(t *testing.T) {
}
}
func TestTextNode_UsesContextDataForCount_Good(t *testing.T) {
svc, _ := i18n.New()
i18n.SetDefault(svc)
tests := []struct {
name string
key string
data map[string]any
want string
}{
{
name: "capitalised count",
key: "i18n.count.file",
data: map[string]any{"Count": 5},
want: "5 files",
},
{
name: "lowercase count",
key: "i18n.count.file",
data: map[string]any{"count": 1},
want: "1 file",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := NewContext()
for k, v := range tt.data {
ctx.Metadata[k] = v
}
got := Text(tt.key).Render(ctx)
if got != tt.want {
t.Fatalf("Text(%q).Render() = %q, want %q", tt.key, got, tt.want)
}
})
}
}
func TestTextNode_Escapes_Good(t *testing.T) {
ctx := NewContext()
node := Text("<script>alert('xss')</script>")

View file

@ -3,8 +3,11 @@
package html
func translateText(ctx *Context, key string, args ...any) string {
if ctx != nil && ctx.service != nil {
return ctx.service.T(key, args...)
if ctx != nil {
args = translationArgs(ctx, key, args)
if ctx.service != nil {
return ctx.service.T(key, args...)
}
}
return translateDefault(key, args...)

View file

@ -4,7 +4,91 @@
package html
import i18n "dappco.re/go/core/i18n"
import (
"strconv"
"strings"
i18n "dappco.re/go/core/i18n"
)
func translationArgs(ctx *Context, key string, args []any) []any {
if ctx == nil || len(ctx.Data) == 0 {
return args
}
count, ok := contextCount(ctx.Data)
if !ok {
return args
}
if len(args) == 0 {
return []any{count}
}
if strings.HasPrefix(key, "i18n.count.") && !isCountLike(args[0]) {
return append([]any{count}, args...)
}
return args
}
func contextCount(data map[string]any) (int, bool) {
if len(data) == 0 {
return 0, false
}
if v, ok := data["Count"]; ok {
if n, ok := countInt(v); ok {
return n, true
}
}
if v, ok := data["count"]; ok {
if n, ok := countInt(v); ok {
return n, true
}
}
return 0, false
}
func countInt(v any) (int, bool) {
switch n := v.(type) {
case int:
return n, true
case int8:
return int(n), true
case int16:
return int(n), true
case int32:
return int(n), true
case int64:
return int(n), true
case uint:
return int(n), true
case uint8:
return int(n), true
case uint16:
return int(n), true
case uint32:
return int(n), true
case uint64:
return int(n), true
case float32:
return int(n), true
case float64:
return int(n), true
case string:
n = strings.TrimSpace(n)
if n == "" {
return 0, false
}
if parsed, err := strconv.Atoi(n); err == nil {
return parsed, true
}
}
return 0, false
}
func isCountLike(v any) bool {
_, ok := countInt(v)
return ok
}
func translateDefault(key string, args ...any) string {
return i18n.T(key, args...)

View file

@ -4,6 +4,10 @@
package html
func translationArgs(_ *Context, _ string, args []any) []any {
return args
}
func translateDefault(key string, _ ...any) string {
return key
}