Multilingual Drupal - Part 1: The Process

Getting started: elaborate on a process

Having a good translation strategy starts at the early beginning of a project. Here are a few topics that could help to elaborate a process.

The translation strategy could be approached in several ways depending on the project:

With a minimum viable product (MVP) or a new project build

  • Fully translated, with several languages, for the first release.
  • A proof of concept in a single initial language.
  • A subset of languages first, then add more languages at a later phase.

With upcycling an existing project or doing a project migration

  • The source and destination content model might not be the same.
  • Some translations could be partial or outdated.

For both content creation and update, we should be able to answer the following questions:

  • Who are the personas? They could be represented by Drupal roles: content editor, translator, reviewer, publisher, etc.
  • What are their relations with the translation system, which features can help their work?
  • How will the content and features access be handled?
  • How will the content flow between personas, is there a publication workflow? Example: when the source is ready for translation is a simple workflow enough (translation review then publication) or do we need a more elaborate process that allows back and forth between reviews?
  • Are revisions required? Would it be possible to roll back a previous revision and how does it affect translations? Also what happens when the source is updated?
  • What are the relations between languages? Are we able to translate from another language than the source?
  • For locale, how can I make use of a first contributed version then override it, handle change and provide flexibility when more context is needed?
  • What are the available resources? In house translators, one or several specific translation agencies that might be business-specific, automated translation services? How do we want to deal with deadlines and scheduled publications?
  • How does it integrate with third parties (if any)? Translators could be part of a CRM or translation jobs might need to be reported in an accounting system.
  • What is the translation scope? It could be frontend and/or backend, do we want URL aliases to be translated?
  • Do we have to deal with external entities (e.g. content being imported and updated from an external service)?
  • Do we need a different structure between the source and the translation?
  • How does the translation fallback behave? Do we want to display the source, display a message, redirect?

Drupal multilingual concepts

Let’s see what Drupal brings out of the box. Here is a quick recap of the Drupal translation concepts.

  • Interface translation: also known as “locale”, it can be handled via Gettext / .po files. It includes strings passed through the t() function or trans Twig tag, these strings are also contained in Yaml files (module name in the info file, schema label, title in routing and annotations. They are not synced between environments by default, but their import can be automated. Example: the label of a button in a Twig template.
  • Configuration entities: core, contributed and custom modules are providing them via their schema. They can be synced via the configuration export/import between environments. Example: strings set for Views, Blocks, settings.
  • Content entities: their blueprints are made from the configuration. They are specific to each environment by default. Examples: Nodes, Terms, Users, Media, etc.


With the Drupal capabilities in mind, we could continue by refining some parts of our process as common user stories, by project stakeholders. Then see how it can be covered with the core or contributed ecosystem. Here are some examples of possible expectations.

As a Product Owner, I can

  • have an overview of all the translations and their status
  • access each node translation without having the admin UI translated
  • edit translations that are defined by code

As a Translator, I can

  • be notified of new translation requests without having to access a Drupal site
  • receive structured files like .xlf or .po that I can use with other translation solutions than Drupal

As a Translation Reviewer, I can

  • let know the Publisher that a translation is ready for publication

As a Site Builder, I can

  • limit the edit/view access to several languages to translate content before publishing it, as a whole for a language
  • limit the access to translation languages, by user

As a Developer, I can

  • add metadata to the locale by specifying context-related strings
  • have support for plural
  • update locales between environments
  • extract translations from custom code
  • make sure that every string is translatable
  • migrate content with translations and map them to a new content model

Translations in the wild

Content translation will be developed in the second part of this series, so let’s see first how some of these user stories can be covered by the contributed ecosystem and which tools are available for developers.

Drupal core (>= 8, 9)

Each core concept is basically covered by its own module with the Language module as the common requirement: Configuration Translation, Content Translation, Interface Translation.

Make the source language editable

Since 8.5.0, the Interface translation module provides an easy way to enable interface translation for the site default language. Given that English is the default language: edit the English language and check “Enable interface translation to English”. In a sense, it can be regarded as a successor of String Overrides.


Multilingual migrations are stable (8.9.0, 9.0.0). Migrate Drupal Multilingual module is no longer required.

Translation context

Context can be used to provide or identify variations of the same string. So it can also be used to group translations for business-specific translations (e.g. custom code) that might not fall in the scope of contributed translations by adding metadata.

This issue aims to provide context filtering in core (> 9.x) so it will replace modules like Locale Translation Context.

Examples of context definition

  • PHP $this->t('May', [], ['context' => 'Long month name']);
  • Twig <span>{% trans 'May' with {'context': 'Long month name'} %}</span>
  • Javascript Drupal.t('May', {}, {context: 'Long month name'});
  • PHP annotation label = @Translation("Month", context="Date"),

The core API

The core provides great services to deal with translations, like 

Contributed solutions

Translation Management Tool (TMGMT)

TMGMT facilitates the translation process and really shines if you need to export the data structure with the content while outsourcing a translation Job.It supports a large variety of translation service providers (Lionbridge, DeepL, Google, ...) and provides support for content, configuration and interface translation. These 3 sources are displayed as an overview, so it replaces solutions like Translation Overview.

The beauty of this unified solution is that you can outsource translations with any of the provider (like DeepL), and e.g. create a Job that groups each locale string as Job items.

TMGMT Source

Translation Extractor (POTX)

The Drupal core interface translation export (admin/config/regional/translate/export) will export basically everything that is available in the interface translation UI. This module provides

  • string extraction from code, instead of strings that have previously been registered
  • filtered extractions as .pot (template) or .po files by language with optional inclusion of the translations.

The Drupal 8 version is still a working in progress, make sure to review these issues:
String context not taken into account when retrieving a translation and Plural translation values are not exported.

POEdit with context

Disable Language
Filters out disabled languages from the language switcher and sitemap redirects users that don’t have the permission to view disabled languages and much more.

Allowed Languages
Set restrictions on which content a user can edit by language.

Administration Language Negotiation
Its main use case is to allow displaying the frontend of the site in one language and still keep most of the backend in English (or another language of your choice).

Since 8.6.4, this behaviour can still be partially achieved for the backend, with core configuration, by using the Account administration pages as a detection method for interface text.

Paragraphs Asymmetric Translation Widgets
While using Paragraphs, it could be required to have a different structure between the source and the translations. Make sure to carefully test it if you switch from Paragraphs default widgets as data loss might occur if you already have translations. Also, there might be some limitations while using TMGMT.

Drush supports locale check, update and import (see

Quick tips

Having an overview of the content model (entities and relations) can help to answer accurately some site-building questions:

  • which entities are the subject of a content moderation
  • which ones are translatable (entity and field level)
  • which tools might answer the requirements (Paragraphs, Blocks, ...)
  • how does it integrate with site search (e.g. while using Search API)

Troubleshooting common errors:

  • Interface: Check if the string is wrapped in a t() function or trans tag. Reduce duplicates early (interface translation strings are case sensitive)
  • Content: check the translatability of your entities and fields, the Content language UI is a great tool for this (/admin/config/regional/content-language)
  • Configuration: the schema or the .config_translation.yml files might be missing

Making use of context early for business-specific translations might help later to include translation metadata to export or filter.


More to come on this topic

In the next blog, we'll adapt our content translation flow and delegate this to the Translation Management Tool (TMGMT), where we will tackle different approaches to solving complex issues such as using content moderation for symmetric and asymmetric translation.
Finally, we'll finish off the series with a third instalment to look into how we've approached and solved a complex Gatsby multilingual integration with Drupal 7, and how this can be applied to a decoupled Drupal 8 site. 

Questions? Comments? Want to learn more? Get in touch with us today!

Stay in the Loop

We will use the personal data you are sharing with us solely for the purpose of sending you our newsletter. See more here: Data Privacy.


Let us know how we can help you.