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'));
+ }
}