CPhpMessageSource.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. /**
  3. * CPhpMessageSource class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CPhpMessageSource represents a message source that stores translated messages in PHP scripts.
  12. *
  13. * CPhpMessageSource uses PHP files and arrays to keep message translations.
  14. * <ul>
  15. * <li>All translations are saved under the {@link basePath} directory.</li>
  16. * <li>Translations in one language are kept as PHP files under an individual subdirectory
  17. * whose name is the same as the language ID. Each PHP file contains messages
  18. * belonging to the same category, and the file name is the same as the category name.</li>
  19. * <li>Within a PHP file, an array of (source, translation) pairs is returned.
  20. * For example:
  21. * <pre>
  22. * return array(
  23. * 'original message 1' => 'translated message 1',
  24. * 'original message 2' => 'translated message 2',
  25. * );
  26. * </pre>
  27. * </li>
  28. * </ul>
  29. * When {@link cachingDuration} is set as a positive number, message translations will be cached.
  30. *
  31. * Messages for an extension class (e.g. a widget, a module) can be specially managed and used.
  32. * In particular, if a message belongs to an extension whose class name is Xyz, then the message category
  33. * can be specified in the format of 'Xyz.categoryName'. And the corresponding message file
  34. * is assumed to be 'BasePath/messages/LanguageID/categoryName.php', where 'BasePath' refers to
  35. * the directory that contains the extension class file. When using Yii::t() to translate an extension message,
  36. * the category name should be set as 'Xyz.categoryName'.
  37. *
  38. * @author Qiang Xue <qiang.xue@gmail.com>
  39. * @package system.i18n
  40. * @since 1.0
  41. */
  42. class CPhpMessageSource extends CMessageSource
  43. {
  44. const CACHE_KEY_PREFIX='Yii.CPhpMessageSource.';
  45. /**
  46. * @var integer the time in seconds that the messages can remain valid in cache.
  47. * Defaults to 0, meaning the caching is disabled.
  48. */
  49. public $cachingDuration=0;
  50. /**
  51. * @var string the ID of the cache application component that is used to cache the messages.
  52. * Defaults to 'cache' which refers to the primary cache application component.
  53. * Set this property to false if you want to disable caching the messages.
  54. */
  55. public $cacheID='cache';
  56. /**
  57. * @var string the base path for all translated messages. Defaults to null, meaning
  58. * the "messages" subdirectory of the application directory (e.g. "protected/messages").
  59. */
  60. public $basePath;
  61. /**
  62. * @var array the message paths for extensions that do not have a base class to use as category prefix.
  63. * The format of the array should be:
  64. * <pre>
  65. * array(
  66. * 'ExtensionName' => 'ext.ExtensionName.messages',
  67. * )
  68. * </pre>
  69. * Where the key is the name of the extension and the value is the alias to the path
  70. * of the "messages" subdirectory of the extension.
  71. * When using Yii::t() to translate an extension message, the category name should be
  72. * set as 'ExtensionName.categoryName'.
  73. * Defaults to an empty array, meaning no extensions registered.
  74. * @since 1.1.13
  75. */
  76. public $extensionPaths=array();
  77. private $_files=array();
  78. /**
  79. * Initializes the application component.
  80. * This method overrides the parent implementation by preprocessing
  81. * the user request data.
  82. */
  83. public function init()
  84. {
  85. parent::init();
  86. if($this->basePath===null)
  87. $this->basePath=Yii::getPathOfAlias('application.messages');
  88. }
  89. /**
  90. * Determines the message file name based on the given category and language.
  91. * If the category name contains a dot, it will be split into the module class name and the category name.
  92. * In this case, the message file will be assumed to be located within the 'messages' subdirectory of
  93. * the directory containing the module class file.
  94. * Otherwise, the message file is assumed to be under the {@link basePath}.
  95. * @param string $category category name
  96. * @param string $language language ID
  97. * @return string the message file path
  98. */
  99. protected function getMessageFile($category,$language)
  100. {
  101. if(!isset($this->_files[$category][$language]))
  102. {
  103. if(($pos=strpos($category,'.'))!==false)
  104. {
  105. $extensionClass=substr($category,0,$pos);
  106. $extensionCategory=substr($category,$pos+1);
  107. // First check if there's an extension registered for this class.
  108. if(isset($this->extensionPaths[$extensionClass]))
  109. $this->_files[$category][$language]=Yii::getPathOfAlias($this->extensionPaths[$extensionClass]).DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.$extensionCategory.'.php';
  110. else
  111. {
  112. // No extension registered, need to find it.
  113. $class=new ReflectionClass($extensionClass);
  114. $this->_files[$category][$language]=dirname($class->getFileName()).DIRECTORY_SEPARATOR.'messages'.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.$extensionCategory.'.php';
  115. }
  116. }
  117. else
  118. $this->_files[$category][$language]=$this->basePath.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.$category.'.php';
  119. }
  120. return $this->_files[$category][$language];
  121. }
  122. /**
  123. * Loads the message translation for the specified language and category.
  124. * @param string $category the message category
  125. * @param string $language the target language
  126. * @return array the loaded messages
  127. */
  128. protected function loadMessages($category,$language)
  129. {
  130. $messageFile=$this->getMessageFile($category,$language);
  131. if($this->cachingDuration>0 && $this->cacheID!==false && ($cache=Yii::app()->getComponent($this->cacheID))!==null)
  132. {
  133. $key=self::CACHE_KEY_PREFIX . $messageFile;
  134. if(($data=$cache->get($key))!==false)
  135. return unserialize($data);
  136. }
  137. if(is_file($messageFile))
  138. {
  139. $messages=include($messageFile);
  140. if(!is_array($messages))
  141. $messages=array();
  142. if(isset($cache))
  143. {
  144. $dependency=new CFileCacheDependency($messageFile);
  145. $cache->set($key,serialize($messages),$this->cachingDuration,$dependency);
  146. }
  147. return $messages;
  148. }
  149. else
  150. return array();
  151. }
  152. }