diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md
index f5ae0f7b23..2c80252b5b 100644
--- a/UPGRADE-3.4.md
+++ b/UPGRADE-3.4.md
@@ -239,6 +239,27 @@ Translation
and will be removed in 4.0, use `Symfony\Component\Translation\Writer\TranslationWriter::write`
instead.
+ * Passing a `Symfony\Component\Translation\MessageSelector` to `Translator` has been
+ deprecated. You should pass a message formatter instead
+
+ Before:
+
+ ```php
+ use Symfony\Component\Translation\Translator;
+ use Symfony\Component\Translation\MessageSelector;
+
+ $translator = new Translator('fr_FR', new MessageSelector());
+ ```
+
+ After:
+
+ ```php
+ use Symfony\Component\Translation\Translator;
+ use Symfony\Component\Translation\Formatter\MessageFormatter;
+
+ $translator = new Translator('fr_FR', new MessageFormatter());
+ ```
+
TwigBridge
----------
diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md
index c6e11a198f..9f8017c47e 100644
--- a/UPGRADE-4.0.md
+++ b/UPGRADE-4.0.md
@@ -648,6 +648,9 @@ Translation
* Removed `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations`,
use `Symfony\Component\Translation\Writer\TranslationWriter::write` instead.
+ * Removed support for passing `Symfony\Component\Translation\MessageSelector` as a second argument to the
+ `Translator::__construct()`. You should pass an instance of `Symfony\Component\Translation\Formatter\MessageFormatterInterface` instead.
+
TwigBundle
----------
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php
index 36016d7f49..b20e0c3905 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php
@@ -14,7 +14,6 @@ namespace Symfony\Bridge\Twig\Tests\Extension;
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Component\Translation\Translator;
-use Symfony\Component\Translation\MessageSelector;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Twig\Environment;
use Twig\Loader\ArrayLoader as TwigArrayLoader;
@@ -37,7 +36,7 @@ class TranslationExtensionTest extends TestCase
echo $template."\n";
$loader = new TwigArrayLoader(array('index' => $template));
$twig = new Environment($loader, array('debug' => true, 'cache' => false));
- $twig->addExtension(new TranslationExtension(new Translator('en', new MessageSelector())));
+ $twig->addExtension(new TranslationExtension(new Translator('en')));
echo $twig->compile($twig->parse($twig->tokenize($twig->getLoader()->getSourceContext('index'))))."\n\n";
$this->assertEquals($expected, $this->getTemplate($template)->render($variables));
@@ -139,7 +138,7 @@ class TranslationExtensionTest extends TestCase
',
);
- $translator = new Translator('en', new MessageSelector());
+ $translator = new Translator('en');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('foo' => 'foo (messages)'), 'en');
$translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom');
@@ -172,7 +171,7 @@ class TranslationExtensionTest extends TestCase
',
);
- $translator = new Translator('en', new MessageSelector());
+ $translator = new Translator('en');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('foo' => 'foo (messages)'), 'en');
$translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom');
@@ -187,7 +186,7 @@ class TranslationExtensionTest extends TestCase
protected function getTemplate($template, $translator = null)
{
if (null === $translator) {
- $translator = new Translator('en', new MessageSelector());
+ $translator = new Translator('en');
}
if (is_array($template)) {
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index 6b98ef7cd4..fab5ac3446 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -669,6 +669,7 @@ class Configuration implements ConfigurationInterface
->defaultValue(array('en'))
->end()
->booleanNode('logging')->defaultValue($this->debug)->end()
+ ->scalarNode('formatter')->defaultValue('translator.formatter.default')->end()
->arrayNode('paths')
->prototype('scalar')->end()
->end()
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 72d66442c6..9b3a071168 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -1075,6 +1075,7 @@ class FrameworkExtension extends Extension
// Use the "real" translator instead of the identity default
$container->setAlias('translator', 'translator.default');
+ $container->setAlias('translator.formatter', new Alias($config['formatter'], false));
$translator = $container->findDefinition('translator.default');
$translator->addMethodCall('setFallbackLocales', array($config['fallbacks']));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
index 481c469e36..f63f937230 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -184,6 +184,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
index cfe05f5148..d8c8f1e030 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
@@ -9,7 +9,7 @@
-
+
%kernel.default_locale%
@@ -28,6 +28,10 @@
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
index 1835625da8..e4e6f0f2a7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
@@ -255,6 +255,7 @@ class ConfigurationTest extends TestCase
'enabled' => !class_exists(FullStack::class),
'fallbacks' => array('en'),
'logging' => true,
+ 'formatter' => 'translator.formatter.default',
'paths' => array(),
),
'validation' => array(
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
index 6d710a76e8..d2d0f878f6 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
@@ -14,9 +14,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Translation;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
+use Symfony\Component\Translation\Formatter\MessageFormatter;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Filesystem\Filesystem;
-use Symfony\Component\Translation\MessageSelector;
class TranslatorTest extends TestCase
{
@@ -149,7 +149,7 @@ class TranslatorTest extends TestCase
->with('kernel.default_locale')
->will($this->returnValue('en'))
;
- $translator = new Translator($container, new MessageSelector());
+ $translator = new Translator($container, new MessageFormatter());
$this->assertSame('en', $translator->getLocale());
}
@@ -162,7 +162,7 @@ class TranslatorTest extends TestCase
public function testGetDefaultLocaleOmittingLocaleWithPsrContainer()
{
$container = $this->getMockBuilder(ContainerInterface::class)->getMock();
- $translator = new Translator($container, new MessageSelector());
+ $translator = new Translator($container, new MessageFormatter());
}
/**
@@ -277,7 +277,7 @@ class TranslatorTest extends TestCase
public function testGetDefaultLocale()
{
$container = $this->getMockBuilder(ContainerInterface::class)->getMock();
- $translator = new Translator($container, new MessageSelector(), 'en');
+ $translator = new Translator($container, new MessageFormatter(), 'en');
$this->assertSame('en', $translator->getLocale());
}
@@ -290,7 +290,7 @@ class TranslatorTest extends TestCase
{
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
- (new Translator($container, new MessageSelector(), 'en', array(), array('foo' => 'bar')));
+ (new Translator($container, new MessageFormatter(), 'en', array(), array('foo' => 'bar')));
}
/** @dataProvider getDebugModeAndCacheDirCombinations */
@@ -468,7 +468,7 @@ class TranslatorTest extends TestCase
if (null === $defaultLocale) {
return new $translatorClass(
$this->getContainer($loader),
- new MessageSelector(),
+ new MessageFormatter(),
array($loaderFomat => array($loaderFomat)),
$options
);
@@ -476,7 +476,7 @@ class TranslatorTest extends TestCase
return new $translatorClass(
$this->getContainer($loader),
- new MessageSelector(),
+ new MessageFormatter(),
$defaultLocale,
array($loaderFomat => array($loaderFomat)),
$options
diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
index d18a3b81f0..2b41d5af61 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
@@ -15,8 +15,8 @@ use Psr\Container\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
use Symfony\Component\Translation\Translator as BaseTranslator;
-use Symfony\Component\Translation\MessageSelector;
use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
/**
* Translator.
@@ -56,15 +56,15 @@ class Translator extends BaseTranslator implements WarmableInterface
* * debug: Whether to enable debugging or not (false by default)
* * resource_files: List of translation resources available grouped by locale.
*
- * @param ContainerInterface $container A ContainerInterface instance
- * @param MessageSelector $selector The message selector for pluralization
- * @param string $defaultLocale
- * @param array $loaderIds An array of loader Ids
- * @param array $options An array of options
+ * @param ContainerInterface $container A ContainerInterface instance
+ * @param MessageFormatterInterface $formatter The message formatter
+ * @param string $defaultLocale
+ * @param array $loaderIds An array of loader Ids
+ * @param array $options An array of options
*
* @throws InvalidArgumentException
*/
- public function __construct(ContainerInterface $container, MessageSelector $selector, $defaultLocale = null, array $loaderIds = array(), array $options = array())
+ public function __construct(ContainerInterface $container, $formatter, $defaultLocale = null, array $loaderIds = array(), array $options = array())
{
// BC 3.x, to be removed in 4.0 along with the $defaultLocale default value
if (is_array($defaultLocale) || 3 > func_num_args()) {
@@ -90,7 +90,7 @@ class Translator extends BaseTranslator implements WarmableInterface
$this->resourceLocales = array_keys($this->options['resource_files']);
$this->addResourceFiles($this->options['resource_files']);
- parent::__construct($defaultLocale, $selector, $this->options['cache_dir'], $this->options['debug']);
+ parent::__construct($defaultLocale, $formatter, $this->options['cache_dir'], $this->options['debug']);
}
/**
diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md
index cdd11cb91b..24753841ca 100644
--- a/src/Symfony/Component/Translation/CHANGELOG.md
+++ b/src/Symfony/Component/Translation/CHANGELOG.md
@@ -12,6 +12,7 @@ CHANGELOG
* Improved Xliff 2.0 loader to load `` section.
* Added `TranslationWriterInterface`
* Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write`
+ * added support for adding custom message formatter and decoupling the default one.
3.2.0
-----
diff --git a/src/Symfony/Component/Translation/Formatter/ChoiceMessageFormatterInterface.php b/src/Symfony/Component/Translation/Formatter/ChoiceMessageFormatterInterface.php
new file mode 100644
index 0000000000..92acbcafe2
--- /dev/null
+++ b/src/Symfony/Component/Translation/Formatter/ChoiceMessageFormatterInterface.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+/**
+ * @author Abdellatif Ait boudad
+ */
+interface ChoiceMessageFormatterInterface
+{
+ /**
+ * Formats a localized message pattern with given arguments.
+ *
+ * @param string $message The message (may also be an object that can be cast to string)
+ * @param int $number The number to use to find the indice of the message
+ * @param string $locale The message locale
+ * @param array $parameters An array of parameters for the message
+ *
+ * @return string
+ */
+ public function choiceFormat($message, $number, $locale, array $parameters = array());
+}
diff --git a/src/Symfony/Component/Translation/Formatter/MessageFormatter.php b/src/Symfony/Component/Translation/Formatter/MessageFormatter.php
new file mode 100644
index 0000000000..e174be36c3
--- /dev/null
+++ b/src/Symfony/Component/Translation/Formatter/MessageFormatter.php
@@ -0,0 +1,48 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+use Symfony\Component\Translation\MessageSelector;
+
+/**
+ * @author Abdellatif Ait boudad
+ */
+class MessageFormatter implements MessageFormatterInterface, ChoiceMessageFormatterInterface
+{
+ private $selector;
+
+ /**
+ * @param MessageSelector|null $selector The message selector for pluralization
+ */
+ public function __construct(MessageSelector $selector = null)
+ {
+ $this->selector = $selector ?: new MessageSelector();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function format($message, $locale, array $parameters = array())
+ {
+ return strtr($message, $parameters);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function choiceFormat($message, $number, $locale, array $parameters = array())
+ {
+ $parameters = array_merge(array('%count%' => $number), $parameters);
+
+ return $this->format($this->selector->choose($message, (int) $number, $locale), $locale, $parameters);
+ }
+}
diff --git a/src/Symfony/Component/Translation/Formatter/MessageFormatterInterface.php b/src/Symfony/Component/Translation/Formatter/MessageFormatterInterface.php
new file mode 100644
index 0000000000..86937fb2f0
--- /dev/null
+++ b/src/Symfony/Component/Translation/Formatter/MessageFormatterInterface.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Formatter;
+
+/**
+ * @author Guilherme Blanco
+ * @author Abdellatif Ait boudad
+ */
+interface MessageFormatterInterface
+{
+ /**
+ * Formats a localized message pattern with given arguments.
+ *
+ * @param string $message The message (may also be an object that can be cast to string)
+ * @param string $locale The message locale
+ * @param array $parameters An array of parameters for the message
+ *
+ * @return string
+ */
+ public function format($message, $locale, array $parameters = array());
+}
diff --git a/src/Symfony/Component/Translation/Tests/Formatter/MessageFormatterTest.php b/src/Symfony/Component/Translation/Tests/Formatter/MessageFormatterTest.php
new file mode 100644
index 0000000000..1fa736e7e3
--- /dev/null
+++ b/src/Symfony/Component/Translation/Tests/Formatter/MessageFormatterTest.php
@@ -0,0 +1,82 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Translation\Tests\Formatter;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Translation\Formatter\MessageFormatter;
+
+class MessageFormatterTest extends TestCase
+{
+ /**
+ * @dataProvider getTransMessages
+ */
+ public function testFormat($expected, $message, $parameters = array())
+ {
+ $this->assertEquals($expected, $this->getMessageFormatter()->format($message, 'en', $parameters));
+ }
+
+ /**
+ * @dataProvider getTransChoiceMessages
+ */
+ public function testFormatPlural($expected, $message, $number, $parameters)
+ {
+ $this->assertEquals($expected, $this->getMessageFormatter()->choiceFormat($message, $number, 'fr', $parameters));
+ }
+
+ public function getTransMessages()
+ {
+ return array(
+ array(
+ 'There is one apple',
+ 'There is one apple',
+ ),
+ array(
+ 'There are 5 apples',
+ 'There are %count% apples',
+ array('%count%' => 5),
+ ),
+ array(
+ 'There are 5 apples',
+ 'There are {{count}} apples',
+ array('{{count}}' => 5),
+ ),
+ );
+ }
+
+ public function getTransChoiceMessages()
+ {
+ return array(
+ array('Il y a 0 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0)),
+ array('Il y a 1 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 1, array('%count%' => 1)),
+ array('Il y a 10 pommes', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 10, array('%count%' => 10)),
+
+ array('Il y a 0 pomme', 'Il y a %count% pomme|Il y a %count% pommes', 0, array('%count%' => 0)),
+ array('Il y a 1 pomme', 'Il y a %count% pomme|Il y a %count% pommes', 1, array('%count%' => 1)),
+ array('Il y a 10 pommes', 'Il y a %count% pomme|Il y a %count% pommes', 10, array('%count%' => 10)),
+
+ array('Il y a 0 pomme', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0)),
+ array('Il y a 1 pomme', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1)),
+ array('Il y a 10 pommes', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10)),
+
+ array('Il n\'y a aucune pomme', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0)),
+ array('Il y a 1 pomme', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1)),
+ array('Il y a 10 pommes', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10)),
+
+ array('Il y a 0 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0)),
+ );
+ }
+
+ private function getMessageFormatter()
+ {
+ return new MessageFormatter();
+ }
+}
diff --git a/src/Symfony/Component/Translation/Tests/TranslatorTest.php b/src/Symfony/Component/Translation/Tests/TranslatorTest.php
index 2394fdb432..d2c6fd51f4 100644
--- a/src/Symfony/Component/Translation/Tests/TranslatorTest.php
+++ b/src/Symfony/Component/Translation/Tests/TranslatorTest.php
@@ -13,7 +13,6 @@ namespace Symfony\Component\Translation\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Translation\Translator;
-use Symfony\Component\Translation\MessageSelector;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Symfony\Component\Translation\MessageCatalogue;
@@ -25,7 +24,7 @@ class TranslatorTest extends TestCase
*/
public function testConstructorInvalidLocale($locale)
{
- $translator = new Translator($locale, new MessageSelector());
+ $translator = new Translator($locale);
}
/**
@@ -33,14 +32,14 @@ class TranslatorTest extends TestCase
*/
public function testConstructorValidLocale($locale)
{
- $translator = new Translator($locale, new MessageSelector());
+ $translator = new Translator($locale);
$this->assertEquals($locale, $translator->getLocale());
}
public function testConstructorWithoutLocale()
{
- $translator = new Translator(null, new MessageSelector());
+ $translator = new Translator(null);
$this->assertNull($translator->getLocale());
}
@@ -61,7 +60,7 @@ class TranslatorTest extends TestCase
*/
public function testSetInvalidLocale($locale)
{
- $translator = new Translator('fr', new MessageSelector());
+ $translator = new Translator('fr');
$translator->setLocale($locale);
}
@@ -70,7 +69,7 @@ class TranslatorTest extends TestCase
*/
public function testSetValidLocale($locale)
{
- $translator = new Translator($locale, new MessageSelector());
+ $translator = new Translator($locale);
$translator->setLocale($locale);
$this->assertEquals($locale, $translator->getLocale());
@@ -144,7 +143,7 @@ class TranslatorTest extends TestCase
*/
public function testSetFallbackInvalidLocales($locale)
{
- $translator = new Translator('fr', new MessageSelector());
+ $translator = new Translator('fr');
$translator->setFallbackLocales(array('fr', $locale));
}
@@ -153,7 +152,7 @@ class TranslatorTest extends TestCase
*/
public function testSetFallbackValidLocales($locale)
{
- $translator = new Translator($locale, new MessageSelector());
+ $translator = new Translator($locale);
$translator->setFallbackLocales(array('fr', $locale));
// no assertion. this method just asserts that no exception is thrown
$this->addToAssertionCount(1);
@@ -176,7 +175,7 @@ class TranslatorTest extends TestCase
*/
public function testAddResourceInvalidLocales($locale)
{
- $translator = new Translator('fr', new MessageSelector());
+ $translator = new Translator('fr');
$translator->addResource('array', array('foo' => 'foofoo'), $locale);
}
@@ -185,7 +184,7 @@ class TranslatorTest extends TestCase
*/
public function testAddResourceValidLocales($locale)
{
- $translator = new Translator('fr', new MessageSelector());
+ $translator = new Translator('fr');
$translator->addResource('array', array('foo' => 'foofoo'), $locale);
// no assertion. this method just asserts that no exception is thrown
$this->addToAssertionCount(1);
@@ -288,7 +287,7 @@ class TranslatorTest extends TestCase
public function testFallbackCatalogueResources()
{
- $translator = new Translator('en_GB', new MessageSelector());
+ $translator = new Translator('en_GB');
$translator->addLoader('yml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
$translator->addResource('yml', __DIR__.'/fixtures/empty.yml', 'en_GB');
$translator->addResource('yml', __DIR__.'/fixtures/resources.yml', 'en');
@@ -324,7 +323,7 @@ class TranslatorTest extends TestCase
*/
public function testTransInvalidLocale($locale)
{
- $translator = new Translator('en', new MessageSelector());
+ $translator = new Translator('en');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
@@ -336,7 +335,7 @@ class TranslatorTest extends TestCase
*/
public function testTransValidLocale($locale)
{
- $translator = new Translator($locale, new MessageSelector());
+ $translator = new Translator($locale);
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('test' => 'OK'), $locale);
@@ -374,7 +373,7 @@ class TranslatorTest extends TestCase
*/
public function testTransChoiceInvalidLocale($locale)
{
- $translator = new Translator('en', new MessageSelector());
+ $translator = new Translator('en');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
@@ -386,7 +385,7 @@ class TranslatorTest extends TestCase
*/
public function testTransChoiceValidLocale($locale)
{
- $translator = new Translator('en', new MessageSelector());
+ $translator = new Translator('en');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php
index 897aced271..96553ec989 100644
--- a/src/Symfony/Component/Translation/Translator.php
+++ b/src/Symfony/Component/Translation/Translator.php
@@ -14,10 +14,14 @@ namespace Symfony\Component\Translation;
use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Translation\Exception\InvalidArgumentException;
+use Symfony\Component\Translation\Exception\LogicException;
use Symfony\Component\Translation\Exception\RuntimeException;
use Symfony\Component\Config\ConfigCacheInterface;
use Symfony\Component\Config\ConfigCacheFactoryInterface;
use Symfony\Component\Config\ConfigCacheFactory;
+use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
+use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface;
+use Symfony\Component\Translation\Formatter\MessageFormatter;
/**
* Translator.
@@ -52,9 +56,9 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
private $resources = array();
/**
- * @var MessageSelector
+ * @var MessageFormatterInterface
*/
- private $selector;
+ private $formatter;
/**
* @var string
@@ -74,17 +78,25 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
/**
* Constructor.
*
- * @param string $locale The locale
- * @param MessageSelector|null $selector The message selector for pluralization
- * @param string|null $cacheDir The directory to use for the cache
- * @param bool $debug Use cache in debug mode ?
+ * @param string $locale The locale
+ * @param MessageFormatterInterface|null $formatter The message formatter
+ * @param string|null $cacheDir The directory to use for the cache
+ * @param bool $debug Use cache in debug mode ?
*
* @throws InvalidArgumentException If a locale contains invalid characters
*/
- public function __construct($locale, MessageSelector $selector = null, $cacheDir = null, $debug = false)
+ public function __construct($locale, $formatter = null, $cacheDir = null, $debug = false)
{
$this->setLocale($locale);
- $this->selector = $selector ?: new MessageSelector();
+
+ if ($formatter instanceof MessageSelector) {
+ $formatter = new MessageFormatter($formatter);
+ @trigger_error(sprintf('Passing a "%s" instance into the "%s" as a second argument is deprecated since version 3.4 and will be removed in 4.0. Inject a "%s" implementation instead.', MessageSelector::class, __METHOD__, MessageFormatterInterface::class), E_USER_DEPRECATED);
+ } elseif (null === $formatter) {
+ $formatter = new MessageFormatter();
+ }
+
+ $this->formatter = $formatter;
$this->cacheDir = $cacheDir;
$this->debug = $debug;
}
@@ -192,7 +204,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
$domain = 'messages';
}
- return strtr($this->getCatalogue($locale)->get((string) $id, $domain), $parameters);
+ return $this->formatter->format($this->getCatalogue($locale)->get((string) $id, $domain), $locale, $parameters);
}
/**
@@ -200,9 +212,9 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
*/
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
{
- $parameters = array_merge(array(
- '%count%' => $number,
- ), $parameters);
+ if (!$this->formatter instanceof ChoiceMessageFormatterInterface) {
+ throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', get_class($this->formatter)));
+ }
if (null === $domain) {
$domain = 'messages';
@@ -220,7 +232,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
}
}
- return strtr($this->selector->choose($catalogue->get($id, $domain), (int) $number, $locale), $parameters);
+ return $this->formatter->choiceFormat($catalogue->get($id, $domain), $number, $locale, $parameters);
}
/**