瀏覽代碼

added an IdentityTranslator to make it possible to always relies on the translator service, even if none is configured

Fabien Potencier 14 年之前
父節點
當前提交
707205410e

+ 33 - 26
src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

@@ -100,9 +100,7 @@ class FrameworkExtension extends Extension
             $this->registerUserConfiguration($config, $container);
         }
 
-        if (array_key_exists('translator', $config)) {
-            $this->registerTranslatorConfiguration($config, $container);
-        }
+        $this->registerTranslatorConfiguration($config, $container);
 
         $this->addCompiledClasses($container, array(
             'Symfony\\Component\\HttpFoundation\\ParameterBag',
@@ -234,40 +232,49 @@ class FrameworkExtension extends Extension
      */
     protected function registerTranslatorConfiguration($config, ContainerBuilder $container)
     {
-        $config = $config['translator'];
+        $first = false;
+        if (!$container->hasDefinition('translator')) {
+            $first = true;
+            $loader = new XmlFileLoader($container, array(__DIR__.'/../Resources/config', __DIR__.'/Resources/config'));
+            $loader->load('translation.xml');
+        }
+
+        $config = array_key_exists('translator', $config) ? $config['translator'] : array();
         if (!is_array($config)) {
             $config = array();
         }
 
-        if (!$container->hasDefinition('translator')) {
-            $loader = new XmlFileLoader($container, array(__DIR__.'/../Resources/config', __DIR__.'/Resources/config'));
-            $loader->load('translation.xml');
+        if (!isset($config['translator']['enabled']) || $config['translator']['enabled']) {
+            // use the "real" translator
+            $container->setDefinition('translator', $container->findDefinition('translator.real'));
 
-            // translation directories
-            $dirs = array();
-            foreach (array_reverse($container->getParameter('kernel.bundles')) as $bundle) {
-                $reflection = new \ReflectionClass($bundle);
-                if (is_dir($dir = dirname($reflection->getFilename()).'/Resources/translations')) {
+            if ($first) {
+                // translation directories
+                $dirs = array();
+                foreach (array_reverse($container->getParameter('kernel.bundles')) as $bundle) {
+                    $reflection = new \ReflectionClass($bundle);
+                    if (is_dir($dir = dirname($reflection->getFilename()).'/Resources/translations')) {
+                        $dirs[] = $dir;
+                    }
+                }
+                if (is_dir($dir = $container->getParameter('kernel.root_dir').'/translations')) {
                     $dirs[] = $dir;
                 }
-            }
-            if (is_dir($dir = $container->getParameter('kernel.root_dir').'/translations')) {
-                $dirs[] = $dir;
-            }
 
-            // translation resources
-            $resources = array();
-            if ($dirs) {
-                $finder = new Finder();
-                $finder->files()->filter(function (\SplFileInfo $file) { return 2 === substr_count($file->getBasename(), '.'); })->in($dirs);
-                foreach ($finder as $file) {
-                    // filename is domain.locale.format
-                    list($domain, $locale, $format) = explode('.', $file->getBasename());
+                // translation resources
+                $resources = array();
+                if ($dirs) {
+                    $finder = new Finder();
+                    $finder->files()->filter(function (\SplFileInfo $file) { return 2 === substr_count($file->getBasename(), '.'); })->in($dirs);
+                    foreach ($finder as $file) {
+                        // filename is domain.locale.format
+                        list($domain, $locale, $format) = explode('.', $file->getBasename());
 
-                    $resources[] = array($format, (string) $file, $locale, $domain);
+                        $resources[] = array($format, (string) $file, $locale, $domain);
+                    }
                 }
+                $container->setParameter('translation.resources', $resources);
             }
-            $container->setParameter('translation.resources', $resources);
         }
 
         if (array_key_exists('fallback', $config)) {

+ 10 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml

@@ -6,14 +6,17 @@
 
     <parameters>
         <parameter key="translator.class">Symfony\Bundle\FrameworkBundle\Translation\Translator</parameter>
+        <parameter key="translator.identity.class">Symfony\Component\Translation\IdentityTranslator</parameter>
+        <parameter key="translator.selector.class">Symfony\Component\Translation\MessageSelector</parameter>
         <parameter key="translation.loader.php.class">Symfony\Component\Translation\Loader\PhpFileLoader</parameter>
         <parameter key="translation.loader.xliff.class">Symfony\Component\Translation\Loader\XliffFileLoader</parameter>
         <parameter key="translator.fallback_locale">en</parameter>
     </parameters>
 
     <services>
-        <service id="translator" class="%translator.class%">
+        <service id="translator.real" class="%translator.class%">
             <argument type="service" id="service_container" />
+            <argument type="service" id="translator.selector" />
             <argument type="collection">
                 <argument key="cache_dir">%kernel.cache_dir%/translations</argument>
                 <argument key="debug">%kernel.debug%</argument>
@@ -22,6 +25,12 @@
             <call method="setFallbackLocale"><argument>%translator.fallback_locale%</argument></call>
         </service>
 
+        <service id="translator" class="%translator.identity.class%">
+            <argument type="service" id="translator.selector" />
+        </service>
+
+        <service id="translator.selector" class="%translator.selector.class%" />
+
         <service id="translation.loader.php" class="%translation.loader.php.class%">
             <tag name="translation.loader" alias="php" />
         </service>

+ 2 - 1
src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

@@ -53,8 +53,9 @@ class FrameworkExtensionTest extends TestCase
                 'Symfony\\Framework' => __DIR__ . '/../../../Framework',
             ),
             'kernel.bundles'          => array(
-                'FrameworkBundle',
+                'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle',
             ),
+            'kernel.root_dir'         => __DIR__,
             'kernel.debug'            => false,
             'kernel.compiled_classes' => array(),
         )));

+ 4 - 2
src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php

@@ -4,6 +4,7 @@ namespace Symfony\Bundle\FrameworkBundle\Translation;
 
 use Symfony\Component\Translation\Translator as BaseTranslator;
 use Symfony\Component\Translation\Loader\LoaderInterface;
+use Symfony\Component\Translation\MessageSelector;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Session;
 
@@ -35,13 +36,14 @@ class Translator extends BaseTranslator
      *   * debug:     Whether to enable debugging or not (false by default)
      *
      * @param ContainerInterface $container A ContainerInterface instance
+     * @param MessageSelector    $selector  The message selector for pluralization
      * @param array              $options   An array of options
      * @param Session            $session   A Session instance
      */
-    public function __construct(ContainerInterface $container, array $options = array(), Session $session = null)
+    public function __construct(ContainerInterface $container, MessageSelector $selector, array $options = array(), Session $session = null)
     {
         if (null !== $session) {
-            parent::__construct($session->getLocale());
+            parent::__construct($session->getLocale(), $selector);
         }
 
         $this->container = $container;

+ 55 - 0
src/Symfony/Component/Translation/IdentityTranslator.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace Symfony\Component\Translation;
+
+/*
+ * This file is part of the Symfony framework.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * IdentityTranslator does not translate anything.
+ *
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ */
+class IdentityTranslator implements TranslatorInterface
+{
+    protected $selector;
+
+    /**
+     * Constructor.
+     *
+     * @param MessageSelector $selector The message selector for pluralization
+     */
+    public function __construct(MessageSelector $selector)
+    {
+        $this->selector = $selector;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setLocale($locale)
+    {
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function trans($id, array $parameters = array(), $domain = 'messages', $locale = null)
+    {
+        return strtr($id, $parameters);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function transChoice($id, $number, array $parameters = array(), $domain = 'messages', $locale = null)
+    {
+        return strtr($this->selector->choose($id, (int) $number, $locale), $parameters);
+    }
+}

+ 52 - 0
src/Symfony/Component/Translation/MessageSelector.php

@@ -0,0 +1,52 @@
+<?php
+
+namespace Symfony\Component\Translation;
+
+/*
+ * This file is part of the Symfony framework.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * This source file is subject to the MIT license that is bundled
+ * with this source code in the file LICENSE.
+ */
+
+/**
+ * MessageSelector.
+ *
+ * @author Fabien Potencier <fabien.potencier@symfony-project.com>
+ */
+class MessageSelector
+{
+    public function choose($message, $number, $locale)
+    {
+        $parts = explode('|', $message);
+        $explicitRules = array();
+        $standardRules = array();
+        foreach ($parts as $part) {
+            $part = trim($part);
+
+            if (preg_match('/^(?<range>'.Range::getRangeRegexp().')\s+(?<message>.+?)$/x', $part, $matches)) {
+                $explicitRules[$matches['range']] = $matches['message'];
+            } elseif (preg_match('/^\w+\: +(.+)$/', $part, $matches)) {
+                $standardRules[] = $matches[1];
+            } else {
+                $standardRules[] = $part;
+            }
+        }
+
+        // try to match an explicit rule, then fallback to the standard ones
+        foreach ($explicitRules as $range => $m) {
+            if (Range::test($number, $range)) {
+                return $m;
+            }
+        }
+
+        $position = PluralizationRules::get($number, $locale);
+        if (!isset($standardRules[$position])) {
+            throw new \InvalidArgumentException('Unable to choose a translation.');
+        }
+
+        return $standardRules[$position];
+    }
+}

+ 6 - 35
src/Symfony/Component/Translation/Translator.php

@@ -25,15 +25,18 @@ class Translator implements TranslatorInterface
     protected $fallbackLocale;
     protected $loaders;
     protected $resources;
+    protected $selector;
 
     /**
      * Constructor.
      *
-     * @param string $locale The locale
+     * @param string          $locale   The locale
+     * @param MessageSelector $selector The message selector for pluralization
      */
-    public function __construct($locale = null)
+    public function __construct($locale = null, MessageSelector $selector)
     {
         $this->locale = $locale;
+        $this->selector = $selector;
         $this->loaders = array();
         $this->resources = array();
         $this->catalogues = array();
@@ -119,39 +122,7 @@ class Translator implements TranslatorInterface
             $this->loadCatalogue($locale);
         }
 
-        return strtr($this->chooseMessage($this->catalogues[$locale]->getMessage($id, $domain), (int) $number, $locale), $parameters);
-    }
-
-    protected function chooseMessage($message, $number, $locale)
-    {
-        $parts = explode('|', $message);
-        $explicitRules = array();
-        $standardRules = array();
-        foreach ($parts as $part) {
-            $part = trim($part);
-
-            if (preg_match('/^(?<range>'.Range::getRangeRegexp().')\s+(?<message>.+?)$/x', $part, $matches)) {
-                $explicitRules[$matches['range']] = $matches['message'];
-            } elseif (preg_match('/^\w+\: +(.+)$/', $part, $matches)) {
-                $standardRules[] = $matches[1];
-            } else {
-                $standardRules[] = $part;
-            }
-        }
-
-        // try to match an explicit rule, then fallback to the standard ones
-        foreach ($explicitRules as $range => $m) {
-            if (Range::test($number, $range)) {
-                return $m;
-            }
-        }
-
-        $position = PluralizationRules::get($number, $locale);
-        if (!isset($standardRules[$position])) {
-            throw new \InvalidArgumentException('Unable to choose a translation.');
-        }
-
-        return $standardRules[$position];
+        return strtr($this->selector->choose($this->catalogues[$locale]->getMessage($id, $domain), (int) $number, $locale), $parameters);
     }
 
     protected function loadCatalogue($locale)

+ 3 - 2
tests/Symfony/Tests/Component/Translation/TranslatorTest.php

@@ -12,6 +12,7 @@
 namespace Symfony\Tests\Component\Translation;
 
 use Symfony\Component\Translation\Translator;
+use Symfony\Component\Translation\MessageSelector;
 use Symfony\Component\Translation\Loader\ArrayLoader;
 
 class TranslatorTest extends \PHPUnit_Framework_TestCase
@@ -21,7 +22,7 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase
      */
     public function testTrans($expected, $id, $translation, $parameters, $locale, $domain)
     {
-        $translator = new Translator();
+        $translator = new Translator('en', new MessageSelector());
         $translator->addLoader('array', new ArrayLoader());
         $translator->addResource('array', array($id => $translation), $locale, $domain);
 
@@ -33,7 +34,7 @@ class TranslatorTest extends \PHPUnit_Framework_TestCase
      */
     public function testTransChoice($expected, $id, $translation, $number, $parameters, $locale, $domain)
     {
-        $translator = new Translator();
+        $translator = new Translator('en', new MessageSelector());
         $translator->addLoader('array', new ArrayLoader());
         $translator->addResource('array', array($id => $translation), $locale, $domain);