src/EventSubscriber/LocaleSubscriber.php line 65
<?phpnamespace App\EventSubscriber;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\HttpKernel\Event\RequestEvent;use Symfony\Component\HttpKernel\Event\ResponseEvent;use Symfony\Component\HttpKernel\KernelEvents;use Symfony\Component\Routing\RouteCollection;use Symfony\Component\Routing\RouterInterface;class LocaleSubscriber implements EventSubscriberInterface{/*** @var RouterInterface*/private $router;/*** @var RouteCollection*/private $routeCollection;/*** @var string*/private $defaultLocale;/*** @var array*/private $supportedLocales;/*** @var string*/private $localeRouteParam;/*** @param RouterInterface $router* @param $defaultLocale* @param array $supportedLocales*/public function __construct($defaultLocale, RouterInterface $router, array $supportedLocales = array('fr', 'en'), $localeRouteParam = '_locale'){$this->router = $router;$this->routeCollection = $router->getRouteCollection();$this->defaultLocale = $defaultLocale;$this->supportedLocales = $supportedLocales;$this->localeRouteParam = $localeRouteParam;}public function isLocaleSupported($locale){return in_array($locale, $this->supportedLocales);}/*** Redirect to correct locale route if omitted or not concordant with route requirements.** @param ResponseEvent $event* @return void*/public function onKernelResponse(ResponseEvent $event): void{//--------------------------------------------------------------------------------------------------------------// GOAL://--------------------------------------------------------------------------------------------------------------// Redirect all incoming requests to their /locale/route equivalent as long as the route will exists when we do so.// If the route required a specific locale so we force it.// Do nothing if it already has /locale/ in the route to prevent redirect loops//--------------------------------------------------------------------------------------------------------------$request = $event->getRequest();$path = $request->getPathInfo();$pathWithoutLocale = null;if (preg_match('#^/([a-zA-Z]{2,3})/#', $path, $parts)) {$pathWithoutLocale = substr($path, strlen($parts[0]) -1);}$route_exists = false; // By default, assume route does not exist.$force_locale = false; // By default, assume not forcing locale.foreach ($this->routeCollection as $routeObject){$routePath = $routeObject->getPath();if ($routePath == '/{'.$this->localeRouteParam.'}'.$path || $routePath == '/{'.$this->localeRouteParam.'}'.$pathWithoutLocale){$route_requirements = $routeObject->getRequirements();$route_exists = true;// Checks if route has a required locale.if (is_array($route_requirements) && array_key_exists($this->localeRouteParam, $route_requirements)&& !empty($route_requirements[$this->localeRouteParam])) {$routeLocales = explode('|', $route_requirements[$this->localeRouteParam]);$force_locale = count($routeLocales) > 1 ? false : $route_requirements[$this->localeRouteParam];}break;}}// If the route does indeed exist then lets redirect there.if ($route_exists == true){// Get the locale from the users browser.$locale = $request->getPreferredLanguage();// If no locale from browser or locale not in list of known locales supported then set to defaultLocale.if (!(!empty($locale) && $this->isLocaleSupported($locale) === true)) {$locale = $request->getDefaultLocale();}// If a locale was detected in route and current locale is different of required locale.if(!is_bool($force_locale) && $locale !== $force_locale) {$locale = $force_locale;}$targeted_url = '/'.$locale.($pathWithoutLocale ?? $path);if ($targeted_url === $path) {return;}$event->setResponse(new RedirectResponse($targeted_url));}elseif ($request->get($this->localeRouteParam) === null && $path === '/')$event->setResponse(new RedirectResponse('/'.$this->defaultLocale.'/'));//Otherwise do nothing and continue on~}public function onKernelRequest(RequestEvent $event): void{$request = $event->getRequest();if (!$request->hasPreviousSession()) {return;}// try to see if the locale has been set as a _locale routing parameterif ($locale = $request->attributes->get($this->localeRouteParam)) {$request->getSession()->set($this->localeRouteParam, $locale);} else {// if no explicit locale has been set on this request, use one from the session$request->setLocale($request->getSession()->get($this->localeRouteParam, $this->defaultLocale));}}public static function getSubscribedEvents(){return [KernelEvents::RESPONSE => [['onKernelResponse', 17]],// must be registered before (i.e. with a higher priority than) the default Locale listenerKernelEvents::REQUEST => [['onKernelRequest', 20]],];}}