8000 [FrameworkBundle] Make Translator works with any PSR-11 container · symfony/symfony@58e3db1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 58e3db1

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

File tree

10 files changed

+222
-26
lines changed

10 files changed

+222
-26
lines changed

UPGRADE-3.3.md

Lines 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

Lines 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

Lines 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

Lines 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

Lines 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

Lines 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

Lines 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/Fra 1241 meworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Lines 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

Lines 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