Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop Symfony from overwriting the localefrom the query string when set_locale_from_accept_language is true #3397

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

nicofrand
Copy link
Contributor

@nicofrand nicofrand commented Jan 30, 2023

Hi!

Context

A bit of context to begin with: I am using Bolt with 3 languages, each page being translated in each of this language.
Some of the visitors do not speak the default language and won't take the time use the language switcher.

I want the pages do be displayed in the language the user chose in its browser configuration.
That's what symfony provides through https://symfony.com/doc/current/reference/configuration/framework.html#set-locale-from-accept-language.

However I'd still like to be able to change the locale, through the language switcher, which simply appends ?_locale=XX to the query string.

Issue

When framework.set_locale_from_accept_language: true is set (with `framework.enabled_locales: ['en', 'fr', 'it']) the preferred language overwrites (Symfony's subscriber is called after Bolt's subscriber) the language set in the query string: symfony only checks the attributes, not the query string.

Solution

When the _locale parameter from the query string is set, also set it in the attributes, which Symfony will check.

⚠️ Warning

I do not know what that might imply (besides fixing my issue). This pull request is kind of here for discussions if that is not the way things should be done (I might not know Symfony well enough).

See https://github.com/symfony/symfony/blob/5.4/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php#L71

@nicofrand
Copy link
Contributor Author

In case that MR is not accepted for some reason (in its current form or another), the issue it fixes can also be fixed by creating a subscriber in the App namespace:

<?php

declare(strict_types=1);

namespace App\Event\Subscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class FixLocaleSubscriber implements EventSubscriberInterface
{
    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();

        /**
         * Symfony's listener has a lower priority and will be called after Bolt's listener.
         * It will not check that the locale was set already and in case useAcceptLanguageHeader is
         * set, it will overwrite the locale just set by Bolt (since it does not care about the
         * query, only the attributes).
         *
         * This listener registers the locale as an attribute (if not already the case) to ensure
         * the _locale query parameter has a greater weight than the HTTP_ACCEPT_LANGUAGE header.
         * It does not set the locale: either Bolt did it or Symfony will.
         */
        if (!$request->attributes->has('_locale') && $request->query->has('_locale')) {
            $locale = $request->query->get('_locale');
            $request->attributes->set('_locale', $locale);
        }
    }

    public static function getSubscribedEvents(): array
    {
        return [
            // must be registered before (i.e. with a higher priority than) the default Bolt's Locale listener
            KernelEvents::REQUEST => [['onKernelRequest', 25]],
        ];
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant