i18n: add 'tr' template function inside the translation files themselves

This commit is contained in:
Gerasimos (Makis) Maropoulos 2020-09-10 05:57:49 +03:00
parent 777ef0cd3e
commit a1f7f57922
No known key found for this signature in database
GPG Key ID: 5DBE766BD26A54E7
4 changed files with 44 additions and 35 deletions

View File

@ -1,2 +1,2 @@
Dog: "σκυλί" Dog: "σκυλί"
HiDogs: Γειά {{plural (tr .locale "Dog") .count }} HiDogs: Γειά {{plural (tr "Dog") .count }}

View File

@ -1,2 +1,2 @@
Dog: "dog" Dog: "dog"
HiDogs: Hi {{plural (tr .locale "Dog") .count }} HiDogs: Hi {{plural (tr "Dog") .count }}

View File

@ -32,8 +32,7 @@ func newApp() *iris.Application {
app.Get("/", func(ctx iris.Context) { app.Get("/", func(ctx iris.Context) {
text := ctx.Tr("HiDogs", iris.Map{ text := ctx.Tr("HiDogs", iris.Map{
"locale": ctx.GetLocale(), "count": 2,
"count": 2,
}) // prints "Hi 2 dogs". }) // prints "Hi 2 dogs".
ctx.WriteString(text) ctx.WriteString(text)
}) })

View File

@ -7,6 +7,7 @@ import (
"io/ioutil" "io/ioutil"
"path/filepath" "path/filepath"
"strings" "strings"
"sync"
"text/template" "text/template"
"github.com/kataras/iris/v12/context" "github.com/kataras/iris/v12/context"
@ -92,14 +93,6 @@ func load(assetNames []string, asset func(string) ([]byte, error), options ...Lo
Left: "{{", Left: "{{",
Right: "}}", Right: "}}",
Strict: false, Strict: false,
FuncMap: template.FuncMap{
// get returns the value of a translate key, can be used inside other template keys
// to translate different words based on the current locale.
"tr": func(locale context.Locale, key string, args ...interface{}) string {
return locale.GetMessage(key, args...)
},
// ^ Alternative to {{call .tr "Dog" | plural }}
},
} }
for _, opt := range options { for _, opt := range options {
@ -146,6 +139,18 @@ func load(assetNames []string, asset func(string) ([]byte, error), options ...Lo
other = make(map[string]interface{}) other = make(map[string]interface{})
) )
t := m.Languages[langIndex]
locale := &defaultLocale{
index: langIndex,
id: t.String(),
tag: &t,
templateKeys: templateKeys,
lineKeys: lineKeys,
other: other,
defaultMessageFunc: m.defaultMessageFunc,
}
for k, v := range keyValues { for k, v := range keyValues {
// fmt.Printf("[%d] %s = %v of type: [%T]\n", langIndex, k, v, v) // fmt.Printf("[%d] %s = %v of type: [%T]\n", langIndex, k, v, v)
@ -153,7 +158,17 @@ func load(assetNames []string, asset func(string) ([]byte, error), options ...Lo
case string: case string:
if leftIdx, rightIdx := strings.Index(value, c.Left), strings.Index(value, c.Right); leftIdx != -1 && rightIdx > leftIdx { if leftIdx, rightIdx := strings.Index(value, c.Left), strings.Index(value, c.Right); leftIdx != -1 && rightIdx > leftIdx {
// we assume it's template? // we assume it's template?
if t, err := template.New(k).Delims(c.Left, c.Right).Funcs(c.FuncMap).Parse(value); err == nil { // each file:line has its own template funcs so,
// just map it.
builtinFuncs := template.FuncMap{
"tr": locale.GetMessage,
}
if t, err := template.New(k).
Delims(c.Left, c.Right).
Funcs(builtinFuncs).
Funcs(c.FuncMap).
Parse(value); err == nil {
templateKeys[k] = t templateKeys[k] = t
continue continue
} else if c.Strict { } else if c.Strict {
@ -166,18 +181,7 @@ func load(assetNames []string, asset func(string) ([]byte, error), options ...Lo
other[k] = v other[k] = v
} }
} locales[langIndex] = locale
t := m.Languages[langIndex]
locales[langIndex] = &defaultLocale{
index: langIndex,
id: t.String(),
tag: &t,
templateKeys: templateKeys,
lineKeys: lineKeys,
other: other,
defaultMessageFunc: m.defaultMessageFunc,
} }
} }
@ -250,6 +254,11 @@ type defaultLocale struct {
defaultMessageFunc MessageFunc defaultMessageFunc MessageFunc
} }
type templateKey struct {
Template *template.Template
once *sync.Once
}
func (l *defaultLocale) Index() int { func (l *defaultLocale) Index() int {
return l.index return l.index
} }
@ -272,23 +281,24 @@ func (l *defaultLocale) GetMessageContext(ctx *context.Context, key string, args
} }
func (l *defaultLocale) getMessage(langInput, key string, args ...interface{}) string { func (l *defaultLocale) getMessage(langInput, key string, args ...interface{}) string {
n := len(args)
if n > 0 { // search on templates.
// search on templates. if tmpl, ok := l.templateKeys[key]; ok {
if tmpl, ok := l.templateKeys[key]; ok { buf := new(bytes.Buffer)
buf := new(bytes.Buffer) err := tmpl.Execute(buf, args[0])
err := tmpl.Execute(buf, args[0]) if err != nil {
if err != nil { return err.Error()
return err.Error()
}
return buf.String()
} }
return buf.String()
} }
if text, ok := l.lineKeys[key]; ok { if text, ok := l.lineKeys[key]; ok {
return fmt.Sprintf(text, args...) return fmt.Sprintf(text, args...)
} }
n := len(args)
if v, ok := l.other[key]; ok { if v, ok := l.other[key]; ok {
if n > 0 { if n > 0 {
return fmt.Sprintf("%v [%v]", v, args) return fmt.Sprintf("%v [%v]", v, args)