<?php
namespace App\EventSubscriber;
use App\Entity\User;
use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTAuthenticatedEvent;
use Lexik\Bundle\JWTAuthenticationBundle\Events;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Component\Translation\Translator;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* This class manage the locale with the user->getLocale() value
* It manage it for session with classic login or jwt token.
*/
class UserLocaleSubscriber implements EventSubscriberInterface
{
public function __construct(
private RequestStack $requestStack,
private string $defaultLocale,
private TranslatorInterface $translator
) {
}
/**
* Used to avoid warning.
*
* @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>>
*/
public static function getSubscribedEvents()
{
// used to be done just after the default locale set
return [
KernelEvents::REQUEST => ['onKernelRequest', 20],
SecurityEvents::INTERACTIVE_LOGIN => 'onInteractiveLogin',
Events::JWT_AUTHENTICATED => 'onJwtAuthenticated',
];
}
/**
* On Login we store in session the locale of the user.
*/
public function onInteractiveLogin(InteractiveLoginEvent $event)
{
/** @var User $user */
$user = $event->getAuthenticationToken()->getUser();
if (null !== $user->getLocale()) {
$this->requestStack->getSession()->set('_locale', $user->getLocale());
}
}
/**
* On kernel request, we set the locale from the session that have been previously stored.
*/
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));
}
// adding the accept-language from header management
/* if ($request->headers->has("Accept-Language")) {
$locale = $request->getPreferredLanguage();
$request->setLocale($locale);
}*/
}
/**
* after a jwt token is set, we need to keep the same logic...
* But as the event is done after the translation set... we need to do it.
*/
public function onJwtAuthenticated(JWTAuthenticatedEvent $event)
{
/** @var User $user */
$user = $event->getToken()->getUser();
$request = $this->requestStack->getCurrentRequest();
if ($locale = $request->attributes->get('_locale')) {
$request->getSession()->set('_locale', $locale);
} else {
$locale = $user->getLocale();
// adding the accept-language from header management
/*if ($request->headers->has("Accept-Language")) {
$locale = $request->getPreferredLanguage();
}*/
$request->setLocale($locale);
// force the translator to the calculated locale
/** @var Translator $translator */
$translator = $this->translator;
$translator->setLocale($locale);
}
}
}