beego中i18n需显式注册locale文件并确保请求上下文正确绑定,否则t()返回空或原始key;必须用os.stat校验conf/locale_en-us.ini等文件存在且路径准确,调用i18n.setmessage前检查错误,prepare()中正确设置b.lang,并在url参数lang解析后立即赋值并写入cookie。

i18n 在 Beego 中不是开箱即用的插件,必须显式加载语言文件、绑定请求上下文、并在控制器中正确调用翻译函数,否则 T() 会返回空字符串或原始 key。
如何正确注册 locale 文件并避免 i18n.SetMessage 失败
Beego v2 的 i18n 模块要求语言文件路径必须存在且可读,且文件名需与 SetMessage(lang, path) 中传入的 lang 参数严格匹配。常见错误是路径拼错或文件未生成到运行时工作目录。
- 确保
conf/locale_en-US.ini和conf/locale_zh-CN.ini真实存在于编译后二进制所在目录的conf/子目录下(不是源码目录) - 调用
i18n.SetMessage("en-US", "conf/locale_en-US.ini")前,先用os.Stat检查文件是否存在,避免静默失败 - 若使用 bee 工具热重载,注意
conf/目录不会自动复制到./tmp下,需在bee.json中配置"watch_ext": ["ini"]并手动确保文件同步 - 不推荐用相对路径如
../conf/...,应统一用运行时相对路径(如conf/locale_*.ini),因为 Beego 默认工作目录是执行二进制的目录
为什么 T("hi") 总是返回 "hi" 而不是翻译值
根本原因是当前请求未成功设置语言上下文,T() 函数内部依赖 Locale.Lang 字段,而该字段为空时默认 fallback 到 key 本身。
- 检查
Prepare()方法是否真被调用:在MainController或基类中加beego.Info("lang set to ", b.Lang)确认日志输出 - 确认
b.Lang是否为空:常见原因是未从 cookie、URL 参数或Accept-Language头提取到有效语言标签,比如传了lang=zh但只注册了zh-CN -
i18n.Locale是匿名嵌入字段,必须保证结构体字段名就是Lang(不能重命名),否则T()无法反射访问 - 不要在
Init()或main()中直接调用T()—— 此时无请求上下文,Locale未初始化
如何支持 URL 参数切换语言(如 ?lang=ja-JP)并持久化到 Cookie
Beego 不自动处理 lang 参数,需手动解析并写入 Cookie,否则每次请求都可能回退到浏览器默认语言。
- 在
Prepare()中优先读取this.GetString("lang"),再 fallback 到this.Ctx.Request.Header.Get("Accept-Language") - 验证语言码是否在白名单内:
if !slices.Contains(supportedLangs, lang) { lang = "en-US" },防止任意字符串注入 - 用
this.Ctx.SetCookie("lang", lang, 3600*24*7, "/", "", false, true)写入 HttpOnly + Secure Cookie(生产环境必须) - 注意:Cookie 设置后,本次请求仍用旧
Lang,要立即赋值b.Lang = lang才能让后续T()生效
模板中使用 {{.T "hi"}} 为何不生效或 panic
模板函数 .T 是 Beego 自动注入的,但仅当控制器嵌入了 i18n.Locale 且 Lang 非空时才可用;否则会 panic 或静默失败。
- 确保模板渲染前控制器已完成
Prepare(),即Lang已设好 —— 若在Get()中才设b.Lang,则模板已开始渲染,.T拿不到值 - 不要在
Layout模板里直接调用.T,除非你确认所有子控制器都继承了i18n.Locale - 若需在非控制器上下文(如中间件、工具函数)中翻译,应显式传入
lang并调用i18n.Tr("en-US", "hi"),而非依赖T() - 模板中 key 区分大小写:
{{.T "Hi"}}和{{.T "hi"}}是两个不同 key,ini 文件里必须完全一致
最易被忽略的一点:Beego v2 的 i18n 模块不自动 reload 文件,修改 locale_*.ini 后必须重启服务;开发阶段建议加个简易文件监听器,在检测到变更时重新调用 i18n.SetMessage,否则会误以为翻译没生效。











