根本原因是PhpMessageSource默认启用缓存且缓存键不含语言标识,导致语言切换后翻译仍读旧缓存;需清runtime/cache或禁用缓存,并确保Yii::$app->language在Application::init()前正确设置。

语言切换后翻译文本不刷新,根本原因不是“没切成功”,而是 Yii 的翻译组件(如 PhpMessageSource)默认启用缓存,且缓存键与语言无关——它把翻译结果按 category 和 message 哈希后直接存起来,不感知 Yii::$app->language 的变化。
清 runtime 缓存是最快见效的操作
PhpMessageSource 默认使用文件缓存,路径在 @runtime/cache/ 下,缓存文件名不含语言标识。改了 messages/zh-CN/app.php 后不生效,90% 是因为旧缓存还在。
- 执行命令清空:
rmdir -rf runtime/cache(Linux/macOS)或手动删除runtime/cache文件夹 - Windows 下可用
del /s /q runtime\cache - 开发阶段可临时禁用缓存:在
i18n组件配置中加'enableCache' => false
确保 language 设置时机正确
如果缓存清了仍不更新,大概率是 Yii::$app->language 没在关键节点设对——翻译组件初始化时已按旧语言加载并缓存,后面再改也无效。
- 必须在
Application::init()之前设置,推荐位置:入口文件web/index.php中$application = new Application($config)之后、$application->run()之前 - 不要在
Controller::beforeAction()或actionLanguage()里设,此时视图、格式器、验证器都已初始化完毕 - 调试时可在任意地方加:
var_dump(Yii::$app->language, Yii::t('app', 'Home'));看是否真变了
检查 DbMessageSource 的 language 字段格式
若用数据库存翻译(DbMessageSource),缓存不刷新还可能是查不到对应语言的数据。
- 数据库
language字段值必须是标准格式,如zh-CN、en-US,不能是zh、cn或zh_cn - 确认查询语句实际用了当前
Yii::$app->language,可开启 SQL 日志看是否命中正确记录 - DbMessageSource 同样受缓存影响,清缓存后需重新触发查询才能加载新数据
避免 Url::to() 导致的“假切换”
用户点语言切换链接后页面文字没变?很可能是跳转回了默认语言页,而非目标语言页。
-
Url::to(['site/about'])不带语言参数,会忽略当前Yii::$app->language,生成无前缀 URL - 所有内部链接必须显式传参:
Url::to(['site/about', 'lang' => Yii::$app->language]) - 切换链接要剥离原路径语言段,例如从
/zh-CN/site/index切英文,目标应是/en-US/site/index,不能拼成/en-US/zh-CN/site/index


















