Teknik is a suite of services with attractive and functional interfaces. https://www.teknik.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Translate.php 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <?php
  2. /**
  3. * Piwik - free/libre analytics platform
  4. *
  5. * @link http://piwik.org
  6. * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  7. *
  8. */
  9. namespace Piwik;
  10. use Exception;
  11. /**
  12. */
  13. class Translate
  14. {
  15. private static $languageToLoad = null;
  16. private static $loadedLanguage = false;
  17. /**
  18. * Clean a string that may contain HTML special chars, single/double quotes, HTML entities, leading/trailing whitespace
  19. *
  20. * @param string $s
  21. * @return string
  22. */
  23. public static function clean($s)
  24. {
  25. return html_entity_decode(trim($s), ENT_QUOTES, 'UTF-8');
  26. }
  27. public static function loadEnglishTranslation()
  28. {
  29. self::loadCoreTranslationFile('en');
  30. }
  31. public static function unloadEnglishTranslation()
  32. {
  33. $GLOBALS['Piwik_translations'] = array();
  34. }
  35. public static function reloadLanguage($language = false)
  36. {
  37. if (empty($language)) {
  38. $language = self::getLanguageToLoad();
  39. }
  40. self::unloadEnglishTranslation();
  41. self::loadEnglishTranslation();
  42. self::loadCoreTranslation($language);
  43. \Piwik\Plugin\Manager::getInstance()->loadPluginTranslations($language);
  44. }
  45. /**
  46. * Reads the specified code translation file in memory.
  47. *
  48. * @param bool|string $language 2 letter language code. If not specified, will detect current user translation, or load default translation.
  49. * @return void
  50. */
  51. public static function loadCoreTranslation($language = false)
  52. {
  53. if (empty($language)) {
  54. $language = self::getLanguageToLoad();
  55. }
  56. if (self::$loadedLanguage == $language) {
  57. return;
  58. }
  59. self::loadCoreTranslationFile($language);
  60. }
  61. private static function loadCoreTranslationFile($language)
  62. {
  63. if(empty($language)) {
  64. return;
  65. }
  66. $path = PIWIK_INCLUDE_PATH . '/lang/' . $language . '.json';
  67. if (!Filesystem::isValidFilename($language) || !is_readable($path)) {
  68. throw new Exception(Piwik::translate('General_ExceptionLanguageFileNotFound', array($language)));
  69. }
  70. $data = file_get_contents($path);
  71. $translations = json_decode($data, true);
  72. self::mergeTranslationArray($translations);
  73. self::setLocale();
  74. self::$loadedLanguage = $language;
  75. }
  76. public static function mergeTranslationArray($translation)
  77. {
  78. if (!isset($GLOBALS['Piwik_translations'])) {
  79. $GLOBALS['Piwik_translations'] = array();
  80. }
  81. if (empty($translation)) {
  82. return;
  83. }
  84. // we could check that no string overlap here
  85. $GLOBALS['Piwik_translations'] = array_replace_recursive($GLOBALS['Piwik_translations'], $translation);
  86. }
  87. /**
  88. * @return string the language filename prefix, eg 'en' for english
  89. * @throws exception if the language set is not a valid filename
  90. */
  91. public static function getLanguageToLoad()
  92. {
  93. if (is_null(self::$languageToLoad)) {
  94. $lang = Common::getRequestVar('language', '', 'string');
  95. /**
  96. * Triggered when the current user's language is requested.
  97. *
  98. * By default the current language is determined by the **language** query
  99. * parameter. Plugins can override this logic by subscribing to this event.
  100. *
  101. * **Example**
  102. *
  103. * public function getLanguage(&$lang)
  104. * {
  105. * $client = new My3rdPartyAPIClient();
  106. * $thirdPartyLang = $client->getLanguageForUser(Piwik::getCurrentUserLogin());
  107. *
  108. * if (!empty($thirdPartyLang)) {
  109. * $lang = $thirdPartyLang;
  110. * }
  111. * }
  112. *
  113. * @param string &$lang The language that should be used for the current user. Will be
  114. * initialized to the value of the **language** query parameter.
  115. */
  116. Piwik::postEvent('User.getLanguage', array(&$lang));
  117. self::$languageToLoad = $lang;
  118. }
  119. return self::$languageToLoad;
  120. }
  121. /** Reset the cached language to load. Used in tests. */
  122. public static function reset()
  123. {
  124. self::$languageToLoad = null;
  125. }
  126. private static function isALanguageLoaded() {
  127. return !empty($GLOBALS['Piwik_translations']);
  128. }
  129. /**
  130. * Either the name of the currently loaded language such as 'en' or 'de' or null if no language is loaded at all.
  131. * @return bool|string
  132. */
  133. public static function getLanguageLoaded()
  134. {
  135. if (!self::isALanguageLoaded()) {
  136. return null;
  137. }
  138. return self::$loadedLanguage;
  139. }
  140. public static function getLanguageDefault()
  141. {
  142. return Config::getInstance()->General['default_language'];
  143. }
  144. /**
  145. * Generate javascript translations array
  146. */
  147. public static function getJavascriptTranslations()
  148. {
  149. $translations = & $GLOBALS['Piwik_translations'];
  150. $clientSideTranslations = array();
  151. foreach (self::getClientSideTranslationKeys() as $key) {
  152. list($plugin, $stringName) = explode("_", $key, 2);
  153. $clientSideTranslations[$key] = $translations[$plugin][$stringName];
  154. }
  155. $js = 'var translations = ' . Common::json_encode($clientSideTranslations) . ';';
  156. $js .= "\n" . 'if(typeof(piwik_translations) == \'undefined\') { var piwik_translations = new Object; }' .
  157. 'for(var i in translations) { piwik_translations[i] = translations[i];} ';
  158. return $js;
  159. }
  160. /**
  161. * Returns the list of client side translations by key. These translations will be outputted
  162. * to the translation JavaScript.
  163. */
  164. private static function getClientSideTranslationKeys()
  165. {
  166. $result = array();
  167. /**
  168. * Triggered before generating the JavaScript code that allows i18n strings to be used
  169. * in the browser.
  170. *
  171. * Plugins should subscribe to this event to specify which translations
  172. * should be available to JavaScript.
  173. *
  174. * Event handlers should add whole translation keys, ie, keys that include the plugin name.
  175. *
  176. * **Example**
  177. *
  178. * public function getClientSideTranslationKeys(&$result)
  179. * {
  180. * $result[] = "MyPlugin_MyTranslation";
  181. * }
  182. *
  183. * @param array &$result The whole list of client side translation keys.
  184. */
  185. Piwik::postEvent('Translate.getClientSideTranslationKeys', array(&$result));
  186. $result = array_unique($result);
  187. return $result;
  188. }
  189. /**
  190. * Set locale
  191. *
  192. * @see http://php.net/setlocale
  193. */
  194. private static function setLocale()
  195. {
  196. $locale = $GLOBALS['Piwik_translations']['General']['Locale'];
  197. $locale_variant = str_replace('UTF-8', 'UTF8', $locale);
  198. setlocale(LC_ALL, $locale, $locale_variant);
  199. setlocale(LC_CTYPE, '');
  200. }
  201. public static function findTranslationKeyForTranslation($translation)
  202. {
  203. if (empty($GLOBALS['Piwik_translations'])) {
  204. return;
  205. }
  206. foreach ($GLOBALS['Piwik_translations'] as $key => $translations) {
  207. $possibleKey = array_search($translation, $translations);
  208. if (!empty($possibleKey)) {
  209. return $key . '_' . $possibleKey;
  210. }
  211. }
  212. }
  213. }