go-i18n/v2加载失败主因是文件名、路径或json结构不合规:文件名须为active.zh-cn.json,路径须匹配os.dirfs("./locales")根目录,json外层须为对象且每个key值含description和translation字段,仅加载active.*前缀文件。

资源文件加载失败,90% 是命名、路径或结构没踩中规范,而不是代码写错了。
go-i18n/v2 加载 JSON 文件时为什么静默返回空字符串
bundle.ParseFS 不会报错,但只要文件名、路径或 JSON 结构有一处不合规,就直接跳过——最终 localizer.Localize 返回空字符串或原始 key。
- 文件名必须是
active.zh-CN.json(不是zh.json、zh_CN.json、zh-CN.json或active-zh-CN.json) - 路径必须匹配
os.DirFS("./locales")的根:即文件得在./locales/active.zh-CN.json,不能少locales/这一层 - JSON 外层必须是对象,每个 message ID 的值必须是
{"description": "...", "translation": "..."},缺description字段也会被忽略 - 只加载前缀为
active.的文件,translate.zh-CN.json或inactive.zh-CN.json不会被读取
用 bundle.ParseFS 时路径写错的典型表现
看似调用了加载,但 localizer.Localize 始终返回 key,且无任何错误提示。这是因为 ParseFS 对路径不合法、文件不存在、glob 匹配失败等情况全部静默处理。
- 错误写法:
bundle.ParseFS(os.DirFS("."), "locales/active.*.json")—— 如果当前工作目录不是项目根,.指向错误位置 - 错误写法:
bundle.ParseFS(os.DirFS("./locales"), "active.*.json")—— glob 路径没带子目录,实际应为"./active.*.json",但更稳妥的是用"active.*.json"并确保os.DirFS的根已包含locales/ - 正确做法:统一用
os.DirFS("./locales"),文件放./locales/active.zh-CN.json,然后调bundle.ParseFS(fs, "active.*.json") - 调试技巧:加
bundle.WithDebug(true),它会在找不到翻译时输出 warning 到 stderr,帮你定位是否加载成功
为什么不能用 golang.org/x/text/message 加载 JSON 文件
message.Catalog 只支持手动注册(message.SetString)或从 TOML 解析(message.LoadMessageFile),它根本不认识 JSON 格式,也不会读取文件系统。
- 想用 JSON,必须选
go-i18n/v2;想用 TOML 或自定义格式,才考虑golang.org/x/text/message -
message.LoadMessageFile("zh-CN.toml")成功后,只是把翻译注入默认message.Catalog,但新建的message.NewPrinter(language.Make("zh-CN"))默认不读这个 catalog,需显式绑定:printer := message.NewPrinter(tag).WithCatalog(message.DefaultCatalog) -
message.Printer不支持热重载,改了 TOML 文件必须重启服务;而go-i18n/v2的bundle可配合 fsnotify 实现运行时刷新
最易被忽略的一点:所有语言标签(文件名、language.Make、matcher 白名单)必须严格一致——zh-CN 和 zh-cn 在 BCP 47 下是不同标签,ParseAcceptLanguage 输出的是标准化形式,你加载的文件名也得完全匹配它,差一个大小写都会失效。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











