golang基于gettext概念的灵活翻译和人机交互插件库spreak的使用
Golang基于gettext概念的灵活翻译和人机交互插件库spreak的使用
Spreak是一个基于gettext概念的Go语言灵活翻译和人机交互库,需要Go 1.19+版本。
为什么选择另一个库?
虽然已有许多优秀的Go本地化库,但作者发现它们存在一些不足:有些使用自定义格式无法用通用工具编辑,有些仅支持单一语言或使用大量互斥锁,且没有工具能轻松提取待翻译字符串。因此开发了spreak来解决这些问题。
特性
- 内置支持
po
、mo
和json
文件格式 - 直接支持Go数据结构的人性化显示
- 支持
fs.FS
(如embed
) - 通过不可变性实现goroutine安全和无锁
- 强大的字符串提取器简化本地化流程(支持模板)
- 支持gettext和CLDR v44复数规则
- 支持双语和单语格式
使用方法
首先安装最新版本的库:
go get -u github.com/vorlif/spreak
基本使用示例
package main
import (
"fmt"
"golang.org/x/text/language"
"github.com/vorlif/spreak"
"github.com/vorlif/spreak/localize"
)
func main() {
// 创建加载所需语言翻译的bundle
// 通常一个应用只需要一个bundle
bundle, err := spreak.NewBundle(
// 设置程序代码/模板中使用的语言
spreak.WithSourceLanguage(language.English),
// 设置翻译文件加载路径
spreak.WithDomainPath(spreak.NoDomain, "./locale"),
// 指定要加载的语言
spreak.WithLanguage(language.German, language.Spanish, language.Chinese),
)
if err != nil {
panic(err)
}
// 创建Localizer选择要翻译的语言
t := spreak.NewLocalizer(bundle, language.Spanish)
// 翻译
fmt.Println(t.Get("Hello world"))
fmt.Println(t.NGetf("I have %d dog", "I have %d dogs", 2, 2))
fmt.Println(t.Localize(GetPlanet()))
// 输出:
// Hola Mundo
// Tengo 2 perros
// No conozco ningún planeta
}
func GetPlanet() *localize.Message {
return &localize.Message{
Singular: "I do not know any planet",
Plural: "I do not know any planets",
}
}
提取字符串
可以使用命令行工具xspreak提取翻译字符串。安装:
go install github.com/vorlif/xspreak@latest
测试安装:
xspreak --help
提取命令示例
# 生成.pot文件
xspreak -D path/to/source/ -p path/to/source/locale
# 生成.json文件
xspreak -D path/to/source/ -p path/to/source/locale -f json
翻译文件结构
如何组织翻译文件由您决定。假设您从路径"./locale"
加载域"helloworld"
和语言language.Spanish
:
spreak.WithDomainPath("helloworld", "./locale"),
spreak.WithLanguage(language.Spanish),
spreak默认会搜索以下文件:
./locale/es/helloworld.po
./locale/helloworld/es.po
./locale/es.po
./locale/LC_MESSAGES/es/helloworld.po
其中es
是[es-ES, es_ES, spa, es]
列表中的示例,文件扩展名.po
是[po, mo, json]
列表中的示例。
人性化包(humanize)
humanize
包提供了一组函数,将Go数据结构转换为人类可读格式。它广泛适配自Django项目并使用了Django的翻译。
使用示例
package main
import (
"fmt"
"time"
"golang.org/x/text/language"
"github.com/vorlif/spreak/humanize"
"github.com/vorlif/spreak/humanize/locale/ar"
"github.com/vorlif/spreak/humanize/locale/es"
"github.com/vorlif/spreak/humanize/locale/zhHans"
)
func main() {
// 加载所需语言的翻译
collection := humanize.MustNew(
humanize.WithLocale(es.New(), ar.New(), zhHans.New()),
)
// 创建humanizer
h := collection.CreateHumanizer(language.English)
// 使用函数...
fmt.Println(h.Intword(1_000_000_000))
// 输出: 1.0 billion
fmt.Println(h.NaturalDay(time.Now()))
// 输出: today
t := time.Now().Add(5 * time.Minute)
fmt.Println(h.NaturalTime(t))
// 输出: 5 minutes from now
d := -80 * time.Hour
fmt.Println(h.TimeSince(d))
// 输出: 3 days, 8 hours
// 为不同语言使用
h = collection.CreateHumanizer(language.Spanish)
fmt.Println(h.TimeSince(d))
// 输出: 3 días, 8 horas
}
许可证
spreak采用MIT许可证。humanize
包的翻译采用Django的BSD许可证。
更多关于golang基于gettext概念的灵活翻译和人机交互插件库spreak的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang基于gettext概念的灵活翻译和人机交互插件库spreak的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用spreak实现Golang的国际化(i18n)和本地化(l10n)
spreak是一个基于gettext概念的Golang国际化库,它提供了灵活的翻译解决方案和人机交互功能。下面我将详细介绍spreak的使用方法。
安装spreak
首先安装spreak库:
go get github.com/vorlif/spreak
基本使用
1. 初始化翻译系统
package main
import (
"fmt"
"log"
"github.com/vorlif/spreak"
"github.com/vorlif/spreak/catalog"
)
func main() {
// 创建本地化器
bundle, err := spreak.NewBundle(
spreak.WithSourceLanguage("en"), // 源语言
spreak.WithDomain("messages"), // 默认域
spreak.WithDomainPath("messages", "./locales"), // 翻译文件路径
spreak.WithLanguage("de"), // 目标语言
)
if err != nil {
log.Fatal(err)
}
// 创建翻译器
t := spreak.NewLocalizer(bundle, "de")
// 简单翻译
fmt.Println(t.Get("Hello world!"))
}
2. 创建翻译文件
在./locales/de/LC_MESSAGES/
目录下创建messages.po
文件:
msgid "Hello world!"
msgstr "Hallo Welt!"
然后使用msgfmt
工具编译为.mo
文件:
msgfmt messages.po -o messages.mo
高级功能
1. 复数形式处理
count := 3
fmt.Println(t.GetN("You have %d message", "You have %d messages", count, count))
对应的.po
文件:
msgid "You have %d message"
msgid_plural "You have %d messages"
msgstr[0] "Du hast %d Nachricht"
msgstr[1] "Du hast %d Nachrichten"
2. 上下文相关翻译
fmt.Println(t.GetC("button", "Save"))
.po
文件:
msgctxt "button"
msgid "Save"
msgstr "Speichern"
3. 多域管理
bundle, err := spreak.NewBundle(
spreak.WithSourceLanguage("en"),
spreak.WithDomain("messages"),
spreak.WithDomain("admin", "./locales/admin"), // 添加admin域
spreak.WithDomainPath("messages", "./locales"),
spreak.WithLanguage("de"),
)
// 使用特定域的翻译
adminT := spreak.NewLocalizer(bundle, "de", "admin")
fmt.Println(adminT.Get("Dashboard"))
4. 动态语言切换
func handleRequest(w http.ResponseWriter, r *http.Request) {
lang := r.Header.Get("Accept-Language")
t := spreak.NewLocalizer(bundle, lang)
fmt.Fprintf(w, t.Get("Welcome"))
}
最佳实践
-
组织翻译文件:
locales/ ├── de/ │ ├── LC_MESSAGES/ │ │ ├── messages.po │ │ └── admin.po ├── fr/ │ ├── LC_MESSAGES/ │ │ ├── messages.po │ │ └── admin.po
-
提取翻译字符串: 使用
xgettext
工具从代码中提取待翻译字符串:xgettext --from-code=UTF-8 -o messages.pot *.go
-
自动重新加载(开发环境):
bundle, err := spreak.NewBundle( spreak.WithSourceLanguage("en"), spreak.WithDomain("messages"), spreak.WithDomainPath("messages", "./locales"), spreak.WithLanguage("de"), spreak.WithAutoReload(true), // 自动重新加载翻译文件 )
-
使用模板:
tmpl := template.Must(template.New("").Funcs(template.FuncMap{ "T": t.Get, }).Parse(`<h1>{{T "Welcome"}}</h1>`))
与标准库i18n的比较
spreak相比Golang标准库的golang.org/x/text
有以下优势:
- 基于成熟的gettext标准
- 支持.po/.mo文件格式
- 提供更完善的复数处理
- 支持上下文相关翻译
- 多域管理更灵活
总结
spreak为Golang应用提供了强大的国际化支持,遵循gettext标准使得它可以与现有的翻译工具链无缝集成。通过合理的组织翻译文件和正确使用API,可以轻松实现多语言支持。
对于需要更复杂国际化功能的项目,spreak是一个值得考虑的解决方案。