需求
我想在 golang gin 同一套网站模板中同时支持中文和英文,类似 SpringBoot 中的 Thymeleaf I18N 那样,能在模板中调用翻译。
<label th:text="#{label}"></label>
改造思路
但是 gin i18n 的文档里并没有介绍如何在 template 中使用翻译。大概是很少有人用 gin 写网站吧,都是如何在 api 中使用翻译的方式。
Google 搜素了半天,几乎没找到几个模板国际化相关的参考。好不容易找到一个台湾大哥的实现方案,给了我很大启发。
其实就是使用 golang template 的自定义函数功能。
https://siongui.github.io/2016/01/19/i18n-go-web-application-by-gettext-html-template/const tmpl = `
<span>{{gettext "Home"}}</span>
<span>{{gettext "About"}}</span>
`
func main() {
setup("zh_TW", "messages", "locale")
setup("vi_VN", "messages", "locale")
funcMap := template.FuncMap{
"gettext": translate,
}
t, _ := template.New("foo").Funcs(funcMap).Parse(tmpl)
这个方案的实现非常像 IBM 的风格,从作者资料看确实在 IBM 呆过。。。
The new template package allows you to at add a function to template's function map, that would transform the given string to a localized version.
golang gin 模板 i18n 实现方案
参考 gin i18n 的这个封装库的 example 目录里的代码
https://github.com/gin-contrib/i18n
我感觉只要把 ginI18n.MustGetMessage 封装一下,映射到模板中,就基本满足我的使用需求了。
修改默认配置
https://github.com/gin-contrib/i18n/blob/master/constant.go
里面显式指定了翻译文件的文件类型,及所在目录。
所以项目里可以分离出一个 i18n 文件来写死这些配置。也方便在其他不需要此功能的项目,能快速删除代码。
开干!
安装 gin-contrib/i18n
go get github.com/gin-contrib/i18n
需要注意的是:
- gin-contrib/i18n 同时自动安装了 nicksnyder/go-i18n
- 自动升级了 gin 的版本
go: added github.com/gin-contrib/i18n v0.0.1
go: upgraded github.com/gin-gonic/gin v1.7.2 => v1.7.4
go: added github.com/nicksnyder/go-i18n/v2 v2.1.2
代码实现
i18n.go
- 将默认语言设置为了中文。因为主要客户在国内,但是对于某些业务,还是设置为英文合适
- 只判断 url 中的语言参数,而不判断 http 头里的 Accept-Language。默认配置会优先使用 Accept-Language,但是我不喜欢这种逻辑
- 选择 toml 是因为示例基本都是 toml 的,看起来对复杂场景(复数、整句带变量)支持较好。
package main
import (
"github.com/BurntSushi/toml"
ginI18n "github.com/gin-contrib/i18n"
"github.com/gin-gonic/gin"
"golang.org/x/text/language"
)
// apply i18n middleware
// router.Use(GinI18nLocalize())
func GinI18nLocalize() gin.HandlerFunc {
return ginI18n.Localize(
ginI18n.WithBundle(&ginI18n.BundleCfg{
RootPath: "./lang",
AcceptLanguage: []language.Tag{language.Chinese, language.English},
DefaultLanguage: language.Chinese,
FormatBundleFile: "toml",
UnmarshalFunc: toml.Unmarshal,
}),
ginI18n.WithGetLngHandle(
func(context *gin.Context, defaultLng string) string {
lng := context.Query("lang")
if lng == "" {
return defaultLng
}
return lng
},
),
)
}
main.go
r := gin.Default()
// apply i18n middleware
r.Use(GinI18nLocalize())
// 自定义模板函数
r.SetFuncMap(template.FuncMap{
"Localize": ginI18n.GetMessage,
})
lang 目录,存放翻译资源文件
> tree lang/
lang/
├── en.toml
└── zh.toml
> cat lang/en.toml
News = "News"
> cat lang/zh.toml
News = "新闻资讯"
模板 index.html 中使用
<h2>{{ Localize "News" }}</h2>
链接格式:
默认中文
http://localhost:9014/
英文
http://localhost:9014/?lang=en
中文
http://localhost:9014/?lang=zh
没有法语资源,所以使用默认的中文翻译
http://localhost:9014/?lang=fr
测试了一下,成功!
在线效果演示
例如,我写了个小 demo:
- 中文版 https://www.sunzhongwei.com/tools2/combine-images?lang=zh
- 英文版 https://www.sunzhongwei.com/tools2/combine-images?lang=en
- 日语版 https://www.sunzhongwei.com/tools2/combine-images?lang=ja
感慨
- golang gin 的文档真是少,即便找到了 i18n 的库,也得看代码才知道怎么用。相比 SpringBoot 详尽的文档,感觉看 go 的源码更爽一点。。。
- 缺乏标准,就得花大精力去选库,确实挺耗费精力
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式