Revel模板中渲染语言切换下拉框需确保value与app.conf中lang键一致、用${revel.T.CurrentLang}匹配选中项、跳转URL带?lang=xx且保留原查询参数;切换后不实时更新翻译是因revel.T为请求级对象,需整页刷新或AJAX实现。

Revel模板里怎么渲染语言切换下拉框
直接在模板中用 revel.T 获取当前语言,再用 revel.Config.StringDefault 或硬编码列出支持的语言列表,就能生成 。关键不是“能不能”,而是“怎么让选项值和当前选中态都对得上路由跳转逻辑”。
常见错误是只渲染了下拉框,但没绑定跳转行为,或者把 lang 参数拼错成 language 导致 404;还有人用 JS 动态改 location.href 却忘了保留原有查询参数,一换语言就把搜索条件丢了。
- 下拉框
的value必须和conf/app.conf中lang.zh.Name=中文的 key(即zh)一致 - 当前选中项要用
${revel.T.CurrentLang}匹配,不是${revel.Lang}(后者不存在) - 跳转地址必须是带
?lang=xx的完整 URL,推荐用${revel.BaseURL}/?lang=${lang}而非硬写/en这类路径,避免和路由前缀冲突
怎么让下拉框切换后保留原页面参数
纯靠 location.href = '/?lang=ja' 会清空所有 query string。Revel 没内置 URL 参数合并工具,得手动拼接。
最稳的方式是在控制器里把当前请求的 query 参数传进模板,比如在 App.Index() 中加:c.RenderArgs["QueryParams"] = c.Request.URL.RawQuery,然后模板里用正则剔除旧的 lang=xxx 再拼新值。
- 模板里别用 JS 做字符串替换,容易漏掉
lang=zh-CN或&lang=en&这类边界情况 - 更可靠的做法:后端提供一个
revel.URLFor("App.Index", "lang", lang)的封装函数,但 Revel 默认不支持动态 route 参数重写,所以实际得自己写个辅助函数返回干净 URL - 简单项目可接受的折中:用
window.location.pathname + '?lang=' + selectedLang,前提是你的路由不带 query,且所有入口都是 GET
为什么 revel.T.Translate 不随下拉框实时变
因为 revel.T 是请求级对象,模板渲染完就固定了。下拉框切换是前端行为,不触发服务端重渲染,所以 ${revel.T("hello")} 不会自动更新——这不是 bug,是设计使然。
要实现“点一下立刻变语言”,只有两个办法:整页刷新(推荐),或用 AJAX 拉取翻译 JSON 后用 JS 替换文本(复杂且易出错)。
- 整页刷新时,确保
lang参数被 Revel 的i18n.Interceptor正确捕获:检查app.Init()是否调用了revel.Intercept(i18n.Interceptor, revel.BEFORE) - 如果用了自定义中间件或修改过
routes,可能拦截顺序错乱,导致revel.T.CurrentLang还是旧值 - 浏览器调试时注意 Network 面板里请求是否真带上了
?lang=fr,有些前端代码会把参数塞进 header 或 body,而 Revel 只认 query 和 cookie
多语言配置里 lang.en.Name 和 lang.en.DisplayName 有什么区别
Revel 的 i18n 模块本身不区分这两个字段,DisplayName 是你自定义的约定。官方示例用 Name,但实际项目中常需要显示名(如 “English”)和内部码(如 en-US)分离。
比如你支持 en 和 en-US 两种英语变体,但下拉框里只想显示 “English (US)”,这时就不能直接用 key 当显示文本。
- 在
conf/messages.conf里定义:lang.en-US.DisplayName=English (US),模板里用${revel.T("lang." + lang + ".DisplayName")} - 别在
app.conf里写lang.en-US.DisplayName,那是配置文件,不是翻译源,Revel 的revel.T只读messages.conf - 如果翻译缺失,
revel.T默认返回 key 字符串,所以下拉框可能显示lang.zh-CN.DisplayName而不是 “中文(简体)”,记得补全
Revel 的多语言下拉框难点不在渲染,而在参数传递的连贯性和拦截器生效时机。最容易卡住的是:前端发了 ?lang=de,但后端没收到,结果页面还是英文——这时候先看 revel.AppLog.Info 是否打印了 “Setting language to de”,没有的话,基本就是拦截器没挂上或者路由匹配失败。











