diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index fe887ca9c97bd..43139cc0a23d1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 5.1.0 ----- + * Added `available_locales` for `Content-language` header handling * Added link to source for controllers registered as named services * Added link to source on controller on `router:match`/`debug:router` (when `framework.ide` is configured) * Added `Routing\Loader` and `Routing\Loader\Configurator` namespaces to ease defining routes with default controllers diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 7caec9b49feab..9cb41634a0309 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -72,6 +72,14 @@ public function getConfigTreeBuilder() return $v; }) ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { return !isset($v['available_locales']) && (isset($v['translator']['enabled_locales']) || isset($v['translator']['enabled-locale'])); }) + ->then(function ($v) { + $v['available_locales'] = $v['translator']['enabled_locales'] ?? $v['translator']['enabled-locale']; + + return $v; + }) + ->end() ->children() ->scalarNode('secret')->end() ->scalarNode('http_method_override') @@ -81,6 +89,11 @@ public function getConfigTreeBuilder() ->scalarNode('ide')->defaultNull()->end() ->booleanNode('test')->end() ->scalarNode('default_locale')->defaultValue('en')->end() + ->arrayNode('available_locales') + ->info('An array of available locales for your application. It will help determine the locale according to the Accept-Language header.') + ->beforeNormalization()->ifEmpty()->thenUnset()->end() + ->prototype('scalar')->end() + ->end() ->arrayNode('trusted_hosts') ->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end() ->prototype('scalar')->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index cef82f8ce1fc0..752db422b6d65 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -234,6 +234,7 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('kernel.http_method_override', $config['http_method_override']); $container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']); $container->setParameter('kernel.default_locale', $config['default_locale']); + $container->setParameter('kernel.available_locales', $config['available_locales']); $container->setParameter('kernel.error_controller', $config['error_controller']); if (!$container->hasParameter('debug.file_link_format')) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index 99ffbabb82cdc..f03803a55bb24 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -33,6 +33,7 @@ + @@ -41,6 +42,7 @@ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml index cbdc5586a27ad..a8c94123b8ad3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml @@ -59,6 +59,7 @@ %kernel.default_locale% + %kernel.available_locales% diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index fad9b09a049fa..703f230bb5450 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -341,6 +341,7 @@ protected static function getBundleDefaultConfig() 'http_method_override' => true, 'ide' => null, 'default_locale' => 'en', + 'available_locales' => [], 'csrf_protection' => [ 'enabled' => false, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/available_locales.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/available_locales.php new file mode 100644 index 0000000000000..0e715ec000753 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/available_locales.php @@ -0,0 +1,7 @@ +loadFromExtension('framework', [ + 'secret' => 's3cr3t', + 'default_locale' => 'fr', + 'available_locales' => ['mi', 'fr'], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/available_locales_cannot_fallback_enabled_locales.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/available_locales_cannot_fallback_enabled_locales.php new file mode 100644 index 0000000000000..92fc12a1ac631 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/available_locales_cannot_fallback_enabled_locales.php @@ -0,0 +1,6 @@ +loadFromExtension('framework', [ + 'secret' => 's3cr3t', + 'default_locale' => 'fr', +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/available_locales_fallback_enabled_locales.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/available_locales_fallback_enabled_locales.php new file mode 100644 index 0000000000000..c4bad94f23399 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/available_locales_fallback_enabled_locales.php @@ -0,0 +1,13 @@ +loadFromExtension('framework', [ + 'secret' => 's3cr3t', + 'default_locale' => 'fr', + 'translator' => [ + 'enabled' => true, + 'fallback' => 'fr', + 'paths' => ['%kernel.project_dir%/Fixtures/translations'], + 'cache_dir' => '%kernel.cache_dir%/translations', + 'enabled_locales' => ['mi', 'fr'], + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php index b11b5e08dcb96..ee3054ebf9945 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php @@ -3,6 +3,7 @@ $container->loadFromExtension('framework', [ 'secret' => 's3cr3t', 'default_locale' => 'fr', + 'available_locales' => ['mi', 'fr'], 'csrf_protection' => true, 'form' => [ 'csrf_protection' => [ @@ -50,7 +51,7 @@ 'fallback' => 'fr', 'paths' => ['%kernel.project_dir%/Fixtures/translations'], 'cache_dir' => '%kernel.cache_dir%/translations', - 'enabled_locales' => ['fr', 'en'] + 'enabled_locales' => ['fr', 'en'], ], 'validation' => [ 'enabled' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/available_locales.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/available_locales.xml new file mode 100644 index 0000000000000..d69430672f1b5 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/available_locales.xml @@ -0,0 +1,13 @@ + + + + + + mi + fr + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/available_locales_cannot_fallback_enabled_locales.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/available_locales_cannot_fallback_enabled_locales.xml new file mode 100644 index 0000000000000..6866841890312 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/available_locales_cannot_fallback_enabled_locales.xml @@ -0,0 +1,14 @@ + + + + + + + %kernel.project_dir%/Fixtures/translations + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/available_locales_fallback_enabled_locales.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/available_locales_fallback_enabled_locales.xml new file mode 100644 index 0000000000000..d9bf05448b019 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/available_locales_fallback_enabled_locales.xml @@ -0,0 +1,16 @@ + + + + + + + %kernel.project_dir%/Fixtures/translations + mi + fr + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml index 10a646049d766..0a2d73f5403fd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -7,6 +7,8 @@ http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> + mi + fr diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/available_locales.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/available_locales.yml new file mode 100644 index 0000000000000..9c858808a4a3a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/available_locales.yml @@ -0,0 +1,4 @@ +framework: + secret: s3cr3t + default_locale: fr + available_locales: [mi, fr] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/available_locales_cannot_fallback_enabled_locales.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/available_locales_cannot_fallback_enabled_locales.yml new file mode 100644 index 0000000000000..0cdd21756c145 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/available_locales_cannot_fallback_enabled_locales.yml @@ -0,0 +1,8 @@ +framework: + secret: s3cr3t + default_locale: fr + translator: + enabled: true + fallback: fr + cache_dir: '%kernel.cache_dir%/translations' + paths: ['%kernel.project_dir%/Fixtures/translations'] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/available_locales_fallback_enabled_locales.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/available_locales_fallback_enabled_locales.yml new file mode 100644 index 0000000000000..5a91c2493f785 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/available_locales_fallback_enabled_locales.yml @@ -0,0 +1,9 @@ +framework: + secret: s3cr3t + default_locale: fr + translator: + enabled: true + fallback: fr + cache_dir: '%kernel.cache_dir%/translations' + paths: ['%kernel.project_dir%/Fixtures/translations'] + enabled_locales: [mi, fr] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml index 5ad80a2da4db2..b53d82480e809 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -1,6 +1,7 @@ framework: secret: s3cr3t default_locale: fr + available_locales: ['mi', 'fr'] csrf_protection: true form: csrf_protection: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 55332ab60bc55..5fd335a23b1fe 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -476,6 +476,7 @@ public function testSession() $this->assertTrue($container->hasDefinition('session'), '->registerSessionConfiguration() loads session.xml'); $this->assertEquals('fr', $container->getParameter('kernel.default_locale')); + $this->assertEquals(['mi', 'fr'], $container->getParameter('kernel.available_locales')); $this->assertEquals('session.storage.native', (string) $container->getAlias('session.storage')); $this->assertEquals('session.handler.native_file', (string) $container->getAlias('session.handler')); @@ -726,6 +727,24 @@ public function testMessengerInvalidTransportRouting() $this->createContainerFromFile('messenger_routing_invalid_transport'); } + public function testAvailableLocales() + { + $container = $this->createContainerFromFile('available_locales'); + $this->assertEquals(['mi', 'fr'], $container->getParameter('kernel.available_locales')); + } + + public function testAvailableLocalesFallbackOnEnabledLocales() + { + $container = $this->createContainerFromFile('available_locales_fallback_enabled_locales'); + $this->assertEquals(['mi', 'fr'], $container->getParameter('kernel.available_locales')); + } + + public function testAvailableLocalesCannotFallbackOnEnabledLocales() + { + $container = $this->createContainerFromFile('available_locales_cannot_fallback_enabled_locales'); + $this->assertEquals([], $container->getParameter('kernel.available_locales')); + } + public function testTranslator() { $container = $this->createContainerFromFile('full'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml index 432e35bd2f24d..81fe01fbb5f7d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml @@ -4,6 +4,7 @@ imports: framework: secret: '%secret%' default_locale: '%env(LOCALE)%' + available_locales: ['%env(LOCALE)%'] session: cookie_httponly: '%env(bool:COOKIE_HTTPONLY)%' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Slugger/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Slugger/config.yml index f80091b831e05..689af7f1a62ef 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Slugger/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Slugger/config.yml @@ -5,6 +5,7 @@ imports: framework: secret: '%secret%' default_locale: '%env(LOCALE)%' + available_locales: ['%env(LOCALE)%'] translator: fallbacks: - '%env(LOCALE)%' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TransDebug/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TransDebug/config.yml index 7f8815b2942fa..2d5e678fc6b93 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TransDebug/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TransDebug/config.yml @@ -5,6 +5,7 @@ imports: framework: secret: '%secret%' default_locale: '%env(LOCALE)%' + available_locales: ['%env(LOCALE)%'] translator: fallbacks: - '%env(LOCALE)%' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml index 1c42894a24d9c..ed02779fdc505 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml @@ -6,6 +6,7 @@ framework: form: true test: true default_locale: en + available_locales: ['en', 'fr'] session: storage_id: session.storage.mock_file diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 1b766484b6d3c..4c078c20834b5 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 5.1.0 ----- + * Allow request locale and Response `Content-Language` header to be set from `preferredLocale` thanks to `available_locales` * made `WarmableInterface::warmUp()` return a list of classes or files to preload on PHP 7.4+; not returning an array is deprecated * deprecated support for `service:action` syntax to reference controllers, use `serviceOrFqcn::method` instead diff --git a/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php b/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php index 8037e32c0e90e..103d0423f1119 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php @@ -31,10 +31,12 @@ class LocaleListener implements EventSubscriberInterface { private $router; private $defaultLocale; + private $availableLocales; private $requestStack; - public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null) + public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null, array $availableLocales = []) { + $this->availableLocales = $availableLocales; $this->defaultLocale = $defaultLocale; $this->requestStack = $requestStack; $this->router = $router; @@ -65,6 +67,11 @@ private function setLocale(Request $request) if ($locale = $request->attributes->get('_locale')) { $request->setLocale($locale); } + + if (null === $locale && !empty($this->availableLocales) && + $preferredLanguage = $request->getPreferredLanguage($this->availableLocales)) { + $request->setLocale($preferredLanguage); + } } private function setRouterContext(Request $request) diff --git a/src/Symfony/Component/HttpKernel/EventListener/ResponseListener.php b/src/Symfony/Component/HttpKernel/EventListener/ResponseListener.php index d8292aec43e49..a5fdb6bda9e05 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ResponseListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ResponseListener.php @@ -25,10 +25,12 @@ class ResponseListener implements EventSubscriberInterface { private $charset; + private $availableLocales; - public function __construct(string $charset) + public function __construct(string $charset, array $availableLocales = []) { $this->charset = $charset; + $this->availableLocales = $availableLocales; } /** @@ -46,6 +48,11 @@ public function onKernelResponse(ResponseEvent $event) $response->setCharset($this->charset); } + if (!empty($this->availableLocales) && !$response->isInformational() && !$response->isEmpty() && !$response->headers->has('Content-Language')) { + $response->headers->set('Content-Language', $event->getRequest()->getLocale()); + $response->setVary('Accept-Language', false); + } + $response->prepare($event->getRequest()); } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php index cb502a89eecc4..d51bce37f912f 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php @@ -114,6 +114,72 @@ public function testRequestLocaleIsNotOverridden() $this->assertEquals('de', $request->getLocale()); } + public function testRequestPreferredLocaleFromAcceptLanguageHeader() + { + $request = Request::create('/'); + $request->headers->set('Accept-Language', ['Accept-Language: fr-FR,fr;q=0.9,en-GB;q=0.8,en;q=0.7,en-US;q=0.6,es;q=0.5']); + + $listener = new LocaleListener($this->requestStack, 'de', null, ['de', 'fr']); + $event = $this->getEvent($request); + + $listener->setDefaultLocale($event); + $listener->onKernelRequest($event); + $this->assertEquals('fr', $request->getLocale()); + } + + public function testRequestSecondPreferredLocaleFromAcceptLanguageHeader() + { + $request = Request::create('/'); + $request->headers->set('Accept-Language', ['Accept-Language: fr-FR,fr;q=0.9,en-GB;q=0.8,en;q=0.7,en-US;q=0.6,es;q=0.5']); + + $listener = new LocaleListener($this->requestStack, 'de', null, ['de', 'en']); + $event = $this->getEvent($request); + + $listener->setDefaultLocale($event); + $listener->onKernelRequest($event); + $this->assertEquals('en', $request->getLocale()); + } + + public function testRequestUnavailablePreferredLocaleFromAcceptLanguageHeader() + { + $request = Request::create('/'); + $request->headers->set('Accept-Language', ['Accept-Language: fr-FR,fr;q=0.9,en-GB;q=0.8,en;q=0.7,en-US;q=0.6,es;q=0.5']); + + $listener = new LocaleListener($this->requestStack, 'de', null, ['de', 'it']); + $event = $this->getEvent($request); + + $listener->setDefaultLocale($event); + $listener->onKernelRequest($event); + $this->assertEquals('de', $request->getLocale()); + } + + public function testRequestNoLocaleFromAcceptLanguageHeader() + { + $request = Request::create('/'); + $request->headers->set('Accept-Language', ['Accept-Language: fr-FR,fr;q=0.9,en-GB;q=0.8,en;q=0.7,en-US;q=0.6,es;q=0.5']); + + $listener = new LocaleListener($this->requestStack, 'de'); + $event = $this->getEvent($request); + + $listener->setDefaultLocale($event); + $listener->onKernelRequest($event); + $this->assertEquals('de', $request->getLocale()); + } + + public function testRequestAttributeLocaleNotOverridenFromAcceptLanguageHeader() + { + $request = Request::create('/'); + $request->attributes->set('_locale', 'it'); + $request->headers->set('Accept-Language', ['Accept-Language: fr-FR,fr;q=0.9,en-GB;q=0.8,en;q=0.7,en-US;q=0.6,es;q=0.5']); + + $listener = new LocaleListener($this->requestStack, 'de', null, ['fr', 'en']); + $event = $this->getEvent($request); + + $listener->setDefaultLocale($event); + $listener->onKernelRequest($event); + $this->assertEquals('it', $request->getLocale()); + } + private function getEvent(Request $request): RequestEvent { return new RequestEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php index 1aaa64bc89ced..8e210a8c4af7c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ResponseListenerTest.php @@ -92,4 +92,50 @@ public function testFiltersSetsNonDefaultCharsetIfNotOverriddenOnNonTextContentT $this->assertEquals('ISO-8859-15', $response->getCharset()); } + + public function testSetContentLanguageHeaderWhenEmptyAndWithAvailableLocales() + { + $listener = new ResponseListener('ISO-8859-15', ['fr']); + $this->dispatcher->addListener(KernelEvents::RESPONSE, [$listener, 'onKernelResponse'], 1); + + $response = new Response('content'); + $request = Request::create('/'); + $request->setLocale('fr'); + + $event = new ResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); + $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); + + $this->assertEquals('fr', $response->headers->get('Content-Language')); + } + + public function testNotOverrideContentLanguageHeaderWhenNotEmpty() + { + $listener = new ResponseListener('ISO-8859-15', ['de']); + $this->dispatcher->addListener(KernelEvents::RESPONSE, [$listener, 'onKernelResponse'], 1); + + $response = new Response('content'); + $response->headers->set('Content-Language', 'mi, en'); + $request = Request::create('/'); + $request->setLocale('de'); + + $event = new ResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); + $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); + + $this->assertEquals('mi, en', $response->headers->get('Content-Language')); + } + + public function testNotSetContentLanguageHeaderWhenEmptyAvailableLocales() + { + $listener = new ResponseListener('ISO-8859-15'); + $this->dispatcher->addListener(KernelEvents::RESPONSE, [$listener, 'onKernelResponse'], 1); + + $response = new Response('content'); + $request = Request::create('/'); + $request->setLocale('fr'); + + $event = new ResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); + $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); + + $this->assertNull($response->headers->get('Content-Language')); + } }