Skip to content
Browse files

Merge branch 'feature/i18n-translator-ini' into develop

Close #2706
  • Loading branch information...
2 parents 129b628 + c6a496c commit ad6a44daf7c16afe3035408c7b5ddf9f654cb0d2 @weierophinney weierophinney committed
View
86 library/Zend/I18n/Translator/Loader/Ini.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_I18n
+ */
+
+namespace Zend\I18n\Translator\Loader;
+
+use Zend\Config\Reader\Ini as IniReader;
+use Zend\I18n\Exception;
+use Zend\I18n\Translator\Plural\Rule as PluralRule;
+use Zend\I18n\Translator\TextDomain;
+
+/**
+ * PHP INI format loader.
+ *
+ * @category Zend
+ * @package Zend_I18n
+ * @subpackage Translator
+ */
+class Ini implements FileLoaderInterface
+{
+ /**
+ * load(): defined by FileLoaderInterface.
+ *
+ * @see FileLoaderInterface::load()
+ * @param string $locale
+ * @param string $filename
+ * @return TextDomain|null
+ * @throws Exception\InvalidArgumentException
+ */
+ public function load($locale, $filename)
+ {
+ if (!is_file($filename) || !is_readable($filename)) {
+ throw new Exception\InvalidArgumentException(sprintf(
+ 'Could not open file %s for reading',
+ $filename
+ ));
+ }
+
+ $messages = array();
+ $iniReader = new IniReader();
+ $messagesNamespaced = $iniReader->fromFile($filename);
+
+ $list = $messagesNamespaced;
+ if (isset($messagesNamespaced['translation'])) {
+ $list = $messagesNamespaced['translation'];
+ }
+
+ foreach ($list as $message) {
+ if (!is_array($message) || count($message) < 2) {
+ throw new Exception\InvalidArgumentException(
+ 'Each INI row must be an array with message and translation'
+ );
+ }
+ if (isset($message['message']) && isset($message['translation'])) {
+ $messages[$message['message']] = $message['translation'];
+ continue;
+ }
+ $messages[array_shift($message)] = array_shift($message);
+ }
+
+ if (!is_array($messages)) {
+ throw new Exception\InvalidArgumentException(sprintf(
+ 'Expected an array, but received %s',
+ gettype($messages)
+ ));
+ }
+
+ $textDomain = new TextDomain($messages);
+
+ if (array_key_exists('plural', $messagesNamespaced)
+ && isset($messagesNamespaced['plural']['plural_forms'])
+ ) {
+ $textDomain->setPluralRule(
+ PluralRule::fromString($messagesNamespaced['plural']['plural_forms'])
+ );
+ }
+
+ return $textDomain;
+ }
+}
View
3 library/Zend/I18n/Translator/LoaderPluginManager.php
@@ -32,8 +32,9 @@ class LoaderPluginManager extends AbstractPluginManager
* @var array
*/
protected $invokableClasses = array(
- 'phparray' => 'Zend\I18n\Translator\Loader\PhpArray',
'gettext' => 'Zend\I18n\Translator\Loader\Gettext',
+ 'ini' => 'Zend\I18n\Translator\Loader\Ini',
+ 'phparray' => 'Zend\I18n\Translator\Loader\PhpArray',
);
/**
View
14 resources/languages/fr/Zend_Validate.php
@@ -81,7 +81,7 @@
// Zend_Validator_DateStep
"Invalid type given. String, integer, array or DateTime expected" => "Entrée invalide. Chaîne, entier, tableau ou DateTime attendu",
"The input does not appear to be a valid date" => "L'entrée ne semble pas être une date valide",
- "The input is not a valid step" => "L'entrée n'est pas un intervalle valide",
+ "The input is not a valid step" => "L'entrée n'est pas une step valide",
// Zend_Validator_Db_AbstractDb
"No record matching the input was found" => "Aucun enregistrement trouvé",
@@ -99,7 +99,7 @@
"'%hostname%' does not appear to have any valid MX or A records for the email address" => "'%hostname%' ne semble pas avoir d'enregistrement MX valide pour l'adresse email",
"'%hostname%' is not in a routable network segment. The email address should not be resolved from public network" => "'%hostname%' n'est pas dans un segment réseau routable. L'adresse email ne devrait pas être résolue depuis un réseau public.",
"'%localPart%' can not be matched against dot-atom format" => "'%localPart%' ne correspond pas au format dot-atom",
- "'%localPart%' can not be matched against quoted-string format" => "'%localPart%' ne correspond pas à une chaîne entre quotes",
+ "'%localPart%' can not be matched against quoted-string format" => "'%localPart%' ne correspond pas au format quoted-string",
"'%localPart%' is not a valid local part for the email address" => "'%localPart%' n'est pas une partie locale valide pour l'adresse email",
"The input exceeds the allowed length" => "L'entrée dépasse la taille autorisée",
@@ -178,7 +178,7 @@
"File '%value%' is not readable or does not exist" => "Le fichier '%value%' n'est pas lisible ou n'existe pas",
// Zend_Validator_File_Upload
- "File '%value%' exceeds the defined ini size" => "Le fichier '%value%' dépasse la taille définie dans le fichier INI",
+ "File '%value%' exceeds the defined ini size" => "File '%value%' dépasse la taille défini dans le fichier INI",
"File '%value%' exceeds the defined form size" => "Le fichier '%value%' dépasse la taille définie dans le formulaire",
"File '%value%' was only partially uploaded" => "Le fichier '%value%' n'a été que partiellement envoyé",
"File '%value%' was not uploaded" => "Le fichier '%value%' n'a pas été envoyé",
@@ -250,11 +250,11 @@
"There was an internal error while using the pattern '%pattern%'" => "Une erreur interne est survenue avec l'expression '%pattern%'",
// Zend_Validator_Sitemap_Changefreq
- "The input is not a valid sitemap changefreq" => "L'entrée n'est pas une valeur de fréquence de changement de sitemap valide",
+ "The input is not a valid sitemap changefreq" => "L'entrée n'est pas une valeur de fréquence de sitemap valide",
"Invalid type given. String expected" => "Type invalide. Chaîne attendue",
// Zend_Validator_Sitemap_Lastmod
- "The input is not a valid sitemap lastmod" => "L'entrée n'est pas une date de dernière modification de sitemap valide",
+ "The input is not a valid sitemap lastmod" => "L'entrée n'est pas une date de modification de sitemap valide",
"Invalid type given. String expected" => "Type invalide. Chaîne attendue",
// Zend_Validator_Sitemap_Loc
@@ -267,11 +267,11 @@
// Zend_Validator_Step
"Invalid value given. Scalar expected" => "Type invalide. Scalaire attendu",
- "The input is not a valid step" => "L'entrée n'est pas un intervalle valide",
+ "The input is not a valid step" => "L'entrée n'est pas un multiple valide",
// Zend_Validator_StringLength
"Invalid type given. String expected" => "Type invalide. Chaîne attendue",
- "The input is less than %min% characters long" => "L'entrée contient moins de %min% caractères",
+ "The input is less than %min% characters long" => "L'entrée conteint moins de %min% caractères",
"The input is more than %max% characters long" => "L'entrée contient plus de %max% caractères",
// Zend_Validator_Uri
View
94 tests/ZendTest/I18n/Translator/Loader/IniTest.php
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Zend Framework (http://framework.zend.com/)
+ *
+ * @link http://github.com/zendframework/zf2 for the canonical source repository
+ * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @package Zend_I18n
+ */
+
+namespace ZendTest\I18n\Translator\Loader;
+
+use PHPUnit_Framework_TestCase as TestCase;
+use Locale;
+use Zend\I18n\Translator\Loader\Ini as IniLoader;
+
+class IniTest extends TestCase
+{
+ protected $testFilesDir;
+ protected $originalLocale;
+
+ public function setUp()
+ {
+ $this->testFilesDir = realpath(__DIR__ . '/../_files');
+ }
+
+ public function testLoaderFailsToLoadMissingFile()
+ {
+ $loader = new IniLoader();
+ $this->setExpectedException('Zend\I18n\Exception\InvalidArgumentException', 'Could not open file');
+ $loader->load('en_EN', 'missing');
+ }
+
+ public function testLoaderLoadsEmptyFile()
+ {
+ $loader = new IniLoader();
+ $textDomain = $loader->load('en_EN', $this->testFilesDir . '/translation_empty.ini');
+ $this->assertInstanceOf('Zend\I18n\Translator\TextDomain', $textDomain);
+ }
+
+ public function testLoaderFailsToLoadNonArray()
+ {
+ $loader = new IniLoader();
+ $this->setExpectedException('Zend\I18n\Exception\InvalidArgumentException',
+ 'Each INI row must be an array with message and translation');
+ $loader->load('en_EN', $this->testFilesDir . '/failed.ini');
+ }
+
+ public function testLoaderFailsToLoadBadSyntax()
+ {
+ $loader = new IniLoader();
+ $this->setExpectedException('Zend\I18n\Exception\InvalidArgumentException',
+ 'Each INI row must be an array with message and translation');
+ $loader->load('en_EN', $this->testFilesDir . '/failed_syntax.ini');
+ }
+
+ public function testLoaderReturnsValidTextDomain()
+ {
+ $loader = new IniLoader();
+ $textDomain = $loader->load('en_EN', $this->testFilesDir . '/translation_en.ini');
+
+ $this->assertEquals('Message 1 (en)', $textDomain['Message 1']);
+ $this->assertEquals('Message 4 (en)', $textDomain['Message 4']);
+ }
+
+ public function testLoaderReturnsValidTextDomainWithFileWithoutPlural()
+ {
+ $loader = new IniLoader();
+ $textDomain = $loader->load('en_EN', $this->testFilesDir . '/translation_en_without_plural.ini');
+
+ $this->assertEquals('Message 1 (en)', $textDomain['Message 1']);
+ $this->assertEquals('Message 4 (en)', $textDomain['Message 4']);
+ }
+
+ public function testLoaderReturnsValidTextDomainWithSimpleSyntax()
+ {
+ $loader = new IniLoader();
+ $textDomain = $loader->load('en_EN', $this->testFilesDir . '/translation_en_simple_syntax.ini');
+
+ $this->assertEquals('Message 1 (en)', $textDomain['Message 1']);
+ $this->assertEquals('Message 4 (en)', $textDomain['Message 4']);
+ }
+
+ public function testLoaderLoadsPluralRules()
+ {
+ $loader = new IniLoader();
+ $textDomain = $loader->load('en_EN', $this->testFilesDir . '/translation_en.ini');
+
+ $this->assertEquals(2, $textDomain->getPluralRule()->evaluate(0));
+ $this->assertEquals(0, $textDomain->getPluralRule()->evaluate(1));
+ $this->assertEquals(1, $textDomain->getPluralRule()->evaluate(2));
+ $this->assertEquals(2, $textDomain->getPluralRule()->evaluate(10));
+ }
+}
View
1 tests/ZendTest/I18n/Translator/_files/failed.ini
@@ -0,0 +1 @@
+identifier1 = "Message 1"
View
1 tests/ZendTest/I18n/Translator/_files/failed_syntax.ini
@@ -0,0 +1 @@
+identifier1[] = "Message 1"
View
0 tests/ZendTest/I18n/Translator/_files/translation_empty.ini
No changes.
View
26 tests/ZendTest/I18n/Translator/_files/translation_en.ini
@@ -0,0 +1,26 @@
+[plural]
+plural_forms = 'nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);'
+
+[translation]
+identifier1.message = "Message 1"
+identifier1.translation = "Message 1 (en)"
+
+identifier2.message = "Message 2"
+identifier2.translation = "Message 2 (en)"
+
+identifier3.message = "Message 3"
+identifier3.translation = "Message 3 (en)"
+
+identifier4.message = "Message 4"
+identifier4.translation = "Message 4 (en)"
+
+identifier5.message = "Message 5"
+identifier5.translation.0 = "Message 5 (en) Plural 0"
+identifier5.translation.1 = "Message 5 (en) Plural 1"
+identifier5.translation.2 = "Message 5 (en) Plural 2"
+
+identifier6.message = "Cooking furniture"
+identifier6.translation = "Küchen Möbel (en)"
+
+identifier7.message = "Küchen Möbel"
+identifier7.translation = "Cooking furniture (en)"
View
26 tests/ZendTest/I18n/Translator/_files/translation_en_simple_syntax.ini
@@ -0,0 +1,26 @@
+[plural]
+plural_forms = 'nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);'
+
+[translation]
+identifier1[] = "Message 1"
+identifier1[] = "Message 1 (en)"
+
+identifier2[] = "Message 2"
+identifier2[] = "Message 2 (en)"
+
+identifier3[] = "Message 3"
+identifier3[] = "Message 3 (en)"
+
+identifier4[] = "Message 4"
+identifier4[] = "Message 4 (en)"
+
+identifier5.message = "Message 5"
+identifier5.translation.0 = "Message 5 (en) Plural 0"
+identifier5.translation.1 = "Message 5 (en) Plural 1"
+identifier5.translation.2 = "Message 5 (en) Plural 2"
+
+identifier6[] = "Cooking furniture"
+identifier6[] = "Küchen Möbel (en)"
+
+identifier7[] = "Küchen Möbel"
+identifier7[] = "Cooking furniture (en)"
View
22 tests/ZendTest/I18n/Translator/_files/translation_en_without_plural.ini
@@ -0,0 +1,22 @@
+identifier1.message = "Message 1"
+identifier1.translation = "Message 1 (en)"
+
+identifier2.message = "Message 2"
+identifier2.translation = "Message 2 (en)"
+
+identifier3.message = "Message 3"
+identifier3.translation = "Message 3 (en)"
+
+identifier4.message = "Message 4"
+identifier4.translation = "Message 4 (en)"
+
+identifier5.message = "Message 5"
+identifier5.translation.0 = "Message 5 (en) Plural 0"
+identifier5.translation.1 = "Message 5 (en) Plural 1"
+identifier5.translation.2 = "Message 5 (en) Plural 2"
+
+identifier6.message = "Cooking furniture"
+identifier6.translation = "Küchen Möbel (en)"
+
+identifier7.message = "Küchen Möbel"
+identifier7.translation = "Cooking furniture (en)"

0 comments on commit ad6a44d

Please sign in to comment.
Something went wrong with that request. Please try again.