In Drupal 7 language switcher block used to disable/strike untranslated language links, but it does not work that way in Drupal 8. for example if I go to http://example.com/node/1 language switcher dose not disable/strike untranslated language links. any solution? thanks

Comments

hilrap’s picture

Did anyone get a solution for this yet?

karol haltenberger’s picture

Using hook_language_switch_links_alter in a custom module

It's really easy to create a minimal custom module, all you need is a .info.yml and a .module file.

function MODULE_NAME_language_switch_links_alter(array &$links, $type, $path) {
    if ($node = \Drupal::routeMatch()->getParameter('node')) {
        foreach ($links as $langcode => $link) {
            if ($node && !array_key_exists($langcode, $node->getTranslationLanguages(TRUE))) {
                //There is no translation in that language, disable url
                unset($links[$langcode]['url']);
                //And probably do something with attributes (eg. add class)
                $links[$langcode]['attributes']['class'][] = 'foo';
                //Or you can unset the whole thing
                //unset($links[$langcode]);
            }
        }
    }
}

Using hook_preprocess_block in a module or (preferably) a theme (THEME_NAME.theme file)

function MODULE_OR_THEME_NAME_preprocess_block(&$variables) {
    $block = Block::load($variables['elements']['#id']);
    if ('language_block' == $variables['base_plugin_id'] && $node = \Drupal::routeMatch()->getParameter('node')) {
        foreach ($variables['content']['#links'] as $langcode => $link) {
            if (!array_key_exists($langcode, $node->getTranslationLanguages(TRUE))) {
              //There is no translation in that language, disable url
              unset($variables['content']['#links'][$langcode]['url']);
             //And probably do something with attributes (eg. add class)
             $variables['content']['#links'][$langcode]['attributes']['class'][] = 'foo';
             //Or you can unset the whole thing
             //unset($variables['content']['#links'][$langcode]);
            }
        }
    }
}
leisurman’s picture

@Karol Haltenberger, Thank you for this! The preprocess hooks works great. It hides any language in the list if the node does not have the translation for that language. How can I modify this preprocess hook to hide the whole block if there are no language translation available for the node.

leon kessler’s picture

I've made a few modifications to what Karol Haltenberger posted. These include:

  • Support for all content entity types
  • Checks whether the user has access to the translation or not (e.g. the translation is published)

I will probably post this module up once I've fully tested it.

<?php

/**
 * @file
 * Hide language switcher links for untranslated languages on an entity.
 */
use Drupal\Core\Entity\ContentEntityInterface;

/**
 * Implements hook_language_switch_links_alter().
 */
function language_switcher_link_disable_language_switch_links_alter(array &$links, $type, $path) {
  if ($entity = language_switcher_link_disable_get_page_entity()) {
    $new_links = array();
    foreach ($links as $lang_code => $link) {
      try {
        if ($entity->getTranslation($lang_code)->access('view')) {
          $new_links[$lang_code] = $link;
        }
      }
      catch (\InvalidArgumentException $e) {
        // This language is untranslated so do not add it to the links.
      }

    }
    $links = $new_links;

    // If we're left with less than 2 links, then there's nothing to switch.
    // Hide the language switcher.
    if (count($links) < 2) {
      $links = array();
    }
  }
}

/**
 * Retrieve the current page entity.
 *
 * @return Drupal\Core\Entity\ContentEntityInterface
 *   The retrieved entity, or FALSE if none found.
 */
function language_switcher_link_disable_get_page_entity() {
  $params = \Drupal::routeMatch()->getParameters()->all();
  $entity = reset($params);
  if ($entity instanceof ContentEntityInterface) {
    return $entity;
  }
  return FALSE;
}
nkraft’s picture

Leon Kessler, this is exactly what I've been looking for. Did you wind up doing further testing and posting this somewhere?

leon kessler’s picture

I ended up putting it in a module I called "language_fallback_disable", which (as well as disabling the switcher links) also gives a 404 when you try to access an entity in a language that it has not been translated to yet.
Unfortunately, I could not find a nice way to do that (the entity access system does not support languages), so it's ended up in a quite hacky code (essentially an EventSubscriber on the request which does the check and hijacks the response with a 404).
So it's not really contrib ready, but happy to ping over the module if you need it.

ybenitezf’s picture

I'll likw to test your "language_fallback_disable" module.

mary89’s picture

thank you for sharing this kind of information

efpapado’s picture

On my setup I use page manager to override the node/{node} pages, so the $entity = reset($params); gives a Drupal\page_manager\Entity\PageVariant
In case of a node, the node entity is my 5th element, while for a taxonomy term it's the 4th.

A suggestion for your second function.

/**
 * Retrieve the current page entity.
 *
 * @return Drupal\Core\Entity\ContentEntityInterface
 *   The retrieved entity, or FALSE if none found.
 */
function language_switcher_link_disable_get_page_entity() {
  $params = \Drupal::routeMatch()->getParameters()->all();
  foreach( $params as $param ) {
    if ($param instanceof ContentEntityInterface) {
      // If you find a ContentEntityInterface stop iterating and return it.
      return $param;
    }
  }
  return FALSE;
}

bbombachini’s picture

For anyone that got here, this code became a module that can be found at https://www.drupal.org/project/language_switcher_extended

anybody’s picture

Shouldn't this functionality be bundles in one contrib module solving this for

  • language switcher block
  • content
  • menu items
  • ...?

Update: Finding this 2 month later again with the same need, I think there should be! Or even better a core fix. Are there any related issues?

http://www.DROWL.de || Professionelle Drupal Lösungen aus Ostwestfalen-Lippe (OWL)
http://www.webks.de || webks: websolutions kept simple - Webbasierte Lösungen die einfach überzeugen!
http://www.drupal-theming.com || Individuelle Responsive Themes