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 58e3db1

Browse filesBrowse files
committed
[FrameworkBundle] Make Translator works with any PSR-11 container
1 parent 3ae36f4 commit 58e3db1
Copy full SHA for 58e3db1

File tree

10 files changed

+222
-26
lines changed
Filter options

10 files changed

+222
-26
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 mandatory 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()`
34+
making `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
+10-2Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111

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

14+
use Symfony\Component\DependencyInjection\Definition;
1415
use Symfony\Component\DependencyInjection\Reference;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
1617
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
18+
use Symfony\Component\DependencyInjection\ServiceLocator;
1719

1820
class TranslatorPass implements CompilerPassInterface
1921
{
@@ -24,7 +26,9 @@ public function process(ContainerBuilder $container)
2426
}
2527

2628
$loaders = array();
29+
$loaderRefs = array();
2730
foreach ($container->findTaggedServiceIds('translation.loader') as $id => $attributes) {
31+
$loaderRefs[$id] = new Reference($id);
2832
$loaders[$id][] = $attributes[0]['alias'];
2933
if (isset($attributes[0]['legacy-alias'])) {
3034
$loaders[$id][] = $attributes[0]['legacy-alias'];
@@ -35,11 +39,15 @@ public function process(ContainerBuilder $container)
3539
$definition = $container->getDefinition('translation.loader');
3640
foreach ($loaders as $id => $formats) {
3741
foreach ($formats as $format) {
38-
$definition->addMethodCall('addLoader', array($format, new Reference($id)));
42+
$definition->addMethodCall('addLoader', array($format, $loaderRefs[$id]));
3943
}
4044
}
4145
}
4246

43-
$container->findDefinition('translator.default')->replaceArgument(2, $loaders);
47+
$container
48+
->findDefinition('translator.default')
49+
->replaceArgument(0, (new Definition(ServiceLocator::class, array($loaderRefs)))->addTag('container.service_locator'))
50+
->replaceArgument(3, $loaders)
51+
;
4452
}
4553
}

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -944,11 +944,11 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
944944
}
945945

946946
$options = array_merge(
947-
$translator->getArgument(3),
947+
$translator->getArgument(4),
948948
array('resource_files' => $files)
949949
);
950950

951-
$translator->replaceArgument(3, $options);
951+
$translator->replaceArgument(4, $options);
952952
}
953953
}
954954

‎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 /> <!-- translation loaders locator -->
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
+11-1Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Definition;
1516
use Symfony\Component\DependencyInjection\Reference;
1617
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
18+
use Symfony\Component\DependencyInjection\ServiceLocator;
1719

1820
class TranslatorPassTest extends TestCase
1921
{
@@ -39,7 +41,15 @@ public function testValidCollector()
3941
->will($this->returnValue(array('xliff' => array(array('alias' => 'xliff', 'legacy-alias' => 'xlf')))));
4042
$container->expects($this->once())
4143
->method('findDefinition')
42-
->will($this->returnValue($this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock()));
44+
->will($this->returnValue($translator = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock()));
45+
$translator->expects($this->at(0))
46+
->method('replaceArgument')
47+
->with(0, $this->equalTo((new Definition(ServiceLocator::class, array(array('xliff' => new Reference('xliff')))))->addTag('container.service_locator')))
48+
->willReturn($translator);
49+
$translator->expects($this->at(1))
50+
->method('replaceArgument')
51+
->with(3, array('xliff' => array('xliff', 'xlf')))
52+
->willReturn($translator);
4353
$pass = new TranslatorPass();
4454
$pass->process($container);
4555
}

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

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

1414
use Doctrine\Common\Annotations\Annotation;
15+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass;
1516
use Symfony\Bundle\FullStack;
1617
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
1718
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
@@ -417,7 +418,7 @@ public function testTranslator()
417418
$container = $this->createContainerFromFile('full');
418419
$this->assertTrue($container->hasDefinition('translator.default'), '->registerTranslatorConfiguration() loads translation.xml');
419420
$this->assertEquals('translator.default', (string) $container->getAlias('translator'), '->registerTranslatorConfiguration() redefines translator service from identity to real translator');
420-
$options = $container->getDefinition('translator.default')->getArgument(3);
421+
$options = $container->getDefinition('translator.default')->getArgument(4);
421422

422423
$files = array_map(function ($resource) { return realpath($resource); }, $options['resource_files']['en']);
423424
$ref = new \ReflectionClass('Symfony\Component\Validator\Validation');
@@ -922,7 +923,7 @@ protected function createContainerFromFile($file, $data = array(), $resetCompile
922923
$container->getCompilerPassConfig()->setOptimizationPasses(array());
923924
$container->getCompilerPassConfig()->setRemovingPasses(array());
924925
}
925-
$container->getCompilerPassConfig()->setBeforeRemovingPasses(array(new AddAnnotationsCachedReaderPass(), new AddConstraintValidatorsPass()));
926+
$container->getCompilerPassConfig()->setBeforeRemovingPasses(array(new AddAnnotationsCachedReaderPass(), new AddConstraintValidatorsPass(), new TranslatorPass()));
926927
$container->compile();
927928

928929
return self::$containerCache[$cacheKey] = $container;

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
+169-13Lines changed: 169 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,158 @@ 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+
* @expectedException \InvalidArgumentException
160+
* @expectedExceptionMessage Missing third $defaultLocale argument.
161+
*/
162+
public function testGetDefaultLocaleOmittingLocaleWithPsrContainer()
163+
{
164+
$container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock();
165+
$translator = new Translator($container, new MessageSelector());
166+
}
167+
168+
/**
169+
* @group legacy
170+
* @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.
171+
*/
172+
public function testWarmupOmittingLocale()
173+
{
174+
$loader = new \Symfony\Component\Translation\Loader\YamlFileLoader();
175+
$resourceFiles = array(
176+
'fr' => array(
177+
__DIR__.'/../Fixtures/Resources/translations/messages.fr.yml',
178+
),
179+
);
180+
181+
// prime the cache
182+
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
183+
$translator->setFallbackLocales(array('fr'));
184+
$translator->warmup($this->tmpDir);
185+
186+
$loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
187+
$loader
188+
->expects($this->never())
189+
->method('load');
190+
191+
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
192+
$translator->setLocale('fr');
193+
$translator->setFallbackLocales(array('fr'));
194+
$this->assertEquals('répertoire', $translator->trans('folder'));
195+
}
196+
45197
public function testTransWithoutCaching()
46198
{
47199
$translator = $this->getTranslator($this->getLoader());
@@ -97,6 +249,7 @@ public function testTransWithCaching()
97249

98250
/**
99251
* @expectedException \InvalidArgumentException
252+
* @expectedExceptionMessage Invalid "invalid locale" locale.
100253
*/
101254
public function testTransWithCachingWithInvalidLocale()
102255
{
@@ -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
}
@@ -144,7 +290,7 @@ public function testInvalidOptions()
144290
{
145291
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
146292

147-
(new Translator($container, new MessageSelector(), array(), array('foo' => 'bar')));
293+
(new Translator($container, new MessageSelector(), 'en', array(), array('foo' => 'bar')));
148294
}
149295

150296
protected function getCatalogue($locale, $messages, $resources = array())
@@ -230,9 +376,9 @@ protected function getContainer($loader)
230376
return $container;
231377
}
232378

233-
public function getTranslator($loader, $options = array(), $loaderFomat = 'loader', $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator')
379+
public function getTranslator($loader, $options = array(), $loaderFomat = 'loader', $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator', $defaultLocale = 'en')
234380
{
235-
$translator = $this->createTranslator($loader, $options, $translatorClass, $loaderFomat);
381+
$translator = $this->createTranslator($loader, $options, $translatorClass, $loaderFomat, $defaultLocale);
236382

237383
if ('loader' === $loaderFomat) {
238384
$translator->addResource('loader', 'foo', 'fr');
@@ -272,11 +418,21 @@ public function testWarmup()
272418
$this->assertEquals('répertoire', $translator->trans('folder'));
273419
}
274420

275-
private function createTranslator($loader, $options, $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator', $loaderFomat = 'loader')
421+
private function createTranslator($loader, $options, $translatorClass = '\Symfony\Bundle\FrameworkBundle\Translation\Translator', $loaderFomat = 'loader', $defaultLocale = 'en')
276422
{
423+
if (null === $defaultLocale) {
424+
return new $translatorClass(
425+
$this->getContainer($loader),
426+
new MessageSelector(),
427+
array($loaderFomat => array($loaderFomat)),
428+
$options
429+
);
430+
}
431+
277432
return new $translatorClass(
278433
$this->getContainer($loader),
279434
new MessageSelector(),
435+
$defaultLocale,
280436
array($loaderFomat => array($loaderFomat)),
281437
$options
282438
);

0 commit comments

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