- create database table as following schema
/Database Schema for oracle database/
drop table if exists "source_message";
drop table if exists "message";
CREATE TABLE "source_message"
(
"id" integer NOT NULL PRIMARY KEY,
"category" varchar(255),
"message" clob
);
CREATE SEQUENCE "source_message_SEQ";
CREATE TABLE "message"
(
"id" integer NOT NULL,
"language" varchar(16) NOT NULL,
"translation" clob,
primary key ("id", "language"),
foreign key ("id") references "source_message" ("id") on delete cascade
);
CREATE INDEX idx_message_language ON "message"("language");
CREATE INDEX idx_source_message_category ON "source_message"("category");
- Extend the yii\i18n\DbMessageSource Class to common\components\CDbMessageSource.php as following,
<?php
namespace common\components;
use Yii;
use yii\db\Expression;
use yii\helpers\ArrayHelper;
use yii\db\Query;
use yii\i18n\DbMessageSource;
class CDbMessageSource extends DbMessageSource
{
/**
* Loads the messages from database.
* You may override this method to customize the message storage in the database.
* @param string $category the message category.
* @param string $language the target language.
* @return array the messages loaded from database.
*/
protected function loadMessagesFromDb($category, $language)
{
$mainQuery = (new Query())->select(['message' => 'to_char("t1"."message")', 'translation' => 'to_char("t2"."translation")'])
->from(['t1' => $this->sourceMessageTable, 't2' => $this->messageTable])
->where([
't1.id' => new Expression('[[t2.id]]'),
'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');
}
/**
* The method builds the [[Query]] object for the fallback language messages search.
* Normally is called from [[loadMessagesFromDb]].
*
* @param string $category the message category
* @param string $language the originally requested language
* @param string $fallbackLanguage the target fallback language
* @return Query
* @see loadMessagesFromDb
* @since 2.0.7
*/
protected function createFallbackQuery($category, $language, $fallbackLanguage)
{
return (new Query())->select(['message' => 'to_char("t1"."message")', 'translation' => 'to_char("t2"."translation")'])
->from(['t1' => $this->sourceMessageTable, 't2' => $this->messageTable])
->where([
't1.id' => new Expression('[[t2.id]]'),
't1.category' => $category,
't2.language' => $fallbackLanguage,
])->andWhere([
'NOT IN', 't2.id', (new Query())->select('[[id]]')->from($this->messageTable)->where(['language' => $language])
]);
}
}
- component can be configured in the application configuration as follows,
'components' => [
// ...
'i18n' => [
'translations' => [
'app*' => [
'class' => 'common\components\CDbMessageSource',
],
],
],
],
- Wrap a text message
The method Yii::t() can be used like the following,
echo \Yii::t('app', 'This is a string to translate!');