golang支持.po/.mo文件的i18n国际化文本模板处理插件txtemplate的使用
Golang 支持 .po/.mo 文件的 i18n 国际化文本模板处理插件 txtemplate 的使用
介绍
t 是一个受 GNU gettext 启发的 Go 语言国际化工具,支持 .po 和 .mo 文件格式。
安装
go get -u github.com/youthlin/t
或者在 go.mod 中添加:
require (
github.com/youthlin/t latest
)
使用示例
基本用法
package main
import (
"fmt"
"github.com/youthlin/t"
)
func main() {
// 1. 绑定翻译文件
path := "path/to/filename.po" // 可以是 .po 或 .mo 文件
// 或者目录路径
// path = "path/to/po_mo/dir"
// 默认绑定在 default 域
t.Load(path)
// 或者指定文本域
t.Bind("my-domain", path)
// 2. 设置使用的文本域
t.SetDomain("my-domain")
// 3. 设置用户语言
t.SetLocale(t.MostMatchLocale()) // 空则使用系统默认
// 4. 使用 gettext 翻译接口
fmt.Println(t.T("Hello, world"))
fmt.Println(t.T("Hello, %v", "Tom"))
// 单复数处理
fmt.Println(t.N("One apple", "%d apples", 1)) // One apple
fmt.Println(t.N("One apple", "%d apples", 2)) // 2 apples
// 带上下文的翻译
t.X("msg_context_text", "msg_id")
t.XN("msg_context_text", "msg_id", "msg_plural", n)
}
文本域(Domain)使用
// 绑定不同域的翻译文件
t.Bind("domain1", "path1")
t.Bind("domain2", "path2")
t.SetLocale("zh_CN")
// 使用默认域
t.T("msg_id")
// 设置当前域
t.SetDomain("domain1")
t.T("msg_id") // 使用 domain1
// 临时指定域
t.D("domain2").T("msg_id") // 使用 domain2
// 不存在的域会直接返回原消息
t.D("unknown-domain").T("msg_id") // 返回 "msg_id"
多语言支持
// 指定语言
t.L("zh_CN").T("msg_id")
// 根据用户偏好自动匹配语言
langs := t.Locales()
var supported []language.Tag
for _, lang := range langs {
supported = append(supported, language.Make(lang))
}
matcher := language.NewMatcher(supported)
// 从浏览器头获取用户语言
userAccept, _, _ := language.ParseAcceptLanguage("zh-CN,zh;q=0.9,en;q=0.8")
// 匹配最合适的语言
matchedTag, index, _ := matcher.Match(userAccept...)
userLang := langs[index]
t.L(userLang).T("msg_id")
// 同时指定域和语言
t.D("domain").L(userLang).T("msg_id")
API 概览
T(msgID, args...) // gettext
N(msgID, msgIDPlural, n, args...) // ngettext
X(msgCTxt, msgID, args...) // pgettext
XN(msgCTxt, msgID, msgIDPlural, n, args...) // npgettext
D(domain) // 指定域
L(locale) // 指定语言
提取翻译文本
使用 PoEdit 提取翻译文本:
- 在 PoEdit 设置中添加 Go 语言提取器
- 语言填 Go,扩展名填 *.go
- 提取命令填写:
xgettext -C --add-comments=TRANSLATORS: --force-po -o %o %C %K %F
- 关键字设置:
T:1;N:1,2;N64:1,2;X:2,1c;XN:2,3,1c;XN64:2,3,1c
或者直接使用命令行:
xgettext -C --add-comments=TRANSLATORS: --force-po -kT -kN:1,2 -kX:2,1c -kXN:2,3,1c *.go
从 HTML 模板提取
安装 xtemplate 工具:
go install github.com/youthlin/t/cmd/xtemplate@latest
已完成功能
- ✅ 支持 .mo 二进制文件
- ✅ 从模板文件中提取翻译文本
示例代码
以下是一个完整的示例,展示如何使用 t 库进行国际化:
package main
import (
"fmt"
"github.com/youthlin/t"
"golang.org/x/text/language"
)
func main() {
// 加载翻译文件
t.Load("locales") // 假设 locales 目录下有 zh_CN.po 和 en_US.po
// 设置语言为中文
t.SetLocale("zh_CN")
// 简单翻译
fmt.Println(t.T("Hello, world")) // 输出: 你好,世界
// 带参数的翻译
fmt.Println(t.T("Hello, %s", "Alice")) // 输出: 你好,Alice
// 单复数处理
fmt.Println(t.N("One apple", "%d apples", 1)) // 输出: 一个苹果
fmt.Println(t.N("One apple", "%d apples", 3)) // 输出: 3 个苹果
// 根据浏览器头自动选择语言
userAccept, _, _ := language.ParseAcceptLanguage("zh-CN,zh;q=0.9,en;q=0.8")
langs := t.Locales()
var supported []language.Tag
for _, lang := range langs {
supported = append(supported, language.Make(lang))
}
matcher := language.NewMatcher(supported)
_, index, _ := matcher.Match(userAccept...)
userLang := langs[index]
// 使用匹配到的语言
fmt.Println(t.L(userLang).T("Welcome")) // 根据用户语言输出欢迎语
}
这个示例展示了 t 库的主要功能,包括基本翻译、带参数翻译、单复数处理以及根据用户偏好自动选择语言。
更多关于golang支持.po/.mo文件的i18n国际化文本模板处理插件txtemplate的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang支持.po/.mo文件的i18n国际化文本模板处理插件txtemplate的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用 txtemplate 处理 Go 中的 i18n 国际化文本
txtemplate 是一个 Go 语言的国际化(i18n)文本处理库,它支持 .po/.mo 文件格式,可以与 Go 的标准模板引擎 text/template 或 html/template 配合使用。
安装 txtemplate
首先安装 txtemplate 库:
go get github.com/tdewolff/parse/v2/txtemplate
基本用法
1. 准备 .po 文件
创建一个翻译文件,例如 translations/zh_CN.po
:
msgid "Hello"
msgstr "你好"
msgid "Welcome, %s"
msgstr "欢迎, %s"
msgid "You have %d new messages"
msgstr "您有 %d 条新消息"
2. 加载翻译文件
package main
import (
"fmt"
"html/template"
"log"
"os"
"github.com/tdewolff/parse/v2/txtemplate"
)
func main() {
// 创建翻译器
translator := txtemplate.NewTranslator()
// 加载翻译文件
if err := translator.LoadPOFile("translations/zh_CN.po"); err != nil {
log.Fatal(err)
}
// 创建带有翻译功能的模板
tmpl := template.New("example").Funcs(txtemplate.FuncMap(translator))
// 解析模板
tmpl, err := tmpl.Parse(`
<p>{{ T "Hello" }}</p>
<p>{{ T "Welcome, %s" "张三" }}</p>
<p>{{ T "You have %d new messages" 5 }}</p>
`)
if err != nil {
log.Fatal(err)
}
// 执行模板
if err := tmpl.Execute(os.Stdout, nil); err != nil {
log.Fatal(err)
}
}
3. 输出结果
执行上面的代码会输出:
<p>你好</p>
<p>欢迎, 张三</p>
<p>您有 5 条新消息</p>
高级用法
支持复数形式
.po 文件中可以定义复数形式:
msgid "%d file"
msgid_plural "%d files"
msgstr[0] "%d 个文件"
msgstr[1] "%d 个文件"
在模板中使用:
{{ T "%d file" "%d files" 1 }} // 输出 "1 个文件"
{{ T "%d file" "%d files" 5 }} // 输出 "5 个文件"
上下文支持
有时相同的原文在不同上下文中需要不同翻译:
msgctxt "button"
msgid "Submit"
msgstr "提交"
msgctxt "form"
msgid "Submit"
msgstr "递交"
在模板中使用:
{{ TC "button" "Submit" }} // 输出 "提交"
{{ TC "form" "Submit" }} // 输出 "递交"
自动重新加载翻译文件
在开发环境中,可以启用自动重新加载:
translator := txtemplate.NewTranslator()
translator.SetAutoReload(true) // 启用自动重新加载
translator.SetWatchInterval(5 * time.Second) // 每5秒检查一次文件变化
最佳实践
-
组织翻译文件:按语言代码组织目录结构,如
translations/zh_CN/LC_MESSAGES/app.po
-
使用工具管理翻译:可以使用 Poedit 等工具编辑 .po 文件
-
在构建时编译 .mo 文件:虽然 txtemplate 可以直接使用 .po 文件,但生产环境建议使用编译后的 .mo 文件
-
处理缺失翻译:可以设置回调函数处理未翻译的文本
translator.SetMissingHandler(func(language, msgid string) string {
log.Printf("Missing translation for %q in language %q", msgid, language)
return msgid // 返回原文作为默认值
})
txtemplate 提供了简单而强大的国际化支持,能够很好地与 Go 的模板系统集成,是处理多语言应用的优秀选择。