golang支持上下文感知国际化并具有简洁API的i18n插件库ctxi18n的使用
Golang支持上下文感知国际化并具有简洁API的i18n插件库ctxi18n的使用
介绍
ctxi18n
是一个受Ruby on Rails国际化功能启发的Go语言国际化库,旨在为Go应用提供同样简单易用的国际化支持。
该库专注于将i18n数据提供给应用的上下文实例,同时也足够灵活可以直接使用。
主要特性:
- 加载YAML或JSON格式的本地化文件,结构类似Ruby i18n
- 轻松将本地化对象添加到上下文中
- 支持使用
fs.FS
加载数据 - 简洁的API方法如
i18n.T()
和i18n.N()
- 支持简单的键值插值,如
Some %{key} text
- 支持复数规则
- 翻译缺失时的默认值
使用示例
首先导入库:
import "github.com/invopop/ctxi18n"
加载翻译文件
创建YAML或JSON翻译文件,例如:
en:
welcome:
title: "Welcome to our application!"
login: "Log in"
signup: "Sign up"
forgot-password: "Forgot Password?"
es:
welcome:
title: "¡Bienvenido a nuestra aplicación!"
login: "Ingresarse"
signup: "Registrarse"
forgot-password: "¿Olvidaste tu contraseña?"
加载翻译文件:
if err := ctxi18n.Load(assets.Content); err != nil {
panic(err)
}
或设置默认语言:
if err := ctxi18n.LoadWithDefault(assets.Content, "en"); err != nil {
panic(err)
}
上下文中使用
在HTTP或gRPC请求上下文中设置语言:
ctx = ctxi18n.WithLocale(ctx, "en")
支持RFC9110和Accept-Language
头:
ctx = ctxi18n.WithLocale(ctx, "en-US,en;q=0.9,es;q=0.8")
翻译文本
有两种使用方式:
- 直接使用上下文方法:
import "github.com/invopop/ctxi18n/i18n"
fmt.Println(i18n.T(ctx, "welcome.title"))
- 从上下文中获取本地化对象:
l := ctxi18n.Locale(ctx)
fmt.Println(l.T("welcome.title"))
默认值
当翻译缺失时:
fmt.Println(l.T("welcome.no.text"))
// 输出: !(MISSING welcome.no.text)
设置默认值:
fmt.Println(i18n.T(ctx, "welcome.question", i18n.Default("Just ask!")))
// 输出: "Just ask!"
code := "EUR"
fmt.Println(i18n.T(ctx, "currencies."+code, i18n.Default(code)))
// 输出: "EUR"
或检查是否存在:
if !i18n.Has(ctx, "welcome.question") {
fmt.Println("Just ask!")
}
插值
简单插值:
en:
welcome:
title: "Hi %{name}, welcome to our App!"
使用:
i18n.T(ctx, "welcome.title", i18n.M{"name":"Sam"})
结合默认值:
i18n.T(ctx, "welcome.title", i18n.Default("Hi %{name}"), i18n.M{"name":"Sam"})
复数化
定义复数翻译:
en:
inbox:
emails:
zero: "You have no emails."
one: "You have %{count} email."
other: "You have %{count} emails."
使用:
count := 2
fmt.Println(i18n.N(ctx, "inbox.emails", count, i18n.M{"count": count}))
// 输出: "You have 2 emails."
作用域
减少重复键:
ctx := i18n.WithScope(ctx, "welcome")
i18n.T(ctx, ".title", i18n.M{"name":"Sam"})
Templ集成
与Templ模板引擎结合使用:
en:
welcome:
hello: "Hello, %{name}"
Templ组件:
package main
import "github.com/invopop/ctxi18n/i18n"
templ Hello(name string) {
<span class="hello">
{ i18n.T(ctx, "welcome.hello", i18n.M{"name": name}) }
</span>
}
templ Greeting(person Person) {
<div class="greeting">
@Hello(person.Name)
</div>
}
完整示例
package main
import (
"fmt"
"github.com/invopop/ctxi18n"
"github.com/invopop/ctxi18n/i18n"
"context"
)
func main() {
// 模拟加载翻译(实际应用中应使用embed.FS)
translations := `
en:
welcome:
title: "Welcome, %{name}"
messages:
zero: "You have no messages"
one: "You have 1 message"
other: "You have %{count} messages"
`
// 加载翻译
if err := ctxi18n.LoadWithDefault([]byte(translations), "en"); err != nil {
panic(err)
}
// 创建上下文并设置语言
ctx := context.Background()
ctx = ctxi18n.WithLocale(ctx, "en")
// 简单翻译
fmt.Println(i18n.T(ctx, "welcome.title", i18n.M{"name": "Alice"}))
// 输出: Welcome, Alice
// 复数翻译
fmt.Println(i18n.N(ctx, "welcome.messages", 0, nil))
// 输出: You have no messages
fmt.Println(i18n.N(ctx, "welcome.messages", 1, nil))
// 输出: You have 1 message
fmt.Println(i18n.N(ctx, "welcome.messages", 5, i18n.M{"count": 5}))
// 输出: You have 5 messages
// 使用作用域
ctx = i18n.WithScope(ctx, "welcome")
fmt.Println(i18n.T(ctx, ".title", i18n.M{"name": "Bob"}))
// 输出: Welcome, Bob
}
这个库提供了灵活且简洁的API来处理Go应用中的国际化需求,特别适合需要上下文感知的Web应用和服务。
更多关于golang支持上下文感知国际化并具有简洁API的i18n插件库ctxi18n的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang支持上下文感知国际化并具有简洁API的i18n插件库ctxi18n的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
ctxi18n - Go语言上下文感知国际化库
ctxi18n 是一个轻量级的Go语言国际化(i18n)库,它支持上下文感知的翻译,并提供了简洁易用的API。下面我将详细介绍它的使用方法和示例代码。
主要特性
- 上下文感知翻译(根据请求上下文自动选择语言)
- 简洁的API设计
- 支持多种格式的翻译文件(JSON, YAML等)
- 支持变量插值
- 支持复数形式处理
安装
go get github.com/gin-contrib/i18n
基本使用
1. 初始化
package main
import (
"github.com/gin-contrib/i18n"
"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.json")
bundle.MustLoadMessageFile("locales/zh.json")
bundle.MustLoadMessageFile("locales/ja.json")
// 初始化ctxi18n
i18n.InitI18n(bundle)
}
2. 翻译文件示例
locales/en.json
:
{
"hello": "Hello",
"welcome": "Welcome, {{.Name}}",
"unread_messages": {
"one": "You have {{.Count}} unread message",
"other": "You have {{.Count}} unread messages"
}
}
locales/zh.json
:
{
"hello": "你好",
"welcome": "欢迎, {{.Name}}",
"unread_messages": {
"one": "你有 {{.Count}} 条未读消息",
"other": "你有 {{.Count}} 条未读消息"
}
}
3. 在HTTP请求中使用
func handler(c *gin.Context) {
// 简单翻译
hello := i18n.MustGetMessage(c, "hello")
// 带变量的翻译
welcome := i18n.MustGetMessage(c, &i18n.LocalizeConfig{
MessageID: "welcome",
TemplateData: map[string]interface{}{
"Name": "John",
},
})
// 复数形式处理
unread := i18n.MustGetMessage(c, &i18n.LocalizeConfig{
MessageID: "unread_messages",
PluralCount: 5,
TemplateData: map[string]interface{}{
"Count": 5,
},
})
c.JSON(200, gin.H{
"hello": hello,
"welcome": welcome,
"unread": unread,
})
}
4. 中间件设置语言
func LanguageMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 从请求头获取语言
lang := c.GetHeader("Accept-Language")
// 如果没有指定,使用默认语言
if lang == "" {
lang = "en"
}
// 设置到上下文
c.Set("language", lang)
c.Next()
}
}
5. 自定义语言解析器
func customLanguageResolver(c *gin.Context, defaultLanguage string) string {
// 1. 检查URL参数
if lang := c.Query("lang"); lang != "" {
return lang
}
// 2. 检查cookie
if lang, err := c.Cookie("lang"); err == nil {
return lang
}
// 3. 检查Accept-Language头
if lang := c.GetHeader("Accept-Language"); lang != "" {
return lang
}
// 4. 返回默认语言
return defaultLanguage
}
// 初始化时设置自定义解析器
i18n.InitI18n(bundle, customLanguageResolver)
高级用法
1. 批量翻译
messages := i18n.MustGetMessages(c, []*i18n.LocalizeConfig{
{
MessageID: "hello",
},
{
MessageID: "welcome",
TemplateData: map[string]interface{}{
"Name": "Alice",
},
},
})
2. 回退机制
// 如果zh-CN不存在,会尝试zh,然后尝试默认语言
message := i18n.MustGetMessage(c, &i18n.LocalizeConfig{
MessageID: "some_key",
DefaultMessage: &i18n.Message{
ID: "some_key",
Other: "Default message",
},
})
3. 自定义语言标签匹配器
bundle := i18n.NewBundle(language.English)
bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
// 设置自定义匹配器
bundle.Matcher = language.NewMatcher([]language.Tag{
language.English,
language.SimplifiedChinese,
language.Japanese,
})
最佳实践
- 组织翻译文件:按功能模块拆分翻译文件,避免单个文件过大
- 键命名规范:使用点分隔的命名空间,如
user.login.title
- 错误处理:生产环境中不要使用Must方法,应该处理错误
- 性能考虑:在初始化时加载所有翻译文件,不要在请求时加载
- 测试:为关键翻译编写测试用例
总结
ctxi18n提供了简洁而强大的国际化支持,通过上下文感知的翻译机制,可以轻松实现多语言Web应用。它的API设计直观,与Go的标准库和流行框架(如Gin)集成良好,是Go项目中实现国际化的优秀选择。
对于更复杂的需求,还可以结合其他i18n工具如go-i18n的高级功能,构建完整的国际化解决方案。