Yii2多语言需协同配置language与sourceLanguage、翻译文件映射、URL路由规则及formatter本地化,任一环节缺失将导致界面不切换、格式错误或404等问题。

Yii2多语言支持不是“配个 language 就完事”,它由语言切换、翻译加载、URL 路由、格式化四块咬合组成;漏掉任一环,都会出现「界面没变」「数字还是英文格式」「切语言后路由 404」这类看似配置成功实则失效的问题。
怎么设 language 和 sourceLanguage 才不翻车
这两个配置决定整个翻译链的起点和终点:sourceLanguage 是你代码里写的原文语言(建议死守 en-US),language 是当前要展示给用户的语言(比如 zh-CN)。如果把 sourceLanguage 错设成 zh-CN,后面所有翻译文件都得反向从中文翻英文——译者难找、工具不认、./yii message 提取直接失效。
-
language必须在应用启动早期设置,不能等控制器里才改;否则Yii::t()已按旧语言查过缓存,再改也白搭 - 动态切换时别只改
Yii::$app->language,还得同步存到 session 或 cookie,否则刷新就回退 - 不要在配置文件里硬写
'language' => $_GET['lang']—— 这会触发 PHP notice 且无法 fallback
Yii::t() 的 category 怎么映射到真实文件
调用 Yii::t('app', 'Hello') 时,app 不是随便起的,它对应 i18n 配置里的 fileMap 键。如果没配或配错,Yii::t() 就返回原文,控制台也没报错,非常隐蔽。
- 常见错误:只配了
'app' => 'app.php',但实际翻译文件放在@app/messages/zh-CN/app/en.php—— 路径必须严格匹配basePath+语言子目录+fileMap指定文件名 -
fileMap支持嵌套键,比如'app/error' => 'error.php',这时调用就得写Yii::t('app/error', 'Invalid input') - category 名称里不能有空格或特殊字符,否则
PhpMessageSource加载失败且静默忽略
多语言 URL 前缀为什么总 404
加了 <lang:>/<controller></controller></lang:> 规则却 404,大概率是规则顺序或 enableStrictParsing 搞错了。Yii 的 UrlManager 是从上到下匹配,一旦某条规则命中,后续就不再看。
- 必须把带
lang的规则放在无前缀规则之前,否则/site先被'<controller>' => '<controller>/index'</controller></controller>吃掉,/zh/site根本没机会匹配 - 开启
enableStrictParsing后,所有 URL 都必须有显式规则,漏一条就 404;关掉它虽能 fallback,但会破坏 SEO 和语言感知 -
lang参数不会自动注入Yii::$app->language,得自己在Bootstrap或Controller::init()里手动赋值
日期数字本地化为什么没反应
Yii::$app->formatter->asDate() 不生效,90% 是因为缺 intl 扩展或 language 没生效。ICU 数据库驱动所有本地化格式,没它,formatter 只能返回 ISO 标准字符串。
- 运行
php -m | grep intl确认扩展已启用;Ubuntu 常见缺失包是php-intl,CentOS 是php-intl或php74-php-intl -
asDecimal(1234.56)在zh-CN下应输出1,234.56,若仍为1234.56,说明Yii::$app->language实际未生效,检查是否被中间件或行为覆盖 - 数据库字段存时间用 UTC,显示时靠
formatter自动转本地时区;别在 SQL 里用NOW()直接插本地时间,否则换语言时区就乱套
真正卡住人的从来不是“怎么写”,而是“哪个环节悄悄绕过了”。比如 message 命令提取不到字符串,往往是因为用了变量拼接:Yii::t('app', $msg) —— 工具根本没法静态分析;又比如 session 存语言后忘了在 AppController::init() 里读,结果只有首页切对了语言。这些点不写进日志、不抛异常,只能靠经验踩一遍。










