diff --git a/core/core.services.yml b/core/core.services.yml index 5d01d87667..2f8dc4a3fb 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -655,6 +655,9 @@ services: menu.default_tree_manipulators: class: Drupal\Core\Menu\DefaultMenuLinkTreeManipulators arguments: ['@access_manager', '@current_user', '@entity_type.manager'] + menu.language_tree_manipulator: + class: Drupal\Core\Menu\LanguageMenuLinkManipulator + arguments: ['@language_manager'] menu.active_trail: class: Drupal\Core\Menu\MenuActiveTrail arguments: ['@plugin.manager.menu.link', '@current_route_match', '@cache.menu', '@lock'] diff --git a/core/lib/Drupal/Core/Menu/LanguageMenuLinkManipulator.php b/core/lib/Drupal/Core/Menu/LanguageMenuLinkManipulator.php new file mode 100644 index 0000000000..a421f01f6a --- /dev/null +++ b/core/lib/Drupal/Core/Menu/LanguageMenuLinkManipulator.php @@ -0,0 +1,56 @@ +languageManager = $language_manager; + } + + /** + * Hide menu links that do not have translation for the current language. + * + * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree + * The menu link tree to manipulate. + * + * @return \Drupal\Core\Menu\MenuLinkTreeElement[] + * The manipulated menu link tree. + */ + public function filterLanguage(array $tree) { + $current_language = $this->languageManager->getCurrentLanguage()->getId(); + + foreach ($tree as $key => $link) { + if ($link->link instanceof MenuLinkTranslationInterface) { + // If the link is translatable, but has no translation, hide it. + if ($link->link->isTranslatable() && !$link->link->hasTranslation($current_language)) { + unset($tree[$key]); + } + else if ($link->hasChildren) { + // Recursively call this method to filter out untranslated children. + $tree[$key]->subtree = $this->filterLanguage($link->subtree); + } + } + } + return $tree; + } + +} diff --git a/core/lib/Drupal/Core/Menu/MenuLinkTranslationInterface.php b/core/lib/Drupal/Core/Menu/MenuLinkTranslationInterface.php new file mode 100644 index 0000000000..5cbe338574 --- /dev/null +++ b/core/lib/Drupal/Core/Menu/MenuLinkTranslationInterface.php @@ -0,0 +1,21 @@ +getEntity()->isTranslatable(); } + /** + * {@inheritdoc} + */ + public function hasTranslation($langcode) { + if (!$this->getEntity()->hasTranslation($langcode)) { + return FALSE; + } + + return (bool) $this->getEntity()->getTranslation($langcode)->content_translation_status->value; + } + /** * {@inheritdoc} */ diff --git a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php index ed2406034f..0eafe5adde 100644 --- a/core/modules/system/src/Plugin/Block/SystemMenuBlock.php +++ b/core/modules/system/src/Plugin/Block/SystemMenuBlock.php @@ -189,6 +189,7 @@ public function build() { $manipulators = [ ['callable' => 'menu.default_tree_manipulators:checkAccess'], ['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'], + ['callable' => 'menu.language_tree_manipulator:filterLanguage'], ]; $tree = $this->menuTree->transform($tree, $manipulators); return $this->menuTree->build($tree);