i18n.SetMessage必须在应用启动早期(如routers/init.go的init函数)一次性调用,按语言代码(如en-US)严格匹配locale_en-US.ini等文件名并逐个注册,不可放在Prepare中重复调用;语言偏好需手动从URL参数、Cookie或Accept-Language头解析,并显式赋值c.Lang才能使this.Tr生效。

i18n.SetMessage 必须在应用启动早期调用,否则后续请求中 i18n.Tr 会返回空字符串或 panic。Beego 的国际化不是运行时按需加载,而是启动时一次性注册所有语言包。
如何正确注册多语言文件
注册动作必须在路由初始化之前完成,通常放在 routers/init.go 或 main.go 的 init() 函数里。常见错误是把 i18n.SetMessage 放到某个 controller 的 Prepare() 里——这会导致每次请求都重复注册,且只对当前 goroutine 生效,其他请求仍无语言数据。
- 语言代码(如
en-US)必须与文件名后缀严格一致:locale_en-US.ini - 路径要相对于执行目录,不是相对于代码文件位置;推荐统一放
conf/下并用绝对路径拼接 - 每个语言调用一次
i18n.SetMessage,不能合并多个语言进同一个调用 - 若文件不存在或格式错误,
SetMessage返回非 nil error,但不会中断程序——务必检查日志
怎么从请求中提取用户语言偏好
Beego 不自动解析 Accept-Language,需要手动实现。最常用方式是按优先级顺序检查:
- URL 查询参数:
?lang=zh-CN(适合调试和分享链接) - Cookie:
beegolocale=zh-CN(需配合c.Ctx.SetCookie写入) - Header:
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8(需用strings.Split解析并匹配已注册语言)
注意:Beego 的 c.Ctx.Input.Language 是只读字段,它仅在你显式赋值后才有效,不会自动填充。
i18n.Tr 在模板和控制器中怎么用
模板里直接调用函数即可,但要注意上下文绑定:
{{i18n.Tr . "hi"}}
其中 . 是当前数据上下文,"hi" 是键名。控制器中则用:
-
this.Tr("hi")—— 前提是 controller 嵌入了i18n.Locale并已设置this.Lang -
i18n.Tr(this.Lang, "hi")—— 更稳妥,不依赖嵌入结构
键名不支持嵌套(如 user.login.title),也不支持带空格的键;INI 文件里写成 user_login_title = 登录标题 更安全。
动态切换时 Cookie 和 Session 怎么配合
单纯改 Cookie 不足以让下个请求自动生效,必须同步更新当前请求上下文中的 Lang 字段。典型流程是:
- 接收
/switchlang?lang=ja-JP请求 - 校验
lang是否在预设列表(如["en-US", "zh-CN", "ja-JP"])中 - 调用
c.Ctx.SetCookie("beegolocale", lang, 3600) - 立即设置
c.Lang = lang,否则本次响应里的Tr仍用旧语言 - 重定向回原页面(避免刷新后又走默认语言逻辑)
容易忽略的是:如果用了 Beego 的 session 模块,Lang 不会自动存进 session,得自己写 c.SetSession("lang", lang) 并在 Prepare() 里读取覆盖 c.Lang。


















