diff --git a/framework/yii/i18n/DbMessageSource.php b/framework/yii/i18n/DbMessageSource.php new file mode 100644 index 0000000..831cabb --- /dev/null +++ b/framework/yii/i18n/DbMessageSource.php @@ -0,0 +1,151 @@ + + * @since 2.0 + */ +class DbMessageSource extends MessageSource +{ + /** + * Prefix which would be used when generating cache key. + */ + const CACHE_KEY_PREFIX = 'DbMessageSource'; + + /** + * @var Connection|string the DB connection object or the application component ID of the DB connection. + * After the DbMessageSource object is created, if you want to change this property, you should only assign + * it with a DB connection object. + */ + public $db = 'db'; + /** + * @var Cache|string the cache object or the application component ID of the cache object. + * The messages data will be cached using this cache object. Note, this property has meaning only + * in case [[cachingDuration]] set to non-zero value. + * After the DbMessageSource object is created, if you want to change this property, you should only assign + * it with a cache object. + */ + public $cache = 'cache'; + /** + * @var string the name of the source message table. Defaults to `{{%source_message}}`. + */ + public $sourceMessageTable = '{{%source_message}}'; + /** + * @var string the name of the translated message table. Defaults to `{{%message}}`. + */ + public $messageTable = '{{%message}}'; + /** + * @var integer the time in seconds that the messages can remain valid in cache. + * Defaults to 0, meaning the caching is disabled. + */ + public $cachingDuration = 0; + + /** + * Initializes the DbMessageSource component. + * This method will initialize the [[db]] property to make sure it refers to a valid DB connection. + * Configured [[cache]] component would also be initialized. + * @throws InvalidConfigException if [[db]] is invalid or [[cache]] is invalid. + */ + public function init() + { + parent::init(); + if (is_string($this->db)) { + $this->db = Yii::$app->getComponent($this->db); + } + if (!$this->db instanceof Connection) { + throw new InvalidConfigException("DbMessageSource::db must be either a DB connection instance or the application component ID of a DB connection."); + } + if ($this->cachingDuration > 0) { + if (is_string($this->cache)) { + $this->cache = Yii::$app->getComponent($this->cache); + } + if (!$this->cache instanceof Cache) { + throw new InvalidConfigException("DbMessageSource::cache must be either a cache object or the application component ID of the cache object."); + } + } + } + + /** + * Loads the message translation for the specified language and category. + * Child classes should override this method to return the message translations of + * the specified language and category. + * @param string $category the message category + * @param string $language the target language + * @return array the loaded messages. The keys are original messages, and the values + * are translated messages. + */ + protected function loadMessages($category, $language) + { + if ($this->cachingDuration === 0) { + return $this->retrieveMessages($category, $language); + } else { + $key = static::CACHE_KEY_PREFIX . ".messages.{$category}.{$language}"; + $messages = $this->cache->get($key); + if ($messages === false) { + $messages = $this->retrieveMessages($category, $language); + $this->cache->set($key, $messages, $this->cachingDuration); + } + return $messages; + } + } + + /** + * 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 retrieveMessages($category, $language) + { + $query = new Query(); + $messages = $query->select(array('t1.message message', 't2.translation translation')) + ->from(array($this->sourceMessageTable . ' t1', $this->messageTable . ' t2')) + ->where('t1.id = t2.id AND t1.category = :category AND t2.language = :language') + ->params(array(':category' => $category, ':language' => $language)) + ->createCommand($this->db) + ->queryAll(); + return ArrayHelper::map($messages, 'message', 'translation'); + } +}