golang国际化文本本地化处理插件库go-i18n的使用

Golang国际化文本本地化处理插件库go-i18n的使用

go-i18n是一个Go包和命令行工具,可以帮助你将Go程序翻译成多种语言。

主要特性

  • 支持Unicode通用语言环境数据存储库(CLDR)中200多种语言的复数形式字符串
  • 支持使用text/template语法的带命名变量的字符串
  • 支持任何格式的消息文件(如JSON、TOML、YAML)

安装

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

基本用法

创建Bundle

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

// 创建Bundle用于应用程序生命周期
bundle := i18n.NewBundle(language.English)

加载翻译文件

// 注册TOML解析器
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)

// 加载西班牙语翻译文件
bundle.LoadMessageFile("es.toml")

// 如果使用go:embed
//go:embed locale.*.toml
var LocaleFS embed.FS

bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
bundle.LoadMessageFileFS(LocaleFS, "locale.es.toml")

创建Localizer

func(w http.ResponseWriter, r *http.Request) {
    lang := r.FormValue("lang") // 从请求获取语言参数
    accept := r.Header.Get("Accept-Language") // 获取Accept-Language头
    localizer := i18n.NewLocalizer(bundle, lang, accept) // 创建本地化器
}

使用Localizer查找消息

localizer.Localize(&i18n.LocalizeConfig{
    DefaultMessage: &i18n.Message{
        ID: "PersonCats", // 消息ID
        One: "{{.Name}} has {{.Count}} cat.", // 单数形式
        Other: "{{.Name}} has {{.Count}} cats.", // 复数形式
    },
    TemplateData: map[string]interface{}{
        "Name": "Nick", // 模板数据
        "Count": 2,
    },
    PluralCount: 2, // 复数计数
}) // 输出: Nick has 2 cats.

命令行工具goi18n

安装命令行工具

go install -v github.com/nicksnyder/go-i18n/v2/goi18n@latest
goi18n -help

提取消息

使用goi18n extract命令从Go源文件中提取所有i18n.Message结构体字面量到消息文件中。

示例active.en.toml文件:

# active.en.toml
[PersonCats]
description = "The number of cats a person has"
one = "{{.Name}} has {{.Count}} cat."
other = "{{.Name}} has {{.Count}} cats."

翻译新语言

  1. 创建空的消息文件(如translate.es.toml)
  2. 运行goi18n merge active.en.toml translate.es.toml填充待翻译消息
  3. 翻译完成后重命名为active.es.toml
  4. 加载翻译文件到bundle中

示例translate.es.toml文件:

# translate.es.toml
[HelloPerson]
hash = "sha1-5b49bfdad81fedaeefb224b0ffc2acc58b09cff5"
other = "Hello {{.Name}}"

翻译后的active.es.toml文件:

# active.es.toml
[HelloPerson]
hash = "sha1-5b49bfdad81fedaeefb224b0ffc2acc58b09cff5"
other = "Hola {{.Name}}"

翻译新消息

  1. 运行goi18n extract更新active.en.toml
  2. 运行goi18n merge active.*.toml生成更新的translate.*.toml文件
  3. 翻译所有消息
  4. 运行goi18n merge active.*.toml translate.*.toml合并翻译

完整示例

package main

import (
	"embed"
	"fmt"
	"github.com/BurntSushi/toml"
	"github.com/nicksnyder/go-i18n/v2/i18n"
	"golang.org/x/text/language"
	"net/http"
)

//go:embed active.*.toml
var LocaleFS embed.FS

func main() {
	// 创建Bundle
	bundle := i18n.NewBundle(language.English)
	bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
	
	// 加载翻译文件
	bundle.LoadMessageFileFS(LocaleFS, "active.es.toml")
	
	// 模拟HTTP请求处理
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		// 从请求获取语言参数
		lang := r.FormValue("lang")
		accept := r.Header.Get("Accept-Language")
		
		// 创建Localizer
		localizer := i18n.NewLocalizer(bundle, lang, accept)
		
		// 本地化消息
		message, err := localizer.Localize(&i18n.LocalizeConfig{
			MessageID: "HelloWorld",
		})
		if err != nil {
			fmt.Fprintf(w, "Error: %v", err)
			return
		}
		
		fmt.Fprintf(w, message)
	})
	
	http.ListenAndServe(":8080", nil)
}

active.en.toml文件:

[HelloWorld]
other = "Hello World"

active.es.toml文件:

[HelloWorld]
other = "Hola Mundo"

这个示例展示了如何使用go-i18n进行基本的国际化文本处理。你可以通过访问http://localhost:8080?lang=es来测试西班牙语翻译。


更多关于golang国际化文本本地化处理插件库go-i18n的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang国际化文本本地化处理插件库go-i18n的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go-i18n 国际化文本本地化处理库使用指南

go-i18n 是一个强大的 Go 语言国际化(i18n)和本地化(l10n)库,它支持基于 JSON 或 TOML 格式的翻译文件,提供了灵活的文本本地化功能。下面我将详细介绍如何使用这个库。

安装

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

基本使用

1. 创建翻译文件

首先创建翻译文件,通常放在 locales 目录下:

locales/en-US.json:

{
  "hello_world": "Hello World",
  "emails": {
    "welcome": {
      "subject": "Welcome to our service",
      "body": "Hello {{.Name}}, thank you for joining us on {{.Date}}"
    }
  }
}

locales/zh-CN.json:

{
  "hello_world": "你好世界",
  "emails": {
    "welcome": {
      "subject": "欢迎使用我们的服务",
      "body": "你好 {{.Name}},感谢你在 {{.Date}} 加入我们"
    }
  }
}

2. 初始化 i18n Bundle

package main

import (
	"fmt"
	"log"

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

func main() {
	// 创建新的 Bundle
	bundle := i18n.NewBundle(language.English)
	
	// 注册 JSON 解码器
	bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
	
	// 加载翻译文件
	bundle.MustLoadMessageFile("locales/en-US.json")
	bundle.MustLoadMessageFile("locales/zh-CN.json")
	
	// 创建本地化器
	localizer := i18n.NewLocalizer(bundle, "zh-CN")
	
	// 获取简单翻译
	helloMsg, err := localizer.Localize(&i18n.LocalizeConfig{
		MessageID: "hello_world",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(helloMsg) // 输出: 你好世界
	
	// 获取带参数的翻译
	emailBody, err := localizer.Localize(&i18n.LocalizeConfig{
		MessageID: "emails.welcome.body",
		TemplateData: map[string]interface{}{
			"Name": "张三",
			"Date": "2023-05-20",
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(emailBody) // 输出: 你好 张三,感谢你在 2023-05-20 加入我们
}

高级功能

1. 复数处理

locales/en-US.json:

{
  "unread_notification_count": {
    "one": "You have {{.Count}} unread notification",
    "other": "You have {{.Count}} unread notifications"
  }
}

locales/zh-CN.json:

{
  "unread_notification_count": "您有 {{.Count}} 条未读通知"
}

使用代码:

count := 5
msg, err := localizer.Localize(&i18n.LocalizeConfig{
    MessageID:   "unread_notification_count",
    PluralCount: count,
    TemplateData: map[string]interface{}{
        "Count": count,
    },
})
// en-US: "You have 5 unread notifications"
// zh-CN: "您有 5 条未读通知"

2. 默认消息

msg, err := localizer.Localize(&i18n.LocalizeConfig{
    DefaultMessage: &i18n.Message{
        ID:    "greeting",
        Other: "Hello, {{.Name}}!",
    },
    TemplateData: map[string]interface{}{
        "Name": "John",
    },
})

3. 多语言切换

func getLocalizer(lang string) *i18n.Localizer {
    // 在实际应用中,你可能需要从请求头或cookie中获取语言偏好
    return i18n.NewLocalizer(bundle, lang)
}

func handler(w http.ResponseWriter, r *http.Request) {
    lang := r.URL.Query().Get("lang") // 从URL参数获取语言
    if lang == "" {
        lang = "en-US" // 默认语言
    }
    
    localizer := getLocalizer(lang)
    // 使用localizer进行本地化...
}

最佳实践

  1. 组织翻译文件:按功能模块组织翻译内容,而不是全部放在一个文件中
  2. 命名规范:使用点分隔的命名方式,如 module.component.message
  3. 参数验证:在模板中使用参数前进行验证
  4. 错误处理:总是检查 Localize 返回的错误
  5. 性能优化:在应用启动时加载所有翻译文件,而不是每次请求时加载

完整示例

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"

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

var bundle *i18n.Bundle

func initI18n() {
	bundle = i18n.NewBundle(language.English)
	bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
	bundle.MustLoadMessageFile("locales/en-US.json")
	bundle.MustLoadMessageFile("locales/zh-CN.json")
	bundle.MustLoadMessageFile("locales/ja-JP.json")
}

func main() {
	initI18n()
	
	http.HandleFunc("/greet", greetHandler)
	log.Println("Server started on :8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

func greetHandler(w http.ResponseWriter, r *http.Request) {
	lang := r.URL.Query().Get("lang")
	if lang == "" {
		lang = "en-US"
	}
	
	localizer := i18n.NewLocalizer(bundle, lang)
	
	name := r.URL.Query().Get("name")
	if name == "" {
		name = "Guest"
	}
	
	greeting, err := localizer.Localize(&i18n.LocalizeConfig{
		MessageID: "greeting.message",
		DefaultMessage: &i18n.Message{
			ID:    "greeting.message",
			Other: "Hello, {{.Name}}!",
		},
		TemplateData: map[string]interface{}{
			"Name": name,
		},
	})
	
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	
	fmt.Fprintf(w, greeting)
}

总结

go-i18n 提供了强大的国际化支持,包括:

  • 多语言翻译文件支持
  • 模板变量替换
  • 复数处理
  • 默认消息回退
  • 灵活的本地化配置

通过合理组织翻译文件和正确使用 Localizer,你可以轻松地为 Go 应用程序添加国际化支持。记得根据实际需求选择合适的语言标识符(如 zh-CN、en-US 等)并保持一致。

回到顶部