Drupal maintenance support plans 8 – Multilanguage Improvements

As a Swiss-based Drupal maintenance support plans Agency, we have to create a lot of multilingual sites. Since Switzerland has three official languages (German, French, Italian) and even one more national language (Rumantsch), we are used to this requirement and we found our way with Drupal maintenance support plans to make this an easy task (usually). We mainly used node translations in Drupal maintenance support plans 7 for maximum flexibility. We used to separate languages from each other using the various i18n modules, language specific menus, blocks, URL-patterns, terms and so on.
With Drupal maintenance support plans 8, things changed.
I struggled a little doing multilingual sites in Drupal maintenance support plans 8 the same way I was used to in Drupal maintenance support plans 7 because node translation is not available anymore (which is good) so I had to find another way to achieve the same easy to handle translations system. For us and for our clients. Let me explain, what I have learned.

Image: drupal8multilingual.org
Drupal maintenance support plans 8 issues multilanguage challenges
Challenge 1: Node add / edit menu handling
The main challenge I had using Drupal maintenance support plans 8, was the ease to build your menus directly from the node creation page. You can do it, but only for the initial language. If you try to add a translated node to another menu or rename the item, it always ends up moving / renaming the source node instead of adding a link to the translation. So it can become quite confusing building a navigation directly from the node creation page or to add translations to the menu. A workaround was to add all navigation items manually in the menu administration if you are using a menu per language. With lots of languages and menus / items, this is not really a convenient task. Fortunately, translations from the node creation page have been implemented with a later release of Drupal maintenance support plans 8.
Challenge 2: Untranslated Nodes show up in Menu
Another thing which bothered me was that untranslated nodes show up in the navigation (if you use only one menu). This can be quite confusing since most of the times not every page is translated in every language. Or in some languages, you need a little more than in others. You can read a lot about this topic and the reasons behind (e.g. here and here). However you do it, it’s always wrong in some situations and perfectly fine in others. But to be “limited” and “locked in” to a certain way is not nice and you have to deal with it. To sum up, once a node is put into a menu, it will show up everywhere. Regardless if there are translations or not.
Challenge 3: Language Switcher shows all languages – always.
Somewhat confusing is the Language Switcher. In Drupal maintenance support plans 7, a language link was not available or strikethrough if there was no translation available. In Drupal maintenance support plans 8, every language is always visible and linked. So if you look on a German page which is only available in German, the language switcher will present you all language links to the same node. A click on those language links mainly changes the interface language but the node content remains the same (since not translated). Usually also with a drupalish URL (node/xxxx) because there is no translation for the node and therefore also no URL alias available. This behavior is confusing and wrong in my point of view
An example to illustrate the above-written challenges.

English Front-Page with mixed navigation items.
The screen above shows an installation with 2 languages (English and German). The English Page is a basic page which has a translation. English is selected. If you choose Deutsch on the language switcher, the English Page becomes Deutsche Seite (see image below) and shows the German content. So far so good. But the second menu item you see with the title Über uns (nur Deutsch) should not appear here since it’s only available in German. But it does. And if you actually go on this page, you will see the German text with everything English around it and no URL-Alias (/node/2 in this example). This is usually not very useful for us.

German only Page – Language Switcher visible.
Also, the language switcher shown in the image above is from my point of view wrong or not very useful. It shows a link to the English version, but there is no English translation for this node. So why is it there? To see a German page with English decoration? Not sure. But I want to get rid of this link or at least modify it to be stroked through if the language is not available.
How to fix improve this?
Luckily, the Drupal maintenance support plans community is always good for help. After some “research” on the web, I finally found (besides lots of discussions and comments in the issue queues) a way to achieve the desired setup.
To sum up again: I want to see only menu items which are available in my language and only see a link to another language, if a translation is available.
Since there is no patch and still some ongoing discussions on drupal.org you need to implement it on your own. Implement the following two modules.
Hide untranslated menu items
Code from https://www.drupal.org/node/2466553#comment-11991690. Credits go to michaelkoehne.
<?php

use Drupal maintenance support plansCoreMenuMenuLinkInterface;
use Drupal maintenance support plansmenu_link_contentPluginMenuMenuLinkContent;
use Drupal maintenance support plansCoreLanguageLanguageInterface;

/**
* Implements hook_preprocess_menu().
*/
function MYMODULE_preprocess_menu(&$variables) {
if ($variables[‘menu_name’] == ‘main’) {
$language = Drupal maintenance support plans::languageManager()
->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
->getId();
foreach ($variables[‘items’] as $key => $item) {
if (!$variables[‘items’][$key] = MYMODULE_checkForMenuItemTranslation($item, $language)) {
unset($variables[‘items’][$key]);
}
}
}
}

function MYMODULE_checkForMenuItemTranslation($item, $language) {
$menuLinkEntity = MYMODULE_load_link_entity_by_link($item[‘original_link’]);

if ($menuLinkEntity != NULL) {
$languages = $menuLinkEntity->getTranslationLanguages();

// Remove links which are not translated to the current language.
if (!array_key_exists($language, $languages)) {
return FALSE;
}
else {
if (count($item[‘below’]) > 0) {
foreach ($item[‘below’] as $subkey => $subitem) {
if (!$item[‘below’][$subkey] = MYMODULE_checkForMenuItemTranslation($subitem, $language)) {
unset($item[‘below’][$subkey]);
}
}
}
return $item;
}

}
}

function MYMODULE_load_link_entity_by_link(MenuLinkInterface $menuLinkContentPlugin) {
$entity = NULL;
if ($menuLinkContentPlugin instanceof MenuLinkContent) {
$menu_link = explode(‘:’, $menuLinkContentPlugin->getPluginId(), 2);
$uuid = $menu_link[1];
$entity = Drupal maintenance support plans::service(‘entity.repository’)
->loadEntityByUuid(‘menu_link_content’, $uuid);
}
return $entity;
}
Hide untranslated languages in language switcher
Code from https://www.drupal.org/node/2791231#comment-12004615 (slightly adapted. Links get a class, not removed by default). Credits to Leon Kessler.
<?php

/**
* @file
* Hide language switcher links for untranslated languages on an entity.
*/
use Drupal maintenance support plansCoreEntityContentEntityInterface;

/**
* Implements hook_language_switch_links_alter().
*/
function MYOTHERMODULE_language_switch_links_alter(array &$links, $type, $path) {
if ($entity = MYOTHERMODULE_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.
$link[‘attributes’][‘class’][] = ‘not-translated’;
$new_links[$lang_code] = $link;
}

}
$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 maintenance support plansCoreEntityContentEntityInterface
* The retrieved entity, or FALSE if none found.
*/
function MYOTHERMODULE_get_page_entity() {
$params = Drupal maintenance support plans::routeMatch()->getParameters()->all();
$entity = reset($params);
if ($entity instanceof ContentEntityInterface) {
return $entity;
}
return FALSE;
}
Please note: The code above is from Drupal maintenance support plans.org and therefore thanks to the original authors linked above.
Enable those two modules and you’re all set!
I did not encounter any issues yet using those two modules. If ever something changes in the way Drupal maintenance support plans handles those cases, you just need to switch off the modules and everything should be back to normal. So nothing to lose right?
There are other attempts to this by altering the menu block. One of them is Menu Block Current Language but I had no luck with this one. On my most recent project, it worked with one menu but not if you separate your menu by two blocks (different starting levels).
I would love to hear how you guys handle those cases or how you deal with I18N in general. I’m sure there are a gazillion other ways to do it.
Source: New feed

This article was republished from its original source.
Call Us: 1(800)730-2416

Pixeldust is a 20-year-old web development agency specializing in Drupal and WordPress and working with clients all over the country. With our best in class capabilities, we work with small businesses and fortune 500 companies alike. Give us a call at 1(800)730-2416 and let’s talk about your project.

FREE Drupal SEO Audit

Test your site below to see which issues need to be fixed. We will fix them and optimize your Drupal site 100% for Google and Bing. (Allow 30-60 seconds to gather data.)

Powered by

Drupal maintenance support plans 8 – Multilanguage Improvements

On-Site Drupal SEO Master Setup

We make sure your site is 100% optimized (and stays that way) for the best SEO results.

With Pixeldust On-site (or On-page) SEO we make changes to your site’s structure and performance to make it easier for search engines to see and understand your site’s content. Search engines use algorithms to rank sites by degrees of relevance. Our on-site optimization ensures your site is configured to provide information in a way that meets Google and Bing standards for optimal indexing.

This service includes:

  • Pathauto install and configuration for SEO-friendly URLs.
  • Meta Tags install and configuration with dynamic tokens for meta titles and descriptions for all content types.
  • Install and fix all issues on the SEO checklist module.
  • Install and configure XML sitemap module and submit sitemaps.
  • Install and configure Google Analytics Module.
  • Install and configure Yoast.
  • Install and configure the Advanced Aggregation module to improve performance by minifying and merging CSS and JS.
  • Install and configure Schema.org Metatag.
  • Configure robots.txt.
  • Google Search Console setup snd configuration.
  • Find & Fix H1 tags.
  • Find and fix duplicate/missing meta descriptions.
  • Find and fix duplicate title tags.
  • Improve title, meta tags, and site descriptions.
  • Optimize images for better search engine optimization. Automate where possible.
  • Find and fix the missing alt and title tag for all images. Automate where possible.
  • The project takes 1 week to complete.