Search code examples
phpsymfonyroutessymfony-3.2php-7.1

Symfony3 can't create translated routes with router in service


I'm trying to build a language switcher into my main navigation, which is created by the KNPMenuBundle. Translations are done with the JMSTranslationBundle. Both work fine.

I want to create a language switcher with my menu builder, but the generation of the correct routes gives me some headaches.

This is my service:

class MenuService
{
    private $factory;
    private $translator;
    private $router;

    public function __construct(FactoryInterface $factory, Translator $translator, Router $router)
    {
        $this->factory = $factory;
        $this->translator = $translator;
        $this->router = $router;
    }

    public function createMainMenu(RequestStack $requestStack, array $languages)
    {
        // Language Switcher - $languages === ['en', 'de']
        $request = $requestStack->getCurrentRequest();
        $routeName = $request->get('_route');

        $menu->addChild('menu.language', array(
            'uri' => '#',
            'label' => '<i class=\'fa fa-flag-checkered\'></i> '.$this->translator->trans('menu.language.main'),
            'extras' => array('safe_label' => true)
        ))
            ->setAttribute('class', 'dropdown singleDrop')
            ->setChildrenAttribute('class', 'dropdown-menu dropdown-menu-left')
        ;

        foreach ($languages as $language)
        {
            $menu->getChild('menu.language')->addChild('menu.language.'.$language, array(
                'route' => $this->router->generate($routeName, array_merge($request->get('_route_params'), ['_locale' => $language]))
            ));
        }
    }

And this is my service definition

menu_builder:
    class: AppBundle\DependencyInjection\MenuService
    arguments: ['@knp_menu.factory', '@translator.default', '@jms_i18n_routing.router']

menu.main:
    class: Knp\Menu\MenuItem
    factory: ['@menu_builder', createMainMenu]
    arguments: ['@request_stack', '%locales%']
    scope: request
    tags:
      - { name: knp_menu.menu, alias: main }

If I inject the Router provided by the JMSTranslationBundle, I receive the following error:

An exception has been thrown during the rendering of a template ("Unable to generate a URL for the named route "/en/" as such route does not exist.").

If I'm using the default router of symfony I'm getting this error message:

An exception has been thrown during the rendering of a template ("Unable to generate a URL for the named route "homepage" as such route does not exist.").

When I debug the router on the console, this is the output:

  en__RG__homepage                                         ANY        ANY      ANY    /en/                                                 
  de__RG__homepage                                         ANY        ANY      ANY    /de/  

Which router must be used to get the routing to work?


Solution

  • I've found my mistake with the usage of those two bundles.

    The JMS\I18nRoutingBundle\Router::generate() function will return the absolute path for the route given to the function.

    So the following happens:

    $absolutePath = $this->router->generate('homepage', array_merge($request->get('_route_params'), ['_locale' => $language]));
    dump($absolutePath); // Will return "/de/" or "/en" in my case
    

    So, taken that into account, my generation of the routes with the parameter route will obviously fail, because the function doesn't return the route but the absolute path.

    Given that, this works:

    foreach ($languages as $language)
    {
        $menu->getChild('menu.language')->addChild('menu.language.'.$language, array(
            'uri' => $this->router->generate($routeName, array_merge($request->get('_route_params'), ['_locale' => $language]))
        ));
    }
    

    If I change the route to uri my code works correctly.