Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 43f0161

Browse filesBrowse files
committed
feature #43108 [HttpKernel] Add basic support for language negotiation (GregoireHebert)
This PR was merged into the 5.4 branch. Discussion ---------- [HttpKernel] Add basic support for language negotiation | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - Continuation of #36507. Thanks `@GregoireHebert`! This PR adds two options to the framework configuration: - `set_locale_from_accept_language`: Makes the `Request`' locale automatically set based on the `Accept-Language` header (restricted by a new `framework.enabled_locales` config option which replaces `framework.translator.enabled_locales`). The explicit `_locale` request attribute always wins over the `Accept-Language` header when it's set. - `set_content_language_from_locale`: Sets the `Content-Language` Response header based on the `Request`' locale. This is going to be useful for API Platform and related (e.g. Sylius/Sylius#11412). Commits ------- 904b54f [HttpKernel] Add basic support for language negotiation
2 parents 2100d7b + 904b54f commit 43f0161
Copy full SHA for 43f0161

23 files changed

+259
-12
lines changed

‎UPGRADE-5.4.md

Copy file name to clipboardExpand all lines: UPGRADE-5.4.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Form
2525
FrameworkBundle
2626
---------------
2727

28+
* Deprecate the `framework.translator.enabled_locales` config option, use `framework.enabled_locales` instead
2829
* Deprecate the `AdapterInterface` autowiring alias, use `CacheItemPoolInterface` instead
2930
* Deprecate the public `profiler` service to private
3031
* Deprecate `get()`, `has()`, `getDoctrine()`, and `dispatchMessage()` in `AbstractController`, use method/constructor injection instead

‎UPGRADE-6.0.md

Copy file name to clipboardExpand all lines: UPGRADE-6.0.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Form
8989
FrameworkBundle
9090
---------------
9191

92+
* Remove the `framework.translator.enabled_locales` config option, use `framework.enabled_locales` instead
9293
* Remove the `session.storage` alias and `session.storage.*` services, use the `session.storage.factory` alias and `session.storage.factory.*` services instead
9394
* Remove `framework.session.storage_id` configuration option, use the `framework.session.storage_factory_id` configuration option instead
9495
* Remove the `session` service and the `SessionInterface` alias, use the `\Symfony\Component\HttpFoundation\Request::getSession()` or the new `\Symfony\Component\HttpFoundation\RequestStack::getSession()` methods instead

‎src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ CHANGELOG
44
5.4
55
---
66

7+
* Add `set_locale_from_accept_language` config option to automatically set the request locale based on the `Accept-Language`
8+
HTTP request header and the `framework.enabled_locales` config option
9+
* Add `set_content_language_from_locale` config option to automatically set the `Content-Language` HTTP response header based on the Request locale
10+
* Deprecate the `framework.translator.enabled_locales`, use `framework.enabled_locales` instead
711
* Add autowiring alias for `HttpCache\StoreInterface`
812
* Deprecate the `AdapterInterface` autowiring alias, use `CacheItemPoolInterface` instead
913
* Deprecate the public `profiler` service to private

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+15-1Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public function getConfigTreeBuilder()
7777
return $v;
7878
})
7979
->end()
80+
->fixXmlConfig('enabled_locale')
8081
->children()
8182
->scalarNode('secret')->end()
8283
->scalarNode('http_method_override')
@@ -86,6 +87,18 @@ public function getConfigTreeBuilder()
8687
->scalarNode('ide')->defaultNull()->end()
8788
->booleanNode('test')->end()
8889
->scalarNode('default_locale')->defaultValue('en')->end()
90+
->booleanNode('set_locale_from_accept_language')
91+
->info('Whether to use the Accept-Language HTTP header to set the Request locale (only when the "_locale" request attribute is not passed).')
92+
->defaultFalse()
93+
->end()
94+
->booleanNode('set_content_language_from_locale')
95+
->info('Whether to set the Content-Language HTTP header on the Response using the Request locale.')
96+
->defaultFalse()
97+
->end()
98+
->arrayNode('enabled_locales')
99+
->info('Defines the possible locales for the application. This list is used for generating translations files, but also to restrict which locales are allowed when it is set from Accept-Language header (using "set_locale_from_accept_language").')
100+
->prototype('scalar')->end()
101+
->end()
89102
->arrayNode('trusted_hosts')
90103
->beforeNormalization()->ifString()->then(function ($v) { return [$v]; })->end()
91104
->prototype('scalar')->end()
@@ -814,6 +827,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $e
814827
->prototype('scalar')->end()
815828
->end()
816829
->arrayNode('enabled_locales')
830+
->setDeprecated('symfony/framework-bundle', '5.3', 'Option "%node%" at "%path%" is deprecated, set the "framework.enabled_locales" option instead.')
817831
->prototype('scalar')->end()
818832
->defaultValue([])
819833
->end()
@@ -848,7 +862,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode, callable $e
848862
->arrayNode('locales')
849863
->prototype('scalar')->end()
850864
->defaultValue([])
851-
->info('If not set, all locales listed under framework.translator.enabled_locales are used.')
865+
->info('If not set, all locales listed under framework.enabled_locales are used.')
852866
->end()
853867
->end()
854868
->end()

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+15-5Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@ public function load(array $configs, ContainerBuilder $container)
275275
}
276276
}
277277

278+
$container->getDefinition('locale_listener')->replaceArgument(3, $config['set_locale_from_accept_language']);
279+
$container->getDefinition('response_listener')->replaceArgument(1, $config['set_content_language_from_locale']);
280+
278281
// If the slugger is used but the String component is not available, we should throw an error
279282
if (!ContainerBuilder::willBeAvailable('symfony/string', SluggerInterface::class, ['symfony/framework-bundle'])) {
280283
$container->register('slugger', 'stdClass')
@@ -297,6 +300,7 @@ public function load(array $configs, ContainerBuilder $container)
297300
$container->setParameter('kernel.http_method_override', $config['http_method_override']);
298301
$container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']);
299302
$container->setParameter('kernel.default_locale', $config['default_locale']);
303+
$container->setParameter('kernel.enabled_locales', $config['enabled_locales']);
300304
$container->setParameter('kernel.error_controller', $config['error_controller']);
301305

302306
if (($config['trusted_proxies'] ?? false) && ($config['trusted_headers'] ?? false)) {
@@ -418,11 +422,13 @@ public function load(array $configs, ContainerBuilder $container)
418422
$this->registerEsiConfiguration($config['esi'], $container, $loader);
419423
$this->registerSsiConfiguration($config['ssi'], $container, $loader);
420424
$this->registerFragmentsConfiguration($config['fragments'], $container, $loader);
421-
$this->registerTranslatorConfiguration($config['translator'], $container, $loader, $config['default_locale']);
425+
$this->registerTranslatorConfiguration($config['translator'], $container, $loader, $config['default_locale'], $config['enabled_locales']);
422426
$this->registerProfilerConfiguration($config['profiler'], $container, $loader);
423427
$this->registerWorkflowConfiguration($config['workflows'], $container, $loader);
424428
$this->registerDebugConfiguration($config['php_errors'], $container, $loader);
425-
$this->registerRouterConfiguration($config['router'], $container, $loader, $config['translator']['enabled_locales'] ?? []);
429+
// @deprecated since Symfony 5.4, in 6.0 change to:
430+
// $this->registerRouterConfiguration($config['router'], $container, $loader, $config['enabled_locales']);
431+
$this->registerRouterConfiguration($config['router'], $container, $loader, $config['translator']['enabled_locales'] ?: $config['enabled_locales']);
426432
$this->registerAnnotationsConfiguration($config['annotations'], $container, $loader);
427433
$this->registerPropertyAccessConfiguration($config['property_access'], $container, $loader);
428434
$this->registerSecretsConfiguration($config['secrets'], $container, $loader);
@@ -1228,7 +1234,7 @@ private function createVersion(ContainerBuilder $container, ?string $version, ?s
12281234
return new Reference('assets.empty_version_strategy');
12291235
}
12301236

1231-
private function registerTranslatorConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader, string $defaultLocale)
1237+
private function registerTranslatorConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader, string $defaultLocale, array $enabledLocales)
12321238
{
12331239
if (!$this->isConfigEnabled($container, $config)) {
12341240
$container->removeDefinition('console.command.translation_debug');
@@ -1252,7 +1258,9 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
12521258
$defaultOptions['cache_dir'] = $config['cache_dir'];
12531259
$translator->setArgument(4, $defaultOptions);
12541260

1255-
$translator->setArgument(5, $config['enabled_locales']);
1261+
// @deprecated since Symfony 5.4, in 6.0 change to:
1262+
// $translator->setArgument(5, $enabledLocales);
1263+
$translator->setArgument(5, $config['enabled_locales'] ?: $enabledLocales);
12561264

12571265
$container->setParameter('translator.logging', $config['logging']);
12581266
$container->setParameter('translator.default_path', $config['default_path']);
@@ -1385,7 +1393,9 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
13851393
return;
13861394
}
13871395

1388-
$locales = $config['enabled_locales'] ?? [];
1396+
// @deprecated since Symfony 5.4, in 6.0 change to:
1397+
// $locales = $enabledLocales;
1398+
$locales = $config['enabled_locales'] ?: $enabledLocales;
13891399

13901400
foreach ($config['providers'] as $provider) {
13911401
if ($provider['locales']) {

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,15 @@
3838
<xsd:element name="rate-limiter" type="rate_limiter" minOccurs="0" maxOccurs="1" />
3939
<xsd:element name="uid" type="uid" minOccurs="0" maxOccurs="1" />
4040
<xsd:element name="notifier" type="notifier" minOccurs="0" maxOccurs="1" />
41+
<xsd:element name="enabled-locale" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
4142
</xsd:choice>
4243

4344
<xsd:attribute name="http-method-override" type="xsd:boolean" />
4445
<xsd:attribute name="ide" type="xsd:string" />
4546
<xsd:attribute name="secret" type="xsd:string" />
4647
<xsd:attribute name="default-locale" type="xsd:string" />
48+
<xsd:attribute name="set_locale_from_accept_language" type="xsd:boolean" />
49+
<xsd:attribute name="set_content_language_from_locale" type="xsd:boolean" />
4750
<xsd:attribute name="test" type="xsd:boolean" />
4851
<xsd:attribute name="error-controller" type="xsd:string" />
4952
<xsd:attribute name="trusted-hosts" type="xsd:string" />

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@
6969
->set('response_listener', ResponseListener::class)
7070
->args([
7171
param('kernel.charset'),
72+
abstract_arg('The "set_content_language_from_locale" config value'),
73+
param('kernel.enabled_locales'),
7274
])
7375
->tag('kernel.event_subscriber')
7476

@@ -80,6 +82,8 @@
8082
service('request_stack'),
8183
param('kernel.default_locale'),
8284
service('router')->ignoreOnInvalid(),
85+
abstract_arg('The "set_locale_from_accept_language" config value'),
86+
param('kernel.enabled_locales'),
8387
])
8488
->tag('kernel.event_subscriber')
8589

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,9 @@ protected static function getBundleDefaultConfig()
370370
'http_method_override' => true,
371371
'ide' => null,
372372
'default_locale' => 'en',
373+
'enabled_locales' => [],
374+
'set_locale_from_accept_language' => false,
375+
'set_content_language_from_locale' => false,
373376
'secret' => 's3cr3t',
374377
'trusted_hosts' => [],
375378
'trusted_headers' => [

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
$container->loadFromExtension('framework', [
44
'secret' => 's3cr3t',
55
'default_locale' => 'fr',
6+
'enabled_locales' => ['fr', 'en'],
67
'csrf_protection' => true,
78
'form' => [
89
'csrf_protection' => [
@@ -51,7 +52,6 @@
5152
'fallback' => 'fr',
5253
'paths' => ['%kernel.project_dir%/Fixtures/translations'],
5354
'cache_dir' => '%kernel.cache_dir%/translations',
54-
'enabled_locales' => ['fr', 'en'],
5555
],
5656
'validation' => [
5757
'enabled' => true,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
$container->loadFromExtension('framework', [
4+
'secret' => 's3cr3t',
5+
'default_locale' => 'fr',
6+
'router' => [
7+
'resource' => '%kernel.project_dir%/config/routing.xml',
8+
'type' => 'xml',
9+
'utf8' => true,
10+
],
11+
'translator' => [
12+
'enabled' => true,
13+
'fallback' => 'fr',
14+
'paths' => ['%kernel.project_dir%/Fixtures/translations'],
15+
'cache_dir' => '%kernel.cache_dir%/translations',
16+
'enabled_locales' => ['fr', 'en'],
17+
],
18+
]);

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
88

99
<framework:config secret="s3cr3t" ide="file%%link%%format" default-locale="fr" http-method-override="false">
10+
<framework:enabled-locale>fr</framework:enabled-locale>
11+
<framework:enabled-locale>en</framework:enabled-locale>
1012
<framework:csrf-protection />
1113
<framework:form legacy-error-messages="false">
1214
<framework:csrf-protection field-name="_csrf"/>
@@ -28,8 +30,6 @@
2830
<framework:assets version="v1" />
2931
<framework:translator enabled="true" fallback="fr" logging="true" cache-dir="%kernel.cache_dir%/translations">
3032
<framework:path>%kernel.project_dir%/Fixtures/translations</framework:path>
31-
<framework:enabled-locale>fr</framework:enabled-locale>
32-
<framework:enabled-locale>en</framework:enabled-locale>
3333
</framework:translator>
3434
<framework:validation enabled="true" />
3535
<framework:annotations cache="file" debug="true" file-cache-dir="%kernel.cache_dir%/annotations" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xmlns:framework="http://symfony.com/schema/dic/symfony"
6+
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
7+
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
8+
9+
<framework:config secret="s3cr3t" ide="file%%link%%format" default-locale="fr" http-method-override="false">
10+
<framework:router resource="%kernel.project_dir%/config/routing.xml" type="xml" utf8="true" />
11+
<framework:translator enabled="true" fallback="fr" logging="true" cache-dir="%kernel.cache_dir%/translations">
12+
<framework:path>%kernel.project_dir%/Fixtures/translations</framework:path>
13+
<framework:enabled-locale>fr</framework:enabled-locale>
14+
<framework:enabled-locale>en</framework:enabled-locale>
15+
</framework:translator>
16+
</framework:config>
17+
</container>

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
framework:
22
secret: s3cr3t
33
default_locale: fr
4+
enabled_locales: ['fr', 'en']
45
csrf_protection: true
56
form:
67
csrf_protection:
@@ -42,7 +43,6 @@ framework:
4243
default_path: '%kernel.project_dir%/translations'
4344
cache_dir: '%kernel.cache_dir%/translations'
4445
paths: ['%kernel.project_dir%/Fixtures/translations']
45-
enabled_locales: [fr, en]
4646
validation:
4747
enabled: true
4848
annotations:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
framework:
2+
secret: s3cr3t
3+
default_locale: fr
4+
router:
5+
resource: '%kernel.project_dir%/config/routing.xml'
6+
type: xml
7+
utf8: true
8+
translator:
9+
enabled: true
10+
fallback: fr
11+
default_path: '%kernel.project_dir%/translations'
12+
cache_dir: '%kernel.cache_dir%/translations'
13+
paths: ['%kernel.project_dir%/Fixtures/translations']
14+
enabled_locales: [ 'fr', 'en' ]

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,22 @@ public function testRouter()
546546
$this->assertSame(['_locale' => 'fr|en'], $container->getDefinition('routing.loader')->getArgument(2));
547547
}
548548

549+
/**
550+
* @group legacy
551+
*/
552+
public function testRouterWithLegacyTranslatorEnabledLocales()
553+
{
554+
$container = $this->createContainerFromFile('legacy_translator_enabled_locales');
555+
556+
$this->assertTrue($container->has('router'), '->registerRouterConfiguration() loads routing.xml');
557+
$arguments = $container->findDefinition('router')->getArguments();
558+
$this->assertEquals($container->getParameter('kernel.project_dir').'/config/routing.xml', $container->getParameter('router.resource'), '->registerRouterConfiguration() sets routing resource');
559+
$this->assertEquals('%router.resource%', $arguments[1], '->registerRouterConfiguration() sets routing resource');
560+
$this->assertEquals('xml', $arguments[2]['resource_type'], '->registerRouterConfiguration() sets routing resource type');
561+
562+
$this->assertSame(['_locale' => 'fr|en'], $container->getDefinition('routing.loader')->getArgument(2));
563+
}
564+
549565
public function testRouterRequiresResourceOption()
550566
{
551567
$this->expectException(InvalidConfigurationException::class);

‎src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ imports:
44
framework:
55
secret: '%secret%'
66
default_locale: '%env(LOCALE)%'
7+
enabled_locales: ['%env(LOCALE)%']
78
session:
89
storage_factory_id: session.storage.factory.native
910
cookie_httponly: '%env(bool:COOKIE_HTTPONLY)%'

‎src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Slugger/config.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Slugger/config.yml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ imports:
55
framework:
66
secret: '%secret%'
77
default_locale: '%env(LOCALE)%'
8+
enabled_locales: ['%env(LOCALE)%']
89
translator:
910
fallbacks:
1011
- '%env(LOCALE)%'

‎src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TransDebug/config.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/TransDebug/config.yml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ imports:
55
framework:
66
secret: '%secret%'
77
default_locale: '%env(LOCALE)%'
8+
enabled_locales: ['%env(LOCALE)%']
89
translator:
910
fallbacks:
1011
- '%env(LOCALE)%'

‎src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/config/framework.yml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ framework:
88
legacy_error_messages: false
99
test: true
1010
default_locale: en
11+
enabled_locales: ['en', 'fr']
1112
session:
1213
storage_factory_id: session.storage.factory.mock_file
1314

‎src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php
+7-1Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,16 @@ class LocaleListener implements EventSubscriberInterface
3232
private $router;
3333
private $defaultLocale;
3434
private $requestStack;
35+
private $useAcceptLanguageHeader;
36+
private $enabledLocales;
3537

36-
public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null)
38+
public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null, bool $useAcceptLanguageHeader = false, array $enabledLocales = [])
3739
{
3840
$this->defaultLocale = $defaultLocale;
3941
$this->requestStack = $requestStack;
4042
$this->router = $router;
43+
$this->useAcceptLanguageHeader = $useAcceptLanguageHeader;
44+
$this->enabledLocales = $enabledLocales;
4145
}
4246

4347
public function setDefaultLocale(KernelEvent $event)
@@ -64,6 +68,8 @@ private function setLocale(Request $request)
6468
{
6569
if ($locale = $request->attributes->get('_locale')) {
6670
$request->setLocale($locale);
71+
} elseif ($this->useAcceptLanguageHeader && $this->enabledLocales && ($preferredLanguage = $request->getPreferredLanguage($this->enabledLocales))) {
72+
$request->setLocale($preferredLanguage);
6773
}
6874
}
6975

‎src/Symfony/Component/HttpKernel/EventListener/ResponseListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/EventListener/ResponseListener.php
+8-1Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
class ResponseListener implements EventSubscriberInterface
2626
{
2727
private $charset;
28+
private $addContentLanguageHeader;
2829

29-
public function __construct(string $charset)
30+
public function __construct(string $charset, bool $addContentLanguageHeader = false)
3031
{
3132
$this->charset = $charset;
33+
$this->addContentLanguageHeader = $addContentLanguageHeader;
3234
}
3335

3436
/**
@@ -46,6 +48,11 @@ public function onKernelResponse(ResponseEvent $event)
4648
$response->setCharset($this->charset);
4749
}
4850

51+
if ($this->addContentLanguageHeader && !$response->isInformational() && !$response->isEmpty() && !$response->headers->has('Content-Language')) {
52+
$response->headers->set('Content-Language', $event->getRequest()->getLocale());
53+
$response->setVary('Accept-Language', false);
54+
}
55+
4956
$response->prepare($event->getRequest());
5057
}
5158

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.