Reputation: 1344
By Default Yii 2 has databases for localization which calls TranslationMessage
and TranslationSourceMessage
.
For some important reasons I decided to write my custom translation class, that should get some localization from cached data (Redis).
I customized my db structure.
By default, Yii 2 provides columns in TranslationMessage
(id
, language
).
I customized this DB, instead of id
I prefered using message_id
.
So my new TranslationMessage
structure is (id
, message_id
, translation
).
message_id
is a foreign key of TranslationSourceMessage (id)
However, sometimes I need to use
Yii::t($message, $category)
But in this case, this doesn't retrieve suitable row from db, just because I changed relation of two tables.
From debugbar I see, Yii::t
retrieves a query:
SELECT `t1`.`message` AS `message`, `t2`.`translation` AS `translation` FROM `TranslationSourceMessage` `t1`, `TranslationMessage` `t2` WHERE (`t1`.`id`=`t2`.`id`)...
Instead of:
`t1`.`id`=`t2`.`id`
it should be:
`t1`.`id`=`t2`.`message_id`
I tried to set my custom hasOne
method on model, but wasn't any result.
Upvotes: 1
Views: 288
Reputation: 18789
Create your own version of the DbMessageSource
class and change your i18n config to use this version.
So in your config change:
'class' => 'yii\i18n\DbMessageSource',
to
'class' => 'your\namespace\path\CustomDbMessageSource',
and add the following class:
<?php
namespace your\namespace\path;
use yii\helpers\ArrayHelper;
use yii\db\Query;
use yii\db\Expression;
class CustomDbMessageSource extends \yii\i18n\DbMessageSource {
protected function loadMessagesFromDb($category, $language) {
$mainQuery = (new Query())
->select([
'message' => 't1.message',
'translation' => 't2.translation',
])
->from([
't1' => $this->sourceMessageTable,
't2' => $this->messageTable,
])
->where([
't1.id' => new Expression('[[t2.message_id]]'), // <-- this is the change to your field.
't1.category' => $category,
't2.language' => $language,
]);
$fallbackLanguage = substr($language, 0, 2);
$fallbackSourceLanguage = substr($this->sourceLanguage, 0, 2);
if ($fallbackLanguage !== $language) {
$mainQuery->union($this->createFallbackQuery($category, $language, $fallbackLanguage), true);
} elseif ($language === $fallbackSourceLanguage) {
$mainQuery->union($this->createFallbackQuery($category, $language, $fallbackSourceLanguage), true);
}
$messages = $mainQuery->createCommand($this->db)->queryAll();
return ArrayHelper::map($messages, 'message', 'translation');
}
protected function createFallbackQuery($category, $language, $fallbackLanguage) {
return (new Query())
->select([
'message' => 't1.message',
'translation' => 't2.translation',
])
->from([
't1' => $this->sourceMessageTable,
't2' => $this->messageTable,
])
->where([
't1.id' => new Expression('[[t2.message_id]]'), // <-- also changed it here
't1.category' => $category,
't2.language' => $fallbackLanguage,
])->andWhere([
'NOT IN',
't2.message_id', // <-- also changed it here
(new Query())->select('[[id]]')->from($this->messageTable)->where(['language' => $language]),
]);
}
}
Upvotes: 2