在现代Web应用开发中,国际化(i18n)是一个非常常见的需求。不同地区的用户访问同一个应用时,希望能看到本地语言的界面,这就需要应用程序具备多语言支持能力。Go语言的国际化支持非常好,GoFrame框架也提供了完善的i18n支持,下面我们就来详细介绍一下如何在GoFrame项目中实现i18n。
安装i18n模块
GoFrame的i18n能力由g-i18n模块提供,首先需要安装该模块:
go get -u github.com/gogf/gf/v2/i18n/gi18n
配置i18n选项
在项目的配置文件(manifest/config/config.yaml)中添加i18n相关配置:
i18n:
path: i18n
language: zh-CN
delimiters: ["${", "}"]
其中:
path指定语言文件存储的目录路径language指定默认语言delimiters指定翻译字符串的定界符,默认为["${", "}"]
准备语言文件
在i18n目录下按语言编码创建不同的语言文件,如:
zh-CN.toml中文简体en-US.toml英文ja-JP.toml日文
每个语言文件中定义该语言的翻译字符串,格式为: key = "value"。如:
# zh-CN.toml
hello = "你好"
welcome = "欢迎来到GoFrame"
# en-US.toml
hello = "Hello"
welcome = "Welcome to GoFrame"
# ja-JP.toml
hello = "こんにちは"
welcome = "GoFrameへようこそ"
使用翻译函数
在代码中,通过调用i18n.Translate方法来翻译字符串:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/i18n/gi18n"
)
func main() {
g.I18n().SetLanguage("zh-CN") // 设置当前语言为中文
println(gi18n.Translate(`hello`)) // 输出: 你好
g.I18n().SetLanguage("en-US") // 切换语言为英文
println(gi18n.Translate(`hello`)) // 输出: Hello
}
gi18n.Translate方法会自动根据当前设置的语言,在对应的语言文件中查找翻译字符串。
g.I18n().SetLanguage用于设置当前的语言,修改该值可动态切换语言。
参数替换
翻译字符串支持参数替换,可以很方便的构造动态文本:
# zh-CN.toml
hello.name = "你好 ${name}, 年龄 ${age}"
# en-US.toml
hello.name = "Hello ${name}, age ${age}"
println(gi18n.Translate(gi18n.Translate(ctx, "{#hello.name}")))
// zh-CN: 你好 john, 年龄 18
// en-US: Hello john, age 18
在翻译字符串中使用${xxx}占位符即可。
复数规则
i18n模块支持复数规则,可以很方便的处理单复数形式:
# zh-CN.toml
book.count = "书 ${count} 本"
book.count.plural = "书 ${count} 本"
# en-US.toml
book.count = "${count} book"
book.count.plural = "${count} books"
println(gi18n.Translate(ctx,`{#book.count}`))
println(gi18n.Translate(ctx,`{#book.count}`))
// zh-CN: 书 1 本 、 书 2 本
// en-US: 1 book 、 2 books
通过key和key.plural来定义单复数形式的翻译字符串。中文中通常单复数形式一样,英文中则需要区分。使用时会根据count参数自动匹配单复数形式。
语言自动检测
通常i18n信息需要从HTTP请求中获取,gi18n模块对此做了很好的封装,在HTTP请求处理中可以非常方便的实现语言自动检测:
func(r *ghttp.Request) {
lang := r.GetString("lang") // 从请求参数、Cookie、Header等获取语言
r.SetCtx(gi18n.WithLanguage(r.Context(), lang))
// 后续的翻译会自动使用该请求的语言
r.Response.WriteTplDefault(g.Map{
"hello": gi18n.Translate(ctx,`hello`),
})
}
利用go context在请求间传递语言信息,使该请求后续的处理都自动使用指定的语言,不需要每次都设置。
热更新选项
在配置文件(manifest/config/config.yaml)中添加i18n.reload选项,设置为true:
i18n:
path: i18n
language: zh-CN
reload: true # 开启语言文件热更新
reload选项用于控制是否开启语言文件的热更新特性,默认为false。设置为true时,会在每次翻译时自动重新加载语言文件,以保证翻译始终使用最新的语言文件内容。
调用SetPath方法
如果需要在运行时动态修改语言文件的路径,可以调用gi18n.SetPath方法:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/i18n/gi18n"
)
func main() {
// 设置语言文件目录为 i18n-new
gi18n.SetPath("i18n-new")
// 之后的翻译会使用 i18n-new 目录下的语言文件
println(gi18n.Translate(ctx,`hello`))
}
gi18n.SetPath方法可以在运行时动态设置语言文件的目录路径。调用该方法后,后续的翻译都会使用新设置的目录下的语言文件。
修改语言文件
开启热更新后,我们可以在运行时修改语言文件的内容,修改会立即生效,无需重启应用。
例如,我们修改en-US.toml文件:
# en-US.toml
hello = "Hello, world!" # 修改翻译内容
然后在代码中执行翻译:
println(gi18n.Translate(ctx,`hello`))
// 输出: Hello, world!
可以看到,修改后的翻译内容已经立即生效了。
注意:
-
开启热更新会在每次翻译时重新加载语言文件,略微影响性能,建议在开发环境下开启,生产环境可以关闭。
-
gi18n.SetPath方法也会触发语言文件的重新加载。 -
如果语言文件的格式有错误,会导致加载失败,翻译会使用上一次加载的语言文件。
其他功能
gi18n还支持:
- 支持多种格式的语言文件(toml/ini/json/yaml等)
- 支持语言文件分级存储
- 支持自定义翻译加载器
- 等等
总结
GoFrame提供了强大灵活的i18n支持,让我们能够轻松的实现Web应用的多语言支持,提升产品的国际化能力。合理的规划i18n能力,可以让我们的应用更加通用,能够服务更多区域的用户。