feature #28375 [Translator] Deprecated transChoice and moved it away from contracts (Nyholm, nicolas-grekas)
This PR was merged into the 4.2-dev branch. Discussion ---------- [Translator] Deprecated transChoice and moved it away from contracts | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | Issue: https://github.com/symfony/symfony-docs/issues/10264 This will address comment made here: https://github.com/symfony/symfony/pull/27399#pullrequestreview-151929117 This PR moves the `transChoice()` method away from Contracts and back to the component. I also reverted changes in the `IdentityTranslator`. I will still use the deprecated `MessageSelector` but this is not fine since `transChoice()` is also deprecated. Commits -------dc5f3bfff7
Make trans + %count% parameter resolve pluralsd870a850bd
[Translator] Deprecated transChoice and moved it away from contracts
This commit is contained in:
commit
23b0787a88
@ -114,6 +114,7 @@ FrameworkBundle
|
|||||||
set the "APP_ENV" environment variable instead.
|
set the "APP_ENV" environment variable instead.
|
||||||
* The `--no-debug` console option has been deprecated,
|
* The `--no-debug` console option has been deprecated,
|
||||||
set the "APP_DEBUG" environment variable to "0" instead.
|
set the "APP_DEBUG" environment variable to "0" instead.
|
||||||
|
* The `Templating\Helper\TranslatorHelper::transChoice()` method has been deprecated, use the `trans()` one instead with a `%count%` parameter.
|
||||||
|
|
||||||
Messenger
|
Messenger
|
||||||
---------
|
---------
|
||||||
@ -219,9 +220,15 @@ Translation
|
|||||||
-----------
|
-----------
|
||||||
|
|
||||||
* The `TranslatorInterface` has been deprecated in favor of `Symfony\Contracts\Translation\TranslatorInterface`
|
* The `TranslatorInterface` has been deprecated in favor of `Symfony\Contracts\Translation\TranslatorInterface`
|
||||||
|
* The `Translator::transChoice()` method has been deprecated in favor of using `Translator::trans()` with "%count%" as the parameter driving plurals
|
||||||
* The `MessageSelector`, `Interval` and `PluralizationRules` classes have been deprecated, use `IdentityTranslator` instead
|
* The `MessageSelector`, `Interval` and `PluralizationRules` classes have been deprecated, use `IdentityTranslator` instead
|
||||||
* The `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` method have been marked as internal
|
* The `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` method have been marked as internal
|
||||||
|
|
||||||
|
TwigBundle
|
||||||
|
----------
|
||||||
|
|
||||||
|
* The `transchoice` tag and filter have been deprecated, use the `trans` ones instead with a `%count%` parameter.
|
||||||
|
|
||||||
Validator
|
Validator
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
@ -120,6 +120,7 @@ FrameworkBundle
|
|||||||
set the "APP_ENV" environment variable instead.
|
set the "APP_ENV" environment variable instead.
|
||||||
* The `--no-debug` console option has been removed,
|
* The `--no-debug` console option has been removed,
|
||||||
set the "APP_DEBUG" environment variable to "0" instead.
|
set the "APP_DEBUG" environment variable to "0" instead.
|
||||||
|
* The `Templating\Helper\TranslatorHelper::transChoice()` method has been removed, use the `trans()` one instead with a `%count%` parameter.
|
||||||
|
|
||||||
HttpFoundation
|
HttpFoundation
|
||||||
--------------
|
--------------
|
||||||
@ -196,11 +197,13 @@ Translation
|
|||||||
* The `TranslatorInterface` has been removed in favor of `Symfony\Contracts\Translation\TranslatorInterface`
|
* The `TranslatorInterface` has been removed in favor of `Symfony\Contracts\Translation\TranslatorInterface`
|
||||||
* The `MessageSelector`, `Interval` and `PluralizationRules` classes have been removed, use `IdentityTranslator` instead
|
* The `MessageSelector`, `Interval` and `PluralizationRules` classes have been removed, use `IdentityTranslator` instead
|
||||||
* The `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` method are now internal
|
* The `Translator::getFallbackLocales()` and `TranslationDataCollector::getFallbackLocales()` method are now internal
|
||||||
|
* The `Translator::transChoice()` method has been removed in favor of using `Translator::trans()` with "%count%" as the parameter driving plurals
|
||||||
|
|
||||||
TwigBundle
|
TwigBundle
|
||||||
----------
|
----------
|
||||||
|
|
||||||
* The default value (`false`) of the `twig.strict_variables` configuration option has been changed to `%kernel.debug%`.
|
* The default value (`false`) of the `twig.strict_variables` configuration option has been changed to `%kernel.debug%`.
|
||||||
|
* The `transchoice` tag and filter have been removed, use the `trans` ones instead with a `%count%` parameter.
|
||||||
|
|
||||||
Validator
|
Validator
|
||||||
--------
|
--------
|
||||||
|
@ -4,8 +4,9 @@ CHANGELOG
|
|||||||
4.2.0
|
4.2.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
* add bundle name suggestion on wrongly overridden templates paths
|
* add bundle name suggestion on wrongly overridden templates paths
|
||||||
* added `name` argument in `debug:twig` command and changed `filter` argument as `--filter` option
|
* added `name` argument in `debug:twig` command and changed `filter` argument as `--filter` option
|
||||||
|
* deprecated the `transchoice` tag and filter, use the `trans` ones instead with a `%count%` parameter
|
||||||
|
|
||||||
4.1.0
|
4.1.0
|
||||||
-----
|
-----
|
||||||
|
@ -16,6 +16,7 @@ use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
|
|||||||
use Symfony\Bridge\Twig\TokenParser\TransChoiceTokenParser;
|
use Symfony\Bridge\Twig\TokenParser\TransChoiceTokenParser;
|
||||||
use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser;
|
use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser;
|
||||||
use Symfony\Bridge\Twig\TokenParser\TransTokenParser;
|
use Symfony\Bridge\Twig\TokenParser\TransTokenParser;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorTrait;
|
use Symfony\Contracts\Translation\TranslatorTrait;
|
||||||
use Twig\Extension\AbstractExtension;
|
use Twig\Extension\AbstractExtension;
|
||||||
@ -27,6 +28,8 @@ use Twig\TwigFilter;
|
|||||||
* Provides integration of the Translation component with Twig.
|
* Provides integration of the Translation component with Twig.
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* @final since Symfony 4.2
|
||||||
*/
|
*/
|
||||||
class TranslationExtension extends AbstractExtension
|
class TranslationExtension extends AbstractExtension
|
||||||
{
|
{
|
||||||
@ -34,20 +37,30 @@ class TranslationExtension extends AbstractExtension
|
|||||||
getLocale as private;
|
getLocale as private;
|
||||||
setLocale as private;
|
setLocale as private;
|
||||||
trans as private doTrans;
|
trans as private doTrans;
|
||||||
transChoice as private doTransChoice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private $translator;
|
private $translator;
|
||||||
private $translationNodeVisitor;
|
private $translationNodeVisitor;
|
||||||
|
|
||||||
public function __construct(TranslatorInterface $translator = null, NodeVisitorInterface $translationNodeVisitor = null)
|
/**
|
||||||
|
* @param TranslatorInterface|null $translator
|
||||||
|
*/
|
||||||
|
public function __construct($translator = null, NodeVisitorInterface $translationNodeVisitor = null)
|
||||||
{
|
{
|
||||||
|
if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
$this->translationNodeVisitor = $translationNodeVisitor;
|
$this->translationNodeVisitor = $translationNodeVisitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since Symfony 4.2
|
||||||
|
*/
|
||||||
public function getTranslator()
|
public function getTranslator()
|
||||||
{
|
{
|
||||||
|
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
|
||||||
|
|
||||||
return $this->translator;
|
return $this->translator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +71,7 @@ class TranslationExtension extends AbstractExtension
|
|||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
new TwigFilter('trans', array($this, 'trans')),
|
new TwigFilter('trans', array($this, 'trans')),
|
||||||
new TwigFilter('transchoice', array($this, 'transchoice')),
|
new TwigFilter('transchoice', array($this, 'transchoice'), array('deprecated' => '4.2', 'alternative' => 'trans" with parameter "%count%')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +109,11 @@ class TranslationExtension extends AbstractExtension
|
|||||||
return $this->translationNodeVisitor ?: $this->translationNodeVisitor = new TranslationNodeVisitor();
|
return $this->translationNodeVisitor ?: $this->translationNodeVisitor = new TranslationNodeVisitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function trans($message, array $arguments = array(), $domain = null, $locale = null)
|
public function trans($message, array $arguments = array(), $domain = null, $locale = null, $count = null)
|
||||||
{
|
{
|
||||||
|
if (null !== $count) {
|
||||||
|
$arguments['%count%'] = $count;
|
||||||
|
}
|
||||||
if (null === $this->translator) {
|
if (null === $this->translator) {
|
||||||
return $this->doTrans($message, $arguments, $domain, $locale);
|
return $this->doTrans($message, $arguments, $domain, $locale);
|
||||||
}
|
}
|
||||||
@ -105,10 +121,16 @@ class TranslationExtension extends AbstractExtension
|
|||||||
return $this->translator->trans($message, $arguments, $domain, $locale);
|
return $this->translator->trans($message, $arguments, $domain, $locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
|
||||||
|
*/
|
||||||
public function transchoice($message, $count, array $arguments = array(), $domain = null, $locale = null)
|
public function transchoice($message, $count, array $arguments = array(), $domain = null, $locale = null)
|
||||||
{
|
{
|
||||||
if (null === $this->translator) {
|
if (null === $this->translator) {
|
||||||
return $this->doTransChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale);
|
return $this->doTrans($message, array_merge(array('%count%' => $count), $arguments), $domain, $locale);
|
||||||
|
}
|
||||||
|
if ($this->translator instanceof TranslatorInterface) {
|
||||||
|
return $this->translator->trans($message, array_merge(array('%count%' => $count), $arguments), $domain, $locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->translator->transChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale);
|
return $this->translator->transChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale);
|
||||||
|
@ -60,19 +60,12 @@ class TransNode extends Node
|
|||||||
$method = !$this->hasNode('count') ? 'trans' : 'transChoice';
|
$method = !$this->hasNode('count') ? 'trans' : 'transChoice';
|
||||||
|
|
||||||
$compiler
|
$compiler
|
||||||
->write('echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->getTranslator()->'.$method.'(')
|
->write('echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->trans(')
|
||||||
->subcompile($msg)
|
->subcompile($msg)
|
||||||
;
|
;
|
||||||
|
|
||||||
$compiler->raw(', ');
|
$compiler->raw(', ');
|
||||||
|
|
||||||
if ($this->hasNode('count')) {
|
|
||||||
$compiler
|
|
||||||
->subcompile($this->getNode('count'))
|
|
||||||
->raw(', ')
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null !== $vars) {
|
if (null !== $vars) {
|
||||||
$compiler
|
$compiler
|
||||||
->raw('array_merge(')
|
->raw('array_merge(')
|
||||||
@ -98,7 +91,17 @@ class TransNode extends Node
|
|||||||
->raw(', ')
|
->raw(', ')
|
||||||
->subcompile($this->getNode('locale'))
|
->subcompile($this->getNode('locale'))
|
||||||
;
|
;
|
||||||
|
} elseif ($this->hasNode('count')) {
|
||||||
|
$compiler->raw(', null');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->hasNode('count')) {
|
||||||
|
$compiler
|
||||||
|
->raw(', ')
|
||||||
|
->subcompile($this->getNode('count'))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
$compiler->raw(");\n");
|
$compiler->raw(");\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,15 @@ class TranslationExtensionTest extends TestCase
|
|||||||
$this->assertEquals($expected, $this->getTemplate($template)->render($variables));
|
$this->assertEquals($expected, $this->getTemplate($template)->render($variables));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
* @dataProvider getTransChoiceTests
|
||||||
|
*/
|
||||||
|
public function testTransChoice($template, $expected, array $variables = array())
|
||||||
|
{
|
||||||
|
$this->testTrans($template, $expected, $variables);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Twig\Error\SyntaxError
|
* @expectedException \Twig\Error\SyntaxError
|
||||||
* @expectedExceptionMessage Unexpected token. Twig was looking for the "with", "from", or "into" keyword in "index" at line 3.
|
* @expectedExceptionMessage Unexpected token. Twig was looking for the "with", "from", or "into" keyword in "index" at line 3.
|
||||||
@ -64,6 +73,7 @@ class TranslationExtensionTest extends TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @group legacy
|
||||||
* @expectedException \Twig\Error\SyntaxError
|
* @expectedException \Twig\Error\SyntaxError
|
||||||
* @expectedExceptionMessage A message inside a transchoice tag must be a simple text in "index" at line 2.
|
* @expectedExceptionMessage A message inside a transchoice tag must be a simple text in "index" at line 2.
|
||||||
*/
|
*/
|
||||||
@ -87,6 +97,69 @@ class TranslationExtensionTest extends TestCase
|
|||||||
|
|
||||||
array('{% trans into "fr"%}Hello{% endtrans %}', 'Hello'),
|
array('{% trans into "fr"%}Hello{% endtrans %}', 'Hello'),
|
||||||
|
|
||||||
|
// trans with count
|
||||||
|
array(
|
||||||
|
'{% trans from "messages" %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtrans %}',
|
||||||
|
'There is no apples',
|
||||||
|
array('count' => 0),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{% trans %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtrans %}',
|
||||||
|
'There is 5 apples',
|
||||||
|
array('count' => 5),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{% trans %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtrans %}',
|
||||||
|
'There is 5 apples (Symfony)',
|
||||||
|
array('count' => 5, 'name' => 'Symfony'),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{% trans with { \'%name%\': \'Symfony\' } %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtrans %}',
|
||||||
|
'There is 5 apples (Symfony)',
|
||||||
|
array('count' => 5),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{% trans into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtrans %}',
|
||||||
|
'There is no apples',
|
||||||
|
array('count' => 0),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'{% trans count 5 into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtrans %}',
|
||||||
|
'There is 5 apples',
|
||||||
|
),
|
||||||
|
|
||||||
|
// trans filter
|
||||||
|
array('{{ "Hello"|trans }}', 'Hello'),
|
||||||
|
array('{{ name|trans }}', 'Symfony', array('name' => 'Symfony')),
|
||||||
|
array('{{ hello|trans({ \'%name%\': \'Symfony\' }) }}', 'Hello Symfony', array('hello' => 'Hello %name%')),
|
||||||
|
array('{% set vars = { \'%name%\': \'Symfony\' } %}{{ hello|trans(vars) }}', 'Hello Symfony', array('hello' => 'Hello %name%')),
|
||||||
|
array('{{ "Hello"|trans({}, "messages", "fr") }}', 'Hello'),
|
||||||
|
|
||||||
|
// trans filter with count
|
||||||
|
array('{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|trans(count=count) }}', 'There is 5 apples', array('count' => 5)),
|
||||||
|
array('{{ text|trans(count=5, arguments={\'%name%\': \'Symfony\'}) }}', 'There is 5 apples (Symfony)', array('text' => '{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%)')),
|
||||||
|
array('{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|trans({}, "messages", "fr", count) }}', 'There is 5 apples', array('count' => 5)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
|
public function getTransChoiceTests()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
// trans tag
|
||||||
|
array('{% trans %}Hello{% endtrans %}', 'Hello'),
|
||||||
|
array('{% trans %}%name%{% endtrans %}', 'Symfony', array('name' => 'Symfony')),
|
||||||
|
|
||||||
|
array('{% trans from elsewhere %}Hello{% endtrans %}', 'Hello'),
|
||||||
|
|
||||||
|
array('{% trans %}Hello %name%{% endtrans %}', 'Hello Symfony', array('name' => 'Symfony')),
|
||||||
|
array('{% trans with { \'%name%\': \'Symfony\' } %}Hello %name%{% endtrans %}', 'Hello Symfony'),
|
||||||
|
array('{% set vars = { \'%name%\': \'Symfony\' } %}{% trans with vars %}Hello %name%{% endtrans %}', 'Hello Symfony'),
|
||||||
|
|
||||||
|
array('{% trans into "fr"%}Hello{% endtrans %}', 'Hello'),
|
||||||
|
|
||||||
// transchoice
|
// transchoice
|
||||||
array(
|
array(
|
||||||
'{% transchoice count from "messages" %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
|
'{% transchoice count from "messages" %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}',
|
||||||
@ -145,8 +218,8 @@ class TranslationExtensionTest extends TestCase
|
|||||||
{%- trans from "custom" %}foo{% endtrans %}
|
{%- trans from "custom" %}foo{% endtrans %}
|
||||||
{{- "foo"|trans }}
|
{{- "foo"|trans }}
|
||||||
{{- "foo"|trans({}, "custom") }}
|
{{- "foo"|trans({}, "custom") }}
|
||||||
{{- "foo"|transchoice(1) }}
|
{{- "foo"|trans(count=1) }}
|
||||||
{{- "foo"|transchoice(1, {}, "custom") }}
|
{{- "foo"|trans({"%count%":1}, "custom") }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
',
|
',
|
||||||
|
|
||||||
@ -174,12 +247,12 @@ class TranslationExtensionTest extends TestCase
|
|||||||
|
|
||||||
{%- block content %}
|
{%- block content %}
|
||||||
{{- "foo"|trans(arguments = {}, domain = "custom") }}
|
{{- "foo"|trans(arguments = {}, domain = "custom") }}
|
||||||
{{- "foo"|transchoice(count = 1) }}
|
{{- "foo"|trans(count = 1) }}
|
||||||
{{- "foo"|transchoice(count = 1, arguments = {}, domain = "custom") }}
|
{{- "foo"|trans(count = 1, arguments = {}, domain = "custom") }}
|
||||||
{{- "foo"|trans({}, domain = "custom") }}
|
{{- "foo"|trans({}, domain = "custom") }}
|
||||||
{{- "foo"|trans({}, "custom", locale = "fr") }}
|
{{- "foo"|trans({}, "custom", locale = "fr") }}
|
||||||
{{- "foo"|transchoice(1, arguments = {}, domain = "custom") }}
|
{{- "foo"|trans(arguments = {"%count%":1}, domain = "custom") }}
|
||||||
{{- "foo"|transchoice(1, {}, "custom", locale = "fr") }}
|
{{- "foo"|trans({"%count%":1}, "custom", locale = "fr") }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
',
|
',
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class TransNodeTest extends TestCase
|
|||||||
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
sprintf(
|
sprintf(
|
||||||
'echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->getTranslator()->trans("trans %%var%%", array_merge(array("%%var%%" => %s), %s), "messages");',
|
'echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->trans("trans %%var%%", array_merge(array("%%var%%" => %s), %s), "messages");',
|
||||||
$this->getVariableGetterWithoutStrictCheck('var'),
|
$this->getVariableGetterWithoutStrictCheck('var'),
|
||||||
$this->getVariableGetterWithStrictCheck('foo')
|
$this->getVariableGetterWithStrictCheck('foo')
|
||||||
),
|
),
|
||||||
|
@ -50,15 +50,21 @@ class TwigExtractorTest extends TestCase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
* @dataProvider getLegacyExtractData
|
||||||
|
*/
|
||||||
|
public function testLegacyExtract($template, $messages)
|
||||||
|
{
|
||||||
|
$this->testExtract($template, $messages);
|
||||||
|
}
|
||||||
|
|
||||||
public function getExtractData()
|
public function getExtractData()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array('{{ "new key" | trans() }}', array('new key' => 'messages')),
|
array('{{ "new key" | trans() }}', array('new key' => 'messages')),
|
||||||
array('{{ "new key" | trans() | upper }}', array('new key' => 'messages')),
|
array('{{ "new key" | trans() | upper }}', array('new key' => 'messages')),
|
||||||
array('{{ "new key" | trans({}, "domain") }}', array('new key' => 'domain')),
|
array('{{ "new key" | trans({}, "domain") }}', array('new key' => 'domain')),
|
||||||
array('{{ "new key" | transchoice(1) }}', array('new key' => 'messages')),
|
|
||||||
array('{{ "new key" | transchoice(1) | upper }}', array('new key' => 'messages')),
|
|
||||||
array('{{ "new key" | transchoice(1, {}, "domain") }}', array('new key' => 'domain')),
|
|
||||||
array('{% trans %}new key{% endtrans %}', array('new key' => 'messages')),
|
array('{% trans %}new key{% endtrans %}', array('new key' => 'messages')),
|
||||||
array('{% trans %} new key {% endtrans %}', array('new key' => 'messages')),
|
array('{% trans %} new key {% endtrans %}', array('new key' => 'messages')),
|
||||||
array('{% trans from "domain" %}new key{% endtrans %}', array('new key' => 'domain')),
|
array('{% trans from "domain" %}new key{% endtrans %}', array('new key' => 'domain')),
|
||||||
@ -67,11 +73,27 @@ class TwigExtractorTest extends TestCase
|
|||||||
|
|
||||||
// make sure 'trans_default_domain' tag is supported
|
// make sure 'trans_default_domain' tag is supported
|
||||||
array('{% trans_default_domain "domain" %}{{ "new key"|trans }}', array('new key' => 'domain')),
|
array('{% trans_default_domain "domain" %}{{ "new key"|trans }}', array('new key' => 'domain')),
|
||||||
array('{% trans_default_domain "domain" %}{{ "new key"|transchoice }}', array('new key' => 'domain')),
|
|
||||||
array('{% trans_default_domain "domain" %}{% trans %}new key{% endtrans %}', array('new key' => 'domain')),
|
array('{% trans_default_domain "domain" %}{% trans %}new key{% endtrans %}', array('new key' => 'domain')),
|
||||||
|
|
||||||
// make sure this works with twig's named arguments
|
// make sure this works with twig's named arguments
|
||||||
array('{{ "new key" | trans(domain="domain") }}', array('new key' => 'domain')),
|
array('{{ "new key" | trans(domain="domain") }}', array('new key' => 'domain')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
|
public function getLegacyExtractData()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array('{{ "new key" | transchoice(1) }}', array('new key' => 'messages')),
|
||||||
|
array('{{ "new key" | transchoice(1) | upper }}', array('new key' => 'messages')),
|
||||||
|
array('{{ "new key" | transchoice(1, {}, "domain") }}', array('new key' => 'domain')),
|
||||||
|
|
||||||
|
// make sure 'trans_default_domain' tag is supported
|
||||||
|
array('{% trans_default_domain "domain" %}{{ "new key"|transchoice }}', array('new key' => 'domain')),
|
||||||
|
|
||||||
|
// make sure this works with twig's named arguments
|
||||||
array('{{ "new key" | transchoice(domain="domain", count=1) }}', array('new key' => 'domain')),
|
array('{{ "new key" | transchoice(domain="domain", count=1) }}', array('new key' => 'domain')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ use Twig\Token;
|
|||||||
* Token Parser for the 'transchoice' tag.
|
* Token Parser for the 'transchoice' tag.
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.2, use the "trans" tag with a "%count%" parameter instead
|
||||||
*/
|
*/
|
||||||
class TransChoiceTokenParser extends TransTokenParser
|
class TransChoiceTokenParser extends TransTokenParser
|
||||||
{
|
{
|
||||||
@ -38,6 +40,8 @@ class TransChoiceTokenParser extends TransTokenParser
|
|||||||
$lineno = $token->getLine();
|
$lineno = $token->getLine();
|
||||||
$stream = $this->parser->getStream();
|
$stream = $this->parser->getStream();
|
||||||
|
|
||||||
|
@trigger_error(sprintf('The "transchoice" tag is deprecated since Symfony 4.2, use the "trans" one instead with a "%count%" parameter in %s line %d.', $stream->getSourceContext()->getName(), $lineno), E_USER_DEPRECATED);
|
||||||
|
|
||||||
$vars = new ArrayExpression(array(), $lineno);
|
$vars = new ArrayExpression(array(), $lineno);
|
||||||
|
|
||||||
$count = $this->parser->getExpressionParser()->parseExpression();
|
$count = $this->parser->getExpressionParser()->parseExpression();
|
||||||
|
@ -39,10 +39,17 @@ class TransTokenParser extends AbstractTokenParser
|
|||||||
$lineno = $token->getLine();
|
$lineno = $token->getLine();
|
||||||
$stream = $this->parser->getStream();
|
$stream = $this->parser->getStream();
|
||||||
|
|
||||||
|
$count = null;
|
||||||
$vars = new ArrayExpression(array(), $lineno);
|
$vars = new ArrayExpression(array(), $lineno);
|
||||||
$domain = null;
|
$domain = null;
|
||||||
$locale = null;
|
$locale = null;
|
||||||
if (!$stream->test(Token::BLOCK_END_TYPE)) {
|
if (!$stream->test(Token::BLOCK_END_TYPE)) {
|
||||||
|
if ($stream->test('count')) {
|
||||||
|
// {% trans count 5 %}
|
||||||
|
$stream->next();
|
||||||
|
$count = $this->parser->getExpressionParser()->parseExpression();
|
||||||
|
}
|
||||||
|
|
||||||
if ($stream->test('with')) {
|
if ($stream->test('with')) {
|
||||||
// {% trans with vars %}
|
// {% trans with vars %}
|
||||||
$stream->next();
|
$stream->next();
|
||||||
@ -74,7 +81,7 @@ class TransTokenParser extends AbstractTokenParser
|
|||||||
|
|
||||||
$stream->expect(Token::BLOCK_END_TYPE);
|
$stream->expect(Token::BLOCK_END_TYPE);
|
||||||
|
|
||||||
return new TransNode($body, $domain, null, $vars, $locale, $lineno, $this->getTag());
|
return new TransNode($body, $domain, $count, $vars, $locale, $lineno, $this->getTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function decideTransFork($token)
|
public function decideTransFork($token)
|
||||||
|
@ -18,6 +18,7 @@ CHANGELOG
|
|||||||
the "APP_ENV" environment variable instead.
|
the "APP_ENV" environment variable instead.
|
||||||
* Deprecated the `--no-debug` console option, set the "APP_DEBUG"
|
* Deprecated the `--no-debug` console option, set the "APP_DEBUG"
|
||||||
environment variable to "0" instead.
|
environment variable to "0" instead.
|
||||||
|
* Deprecated the `Templating\Helper\TranslatorHelper::transChoice()` method, use the `trans()` one instead with a `%count%` parameter
|
||||||
|
|
||||||
4.1.0
|
4.1.0
|
||||||
-----
|
-----
|
||||||
|
@ -26,6 +26,7 @@ use Symfony\Component\Translation\LoggingTranslator;
|
|||||||
use Symfony\Component\Translation\MessageCatalogue;
|
use Symfony\Component\Translation\MessageCatalogue;
|
||||||
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
|
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
|
||||||
use Symfony\Component\Translation\Translator;
|
use Symfony\Component\Translation\Translator;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,8 +51,14 @@ class TranslationDebugCommand extends Command
|
|||||||
private $defaultTransPath;
|
private $defaultTransPath;
|
||||||
private $defaultViewsPath;
|
private $defaultViewsPath;
|
||||||
|
|
||||||
public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null)
|
/**
|
||||||
|
* @param TranslatorInterface $translator
|
||||||
|
*/
|
||||||
|
public function __construct($translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null)
|
||||||
{
|
{
|
||||||
|
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
|
namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
|
||||||
|
|
||||||
use Symfony\Component\Templating\Helper\Helper;
|
use Symfony\Component\Templating\Helper\Helper;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorTrait;
|
use Symfony\Contracts\Translation\TranslatorTrait;
|
||||||
|
|
||||||
@ -24,13 +25,18 @@ class TranslatorHelper extends Helper
|
|||||||
getLocale as private;
|
getLocale as private;
|
||||||
setLocale as private;
|
setLocale as private;
|
||||||
trans as private doTrans;
|
trans as private doTrans;
|
||||||
transChoice as private doTransChoice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected $translator;
|
protected $translator;
|
||||||
|
|
||||||
public function __construct(TranslatorInterface $translator = null)
|
/**
|
||||||
|
* @param TranslatorInterface|null $translator
|
||||||
|
*/
|
||||||
|
public function __construct($translator = null)
|
||||||
{
|
{
|
||||||
|
if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,11 +54,17 @@ class TranslatorHelper extends Helper
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see TranslatorInterface::transChoice()
|
* @see TranslatorInterface::transChoice()
|
||||||
|
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
|
||||||
*/
|
*/
|
||||||
public function transChoice($id, $number, array $parameters = array(), $domain = 'messages', $locale = null)
|
public function transChoice($id, $number, array $parameters = array(), $domain = 'messages', $locale = null)
|
||||||
{
|
{
|
||||||
|
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%count%" parameter.', __METHOD__), E_USER_DEPRECATED);
|
||||||
|
|
||||||
if (null === $this->translator) {
|
if (null === $this->translator) {
|
||||||
return $this->doTransChoice($id, $number, $parameters, $domain, $locale);
|
return $this->doTrans($id, array('%count%' => $number) + $parameters, $domain, $locale);
|
||||||
|
}
|
||||||
|
if ($this->translator instanceof TranslatorInterface) {
|
||||||
|
return $this->translator->trans($id, array('%count%' => $number) + $parameters, $domain, $locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
|
return $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
|
||||||
|
@ -52,14 +52,27 @@ class TranslatorTest extends TestCase
|
|||||||
$this->assertEquals('foo (FR)', $translator->trans('foo'));
|
$this->assertEquals('foo (FR)', $translator->trans('foo'));
|
||||||
$this->assertEquals('bar (EN)', $translator->trans('bar'));
|
$this->assertEquals('bar (EN)', $translator->trans('bar'));
|
||||||
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
|
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
|
||||||
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
|
$this->assertEquals('choice 0 (EN)', $translator->trans('choice', array('%count%' => 0)));
|
||||||
$this->assertEquals('no translation', $translator->trans('no translation'));
|
$this->assertEquals('no translation', $translator->trans('no translation'));
|
||||||
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
|
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
|
||||||
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
|
$this->assertEquals('other choice 1 (PT-BR)', $translator->trans('other choice', array('%count%' => 1)));
|
||||||
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
|
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
|
||||||
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
|
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
|
public function testTransChoiceWithoutCaching()
|
||||||
|
{
|
||||||
|
$translator = $this->getTranslator($this->getLoader());
|
||||||
|
$translator->setLocale('fr');
|
||||||
|
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
|
||||||
|
|
||||||
|
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
|
||||||
|
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
|
||||||
|
}
|
||||||
|
|
||||||
public function testTransWithCaching()
|
public function testTransWithCaching()
|
||||||
{
|
{
|
||||||
// prime the cache
|
// prime the cache
|
||||||
@ -70,10 +83,10 @@ class TranslatorTest extends TestCase
|
|||||||
$this->assertEquals('foo (FR)', $translator->trans('foo'));
|
$this->assertEquals('foo (FR)', $translator->trans('foo'));
|
||||||
$this->assertEquals('bar (EN)', $translator->trans('bar'));
|
$this->assertEquals('bar (EN)', $translator->trans('bar'));
|
||||||
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
|
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
|
||||||
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
|
$this->assertEquals('choice 0 (EN)', $translator->trans('choice', array('%count%' => 0)));
|
||||||
$this->assertEquals('no translation', $translator->trans('no translation'));
|
$this->assertEquals('no translation', $translator->trans('no translation'));
|
||||||
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
|
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
|
||||||
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
|
$this->assertEquals('other choice 1 (PT-BR)', $translator->trans('other choice', array('%count%' => 1)));
|
||||||
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
|
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
|
||||||
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
|
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
|
||||||
|
|
||||||
@ -88,14 +101,37 @@ class TranslatorTest extends TestCase
|
|||||||
$this->assertEquals('foo (FR)', $translator->trans('foo'));
|
$this->assertEquals('foo (FR)', $translator->trans('foo'));
|
||||||
$this->assertEquals('bar (EN)', $translator->trans('bar'));
|
$this->assertEquals('bar (EN)', $translator->trans('bar'));
|
||||||
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
|
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
|
||||||
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
|
|
||||||
$this->assertEquals('no translation', $translator->trans('no translation'));
|
$this->assertEquals('no translation', $translator->trans('no translation'));
|
||||||
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
|
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
|
||||||
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
|
|
||||||
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
|
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
|
||||||
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
|
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
|
public function testTransChoiceWithCaching()
|
||||||
|
{
|
||||||
|
// prime the cache
|
||||||
|
$translator = $this->getTranslator($this->getLoader(), array('cache_dir' => $this->tmpDir));
|
||||||
|
$translator->setLocale('fr');
|
||||||
|
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
|
||||||
|
|
||||||
|
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
|
||||||
|
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
|
||||||
|
|
||||||
|
// do it another time as the cache is primed now
|
||||||
|
$loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
|
||||||
|
$loader->expects($this->never())->method('load');
|
||||||
|
|
||||||
|
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir));
|
||||||
|
$translator->setLocale('fr');
|
||||||
|
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
|
||||||
|
|
||||||
|
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
|
||||||
|
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \InvalidArgumentException
|
* @expectedException \InvalidArgumentException
|
||||||
* @expectedExceptionMessage Invalid "invalid locale" locale.
|
* @expectedExceptionMessage Invalid "invalid locale" locale.
|
||||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Form\Extension\Csrf;
|
|||||||
|
|
||||||
use Symfony\Component\Form\AbstractExtension;
|
use Symfony\Component\Form\AbstractExtension;
|
||||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,11 +29,14 @@ class CsrfExtension extends AbstractExtension
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param CsrfTokenManagerInterface $tokenManager The CSRF token manager
|
* @param CsrfTokenManagerInterface $tokenManager The CSRF token manager
|
||||||
* @param TranslatorInterface $translator The translator for translating error messages
|
* @param TranslatorInterface|null $translator The translator for translating error messages
|
||||||
* @param string|null $translationDomain The translation domain for translating
|
* @param string|null $translationDomain The translation domain for translating
|
||||||
*/
|
*/
|
||||||
public function __construct(CsrfTokenManagerInterface $tokenManager, TranslatorInterface $translator = null, string $translationDomain = null)
|
public function __construct(CsrfTokenManagerInterface $tokenManager, $translator = null, string $translationDomain = null)
|
||||||
{
|
{
|
||||||
|
if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 2 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->tokenManager = $tokenManager;
|
$this->tokenManager = $tokenManager;
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
$this->translationDomain = $translationDomain;
|
$this->translationDomain = $translationDomain;
|
||||||
|
@ -18,6 +18,7 @@ use Symfony\Component\Form\FormEvents;
|
|||||||
use Symfony\Component\Form\Util\ServerParams;
|
use Symfony\Component\Form\Util\ServerParams;
|
||||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,8 +41,14 @@ class CsrfValidationListener implements EventSubscriberInterface
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __construct(string $fieldName, CsrfTokenManagerInterface $tokenManager, string $tokenId, string $errorMessage, TranslatorInterface $translator = null, string $translationDomain = null, ServerParams $serverParams = null)
|
/**
|
||||||
|
* @param TranslatorInterface|null $translator
|
||||||
|
*/
|
||||||
|
public function __construct(string $fieldName, CsrfTokenManagerInterface $tokenManager, string $tokenId, string $errorMessage, $translator = null, string $translationDomain = null, ServerParams $serverParams = null)
|
||||||
{
|
{
|
||||||
|
if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 5 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->fieldName = $fieldName;
|
$this->fieldName = $fieldName;
|
||||||
$this->tokenManager = $tokenManager;
|
$this->tokenManager = $tokenManager;
|
||||||
$this->tokenId = $tokenId;
|
$this->tokenId = $tokenId;
|
||||||
|
@ -19,6 +19,7 @@ use Symfony\Component\Form\FormView;
|
|||||||
use Symfony\Component\Form\Util\ServerParams;
|
use Symfony\Component\Form\Util\ServerParams;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,8 +34,14 @@ class FormTypeCsrfExtension extends AbstractTypeExtension
|
|||||||
private $translationDomain;
|
private $translationDomain;
|
||||||
private $serverParams;
|
private $serverParams;
|
||||||
|
|
||||||
public function __construct(CsrfTokenManagerInterface $defaultTokenManager, bool $defaultEnabled = true, string $defaultFieldName = '_token', TranslatorInterface $translator = null, string $translationDomain = null, ServerParams $serverParams = null)
|
/**
|
||||||
|
* @param TranslatorInterface|null $translator
|
||||||
|
*/
|
||||||
|
public function __construct(CsrfTokenManagerInterface $defaultTokenManager, bool $defaultEnabled = true, string $defaultFieldName = '_token', $translator = null, string $translationDomain = null, ServerParams $serverParams = null)
|
||||||
{
|
{
|
||||||
|
if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 4 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->defaultTokenManager = $defaultTokenManager;
|
$this->defaultTokenManager = $defaultTokenManager;
|
||||||
$this->defaultEnabled = $defaultEnabled;
|
$this->defaultEnabled = $defaultEnabled;
|
||||||
$this->defaultFieldName = $defaultFieldName;
|
$this->defaultFieldName = $defaultFieldName;
|
||||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\Form\Extension\Validator\Type;
|
|||||||
use Symfony\Component\Form\AbstractTypeExtension;
|
use Symfony\Component\Form\AbstractTypeExtension;
|
||||||
use Symfony\Component\OptionsResolver\Options;
|
use Symfony\Component\OptionsResolver\Options;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,8 +26,14 @@ class UploadValidatorExtension extends AbstractTypeExtension
|
|||||||
private $translator;
|
private $translator;
|
||||||
private $translationDomain;
|
private $translationDomain;
|
||||||
|
|
||||||
public function __construct(TranslatorInterface $translator, string $translationDomain = null)
|
/**
|
||||||
|
* @param TranslatorInterface $translator
|
||||||
|
*/
|
||||||
|
public function __construct($translator, string $translationDomain = null)
|
||||||
{
|
{
|
||||||
|
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
$this->translationDomain = $translationDomain;
|
$this->translationDomain = $translationDomain;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ use Symfony\Component\HttpFoundation\RequestStack;
|
|||||||
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
||||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||||
use Symfony\Component\HttpKernel\KernelEvents;
|
use Symfony\Component\HttpKernel\KernelEvents;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,8 +30,14 @@ class TranslatorListener implements EventSubscriberInterface
|
|||||||
private $translator;
|
private $translator;
|
||||||
private $requestStack;
|
private $requestStack;
|
||||||
|
|
||||||
public function __construct(TranslatorInterface $translator, RequestStack $requestStack)
|
/**
|
||||||
|
* @param TranslatorInterface $translator
|
||||||
|
*/
|
||||||
|
public function __construct($translator, RequestStack $requestStack)
|
||||||
{
|
{
|
||||||
|
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
$this->requestStack = $requestStack;
|
$this->requestStack = $requestStack;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ CHANGELOG
|
|||||||
-----
|
-----
|
||||||
|
|
||||||
* Started using ICU parent locales as fallback locales.
|
* Started using ICU parent locales as fallback locales.
|
||||||
|
* deprecated `Translator::transChoice()` in favor of using `Translator::trans()` with a `%count%` parameter
|
||||||
* deprecated `TranslatorInterface` in favor of `Symfony\Contracts\Translation\TranslatorInterface`
|
* deprecated `TranslatorInterface` in favor of `Symfony\Contracts\Translation\TranslatorInterface`
|
||||||
* deprecated `MessageSelector`, `Interval` and `PluralizationRules`; use `IdentityTranslator` instead
|
* deprecated `MessageSelector`, `Interval` and `PluralizationRules`; use `IdentityTranslator` instead
|
||||||
* Added `IntlMessageFormatter` and `FallbackMessageFormatter`
|
* Added `IntlMessageFormatter` and `FallbackMessageFormatter`
|
||||||
|
@ -18,7 +18,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
|||||||
/**
|
/**
|
||||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||||
*/
|
*/
|
||||||
class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorBagInterface
|
class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorInterface, TranslatorBagInterface
|
||||||
{
|
{
|
||||||
const MESSAGE_DEFINED = 0;
|
const MESSAGE_DEFINED = 0;
|
||||||
const MESSAGE_MISSING = 1;
|
const MESSAGE_MISSING = 1;
|
||||||
@ -34,8 +34,11 @@ class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorBa
|
|||||||
/**
|
/**
|
||||||
* @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
|
* @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
|
||||||
*/
|
*/
|
||||||
public function __construct(TranslatorInterface $translator)
|
public function __construct($translator)
|
||||||
{
|
{
|
||||||
|
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
if (!$translator instanceof TranslatorBagInterface) {
|
if (!$translator instanceof TranslatorBagInterface) {
|
||||||
throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface and TranslatorBagInterface.', \get_class($translator)));
|
throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface and TranslatorBagInterface.', \get_class($translator)));
|
||||||
}
|
}
|
||||||
@ -56,11 +59,18 @@ class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorBa
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
|
||||||
*/
|
*/
|
||||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
||||||
{
|
{
|
||||||
|
if ($this->translator instanceof TranslatorInterface) {
|
||||||
|
$trans = $this->translator->trans($id, array('%count%' => $number) + $parameters, $domain, $locale);
|
||||||
|
}
|
||||||
|
|
||||||
$trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
|
$trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
|
||||||
$this->collectMessage($locale, $domain, $id, $trans, $parameters, $number);
|
|
||||||
|
$this->collectMessage($locale, $domain, $id, $trans, array('%count%' => $number) + $parameters);
|
||||||
|
|
||||||
return $trans;
|
return $trans;
|
||||||
}
|
}
|
||||||
@ -125,9 +135,8 @@ class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorBa
|
|||||||
* @param string $id
|
* @param string $id
|
||||||
* @param string $translation
|
* @param string $translation
|
||||||
* @param array|null $parameters
|
* @param array|null $parameters
|
||||||
* @param int|null $number
|
|
||||||
*/
|
*/
|
||||||
private function collectMessage($locale, $domain, $id, $translation, $parameters = array(), $number = null)
|
private function collectMessage($locale, $domain, $id, $translation, $parameters = array())
|
||||||
{
|
{
|
||||||
if (null === $domain) {
|
if (null === $domain) {
|
||||||
$domain = 'messages';
|
$domain = 'messages';
|
||||||
@ -160,8 +169,8 @@ class DataCollectorTranslator implements LegacyTranslatorInterface, TranslatorBa
|
|||||||
'id' => $id,
|
'id' => $id,
|
||||||
'translation' => $translation,
|
'translation' => $translation,
|
||||||
'parameters' => $parameters,
|
'parameters' => $parameters,
|
||||||
'transChoiceNumber' => $number,
|
|
||||||
'state' => $state,
|
'state' => $state,
|
||||||
|
'transChoiceNumber' => isset($parameters['%count%']) && is_numeric($parameters['%count%']) ? $parameters['%count%'] : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ namespace Symfony\Component\Translation\Formatter;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.2, use MessageFormatterInterface::format() with a %count% parameter instead
|
||||||
*/
|
*/
|
||||||
interface ChoiceMessageFormatterInterface
|
interface ChoiceMessageFormatterInterface
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Translation\Formatter;
|
|||||||
|
|
||||||
use Symfony\Component\Translation\IdentityTranslator;
|
use Symfony\Component\Translation\IdentityTranslator;
|
||||||
use Symfony\Component\Translation\MessageSelector;
|
use Symfony\Component\Translation\MessageSelector;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,7 +30,7 @@ class MessageFormatter implements MessageFormatterInterface, ChoiceMessageFormat
|
|||||||
{
|
{
|
||||||
if ($translator instanceof MessageSelector) {
|
if ($translator instanceof MessageSelector) {
|
||||||
$translator = new IdentityTranslator($translator);
|
$translator = new IdentityTranslator($translator);
|
||||||
} elseif (null !== $translator && !$translator instanceof TranslatorInterface) {
|
} elseif (null !== $translator && !$translator instanceof TranslatorInterface && !$translator instanceof LegacyTranslatorInterface) {
|
||||||
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,15 +42,27 @@ class MessageFormatter implements MessageFormatterInterface, ChoiceMessageFormat
|
|||||||
*/
|
*/
|
||||||
public function format($message, $locale, array $parameters = array())
|
public function format($message, $locale, array $parameters = array())
|
||||||
{
|
{
|
||||||
|
if ($this->translator instanceof TranslatorInterface) {
|
||||||
|
return $this->translator->trans($message, $parameters, null, $locale);
|
||||||
|
}
|
||||||
|
|
||||||
return strtr($message, $parameters);
|
return strtr($message, $parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.2, use format() with a %count% parameter instead
|
||||||
*/
|
*/
|
||||||
public function choiceFormat($message, $number, $locale, array $parameters = array())
|
public function choiceFormat($message, $number, $locale, array $parameters = array())
|
||||||
{
|
{
|
||||||
$parameters = array_merge(array('%count%' => $number), $parameters);
|
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the format() one instead with a %count% parameter.', __METHOD__), E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
$parameters = array('%count%' => $number) + $parameters;
|
||||||
|
|
||||||
|
if ($this->translator instanceof TranslatorInterface) {
|
||||||
|
return $this->format($message, $locale, $parameters);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->format($this->translator->transChoice($message, $number, array(), null, $locale), $locale, $parameters);
|
return $this->format($this->translator->transChoice($message, $number, array(), null, $locale), $locale, $parameters);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Translation;
|
namespace Symfony\Component\Translation;
|
||||||
|
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorTrait;
|
use Symfony\Contracts\Translation\TranslatorTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,11 +20,9 @@ use Symfony\Contracts\Translation\TranslatorTrait;
|
|||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
*/
|
*/
|
||||||
class IdentityTranslator implements TranslatorInterface
|
class IdentityTranslator implements LegacyTranslatorInterface, TranslatorInterface
|
||||||
{
|
{
|
||||||
use TranslatorTrait {
|
use TranslatorTrait;
|
||||||
transChoice as private doTransChoice;
|
|
||||||
}
|
|
||||||
|
|
||||||
private $selector;
|
private $selector;
|
||||||
|
|
||||||
@ -40,14 +40,18 @@ class IdentityTranslator implements TranslatorInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
|
||||||
*/
|
*/
|
||||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
||||||
{
|
{
|
||||||
|
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%count%" parameter.', __METHOD__), E_USER_DEPRECATED);
|
||||||
|
|
||||||
if ($this->selector) {
|
if ($this->selector) {
|
||||||
return strtr($this->selector->choose((string) $id, (int) $number, $locale ?: $this->getLocale()), $parameters);
|
return strtr($this->selector->choose((string) $id, $number, $locale ?: $this->getLocale()), $parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->doTransChoice($id, $number, $parameters, $domain, $locale);
|
return $this->trans($id, array('%count%' => $number) + $parameters, $domain, $locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getPluralizationRule(int $number, string $locale): int
|
private function getPluralizationRule(int $number, string $locale): int
|
||||||
|
@ -32,8 +32,11 @@ class LoggingTranslator implements LegacyTranslatorInterface, TranslatorBagInter
|
|||||||
* @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
|
* @param TranslatorInterface $translator The translator must implement TranslatorBagInterface
|
||||||
* @param LoggerInterface $logger
|
* @param LoggerInterface $logger
|
||||||
*/
|
*/
|
||||||
public function __construct(TranslatorInterface $translator, LoggerInterface $logger)
|
public function __construct($translator, LoggerInterface $logger)
|
||||||
{
|
{
|
||||||
|
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
if (!$translator instanceof TranslatorBagInterface) {
|
if (!$translator instanceof TranslatorBagInterface) {
|
||||||
throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface and TranslatorBagInterface.', \get_class($translator)));
|
throw new InvalidArgumentException(sprintf('The Translator "%s" must implement TranslatorInterface and TranslatorBagInterface.', \get_class($translator)));
|
||||||
}
|
}
|
||||||
@ -55,10 +58,19 @@ class LoggingTranslator implements LegacyTranslatorInterface, TranslatorBagInter
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
|
||||||
*/
|
*/
|
||||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
||||||
{
|
{
|
||||||
$trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
|
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%count%" parameter.', __METHOD__), E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
if ($this->translator instanceof TranslatorInterface) {
|
||||||
|
$trans = $this->translator->trans($id, array('%count%' => $number) + $parameters, $domain, $locale);
|
||||||
|
} else {
|
||||||
|
$trans = $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
|
||||||
|
}
|
||||||
|
|
||||||
$this->log($id, $domain, $locale);
|
$this->log($id, $domain, $locale);
|
||||||
|
|
||||||
return $trans;
|
return $trans;
|
||||||
|
@ -43,9 +43,9 @@ class MessageSelector
|
|||||||
* The two methods can also be mixed:
|
* The two methods can also be mixed:
|
||||||
* {0} There are no apples|one: There is one apple|more: There are %count% apples
|
* {0} There are no apples|one: There is one apple|more: There are %count% apples
|
||||||
*
|
*
|
||||||
* @param string $message The message being translated
|
* @param string $message The message being translated
|
||||||
* @param int $number The number of items represented for the message
|
* @param int|float $number The number of items represented for the message
|
||||||
* @param string $locale The locale to use for choosing
|
* @param string $locale The locale to use for choosing
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
*
|
||||||
|
@ -25,7 +25,7 @@ class DataCollectorTranslatorTest extends TestCase
|
|||||||
|
|
||||||
$collector->trans('foo');
|
$collector->trans('foo');
|
||||||
$collector->trans('bar');
|
$collector->trans('bar');
|
||||||
$collector->transChoice('choice', 0);
|
$collector->trans('choice', array('%count%' => 0));
|
||||||
$collector->trans('bar_ru');
|
$collector->trans('bar_ru');
|
||||||
$collector->trans('bar_ru', array('foo' => 'bar'));
|
$collector->trans('bar_ru', array('foo' => 'bar'));
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ class DataCollectorTranslatorTest extends TestCase
|
|||||||
'locale' => 'en',
|
'locale' => 'en',
|
||||||
'domain' => 'messages',
|
'domain' => 'messages',
|
||||||
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||||
'parameters' => array(),
|
'parameters' => array('%count%' => 0),
|
||||||
'transChoiceNumber' => 0,
|
'transChoiceNumber' => 0,
|
||||||
);
|
);
|
||||||
$expectedMessages[] = array(
|
$expectedMessages[] = array(
|
||||||
@ -79,6 +79,30 @@ class DataCollectorTranslatorTest extends TestCase
|
|||||||
$this->assertEquals($expectedMessages, $collector->getCollectedMessages());
|
$this->assertEquals($expectedMessages, $collector->getCollectedMessages());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
|
public function testCollectMessagesTransChoice()
|
||||||
|
{
|
||||||
|
$collector = $this->createCollector();
|
||||||
|
$collector->setFallbackLocales(array('fr', 'ru'));
|
||||||
|
$collector->transChoice('choice', 0);
|
||||||
|
|
||||||
|
$expectedMessages = array();
|
||||||
|
|
||||||
|
$expectedMessages[] = array(
|
||||||
|
'id' => 'choice',
|
||||||
|
'translation' => 'choice',
|
||||||
|
'locale' => 'en',
|
||||||
|
'domain' => 'messages',
|
||||||
|
'state' => DataCollectorTranslator::MESSAGE_MISSING,
|
||||||
|
'parameters' => array('%count%' => 0),
|
||||||
|
'transChoiceNumber' => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals($expectedMessages, $collector->getCollectedMessages());
|
||||||
|
}
|
||||||
|
|
||||||
private function createCollector()
|
private function createCollector()
|
||||||
{
|
{
|
||||||
$translator = new Translator('en');
|
$translator = new Translator('en');
|
||||||
|
@ -26,6 +26,7 @@ class MessageFormatterTest extends TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider getTransChoiceMessages
|
* @dataProvider getTransChoiceMessages
|
||||||
|
* @group legacy
|
||||||
*/
|
*/
|
||||||
public function testFormatPlural($expected, $message, $number, $parameters)
|
public function testFormatPlural($expected, $message, $number, $parameters)
|
||||||
{
|
{
|
||||||
|
@ -21,17 +21,19 @@ class LoggingTranslatorTest extends TestCase
|
|||||||
public function testTransWithNoTranslationIsLogged()
|
public function testTransWithNoTranslationIsLogged()
|
||||||
{
|
{
|
||||||
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||||
$logger->expects($this->exactly(2))
|
$logger->expects($this->exactly(1))
|
||||||
->method('warning')
|
->method('warning')
|
||||||
->with('Translation not found.')
|
->with('Translation not found.')
|
||||||
;
|
;
|
||||||
|
|
||||||
$translator = new Translator('ar');
|
$translator = new Translator('ar');
|
||||||
$loggableTranslator = new LoggingTranslator($translator, $logger);
|
$loggableTranslator = new LoggingTranslator($translator, $logger);
|
||||||
$loggableTranslator->transChoice('some_message2', 10, array('%count%' => 10));
|
|
||||||
$loggableTranslator->trans('bar');
|
$loggableTranslator->trans('bar');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
public function testTransChoiceFallbackIsLogged()
|
public function testTransChoiceFallbackIsLogged()
|
||||||
{
|
{
|
||||||
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||||
@ -47,4 +49,20 @@ class LoggingTranslatorTest extends TestCase
|
|||||||
$loggableTranslator = new LoggingTranslator($translator, $logger);
|
$loggableTranslator = new LoggingTranslator($translator, $logger);
|
||||||
$loggableTranslator->transChoice('some_message2', 10, array('%count%' => 10));
|
$loggableTranslator->transChoice('some_message2', 10, array('%count%' => 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
|
public function testTransChoiceWithNoTranslationIsLogged()
|
||||||
|
{
|
||||||
|
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
|
||||||
|
$logger->expects($this->exactly(1))
|
||||||
|
->method('warning')
|
||||||
|
->with('Translation not found.')
|
||||||
|
;
|
||||||
|
|
||||||
|
$translator = new Translator('ar');
|
||||||
|
$loggableTranslator = new LoggingTranslator($translator, $logger);
|
||||||
|
$loggableTranslator->transChoice('some_message2', 10, array('%count%' => 10));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,6 +393,7 @@ class TranslatorTest extends TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider getTransChoiceTests
|
* @dataProvider getTransChoiceTests
|
||||||
|
* @group legacy
|
||||||
*/
|
*/
|
||||||
public function testTransChoice($expected, $id, $translation, $number, $parameters, $locale, $domain)
|
public function testTransChoice($expected, $id, $translation, $number, $parameters, $locale, $domain)
|
||||||
{
|
{
|
||||||
@ -406,6 +407,7 @@ class TranslatorTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @dataProvider getInvalidLocalesTests
|
* @dataProvider getInvalidLocalesTests
|
||||||
* @expectedException \Symfony\Component\Translation\Exception\InvalidArgumentException
|
* @expectedException \Symfony\Component\Translation\Exception\InvalidArgumentException
|
||||||
|
* @group legacy
|
||||||
*/
|
*/
|
||||||
public function testTransChoiceInvalidLocale($locale)
|
public function testTransChoiceInvalidLocale($locale)
|
||||||
{
|
{
|
||||||
@ -418,6 +420,7 @@ class TranslatorTest extends TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider getValidLocalesTests
|
* @dataProvider getValidLocalesTests
|
||||||
|
* @group legacy
|
||||||
*/
|
*/
|
||||||
public function testTransChoiceValidLocale($locale)
|
public function testTransChoiceValidLocale($locale)
|
||||||
{
|
{
|
||||||
@ -499,7 +502,7 @@ class TranslatorTest extends TestCase
|
|||||||
array('Il y a 0 pomme', new StringClass('{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples'), '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array(), 'fr', ''),
|
array('Il y a 0 pomme', new StringClass('{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples'), '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array(), 'fr', ''),
|
||||||
|
|
||||||
// Override %count% with a custom value
|
// Override %count% with a custom value
|
||||||
array('Il y a quelques pommes', 'one: There is one apple|more: There are %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 2, array('%count%' => 'quelques'), 'fr', ''),
|
array('Il y a quelques pommes', 'one: There is one apple|more: There are %count% apples', 'one: Il y a %count% pomme|more: Il y a quelques pommes', 2, array('%count%' => 'quelques'), 'fr', ''),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,6 +540,9 @@ class TranslatorTest extends TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
public function testTransChoiceFallback()
|
public function testTransChoiceFallback()
|
||||||
{
|
{
|
||||||
$translator = new Translator('ru');
|
$translator = new Translator('ru');
|
||||||
@ -547,6 +553,9 @@ class TranslatorTest extends TestCase
|
|||||||
$this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
|
$this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
public function testTransChoiceFallbackBis()
|
public function testTransChoiceFallbackBis()
|
||||||
{
|
{
|
||||||
$translator = new Translator('ru');
|
$translator = new Translator('ru');
|
||||||
@ -557,6 +566,9 @@ class TranslatorTest extends TestCase
|
|||||||
$this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
|
$this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
public function testTransChoiceFallbackWithNoTranslation()
|
public function testTransChoiceFallbackWithNoTranslation()
|
||||||
{
|
{
|
||||||
$translator = new Translator('ru');
|
$translator = new Translator('ru');
|
||||||
|
@ -22,11 +22,13 @@ use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface;
|
|||||||
use Symfony\Component\Translation\Formatter\MessageFormatter;
|
use Symfony\Component\Translation\Formatter\MessageFormatter;
|
||||||
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
|
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
|
||||||
use Symfony\Component\Translation\Loader\LoaderInterface;
|
use Symfony\Component\Translation\Loader\LoaderInterface;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
*/
|
*/
|
||||||
class Translator implements TranslatorInterface, TranslatorBagInterface
|
class Translator implements LegacyTranslatorInterface, TranslatorInterface, TranslatorBagInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var MessageCatalogueInterface[]
|
* @var MessageCatalogueInterface[]
|
||||||
@ -199,9 +201,13 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
|
||||||
*/
|
*/
|
||||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
||||||
{
|
{
|
||||||
|
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%count%" parameter.', __METHOD__), E_USER_DEPRECATED);
|
||||||
|
|
||||||
if (!$this->formatter instanceof ChoiceMessageFormatterInterface) {
|
if (!$this->formatter instanceof ChoiceMessageFormatterInterface) {
|
||||||
throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', \get_class($this->formatter)));
|
throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', \get_class($this->formatter)));
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,59 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Translation;
|
namespace Symfony\Component\Translation;
|
||||||
|
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface as BaseTranslatorInterface;
|
use Symfony\Component\Translation\Exception\InvalidArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* TranslatorInterface.
|
||||||
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
*
|
*
|
||||||
* @deprecated since Symfony 4.2, use the same interface from the Symfony\Contracts\Translation namespace
|
* @deprecated since Symfony 4.2, use Symfony\Contracts\Translation\TranslatorInterface instead
|
||||||
*/
|
*/
|
||||||
interface TranslatorInterface extends BaseTranslatorInterface
|
interface TranslatorInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Translates the given message.
|
||||||
|
*
|
||||||
|
* @param string $id The message id (may also be an object that can be cast to string)
|
||||||
|
* @param array $parameters An array of parameters for the message
|
||||||
|
* @param string|null $domain The domain for the message or null to use the default
|
||||||
|
* @param string|null $locale The locale or null to use the default
|
||||||
|
*
|
||||||
|
* @return string The translated string
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If the locale contains invalid characters
|
||||||
|
*/
|
||||||
|
public function trans($id, array $parameters = array(), $domain = null, $locale = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates the given choice message by choosing a translation according to a number.
|
||||||
|
*
|
||||||
|
* @param string $id The message id (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 array $parameters An array of parameters for the message
|
||||||
|
* @param string|null $domain The domain for the message or null to use the default
|
||||||
|
* @param string|null $locale The locale or null to use the default
|
||||||
|
*
|
||||||
|
* @return string The translated string
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If the locale contains invalid characters
|
||||||
|
*/
|
||||||
|
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current locale.
|
||||||
|
*
|
||||||
|
* @param string $locale The locale
|
||||||
|
*
|
||||||
|
* @throws InvalidArgumentException If the locale contains invalid characters
|
||||||
|
*/
|
||||||
|
public function setLocale($locale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current locale.
|
||||||
|
*
|
||||||
|
* @return string The locale
|
||||||
|
*/
|
||||||
|
public function getLocale();
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Validator\Context;
|
namespace Symfony\Component\Validator\Context;
|
||||||
|
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
use Symfony\Component\Validator\ConstraintViolation;
|
use Symfony\Component\Validator\ConstraintViolation;
|
||||||
use Symfony\Component\Validator\ConstraintViolationList;
|
use Symfony\Component\Validator\ConstraintViolationList;
|
||||||
@ -140,8 +141,11 @@ class ExecutionContext implements ExecutionContextInterface
|
|||||||
* @internal Called by {@link ExecutionContextFactory}. Should not be used
|
* @internal Called by {@link ExecutionContextFactory}. Should not be used
|
||||||
* in user code.
|
* in user code.
|
||||||
*/
|
*/
|
||||||
public function __construct(ValidatorInterface $validator, $root, TranslatorInterface $translator, string $translationDomain = null)
|
public function __construct(ValidatorInterface $validator, $root, $translator, string $translationDomain = null)
|
||||||
{
|
{
|
||||||
|
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 3 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->validator = $validator;
|
$this->validator = $validator;
|
||||||
$this->root = $root;
|
$this->root = $root;
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Validator\Context;
|
namespace Symfony\Component\Validator\Context;
|
||||||
|
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
@ -34,8 +35,12 @@ class ExecutionContextFactory implements ExecutionContextFactoryInterface
|
|||||||
* use for translating
|
* use for translating
|
||||||
* violation messages
|
* violation messages
|
||||||
*/
|
*/
|
||||||
public function __construct(TranslatorInterface $translator, string $translationDomain = null)
|
public function __construct($translator, string $translationDomain = null)
|
||||||
{
|
{
|
||||||
|
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
|
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
$this->translationDomain = $translationDomain;
|
$this->translationDomain = $translationDomain;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
|||||||
/**
|
/**
|
||||||
* @internal to be removed in Symfony 5.0.
|
* @internal to be removed in Symfony 5.0.
|
||||||
*/
|
*/
|
||||||
class LegacyTranslatorProxy implements LegacyTranslatorInterface
|
class LegacyTranslatorProxy implements LegacyTranslatorInterface, TranslatorInterface
|
||||||
{
|
{
|
||||||
private $translator;
|
private $translator;
|
||||||
|
|
||||||
@ -60,6 +60,6 @@ class LegacyTranslatorProxy implements LegacyTranslatorInterface
|
|||||||
*/
|
*/
|
||||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
||||||
{
|
{
|
||||||
return $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
|
return $this->translator->trans($id, array('%count%' => $number) + $parameters, $domain, $locale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\Validator\Violation;
|
namespace Symfony\Component\Validator\Violation;
|
||||||
|
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
use Symfony\Component\Validator\ConstraintViolation;
|
use Symfony\Component\Validator\ConstraintViolation;
|
||||||
use Symfony\Component\Validator\ConstraintViolationList;
|
use Symfony\Component\Validator\ConstraintViolationList;
|
||||||
@ -43,8 +44,14 @@ class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface
|
|||||||
*/
|
*/
|
||||||
private $cause;
|
private $cause;
|
||||||
|
|
||||||
public function __construct(ConstraintViolationList $violations, Constraint $constraint, $message, array $parameters, $root, $propertyPath, $invalidValue, TranslatorInterface $translator, $translationDomain = null)
|
/**
|
||||||
|
* @param TranslatorInterface $translator
|
||||||
|
*/
|
||||||
|
public function __construct(ConstraintViolationList $violations, Constraint $constraint, $message, array $parameters, $root, $propertyPath, $invalidValue, $translator, $translationDomain = null)
|
||||||
{
|
{
|
||||||
|
if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 8 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->violations = $violations;
|
$this->violations = $violations;
|
||||||
$this->message = $message;
|
$this->message = $message;
|
||||||
$this->parameters = $parameters;
|
$this->parameters = $parameters;
|
||||||
@ -147,6 +154,12 @@ class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface
|
|||||||
$this->parameters,
|
$this->parameters,
|
||||||
$this->translationDomain
|
$this->translationDomain
|
||||||
);
|
);
|
||||||
|
} elseif ($this->translator instanceof TranslatorInterface) {
|
||||||
|
$translatedMessage = $this->translator->trans(
|
||||||
|
$this->message,
|
||||||
|
array('%count%' => $this->plural) + $this->parameters,
|
||||||
|
$this->translationDomain
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
$translatedMessage = $this->translator->transChoice(
|
$translatedMessage = $this->translator->transChoice(
|
||||||
|
@ -50,24 +50,24 @@ class TranslatorTest extends TestCase
|
|||||||
/**
|
/**
|
||||||
* @dataProvider getTransChoiceTests
|
* @dataProvider getTransChoiceTests
|
||||||
*/
|
*/
|
||||||
public function testTransChoiceWithExplicitLocale($expected, $id, $number, $parameters)
|
public function testTransChoiceWithExplicitLocale($expected, $id, $number)
|
||||||
{
|
{
|
||||||
$translator = $this->getTranslator();
|
$translator = $this->getTranslator();
|
||||||
$translator->setLocale('en');
|
$translator->setLocale('en');
|
||||||
|
|
||||||
$this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
|
$this->assertEquals($expected, $translator->trans($id, array('%count%' => $number)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider getTransChoiceTests
|
* @dataProvider getTransChoiceTests
|
||||||
*/
|
*/
|
||||||
public function testTransChoiceWithDefaultLocale($expected, $id, $number, $parameters)
|
public function testTransChoiceWithDefaultLocale($expected, $id, $number)
|
||||||
{
|
{
|
||||||
\Locale::setDefault('en');
|
\Locale::setDefault('en');
|
||||||
|
|
||||||
$translator = $this->getTranslator();
|
$translator = $this->getTranslator();
|
||||||
|
|
||||||
$this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
|
$this->assertEquals($expected, $translator->trans($id, array('%count%' => $number)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetSetLocale()
|
public function testGetSetLocale()
|
||||||
@ -103,14 +103,14 @@ class TranslatorTest extends TestCase
|
|||||||
public function getTransChoiceTests()
|
public function getTransChoiceTests()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0, array('%count%' => 0)),
|
array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
|
||||||
array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1, array('%count%' => 1)),
|
array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1),
|
||||||
array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10, array('%count%' => 10)),
|
array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
|
||||||
array('There are 0 apples', 'There is 1 apple|There are %count% apples', 0, array('%count%' => 0)),
|
array('There are 0 apples', 'There is 1 apple|There are %count% apples', 0),
|
||||||
array('There is 1 apple', 'There is 1 apple|There are %count% apples', 1, array('%count%' => 1)),
|
array('There is 1 apple', 'There is 1 apple|There are %count% apples', 1),
|
||||||
array('There are 10 apples', 'There is 1 apple|There are %count% apples', 10, array('%count%' => 10)),
|
array('There are 10 apples', 'There is 1 apple|There are %count% apples', 10),
|
||||||
// custom validation messages may be coded with a fixed value
|
// custom validation messages may be coded with a fixed value
|
||||||
array('There are 2 apples', 'There are 2 apples', 2, array('%count%' => 2)),
|
array('There are 2 apples', 'There are 2 apples', 2),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ class TranslatorTest extends TestCase
|
|||||||
{
|
{
|
||||||
$translator = $this->getTranslator();
|
$translator = $this->getTranslator();
|
||||||
|
|
||||||
$this->assertEquals($expected, $translator->transChoice($interval.' foo|[1,Inf[ bar', $number));
|
$this->assertEquals($expected, $translator->trans($interval.' foo|[1,Inf[ bar', array('%count%' => $number)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInternal()
|
public function getInternal()
|
||||||
@ -146,14 +146,14 @@ class TranslatorTest extends TestCase
|
|||||||
{
|
{
|
||||||
$translator = $this->getTranslator();
|
$translator = $this->getTranslator();
|
||||||
|
|
||||||
$this->assertEquals($expected, $translator->transChoice($id, $number));
|
$this->assertEquals($expected, $translator->trans($id, array('%count%' => $number)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
|
public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
|
||||||
{
|
{
|
||||||
$translator = $this->getTranslator();
|
$translator = $this->getTranslator();
|
||||||
|
|
||||||
$this->assertEquals('There are two apples', $translator->transChoice('There are two apples', 2));
|
$this->assertEquals('There are two apples', $translator->trans('There are two apples', array('%count%' => 2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,7 +164,7 @@ class TranslatorTest extends TestCase
|
|||||||
{
|
{
|
||||||
$translator = $this->getTranslator();
|
$translator = $this->getTranslator();
|
||||||
|
|
||||||
$translator->transChoice($id, $number);
|
$translator->trans($id, array('%count%' => $number));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNonMatchingMessages()
|
public function getNonMatchingMessages()
|
||||||
@ -186,29 +186,29 @@ class TranslatorTest extends TestCase
|
|||||||
|
|
||||||
array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1),
|
array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1),
|
||||||
|
|
||||||
array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
|
array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
|
||||||
array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10),
|
array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10),
|
||||||
array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
|
array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
|
||||||
|
|
||||||
array('There are %count% apples', 'There is one apple|There are %count% apples', 0),
|
array('There are 0 apples', 'There is one apple|There are %count% apples', 0),
|
||||||
array('There is one apple', 'There is one apple|There are %count% apples', 1),
|
array('There is one apple', 'There is one apple|There are %count% apples', 1),
|
||||||
array('There are %count% apples', 'There is one apple|There are %count% apples', 10),
|
array('There are 10 apples', 'There is one apple|There are %count% apples', 10),
|
||||||
|
|
||||||
array('There are %count% apples', 'one: There is one apple|more: There are %count% apples', 0),
|
array('There are 0 apples', 'one: There is one apple|more: There are %count% apples', 0),
|
||||||
array('There is one apple', 'one: There is one apple|more: There are %count% apples', 1),
|
array('There is one apple', 'one: There is one apple|more: There are %count% apples', 1),
|
||||||
array('There are %count% apples', 'one: There is one apple|more: There are %count% apples', 10),
|
array('There are 10 apples', 'one: There is one apple|more: There are %count% apples', 10),
|
||||||
|
|
||||||
array('There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0),
|
array('There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0),
|
||||||
array('There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1),
|
array('There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1),
|
||||||
array('There are %count% apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10),
|
array('There are 10 apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10),
|
||||||
|
|
||||||
array('', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0),
|
array('', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0),
|
||||||
array('', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1),
|
array('', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1),
|
||||||
|
|
||||||
// Indexed only tests which are Gettext PoFile* compatible strings.
|
// Indexed only tests which are Gettext PoFile* compatible strings.
|
||||||
array('There are %count% apples', 'There is one apple|There are %count% apples', 0),
|
array('There are 0 apples', 'There is one apple|There are %count% apples', 0),
|
||||||
array('There is one apple', 'There is one apple|There are %count% apples', 1),
|
array('There is one apple', 'There is one apple|There are %count% apples', 1),
|
||||||
array('There are %count% apples', 'There is one apple|There are %count% apples', 2),
|
array('There are 2 apples', 'There is one apple|There are %count% apples', 2),
|
||||||
|
|
||||||
// Tests for float numbers
|
// Tests for float numbers
|
||||||
array('There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7),
|
array('There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7),
|
||||||
|
@ -19,19 +19,8 @@ interface TranslatorInterface
|
|||||||
/**
|
/**
|
||||||
* Translates the given message.
|
* Translates the given message.
|
||||||
*
|
*
|
||||||
* @param string $id The message id (may also be an object that can be cast to string)
|
* When a number is provided as a parameter named "%count%", the message is parsed for plural
|
||||||
* @param array $parameters An array of parameters for the message
|
* forms and a translation is chosen according to this number using the following rules:
|
||||||
* @param string|null $domain The domain for the message or null to use the default
|
|
||||||
* @param string|null $locale The locale or null to use the default
|
|
||||||
*
|
|
||||||
* @return string The translated string
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException If the locale contains invalid characters
|
|
||||||
*/
|
|
||||||
public function trans($id, array $parameters = array(), $domain = null, $locale = null);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates the given choice message by choosing a translation according to a number.
|
|
||||||
*
|
*
|
||||||
* Given a message with different plural translations separated by a
|
* Given a message with different plural translations separated by a
|
||||||
* pipe (|), this method returns the correct portion of the message based
|
* pipe (|), this method returns the correct portion of the message based
|
||||||
@ -64,7 +53,6 @@ interface TranslatorInterface
|
|||||||
* @see https://en.wikipedia.org/wiki/ISO_31-11
|
* @see https://en.wikipedia.org/wiki/ISO_31-11
|
||||||
*
|
*
|
||||||
* @param string $id The message id (may also be an object that can be cast to string)
|
* @param string $id The message id (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 array $parameters An array of parameters for the message
|
* @param array $parameters An array of parameters for the message
|
||||||
* @param string|null $domain The domain for the message or null to use the default
|
* @param string|null $domain The domain for the message or null to use the default
|
||||||
* @param string|null $locale The locale or null to use the default
|
* @param string|null $locale The locale or null to use the default
|
||||||
@ -73,7 +61,7 @@ interface TranslatorInterface
|
|||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException If the locale contains invalid characters
|
* @throws \InvalidArgumentException If the locale contains invalid characters
|
||||||
*/
|
*/
|
||||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null);
|
public function trans($id, array $parameters = array(), $domain = null, $locale = null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current locale.
|
* Sets the current locale.
|
||||||
|
@ -42,17 +42,14 @@ trait TranslatorTrait
|
|||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function trans($id, array $parameters = array(), $domain = null, $locale = null)
|
public function trans($id, array $parameters = array(), $domain = null, $locale = null)
|
||||||
{
|
|
||||||
return strtr((string) $id, $parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
|
|
||||||
{
|
{
|
||||||
$id = (string) $id;
|
$id = (string) $id;
|
||||||
$number = (float) $number;
|
|
||||||
|
if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) {
|
||||||
|
return strtr($id, $parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
$number = (float) $parameters['%count%'];
|
||||||
$locale = (string) $locale ?: $this->getLocale();
|
$locale = (string) $locale ?: $this->getLocale();
|
||||||
|
|
||||||
$parts = array();
|
$parts = array();
|
||||||
|
Reference in New Issue
Block a user