Skip to content

Instantly share code, notes, and snippets.

@sufimalek
Last active April 17, 2019 18:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sufimalek/83859e12f472f427459a2f93d5ac7671 to your computer and use it in GitHub Desktop.
Save sufimalek/83859e12f472f427459a2f93d5ac7671 to your computer and use it in GitHub Desktop.
LocaleListener Symfony3
<?php
namespace YourBundle\EventListener;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
class LocaleListener implements EventSubscriberInterface
{
/**
* @var routeCollection \Symfony\Component\Routing\RouteCollection
*/
private $routeCollection;
/**
* @var urlMatcher \Symfony\Component\Routing\Matcher\UrlMatcher;
*/
private $urlMatcher;
private $oldUrl;
private $newUrl;
private $languages;
private $defaultLanguage;
public function __construct(RouterInterface $router, $languages, $defaultLanguage = 'de')
{
$this->routeCollection = $router->getRouteCollection();
$this->languages = $languages;
$this->defaultLanguage = $defaultLanguage;
$context = new RequestContext("/");
}
public function onKernelRequest(GetResponseEvent $event)
{
//GOAL:
// Redirect all incoming requests to their /locale/route equivalent when exists.
// Do nothing if it already has /locale/ in the route to prevent redirect loops
// Do nothing if the route requested has no locale param
$request = $event->getRequest();
$this->newUrl = $request->getPathInfo();
$this->oldUrl = $request->headers->get('referer');
$locale = $this->checkLanguage();
if($locale === null) return;
$request->setLocale($locale);
$pathLocale = "/".$locale.$this->newUrl;
//We have to catch the ResourceNotFoundException
try {
//Try to match the path with the local prefix
$this->urlMatcher->match($pathLocale);
$event->setResponse(new RedirectResponse($pathLocale));
} catch (\Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
} catch (\Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
}
}
private function checkLanguage(){
foreach($this->languages as $language){
if(preg_match_all("/\/$language\//", $this->newUrl))
return null;
if(preg_match_all("/\/$language\//", $this->oldUrl))
return $language;
}
return $this->defaultLanguage;
}
public static function getSubscribedEvents()
{
return array(
// must be registered before the default Locale listener
KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
);
}
}
language_routing:
resource: "@YourBundle/Resources/config/multilanguage-routes.yml"
prefix: /{_locale}
requirements:
_locale: de|en
defaults: { _locale: de}
parameters:
locale: de
languages: [de, en]
services:
app.locale.listener:
class: YourBundle\EventListener\LocaleListener
arguments: ["@router","%languages%","%locale%"]
tags:
- { name: kernel.event_subscriber }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment