PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/LanguagesManager/tests/LanguagesManager.test.php

https://github.com/quarkness/piwik
PHP | 259 lines | 225 code | 16 blank | 18 comment | 43 complexity | 6f04e8a9fbcf2efe5e5ef542f92a4ee0 MD5 | raw file
  1. <?php
  2. if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
  3. {
  4. require_once dirname(__FILE__)."/../../../tests/config_test.php";
  5. }
  6. require_once 'LanguagesManager/API.php';
  7. class Test_LanguagesManager extends UnitTestCase
  8. {
  9. function __construct( $title = '')
  10. {
  11. parent::__construct( $title );
  12. }
  13. // test all languages
  14. function test_getTranslationsForLanguages()
  15. {
  16. $allLanguages = Piwik_Common::getLanguagesList();
  17. $allCountries = Piwik_Common::getCountriesList();
  18. $englishStrings = Piwik_LanguagesManager_API::getInstance()->getTranslationsForLanguage('en');
  19. $englishStringsWithParameters = array();
  20. $expectedLanguageKeys = array();
  21. foreach($englishStrings as $englishString)
  22. {
  23. $stringLabel = $englishString['label'];
  24. $stringValue = $englishString['value'];
  25. $count = $this->getCountParametersToReplace($stringValue);
  26. if($count > 0)
  27. {
  28. $englishStringsWithParameters[$stringLabel] = $count;
  29. }
  30. $englishStringsIndexed[$stringLabel] = $stringValue;
  31. $expectedLanguageKeys[] = $stringLabel;
  32. }
  33. // we also test that none of the language php files outputs any character on the screen (eg. space before the <?php)
  34. $languages = Piwik_LanguagesManager_API::getInstance()->getAvailableLanguages();
  35. foreach($languages as $language)
  36. {
  37. ob_start();
  38. $writeCleanedFile = false;
  39. $strings = Piwik_LanguagesManager_API::getInstance()->getTranslationsForLanguage($language);
  40. $content = ob_get_flush();
  41. $serializedStrings = serialize($strings);
  42. $invalids = array("<script", 'document.', 'javascript:', 'src=', 'BACKGROUND=', 'onload=' );
  43. foreach($invalids as $invalid)
  44. {
  45. $this->assertTrue(stripos($serializedStrings, $invalid) === false, "$language: language file containing javascript");
  46. }
  47. $this->assertTrue(count($strings) > 100, "$language: expecting at least 100 translations in the language file");
  48. $this->assertTrue(strlen($content) == 0, "$language: buffer was ".strlen($content)." long but should be zero. Translation file for '$language' must be buggy.");
  49. $cleanedStrings = array();
  50. foreach($strings as $string)
  51. {
  52. $stringLabel = $string['label'];
  53. $stringValue = $string['value'];
  54. $plugin = substr($stringLabel, 0, strpos($stringLabel, '_'));
  55. $plugins[$plugin] = true;
  56. // Testing that the translated string is not empty => '',
  57. if(empty($stringValue) || trim($stringValue) === '')
  58. {
  59. $writeCleanedFile = true;
  60. echo "$language: The string $stringLabel is empty in the translation file, removing the line. <br/>\n";
  61. $cleanedStrings[$stringLabel] = false;
  62. }
  63. elseif(!in_array($stringLabel, $expectedLanguageKeys)
  64. // translation files should not contain 3rd plugin translations, but if they are there, we shall not delete them
  65. // since translators have spent time working on it... at least for now we shall leave them in (until V2 and plugin repository is done)
  66. && !in_array($plugin, array('GeoIP', 'Forecast', 'EntryPage', 'UserLanguage'))
  67. )
  68. {
  69. $writeCleanedFile = true;
  70. echo "$language: The string $stringLabel was not found in the English language file, removing the line. <br/>\n";
  71. $cleanedStrings[$stringLabel] = false;
  72. }
  73. else
  74. {
  75. // checking that translated strings have the same number of %s as the english source strings
  76. if(isset($englishStringsWithParameters[$stringLabel]))
  77. {
  78. $englishParametersCount = $englishStringsWithParameters[$stringLabel];
  79. $countTranslation = $this->getCountParametersToReplace($stringValue);
  80. if($englishParametersCount != $countTranslation)
  81. {
  82. // Write fixed file in given location
  83. // Will trigger a ->fail()
  84. $writeCleanedFile = true;
  85. echo "$language: The string $stringLabel has $englishParametersCount parameters in English, but $countTranslation in this translation. <br/>\n";
  86. }
  87. else
  88. {
  89. $cleanedStrings[$stringLabel] = $stringValue;
  90. }
  91. }
  92. // No %s found
  93. else
  94. {
  95. $cleanedStrings[$stringLabel] = $stringValue;
  96. }
  97. }
  98. // If the translation is the same as in English, we remove it from the translation file (as it might have been copied by
  99. // the translator but this would skew translation stats
  100. if(isset($englishStringsIndexed[$stringLabel])
  101. && $englishStringsIndexed[$stringLabel] == $stringValue
  102. //Currently hackjed for Persian since only the Farsi translation seems affected by "english copy paste"
  103. && $language == 'fa')
  104. {
  105. $writeCleanedFile = true;
  106. echo "$language: The string $stringLabel is the same as in English, removing... <br/>\n";
  107. $cleanedStrings[$stringLabel] = false;
  108. }
  109. // remove excessive line breaks (and leading/trailing whitespace) from translations
  110. if(!empty($cleanedStrings[$stringLabel]))
  111. {
  112. $stringNoLineBreak = trim($cleanedStrings[$stringLabel]);
  113. if($stringLabel != 'Login_MailPasswordRecoveryBody')
  114. {
  115. $stringNoLineBreak = str_replace(array("\n", "\r"), " ", $stringNoLineBreak);
  116. }
  117. if($cleanedStrings[$stringLabel] !== $stringNoLineBreak)
  118. {
  119. echo "$language: found unnecessary whitespace in some strings in $stringLabel <br/>\n";
  120. $writeCleanedFile = true;
  121. $cleanedStrings[$stringLabel] = $stringNoLineBreak;
  122. }
  123. }
  124. // Test locale
  125. if($stringLabel == 'General_Locale'
  126. && !empty($cleanedStrings[$stringLabel]))
  127. {
  128. if(!preg_match('/^([a-z]{2})_([A-Z]{2})\.UTF-8$/', $cleanedStrings[$stringLabel], $matches))
  129. {
  130. $this->fail("$language: invalid locale in $stringLabel");
  131. }
  132. else if(!array_key_exists($matches[1], $allLanguages))
  133. {
  134. $this->fail("$language: invalid language code in $stringLabel");
  135. }
  136. else if(!array_key_exists(strtolower($matches[2]), $allCountries))
  137. {
  138. $this->fail("$language: invalid region (country code) in $stringLabel");
  139. }
  140. }
  141. if(isset($cleanedStrings[$stringLabel]))
  142. {
  143. $currentString = $cleanedStrings[$stringLabel];
  144. $decoded = Piwik_TranslationWriter::clean($currentString);
  145. if($currentString != $decoded )
  146. {
  147. echo "$language: found encoded entities in $stringLabel, converting entities to characters <br/>\n";
  148. $writeCleanedFile = true;
  149. $cleanedStrings[$stringLabel] = $decoded;
  150. }
  151. }
  152. }
  153. $this->assertTrue( !empty($cleanedStrings['General_TranslatorName'] ), "$language: translator info not specified");
  154. $this->assertTrue( !empty($cleanedStrings['General_TranslatorEmail'] ), "$language: translator info not specified");
  155. if(!empty($cleanedStrings['General_LayoutDirection'])
  156. && !in_array($cleanedStrings['General_LayoutDirection'], array('rtl','ltr')))
  157. {
  158. $writeCleanedFile = true;
  159. $cleanedStrings['General_LayoutDirection'] = false;
  160. echo "$language: General_LayoutDirection must be rtl or ltr";
  161. }
  162. if($writeCleanedFile)
  163. {
  164. $this->writeCleanedTranslationFile($cleanedStrings, $language);
  165. }
  166. }
  167. // var_dump('Unique plugins found: ' . var_export($plugins, 1));
  168. $this->pass();
  169. }
  170. private function writeCleanedTranslationFile($translations, $language)
  171. {
  172. $path = Piwik_TranslationWriter::getTranslationPath($language, 'tmp');
  173. Piwik_TranslationWriter::saveTranslation($translations, $path);
  174. $this->fail('Translation file errors detected in '.$language.'...
  175. Wrote cleaned translation file in: '.$path .".
  176. You can copy the cleaned files to /lang/<br/>\n");
  177. }
  178. private function getCountParametersToReplace($string)
  179. {
  180. $sprintfParameters = array('%s', '%1$s', '%2$s', '%3$s', '%4$s', '%5$s', '%6$s');
  181. $count = 0;
  182. foreach($sprintfParameters as $parameter)
  183. {
  184. $count += substr_count($string, $parameter);
  185. }
  186. return $count;
  187. }
  188. //test language when it's not defined
  189. function test_getTranslationsForLanguages_not()
  190. {
  191. $this->assertFalse(Piwik_LanguagesManager_API::getInstance()->getTranslationsForLanguage("../no-language"));
  192. }
  193. // test English short name for language
  194. function test_getLanguageNamesInEnglish()
  195. {
  196. require_once PIWIK_INCLUDE_PATH . '/core/DataFiles/Languages.php';
  197. $languages = Piwik_LanguagesManager_API::getInstance()->getAvailableLanguages();
  198. foreach($languages as $language)
  199. {
  200. require PIWIK_INCLUDE_PATH . "/lang/$language.php";
  201. $name = $translations['General_EnglishLanguageName'];
  202. if($language != 'en')
  203. {
  204. $this->assertFalse($name == 'English');
  205. }
  206. $languageCode = substr($language, 0, 2);
  207. $this->assertTrue(isset($GLOBALS['Piwik_LanguageList'][$languageCode]));
  208. $names = $GLOBALS['Piwik_LanguageList'][$languageCode];
  209. if(isset($GLOBALS['Piwik_LanguageList'][$language]))
  210. {
  211. if(is_array($names))
  212. {
  213. $this->assertTrue(in_array($name, $names), "$language: failed because $name not a known language name <br/>");
  214. }
  215. else
  216. {
  217. $this->assertTrue($name == $names, "$language: failed because $name == $names <br/>");
  218. }
  219. }
  220. else
  221. {
  222. if(is_array($names))
  223. {
  224. $this->assertTrue(strpos($name, $names[0]) !== false);
  225. }
  226. else
  227. {
  228. $this->fail("$language: expected an array of language names");
  229. }
  230. }
  231. }
  232. }
  233. // test format of DataFile/Languages.php
  234. function test_getLanguagesList()
  235. {
  236. $languages = Piwik_Common::getLanguagesList();
  237. $this->assertTrue( count($languages) > 0 );
  238. foreach($languages as $langCode => $langs) {
  239. $this->assertTrue(strlen($langCode) == 2, "$langCode length = 2");
  240. $this->assertTrue(is_array($langs) && count($langs) >= 1, "$langCode array(names) >= 1");
  241. }
  242. }
  243. }