golang基于gettext概念的灵活翻译和人机交互插件库spreak的使用

Golang基于gettext概念的灵活翻译和人机交互插件库spreak的使用

Spreak是一个基于gettext概念的Go语言灵活翻译和人机交互库,需要Go 1.19+版本。

为什么选择另一个库?

虽然已有许多优秀的Go本地化库,但作者发现它们存在一些不足:有些使用自定义格式无法用通用工具编辑,有些仅支持单一语言或使用大量互斥锁,且没有工具能轻松提取待翻译字符串。因此开发了spreak来解决这些问题。

特性

  • 内置支持pomojson文件格式
  • 直接支持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

1 回复

更多关于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"))
}

最佳实践

  1. 组织翻译文件

    locales/
    ├── de/
    │   ├── LC_MESSAGES/
    │   │   ├── messages.po
    │   │   └── admin.po
    ├── fr/
    │   ├── LC_MESSAGES/
    │   │   ├── messages.po
    │   │   └── admin.po
    
  2. 提取翻译字符串: 使用xgettext工具从代码中提取待翻译字符串:

    xgettext --from-code=UTF-8 -o messages.pot *.go
    
  3. 自动重新加载(开发环境):

    bundle, err := spreak.NewBundle(
        spreak.WithSourceLanguage("en"),
        spreak.WithDomain("messages"),
        spreak.WithDomainPath("messages", "./locales"),
        spreak.WithLanguage("de"),
        spreak.WithAutoReload(true), // 自动重新加载翻译文件
    )
    
  4. 使用模板

    tmpl := template.Must(template.New("").Funcs(template.FuncMap{
        "T": t.Get,
    }).Parse(`<h1>{{T "Welcome"}}</h1>`))
    

与标准库i18n的比较

spreak相比Golang标准库的golang.org/x/text有以下优势:

  1. 基于成熟的gettext标准
  2. 支持.po/.mo文件格式
  3. 提供更完善的复数处理
  4. 支持上下文相关翻译
  5. 多域管理更灵活

总结

spreak为Golang应用提供了强大的国际化支持,遵循gettext标准使得它可以与现有的翻译工具链无缝集成。通过合理的组织翻译文件和正确使用API,可以轻松实现多语言支持。

对于需要更复杂国际化功能的项目,spreak是一个值得考虑的解决方案。

回到顶部