Making the Locale "Sticky" during a User's Session
Edit this pageWarning: You are browsing the documentation for Symfony 2.4, which is no longer maintained.
Read the updated version of this page for Symfony 7.0 (the current stable version).
Making the Locale "Sticky" during a User's Session
Prior to Symfony 2.1, the locale was stored in a session attribute called _locale
.
Since 2.1, it is stored in the Request, which means that it's not "sticky"
during a user's request. In this article, you'll learn how to make the locale
of a user "sticky" so that once it's set, that same locale will be used for
every subsequent request.
Creating a LocaleListener
To simulate that the locale is stored in a session, you need to create and
register a new event listener.
The listener will look something like this. Typically, _locale
is used
as a routing parameter to signify the locale, though it doesn't really matter
how you determine the desired locale from the request:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
// src/Acme/LocaleBundle/EventListener/LocaleListener.php
namespace Acme\LocaleBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class LocaleListener implements EventSubscriberInterface
{
private $defaultLocale;
public function __construct($defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$request->hasPreviousSession()) {
return;
}
// try to see if the locale has been set as a _locale routing parameter
if ($locale = $request->attributes->get('_locale')) {
$request->getSession()->set('_locale', $locale);
} else {
// if no explicit locale has been set on this request, use one from the session
$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}
}
public static function getSubscribedEvents()
{
return array(
// must be registered before the default Locale listener
KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
);
}
}
Then register the listener:
1 2 3 4 5 6
services:
acme_locale.locale_listener:
class: Acme\LocaleBundle\EventListener\LocaleListener
arguments: ["%kernel.default_locale%"]
tags:
- { name: kernel.event_subscriber }
1 2 3 4 5 6
<service id="acme_locale.locale_listener"
class="Acme\LocaleBundle\EventListener\LocaleListener">
<argument>%kernel.default_locale%</argument>
<tag name="kernel.event_subscriber" />
</service>
1 2 3 4 5 6 7 8 9
use Symfony\Component\DependencyInjection\Definition;
$container
->setDefinition('acme_locale.locale_listener', new Definition(
'Acme\LocaleBundle\EventListener\LocaleListener',
array('%kernel.default_locale%')
))
->addTag('kernel.event_subscriber')
;
That's it! Now celebrate by changing the user's locale and seeing that it's sticky throughout the request. Remember, to get the user's locale, always use the Request::getLocale method:
1 2 3 4 5 6 7
// from a controller...
use Symfony\Component\HttpFoundation\Request;
public function indexAction(Request $request)
{
$locale = $request->getLocale();
}