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

Skip to content

Commit f9f7f3f

Browse files
committed
[FrameworkBundle] Make Translator works with any PSR-11 container
1 parent 4149eab commit f9f7f3f

File tree

10 files changed

+223
-26
lines changed

10 files changed

+223
-26
lines changed

UPGRADE-3.3.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ FrameworkBundle
180180
Require `symfony/web-server-bundle` in your composer.json and register
181181
`Symfony\Bundle\WebServerBundle\WebServerBundle` in your AppKernel to use them.
182182

183+
* The `Symfony\Bundle\FrameworkBundle\Translation\Translator` constructor now takes the
184+
default locale as 3rd argument. Not passing it will trigger an error in 4.0.
185+
>>>>>>> fc2d3b8... [FrameworkBundle] Make Translator works with any PSR-11 container
186+
183187
HttpKernel
184188
-----------
185189

UPGRADE-4.0.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ FrameworkBundle
274274
class has been removed. Use the
275275
`Symfony\Component\Routing\DependencyInjection\RoutingResolverPass` class instead.
276276

277+
* The `Symfony\Bundle\FrameworkBundle\Translation\Translator` constructor now takes the
278+
default locale as mandatory 3rd argument.
279+
277280
HttpFoundation
278281
---------------
279282

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ CHANGELOG
3535
`server:status` console commands have been moved to a dedicated bundle.
3636
Require `symfony/web-server-bundle` in your composer.json and register
3737
`Symfony\Bundle\WebServerBundle\WebServerBundle` in your AppKernel to use them.
38+
* Added `$defaultLocale` as 3rd argument of `Translator::__construct()`
39+
making `Translator` works with any PSR-11 container
3840

3941
3.2.0
4042
-----

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
@@ -954,11 +954,11 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
954954
}
955955

956956
$options = array_merge(
957-
$translator->getArgument(3),
957+
$translator->getArgument(4),
958958
array('resource_files' => $files)
959959
);
960960

961-
$translator->replaceArgument(3, $options);
961+
$translator->replaceArgument(4, $options);
962962
}
963963
}
964964

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/FrameworkBundle/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('realpath', $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
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Tests\Translation;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Psr\Container\ContainerInterface;
1516
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
1617
use Symfony\Component\Translation\MessageCatalogue;
1718
use Symfony\Component\Filesystem\Filesystem;
@@ -42,6 +43,157 @@ protected function deleteTmpDir()
4243
$fs->remove($dir);
4344
}
4445

46+
/**
47+
* @group legacy
48+
* @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.
49+
*/
50+
public function testTransWithoutCachingOmittingLocale()
51+
{
52+
$translator = $this->getTranslator($this->getLoader(), array(), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
53+
$translator->setLocale('fr');
54+
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
55+
56+
$this->assertEquals('foo (FR)', $translator->trans('foo'));
57+
$this->assertEquals('bar (EN)', $translator->trans('bar'));
58+
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
59+
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
60+
$this->assertEquals('no translation', $translator->trans('no translation'));
61+
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
62+
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
63+
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
64+
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
65+
}
66+
67+
/**
68+
* @group legacy
69+
* @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.
70+
*/
71+
public function testTransWithCachingOmittingLocale()
72+
{
73+
// prime the cache
74+
$translator = $this->getTranslator($this->getLoader(), array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
75+
$translator->setLocale('fr');
76+
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
77+
78+
$this->assertEquals('foo (FR)', $translator->trans('foo'));
79+
$this->assertEquals('bar (EN)', $translator->trans('bar'));
80+
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
81+
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
82+
$this->assertEquals('no translation', $translator->trans('no translation'));
83+
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
84+
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
85+
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
86+
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
87+
88+
// do it another time as the cache is primed now
89+
$loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
90+
$loader->expects($this->never())->method('load');
91+
92+
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
93+
$translator->setLocale('fr');
94+
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin'));
95+
96+
$this->assertEquals('foo (FR)', $translator->trans('foo'));
97+
$this->assertEquals('bar (EN)', $translator->trans('bar'));
98+
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
99+
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
100+
$this->assertEquals('no translation', $translator->trans('no translation'));
101+
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
102+
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
103+
$this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz'));
104+
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
105+
}
106+
107+
/**
108+
* @group legacy
109+
* @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.
110+
* @expectedException \InvalidArgumentException
111+
*/
112+
public function testTransWithCachingWithInvalidLocaleOmittingLocale()
113+
{
114+
$loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
115+
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Tests\Translation\TranslatorWithInvalidLocale', null);
116+
117+
$translator->trans('foo');
118+
}
119+
120+
/**
121+
* @group legacy
122+
* @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.
123+
*/
124+
public function testLoadResourcesWithoutCachingOmittingLocale()
125+
{
126+
$loader = new \Symfony\Component\Translation\Loader\YamlFileLoader();
127+
$resourceFiles = array(
128+
'fr' => array(
129+
__DIR__.'/../Fixtures/Resources/translations/messages.fr.yml',
130+
),
131+
);
132+
133+
$translator = $this->getTranslator($loader, array('resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null);
134+
$translator->setLocale('fr');
135+
136+
$this->assertEquals('répertoire', $translator->trans('folder'));
137+
}
138+
139+
/**
140+
* @group legacy
141+
* @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.
142+
*/
143+
public function testGetDefaultLocaleOmittingLocale()
144+
{
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(ContainerInterface::class)->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(ContainerInterface::class)->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