0

I have a headless Drupal 9 solution and I'm currently working on i18n of the whole site.

I've managed to do everything except menus. The content translation core module is installed and setup correctly. I have all the menu items translated. This a snippet of the code:

  $parameters = new MenuTreeParameters();
  $parameters->onlyEnabledLinks();

  // Get drupal menu tree.
  $menu_tree = \Drupal::menuTree();

  // Load the menu tree.
  $main_menu_tree = $menu_tree->load('main', $parameters);

...

$manipulators = [
  ['callable' => 'menu.default_tree_manipulators:checkNodeAccess'],
  ['callable' => 'menu.default_tree_manipulators:checkAccess'],
  ['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'],
];

$tree = $menu_tree->transform($main_menu_tree, $manipulators);

...

  foreach ($tree as $key => $menu_tree_element) {
    $menu_object = $this->generateSingleMenuObject($menu_tree_element, $max_depth);

    array_push($menu_array, $menu_object);
  }

The 'generateSingleMenuObject' function is where I'd expect to somehow get the objects in a certain language. Here's how the function starts

// Get link from menu tree element.
$menu_tree_element_link = $menu_tree_element->link;

// Get url object from link.
$menu_url_object = $menu_tree_element_link->getUrlObject();

// Create dummy object for storing data.
$menu_object = new stdClass();

// Get id and label.
$menu_object->id = $menu_tree_element_link->getDerivativeId();
$menu_object->label = $menu_tree_element_link->getTitle();

// Get href.
$menu_object->href = $menu_url_object->toString();

I've tried some of the standard options that worked on other entities but without luck.

This is basically the same question as this one.

The only thing I need is the translated menu label. What am I missing? This really sounds like it should be a relatively simple ask. Thank you!

2 Answers 2

0

It seems like you're building a custom solution to generate menu items for a headless Drupal site, and you're encountering difficulties with retrieving translated menu labels. In Drupal 9, using the right services and methods is crucial to achieving accurate translations. To get the translated menu labels for each language, you can follow these steps:

  1. Use the Translation Manager: The MenuLinkManagerInterface provides a method to load menu links with translations. Using the MenuLinkManagerInterface::loadLinks() method with the appropriate parameters, you can load translated menu links.

  2. Loop Through Translated Links: Once you have the translated menu links, you can loop through them and extract the translated label for each link. This ensures that you get the labels in the correct language.

Here's how you can modify your code to achieve this:

use Drupal\Core\Menu\MenuLinkManagerInterface;
use Drupal\Core\Menu\MenuTreeParameters;
use Symfony\Component\DependencyInjection\ContainerInterface;

class MyMenuService {

  protected $menuLinkManager;

  public function __construct(MenuLinkManagerInterface $menuLinkManager) {
    $this->menuLinkManager = $menuLinkManager;
  }

  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('menu.link_manager')
    );
  }

  public function generateMenu() {
    $parameters = new MenuTreeParameters();
    $parameters->onlyEnabledLinks();

    // Load the menu tree.
    $main_menu_tree = $this->menuLinkManager->loadLinks('main', $parameters);

    // Add your manipulators and transform the tree.
    // ...

    $menu_array = [];

    foreach ($tree as $key => $menu_tree_element) {
      $menu_object = $this->generateSingleMenuObject($menu_tree_element, $max_depth);

      array_push($menu_array, $menu_object);
    }

    // ...
  }

  protected function generateSingleMenuObject($menu_tree_element, $max_depth) {
    // ... your existing code ...

    // Load the translated link.
    $translated_menu_tree_element_link = $this->menuLinkManager->loadLink($menu_tree_element->link->getPluginId(), $menu_tree_element->link->getMenuName(), $menu_tree_element->link->getPluginDefinition());

    // Get the translated title.
    $translated_label = $translated_menu_tree_element_link->getTitle();

    // Set the translated label in the menu object.
    $menu_object->label = $translated_label;

    // ... rest of your code ...
  }
}

By using the MenuLinkManagerInterface methods to load and handle menu links, you ensure that you get the translated menu labels for each language. This approach should work well with your headless Drupal solution. Just make sure you have the necessary dependency injections set up and the right services used in your class.

1
  • Hi Z CHAMP, thanks for you response. You are right, it's a Drupal 9 headless solution but I'm afraid your answer isn't as helpful as I hoped it would be. By looking into it I've found the menu.link_manager service doesn't exist and even if it did the MenuLinkManagerInterface doesn't have the functions you are suggesting (loadLinks() and loadLink)? Could you elaborate a bit further or tell me if I'm getting something totally wrong here? Thanks!
    – frajer
    Aug 31, 2023 at 13:39
0

I managed to solve this issue with the following code:

if ($lang) {
  $entity = \Drupal::service('entity.repository')
    ->loadEntityByUuid('menu_link_content', $menu_tree_element_link->getDerivativeId());

  if ($entity->hasTranslation($lang)) {
    $translation = $entity->getTranslation($lang);
    $link_override = $translation->get('link_override')->first();
    if ($link_override) {
      $menu_object->href = $link_override->getUrl()->toString();
    }
    $menu_object->label = $translation->getTitle();
  }
  else {
    $menu_object->label = $menu_tree_element_link->getTitle();
  }
}
else {
  $menu_object->label = $menu_tree_element_link->getTitle();
}

Basically loading the menu_link_content entity by Uuid from the menu tree element link. Then checking if the entity has a translation and if so populating the fields from the translated entity.

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.