Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 645cf66

Browse filesBrowse files
committed
[FrameworkBundle] Make Translator works with any PSR-11 container
1 parent 2a99e16 commit 645cf66
Copy full SHA for 645cf66

File tree

Expand file treeCollapse file tree

8 files changed

+215
-21
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+215
-21
lines changed

‎UPGRADE-3.3.md

Copy file name to clipboardExpand all lines: UPGRADE-3.3.md
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ FrameworkBundle
172172
class has been deprecated and will be removed in 4.0. Use the
173173
`Symfony\Component\Routing\DependencyInjection\RoutingResolverPass` class instead.
174174

175+
* The `Symfony\Bundle\FrameworkBundle\Translation\Translator` constructor now takes the
176+
default locale as 3rd argument. Not passing it will trigger an error in 4.0.
177+
175178
HttpKernel
176179
-----------
177180

‎UPGRADE-4.0.md

Copy file name to clipboardExpand all lines: UPGRADE-4.0.md
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,9 @@ FrameworkBundle
271271
class has been removed. Use the
272272
`Symfony\Component\Routing\DependencyInjection\RoutingResolverPass` class instead.
273273

274+
* The `Symfony\Bundle\FrameworkBundle\Translation\Translator` constructor now takes the
275+
default locale as 3rd argument.
276+
274277
HttpFoundation
275278
---------------
276279

‎src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ CHANGELOG
3030
* Deprecated `ControllerArgumentValueResolverPass`. Use
3131
`Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass` instead
3232
* Deprecated `RoutingResolverPass`, use `Symfony\Component\Routing\DependencyInjection\RoutingResolverPass` instead
33+
* Added `$defaultLocale` as 3rd argument of `Translator::__construct()` and
34+
made `Translator` works with any PSR-11 container
3335

3436
3.2.0
3537
-----

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php
+9-2Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
1313

14+
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1415
use Symfony\Component\DependencyInjection\Reference;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
1617
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
@@ -24,7 +25,9 @@ public function process(ContainerBuilder $container)
2425
}
2526

2627
$loaders = array();
28+
$loaderRefs = array();
2729
foreach ($container->findTaggedServiceIds('translation.loader') as $id => $attributes) {
30+
$loaderRefs[$id] = new Reference($id);
2831
$loaders[$id][] = $attributes[0]['alias'];
2932
if (isset($attributes[0]['legacy-alias'])) {
3033
$loaders[$id][] = $attributes[0]['legacy-alias'];
@@ -35,11 +38,15 @@ public function process(ContainerBuilder $container)
3538
$definition = $container->getDefinition('translation.loader');
3639
foreach ($loaders as $id => $formats) {
3740
foreach ($formats as $format) {
38-
$definition->addMethodCall('addLoader', array($format, new Reference($id)));
41+
$definition->addMethodCall('addLoader', array($format, $loaderRefs[$id]));
3942
}
4043
}
4144
}
4245

43-
$container->findDefinition('translator.default')->replaceArgument(2, $loaders);
46+
$container
47+
->findDefinition('translator.default')
48+
->replaceArgument(0, new ServiceLocatorArgument($loaderRefs))
49+
->replaceArgument(3, $loaders)
50+
;
4451
}
4552
}

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66

77
<services>
88
<service id="translator.default" class="Symfony\Bundle\FrameworkBundle\Translation\Translator">
9-
<argument type="service" id="service_container" />
9+
<argument type="service-locator" /> <!-- translation loaders -->
1010
<argument type="service" id="translator.selector" />
11-
<argument type="collection" /> <!-- translation loaders -->
11+
<argument>%kernel.default_locale%</argument>
12+
<argument type="collection" /> <!-- translation loaders ids -->
1213
<argument type="collection">
1314
<argument key="cache_dir">%kernel.cache_dir%/translations</argument>
1415
<argument key="debug">%kernel.debug%</argument>
1516
</argument>
16-
<argument type="collection" /> <!-- translation resources -->
1717
<call method="setConfigCacheFactory">
1818
<argument type="service" id="config_cache_factory" />
1919
</call>

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php
+10-1Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1516
use Symfony\Component\DependencyInjection\Reference;
1617
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
1718

@@ -39,7 +40,15 @@ public function testValidCollector()
3940
->will($this->returnValue(array('xliff' => array(array('alias' => 'xliff', 'legacy-alias' => 'xlf')))));
4041
$container->expects($this->once())
4142
->method('findDefinition')
42-
->will($this->returnValue($this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock()));
43+
->will($this->returnValue($translator = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock()));
44+
$translator->expects($this->at(0))
45+
->method('replaceArgument')
46+
->with(0, $this->equalTo(new ServiceLocatorArgument(array('xliff' => new Reference('xliff')))))
47+
->willReturn($translator);
48+
$translator->expects($this->at(1))
49+
->method('replaceArgument')
50+
->with(3, array('xliff' => array('xliff', 'xlf')))
51+
->willReturn($translator);
4352
$pass = new TranslatorPass();
4453
$pass->process($container);
4554
}

‎src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
+168-12Lines changed: 168 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,159 @@ protected function deleteTmpDir()
4242
$fs->remove($dir);
4343
}
4444

45+
/**
46+
* @group legacy
47+
* @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
48+
*/
49+
public function testTransWithoutCachingOmittingLocale()
50+
{
51+
$translator = $this->getTranslator($this->getLoader(), array(), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
52+
$translator->setLocale('fr');
53+
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
54+
55+
$this->assertEquals('foo (FR)', $translator->trans('foo'));
56+
$this->assertEquals('bar (EN)', $translator->trans('bar'));
57+
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
58+
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
59+
$this->assertEquals('no translation', $translator->trans('no translation'));
60+
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
61+
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
62+
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
63+
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
64+
}
65+
66+
/**
67+
* @group legacy
68+
* @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
69+
*/
70+
public function testTransWithCachingOmittingLocale()
71+
{
72+
// prime the cache
73+
$translator = $this->getTranslator($this->getLoader(), array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
74+
$translator->setLocale('fr');
75+
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
76+
77+
$this->assertEquals('foo (FR)', $translator->trans('foo'));
78+
$this->assertEquals('bar (EN)', $translator->trans('bar'));
79+
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
80+
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
81+
$this->assertEquals('no translation', $translator->trans('no translation'));
82+
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
83+
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
84+
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
85+
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
86+
87+
// do it another time as the cache is primed now
88+
$loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
89+
$loader->expects($this->never())->method('load');
90+
91+
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
92+
$translator->setLocale('fr');
93+
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
94+
95+
$this->assertEquals('foo (FR)', $translator->trans('foo'));
96+
$this->assertEquals('bar (EN)', $translator->trans('bar'));
97+
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
98+
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
99+
$this->assertEquals('no translation', $translator->trans('no translation'));
100+
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
101+
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
102+
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
103+
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
104+
}
105+
106+
/**
107+
* @group legacy
108+
* @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
109+
* @expectedException \InvalidArgumentException
110+
*/
111+
public function testTransWithCachingWithInvalidLocaleOmittingLocale()
112+
{
113+
$loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
114+
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Tests\Translation\TranslatorWithInvalidLocale', null);
115+
116+
$translator->trans('foo');
117+
}
118+
119+
/**
120+
* @group legacy
121+
* @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
122+
*/
123+
public function testLoadResourcesWithoutCachingOmittingLocale()
124+
{
125+
$loader = new \Symfony\Component\Translation\Loader\YamlFileLoader();
126+
$resourceFiles = array(
127+
'fr' => array(
128+
__DIR__.'/../Fixtures/Resources/translations/messages.fr.yml',
129+
),
130+
);
131+
132+
$translator = $this->getTranslator($loader, array('resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
133+
$translator->setLocale('fr');
134+
135+
$this->assertEquals('répertoire', $translator->trans('folder'));
136+
}
137+
138+
/**
139+
* @group legacy
140+
* @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
141+
*/
142+
public function testGetDefaultLocaleOmittingLocale()
143+
{
144+
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
145+
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
146+
$container
147+
->expects($this->once())
148+
->method('getParameter')
149+
->with('kernel.default_locale')
150+
->will($this->returnValue('en'))
151+
;
152+
$translator = new Translator($container, new MessageSelector());
153+
154+
$this->assertSame('en', $translator->getLocale());
155+
}
156+
157+
/**
158+
* @group legacy
159+
* @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
160+
* @expectedException \InvalidArgumentException
161+
* @expectedExceptionMessage A default locale must be passed as 3rd argument of Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() since version 3.3, the argument will be mandatory in 4.0.
162+
*/
163+
public function testGetDefaultLocaleOmittingLocaleWithPsrContainer()
164+
{
165+
$container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock();
166+
$translator = new Translator($container, new MessageSelector());
167+
}
168+
169+
/**
170+
* @group legacy
171+
* @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.
172+
*/
173+
public function testWarmupOmittingLocale()
174+
{
175+
$loader = new \Symfony\Component\Translation\Loader\YamlFileLoader();
176+
$resourceFiles = array(
177+
'fr' => array(
178+
__DIR__.'/../Fixtures/Resources/translations/messages.fr.yml',
179+
),
180+
);
181+
182+
// prime the cache
183+
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
184+
$translator->setFallbackLocales(array('fr'));
185+
$translator->warmup($this->tmpDir);
186+
187+
$loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
188+
$loader
189+
->expects($this->never())
190+
->method('load');
191+
192+
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
193+
$translator->setLocale('fr');
194+
$translator->setFallbackLocales(array('fr'));
195+
$this->assertEquals('répertoire', $translator->trans('folder'));
196+
}
197+
45198
public function testTransWithoutCaching()
46199
{
47200
$translator = $this->getTranslator($this->getLoader());
@@ -123,15 +276,8 @@ public function testLoadResourcesWithoutCaching()
123276

124277
public function testGetDefaultLocale()
125278
{
126-
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
127-
$container
128-
->expects($this->once())
129-
->method('getParameter')
130-
->with('kernel.default_locale')
131-
->will($this->returnValue('en'))
132-
;
133-
134-
$translator = new Translator($container, new MessageSelector());
279+
$container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock();
280+
$translator = new Translator($container, new MessageSelector(), 'en');
135281

136282
$this->assertSame('en', $translator->getLocale());
137283
}
@@ -219,9 +365,9 @@ protected function getContainer($loader)
219365
return $container;
220366
}
221367

222-
public function getTranslator($loader, $options = array(), $loaderFomat = 'loader', $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator')
368+
public function getTranslator($loader, $options = array(), $loaderFomat = 'loader', $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator', $defaultLocale = 'en')
223369
{
224-
$translator = $this->createTranslator($loader, $options, $translatorClass, $loaderFomat);
370+
$translator = $this->createTranslator($loader, $options, $translatorClass, $loaderFomat, $defaultLocale);
225371

226372
if ('loader' === $loaderFomat) {
227373
$translator->addResource('loader', 'foo', 'fr');
@@ -261,11 +407,21 @@ public function testWarmup()
261407
$this->assertEquals('répertoire', $translator->trans('folder'));
262408
}
263409

264-
private function createTranslator($loader, $options, $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator', $loaderFomat = 'loader')
410+
private function createTranslator($loader, $options, $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator', $loaderFomat = 'loader', $defaultLocale = 'en')
265411
{
412+
if (null === $defaultLocale) {
413+
return new $translatorClass(
414+
$this->getContainer($loader),
415+
new MessageSelector(),
416+
array($loaderFomat => array($loaderFomat)),
417+
$options
418+
);
419+
}
420+
266421
return new $translatorClass(
267422
$this->getContainer($loader),
268423
new MessageSelector(),
424+
$defaultLocale,
269425
array($loaderFomat => array($loaderFomat)),
270426
$options
271427
);

‎src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
+17-3Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\Translation;
1313

14+
use Psr\Container\ContainerInterface;
15+
use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface;
1416
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
1517
use Symfony\Component\Translation\Translator as BaseTranslator;
1618
use Symfony\Component\Translation\MessageSelector;
17-
use Symfony\Component\DependencyInjection\ContainerInterface;
1819
use Symfony\Component\Translation\Exception\InvalidArgumentException;
1920

2021
/**
@@ -54,8 +55,21 @@ class Translator extends BaseTranslator implements WarmableInterface
5455
*
5556
* @throws InvalidArgumentException
5657
*/
57-
public function __construct(ContainerInterface $container, MessageSelector $selector, $loaderIds = array(), array $options = array())
58+
public function __construct(ContainerInterface $container, MessageSelector $selector, $defaultLocale = null, $loaderIds = array(), array $options = array())
5859
{
60+
// BC 3.x, to be removed in 4.0 along with the $defaultLocale default value
61+
if (is_array($defaultLocale) || 3 > func_num_args()) {
62+
@trigger_error(sprintf('Method %s() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.', __METHOD__), E_USER_DEPRECATED);
63+
$options = $loaderIds;
64+
$loaderIds = $defaultLocale;
65+
66+
if (!$container instanceof SymfonyContainerInterface) {
67+
throw new \InvalidArgumentException(sprintf('A default locale must be passed as 3rd argument of %s() since version 3.3, the argument will be mandatory in 4.0.', __METHOD__));
68+
}
69+
70+
$defaultLocale = $container->getParameter('kernel.default_locale');
71+
}
72+
5973
$this->container = $container;
6074
$this->loaderIds = $loaderIds;
6175

@@ -70,7 +84,7 @@ public function __construct(ContainerInterface $container, MessageSelector $sele
7084
$this->loadResources();
7185
}
7286

73-
parent::__construct($container->getParameter('kernel.default_locale'), $selector, $this->options['cache_dir'], $this->options['debug']);
87+
parent::__construct($defaultLocale, $selector, $this->options['cache_dir'], $this->options['debug']);
7488
}
7589

7690
/**

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.