Symfony2 wrong locale detection? Symfony2 wrong locale detection? symfony symfony

Symfony2 wrong locale detection?


I looked more thoroughly onto the code today, because I was experiencing the same problem as you, and it appears that the language comes from Session::getLocale(). But Symfony2 never calls Session::setLocale(), and sets the locale member of the Session object. A google search for "symfony2 session setlocale" leads to this ยง of the documentation

So I ended up putting this line on top of the controller I was working on, and it worked :

$this->getRequest()->getSession()->setLocale(    $this->getRequest()->getPreferredLanguage());

Now I guess this is not acceptable, because you're not going to add this on top of each and every controller. Plus, this should not be done for every request, it should only be done for the first one, when the user has no session yet. If anyone knows how to do this feel free to edit this answer.


per HTTP-Standard you should be using a different URL for each translated version of the page. What remains is a simple action that will infer the best-to-use locale from the request and redirect to the corresponding page:

/** * @Route("/") */public function localeRedirectAction() {    /* @var $request \Symfony\Component\HttpFoundation\Request */    /* @var $session \Symfony\Component\HttpFoundation\Session */    $req = $this->getRequest();    $session = $this->get('session');    $session->setLocale($req->getPreferredLanguage(array('de', 'en')));    return $this->redirect($this->generateUrl('home'));}

if you need to do this for any page, you'll basically need to do the same, but within a Listener for the kernel.request-Event. In order to be reliably called after the route-matcher did it's work you should set the priority of the listener to a value < 0:

# services.ymlservices:  my_locale_listener:    class: Namespace\LocaleListener    tags: [{ name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: -255 }]    arguments: [ @service_container, [ 'en', 'fr', 'de', 'es', 'it' ] ]

the listener would then look like this:

class LocaleListener {    public function __construct($container, $availableLocales) {        $this->container = $container;        $this->availableLocales = $availableLocales;    }    public function onKernelRequest(GetResponseEvent $e) {        $req = $e->getRequest();        $locale = $req->getPreferredLanguage($this->availableLocales);        // generate a new URL from the current route-name and -params, overwriting        // the current locale        $routeName = $req->attributes->get('_route');        $routeParams = array_merge($req->attributes->all(), array('_locale' => $locale));        $localizedUrl = $this->container->get('router')->generateUrl($routeName, $routeParams);        $e->setResponse(new RedirectResponse($localizedUrl));    }}

P.S. i'm not entirely confident that this code actually works, but it should give a basic idea on how this could be done.


You can register listener like follow:

use Symfony\Component\DependencyInjection\ContainerInterface;use Symfony\Component\HttpKernel\HttpKernelInterface;use Symfony\Component\HttpKernel\Event\GetResponseEvent;class LocaleListener{    private $container;    private $defaultLocale;    public function __construct(ContainerInterface $container, $defaultLocale = 'nl')    {        $this->container = $container;        $this->defaultLocale = $defaultLocale;    }    public function onKernelRequest(GetResponseEvent $event)    {        if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {            return;        }        if (!$this->container->has('session')) {            return;        }        $session = $this->container->get('session');        $session->setLocale($this->defaultLocale);    }}

(gist)

Just after framework session setup stage:

<service id="my.event_listener.locale_listener" class="MyBundle\MyEventListener\LocaleListener">    <tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="100" />    <argument type="service" id="service_container" /></service>

(gist)