In Drupal 8 there is only one unified way of translating content to different languages. However, in Drupal 7, there were two different ways to do it:
- Using core's Content Translation module: this will create separate nodes per language.
- Using the contributed Entity Translation module: this maintains a single node and the translation happens at a field level.
Entity Translation is what is closer to Drupal 8's implementation of translation. Evolving Web has written blog posts about both methods in the past: content translation and entity translation.
However, that was a while ago, and there are updated ways to do proceed with entity translation migration. We'll go over those updated methods in this article.
Before We Start
- If you are new to migrations in Drupal 8, you may want to read about migrating basic data to Drupal 8 first.
- You can follow the sample code for this tutorial: Migrate example: Entity Translation module on GitHub.
- You need to have migrate_tools and migrate_plus modules to follow this tutorial.
- You need to have Drush installed to run migrations as described in this article.
The Problem
Our imaginary client has provided a database dump for their Drupal 7 site containing some nodes. These nodes might have translations in English, Spanish and French, but there could also be some non-translatable nodes. We need to migrate those nodes to Drupal 8 while preserving the translations.
Setting up the Migration
Create the migration module
We need to create a module for our migrations. In this example, we're naming it migrate_example_entity_translation
.
We then need to add the following modules as dependencies in the module declaration:
Create a migration group
To group the migrations, we also need to create a migration group. To do so, we’ll create a fairly simple configuration file so that the group gets created when the module is installed. The file’s contents should be as follows:
id: entity_translation
label: Entity Translation Group
source_type: Drupal 7
shared_configuration:
source:
key: migrate_d7
Define a new database connection
Next, you need to load the Drupal 7 database into your Drupal 8 installation. To do so, you need to define a new database connection in your settings.php file like this:
$databases['migrate_d7']['default'] = array(
'driver' => 'mysql',
'database' => 'migrate_d7',
'username' => 'user',
'password' => 'password',
'host' => 'db',
'prefix' => '',
);
And then you can import the database dump into this new database connection using your preferred method.
Writing the Migrations
Next thing to do is to write the actual migrations. Per our requirements, we need to write two different migrations: one for the base nodes and one for the translations.
Since Drupal 8.1.x, migrations are plugins that should be stored in a migrations folder inside any module. You can still make them configuration entities as part of the migrate_plus module but I personally prefer to follow the core recommendation because it's easier to develop (you can make an edit and just rebuild cache to update it).
Write the base nodes migration
The first migration to write is the base nodes migration. This will be just a simple migration without anything special related to entity translation.
The full migration file will look like this:
id: example_creature_base
label: Creature base data
migration_group: entity_translation
migration_tags:
- node
- Drupal 7
source:
plugin: d7_node
node_type: article
destination:
plugin: entity:node
process:
type:
plugin: default_value
default_value: article
title: title
status: status
langcode: language
created: created
changed: changed
promote: promote
sticky: sticky
revision_log: log
field_one_liner: field_one_liner
body/value: body/value
body/format:
plugin: default_value
default_value: full_html
Write the translations migration
Now we should write the translations migration. We start by creating the migration file. In this case, we'll name it example_creature_translations.yml. The source section of this migration will look like this:
source:
plugin: d7_node_entity_translation
node_type: article
In the plugin, we're using d7_node_entity_translation; this is a plugin already included in core to handle this type of migration.
The destination for this plugin will be pretty similar to the destination for the base migration. It will look like this:
destination:
plugin: entity:node
translations: true
destination_module: content_translation
Now it's time to write the process section for this migration. It will be pretty similar to the base migration. You only need to keep in mind that you need to migrate two new properties: content_translation_source and content_translation_outdated. So, your process section will look like this:
process:
nid:
plugin: migration_lookup
migration: example_creature_base
source: entity_id
type:
plugin: default_value
default_value: article
title: title
status: status
langcode: language
created: created
changed: changed
promote: promote
sticky: sticky
revision_log: log
field_one_liner: field_one_liner
body/value: body/value
body/format:
plugin: default_value
default_value: full_html
content_translation_source: source
content_translation_outdated: translate
Finally you can setup migration dependencies to ensure your migrations run in the right order:
migration_dependencies:
required:
- example_creature_base
You can look at the full migration file in the code samples repo.
Running the Migrations
Since we have set dependencies, we can instruct Drupal to run the migration group and it will run the migrations in the right order.
To do so, execute drush mim --group=entity_translation
and the output will look like this:
[notice] Processed 9 items (9 created, 0 updated, 0 failed, 0 ignored) - done with 'example_creature_base'
[notice] Processed 9 items (9 created, 0 updated, 0 failed, 0 ignored) - done with 'example_creature_translations'
You can also run drush ms
to see current migration status:
--------------------- ----------------------------------- -------- ------- ---------- ------------- ---------------------
Group Migration ID Status Total Imported Unprocessed Last Imported
--------------------- ----------------------------------- -------- ------- ---------- ------------- ---------------------
Entity Translation example_creature_base Idle 9 9 0 2020-11-09 15:54:06
Entity Translation example_creature_tran Idle 9 9 0 2020-11-09 15:54:07
Next Steps
- Check out the code for the migrate_example_entity_translation module on GitHub.
- Read about migrating basic data to Drupal 8.
- Learn more about migrations in our blog