Question

My website is running Symfony, master version. So far, I was able to use the LocalListener logic from the website, with a slight difference due to code not being compatible with my version. (I think) I only simplified the onKernelRequest method this way:

public function onKernelRequest(GetResponseEvent $event)
{
    $request = $event->getRequest();
    if (!$request->hasPreviousSession()) {
        return;
    }

    if ($locale = $request->get('_locale')) {
        $request->getSession()->set('_locale', $locale);
    }
    $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}

That way, I could put up a simple language selector on my page, using these paths, and the new language would apply at the first request. (it would not happen if I left the "else" condition)

Then I wanted to take account of the locale stored in user accounts, in case the user is logged in and has specified a locale in his or her profile. So I added this piece of code in the function :

public function onKernelRequest(GetResponseEvent $event)
{
    $request = $event->getRequest();
    if (!$request->hasPreviousSession()) {
        return;
    }

    $token = $this->container->get('security.context')->getToken();
    if (is_object($token)) {
    $user = $token->getUser();
    if (is_object($user)) {
        $userlocale = $user->getLocale();
        if ($userlocale) {
        $request->getSession()->set('_locale', $userlocale);
        $request->setLocale($userlocale);
        return;
        }
    }
}

    if ($locale = $request->get('_locale')) {
        $request->getSession()->set('_locale', $locale);
    }
    $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}

(EDIT: sorry for poor indentation, somehow stackoverflow does not want to indent it properly...)

Basically it checks if a user is logged in, and if there is, if he or she has set a locale, and if they have, sets the locale to the user locale instead. Now this works, but... not instantly. Whenever I log in or change my locale in my profile, the next page I get to is still in the previously set locale. Only when I load a new page does it change its translations properly, and stays that way for the next requests.

So here is my question: is there something I am supposed to add to make this change occur on those post-login and post-profile-edit requests?

Was it helpful?

Solution 2

Well thanks to Elnur I decided to go back to my jms_i18n solution (see comments in Elnur's answer), and I found this question that helped me build my own solution. So I switched from an EventSubscriber extended class to a simple "unextended" class of my own. Here is the working code:

<?php
//src/myApp/MainBundle/EventListener/LocaleListener.php
namespace myApp\MainBundle\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Cookie;

class LocaleListener
{
  private $container;

  public function __construct(ContainerInterface $container)
  {
    $this->container = $container;
  }

  public function onKernelRequest(GetResponseEvent $event)
  {
    if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
      return;
    }
    $request = $event->getRequest();
    if ($request->getRequestFormat() !== 'html') {
      return;
    }

    $token = $this->container->get('security.context')->getToken();
    if (is_object($token)) {
      $user = $token->getUser();
      if (is_object($user)) {
        $userlocale = $user->getLocale();
        if ($userlocale && $userlocale != $request->get('_locale')) {
          $parmArray = $request->get('_route_params');
          $parmArray['_locale'] = $userlocale;

          $redirectResponse = new RedirectResponse( $this->container->get('router')->generate($request->get('_route'), $parmArray) );
          $redirectResponse->headers->setCookie( new Cookie('b_locale', $userlocale, time() + 2592000) );

          $event->setResponse( $redirectResponse );
        }
      }
    }
  }
}

And here is how to register it in services :

# app/config/config.yml
services:
    myapp_main.locale_listener:
        class: myApp\MainBundle\EventListener\LocaleListener
        arguments: ["@service_container"]
        tags:
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

Many thanks to Elnur for changing my mind.

OTHER TIPS

You need not just set the new locale but also to redirect the user after you do that for changes to take effect.

Also, it's not a good practice to store the locale in the session — you should keep the locale in the URL. This way a redirect to a URL with a proper locale makes even more sense.

I am not sure if this will work. But when user is logged in locale will be set in his/her session.

you can do something like this in your listener:

    $request = $event->getRequest();
    $session = $request->getSession();
    $locale = $session->get('_locale');
    if (!empty($locale)) {
     $request->setLocale($locale);
    }

and on link where user will select locale you can create some action

    public function localeAction($locale)
    {
      $this->get('session')->set('_locale', $locale);

      return $this->redirect($this->generateUrl('route'));
    }

I just find out that you have a problem with your listener and specially in this:

if (!$request->hasPreviousSession()) {
    return;
}

You are requesting for hasPreviousSession and it has but it doesnt has the locales I don't know what cause this but this is the major problem on the first request. If you change it in:

 if ($request->hasPreviousSession() && $this->defaultLocale == $request->get('_locale') ) {
        return;
    }

It will work like a charm :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top