Drupal 8 Migrate Multilingual Content using Migrate API

As a follow-up to my previous blog post about the usage of Migrate API in Drupal 8, I would like to give an example, how to import multilingual content and translations in Drupal 8.

Prepare and enable translation for your content type

Before you can start, you need to install the “Language” and “Content Translation” Module. Then head over to “admin/config/regional/content-language” and enable Entity Translation for the node type or the taxonomy you want to be able to translate.

As a starting point for setting up the migrate module, I recommend you my blog post mentioned above. To import data from a CSV file, you also need to install the migrate_source_csv module.

Prerequisites for migrating multilingual entities

Before you start, please check the requirements. You need at least Drupal 8.2 to import multilingual content. We need the destination option “translations”, which was added in a patch in Drupal 8.2. See the corresponding drupal.org issue here.

Example: Import multilingual taxonomy terms

Let’s do a simple example with taxonomy terms. First, create a vocabulary called “Event Types” (machine name: event_type).

Here is a simplified dataset:

Id Name Name_en
1 Kurs Course
2 Turnier Tournament

You may save this a csv file.

The recipe to import multilingual content

As you can see in the example data,  it contains the base language (“German”) and also the translations (“English”) in the same file.

But here comes a word of warning:

Don’t try to import the term and its translation in one migration run. I am aware, that there are some workarounds with post import events, but these are hacks and you will run into troubles later.

The correct way of importing multilingual content, is to

  1. create a migration for the base language and import the terms / nodes. This will create the entities and its fields.
  2. Then, with an additional dependent migration for each translated language, you can then add the translations for the fields you want.

In short: You need a base migration and a migration for every language. Let’s try this out.

Taxonomy term base language config file

In my example, the base language is “German”. Therefore, we first create a migration configuration file for the base language:

This is a basic example in migrating a taxonomy term in my base language ‘de’.

Put the file into <yourmodule>/config/install/migrate.migration.event_type.yml and import the configuration using the drush commands explained in my previous blog post about Migration API.

Taxonomy term translation migration configuration file:

This is the example file for the English translation of the name field of the term.

Put the file into <yourmodule>/config/install/migrate.migration.event_type_en.yml and import the configuration using the drush commands explained in my previous blog post about Migration API.

Explanation and sum up of the learnings

The key in the migrate configuration to import multilingual content are the following lines:

These configuration lines instruct the migrate module, that a translation should be created.

This is the real secret. Using the process plugin migration,  we maintain the relationship between the node and its translation.The wiring via the tid field make sure, that Migrate API will not create a new term with a new term id. Instead, the existing term will be loaded and the translation of the migrated field will be added. And thats exactly what we need!

Now go ahead and try to create a working example based on my explanation. Happy Drupal migrations!

Liip related services

Jon, Thanks for this excellent walk through. I used this and some other posts as a guide for importing my multilingual content from CSV into Drupal 8. I ran into a challenging problem involving import of some special multi-lingual fields, like an image field where the image is shared across translations but the ALT text is translated. The fix ended up being adding a content_translation_source in the process section of the foreign language migration YAML. The full writeup with complete example code can be found here http://drupal.stackexchange.com/questions/229750/how-to-migrate-multilingual-image-alt-fields-from-csv/229874#229874

Best regards,

This helped my a lot, thank you!

I get an “Illegal string offset ‘plugin'” message if I don’t write “plugin: get” on the name mapping.

plugin: get
source: Name_en
language: ‘en’

I guess you can only skip the “plugin” if you do direct mapping like “name: Name_en”

One quick tip for people with >2 languages to migrate:

The article says “In short: You need a base migration and a migration for every language.”

You don’t actually need a migration for every language if you dynamically set the language code instead of hardcoding it in the secondary migration files. So, even if you are importing 5 languages, you should still only need 2 migrations.

Thanks for the article.

    Do you have any sample reference code for migration to set the dynamic language. ?

    I’d love to see an example of this as well. Do you mean execute code to dynamically change the migrate config then execute the import?

Excellent points Jon. I think LIIP authors have given most wonderful tips on their articles. Keep up the great work!

Leave a Reply