[Translation] Support adding custom message formatter
This commit is contained in:
parent
b1b686081b
commit
42183b0213
@ -234,6 +234,27 @@ Translation
|
|||||||
and will be removed in 4.0, use `Symfony\Component\Translation\Writer\TranslationWriter::write`
|
and will be removed in 4.0, use `Symfony\Component\Translation\Writer\TranslationWriter::write`
|
||||||
instead.
|
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
|
TwigBridge
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -643,6 +643,9 @@ Translation
|
|||||||
* Removed `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations`,
|
* Removed `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations`,
|
||||||
use `Symfony\Component\Translation\Writer\TranslationWriter::write` instead.
|
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
|
TwigBundle
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ namespace Symfony\Bridge\Twig\Tests\Extension;
|
|||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Bridge\Twig\Extension\TranslationExtension;
|
use Symfony\Bridge\Twig\Extension\TranslationExtension;
|
||||||
use Symfony\Component\Translation\Translator;
|
use Symfony\Component\Translation\Translator;
|
||||||
use Symfony\Component\Translation\MessageSelector;
|
|
||||||
use Symfony\Component\Translation\Loader\ArrayLoader;
|
use Symfony\Component\Translation\Loader\ArrayLoader;
|
||||||
use Twig\Environment;
|
use Twig\Environment;
|
||||||
use Twig\Loader\ArrayLoader as TwigArrayLoader;
|
use Twig\Loader\ArrayLoader as TwigArrayLoader;
|
||||||
@ -37,7 +36,7 @@ class TranslationExtensionTest extends TestCase
|
|||||||
echo $template."\n";
|
echo $template."\n";
|
||||||
$loader = new TwigArrayLoader(array('index' => $template));
|
$loader = new TwigArrayLoader(array('index' => $template));
|
||||||
$twig = new Environment($loader, array('debug' => true, 'cache' => false));
|
$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";
|
echo $twig->compile($twig->parse($twig->tokenize($twig->getLoader()->getSourceContext('index'))))."\n\n";
|
||||||
$this->assertEquals($expected, $this->getTemplate($template)->render($variables));
|
$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->addLoader('array', new ArrayLoader());
|
||||||
$translator->addResource('array', array('foo' => 'foo (messages)'), 'en');
|
$translator->addResource('array', array('foo' => 'foo (messages)'), 'en');
|
||||||
$translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom');
|
$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->addLoader('array', new ArrayLoader());
|
||||||
$translator->addResource('array', array('foo' => 'foo (messages)'), 'en');
|
$translator->addResource('array', array('foo' => 'foo (messages)'), 'en');
|
||||||
$translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom');
|
$translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom');
|
||||||
@ -187,7 +186,7 @@ class TranslationExtensionTest extends TestCase
|
|||||||
protected function getTemplate($template, $translator = null)
|
protected function getTemplate($template, $translator = null)
|
||||||
{
|
{
|
||||||
if (null === $translator) {
|
if (null === $translator) {
|
||||||
$translator = new Translator('en', new MessageSelector());
|
$translator = new Translator('en');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_array($template)) {
|
if (is_array($template)) {
|
||||||
|
@ -668,6 +668,7 @@ class Configuration implements ConfigurationInterface
|
|||||||
->defaultValue(array('en'))
|
->defaultValue(array('en'))
|
||||||
->end()
|
->end()
|
||||||
->booleanNode('logging')->defaultValue($this->debug)->end()
|
->booleanNode('logging')->defaultValue($this->debug)->end()
|
||||||
|
->scalarNode('formatter')->defaultValue('translator.formatter.default')->end()
|
||||||
->arrayNode('paths')
|
->arrayNode('paths')
|
||||||
->prototype('scalar')->end()
|
->prototype('scalar')->end()
|
||||||
->end()
|
->end()
|
||||||
|
@ -1075,6 +1075,7 @@ class FrameworkExtension extends Extension
|
|||||||
|
|
||||||
// Use the "real" translator instead of the identity default
|
// Use the "real" translator instead of the identity default
|
||||||
$container->setAlias('translator', 'translator.default');
|
$container->setAlias('translator', 'translator.default');
|
||||||
|
$container->setAlias('translator.formatter', new Alias($config['formatter'], false));
|
||||||
$translator = $container->findDefinition('translator.default');
|
$translator = $container->findDefinition('translator.default');
|
||||||
$translator->addMethodCall('setFallbackLocales', array($config['fallbacks']));
|
$translator->addMethodCall('setFallbackLocales', array($config['fallbacks']));
|
||||||
|
|
||||||
|
@ -184,6 +184,7 @@
|
|||||||
<xsd:attribute name="enabled" type="xsd:boolean" />
|
<xsd:attribute name="enabled" type="xsd:boolean" />
|
||||||
<xsd:attribute name="fallback" type="xsd:string" />
|
<xsd:attribute name="fallback" type="xsd:string" />
|
||||||
<xsd:attribute name="logging" type="xsd:boolean" />
|
<xsd:attribute name="logging" type="xsd:boolean" />
|
||||||
|
<xsd:attribute name="formatter" type="xsd:string" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
<xsd:complexType name="validation">
|
<xsd:complexType name="validation">
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
<service id="translator.default" class="Symfony\Bundle\FrameworkBundle\Translation\Translator" public="true">
|
<service id="translator.default" class="Symfony\Bundle\FrameworkBundle\Translation\Translator" public="true">
|
||||||
<argument /> <!-- translation loaders locator -->
|
<argument /> <!-- translation loaders locator -->
|
||||||
<argument type="service" id="translator.selector" />
|
<argument type="service" id="translator.formatter" />
|
||||||
<argument>%kernel.default_locale%</argument>
|
<argument>%kernel.default_locale%</argument>
|
||||||
<argument type="collection" /> <!-- translation loaders ids -->
|
<argument type="collection" /> <!-- translation loaders ids -->
|
||||||
<argument type="collection">
|
<argument type="collection">
|
||||||
@ -28,6 +28,10 @@
|
|||||||
<tag name="monolog.logger" channel="translation" />
|
<tag name="monolog.logger" channel="translation" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service id="translator.formatter.default" class="Symfony\Component\Translation\Formatter\MessageFormatter">
|
||||||
|
<argument type="service" id="translator.selector" />
|
||||||
|
</service>
|
||||||
|
|
||||||
<service id="translation.loader.php" class="Symfony\Component\Translation\Loader\PhpFileLoader" public="true">
|
<service id="translation.loader.php" class="Symfony\Component\Translation\Loader\PhpFileLoader" public="true">
|
||||||
<tag name="translation.loader" alias="php" />
|
<tag name="translation.loader" alias="php" />
|
||||||
</service>
|
</service>
|
||||||
|
@ -255,6 +255,7 @@ class ConfigurationTest extends TestCase
|
|||||||
'enabled' => !class_exists(FullStack::class),
|
'enabled' => !class_exists(FullStack::class),
|
||||||
'fallbacks' => array('en'),
|
'fallbacks' => array('en'),
|
||||||
'logging' => true,
|
'logging' => true,
|
||||||
|
'formatter' => 'translator.formatter.default',
|
||||||
'paths' => array(),
|
'paths' => array(),
|
||||||
),
|
),
|
||||||
'validation' => array(
|
'validation' => array(
|
||||||
|
@ -14,9 +14,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Translation;
|
|||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
|
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
|
||||||
|
use Symfony\Component\Translation\Formatter\MessageFormatter;
|
||||||
use Symfony\Component\Translation\MessageCatalogue;
|
use Symfony\Component\Translation\MessageCatalogue;
|
||||||
use Symfony\Component\Filesystem\Filesystem;
|
use Symfony\Component\Filesystem\Filesystem;
|
||||||
use Symfony\Component\Translation\MessageSelector;
|
|
||||||
|
|
||||||
class TranslatorTest extends TestCase
|
class TranslatorTest extends TestCase
|
||||||
{
|
{
|
||||||
@ -149,7 +149,7 @@ class TranslatorTest extends TestCase
|
|||||||
->with('kernel.default_locale')
|
->with('kernel.default_locale')
|
||||||
->will($this->returnValue('en'))
|
->will($this->returnValue('en'))
|
||||||
;
|
;
|
||||||
$translator = new Translator($container, new MessageSelector());
|
$translator = new Translator($container, new MessageFormatter());
|
||||||
|
|
||||||
$this->assertSame('en', $translator->getLocale());
|
$this->assertSame('en', $translator->getLocale());
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ class TranslatorTest extends TestCase
|
|||||||
public function testGetDefaultLocaleOmittingLocaleWithPsrContainer()
|
public function testGetDefaultLocaleOmittingLocaleWithPsrContainer()
|
||||||
{
|
{
|
||||||
$container = $this->getMockBuilder(ContainerInterface::class)->getMock();
|
$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()
|
public function testGetDefaultLocale()
|
||||||
{
|
{
|
||||||
$container = $this->getMockBuilder(ContainerInterface::class)->getMock();
|
$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());
|
$this->assertSame('en', $translator->getLocale());
|
||||||
}
|
}
|
||||||
@ -290,7 +290,7 @@ class TranslatorTest extends TestCase
|
|||||||
{
|
{
|
||||||
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
|
$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 */
|
/** @dataProvider getDebugModeAndCacheDirCombinations */
|
||||||
@ -468,7 +468,7 @@ class TranslatorTest extends TestCase
|
|||||||
if (null === $defaultLocale) {
|
if (null === $defaultLocale) {
|
||||||
return new $translatorClass(
|
return new $translatorClass(
|
||||||
$this->getContainer($loader),
|
$this->getContainer($loader),
|
||||||
new MessageSelector(),
|
new MessageFormatter(),
|
||||||
array($loaderFomat => array($loaderFomat)),
|
array($loaderFomat => array($loaderFomat)),
|
||||||
$options
|
$options
|
||||||
);
|
);
|
||||||
@ -476,7 +476,7 @@ class TranslatorTest extends TestCase
|
|||||||
|
|
||||||
return new $translatorClass(
|
return new $translatorClass(
|
||||||
$this->getContainer($loader),
|
$this->getContainer($loader),
|
||||||
new MessageSelector(),
|
new MessageFormatter(),
|
||||||
$defaultLocale,
|
$defaultLocale,
|
||||||
array($loaderFomat => array($loaderFomat)),
|
array($loaderFomat => array($loaderFomat)),
|
||||||
$options
|
$options
|
||||||
|
@ -15,8 +15,8 @@ use Psr\Container\ContainerInterface;
|
|||||||
use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
|
||||||
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
|
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
|
||||||
use Symfony\Component\Translation\Translator as BaseTranslator;
|
use Symfony\Component\Translation\Translator as BaseTranslator;
|
||||||
use Symfony\Component\Translation\MessageSelector;
|
|
||||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||||
|
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translator.
|
* Translator.
|
||||||
@ -57,14 +57,14 @@ class Translator extends BaseTranslator implements WarmableInterface
|
|||||||
* * resource_files: List of translation resources available grouped by locale.
|
* * resource_files: List of translation resources available grouped by locale.
|
||||||
*
|
*
|
||||||
* @param ContainerInterface $container A ContainerInterface instance
|
* @param ContainerInterface $container A ContainerInterface instance
|
||||||
* @param MessageSelector $selector The message selector for pluralization
|
* @param MessageFormatterInterface $formatter The message formatter
|
||||||
* @param string $defaultLocale
|
* @param string $defaultLocale
|
||||||
* @param array $loaderIds An array of loader Ids
|
* @param array $loaderIds An array of loader Ids
|
||||||
* @param array $options An array of options
|
* @param array $options An array of options
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException
|
* @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
|
// BC 3.x, to be removed in 4.0 along with the $defaultLocale default value
|
||||||
if (is_array($defaultLocale) || 3 > func_num_args()) {
|
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->resourceLocales = array_keys($this->options['resource_files']);
|
||||||
$this->addResourceFiles($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']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,6 +12,7 @@ CHANGELOG
|
|||||||
* Improved Xliff 2.0 loader to load `<notes>` section.
|
* Improved Xliff 2.0 loader to load `<notes>` section.
|
||||||
* Added `TranslationWriterInterface`
|
* Added `TranslationWriterInterface`
|
||||||
* Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write`
|
* Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write`
|
||||||
|
* added support for adding custom message formatter and decoupling the default one.
|
||||||
|
|
||||||
3.2.0
|
3.2.0
|
||||||
-----
|
-----
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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 <a.aitboudad@gmail.com>
|
||||||
|
*/
|
||||||
|
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());
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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 <a.aitboudad@gmail.com>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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 <guilhermeblanco@hotmail.com>
|
||||||
|
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||||
|
*/
|
||||||
|
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());
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,6 @@ namespace Symfony\Component\Translation\Tests;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\Translation\Translator;
|
use Symfony\Component\Translation\Translator;
|
||||||
use Symfony\Component\Translation\MessageSelector;
|
|
||||||
use Symfony\Component\Translation\Loader\ArrayLoader;
|
use Symfony\Component\Translation\Loader\ArrayLoader;
|
||||||
use Symfony\Component\Translation\MessageCatalogue;
|
use Symfony\Component\Translation\MessageCatalogue;
|
||||||
|
|
||||||
@ -25,7 +24,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testConstructorInvalidLocale($locale)
|
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)
|
public function testConstructorValidLocale($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator($locale, new MessageSelector());
|
$translator = new Translator($locale);
|
||||||
|
|
||||||
$this->assertEquals($locale, $translator->getLocale());
|
$this->assertEquals($locale, $translator->getLocale());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testConstructorWithoutLocale()
|
public function testConstructorWithoutLocale()
|
||||||
{
|
{
|
||||||
$translator = new Translator(null, new MessageSelector());
|
$translator = new Translator(null);
|
||||||
|
|
||||||
$this->assertNull($translator->getLocale());
|
$this->assertNull($translator->getLocale());
|
||||||
}
|
}
|
||||||
@ -61,7 +60,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testSetInvalidLocale($locale)
|
public function testSetInvalidLocale($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator('fr', new MessageSelector());
|
$translator = new Translator('fr');
|
||||||
$translator->setLocale($locale);
|
$translator->setLocale($locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +69,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testSetValidLocale($locale)
|
public function testSetValidLocale($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator($locale, new MessageSelector());
|
$translator = new Translator($locale);
|
||||||
$translator->setLocale($locale);
|
$translator->setLocale($locale);
|
||||||
|
|
||||||
$this->assertEquals($locale, $translator->getLocale());
|
$this->assertEquals($locale, $translator->getLocale());
|
||||||
@ -144,7 +143,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testSetFallbackInvalidLocales($locale)
|
public function testSetFallbackInvalidLocales($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator('fr', new MessageSelector());
|
$translator = new Translator('fr');
|
||||||
$translator->setFallbackLocales(array('fr', $locale));
|
$translator->setFallbackLocales(array('fr', $locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +152,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testSetFallbackValidLocales($locale)
|
public function testSetFallbackValidLocales($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator($locale, new MessageSelector());
|
$translator = new Translator($locale);
|
||||||
$translator->setFallbackLocales(array('fr', $locale));
|
$translator->setFallbackLocales(array('fr', $locale));
|
||||||
// no assertion. this method just asserts that no exception is thrown
|
// no assertion. this method just asserts that no exception is thrown
|
||||||
$this->addToAssertionCount(1);
|
$this->addToAssertionCount(1);
|
||||||
@ -176,7 +175,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAddResourceInvalidLocales($locale)
|
public function testAddResourceInvalidLocales($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator('fr', new MessageSelector());
|
$translator = new Translator('fr');
|
||||||
$translator->addResource('array', array('foo' => 'foofoo'), $locale);
|
$translator->addResource('array', array('foo' => 'foofoo'), $locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +184,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testAddResourceValidLocales($locale)
|
public function testAddResourceValidLocales($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator('fr', new MessageSelector());
|
$translator = new Translator('fr');
|
||||||
$translator->addResource('array', array('foo' => 'foofoo'), $locale);
|
$translator->addResource('array', array('foo' => 'foofoo'), $locale);
|
||||||
// no assertion. this method just asserts that no exception is thrown
|
// no assertion. this method just asserts that no exception is thrown
|
||||||
$this->addToAssertionCount(1);
|
$this->addToAssertionCount(1);
|
||||||
@ -288,7 +287,7 @@ class TranslatorTest extends TestCase
|
|||||||
|
|
||||||
public function testFallbackCatalogueResources()
|
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->addLoader('yml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
|
||||||
$translator->addResource('yml', __DIR__.'/fixtures/empty.yml', 'en_GB');
|
$translator->addResource('yml', __DIR__.'/fixtures/empty.yml', 'en_GB');
|
||||||
$translator->addResource('yml', __DIR__.'/fixtures/resources.yml', 'en');
|
$translator->addResource('yml', __DIR__.'/fixtures/resources.yml', 'en');
|
||||||
@ -324,7 +323,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testTransInvalidLocale($locale)
|
public function testTransInvalidLocale($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator('en', new MessageSelector());
|
$translator = new Translator('en');
|
||||||
$translator->addLoader('array', new ArrayLoader());
|
$translator->addLoader('array', new ArrayLoader());
|
||||||
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
|
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
|
||||||
|
|
||||||
@ -336,7 +335,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testTransValidLocale($locale)
|
public function testTransValidLocale($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator($locale, new MessageSelector());
|
$translator = new Translator($locale);
|
||||||
$translator->addLoader('array', new ArrayLoader());
|
$translator->addLoader('array', new ArrayLoader());
|
||||||
$translator->addResource('array', array('test' => 'OK'), $locale);
|
$translator->addResource('array', array('test' => 'OK'), $locale);
|
||||||
|
|
||||||
@ -374,7 +373,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testTransChoiceInvalidLocale($locale)
|
public function testTransChoiceInvalidLocale($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator('en', new MessageSelector());
|
$translator = new Translator('en');
|
||||||
$translator->addLoader('array', new ArrayLoader());
|
$translator->addLoader('array', new ArrayLoader());
|
||||||
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
|
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
|
||||||
|
|
||||||
@ -386,7 +385,7 @@ class TranslatorTest extends TestCase
|
|||||||
*/
|
*/
|
||||||
public function testTransChoiceValidLocale($locale)
|
public function testTransChoiceValidLocale($locale)
|
||||||
{
|
{
|
||||||
$translator = new Translator('en', new MessageSelector());
|
$translator = new Translator('en');
|
||||||
$translator->addLoader('array', new ArrayLoader());
|
$translator->addLoader('array', new ArrayLoader());
|
||||||
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
|
$translator->addResource('array', array('foo' => 'foofoo'), 'en');
|
||||||
|
|
||||||
|
@ -14,10 +14,14 @@ namespace Symfony\Component\Translation;
|
|||||||
use Symfony\Component\Translation\Loader\LoaderInterface;
|
use Symfony\Component\Translation\Loader\LoaderInterface;
|
||||||
use Symfony\Component\Translation\Exception\NotFoundResourceException;
|
use Symfony\Component\Translation\Exception\NotFoundResourceException;
|
||||||
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||||
|
use Symfony\Component\Translation\Exception\LogicException;
|
||||||
use Symfony\Component\Translation\Exception\RuntimeException;
|
use Symfony\Component\Translation\Exception\RuntimeException;
|
||||||
use Symfony\Component\Config\ConfigCacheInterface;
|
use Symfony\Component\Config\ConfigCacheInterface;
|
||||||
use Symfony\Component\Config\ConfigCacheFactoryInterface;
|
use Symfony\Component\Config\ConfigCacheFactoryInterface;
|
||||||
use Symfony\Component\Config\ConfigCacheFactory;
|
use Symfony\Component\Config\ConfigCacheFactory;
|
||||||
|
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
|
||||||
|
use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface;
|
||||||
|
use Symfony\Component\Translation\Formatter\MessageFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translator.
|
* Translator.
|
||||||
@ -52,9 +56,9 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
|
|||||||
private $resources = array();
|
private $resources = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var MessageSelector
|
* @var MessageFormatterInterface
|
||||||
*/
|
*/
|
||||||
private $selector;
|
private $formatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
@ -75,16 +79,24 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
|
|||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param string $locale The locale
|
* @param string $locale The locale
|
||||||
* @param MessageSelector|null $selector The message selector for pluralization
|
* @param MessageFormatterInterface|null $formatter The message formatter
|
||||||
* @param string|null $cacheDir The directory to use for the cache
|
* @param string|null $cacheDir The directory to use for the cache
|
||||||
* @param bool $debug Use cache in debug mode ?
|
* @param bool $debug Use cache in debug mode ?
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException If a locale contains invalid characters
|
* @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->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->cacheDir = $cacheDir;
|
||||||
$this->debug = $debug;
|
$this->debug = $debug;
|
||||||
}
|
}
|
||||||
@ -192,7 +204,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
|
|||||||
$domain = 'messages';
|
$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)
|
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
||||||
{
|
{
|
||||||
$parameters = array_merge(array(
|
if (!$this->formatter instanceof ChoiceMessageFormatterInterface) {
|
||||||
'%count%' => $number,
|
throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', get_class($this->formatter)));
|
||||||
), $parameters);
|
}
|
||||||
|
|
||||||
if (null === $domain) {
|
if (null === $domain) {
|
||||||
$domain = 'messages';
|
$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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user