diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigureLocaleSwitcherPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigureLocaleSwitcherPass.php deleted file mode 100644 index 78f633bfcb5d2..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigureLocaleSwitcherPass.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Kevin Bond - * - * @internal - */ -class ConfigureLocaleSwitcherPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - if (!$container->has('translation.locale_switcher')) { - return; - } - - $localeAwareServices = array_map( - fn (string $id) => new Reference($id), - array_keys($container->findTaggedServiceIds('kernel.locale_aware')) - ); - - if ($container->has('translation.locale_aware_request_context')) { - $localeAwareServices[] = new Reference('translation.locale_aware_request_context'); - } - - $container->getDefinition('translation.locale_switcher') - ->setArgument(1, new IteratorArgument($localeAwareServices)) - ; - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index c689e2e21744c..aeed63946b25a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -205,6 +205,7 @@ use Symfony\Component\Translation\Bridge\Loco\LocoProviderFactory; use Symfony\Component\Translation\Bridge\Lokalise\LokaliseProviderFactory; use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand; +use Symfony\Component\Translation\LocaleSwitcher; use Symfony\Component\Translation\PseudoLocalizationTranslator; use Symfony\Component\Translation\Translator; use Symfony\Component\Uid\Factory\UuidFactory; @@ -1082,7 +1083,6 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co $container->removeDefinition('console.command.router_debug'); $container->removeDefinition('console.command.router_match'); $container->removeDefinition('messenger.middleware.router_context'); - $container->removeDefinition('translation.locale_aware_request_context'); return; } @@ -1295,6 +1295,11 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder } $loader->load('translation.php'); + + if (!ContainerBuilder::willBeAvailable('symfony/translation', LocaleSwitcher::class, ['symfony/framework-bundle'])) { + $container->removeDefinition('translation.locale_switcher'); + } + $loader->load('translation_providers.php'); // Use the "real" translator instead of the identity default diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 377d84b32673f..3b86ea1344fcf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -15,7 +15,6 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AssetsContextPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigureLocaleSwitcherPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; @@ -164,7 +163,6 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new RegisterReverseContainerPass(true)); $container->addCompilerPass(new RegisterReverseContainerPass(false), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new RemoveUnusedSessionMarshallingHandlerPass()); - $container->addCompilerPass(new ConfigureLocaleSwitcherPass()); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 2); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php index 79a7e9dce89e3..fadaff6d2b596 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.php @@ -13,7 +13,6 @@ use Psr\Container\ContainerInterface; use Symfony\Bundle\FrameworkBundle\CacheWarmer\TranslationsCacheWarmer; -use Symfony\Bundle\FrameworkBundle\Translation\LocaleAwareRequestContext; use Symfony\Bundle\FrameworkBundle\Translation\Translator; use Symfony\Component\Translation\Dumper\CsvFileDumper; use Symfony\Component\Translation\Dumper\IcuResFileDumper; @@ -46,6 +45,7 @@ use Symfony\Component\Translation\Reader\TranslationReaderInterface; use Symfony\Component\Translation\Writer\TranslationWriter; use Symfony\Component\Translation\Writer\TranslationWriterInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; use Symfony\Contracts\Translation\TranslatorInterface; return static function (ContainerConfigurator $container) { @@ -164,22 +164,15 @@ ->args([service(ContainerInterface::class)]) ->tag('container.service_subscriber', ['id' => 'translator']) ->tag('kernel.cache_warmer') - ; - - if (class_exists(LocaleSwitcher::class)) { - $container->services() - ->set('translation.locale_switcher', LocaleSwitcher::class) - ->args([ - param('kernel.default_locale'), - abstract_arg('LocaleAware services'), - ]) - ->alias(LocaleSwitcher::class, 'translation.locale_switcher') - ->set('translation.locale_aware_request_context', LocaleAwareRequestContext::class) + ->set('translation.locale_switcher', LocaleSwitcher::class) ->args([ - service('router.request_context'), param('kernel.default_locale'), + tagged_iterator('kernel.locale_aware'), + service('router.request_context')->ignoreOnInvalid(), ]) - ; - } + ->tag('kernel.reset', ['method' => 'reset']) + ->alias(LocaleAwareInterface::class, 'translation.locale_switcher') + ->alias(LocaleSwitcher::class, 'translation.locale_switcher') + ; }; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigureLocaleSwitcherPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigureLocaleSwitcherPassTest.php deleted file mode 100644 index 5a353ba460b1b..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigureLocaleSwitcherPassTest.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigureLocaleSwitcherPass; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -class ConfigureLocaleSwitcherPassTest extends TestCase -{ - public function testProcess() - { - $container = new ContainerBuilder(); - $container->register('translation.locale_switcher')->setArgument(0, 'en'); - $container->register('locale_aware_service') - ->addTag('kernel.locale_aware') - ; - - $pass = new ConfigureLocaleSwitcherPass(); - $pass->process($container); - - $switcherDef = $container->getDefinition('translation.locale_switcher'); - - $this->assertInstanceOf(IteratorArgument::class, $switcherDef->getArgument(1)); - $this->assertEquals([new Reference('locale_aware_service')], $switcherDef->getArgument(1)->getValues()); - } - - public function testProcessWithRequestContext() - { - $container = new ContainerBuilder(); - $container->register('translation.locale_switcher'); - $container->register('locale_aware_service') - ->addTag('kernel.locale_aware') - ; - $container->register('translation.locale_aware_request_context'); - - $pass = new ConfigureLocaleSwitcherPass(); - $pass->process($container); - - $switcherDef = $container->getDefinition('translation.locale_switcher'); - - $this->assertInstanceOf(IteratorArgument::class, $switcherDef->getArgument(1)); - $this->assertEquals( - [ - new Reference('locale_aware_service'), - new Reference('translation.locale_aware_request_context'), - ], - $switcherDef->getArgument(1)->getValues() - ); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 301647901cc8d..ba19f50419ede 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -31,7 +31,6 @@ use Symfony\Component\Cache\Adapter\TagAwareAdapter; use Symfony\Component\Cache\DependencyInjection\CachePoolPass; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; -use Symfony\Component\DependencyInjection\Argument\AbstractArgument; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; @@ -2019,15 +2018,13 @@ public function testLocaleSwitcherServiceRegistered() $container = $this->createContainerFromFile('full'); $this->assertTrue($container->has('translation.locale_switcher')); - $this->assertTrue($container->has('translation.locale_aware_request_context')); $switcherDef = $container->getDefinition('translation.locale_switcher'); - $localeAwareRequestContextDef = $container->getDefinition('translation.locale_aware_request_context'); $this->assertSame('%kernel.default_locale%', $switcherDef->getArgument(0)); - $this->assertInstanceOf(AbstractArgument::class, $switcherDef->getArgument(1)); - $this->assertEquals(new Reference('router.request_context'), $localeAwareRequestContextDef->getArgument(0)); - $this->assertSame('%kernel.default_locale%', $localeAwareRequestContextDef->getArgument(1)); + $this->assertInstanceOf(TaggedIteratorArgument::class, $switcherDef->getArgument(1)); + $this->assertSame('kernel.locale_aware', $switcherDef->getArgument(1)->getTag()); + $this->assertEquals(new Reference('router.request_context', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE), $switcherDef->getArgument(2)); } protected function createContainer(array $data = []) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/LocaleAwareRequestContextTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/LocaleAwareRequestContextTest.php deleted file mode 100644 index f98454cb1136b..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/LocaleAwareRequestContextTest.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\Translation; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\Translation\LocaleAwareRequestContext; -use Symfony\Component\Routing\RequestContext; - -class LocaleAwareRequestContextTest extends TestCase -{ - public function testCanSwitchLocale() - { - $context = new RequestContext(); - $service = new LocaleAwareRequestContext($context, 'en'); - - $this->assertSame('en', $service->getLocale()); - $this->assertNull($context->getParameter('_locale')); - - $service->setLocale('fr'); - - $this->assertSame('fr', $service->getLocale()); - $this->assertSame('fr', $context->getParameter('_locale')); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/LocaleAwareRequestContext.php b/src/Symfony/Bundle/FrameworkBundle/Translation/LocaleAwareRequestContext.php deleted file mode 100644 index 59e846b1b4ad4..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/LocaleAwareRequestContext.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Translation; - -use Symfony\Component\Routing\RequestContext; -use Symfony\Contracts\Translation\LocaleAwareInterface; - -/** - * @author Kevin Bond - */ -final class LocaleAwareRequestContext implements LocaleAwareInterface -{ - public function __construct(private RequestContext $requestContext, private string $defaultLocale) - { - } - - public function setLocale(string $locale): void - { - $this->requestContext->setParameter('_locale', $locale); - } - - public function getLocale(): string - { - return $this->requestContext->getParameter('_locale') ?? $this->defaultLocale; - } -} diff --git a/src/Symfony/Component/Translation/LocaleSwitcher.php b/src/Symfony/Component/Translation/LocaleSwitcher.php index 9c2dc38096eef..0fc56e3380ef1 100644 --- a/src/Symfony/Component/Translation/LocaleSwitcher.php +++ b/src/Symfony/Component/Translation/LocaleSwitcher.php @@ -11,23 +11,31 @@ namespace Symfony\Component\Translation; +use Symfony\Component\Routing\RequestContext; use Symfony\Contracts\Translation\LocaleAwareInterface; /** * @author Kevin Bond */ -final class LocaleSwitcher implements LocaleAwareInterface +class LocaleSwitcher implements LocaleAwareInterface { + private string $defaultLocale; + /** * @param LocaleAwareInterface[] $localeAwareServices */ - public function __construct(private string $locale, private iterable $localeAwareServices) - { + public function __construct( + private string $locale, + private iterable $localeAwareServices, + private ?RequestContext $requestContext = null, + ) { + $this->defaultLocale = $locale; } public function setLocale(string $locale): void { \Locale::setDefault($this->locale = $locale); + $this->requestContext?->setParameter('_locale', $locale); foreach ($this->localeAwareServices as $service) { $service->setLocale($locale); @@ -42,17 +50,26 @@ public function getLocale(): string /** * Switch to a new locale, execute a callback, then switch back to the original. * - * @param callable():void $callback + * @template T + * + * @param callable():T $callback + * + * @return T */ - public function runWithLocale(string $locale, callable $callback): void + public function runWithLocale(string $locale, callable $callback): mixed { $original = $this->getLocale(); $this->setLocale($locale); try { - $callback(); + return $callback(); } finally { $this->setLocale($original); } } + + public function reset(): void + { + $this->setLocale($this->defaultLocale); + } } diff --git a/src/Symfony/Component/Translation/Tests/LocaleSwitcherTest.php b/src/Symfony/Component/Translation/Tests/LocaleSwitcherTest.php index 5410df89f7723..f75370a063f66 100644 --- a/src/Symfony/Component/Translation/Tests/LocaleSwitcherTest.php +++ b/src/Symfony/Component/Translation/Tests/LocaleSwitcherTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Translation\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Component\Routing\RequestContext; use Symfony\Component\Translation\LocaleSwitcher; use Symfony\Contracts\Translation\LocaleAwareInterface; @@ -75,6 +76,24 @@ public function testCanSwitchLocaleForCallback() $this->assertSame('en', $service->getLocale()); $this->assertSame('en', $switcher->getLocale()); } + + public function testWithRequestContext() + { + $context = new RequestContext(); + $service = new LocaleSwitcher('en', [], $context); + + $this->assertSame('en', $service->getLocale()); + + $service->setLocale('fr'); + + $this->assertSame('fr', $service->getLocale()); + $this->assertSame('fr', $context->getParameter('_locale')); + + $service->reset(); + + $this->assertSame('en', $service->getLocale()); + $this->assertSame('en', $context->getParameter('_locale')); + } } class DummyLocaleAware implements LocaleAwareInterface diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index 98e00de5c9a86..e25f09ef76054 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -28,6 +28,7 @@ "symfony/http-kernel": "^5.4|^6.0", "symfony/intl": "^5.4|^6.0", "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0", "symfony/service-contracts": "^1.1.2|^2|^3", "symfony/yaml": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0",