1

In Drupal 8, I'm trying to get my menu which has translated menu item filtered by a given language.

So far, I was able to get my menu tree :

    $menu_parameters = $this->menuLinkTree->getCurrentRouteMenuTreeParameters('main');
    $menu_tree = $this->menuLinkTree->load('main', $menu_parameters);
    $manipulators = array(
        // Only show links that are accessible for the current user.
        array('callable' => 'menu.default_tree_manipulators:checkAccess'),
        // Use the default sorting of menu links.
        array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
    );
    $menu_tree = $this->menuLinkTree->transform($menu_tree, $manipulators);

But I still have "stand alone" links in both language.

I looked into manipulators and parameters, but couldn't see anything related to translation.

Maybe using MenuTreeParameters::addCondition, but i'm missing something here.

Any help would be greatly appreciated.

1 Answer 1

0

@pbonnefoi. I've played a lot around with a filtering of menu items by language while worked on menu block multilingual task.

Here what I got:
Drupal\menu_link_content\Plugin\Menu\MenuLinkContent is responsible for retrieving of menu_link entity, but this class hides from us getEntity() method, using one we could get menu link language ($link->getEntity()->get('langcode'))

So the trick is:

  1. Extend this plugin by a new method getLanguage() and register it.
    This plugin used in the menu.tree_storage service, also you need to change link provider class and plugin class to yours.

  2. Create a new manipulator yourmodule.menu_manipulators:filterByLang,
    and use it wherever you want like:
    ['callable' => 'yourmodule.menu_manipulators:filterByLang', 'args' => ['langcode' => $langcode]]

Result code can be something like:

class MenuMultilingualServiceProvider extends ServiceProviderBase {

  public function alter(ContainerBuilder $container) {
    $definition = $container->getDefinition('menu.tree_storage');
    $definition->setClass('Drupal\yourmodule\Menu\MenuTreeStorageMultilingual');
  }
}

class MenuTreeStorageMultilingual extends MenuTreeStorage {
  protected function doCollectRoutesAndDefinitions(array $tree, array &$definitions) {
    foreach ($definitions as &$definition) {
      if ($definition['provider'] == 'menu_link_content') {
        $definition['class'] = 'Drupal\yourmodule\Plugin\Menu\MenuLinkContentMultilingual';
      }
    }
    return parent::doCollectRoutesAndDefinitions($tree, $definitions);
  }

  protected function loadLinks($menu_name, MenuTreeParameters $parameters) {
    $links = parent::loadLinks($menu_name, $parameters);
    foreach ($links as &$link) {
      if ($link['provider'] == 'menu_link_content') {
        $link['class'] = 'Drupal\yourmodule\Plugin\Menu\MenuLinkContentMultilingual';
      }
    }
    return $links;
  }

}

UPDATE: Also tuutti created another solution for that using a new menu tree manipulator menu_block_current_language_tree_manipulator::filterLanguages inside a new menu block type.

Here is his sandbox https://www.drupal.org/sandbox/tuutti/2832329

Also welcome to the discussion regarding translatable menu links on the d.o https://www.drupal.org/node/2466553

UPDATE 2: I've created a module for the end user to bring multilingual features to the menu blocks https://www.drupal.org/sandbox/matsbla/2831709

You can refer to it as an example of all said above.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.