go标准库无i18n包,需组合使用golang.org/x/text/language、message及手动管理toml翻译资源,通过gotext提取编译、context传递printer实现多语言。

Go 标准库 i18n 不存在,别被误导
Go 官方没有叫 i18n 的标准包。常见误区是搜到第三方库(比如 go-i18n)或误以为 golang.org/x/text 提供开箱即用的翻译模块——它只提供底层支持:语言标签解析、本地化格式(如数字/日期)、复数规则等,不包含翻译字符串加载与切换逻辑。
真正能落地的方案,是组合使用:golang.org/x/text/language 做语言识别与匹配,golang.org/x/text/message 做格式化输出,再自己管理翻译资源(通常是 JSON 或 TOML 文件)。
用 message.Printer 输出带本地化的字符串
message.Printer 是实际做“翻译+格式化”的核心类型,但它本身不存翻译内容,只依赖传入的 message.Catalog。你得手动把多语言资源编译进 Catalog。
- 翻译文件推荐用
.toml(比 JSON 更易读,支持注释),每个语言一个文件,如en.toml、zh.toml - 用
gotext命令行工具(go install golang.org/x/text/cmd/gotext@latest)从代码中提取模板字符串,生成active.en.toml等骨架文件 - 运行
gotext generate把所有.toml编译成 Go 代码(locales_gen.go),其中包含注册好的Catalog - 初始化时调用
message.NewPrinter,传入匹配到的语言language.Tag,后续用p.Printf或p.Sprintf替代原生fmt
示例:p := message.NewPrinter(language.Make("zh")),然后 p.Sprintf("Hello %s", name) 会查 zh.toml 中对应 key 的中文翻译并插入变量。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
语言自动匹配要小心 language.MatchStrings 的行为
用户请求头里的 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 不能直接当 language.Tag 用。必须用 language.Parse 解析,再通过 language.Matcher 匹配你实际支持的语言列表。
-
language.Parse("zh-CN")返回language.Tag,但你的资源可能只有zh(没细分 CN/SG/TW) - 用
language.NewMatcher(supportedTags),再调matcher.Match(tag1, tag2, ...)才能得到最接近的可用语言 - 别用
strings.Split自己切 Accept-Language —— 它含权重q=,且有复杂通配规则(如zh-*匹配zh-CN) - 常见坑:硬编码
language.Chinese,它等价于language.Make("zh"),但用户浏览器发的是zh-Hans或zh-TW,匹配失败后 fallback 到默认语言,却不报错
HTTP 请求级语言隔离必须靠 context.Context
一个 HTTP handler 里不能全局设语言(比如改某个包级变量),否则并发请求会互相覆盖。正确做法是把 message.Printer 放进 context.Context,并在中间件里注入。
- 中间件解析
Accept-Language→ 得到匹配后的language.Tag→ 创建message.Printer→ 用context.WithValue存入 ctx - handler 中通过
ctx.Value(key)取出*message.Printer(建议定义私有 type 避免 key 冲突) - 不要在 init 函数里初始化 Printer —— 它绑定具体语言,不是全局单例
- 如果用了 Gin/Echo,注意它们的 context 和
net/http的context.Context不同,需桥接或直接用框架自带的上下文取值方式
资源加载和匹配逻辑本身不重,但上下文传递漏掉一环,就会出现“明明设了 zh 却打出 en”的静默故障。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










