Revel模板中必须在Controller中显式绑定c.RenderArgs["T"] = c.Message,否则{{T "key"}}报未定义函数;消息文件须严格置于/messages目录、用ISO 639-1短码命名(如en)、UTF-8无BOM编码,多文件同语言key冲突会静默覆盖。

Revel模板里怎么用{{T "key"}}输出翻译
必须先在Controller中把c.Message绑定到RenderArgs["T"],否则{{T "key"}}会报未定义函数错误。这个步骤不能省,也不是框架自动做的。
常见错误是直接在模板里写{{T "submit.button"}}但没在Controller里赋值:
- 在
app/controllers/app.go的Action方法开头加一行:c.RenderArgs["T"] = c.Message - 确保这行代码在
c.Render()之前执行 - 如果用了自定义Filter提前设置了
c.Request.Locale,也要确认它在I18nFilter之前完成(否则会被覆盖)
消息文件名和路径为什么总是不生效
Revel只认/messages这个硬编码路径,且文件名后缀必须是ISO 639-1标准短码(如en、zh),写成en-US或zh_CN会被完全忽略。
典型失效场景:
-
/messages/home.en-US→ 不加载,静默跳过 -
/i18n/labels.zh→ 路径错,根本不会扫描 -
/messages/login.zh-CN→ 后缀非法,Revel只取zh部分匹配,但文件名不匹配规则 - 文件编码不是UTF-8无BOM → 中文显示为乱码,且某些版本会跳过解析
多模块消息合并时key冲突怎么办
Revel启动时会把同一语言的所有.en、.zh文件合并进一个map,key重复会导致后加载的覆盖先加载的——没有警告,也不报错,只是翻译随机出错。
安全做法:
- 按功能拆分文件,但统一加前缀,比如
user.login=...、user.logout=...、admin.edit=... - 避免在
labels.en和errors.en里都定义required这种泛用key - 检查是否误把
home.en和home.zh放在不同子目录下——Revel只扫/messages一级,子目录里的文件不识别
热重载改了消息文件却看不到效果
Revel确实支持消息文件热重载,但有两个隐藏前提:文件必须保存成功(编辑器没卡住)、且HTTP请求触发了I18nFilter。如果页面是静态HTML或绕过了Filter链(比如直接c.RenderText),就不会重新读取。
调试建议:
- 改完
messages/home.en后,curl一下带Accept-Language头的接口,看响应是否变化:curl -H "Accept-Language: en" http://localhost:9000/ - 在Controller里临时加一行
revel.INFO.Printf("locale: %s", c.Request.Locale),确认当前语言确实是预期值 - 如果用了Nginx反向代理,检查是否透传了
Accept-Language头
关键点其实就一个:Revel的i18n不是“写完文件就自动可用”,而是依赖Filter链顺序、路径硬编码、文件命名规范三者严丝合缝。任何一环松动,都会静默失败——不报错,只返回原始key。











