2

I setup Drupal 8 with 2 languages English & Arabic. Now when an article (English for eg.) does not have a translation (in Arabic) and the user switches the language from the menu. The page loads in Arabic and the article loads in English. I need to return a 404 or something different.

Any advise would be helpful.

1 Answer 1

3

It can not be done using core or contrib

To present 404 page not found (might create bad UX)

You could do something like this in your own module MODULENAME.module file

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Drupal\Core\Language\LanguageInterface;

/**
 * Implements hook_entity_view().
 */
function MODULENAME_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  $lang = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
  $type_id = $entity->getEntityTypeId();
  $translated = $entity->hasTranslation($lang);
  if ($type_id = "node" && $view_mode == "full" && !$translated) {
    throw new NotFoundHttpException();
  }
}

but once you go to the not found page the language switcher will not be able to take you back to the translated page though

To Hide untranslated languages in language switcher

There is a core issue about this and solutions are worked out but until it is solved you could create your own module

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

/**
 * Implements hook_language_switch_links_alter().
 */
function MODULENAME_language_switch_links_alter(array &$links, $type, $path) {
  if ($entity = MODULENAME_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 MODULENAME_get_page_entity() {
  $params = \Drupal::routeMatch()->getParameters()->all();
  $entity = reset($params);
  if ($entity instanceof ContentEntityInterface) {
    return $entity;
  }
  return FALSE;
}

Above solution is taken from this post

To Hide untranslated menu items

You can use menu_multilingual which gives option when you create/edit a menu block to hide untraslated items.

4
  • Thank you @GiorgosK I've been banging my head against the issue for a whilst. I'll give it a shot.
    – Alex Seif
    Commented Mar 14, 2018 at 11:20
  • I'm going to keep working on it, but the first solution (which is the best so far) causes PHP Fatal error: Allowed memory size of 134217728 for different files. I'm debugging
    – Alex Seif
    Commented Mar 14, 2018 at 19:47
  • I have tested it and worked, not sure why it would need more memory. I suppose you have set your php memory to 128 which I would not recommend set it at least to 256MB (in your php.ini stackoverflow.com/questions/561066/…)
    – GiorgosK
    Commented Mar 14, 2018 at 20:20
  • So this is what I ended up with. ` $response = new RedirectResponse("/$lang"); drupal_set_message(t('Page not found.')); $response->send(); return; ` Still can't print that message though
    – Alex Seif
    Commented Apr 25, 2018 at 18:11

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.