فهرست منبع

[Translation] Added flatten method on ArrayLoader

This allows the translations to be deeply nested arrays that will be flattened, allowing for namespacing of translations easily.

The following:
  'key' => array('key2' => array('key3' => 'value'))
Becomes:
  'key.key2.key3' => 'value'

This isn't applied to Xliff since it does not make sense within the scope of the XLIFF standard
Jordi Boggiano 14 سال پیش
والد
کامیت
3cbc99c180

+ 33 - 0
src/Symfony/Component/Translation/Loader/ArrayLoader.php

@@ -25,9 +25,42 @@ class ArrayLoader implements LoaderInterface
      */
     public function load($resource, $locale, $domain = 'messages')
     {
+        $catalogue = $this->flatten($resource);
         $catalogue = new MessageCatalogue($locale);
         $catalogue->addMessages($resource, $domain);
 
         return $catalogue;
     }
+
+    /**
+     * Flattens an nested array of translations
+     *
+     * The scheme used is:
+     *   'key' => array('key2' => array('key3' => 'value'))
+     * Becomes:
+     *   'key.key2.key3' => 'value'
+     *
+     * This function takes an array by reference and will modify it
+     *
+     * @param array $messages the array that will be flattened
+     * @param array $subnode current subnode being parsed, used internally for recursive calls
+     * @param string $path current path being parsed, used internally for recursive calls
+     */
+    protected function flatten(array &$messages, array $subnode = null, $path = null)
+    {
+        if ($subnode === null) {
+            $subnode =& $messages;
+        }
+        foreach ($subnode as $key => $value) {
+            if (is_array($value)) {
+                $nodePath = $path ? $path.'.'.$key : $key;
+                $this->flatten($messages, $value, $nodePath);
+                if ($path === null) {
+                    unset($messages[$key]);
+                }
+            } elseif ($path !== null) {
+                $messages[$path.'.'.$key] = $value;
+            }
+        }
+    }
 }

+ 4 - 4
src/Symfony/Component/Translation/Loader/PhpFileLoader.php

@@ -2,7 +2,6 @@
 
 namespace Symfony\Component\Translation\Loader;
 
-use Symfony\Component\Translation\MessageCatalogue;
 use Symfony\Component\Translation\Resource\FileResource;
 
 /*
@@ -19,15 +18,16 @@ use Symfony\Component\Translation\Resource\FileResource;
  *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  */
-class PhpFileLoader implements LoaderInterface
+class PhpFileLoader extends ArrayLoader implements LoaderInterface
 {
     /**
      * {@inheritdoc}
      */
     public function load($resource, $locale, $domain = 'messages')
     {
-        $catalogue = new MessageCatalogue($locale);
-        $catalogue->addMessages(require($resource), $domain);
+        $messages = require($resource);
+
+        $catalogue = parent::load($messages, $locale, $domain);
         $catalogue->addResource(new FileResource($resource));
 
         return $catalogue;

+ 2 - 4
src/Symfony/Component/Translation/Loader/YamlFileLoader.php

@@ -2,7 +2,6 @@
 
 namespace Symfony\Component\Translation\Loader;
 
-use Symfony\Component\Translation\MessageCatalogue;
 use Symfony\Component\Translation\Resource\FileResource;
 use Symfony\Component\Yaml\Yaml;
 
@@ -20,7 +19,7 @@ use Symfony\Component\Yaml\Yaml;
  *
  * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  */
-class YamlFileLoader implements LoaderInterface
+class YamlFileLoader extends ArrayLoader implements LoaderInterface
 {
     /**
      * {@inheritdoc}
@@ -29,8 +28,7 @@ class YamlFileLoader implements LoaderInterface
     {
         $messages = Yaml::load($resource);
 
-        $catalogue = new MessageCatalogue($locale);
-        $catalogue->addMessages($messages, $domain);
+        $catalogue = parent::load($messages, $locale, $domain);
         $catalogue->addResource(new FileResource($resource));
 
         return $catalogue;

+ 35 - 0
tests/Symfony/Tests/Component/Translation/TranslatorTest.php

@@ -74,6 +74,18 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($expected, $translator->trans($id, $parameters, $domain, $locale));
     }
 
+    /**
+     * @dataProvider getFlattenedTransTests
+     */
+    public function testFlattenedTrans($expected, $messages, $id)
+    {
+        $translator = new Translator('en', new MessageSelector());
+        $translator->addLoader('array', new ArrayLoader());
+        $translator->addResource('array', $messages, 'fr', '');
+
+        $this->assertEquals($expected, $translator->trans($id, array(), '', 'fr'));
+    }
+
     /**
      * @dataProvider getTransChoiceTests
      */
@@ -94,6 +106,29 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase
         );
     }
 
+    public function getFlattenedTransTests()
+    {
+        $messages = array(
+            'symfony2' => array(
+                'is' => array(
+                    'great' => 'Symfony2 est super!'
+                )
+            ),
+            'foo' => array(
+                'bar' => array(
+                    'baz' => 'Foo Bar Baz'
+                ),
+                'baz' => 'Foo Baz',
+            ),
+        );
+
+        return array(
+            array('Symfony2 est super!', $messages, 'symfony2.is.great'),
+            array('Foo Bar Baz', $messages, 'foo.bar.baz'),
+            array('Foo Baz', $messages, 'foo.baz'),
+        );
+    }
+
     public function getTransChoiceTests()
     {
         return array(