8000 Make trans + %count% parameter resolve plurals · symfony/symfony@943f23b · GitHub
[go: up one dir, main page]

Skip to content

Commit 943f23b

Browse files
Make trans + %count% parameter resolve plurals
1 parent 640a887 commit 943f23b

38 files changed

+890
-435
lines changed

UPGRADE-4.2.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ FrameworkBundle
108108
serializer:
109109
id: your_messenger_service_id
110110
```
111-
* The `ContainerAwareCommand` class has been deprecated, use `Symfony\Component\Console\Command\Command`
112-
with dependency injection instead.
111+
* The `ContainerAwareCommand` class has been deprecated, use `Symfony\Component\Console\Command\Command` with dependency injection instead.
112+
* The `Templating\Helper\TranslatorHelper::transChoice()` method has been deprecated, use the `trans()` one instead with a `%count%` parameter.
113113

114114
Messenger
115115
---------
@@ -208,9 +208,14 @@ Translation
208208
-----------
209209

210210
* The `TranslatorInterface` has been deprecated in favor of `Symfony\Contracts\Translation\TranslatorInterface`
211-
* The `Translator::transChoice()` has been deprecated in favor of using `Translator::trans()` with intl message format
211+
* The `Translator::transChoice()` method has been deprecated in favor of using `Translator::trans()` with "%count%" as the parameter driving plurals
212212
* The `MessageSelector`, `Interval` and `PluralizationRules` classes have been deprecated, use `IdentityTranslator` instead
213213

214+
TwigBundle
215+
----------
216+
217+
* The `transchoice` tag and filter have been deprecated, use the `trans` ones instead with a `%count%` parameter.
218+
214219
Validator
215220
---------
216221

UPGRADE-5.0.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ FrameworkBundle
114114
* The `RequestDataCollector` class has been removed. Use the `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector` class instead.
115115
* Removed `Symfony\Bundle\FrameworkBundle\Controller\Controller`. Use `Symfony\Bundle\FrameworkBundle\Controller\AbstractController` instead.
116116
* Added support for the SameSite attribute for session cookies. It is highly recommended to set this setting (`framework.session.cookie_samesite`) to `lax` for increased security against CSRF attacks.
117-
* The `ContainerAwareCommand` class has been removed, use `Symfony\Component\Console\Command\Command`
118-
with dependency injection instead.
117+
* The `ContainerAwareCommand` class has been removed, use `Symfony\Component\Console\Command\Command` with dependency injection instead.
118+
* The `Templating\Helper\TranslatorHelper::transChoice()` method has been removed, use the `trans()` one instead with a `%count%` parameter.
119119

120120
HttpFoundation
121121
--------------
@@ -184,11 +184,13 @@ Translation
184184
* The `TranslationWriter::disableBackup()` method has been removed.
185185
* The `TranslatorInterface` has been removed in favor of `Symfony\Contracts\Translation\TranslatorInterface`
186186
* The `MessageSelector`, `Interval` and `PluralizationRules` classes have been removed, use `IdentityTranslator` instead
187+
* The `Translator::transChoice()` method has been removed in favor of using `Translator::trans()` with "%count%" as the parameter driving plurals
187188

188189
TwigBundle
189190
----------
190191

191192
* The default value (`false`) of the `twig.strict_variables` configuration option has been changed to `%kernel.debug%`.
193+
* The `transchoice` tag and filter have been removed, use the `trans` ones instead with a `%count%` parameter.
192194

193195
Validator
194196
--------

src/Symfony/Bridge/Twig/CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ CHANGELOG
44
4.2.0
55
-----
66

7-
* add bundle name suggestion on wrongly overridden templates paths
8-
* added `name` argument in `debug:twig` command and changed `filter` argument as `--filter` option
7+
* add bundle name suggestion on wrongly overridden templates paths
8+
* added `name` argument in `debug:twig` command and changed `filter` argument as `--filter` option
9+
* deprecated the `transchoice` tag and filter, use the `trans` ones instead with a `%count%` parameter
910

1011
4.1.0
1112
-----

src/Symfony/Bridge/Twig/Extension/TranslationExtension.php

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use Symfony\Bridge\Twig\TokenParser\TransChoiceTokenParser;
1717
use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser;
1818
use Symfony\Bridge\Twig\TokenParser\TransTokenParser;
19-
use Symfony\Component\Translation\LegacyTranslatorTrait;
2019
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
2120
use Symfony\Contracts\Translation\TranslatorInterface;
2221
use Symfony\Contracts\Translation\TranslatorTrait;
@@ -29,6 +28,8 @@
2928
* Provides integration of the Translation component with Twig.
3029
*
3130
* @author Fabien Potencier <fabien@symfony.com>
31+
*
32+
* @final since Symfony 4.2
3233
*/
3334
class TranslationExtension extends AbstractExtension
3435
{
@@ -38,21 +39,28 @@ class TranslationExtension extends AbstractExtension
3839
trans as private doTrans;
3940
}
4041

41-
use LegacyTranslatorTrait {
42-
transChoice as private doTransChoice;
43-
}
44-
4542
private $translator;
4643
private $translationNodeVisitor;
4744

48-
public function __construct(TranslatorInterface $translator = null, NodeVisitorInterface $translationNodeVisitor = null)
45+
/**
46+
* @param TranslatorInterface|null $translator
47+
*/
48+
public function __construct($translator = null, NodeVisitorInterface $translationNodeVisitor = null)
4949
{
50+
if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
51+
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)));
52+
}
5053
$this->translator = $translator;
5154
$this->translationNodeVisitor = $translationNodeVisitor;
5255
}
5356

57+
/**
58+
* @deprecated since Symfony 4.2
59+
*/
5460
public function getTranslator()
5561
{
62+
@trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
63+
5664
return $this->translator;
5765
}
5866

@@ -63,7 +71,7 @@ public function getFilters()
6371
{
6472
return array(
6573
new TwigFilter('trans', array($this, 'trans')),
66-
new TwigFilter('transchoice', array($this, 'transchoice')),
74+
new TwigFilter('transchoice', array($this, 'transchoice'), array('deprecated' => '4.2', 'alternative' => 'trans" with parameter "%count%')),
6775
);
6876
}
6977

@@ -101,19 +109,28 @@ public function getTranslationNodeVisitor()
101109
return $this->translationNodeVisitor ?: $this->translationNodeVisitor = new TranslationNodeVisitor();
102110
}
103111

104-
public function trans($message, array $arguments = array(), $domain = null, $locale = null)
112+
public function trans($message, array $arguments = array(), $domain = null, $locale = null, $count = null)
105113
{
114+
if (null !== $count) {
115+
$arguments['%count%'] = $count;
116+
}
106117
if (null === $this->translator) {
107118
return $this->doTrans($message, $arguments, $domain, $locale);
108119
}
109120

110121
return $this->translator->trans($message, $arguments, $domain, $locale);
111122
}
112123

124+
/**
125+
* @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
126+
*/
113127
public function transchoice($message, $count, array $arguments = array(), $domain = null, $locale = null)
114128
{
115-
if (null === $this->translator || !$this->translator instanceof LegacyTranslatorInterface) {
116-
return $this->doTransChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale);
129+
if (null === $this->translator) {
130+
return $this->doTrans($message, array_merge(array('%count%' => $count), $arguments), $domain, $locale);
131+
}
132+
if ($this->translator instanceof TranslatorInterface) {
133+
return $this->translator->trans($message, array_merge(array('%count%' => $count), $arguments), $domain, $locale);
117134
}
118135

119136
return $this->translator->transChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale);

src/Symfony/Bridge/Twig/Node/TransNode.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,12 @@ public function compile(Compiler $compiler)
6060
$method = !$this->hasNode('count') ? 'trans' : 'transChoice';
6161

6262
$compiler
63-
->write('echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->getTranslator()->'.$method.'(')
63+
->write('echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->trans(')
6464
->subcompile($msg)
6565
;
6666

6767
$compiler->raw(', ');
6868

69-
if ($this->hasNode('count')) {
70-
$compiler
71-
->subcompile($this->getNode('count'))
72-
->raw(', ')
73-
;
74-
}
75-
C2EE
7669
if (null !== $vars) {
7770
$compiler
7871
->raw('array_merge(')
@@ -98,7 +91,17 @@ public function compile(Compiler $compiler)
9891
->raw(', ')
9992
->subcompile($this->getNode('locale'))
10093
;
94+
} elseif ($this->hasNode('count')) {
95+
$compiler->raw(', null');
10196
}
97+
98+
if ($this->hasNode('count')) {
99+
$compiler
100+
->raw(', ')
101+
->subcompile($this->getNode('count'))
102+
;
103+
}
104+
102105
$compiler->raw(");\n");
103106
}
104107

src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ public function testTrans($template, $expected, array $variables = array())
4545
$this->assertEquals($expected, $this->getTemplate($template)->render($variables));
4646
}
4747

48+
/**
49+
* @group legacy
50+
* @dataProvider getTransChoiceTests
51+
*/
52+
public function testTransChoice($template, $expected, array $variables = array())
53+
{
54+
$this->testTrans($template, $expected, $variables);
55+
}
56+
4857
/**
4958
* @expectedException \Twig\Error\SyntaxError
5059
* @expectedExceptionMessage Unexpected token. Twig was looking for the "with", "from", or "into" keyword in "index" at line 3.
@@ -64,6 +73,7 @@ public function testTransComplexBody()
6473
}
6574

6675
/**
76+
* @group legacy
6777
* @expectedException \Twig\Error\SyntaxError
6878
* @expectedExceptionMessage A message inside a transchoice tag must be a simple text in "index" at line 2.
6979
*/
@@ -87,6 +97,69 @@ public function getTransTests()
8797

8898
array('{% trans into "fr"%}Hello{% endtrans %}', 'Hello'),
8999

100+
// trans with count
101+
array(
102+
'{% trans from "messages" %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtrans %}',
103+
'There is no apples',
104+
array('count' => 0),
105+
),
106+
array(
107+
'{% trans %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtrans %}',
108+
'There is 5 apples',
109+
array('count' => 5),
110+
),
111+
array(
112+
'{% trans %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtrans %}',
113+
'There is 5 apples (Symfony)',
114+
array('count' => 5, 'name' => 'Symfony'),
115+
),
116+
array(
117+
'{% trans with { \'%name%\': \'Symfony\' } %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtrans %}',
118+
'There is 5 apples (Symfony)',
119+
array('count' => 5),
120+
),
121+
array(
122+
'{% trans into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtrans %}',
123+
'There is no apples',
124+
array('count' => 0),
125+
),
126+
array(
127+
'{% trans count 5 into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtrans %}',
128+
'There is 5 apples',
129+
),
130+
131+
// trans filter
132+
array('{{ "Hello"|trans }}', 'Hello'),
133+
array('{{ name|trans }}', 'Symfony', array('name' => 'Symfony')),
134+
array('{{ hello|trans({ \'%name%\': \'Symfony\' }) }}', 'Hello Symfony', array('hello' => 'Hello %name%')),
135+
array('{% set vars = { \'%name%\': \'Symfony\' } %}{{ hello|trans(vars) }}', 'Hello Symfony', array('hello' => 'Hello %name%')),
136+
array('{{ "Hello"|trans({}, "messages", "fr") }}', 'Hello'),
137+
138+
// trans filter with count
139+
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)),
140+
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%)')),
141+
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)),
142+
);
143+
}
144+
145+
/**
146+
* @group legacy
147+
*/
148+
public function getTransChoiceTests()
149+
{
150+
return array(
151+
// trans tag
152+
array('{% trans %}Hello{% endtrans %}', 'Hello'),
153+
array('{% trans %}%name%{% endtrans %}', 'Symfony', array('name' => 'Symfony')),
154+
155+
array('{% trans from elsewhere %}Hello{% endtrans %}', 'Hello'),
156+
157+
array('{% trans %}Hello %name%{% endtrans %}', 'Hello Symfony', array('name' => 'Symfony')),
158+
array('{% trans with { \'%name%\': \'Symfony\' } %}Hello %name%{% endtrans %}', 'Hello Symfony'),
159+
array('{% set vars = { \'%name%\': \'Symfony\' } %}{% trans with vars %}Hello %name%{% endtrans %}', 'Hello Symfony'),
160+
161+
array('{% trans into "fr"%}Hello{% endtrans %}', 'Hello'),
162+
90163
// transchoice
91164
array(
92165
'{% 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 @@ public function testDefaultTranslationDomain()
145218
{%- trans from "custom" %}foo{% endtrans %}
146219
{{- "foo"|trans }}
147220
{{- "foo"|trans({}, "custom") }}
148-
{{- "foo"|transchoice(1) }}
149-
{{- "foo"|transchoice(1, {}, "custom") }}
221+
{{- "foo"|trans(count=1) }}
222+
{{- "foo"|trans({"%count%":1}, "custom") }}
150223
{% endblock %}
151224
',
152225

@@ -174,12 +247,12 @@ public function testDefaultTranslationDomainWithNamedArguments()
174247
175248
{%- block content %}
176249
{{- "foo"|trans(arguments = {}, domain = "custom") }}
177-
{{- "foo"|transchoice(count = 1) }}
178-
{{- "foo"|transchoice(count = 1, arguments = {}, domain = "custom") }}
250+
{{- "foo"|trans(count = 1) }}
251+
{{- "foo"|trans(count = 1, arguments = {}, domain = "custom") }}
179252
{{- "foo"|trans({}, domain = "custom") }}
180253
{{- "foo"|trans({}, "custom", locale = "fr") }}
181-
{{- "foo"|transchoice(1, arguments = {}, domain = "custom") }}
182-
{{- "foo"|transchoice(1, {}, "custom", locale = "fr") }}
254+
{{- "foo"|trans(arguments = {"%count%":1}, domain = "custom") }}
255+
{{- "foo"|trans({"%count%":1}, "custom", locale = "fr") }}
183256
{% endblock %}
184257
',
185258

src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function testCompileStrict()
3434

3535
$this->assertEquals(
3636
sprintf(
37-
'echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->getTranslator()->trans("trans %%var%%", array_merge(array("%%var%%" => %s), %s), "messages");',
37+
'echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->trans("trans %%var%%", array_merge(array("%%var%%" => %s), %s), "messages");',
3838
$this->getVariableGetterWithoutStrictCheck('var'),
3939
$this->getVariableGetterWithStrictCheck('foo')
4040
),

src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,21 @@ public function testExtract($template, $messages)
5050
}
5151
}
5252

53+
/**
54+
* @group legacy
55+
* @dataProvider getLegacyExtractData
56+
*/
57+
public function testLegacyExtract($template, $messages)
58+
{
59+
$this->testExtract($template, $messages);
60+
}
61+
5362
public function getExtractData()
5463
{
5564
return array(
5665
array('{{ "new key" | trans() }}', array('new key' => 'messages')),
5766
array('{{ "new key" | trans() | upper }}', array('new key' => 'messages')),
5867
array('{{ "new key" | trans({}, "domain") }}', array('new key' => 'domain')),
59-
array('{{ "new key" | transchoice(1) }}', array('new key' => 'message 10000 s')),
60-
array('{{ "new key" | transchoice(1) | upper }}', array('new key' => 'messages')),
61-
array('{{ "new key" | transchoice(1, {}, "domain") }}', array('new key' => 'domain')),
6268
array('{% trans %}new key{% endtrans %}', array('new key' => 'messages')),
6369
array('{% trans %} new key {% endtrans %}', array('new key' => 'messages')),
6470
array('{% trans from "domain" %}new key{% endtrans %}', array('new key' => 'domain')),
@@ -67,11 +73,27 @@ public function getExtractData()
6773

6874
// make sure 'trans_default_domain' tag is supported
6975
array('{% trans_default_domain "domain" %}{{ "new key"|trans }}', array('new key' => 'domain')),
70-
array('{% trans_default_domain "domain" %}{{ "new key"|transchoice }}', array('new key' => 'domain')),
7176
array('{% trans_default_domain "domain" %}{% trans %}new key{% endtrans %}', array('new key' => 'domain')),
7277

7378
// make sure this works with twig's named arguments
7479
array('{{ "new key" | trans(domain="domain") }}', array('new key' => 'domain')),
80+
);
81+
}
82+
83+
/**
84+
* @group legacy
85+
*/
86+
public function getLegacyExtractData()
87+
{
88+
return array(
89+
array('{{ "new key" | transchoice(1) }}', array('new key' => 'messages')),
90+
array('{{ "new key" | transchoice(1) | upper }}', array('new key' => 'messages')),
91+
array('{{ "new key" | transchoice(1, {}, "domain") }}', array('new key' => 'domain')),
92+
93+
// make sure 'trans_default_domain' tag is supported
94+
array('{% trans_default_domain "domain" %}{{ "new key"|transchoice }}', array('new key' => 'domain')),
95+
96+
// make sure this works with twig's named arguments
7597
array('{{ "new key" | transchoice(domain="domain", count=1) }}', array('new key' => 'domain')),
7698
);
7799
}

src/Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
* Token Parser for the 'transchoice' tag.
2424
*
2525
* @author Fabien Potencier <fabien@symfony.com>
26+
*
27+
* @deprecated since Symfony 4.2, use the "trans" tag with a "%count%" parameter instead
2628
*/
2729
class TransChoiceTokenParser extends TransTokenParser
2830
{
@@ -38,6 +40,8 @@ public function parse(Token $token)
3840
$lineno = $token->getLine();
3941
$stream = $this->parser->getStream();
4042

43+
@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);
44+
4145
$vars = new ArrayExpression(array(), $lineno);
4246

4347
$count = $this->parser->getExpressionParser()->parseExpression();

0 commit comments

Comments
 (0)
0