要在 Yii2.0.48 中实现真正的多语言切换,必须同时配置 i18n 组件启用 PhpMessageSource 并确保语言设置在应用启动早期生效,二者缺一不可。

要在 Yii2.0.48 中让网站真正支持中文、英文等多语言切换,必须完成两件事:一是让 Yii::t() 调用能查到翻译文件并返回对应译文,二是确保语言切换后所有文本、日期、数字格式同步变化——缺一不可,否则页面仍显示英文或报错。
配置 i18n 组件并启用 PhpMessageSource
打开 config/web.php(Web 应用)或 config/main.php(高级模板),在 components 数组内添加 i18n 配置:
```php
'i18n' => [
'translations' => [
'*' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@app/messages',
'fileMap' => [
'app' => 'app.php',
'common' => 'common.php',
],
],
],
],
```
【basePath 对应的 @app/messages 目录必须手动创建,且 Web 进程有读权限】。若目录不存在或权限不足,Yii::t() 会静默失败,始终返回原文。
同时,在 config 数组顶层设置源语言和默认目标语言:
```php
'language' => 'zh-CN',
'sourceLanguage' => 'en-US',
```
sourceLanguage 必须写死为 'en-US',不能留空或设为 'zh-CN'——否则翻译回退逻辑失效,中文用户看到英文时无法 fallback 到源语言原文。
创建翻译文件目录结构
在项目根目录下新建 messages 文件夹(路径为 @app/messages),再按语言代码建子目录:
```
@/messages/
en-US/
app.php
common.php
zh-CN/
app.php
common.php
```
每个 PHP 文件必须返回纯关联数组,键名严格匹配 Yii::t() 第二个参数,区分大小写:
例如 @app/messages/zh-CN/app.php 写成:
```php
return [
'Home' => '首页',
'Save' => '保存',
'Hello {name}' => '你好 {name}',
];
```
注意:文件名必须是 app.php,不是 app.zh-CN.php 或 app_zh-CN.php;category 名称中的斜杠 / 会被转为目录分隔符,所以 Yii::t('common/user', 'Login') 会去找 @app/messages/zh-CN/common/user.php。
确保语言在应用启动早期生效
第一步:在 web/index.php 入口文件中,new Application($config) 创建之后、run() 执行之前 设置语言:
```php
$application = new yii\web\Application($config);
// 从 session、cookie 或 URL 获取语言码,此处以 session 为例
$lang = Yii::$app->session->get('language', 'zh-CN');
Yii::$app->language = $lang;
$application->run();
```
第二步:在控制器中提供语言切换动作(如 SiteController::actionLanguage):
```php
public function actionLanguage($lang)
{
if (in_array($lang, ['zh-CN', 'en-US'])) {
Yii::$app->session->set('language', $lang);
}
return $this->goBack();
}
```
第三步:生成带语言参数的链接,避免 URL 嵌套错误:
```php
Url::to(['site/index', 'lang' => 'en-US']) // 正确
// 不要写成 Url::to(['lang' => 'en-US']) —— 缺少路由,会跳转到首页但丢失当前路径
```
第四步:清除 runtime/cache 下所有缓存文件,否则改了翻译内容也看不到效果——PhpMessageSource 默认启用缓存,不删缓存等于没改。
验证翻译是否真正生效
方法一:在任意视图中插入调试语句:
```php
= Yii::t('app', 'Home') ?>
language, Yii::$app->i18n->translate('app', 'Home')); ?>
```
方法二:临时在控制器 init() 中强制设语言并打印结果:
```php
public function init()
{
parent::init();
Yii::$app->language = 'en-US';
var_dump(Yii::t('app', 'Home')); // 应输出 'Home'
}
```
如果 var_dump 显示 null 或原字符串,说明 fileMap 路径错、PHP 文件未返回数组、或 basePath 目录不可读。


















