Skip to content

Commit 6a28b7d

Browse files
committed
[Translation][FrameworkBundle] add LocaleSwitcher service
1 parent 419ab39 commit 6a28b7d

File tree

8 files changed

+219
-0
lines changed

8 files changed

+219
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
15+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Reference;
18+
19+
/**
20+
* @author Kevin Bond <[email protected]>
21+
*
22+
* @internal
23+
*/
24+
class ConfigureLocaleSwitcherPass implements CompilerPassInterface
25+
{
26+
public function process(ContainerBuilder $container): void
27+
{
28+
if (!$container->has('translation.locale_switcher')) {
29+
return;
30+
}
31+
32+
$localeAwareServices = array_map(
33+
fn (string $id) => new Reference($id),
34+
array_keys($container->findTaggedServiceIds('kernel.locale_aware'))
35+
);
36+
37+
if ($container->has('translation.locale_aware_request_context')) {
38+
$localeAwareServices[] = new Reference('translation.locale_aware_request_context');
39+
}
40+
41+
$container->getDefinition('translation.locale_switcher')
42+
->setArgument(1, new IteratorArgument($localeAwareServices))
43+
;
44+
}
45+
}

DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,7 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co
10561056
$container->removeDefinition('console.command.router_debug');
10571057
$container->removeDefinition('console.command.router_match');
10581058
$container->removeDefinition('messenger.middleware.router_context');
1059+
$container->removeDefinition('translation.locale_aware_request_context');
10591060

10601061
return;
10611062
}

FrameworkBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass;
1616
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass;
1717
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AssetsContextPass;
18+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigureLocaleSwitcherPass;
1819
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass;
1920
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass;
2021
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass;
@@ -158,6 +159,7 @@ public function build(ContainerBuilder $container)
158159
$container->addCompilerPass(new RegisterReverseContainerPass(true));
159160
$container->addCompilerPass(new RegisterReverseContainerPass(false), PassConfig::TYPE_AFTER_REMOVING);
160161
$container->addCompilerPass(new RemoveUnusedSessionMarshallingHandlerPass());
162+
$container->addCompilerPass(new ConfigureLocaleSwitcherPass());
161163

162164
if ($container->getParameter('kernel.debug')) {
163165
$container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 2);

Resources/config/translation.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Psr\Container\ContainerInterface;
1515
use Symfony\Bundle\FrameworkBundle\CacheWarmer\TranslationsCacheWarmer;
16+
use Symfony\Bundle\FrameworkBundle\Translation\LocaleAwareRequestContext;
1617
use Symfony\Bundle\FrameworkBundle\Translation\Translator;
1718
use Symfony\Component\Translation\Dumper\CsvFileDumper;
1819
use Symfony\Component\Translation\Dumper\IcuResFileDumper;
@@ -39,6 +40,7 @@
3940
use Symfony\Component\Translation\Loader\QtFileLoader;
4041
use Symfony\Component\Translation\Loader\XliffFileLoader;
4142
use Symfony\Component\Translation\Loader\YamlFileLoader;
43+
use Symfony\Component\Translation\LocaleSwitcher;
4244
use Symfony\Component\Translation\LoggingTranslator;
4345
use Symfony\Component\Translation\Reader\TranslationReader;
4446
use Symfony\Component\Translation\Reader\TranslationReaderInterface;
@@ -163,4 +165,21 @@
163165
->tag('container.service_subscriber', ['id' => 'translator'])
164166
->tag('kernel.cache_warmer')
165167
;
168+
169+
if (class_exists(LocaleSwitcher::class)) {
170+
$container->services()
171+
->set('translation.locale_switcher', LocaleSwitcher::class)
172+
->args([
173+
param('kernel.default_locale'),
174+
abstract_arg('LocaleAware services'),
175+
])
176+
->alias(LocaleSwitcher::class, 'translation.locale_switcher')
177+
178+
->set('translation.locale_aware_request_context', LocaleAwareRequestContext::class)
179+
->args([
180+
service('router.request_context'),
181+
param('kernel.default_locale'),
182+
])
183+
;
184+
}
166185
};
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigureLocaleSwitcherPass;
16+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
17+
use Symfony\Component\DependencyInjection\ContainerBuilder;
18+
use Symfony\Component\DependencyInjection\Reference;
19+
20+
class ConfigureLocaleSwitcherPassTest extends TestCase
21+
{
22+
public function testProcess()
23+
{
24+
$container = new ContainerBuilder();
25+
$container->register('translation.locale_switcher')->setArgument(0, 'en');
26+
$container->register('locale_aware_service')
27+
->addTag('kernel.locale_aware')
28+
;
29+
30+
$pass = new ConfigureLocaleSwitcherPass();
31+
$pass->process($container);
32+
33+
$switcherDef = $container->getDefinition('translation.locale_switcher');
34+
35+
$this->assertInstanceOf(IteratorArgument::class, $switcherDef->getArgument(1));
36+
$this->assertEquals([new Reference('locale_aware_service')], $switcherDef->getArgument(1)->getValues());
37+
}
38+
39+
public function testProcessWithRequestContext()
40+
{
41+
$container = new ContainerBuilder();
42+
$container->register('translation.locale_switcher');
43+
$container->register('locale_aware_service')
44+
->addTag('kernel.locale_aware')
45+
;
46+
$container->register('translation.locale_aware_request_context');
47+
48+
$pass = new ConfigureLocaleSwitcherPass();
49+
$pass->process($container);
50+
51+
$switcherDef = $container->getDefinition('translation.locale_switcher');
52+
53+
$this->assertInstanceOf(IteratorArgument::class, $switcherDef->getArgument(1));
54+
$this->assertEquals(
55+
[
56+
new Reference('locale_aware_service'),
57+
new Reference('translation.locale_aware_request_context'),
58+
],
59+
$switcherDef->getArgument(1)->getValues()
60+
);
61+
}
62+
}

Tests/DependencyInjection/FrameworkExtensionTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
3131
use Symfony\Component\Cache\DependencyInjection\CachePoolPass;
3232
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
33+
use Symfony\Component\DependencyInjection\Argument\AbstractArgument;
3334
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
3435
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
3536
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
@@ -65,6 +66,7 @@
6566
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
6667
use Symfony\Component\Serializer\Serializer;
6768
use Symfony\Component\Translation\DependencyInjection\TranslatorPass;
69+
use Symfony\Component\Translation\LocaleSwitcher;
6870
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
6971
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
7072
use Symfony\Component\Validator\Validation;
@@ -1967,6 +1969,26 @@ public function testIfNotifierTransportsAreKnownByFrameworkExtension()
19671969
}
19681970
}
19691971

1972+
public function testLocaleSwitcherServiceRegistered()
1973+
{
1974+
if (!class_exists(LocaleSwitcher::class)) {
1975+
$this->markTestSkipped('LocaleSwitcher not available.');
1976+
}
1977+
1978+
$container = $this->createContainerFromFile('full');
1979+
1980+
$this->assertTrue($container->has('translation.locale_switcher'));
1981+
$this->assertTrue($container->has('translation.locale_aware_request_context'));
1982+
1983+
$switcherDef = $container->getDefinition('translation.locale_switcher');
1984+
$localeAwareRequestContextDef = $container->getDefinition('translation.locale_aware_request_context');
1985+
1986+
$this->assertSame('%kernel.default_locale%', $switcherDef->getArgument(0));
1987+
$this->assertInstanceOf(AbstractArgument::class, $switcherDef->getArgument(1));
1988+
$this->assertEquals(new Reference('router.request_context'), $localeAwareRequestContextDef->getArgument(0));
1989+
$this->assertSame('%kernel.default_locale%', $localeAwareRequestContextDef->getArgument(1));
1990+
}
1991+
19701992
protected function createContainer(array $data = [])
19711993
{
19721994
return new ContainerBuilder(new EnvPlaceholderParameterBag(array_merge([
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Translation;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bundle\FrameworkBundle\Translation\LocaleAwareRequestContext;
16+
use Symfony\Component\Routing\RequestContext;
17+
18+
class LocaleAwareRequestContextTest extends TestCase
19+
{
20+
public function testCanSwitchLocale()
21+
{
22+
$context = new RequestContext();
23+
$service = new LocaleAwareRequestContext($context, 'en');
24+
25+
$this->assertSame('en', $service->getLocale());
26+
$this->assertNull($context->getParameter('_locale'));
27+
28+
$service->setLocale('fr');
29+
30+
$this->assertSame('fr', $service->getLocale());
31+
$this->assertSame('fr', $context->getParameter('_locale'));
32+
}
33+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Translation;
13+
14+
use Symfony\Component\Routing\RequestContext;
15+
use Symfony\Contracts\Translation\LocaleAwareInterface;
16+
17+
/**
18+
* @author Kevin Bond <[email protected]>
19+
*/
20+
final class LocaleAwareRequestContext implements LocaleAwareInterface
21+
{
22+
public function __construct(private RequestContext $requestContext, private string $defaultLocale)
23+
{
24+
}
25+
26+
public function setLocale(string $locale): void
27+
{
28+
$this->requestContext->setParameter('_locale', $locale);
29+
}
30+
31+
public function getLocale(): string
32+
{
33+
return $this->requestContext->getParameter('_locale') ?? $this->defaultLocale;
34+
}
35+
}

0 commit comments

Comments
 (0)