does Gin has Internationalization support(i18n)?

where's the Document or Example.

Comment From: syssam

Gin does not provide i18n, you could find some pacakge here. https://github.com/avelino/awesome-go

Comment From: aceyin

@syssam is there any plan for support i18n in gin framework?

Comment From: syssam

@aceyin you should ask GIN team any plan support i18n. or you can find i18n package on here. https://github.com/avelino/awesome-go

I have a validator package support multiple language. https://github.com/syssam/go-validator However, it does not fully test.

Comment From: nanom1t

Hi. Is it possible to use go-i18n(https://github.com/nicksnyder/go-i18n) with Gin? How to use it in templates?

Comment From: kataras

Hi. Is it possible to use go-i18n(https://github.com/nicksnyder/go-i18n) with Gin? How to use it in templates?

Hello @nanom1t, No, Gin does not support it, however other frameworks like Iris and Beego does support it for a long time now (iris does support it for 2 years+). I will copy-paste some content here so gin contributors can see its usage and hopefully manage to do something like this for gin users as well, all gophers deserves the Iris features:

./locales/en-US.all.yaml

- id: hi
  translation: "hi {{.}}"

a .go file

import "github.com/kataras/iris/v12"
import "github.com/iris-contrib/middleware/go-i18n"
// ...

app := iris.New()
locale := i18n.New(
    "./locales/en-US.all.yaml",
    "./locales/en-US.errors.yaml",
    "./locales/zh-CN.all.yaml",
)

app.Use(locale.Serve)

// Route, use of i18n in a line of `.Translate("key", optionalArguments)`.
app.Get("/", func(ctx iris.Context){
    message := ctx.Translate("hi", "iris")
    ctx.Writef("translated: %s", message )
})

Inside templates you can bind the ctx.Translate method itself.

app.Get("/", func(ctx iris.Context) {
    ctx.View("index.html", iris.Map{
        "tr": ctx.Translate,
    })
    // it will return "hello, iris"
    // when {{call .tr "hi" "iris"}}
})
{{call .tr "hi" "iris"}}

The full source code is located at: iris-contrib/middleare/go-i18n.

Comment From: appleboy

maybe we can create new middleware in https://github.com/gin-contrib

Comment From: cayter

I'm currently using gin to build a web framework for my own use case which comes with i18n middleware that uses https://github.com/nicksnyder/go-i18n/v2/i18n underneath. Hope that helps to give some reference on how to port it into https://github.com/gin-contrib.

Comment From: thinkerou

please commit pr to https://github.com/gin-contrib/i18n thanks!

Comment From: suisrc

middleware

package middleware

import (
    "github.com/gin-gonic/gin"
    "github.com/nicksnyder/go-i18n/v2/i18n"
    "github.com/suisrc/zgo/modules/helper"
)

// I18nMiddleware 国际化
func I18nMiddleware() gin.HandlerFunc {
    bundle := i18n.NewBundle(language.Chinese)
    bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
    bundle.LoadMessageFile("locales/active.zh-CN.toml")
    bundle.LoadMessageFile("locales/active.en-US.toml")

    return func(c *gin.Context) {
        lang := c.Request.FormValue("lang")
        accept := c.Request.Header.Get("Accept-Language")
        localizer := i18n.NewLocalizer(bundle, lang, accept)
        helper.SetI18n(c, localizer)

        c.Next()
    }
}

helper

package helper

import (
    "errors"
    "strconv"
    "strings"

    "github.com/gin-gonic/gin"
    "github.com/nicksnyder/go-i18n/v2/i18n"
)

// 定义上下文中的键
const (
    ResI18nKey = Prefix + "/res-i18n"
)

// FormatMessage fm
func FormatMessage(c *gin.Context, lc *i18n.LocalizeConfig) string {
    return MustI18n(c).MustLocalize(lc)
}

// FormatText ft
func FormatText(c *gin.Context, message *i18n.Message) string {
    return FormatCode(c, message, nil)
}

// FormatCode fc
func FormatCode(c *gin.Context, message *i18n.Message, args map[string]interface{}) string {
    if localizer, ok := GetI18n(c); ok {
        return localizer.MustLocalize(&i18n.LocalizeConfig{
            DefaultMessage: message,
            TemplateData:   args,
        })
    }
    // 加载i18n中间件后,不会进入该分支,简单处理未加载i18n中间件时候的处理内容
    if args == nil {
        return message.Other
    }
    text := message.Other
    for key, val := range args {
        text = strings.ReplaceAll(text, "{{."+key+"}}", toString(val))
    }
    return text
}

// MustI18n i18n
func MustI18n(c *gin.Context) *i18n.Localizer {
    localizer, ok := GetI18n(c)
    if !ok {
        panic(errors.New("context no has i18n localizer"))
    }
    return localizer
}

// GetI18n i18n
func GetI18n(c *gin.Context) (*i18n.Localizer, bool) {
    if v, ok := c.Get(ResI18nKey); ok {
        if l, b := v.(*i18n.Localizer); b {
            return l, true
        }
    }
    return nil, false
}

// SetI18n i18n
func SetI18n(c *gin.Context, l *i18n.Localizer) {
    c.Set(ResI18nKey, l)
}

// ToString to string
func toString(a interface{}) string {
    switch a.(type) {
    case int:
        return strconv.Itoa(a.(int))
    case bool:
        return strconv.FormatBool(a.(bool))
    case string:
        return a.(string)
    default:
        return "conver error"
    }
}

使用

message := helper.FormatText(c, &i18n.Message{ID: "service.signin.select-role-text", Other: "请选择角色"}

Comment From: suisrc

我将项目中的中间件抽出, 希望可以帮助到大家, suisrc/gin-i18n