Go语言项目实现多语言切换
目录
一、实现
使用 go-i18n 包,实现将你的go程序翻译成多种语言
go get github.com/nicksnyder/go-i18n/v2/i18n
(一)预定义多语言文本
/config
/locales
en.json # 英文
zh.json # 中文
ja.json # 日文
项目存储多语言文本json
例子:zh.json
// zh.json
{
"welcome": "欢迎访问!当前时间:{{.Now}}",
"error_404": "页面不存在",
"button": {
"submit": "提交"
}
}
key 就是渲染html页面的变量,val就是展示的文本
(二)初始化i18n加载器
import "github.com/nicksnyder/go-i18n/v2/i18n"
bundle := i18n.NewBundle(language.English)
func InitLocales() {
langs := []string{"en", "zh", "ja"}
for _, lang := range langs {
bundle := i18n.NewBundle(language.Make(lang))
bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
file, _ := os.ReadFile(fmt.Sprintf("config/locales/%s.json", lang))
bundle.MustParseMessageFileBytes(file, lang+".json")
bundles[lang] = bundle
}
}
(三)动态获取翻译文本
例子一:以 http 的 header 进行识别
// 根据请求头切换语言
func GetTranslator(r *http.Request) *i18n.Localizer {
accept := r.Header.Get("Accept-Language")
tag, _, _ := language.ParseAcceptLanguage(accept)
return i18n.NewLocalizer(bundles["zh"], tag...)
}
// 使用示例
func Handler(w http.ResponseWriter, r *http.Request) {
loc := GetTranslator(r)
msg := loc.MustLocalize(&i18n.LocalizeConfig{
MessageID: "welcome",
TemplateData: map[string]interface{}{
"Now": time.Now().Format("2006-01-02"),
},
})
fmt.Fprint(w, msg)
}
例子二:Gin框架集成
// 中间件注入语言包
func I18nMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
loc := i18n.NewLocalizer(bundle, c.GetHeader("Accept-Language"))
c.Set("loc", loc)
c.Next()
}
}
// 控制器调用
func Welcome(c *gin.Context) {
loc := c.MustGet("loc").(*i18n.Localizer)
c.String(200, loc.MustLocalize("welcome"))
}
例子三、HTML模板动态渲染
注册一个模版函数,在模版重调用即可
<!-- 注册模板函数 -->
funcMap := template.FuncMap{
"T": func(msgID string, args ...interface{}) string {
return loc.MustLocalize(msgID, args...)
}
}
<!-- 模板中使用 -->
<h1>{{T "welcome"}}</h1>
<button>{{T "button.submit"}}</button>
二、原理
其核心流程:
-
资源文件存储:按 lang.json 格式保存翻译文本
-
加载器解析:根据 Locale 加载对应语言包
-
模板注入:通过函数动态替换文本
本质上就是为项目预定义好多语言文本文件,然后根据语言进行切换
三、注意事项
-
当某个变量的多语言不存在时,应该返回默认,而不是报错
-
当切换某种语言不支持时,应该返回默认语言
-
该方案可能存在内存问题,将 json 文件加载到内存,若翻译文件越大,内存占用越多
-
应该是目前最流行多语言解决方案,但是存在缺陷:只能翻译固定的文本,像从数据库查询的文本则不支持翻译
你还知道哪些更优的方案吗
👏欢迎大家评论区分享留言!!!