yii多语言切换需在application::init()前设置yii::$app->language,否则formatter等已按默认语言初始化;url生成需手动传lang参数并剥离原语言段,翻译文件须严格匹配filemap路径和占位符格式。

Yii 多语言切换不是配完 i18n 组件就能自动生效的,关键在于语言设置的时机和作用域——必须在 Request 解析完成、Controller 初始化之前就确定 Yii::$app->language,否则视图、验证器、日期格式器等已按默认语言初始化完毕,后续再改毫无意义。
语言必须在 Application::init() 之前设置
常见错误是把 Yii::$app->language = $lang 写在 beforeAction() 或控制器 init() 里。这时 Formatter、Validator、View 都已按原始 language 构建完成,改了也白改。
- 正确做法是在入口文件
web/index.php中,$application = new yii\web\Application($config)创建后、$application->run()之前赋值 - 或者在
bootstrap阶段(如自定义 Bootstrap 类)中,从Yii::$app->request->getPathInfo()提取首段语言码(如/zh-CN/site/index中的zh-CN),并立即设置 - 别依赖
$_GET['lang']:开启美化 URL 后,它通常为空;也别在UrlRule子类里设语言,规则匹配发生在语言初始化之后
Url::to() 不会自动带语言前缀,必须显式传参
Url::to(['site/about']) 永远不会生成 /zh-CN/site/about,它只按路由规则拼接,完全不感知当前语言上下文。
- 所有内部跳转都得手动加
'lang' => Yii::$app->language,例如:Url::to(['site/about', 'lang' => Yii::$app->language]) - 如果项目大量使用
Url::to(),建议封装一个LangUrl::to()工具方法,默认合并当前语言 - 切换语言链接时,必须先剥离当前路径中的语言段(比如从
/zh-CN/product/view中去掉zh-CN),再拼上新语言前缀,否则会出现/en-US/zh-CN/product/view这种嵌套错误
翻译文件结构与 Yii::t() 的实际用法
翻译不是靠猜路径,而是严格依赖 fileMap 和目录结构。比如配置了 'app' => 'app.php',且 basePath 是 @app/messages,那么中文翻译文件必须放在 @app/messages/zh-CN/app.php,内容为纯数组:
return [
'Welcome' => '欢迎',
'Hello, {name}' => '你好,{name}',
];
-
Yii::t('app', 'Welcome')才会去查app.php;写成Yii::t('common', 'Welcome')却没配common类别,就永远找不到翻译 - 占位符必须用花括号,如
{name},不能写成$name或:name -
sourceLanguage是源语言(开发时写的原文语言),只有当Yii::$app->language !== sourceLanguage时才会触发翻译查找
最易被忽略的是语言初始化时机和 URL 生成逻辑——它们不像配置那样“写完就跑”,而需要精确控制执行顺序和上下文传递。一旦漏掉路径剥离或延迟设语言,整个多语言链路就会在用户点击第一下时无声断裂。











