Skip to main content
Mediacurrent logo

Blog Post

Deep Dive Into Translating Paragraphs

by Dan Polant
May 24, 2017

At Drupalcon, Jay Callicott and I presented “Multilingual in Drupal 8: A soup to nuts guide featuring and”, which featured a step-by-step guide to setting up a Drupal 8 site for content, interface and config translation. We ended up getting a lot of questions (I took this as a good sign), especially about how translation worked with the Paragraphs module. Paragraphs as a content structure has indeed gotten very popular. To maintain its place as a top multilingual CMS solution, Drupal translation must work well with Paragraphs. So does it?

Mediacurrent has launched a number of sites that involve paragraph translation, including and We recommend “full steam ahead” in terms of taking on multilingual projects in D8, including those with paragraphs. However, there are definitely some rough edges that may require workarounds.

Current paragraph translation model

Below is a diagram of how paragraph translation currently works.

Figure 1: Today’s Paragraph translation model
Today’s Paragraph translation model

This article goes on to explain more about this, including how to configure it.

The key thing to note is that the node only reference one set of paragraphs. These paragraphs are fully translatable though, so as long as you’re okay with your Spanish, English, etc versions containing the same translated paragraph entities, you’ll be fine. But is this a realistic expectation?

Problem: Untranslated paragraph bleed

In some projects, this constraint didn’t give us any trouble. However, we did encounter the following scenario:

  • Client was using TMS (e.g. Lingotek)
  • Client wanted to add a paragraph to a page with translations, and wrote the English version first.
  • They published the English version
  • It then showed up in all of the other translations, and the translated content wasn’t ready yet.

Figure 2: Untranslated paragraph bleed
Untranslated paragraph bleed

Solution: Paragraph-level language field

To fix this problem, we added an optional field to paragraphs to let editors pick a set of languages that each paragraph is allowed to display within. For example, to fix the problem as shown in Figure 2, we would set the value of our new “allowed languages” field to just “English,” at least until the Spanish translation was ready.

To add this new field, go to your paragraph type and add a new field. Pick “Language” as the type and set it to multivalue:

Figure 3: Custom language field configuration
Custom language field configuration

Then, go to your default translation (English in our case) for a node containing one of these paragraphs where you only want it to display in the English/default translation. Set the language value to “English.”

Figure 4: Setting paragraph allowed language
Figure 4: Setting paragraph allowed language

Now you need to write some custom code to implement the language restrictions. There are a lot of ways to do this. See below for an example that uses a theme preprocessor, assuming that you are attaching paragraphs to a node:

 * Implements hook_preprocess_node().
function mymodule_preprocess_node(&$variables) {
  $content = $variables['content'];
  // Loop over your paragraph reference field render element.
  foreach (Element::children($content['field_paragraphs']) as $field_name) {
    $element = &$content['field_paragraphs'][$field_name];
    $paragraph = $element['#paragraph'];
    // Don't show the paragraph if it has specified a language set and the
    // current node's language is not in that set.
    if ($paragraph->hasField('field_language') && $paragraph->field_language->value && !in_array($paragraph->field_language->value, $variables['langcode'])) {
      $element['#access'] = FALSE;

Other methods include altering the node template and looping over the paragraph field content there, or you could even make a new field formatter for paragraphs. The idea is the same: loop over the paragraph output, load the paragraph object, compare its language preferences to the current node language and remove the paragraph from the display if necessary.

I hope that this helps anyone stuck on this issue!

Meet team member, Dan Polant

Dan specializes in architecting and implementing large, complex projects. His approach: to provide confident technical leadership and clear, honest communication, because projects need both to succeed.

Dan became interested in web technologies in 2008, when he created a custom content management platform for his funk band. Shortly after this, he began working with Wordpress, at which point he "saw the light" in terms of what was possible with well-adopted and well-documented open source frameworks. During his last semester at the University of Michigan School of Information graduate program, a professor gave him the opportunity to learn Drupal for a project. This introduction paved the way for the career to which Dan has devoted himself ever since: solving problems for clients using open-source technologies and contributing back to these communities.

Dan spent four years working on the Drupal Commerce project, developing the Drupal 7 version of Commerce Coupon module, and contributing to many elements of the Drupal Commerce ecosystem.

At Mediacurrent, Dan embraces new technologies like React, serverless and Gatsby, employing them on projects where they provide value for our clients. Also, he is passionate about spreading knowledge that can help make deliveries successful. This includes mentoring teammates, blogging about technical topics, and doing internal knowledge-shares about delivery strategies.

Dan enjoys playing guitar, writing music, running and building Legos with his wife and two children.

Learn more about Dan >