diff --git a/core/Translate/Writer.php b/core/Translate/Writer.php index a1b295fa070ef14f3e5f3c2af74a5d543a1ea14a..66e34449ec00ff80da9a0bcffddfb2eb4aed989e 100644 --- a/core/Translate/Writer.php +++ b/core/Translate/Writer.php @@ -99,10 +99,16 @@ class Writer /** * @param string $language ISO 639-1 alpha-2 language code + * + * @throws \Exception */ public function setLanguage($language) { - $this->_language = $language; + if (!preg_match('/^([a-z]{2,3}(-[a-z]{2,3})?)$/i', $language)) { + throw new Exception(Piwik_TranslateException('General_ExceptionLanguageFileNotFound', array($language))); + } + + $this->_language = strtolower($language); } /** @@ -185,21 +191,8 @@ class Writer { if (empty($lang)) $lang = $this->getLanguage(); - if (!Common::isValidFilename($lang) || - ($base !== 'lang' && $base !== 'tmp') - ) { - throw new Exception(Piwik_TranslateException('General_ExceptionLanguageFileNotFound', array($lang))); - } - if (!empty($this->_pluginName)) { - $installedPlugins = PluginsManager::getInstance()->readPluginsDirectory(); - - if (!in_array($this->_pluginName, $installedPlugins)) { - - throw new Exception(Piwik_TranslateException('General_ExceptionLanguageFileNotFound', array($lang))); - } - if ($base == 'tmp') { return sprintf('%s/tmp/plugins/%s/lang/%s.json', PIWIK_INCLUDE_PATH, $this->_pluginName, $lang); } else { diff --git a/tests/PHPUnit/Core/Translate/Filter/ByBaseTranslationsTest.php b/tests/PHPUnit/Core/Translate/Filter/ByBaseTranslationsTest.php index 6596059ba7aa89dbb66871f1d9b94817adc41079..f4ec1aaec2dda34ea5a47e07fa1623fa74091e42 100644 --- a/tests/PHPUnit/Core/Translate/Filter/ByBaseTranslationsTest.php +++ b/tests/PHPUnit/Core/Translate/Filter/ByBaseTranslationsTest.php @@ -30,7 +30,7 @@ class ByBaseTranslationsTest extends PHPUnit_Framework_TestCase 'test' => array() ), ), - // empty values/plugins are removed + // not existing values/plugins are removed array( array( 'test' => array( @@ -55,7 +55,7 @@ class ByBaseTranslationsTest extends PHPUnit_Framework_TestCase ) ), ), - // no change if no empty value + // no change if all exist array( array( 'test' => array( @@ -74,7 +74,7 @@ class ByBaseTranslationsTest extends PHPUnit_Framework_TestCase ), array() ), - // empty values are removed, others stay + // unavailable removed, others stay array( array( 'empty' => array( @@ -107,6 +107,38 @@ class ByBaseTranslationsTest extends PHPUnit_Framework_TestCase ) ) ), + array( + array( + 'empty' => array( + 'test' => 'test' + ), + 'test' => array( + 'test' => 'test', + 'empty' => ' ', + ) + ), + array( + 'empty' => array( + 'bla' => 'test' + ), + 'test' => array( + 'test' => 'test', + ) + ), + array( + 'test' => array( + 'test' => 'test' + ) + ), + array( + 'empty' => array( + 'test' => 'test' + ), + 'test' => array( + 'empty' => ' ', + ) + ) + ), ); } diff --git a/tests/PHPUnit/Core/Translate/Validate/CoreTranslationsTest.php b/tests/PHPUnit/Core/Translate/Validate/CoreTranslationsTest.php index f9412d2b174fd6ef0892b191bc407cc52267f2e2..4c325db96c7c7a53d358718e658aabc82133c9eb 100644 --- a/tests/PHPUnit/Core/Translate/Validate/CoreTranslationsTest.php +++ b/tests/PHPUnit/Core/Translate/Validate/CoreTranslationsTest.php @@ -7,8 +7,14 @@ use Piwik\Translate\Validate\CoreTranslations; * @link http://piwik.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -class BaseTranslationsTest extends PHPUnit_Framework_TestCase +class CoreTranslationsTest extends PHPUnit_Framework_TestCase { + public function setUp() + { + include PIWIK_INCLUDE_PATH . '/core/DataFiles/Languages.php'; + include PIWIK_INCLUDE_PATH . '/core/DataFiles/Countries.php'; + } + public function getFilterTestDataValid() { return array( @@ -127,9 +133,6 @@ class BaseTranslationsTest extends PHPUnit_Framework_TestCase */ public function testFilterInvalid($translations, $msg) { - include PIWIK_INCLUDE_PATH . '/core/DataFiles/Languages.php'; - include PIWIK_INCLUDE_PATH . '/core/DataFiles/Countries.php'; - $filter = new CoreTranslations(); $result = $filter->isValid($translations); $this->assertFalse($result); diff --git a/tests/PHPUnit/Core/Translate/WriterTest.php b/tests/PHPUnit/Core/Translate/WriterTest.php index d45fa635afcab5a3bac4b9fbc9084b62109267ff..9606b66151c071314bd71025a87af1338e7c7ae1 100644 --- a/tests/PHPUnit/Core/Translate/WriterTest.php +++ b/tests/PHPUnit/Core/Translate/WriterTest.php @@ -1,6 +1,7 @@ <?php use Piwik\Common; use Piwik\Translate\Writer; +use Piwik\Translate\Validate\CoreTranslations; /** * Piwik - Open source web analytics @@ -50,36 +51,166 @@ class WriterTest extends PHPUnit_Framework_TestCase /** * @group Core * @group Translate + * @ expectedException Exception + * @dataProvider getExceptionalTranslations + */ + public function testSetTranslationsThrowsException($translations, $error) + { + $writer = new Writer('de'); + try { + $writer->setTranslations($translations); + $this->fail('Exception not thrown'); + } catch (Exception $e) { + $this->assertEquals($error, $e->getMessage()); + } + } + + public function getExceptionalTranslations() + { + $translations = json_decode(file_get_contents(PIWIK_INCLUDE_PATH.'/lang/de.json'), true); + return array( + array(array('test' => array('test' => 'test')), CoreTranslations::__ERRORSTATE_MINIMUMTRANSLATIONS__), + array(array('General' => array('Locale' => '')) + $translations, CoreTranslations::__ERRORSTATE_LOCALEREQUIRED__), + array(array('General' => array('Locale' => 'de_DE.UTF-8')) + $translations, CoreTranslations::__ERRORSTATE_TRANSLATORINFOREQUIRED__), + array(array('General' => array('Locale' => 'de_DE.UTF-8', + 'TranslatorName' => 'name')) + $translations, CoreTranslations::__ERRORSTATE_TRANSLATOREMAILREQUIRED__), + array(array('General' => array('Locale' => 'de_DE.UTF-8', + 'TranslatorName' => 'name', + 'TranslatorEmail' => 'name@domain.com', + 'LayoutDirection' => 'fail')) + $translations, CoreTranslations::__ERRORSTATE_LAYOUTDIRECTIONINVALID__), + array(array('General' => array('Locale' => 'invalid', + 'TranslatorName' => 'name', + 'TranslatorEmail' => 'name@domain.com')) + $translations, CoreTranslations::__ERRORSTATE_LOCALEINVALID__), + array(array('General' => array('Locale' => 'xx_DE.UTF-8', + 'TranslatorName' => 'name', + 'TranslatorEmail' => 'name@domain.com',)) + $translations, CoreTranslations::__ERRORSTATE_LOCALEINVALIDLANGUAGE__), + array(array('General' => array('Locale' => 'de_XX.UTF-8', + 'TranslatorName' => 'name', + 'TranslatorEmail' => 'name@domain.com',)) + $translations, CoreTranslations::__ERRORSTATE_LOCALEINVALIDCOUNTRY__), + array(array('General' => array('Locale' => '<script>')) + $translations, 'script tags restricted for language files'), + ); + } + + /** + * @group Core + * @group Translate + * @group Translate_Write */ public function testSaveTranslation() { - $translations = array( - 'General' => array( - 'Locale' => 'en_CA.UTF-8', - 'Id' => 'Id' - ), - 'Goals' => array( - 'Goals' => 'Goals', - ), - 'Plugin' => array( - 'Body' => "Message\nBody" - ) + $translations = json_decode(file_get_contents(PIWIK_INCLUDE_PATH.'/lang/en.json'), true); + + $translationsToWrite = array(); + $translationsToWrite['General'] = $translations['General']; + $translationsToWrite['UserLanguage'] = $translations['UserLanguage']; + $translationsToWrite['UserCountry'] = $translations['UserCountry']; + + $translationsToWrite['General']['Yes'] = 'string with %1$s'; + $translationsToWrite['Plugin'] = array( + 'Body' => "Message\nBody" ); - $translationWriter = new Writer('en', ''); - $translationWriter->setTranslations($translations); + $translationWriter = new Writer('fr'); + $translationWriter->setTranslations($translationsToWrite); $rc = $translationWriter->saveTemporary(); - $this->assertNotEquals(false, $rc); + $this->assertGreaterThan(50000, $rc); - $contents = file_get_contents(PIWIK_DOCUMENT_ROOT.'/tmp/en.json'); + $this->assertCount(4, $translationWriter->getErrors()); + } - $options = 0; - if (defined('JSON_UNESCAPED_UNICODE')) $options |= JSON_UNESCAPED_UNICODE; - if (defined('JSON_PRETTY_PRINT')) $options |= JSON_PRETTY_PRINT; + /** + * @group Core + * @group Translate + * @dataProvider getTranslationPathTestData + */ + public function testGetTranslationsPath($language, $plugin, $path) + { + $writer = new Writer($language, $plugin); + $this->assertEquals($path, $writer->getTranslationPath()); + } - $expected = json_encode(json_decode('{"General":{"Locale":"en_CA.UTF-8","Id":"Id"},"Goals":{"Goals":"Goals"}}', true), $options); + public function getTranslationPathTestData() + { + return array( + array('de', null, PIWIK_INCLUDE_PATH . '/lang/de.json'), + array('te', null, PIWIK_INCLUDE_PATH . '/lang/te.json'), + array('de', 'CoreHome', PIWIK_INCLUDE_PATH . '/plugins/CoreHome/lang/de.json'), + array('pt-br', 'Actions', PIWIK_INCLUDE_PATH . '/plugins/Actions/lang/pt-br.json'), + ); + } - $this->assertEquals($expected, $contents); + /** + * @group Core + * @group Translate + * @dataProvider getTranslationPathTemporaryTestData + */ + public function testGetTemporaryTranslationPath($language, $plugin, $path) + { + $writer = new Writer($language, $plugin); + $this->assertEquals($path, $writer->getTemporaryTranslationPath()); + } + + public function getTranslationPathTemporaryTestData() + { + return array( + array('de', null, PIWIK_INCLUDE_PATH . '/tmp/de.json'), + array('te', null, PIWIK_INCLUDE_PATH . '/tmp/te.json'), + array('de', 'CoreHome', PIWIK_INCLUDE_PATH . '/tmp/plugins/CoreHome/lang/de.json'), + array('pt-br', 'Actions', PIWIK_INCLUDE_PATH . '/tmp/plugins/Actions/lang/pt-br.json'), + ); + } + + /** + * @group Core + * @group Translate + * @dataProvider getValidLanguages + */ + public function testSetLanguageValid($language) + { + $writer = new Writer('en', null); + $writer->setLanguage($language); + $this->assertEquals(strtolower($language), $writer->getLanguage()); + } + + public function getValidLanguages() + { + return array( + array('de'), + array('te'), + array('pt-br'), + array('tzm'), + array('abc'), + array('de-de'), + array('DE'), + array('DE-DE'), + array('DE-de'), + ); + } + /** + * @group Core + * @group Translate + * @expectedException Exception + * @dataProvider getInvalidLanguages + */ + public function testSetLanguageInvalid($language) + { + $writer = new Writer('en', null); + $writer->setLanguage($language); + } + + public function getInvalidLanguages() + { + return array( + array(''), + array('abcd'), + array('pt-brfr'), + array('00'), + array('a-b'), + array('x3'), + array('X4-fd'), + array('12-34'), + array('$§'), + ); } }