如何在不修改Yii2模块文件的前提下外部翻译模块?
Yii2 不修改vendor目录新增模块语言包的通用方案
问题场景
通过Composer安装的Yii2模块(如示例中的vbt-cron)自带部分语言包,出于不改动vendor目录的最佳实践,需在应用侧新增自定义语言包。但直接在应用配置中定义同类别翻译后,Yii仍仅在模块自身的messages目录查找文件,报错如下:
The message file for category 'vbt-cron' does not exist: vendor/sharkom/yii2-cron/messages/it-IT/vbt-cron.php Fallback file does not exist as well: vendor/sharkom/yii2-cron/messages/it/vbt-cron.php
通用解决方案:用CompositeMessageSource组合多消息源
Yii2内置的CompositeMessageSource类可以把模块自带的消息源和应用自定义的消息源组合起来,优先读取应用侧的翻译,找不到再回退到模块自带的,完全不需要修改模块代码。
配置步骤
- 在应用配置文件(
config/web.php或config/main.php)中,重新定义目标翻译类别,替换成CompositeMessageSource配置:
'components' => [ 'i18n' => [ 'translations' => [ 'vbt-cron' => [ 'class' => '\yii\i18n\CompositeMessageSource', 'translations' => [ // 优先级1:查找应用侧的翻译文件 'vbt-cron*' => [ 'class' => '\yii\i18n\PhpMessageSource', 'basePath' => '@app/messages', 'sourceLanguage' => 'en-US', // 必须和模块配置的sourceLanguage保持一致 ], // 优先级2:回退到模块自带的翻译文件 'vbt-cron*' => [ 'class' => '\yii\i18n\PhpMessageSource', 'basePath' => '@sharkom/cron/messages', 'sourceLanguage' => 'en-US', ], ], ], // 其他翻译类别配置... ], ], // 其他组件配置... ],
- 把提取好的翻译文件放到应用侧对应路径:
比如意大利语翻译文件放在@app/messages/it-IT/vbt-cron.php(或it/vbt-cron.php,Yii会自动按语言 fallback规则查找)。
原理说明
CompositeMessageSource会按配置顺序遍历内部的消息源,只要在某一个消息源找到对应翻译,就会直接返回,后续的消息源不会再被查询,完美实现“应用侧优先,模块侧兜底”的需求。
备选方案:覆盖配置+手动处理缺失翻译
如果不想用组合消息源,也可以直接覆盖模块的翻译配置,同时通过事件处理缺失翻译的回退:
'components' => [ 'i18n' => [ 'translations' => [ 'vbt-cron' => [ 'class' => '\yii\i18n\PhpMessageSource', 'basePath' => '@app/messages', 'sourceLanguage' => 'en-US', 'forceTranslation' => true, // 强制使用当前应用的配置 'fileMap' => [ 'vbt-cron' => 'vbt-cron.php', ], // 当应用侧找不到翻译时,自动去模块目录查找 'on missingTranslation' => function ($event) { $moduleSource = new \yii\i18n\PhpMessageSource([ 'basePath' => '@sharkom/cron/messages', 'sourceLanguage' => 'en-US', ]); $event->message = $moduleSource->translate($event->category, $event->message, $event->language); }, ], ], ], ],
这个方案需要手动编写事件回调,相比组合消息源稍繁琐,但同样能实现需求。
内容的提问来源于stack exchange,提问作者Zhigalin
相关产品推荐
相关产品推荐

