<?php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Détermine la langue de la requête (i18n).
*
* Ordre de résolution :
* 1. Paramètre d'URL `?_locale=` (ex. via le lien de changement de langue) — s'il est valide, il est aussi mémorisé en session.
* 2. Valeur mémorisée en session (`_locale`).
* 3. Langue par défaut (français).
*
* Seules les langues déclarées dans self::SUPPORTED_LOCALES sont acceptées :
* toute valeur inconnue retombe sur la langue par défaut (protection contre les valeurs arbitraires).
*/
class LocaleSubscriber implements EventSubscriberInterface
{
/**
* Langues prises en charge. Doit rester cohérent avec `framework.enabled_locales`
* (config/packages/translation.yaml) et les fichiers translations/messages.<locale>.yaml.
*
* @var string[]
*/
private const SUPPORTED_LOCALES = ['fr', 'ar_TN'];
private string $defaultLocale;
public function __construct(string $defaultLocale = 'fr')
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(RequestEvent $event): void
{
$request = $event->getRequest();
if (!$request->hasPreviousSession()) {
return;
}
$session = $request->getSession();
// 1. Langue passée en paramètre d'URL : on la valide puis on la mémorise.
$queryLocale = $request->query->get('_locale');
if (\is_string($queryLocale) && $this->isSupported($queryLocale)) {
$session->set('_locale', $queryLocale);
$request->setLocale($queryLocale);
return;
}
// 2. Langue mémorisée en session, sinon 3. langue par défaut.
$sessionLocale = $session->get('_locale', $this->defaultLocale);
$request->setLocale($this->isSupported($sessionLocale) ? $sessionLocale : $this->defaultLocale);
}
private function isSupported($locale): bool
{
return \is_string($locale) && \in_array($locale, self::SUPPORTED_LOCALES, true);
}
public static function getSubscribedEvents(): array
{
return [
// Priorité élevée pour définir la locale avant les autres listeners (routing, sécurité...).
KernelEvents::REQUEST => [['onKernelRequest', 20]],
];
}
}