
怎么让 Yii2 的 I18N 从数据库加载翻译?
Yii2 默认只支持 PHP 文件或 MO/PO 文件的静态翻译,要动态读取数据库,必须自定义 MessageSource 类,不能只改配置就生效。
必须继承 yii\i18n\MessageSource,重写 loadMessages() 方法数据库表结构至少包含 language、category、message(原文)、translation(译文)字段别直接在 messages 表里加索引却不加 (language, category, message) 联合索引——查得慢还容易漏匹配缓存必须手动处理:loadMessages() 返回前建议用 Yii::$app->cache->set() 存,否则每次 Yii::t() 都查库
Yii::t() 不触发数据库查询?检查这三处
常见现象是改了数据库里的翻译,页面没变,不是缓存没清,而是根本没走到你的自定义 MessageSource。
config/web.php 中 i18n 组件的 class 没指向你写的类,还是默认的 yii\i18n\PhpMessageSourcecomponents[‘i18n’][‘translations’] 配置里用了 * 通配但漏写了 class,导致 fallback 到默认行为调用 Yii::t(‘app’, ‘Hello’) 时,’app’ 这个 category 没在 translations 配置里显式声明,Yii 直接跳过你的源
数据库翻译和文件翻译混用时,优先级怎么定?
Yii2 不会自动合并数据库和 PHP 文件的翻译结果,它按 translations 配置顺序逐个尝试,第一个返回非 null 的就用那个。
想优先数据库:把数据库 MessageSource 的配置放在 translations 数组前面,例如 ‘app*’ => [‘class’ => ‘common\components\DbMessageSource’]想 fallback 到文件:确保数据库源的 loadMessages() 在查不到时 明确 return [](空数组),而不是 null 或抛异常,否则 Yii 会中断查找链注意 sourceLanguage 和 language 必须一致,否则即使数据库有记录,loadMessages() 也可能被跳过
为什么中文翻译显示成英文?字符集或语言码不匹配
最常踩的坑不是逻辑错,是语言码写成了 zh-CN,但数据库里存的是 zh 或 zh_CN —— Yii2 对语言码大小写和分隔符敏感。
查 Yii::$app->language 实际值,用 var_dump() 确认,别只看配置数据库字段存语言码时统一用小写 + 短横(zh-CN),避免 zh_cn 或 ZH-CN如果用 gettext 工具导出 PO 文件再入库,注意有些工具会把 Language: 字段写成 zh_CN,入库前得转换MySQL 表字符集要是 utf8mb4,字段排序规则用 utf8mb4_unicode_ci,否则带 emoji 或生僻字的翻译可能乱码或查不到实际跑起来后,最容易被忽略的是:数据库源的 loadMessages() 方法里没做 trim() 处理——前后空格会让 message 匹配失败,而这个错误既不报错也不提示。

评论(0)