beego v2 的 i18n 必须手动加载 locale_*.ini 文件、显式调用 i18n.setmessage 注册每种语言(路径和语言 code 需严格匹配),并在 basecontroller.prepare 中设置 c.lang 与 c.data["lang"],否则 tran 模板函数返回空字符串。

Beego v2 的 i18n 支持默认不启用,必须手动加载语言文件、设置 locale、注入到上下文,否则 Tran 模板函数和 i18n.Tr 调用一律返回空字符串或 panic。
如何正确加载 locale_*.ini 文件
Beego v2 不再自动扫描 conf/ 目录下的本地化文件,必须显式调用 i18n.SetMessage 注册每种语言。常见错误是路径写错、语言 code 不匹配、或漏掉循环注册。
-
i18n.SetMessage第一个参数是语言标识(如"zh-CN"),必须与后续SetLocale传入的值完全一致(大小写敏感) - 第二个参数是文件路径,推荐用
beego.AppConfig.String("app.path") + "/conf/locale_zh-CN.ini"拼接,避免硬编码相对路径 - 若使用
bee run,确保conf/app.conf中已配置lang::types = zh-CN|en-US,否则strings.Split会得到空 slice - 文件内容必须是纯键值对,不支持注释、section、空行;例如
hi = 您好合法,[default]\nhi = 您好会静默失败
为什么 Tran("hi") 在模板里始终输出原文
模板函数 Tran 依赖当前请求上下文中的 i18n.Locale 实例,而 Beego v2 默认不自动注入该实例。即使语言文件加载成功,没挂载到 c.Data 或 c.Ctx.Input.Data,模板就查不到翻译上下文。
- 必须在
BaseController.Prepare中调用c.Lang = "zh-CN"(或从 cookie/header 解析) - 同时需执行
c.Data["Lang"] = c.Lang,否则Tran函数拿不到当前语言标识 - 如果用了自定义模板函数(如
beegoTplFuncMap["Tran"] = i18n.I18nT),要确认i18n.I18nT内部是否读取了c.Ctx.Input.Data["lang"]—— Beego v2 官方i18n包默认读的是c.Ctx.Input.Data["lang"],不是c.Lang - 检查
app.conf是否启用了国际化:未设置EnableDocs = true不影响,但漏配lang::types会导致整个 i18n 初始化跳过
如何从 URL 参数或 Cookie 动态切换语言
Beego 没有内置语言自动协商逻辑,必须自己解析 Accept-Language、query 参数(如 ?lang=zh-CN)或 cookie(如 lang=zh-CN),然后显式设置 c.Lang 和 c.Ctx.Input.Data["lang"]。
- 在
BaseController.Prepare开头加判断:lang := c.GetString("lang"),若为空则 fallback 到c.Ctx.GetCookie("lang") - 验证
lang是否在预设列表中(如map[string]bool{"zh-CN": true, "en-US": true}),防止任意文件读取或 key 注入 - 设置后立即调用
c.Ctx.SetCookie("lang", lang, 3600*24*7)持久化,避免每次请求都传参 - 注意:Beego v2 的
c.Ctx.Request.URL.Query()是只读的,不能直接改写 URL,切换语言需重定向(c.Redirect("/?lang=en-US", 302))
最容易被忽略的是:i18n 初始化必须在 beego.Run() 之前完成,且所有 i18n.SetMessage 调用必须早于任何控制器实例化——否则首次请求可能因 locale 未就绪而返回空翻译,且无日志提示。











