From a1f7f57922be07f44bdf6b12bd7817c3194a39b4 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Thu, 10 Sep 2020 05:57:49 +0300 Subject: [PATCH] i18n: add 'tr' template function inside the translation files themselves --- .../i18n-template/locales/el-GR/welcome.yml | 2 +- .../i18n-template/locales/en-US/welcome.yml | 2 +- _examples/i18n/i18n-template/main.go | 3 +- i18n/loader.go | 72 +++++++++++-------- 4 files changed, 44 insertions(+), 35 deletions(-) diff --git a/_examples/i18n/i18n-template/locales/el-GR/welcome.yml b/_examples/i18n/i18n-template/locales/el-GR/welcome.yml index fc0e563d..6370122e 100644 --- a/_examples/i18n/i18n-template/locales/el-GR/welcome.yml +++ b/_examples/i18n/i18n-template/locales/el-GR/welcome.yml @@ -1,2 +1,2 @@ Dog: "σκυλί" -HiDogs: Γειά {{plural (tr .locale "Dog") .count }} \ No newline at end of file +HiDogs: Γειά {{plural (tr "Dog") .count }} \ No newline at end of file diff --git a/_examples/i18n/i18n-template/locales/en-US/welcome.yml b/_examples/i18n/i18n-template/locales/en-US/welcome.yml index 4f118ced..82510907 100644 --- a/_examples/i18n/i18n-template/locales/en-US/welcome.yml +++ b/_examples/i18n/i18n-template/locales/en-US/welcome.yml @@ -1,2 +1,2 @@ Dog: "dog" -HiDogs: Hi {{plural (tr .locale "Dog") .count }} \ No newline at end of file +HiDogs: Hi {{plural (tr "Dog") .count }} \ No newline at end of file diff --git a/_examples/i18n/i18n-template/main.go b/_examples/i18n/i18n-template/main.go index be0f8eb2..6a036f95 100644 --- a/_examples/i18n/i18n-template/main.go +++ b/_examples/i18n/i18n-template/main.go @@ -32,8 +32,7 @@ func newApp() *iris.Application { app.Get("/", func(ctx iris.Context) { text := ctx.Tr("HiDogs", iris.Map{ - "locale": ctx.GetLocale(), - "count": 2, + "count": 2, }) // prints "Hi 2 dogs". ctx.WriteString(text) }) diff --git a/i18n/loader.go b/i18n/loader.go index 35fee46f..6b9faf66 100644 --- a/i18n/loader.go +++ b/i18n/loader.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "path/filepath" "strings" + "sync" "text/template" "github.com/kataras/iris/v12/context" @@ -92,14 +93,6 @@ func load(assetNames []string, asset func(string) ([]byte, error), options ...Lo Left: "{{", Right: "}}", 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 { @@ -146,6 +139,18 @@ func load(assetNames []string, asset func(string) ([]byte, error), options ...Lo 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 { // 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: if leftIdx, rightIdx := strings.Index(value, c.Left), strings.Index(value, c.Right); leftIdx != -1 && rightIdx > leftIdx { // 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 continue } else if c.Strict { @@ -166,18 +181,7 @@ func load(assetNames []string, asset func(string) ([]byte, error), options ...Lo other[k] = v } - } - - t := m.Languages[langIndex] - locales[langIndex] = &defaultLocale{ - index: langIndex, - id: t.String(), - tag: &t, - templateKeys: templateKeys, - lineKeys: lineKeys, - other: other, - - defaultMessageFunc: m.defaultMessageFunc, + locales[langIndex] = locale } } @@ -250,6 +254,11 @@ type defaultLocale struct { defaultMessageFunc MessageFunc } +type templateKey struct { + Template *template.Template + once *sync.Once +} + func (l *defaultLocale) Index() int { 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 { - n := len(args) - if n > 0 { - // search on templates. - if tmpl, ok := l.templateKeys[key]; ok { - buf := new(bytes.Buffer) - err := tmpl.Execute(buf, args[0]) - if err != nil { - return err.Error() - } - return buf.String() + + // search on templates. + if tmpl, ok := l.templateKeys[key]; ok { + buf := new(bytes.Buffer) + err := tmpl.Execute(buf, args[0]) + if err != nil { + return err.Error() } + + return buf.String() } if text, ok := l.lineKeys[key]; ok { return fmt.Sprintf(text, args...) } + n := len(args) + if v, ok := l.other[key]; ok { if n > 0 { return fmt.Sprintf("%v [%v]", v, args)