Symfony's cookbook proposes the following recipe to make the locale "sticky" during a user's session:
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)),
);
}
}
Can anybody explain the following three points:
- why do they
return
if! $request->hasPreviousSession()
? - int the following
if/else
, why do they set the locale with$request->getSession()->set('_locale')
in theif
block? Why not using$request->setLocale()
like in theelse
block? - what exactly does "must be registered before the default Locale listener" mean?
This event will make the
_locale
look like it's been submitted with the current request even though it may actually come from the session (BUT_locale
might be in the request - e.g. when user changes locale - in which case updated the session object to the new value).To answer your questions.
If there is no session object, skip as event is redundant (value cannot be in the session as it doesn't exist).
Sync
_locale
's value between session and request, favoring the request's version.As the LocaleListener event handles locale issues, the above needs to happen before that event runs. OnKernelRequest is one of the first events that gets triggered so we can be sure this is the case.