MessageSource.php 4.05 KB
Newer Older
Qiang Xue committed
1 2 3
<?php
/**
 * @link http://www.yiiframework.com/
Qiang Xue committed
4
 * @copyright Copyright (c) 2008 Yii Software LLC
Qiang Xue committed
5 6 7 8 9 10 11 12 13 14 15
 * @license http://www.yiiframework.com/license/
 */

namespace yii\i18n;

use Yii;
use yii\base\Component;

/**
 * MessageSource is the base class for message translation repository classes.
 *
Qiang Xue committed
16
 * A message source stores message translations in some persistent storage.
Qiang Xue committed
17
 *
Qiang Xue committed
18
 * Child classes should override [[loadMessages()]] to provide translated messages.
Qiang Xue committed
19 20 21 22
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
Qiang Xue committed
23
class MessageSource extends Component
Qiang Xue committed
24
{
Qiang Xue committed
25 26 27 28 29
	/**
	 * @event MissingTranslationEvent an event that is triggered when a message translation is not found.
	 */
	const EVENT_MISSING_TRANSLATION = 'missingTranslation';

Qiang Xue committed
30 31 32 33 34
	/**
	 * @var boolean whether to force message translation when the source and target languages are the same.
	 * Defaults to false, meaning translation is only performed when source and target languages are different.
	 */
	public $forceTranslation = false;
Qiang Xue committed
35 36 37 38
	/**
	 * @var string the language that the original messages are in. If not set, it will use the value of
	 * [[\yii\base\Application::sourceLanguage]].
	 */
Qiang Xue committed
39 40
	public $sourceLanguage;

Alexander Makarov committed
41
	private $_messages = [];
Qiang Xue committed
42

Qiang Xue committed
43 44 45
	/**
	 * Initializes this component.
	 */
Qiang Xue committed
46 47 48 49
	public function init()
	{
		parent::init();
		if ($this->sourceLanguage === null) {
Qiang Xue committed
50
			$this->sourceLanguage = Yii::$app->sourceLanguage;
Qiang Xue committed
51 52 53 54 55
		}
	}

	/**
	 * Loads the message translation for the specified language and category.
Alexander Makarov committed
56 57 58
	 * If translation for specific locale code such as `en-US` isn't found it
	 * tries more generic `en`.
	 *
Qiang Xue committed
59 60
	 * @param string $category the message category
	 * @param string $language the target language
Qiang Xue committed
61 62
	 * @return array the loaded messages. The keys are original messages, and the values
	 * are translated messages.
Qiang Xue committed
63
	 */
Qiang Xue committed
64 65
	protected function loadMessages($category, $language)
	{
Alexander Makarov committed
66
		return [];
Qiang Xue committed
67
	}
Qiang Xue committed
68 69 70 71

	/**
	 * Translates a message to the specified language.
	 *
Qiang Xue committed
72 73 74
	 * Note that unless [[forceTranslation]] is true, if the target language
	 * is the same as the [[sourceLanguage|source language]], the message
	 * will NOT be translated.
Qiang Xue committed
75
	 *
76
	 * If a translation is not found, a [[EVENT_MISSING_TRANSLATION|missingTranslation]] event will be triggered.
Qiang Xue committed
77 78 79
	 *
	 * @param string $category the message category
	 * @param string $message the message to be translated
Qiang Xue committed
80
	 * @param string $language the target language
81
	 * @return string|boolean the translated message or false if translation wasn't found or isn't required
Qiang Xue committed
82 83 84 85 86 87
	 */
	public function translate($category, $message, $language)
	{
		if ($this->forceTranslation || $language !== $this->sourceLanguage) {
			return $this->translateMessage($category, $message, $language);
		} else {
88
			return false;
Qiang Xue committed
89 90 91 92 93
		}
	}

	/**
	 * Translates the specified message.
94 95 96 97 98 99 100
	 * If the message is not found, a [[EVENT_MISSING_TRANSLATION|missingTranslation]] event will be triggered.
	 * If there is an event handler, it may provide a [[MissingTranslationEvent::$translatedMessage|fallback translation]].
	 * If no fallback translation is provided this method will return `false`.
	 * @param string $category the category that the message belongs to.
	 * @param string $message the message to be translated.
	 * @param string $language the target language.
	 * @return string|boolean the translated message or false if translation wasn't found.
Qiang Xue committed
101 102 103 104 105 106 107 108 109
	 */
	protected function translateMessage($category, $message, $language)
	{
		$key = $language . '/' . $category;
		if (!isset($this->_messages[$key])) {
			$this->_messages[$key] = $this->loadMessages($category, $language);
		}
		if (isset($this->_messages[$key][$message]) && $this->_messages[$key][$message] !== '') {
			return $this->_messages[$key][$message];
110
		} elseif ($this->hasEventHandlers(self::EVENT_MISSING_TRANSLATION)) {
Alexander Makarov committed
111
			$event = new MissingTranslationEvent([
Qiang Xue committed
112 113 114
				'category' => $category,
				'message' => $message,
				'language' => $language,
Alexander Makarov committed
115
			]);
Qiang Xue committed
116
			$this->trigger(self::EVENT_MISSING_TRANSLATION, $event);
Qiang Xue committed
117
			if ($event->translatedMessage !== null) {
118 119
				return $this->_messages[$key][$message] = $event->translatedMessage;
			}
Qiang Xue committed
120
		}
Qiang Xue committed
121
		return $this->_messages[$key][$message] = false;
Qiang Xue committed
122 123
	}
}