revel 的 i18n 不支持批量导出,需手动用 robfig/config 解析 messages 文件;切换语言须客户端同步传 accept-language 或 lang 参数;api 返回翻译时须校验 module/lang 白名单并避免路径遍历。

Revel 的 i18n 机制不支持批量导出,别指望 revel.Message 能返回全部 key
Revel 内置的国际化是按需查表式设计:revel.Message("welcome", nil) 只能取单个翻译。它把每个语言文件(如 messages/home.en)解析成一个未导出的 *config.Config 对象,存进内部私有 map,对外不暴露遍历接口。所以你无法调用任何 Revel 自带函数来“获取 home 模块下所有英文键值对”。硬要绕过,只能自己读文件、自己解析——不是 bug,是设计使然。
手动加载 messages 文件:用 robfig/config 解析 INI,别重复造轮子
Revel 本身用的就是 github.com/robfig/config,你直接复用它最稳。关键点在于路径拼接和 section 处理:
- 文件路径必须严格匹配 Revel 约定:
revel.AppPath + "/messages/" + module + "." + lang(例如"/path/to/app/messages/home.en") -
config.LoadFile()加载后,c.StringMap("")可拿到顶层键值(INI 中无 section 的部分);若文件用了 section(如[home]),得先c.Section("home")再调.StringMap("") - 注意编码:Revel 默认期望 UTF-8,文件保存时别用 GBK 或 UTF-8 BOM,否则
config解析会静默失败或乱码
切换语言不能只改 revel.BE.Context.Locale,客户端还要同步传 Accept-Language
Revel 的语言判定优先级是:Accept-Language 请求头 > URL 参数(?lang=zh-CN) > Cookie > 默认 locale。单纯在服务端改 revel.BE.Context.Locale 只影响当前请求,下次请求又回退。真实切换必须让客户端配合:
- 前端发请求时带上
Accept-Language: zh-CN(fetch headers 或 axios default headers) - 或统一加
lang查询参数,确保所有 API 请求都带?lang=zh-CN - 别依赖 session 或 cookie 存语言——Revel 的
LocaleCookie默认关闭,且 cookie 方案在跨域、隐私模式下不可靠
API 场景下返回全量翻译时,避免把 messages 目录整个暴露给 HTTP
如果要做“获取当前模块全部翻译”的 API(比如 GET /api/i18n/home?lang=ja),切记不要用 http.FileServer 直接 serve messages/ 目录——这等于把所有语言文件路径和内容全泄漏出去。正确做法是:
- 在 controller 里调用自定义加载函数(见第二点),仅返回解析后的
map[string]string - 对
module和lang参数做白名单校验,例如只允许module是"home"、"user"等预设值,拒绝../../../etc/passwd类路径遍历 - 返回前用
json.Marshal,别拼 HTML 或直接写字符串,防止注入
最易被忽略的是路径校验和编码一致性——INI 文件名大小写敏感、空格会被截断、带连字符的语言标签(如 zh-Hans)需提前映射到文件名(zh_Hans),这些细节一错,config.LoadFile 就静默返回空 map,而日志里不会报错。











