Symfony: Set language based on user’s setting
When using localization in a web application it might be useful to store user’s language in database so that every time they log in to the application they get the interface in the language they are used to. Let’s see how to do that in Symfony.
First install and configure these bundles using their respective configuration:
- FOSUserBundle – provides login forms, authentication and User database entity
- JMSTranslationBundle – enhances Symfony translation capabilities
- JMSI18nRoutingBundle – automatically localizes routes by adding language prefixes
Once we have all these bundles properly set up, we are able to switch between interface languages and we have localized login forms. The only remaining part is to redirect the user to correct language version once they log in.
Step 1: Add locale attribute to user entity
Find your user entity and add a locale attribute. Implement getLocale() function. It might also be a good idea to make the value configurable in user profile form.
Step 2: Implement AuthenticationSuccessHandler
The handler will be called when user successfully logs in to the application. It will check user’s locale and redirect to proper language version. Please note that ‘dashboard’ is name of the route we want to redirect the user to.
namespace AppBundle\Authentication; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; class AfterLoginRedirection implements AuthenticationSuccessHandlerInterface { const DEFAULT_LOCALE = 'en'; /** @var RouterInterface */ private $router; /** * AfterLoginRedirection constructor. * * @param RouterInterface $router */ public function __construct(RouterInterface $router) { $this->router = $router; } public function onAuthenticationSuccess(Request $request, TokenInterface $token) { $response = new RedirectResponse($this->router->generate('fos_user_security_login')); if ($token->isAuthenticated()) { $locale = self::DEFAULT_LOCALE; $user = $token->getUser(); if ($request->getLocale()) { $locale = $request->getLocale(); } if ($user->getLocale()) { $locale = $user->getLocale(); } $response = new RedirectResponse($this->router->generate('dashboard', array( '_locale' => $locale ))); } return $response; } }
Step 3: Activate the handler
Configure service:
services: app.authentication.login.redirect: class: AppBundle\Authentication\AfterLoginRedirection arguments: ['@router']
Configure FOSUserBundle to use the service:
security: firewalls: main: pattern: ^/ form_login: provider: fos_userbundle login_path: fos_user_security_login check_path: fos_user_security_check success_handler: app.authentication.login.redirect csrf_token_generator: security.csrf.token_manager logout: true anonymous: true
And that’s it. Now users are redirected to the correct language version.
3 thoughts on “Symfony: Set language based on user’s setting”
Wow, this is exactly what I was looking for
Is there a way to make the confirmation mail sent to the user, translated on the user’s prefered language parameter saved in the registration form?
I’m using the following workflow:
1. User reads information on public website. They read it in a language they understand. (They use a language switch which sets their locale).
2. They go to registration form, fill it out and submit.
3. When creating a new User entity, I store current locale.
4. FOSUserBundle generates confirmation email. At this time locale is set to user’s preferred one so the confirmation email can be translated in the same way as any other web page. I use Twig templates as described here and {% trans %} blocks in the template.
3. The email is sent in user’s locale.