Issue
I'm currently working on symfony 5 and I've fully translated my website in several languages. I have a button to select the language, but I would like the default language of the site to be the one of the user (of his browser more precisely). For the moment I have found a solution, but it is not optimal at all.
What I do is that in my index, I check if the user has already browsed the site before, and if not, I redirect him to a change_locale
route which will take the language in question as a parameter (He enters the condition only if it's his first visit)
public function index(Request $request): Response
{
// If this is the first visit to the site, the default language is set according to the user's browser language
if (!$request->hasPreviousSession()) {
return $this->redirectToRoute('change_locale', ['locale' => strtolower(str_split($_SERVER['HTTP_ACCEPT_LANGUAGE'], 2)[0])]);
}
return $this->render('accueil/index.html.twig');
}
Here I simply register the variable in the session to change the language.
And my problem is just after this step. When the user simply clicks on the language change button on the site, he goes back to the previous page (he doesn't enter the if).
However, if he comes to the site for the first time, he is redirected from the index, and when he comes to this route, he enters the condition if (!$request->hasPreviousSession())
and... That's the problem. Because if he hasn't visited anything before, I can't redirect him to the page he was visiting.
/**
* @Route("/change-locale/{locale}", name="change_locale")
*/
public function changeLocale($locale, Request $request)
{
$request->getSession()->set('_locale', $locale); // Storing the requested language in the session
// If it's the first page visited by the user
if (!$request->headers->get('referer')) {
return $this->redirectToRoute('index');
}
// Back to the previous page
return $this->redirect($request->headers->get('referer'));
}
So I try to remove this condition from my change_locale
route and find a way to add in the header of the request the attribute 'referer'
which points to the previous page.
I could do this in my index before doing the redirectToRoute
to change_locale
.
Solution
Don't use a redirect to set the locale.
Symfony's documentation on How to Work with the User’s Locale has a great suggestion: use a custom event listener instead. Also read Making the Locale “Sticky” during a User’s Session.
You can use this example from the documentation:
class LocaleSubscriber implements EventSubscriberInterface
{
private $defaultLocale;
public function __construct(string $defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(RequestEvent $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 [
// must be registered before (i.e. with a higher priority than) the default Locale listener
KernelEvents::REQUEST => [['onKernelRequest', 20]],
];
}
}
And some free advice: in the onKernelRequest
method you can use HTTP_ACCEPT_LANGUAGE
to see what language the user might use, but (like all other user input!) it can be unavailable or unreliable. You might want to use information from the user's IP address or other logic.
Answered By - Stephan Vierkant
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.