HOW TO CUSTOMIZE THE LANGUAGE SELECTOR IN DRUPAL

Drupal 8 dramatically improved the capabilities for creating multilingual websites. The content translation was moved to the core and an improved architecture made it much easier to internationalize complex sites. However, the language switcher could use some improvements. Here's how we customized it.

As a digital agency with Catalan origins, we've become accustomed to having two languages of conduct: Spanish, Catalan (and now English). We switch back and forth without even noticing and have learned to read, write and do business in both languages effortlessly. Our clients are mostly Spanish, but many serve an international audience or operate across borders, so there are now quite a few multilingual websites in our portfolio.

Despite the potential complexities that multilingual websites can present, Drupal has always been notoriously adamant about supporting all languages, including those with non-Latin languages and those that read from right to left. While multilingual sites in Drupal 7 often required a lot of internationalization and translation modules, combined with some custom code, Drupal 8 was going to solve all our multilingual headaches once and for all. Did it?

Everything is (almost) perfect.

Drupal 8 has indeed made it easier than ever to support multiple languages. Its architectural overhaul simplified the structure, making the internationalization of content much more logical and efficient. It moved a lot of internationalization functionality into the core to improve maintenance and support. And, of course, to allow Drupal site builders to create ready-to-use multilingual sites.

So, Drupal 8 solves all the hassles you might have had with multiple languages on a single site perfectly and forever. right? Not exactly.

Things are never exactly the way we (or our customers) want them and that's okay. That's why there are Drupal developers.

Elegant and minimalistic

Let's talk about the language switcher in Drupal 8. You can enable it, place it as a block in the region of your choice and it practically works. It displays all the added languages written completely as well:

  • English
  • Catalan
  • Spanish

However, as we like our site sleek and minimalistic and consider our visitors tech-savvy, we would like to customize the links and determine exactly where and how the language switcher links are represented.

Customizing the language block

To control the output of the language switching block, we want to be able to display only the necessary links. We don't need a block title or any of those annoying elements, we just want an HTML list with links, for example:

<ul class="language-switcher-language-url links">
  <li hreflang="en" class="en">
    <a href="/" class="language-link" hreflang="en">en</a>
  </li>
  <li hreflang="es" class="es is-active">
    <a href="/es" class="language-link is-active" hreflang="es">es</a>
  </li>
</ul>

Fortunately, Drupal 8's Twig templating system makes it fairly easy to render exactly what we want. Simply place it in the page.html.twig of your custom theme where you want your language switcher links:

{ # Language switcher # }
{{ drupal_block('language_block:language_interface', wrapper=false) }}

Change link tags

Although it is probably best practice to write the available languages in full (English, Spanish, French, Catalan), we could do it with more elegant minimalism. Also, we consider our visitors as tech-savvy, so we could probably suffice by displaying only the language codes as our links: EN and ES.

Let's tackle this one with a preprocessing function. Simply paste this code into your CUSTOMTHEMENAME.theme and the links in your switcher should magically transform into language codes:

/**
 * Use language code for the language switcher
 */
function CUSTOMTHEMENAME_preprocess_links__language_block(&$variables) {
  foreach ($variables['links'] as $i => $link) {
    // @var \Drupal\language\Entity\ConfigurableLanguage $linkLanguage
    $linkLanguage = $link['link']['#options']['language'];
    $variables['links'][$i]['link']['#title'] = $linkLanguage->get('id');
  }
}

Don't forget to change CUSTOMTHEMENAME to the name of your custom theme.

We are replacing the language name with your "language code".

Hide links for non-translated content

Once the language switcher is enabled and in place, it is always there. Even when there is no translated version of the page you are viewing, there is a link to the translation of that page. Which doesn't exist and will just take you back to the same node, possibly on a path with no alias. That's bad for SEO and worse for usability.

This can be fixed quickly and easily using the "Language Switcher Extended" module that allows you to specify how the links will behave just in these cases.

Another way to do the same is to program a custom module for the specific web project. But in most cases, this is not necessary, although it gives more control and may be necessary in some special cases.

Now the untranslated links should magically disappear until I publish a translation of the page.

It has been debated whether you should remove links to untranslated content as we demonstrate here or take a less radical approach and add CSS classes to show dimmed links or apply strikethrough. In my experience, it is best not to hide things with CSS if you can do the same on the backend. For performance, usability, accessibility (screen readers) and not to depend on the visual theme if you change it in the future.

Have Any Project in Mind?

If you want to do something in Drupal maybe you can hire me.

Either for consulting, development or maintenance of Drupal websites.