I was implementing simple menu, that would allow user to change site language. The site uses standard symfony2 localized urls like http://www.example.com/en/contact. The problem was to return user to a page, where he previously was, but rendered in a selected language.
Let me show you my solution. I’ve written kernel event listener and I registered it at my bundle’s Resources/config/services.xml file:
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="twig.extension.getlangarray.expedio_simple" public="false">
<tag name="twig.extension" />
<argument type="service" id="service_container" />
</service>
<service id="acme.demo.listener">
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
<argument type="service" id="router" />
</service>
</services>
</container>This file is merged into Symfony2 configuration from DependencyInjection/ExpedioSimpleExtension.php:
class ExpedioSimpleExtension extends Extension {
/**
* {@inheritDoc}
* @param array $configs
* @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
*/
public function load(array $configs, ContainerBuilder $container) {
$loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('services.xml');
}
public function getAlias() {
return 'expedio_simple';
}
}Listener implementation:
namespace Expedio\SimpleBundle\Listener;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
class Kernel {
/**
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
private $router;
public function __construct(\Symfony\Component\Routing\Router $router) {
$this->router = $router;
}
public function onKernelRequest(GetResponseEvent $event) {
if ($event->getRequestType() !== \Symfony\Component\HttpKernel\HttpKernel::MASTER_REQUEST) {
return;
}
/** @var \Symfony\Component\HttpFoundation\Request $request */
$request = $event->getRequest();
/** @var \Symfony\Component\HttpFoundation\Session $session */
$session = $request->getSession();
$routeParams = $this->router->match($request->getPathInfo());
$routeName = $routeParams['_route'];
if ($routeName[0] == '_') {
return;
}
unset($routeParams['_route']);
$routeData = array('name' => $routeName, 'params' => $routeParams);
//Skipping duplicates
$thisRoute = $session->get('this_route', array());
if ($thisRoute == $routeData) {
return;
}
$session->set('last_route', $thisRoute);
$session->set('this_route', $routeData);
}
}It just saves last request route data each time user opens a page. And in controller when user wants to change locale I do this:
/**
* @Route("/setlocale/{locale}", name="set_locale")
* @param string $locale
* @return array
*/
public function setLocaleAction($locale) {
/** @var \Symfony\Component\HttpFoundation\Session $session */
$session = $this->get('session');
$session->setLocale($locale);
$last_route = $session->get('last_route', array('name' => 'index'));
$last_route['params']['_locale'] = $locale;
return ($this->redirect($this->generateUrl($last_route['name'], $last_route['params'])));
}Well, this is how it works




