function test_saveTranslation()
 {
     $path = Piwik_TranslationWriter::getTranslationPath('en', 'tmp');
     $translations = array('General_Locale' => 'en_CA.UTF-8', 'General_Id' => 'Id', 'Goals_Goals' => 'Goals', 'Plugin_Body' => "Message\nBody");
     @unlink($path);
     $rc = Piwik_TranslationWriter::saveTranslation($translations, $path);
     $this->assertTrue($rc !== false);
     $contents = file_get_contents($path);
     $expected = "<?php\n\$translations = array(\n\t'General_Locale' => 'en_CA.UTF-8',\n\t'General_Id' => 'Id',\n\t'Goals_Goals' => 'Goals',\n\n\t// FOR REVIEW\n\t'Plugin_Body' => 'Message\nBody',\n);\n";
     if (Piwik_Common::isWindows()) {
         $expected = str_replace("\r\n", "\n", $expected);
     }
     $this->assertEqual($contents, $expected);
 }
    private function writeCleanedTranslationFile($translations, $language)
    {
        $path = Piwik_TranslationWriter::getTranslationPath($language, 'tmp');
        Piwik_TranslationWriter::saveTranslation($translations, $path);
        $this->fail('Translation file errors detected in ' . $language . '... 
					Wrote cleaned translation file in: ' . $path . ".\n\t\t\t\t\tYou can copy the cleaned files to /lang/<br/>\n");
    }
 /**
  * test all languages
  * 
  * @group Plugins
  * @group LanguagesManager
  */
 function testGetTranslationsForLanguages()
 {
     $allLanguages = Piwik_Common::getLanguagesList();
     $allCountries = Piwik_Common::getCountriesList();
     $englishStrings = Piwik_LanguagesManager_API::getInstance()->getTranslationsForLanguage('en');
     $englishStringsWithParameters = array();
     $expectedLanguageKeys = array();
     foreach ($englishStrings as $englishString) {
         $stringLabel = $englishString['label'];
         $stringValue = $englishString['value'];
         $count = $this->getCountParametersToReplace($stringValue);
         if ($count > 0) {
             $englishStringsWithParameters[$stringLabel] = $count;
         }
         $englishStringsIndexed[$stringLabel] = $stringValue;
         $expectedLanguageKeys[] = $stringLabel;
     }
     self::$englishStringsIndexed = $englishStringsIndexed;
     // we also test that none of the language php files outputs any character on the screen (eg. space before the <?php)
     $languages = Piwik_LanguagesManager_API::getInstance()->getAvailableLanguages();
     $output = array();
     foreach ($languages as $language) {
         self::$errors = array();
         if ($language == 'en') {
             continue;
         }
         ob_start();
         $writeCleanedFile = false;
         $strings = Piwik_LanguagesManager_API::getInstance()->getTranslationsForLanguage($language);
         $content = ob_get_flush();
         $serializedStrings = serialize($strings);
         $invalids = array("<script", 'document.', 'javascript:', 'src=', 'BACKGROUND=', 'onload=');
         foreach ($invalids as $invalid) {
             $this->assertTrue(stripos($serializedStrings, $invalid) === false, "{$language}: language file containing javascript");
         }
         $this->assertTrue(count($strings) > 100, "{$language}: expecting at least 100 translations in the language file");
         $this->assertTrue(strlen($content) == 0, "{$language}: buffer was " . strlen($content) . " long but should be zero. Translation file for '{$language}' must be buggy.");
         $cleanedStrings = array();
         foreach ($strings as $string) {
             $stringLabel = $string['label'];
             $stringValue = $string['value'];
             $plugin = substr($stringLabel, 0, strpos($stringLabel, '_'));
             $plugins[$plugin] = true;
             // Testing that the translated string is not empty => '',
             if (empty($stringValue) || trim($stringValue) === '') {
                 $writeCleanedFile = true;
                 self::$errors[] = "{$language}: The string {$stringLabel} is empty in the translation file, removing the line.";
                 $cleanedStrings[$stringLabel] = false;
             } elseif (!in_array($stringLabel, $expectedLanguageKeys) && !in_array($plugin, array('GeoIP', 'Forecast', 'EntryPage', 'UserLanguage'))) {
                 $writeCleanedFile = true;
                 self::$errors[] = "{$language}: The string {$stringLabel} was not found in the English language file, removing the line.";
                 $cleanedStrings[$stringLabel] = false;
             } else {
                 // checking that translated strings have the same number of %s as the english source strings
                 if (isset($englishStringsWithParameters[$stringLabel])) {
                     $englishParametersCount = $englishStringsWithParameters[$stringLabel];
                     $countTranslation = $this->getCountParametersToReplace($stringValue);
                     if ($englishParametersCount != $countTranslation) {
                         // Write fixed file in given location
                         // Will trigger a ->fail()
                         $writeCleanedFile = true;
                         self::$errors[] = "{$language}: The string {$stringLabel} has {$englishParametersCount} parameters in English, but {$countTranslation} in this translation.";
                     } else {
                         $cleanedStrings[$stringLabel] = $stringValue;
                     }
                 } else {
                     $cleanedStrings[$stringLabel] = $stringValue;
                 }
             }
             // If the translation is the same as in English, we remove it from the translation file (as it might have been copied by
             // the translator but this would skew translation stats
             if (isset($englishStringsIndexed[$stringLabel]) && $englishStringsIndexed[$stringLabel] == $stringValue && strpos($stringLabel, 'General_') === false && strpos($stringLabel, 'CoreHome_') === false && strpos($stringLabel, 'UserCountry_') === false && $language != 'de') {
                 $writeCleanedFile = true;
                 self::$errors[] = "{$language}: The string {$stringLabel} is the same as in English, removing...";
                 $cleanedStrings[$stringLabel] = false;
             }
             // remove excessive line breaks (and leading/trailing whitespace) from translations
             if (!empty($cleanedStrings[$stringLabel])) {
                 $stringNoLineBreak = trim($cleanedStrings[$stringLabel]);
                 if ($stringLabel != 'Login_MailPasswordChangeBody') {
                     $stringNoLineBreak = str_replace(array("\n", "\r"), " ", $stringNoLineBreak);
                 }
                 if ($cleanedStrings[$stringLabel] !== $stringNoLineBreak) {
                     self::$errors[] = "{$language}: found unnecessary whitespace in some strings in {$stringLabel}";
                     $writeCleanedFile = true;
                     $cleanedStrings[$stringLabel] = $stringNoLineBreak;
                 }
             }
             // Test locale
             if ($stringLabel == 'General_Locale' && !empty($cleanedStrings[$stringLabel])) {
                 if (!preg_match('/^([a-z]{2})_([A-Z]{2})\\.UTF-8$/', $cleanedStrings[$stringLabel], $matches)) {
                     $this->fail("{$language}: invalid locale in {$stringLabel}");
                 } else {
                     if (!array_key_exists($matches[1], $allLanguages)) {
                         $this->fail("{$language}: invalid language code in {$stringLabel}");
                     } else {
                         if (!array_key_exists(strtolower($matches[2]), $allCountries)) {
                             $this->fail("{$language}: invalid region (country code) in {$stringLabel}");
                         }
                     }
                 }
             }
             if (isset($cleanedStrings[$stringLabel])) {
                 $currentString = $cleanedStrings[$stringLabel];
                 $decoded = Piwik_TranslationWriter::clean($currentString);
                 if ($currentString != $decoded) {
                     self::$errors[] = "{$language}: found encoded entities in {$stringLabel}, converting entities to characters";
                     $writeCleanedFile = true;
                     $cleanedStrings[$stringLabel] = $decoded;
                 }
             }
         }
         $this->assertTrue(!empty($cleanedStrings['General_TranslatorName']), "{$language}: translator info not specified");
         $this->assertTrue(!empty($cleanedStrings['General_TranslatorEmail']), "{$language}: translator email not specified");
         if (!empty($cleanedStrings['General_LayoutDirection']) && !in_array($cleanedStrings['General_LayoutDirection'], array('rtl', 'ltr'))) {
             $writeCleanedFile = true;
             $cleanedStrings['General_LayoutDirection'] = false;
             self::$errors[] = "{$language}: General_LayoutDirection must be rtl or ltr";
         }
         if ($writeCleanedFile) {
             $path = Piwik_TranslationWriter::getTranslationPath($language, 'tmp');
             // Reorder cleaned up translations as the same order as en.php
             uksort($cleanedStrings, array($this, 'sortTranslationsKeys'));
             Piwik_TranslationWriter::saveTranslation($cleanedStrings, $path);
             $output[] = implode("<br>\n", self::$errors) . "\n" . 'Translation file errors detected in ' . $language . '...
                 Wrote cleaned translation file in: ' . $path . ".\n                    You can copy the cleaned files to /lang/\n";
         }
     }
     if (!empty($output)) {
         $this->fail(implode(",", $output));
     }
 }