Symfony3 can't create translated routes with router in service
Asked Answered
H

1

6

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?

Hunkers answered 2/6, 2017 at 6:41 Comment(4)
where does $routeName in 'route' => $this->router->generate($routeName, array_merge($request->get('_route_params'), ['_locale' => $language])) comes from?Haggi
@Haggi I've edited my question, I've forgot that part, thank you for pointing it out.Hunkers
I think you must use : JMS\I18nRoutingBundle\Router, see github.com/schmittjoh/JMSI18nRoutingBundle/blob/master/Router/… Hope this helps !Nevernever
@MathieuDormeval thank you for your reply. Truly, I must use the Router from the JMS Routing Bundle, but that didn't fix the issue.Hunkers
H
0

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.

Hunkers answered 26/6, 2017 at 8:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.