<?php
namespace App\EventListener;
use App\Application\Service\Session\SessionService;
use App\Entity\System\Customer;
use App\Service\EnvironmentService;
use Doctrine\ORM\NonUniqueResultException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
class LocaleListener
{
private TranslatorInterface $translator;
private TokenStorageInterface $tokenStorage;
private EnvironmentService $environmentService;
private SessionService $sessionService;
private string $defaultLocale;
private array $locales;
public function __construct(
TranslatorInterface $translator,
TokenStorageInterface $tokenStorage,
ParameterBagInterface $parameterBag,
EnvironmentService $environmentService,
SessionService $sessionService
) {
$this->translator = $translator;
$this->tokenStorage = $tokenStorage;
$this->environmentService = $environmentService;
$this->sessionService = $sessionService;
$this->defaultLocale = $parameterBag->get('locale');
$this->locales = $parameterBag->get('locales');
}
public function onKernelRequest(RequestEvent $event): void
{
if ($this->environmentService->isApi()) {
return;
}
$request = $event->getRequest();
$urlLocale = $this->getLocaleFromUrl($request);
if ($urlLocale) {
$this->setLocale($urlLocale, $request);
return;
}
$browserLocale = $this->getLocaleFromBrowser($request);
if (!$request->getSession()->get('lang')) {
if ($this->tokenStorage->getToken()) {
/** @var Customer $user */
$user = $this->tokenStorage->getToken()->getUser();
$userLocale = $user->getLanguage()->getIsoCode();
$this->setLocale($userLocale, $request);
return;
}
$locale = $browserLocale ?: $this->defaultLocale;
$this->setLocale($locale, $request);
}
}
/**
* @throws NonUniqueResultException
*/
private function setLocale(string $locale, Request $request): void
{
$request->setLocale($locale);
$this->translator->setLocale($locale);
$this->sessionService->setLocaleParameters($locale);
}
private function getLocaleFromBrowser(Request $request): ?string
{
return $request->getPreferredLanguage($this->locales);
}
private function isLocaleSupported(string $locale): bool
{
return \in_array($locale, $this->locales, true);
}
private function getLocaleFromUrl(Request $request): ?string
{
$urlArray = \explode('/', $request->getPathInfo());
if (
is_array($urlArray)
&& isset($urlArray[1])
&& $this->isLocaleSupported($urlArray[1])
) {
return $urlArray[1];
}
return $request->getSession()->get('lang') ?: null;
}
}