golang支持.po/.mo文件的i18n国际化插件库t的使用

Golang 支持 .po/.mo 文件的 i18n 国际化插件库 t 的使用

介绍

t 是一个 Go 语言的国际化工具,灵感来自 GNU gettext,支持 .po 和 .mo 文件格式。

安装

go get -u github.com/youthlin/t

或者在 go.mod 中添加:

require (
    github.com/youthlin/t latest
)

也可以使用 Gitee 镜像:

// go.mod:
replace github.com/youthlin/t latest => gitee.com/youthlin/gottext 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"    
	// (如果 mo 和 po 同名,po 会覆盖 mo 文件,因为 po 是文本文件更方便修改)
	
	// 默认绑定到 default 域
	t.Load(path) 
	// 或者指定文本域
	t.Bind("my-domain", path) 
	
	// 2. 设置当前使用的文本域
	t.SetDomain("my-domain")
	
	// 3. 设置用户语言
	// t.SetLocale("zh_CN")
	t.SetLocale(t.MostMatchLocale()) // 空表示使用系统默认
	
	// 4. 使用 gettext API
	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)) // 输出: %d apples
	
	// 支持格式化参数
	fmt.Println(t.N("One apple", "%d apples", 2, 2)) // 输出: 2 apples
	fmt.Println(t.N("%[2]s has one apple", "%[2]s has %[1]d apples", 2, 200, "Bob"))
	// 输出: Bob has 200 apples
	
	// 带上下文的翻译
	t.X("msg_context_text", "msg_id")
	t.XN("msg_context_text", "msg_id", "msg_plural", n)
}

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)                             // 指定语言

文本域使用

t.Bind("domain1", "path1")
t.Bind("domain2", "path2")
t.SetLocale("zh_CN")

t.T("msg_id")           // 使用 default 域

t.SetDomain("domain1")
t.T("msg_id")           // 使用 domain1
t.D("domain2").T("msg_id") // 使用 domain2
t.D("unknown-domain").T("msg_id") // 直接返回 "msg_id"

语言选择

如果是 web 应用,可以为每个请求设置不同语言:

t.Load(path)

// 1. 直接指定语言
t.L("zh_CN").T("msg_id")

// 2. 根据用户偏好选择语言
// 2.1 获取服务器支持的语言
langs := t.Locales()
var supported []language.Tag
for _, lang = range langs {
    supported = append(supported, language.Make(lang))
}
matcher := language.NewMatcher(supported)

// 2.2 获取用户接受的语言 (从浏览器头或cookie)
userAccept, _, _ := language.ParseAcceptLanguage("zh-CN,zh;q=0.9,en;q=0.8")

// 2.3 匹配最适合的语言
matchedTag, index, _ := matcher.Match(userAccept...)
userLang := langs[index]
t.L(userLang).T("msg_id")

// 同时指定文本域和语言
t.D(domain).L(userLang).T("msg_id")

提取翻译文本

使用 PoEdit 提取翻译文本:

# 在 PoEdit 中设置提取器:
# 语言: 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 模板提取

安装提取工具:

go install github.com/youthlin/t/cmd/xtemplate@latest

已完成功能

  • ✅ 支持 mo 二进制文件
  • ✅ 从模板文件中提取文本

更多关于golang支持.po/.mo文件的i18n国际化插件库t的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang支持.po/.mo文件的i18n国际化插件库t的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang 国际化(i18n)库推荐及使用指南

在Go语言中,有几个优秀的库可以处理.po/.mo文件的国际化(i18n)需求。下面我将介绍几个主流的选择,并提供详细的使用示例。

1. go-i18n (推荐)

go-i18n 是由Go官方团队维护的国际化库,支持.po/.mo文件格式。

安装

go get -u github.com/nicksnyder/go-i18n/v2/i18n
go get -u github.com/nicksnyder/go-i18n/v2/goi18n

基本使用

  1. 首先创建翻译文件,例如 active.en.toml:
[hello]
other = "Hello, World!"

[greeting]
other = "Hello, {{.Name}}"
  1. 代码示例:
package main

import (
	"fmt"
	"log"

	"github.com/nicksnyder/go-i18n/v2/i18n"
	"golang.org/x/text/language"
)

func main() {
	// 创建i18n Bundle
	bundle := i18n.NewBundle(language.English)
	
	// 加载翻译文件
	bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
	bundle.MustLoadMessageFile("active.en.toml")
	bundle.MustLoadMessageFile("active.zh.toml") // 中文翻译文件

	// 创建本地化器
	localizer := i18n.NewLocalizer(bundle, "zh") // 使用中文

	// 简单翻译
	helloMsg, err := localizer.Localize(&i18n.LocalizeConfig{
		MessageID: "hello",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(helloMsg) // 输出: 你好, 世界!

	// 带参数的翻译
	greetingMsg, err := localizer.Localize(&i18n.LocalizeConfig{
		MessageID: "greeting",
		TemplateData: map[string]string{
			"Name": "张三",
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(greetingMsg) // 输出: 你好, 张三
}

2. go-gettext

如果你需要直接处理.po/.mo文件,可以使用 go-gettext 库。

安装

go get github.com/leonelquinteros/gotext

使用示例

  1. 创建 locales/en_US/LC_MESSAGES/default.po 文件:
msgid "hello"
msgstr "Hello, World!"

msgid "greeting"
msgstr "Hello, %s"
  1. 编译为.mo文件:
msgfmt -o locales/en_US/LC_MESSAGES/default.mo locales/en_US/LC_MESSAGES/default.po
  1. 代码示例:
package main

import (
	"fmt"
	"github.com/leonelquinteros/gotext"
)

func main() {
	// 配置语言环境
	gotext.Configure("locales", "en_US", "default")
	
	// 简单翻译
	fmt.Println(gotext.Get("hello")) // 输出: Hello, World!
	
	// 带参数的翻译
	fmt.Println(gotext.Get("greeting", "John")) // 输出: Hello, John
}

3. 使用PO文件的最佳实践

  1. 组织翻译文件:
locales/
├── en_US/
│   └── LC_MESSAGES/
│       ├── default.po
│       └── default.mo
└── zh_CN/
    └── LC_MESSAGES/
        ├── default.po
        └── default.mo
  1. 自动重新加载 (开发环境):
// 使用gotext的自动重新加载功能
gotext.Configure("locales", "en_US", "default")
gotext.Get("hello") // 从磁盘加载

// 开发模式下可以设置自动重新加载
gotext.GetStorage().SetDomain("default")
gotext.GetStorage().SetLanguage("en_US")
  1. Web应用中的使用 (基于Gin框架示例):
func i18nMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		lang := c.GetHeader("Accept-Language")
		if lang == "" {
			lang = "en_US" // 默认语言
		}
		
		// 配置当前请求的语言
		gotext.Configure("locales", lang, "default")
		c.Next()
	}
}

func main() {
	r := gin.Default()
	r.Use(i18nMiddleware())
	
	r.GET("/hello", func(c *gin.Context) {
		c.String(200, gotext.Get("hello"))
	})
	
	r.Run(":8080")
}

总结

  • 对于大多数项目,推荐使用 go-i18n,它功能全面且维护良好
  • 如果需要直接处理.po/.mo文件,go-gettext 是不错的选择
  • 在Web应用中,可以通过中间件根据请求头动态切换语言
  • 开发环境下可以启用自动重新加载翻译文件,方便调试

以上库都支持常见的国际化需求,如复数处理、变量插值等高级功能。根据项目需求选择合适的解决方案即可。

回到顶部