Last updated March 19, 2015. Created on March 16, 2014.
Edited by Grimreaper, Kristen Pol, akronym. Log in to edit this page.

Using migrate-7.x-2.6-RC1.

The main purpose of this cookbook is to show how to import one content type in as many languages as you want using CSV import.

It assumes that you have one csv file per language, that each is in the csv format, and that the content for all its translations are at the same line.

Force using "" to avoid problem with language like russian chinese, japanese, arabic, etc...

Principle

  • You first import the content in your main language.
  • In this import, you set the tnid using the postImport method.
  • Then you import your content in the other language, and you set the tnid using the method gettnid which go in the main language migration table made by migrate to retrieve the tnid.

Structure of the module

my_module :

  • my_module.info
  • my_module.module
  • my_module.migrate.inc
  • my_module.install
  • includes
    • basic.inc
    • content_type_1.inc
    • content_type_2.inc
  • data_sources
    • Content_type_1
      • content_type_1.en.csv
      • content_type_1.fr.csv
      • ...
    • Content_type_2
      • content_type_2.en.csv
      • content_type_2.fr.csv
      • ...

Content_type_2 will be used in https://drupal.org/node/2218857.

my_module.info

name = my module
description = Module to import content from csv
core = 7.x

dependencies[] = migrate

files[] = my_module.migrate.inc
files[] = includes/basic.inc
files[] = includes/content_type_1.inc
files[] = includes/content_type_2.inc

my_module.module

The simplest part :)

<?php

?>

my_module.migrate.inc

<?php
/**
 * Implements hook_migrate_api().
 */
function my_module_migrate_api() {

 
module_load_include('inc', 'my_module', 'includes/basic');
 
module_load_include('inc', 'my_module', 'includes/content_type_1');
 
module_load_include('inc', 'my_module', 'includes/content_type_2');

 
// Prepare migration per language
 
$migrations = array();
 
$language_list = language_list();

  foreach (
$language_list as $language_prefix => $language) {
   
// Need to remove '-'
   
$language_prefix = str_replace('-', '_', $language_prefix);

   
$migrations['ContentType1_' . $language_prefix] = array(
     
'class_name' => 'ContentType1Migration',
     
'group_name' => 'ContentType1Migrate',
     
'language_prefix' => $language_prefix,
    );
   
$migrations['ContentType2_' . $language_prefix] = array(
     
'class_name' => 'ContentType2Migration',
     
'group_name' => 'ContentType2Migrate',
     
'language_prefix' => $language_prefix,
    );
  }

 
$api = array(
   
'api' => 2,
   
'groups' => array(
     
'ContentType1Migrate' => array(
       
'title' => t('ContentType1 Migrations'),
      ),
     
'ContentType2Migrate' => array(
       
'title' => t('ContentType2 Migrations'),
      ),
    ),
   
'migrations' => $migrations,
  );
  return
$api;
}
?>

my_module.install (optional)

<?php
/**
 * Implements hook_enable().
 */
function my_module_enable() {
 
$language_list = language_list();

  foreach (
$language_list as $language_prefix => $language) {
   
// Need to remove '-'
   
$language_prefix = str_replace('-', '_', $language_prefix);

   
MigrationBase::registerMigration(
     
'ContentType1Migration',
     
'ContentType1_' . $language_prefix,
      array(
       
'class_name' => 'ContentType1Migration',
       
'group_name' => 'ContentType1Migrate',
       
'language_prefix' => $language_prefix,
      )
    );
   
MigrationBase::registerMigration(
     
'ContentType2Migration',
     
'ContentType2_' . $language_prefix,
      array(
       
'class_name' => 'ContentType2Migration',
       
'group_name' => 'ContentType2Migrate',
       
'language_prefix' => $language_prefix,
      )
    );
  }
}

/**
 * Implements hook_disable().
 */
function my_module_disable() {
 
$language_list = language_list();

  foreach (
$language_list as $language_prefix => $language) {
   
// Need to remove '-'
   
$language_prefix = str_replace('-', '_', $language_prefix);

   
Migration::deregisterMigration('ContentType1_' . $language_prefix);
   
Migration::deregisterMigration('ContentType2_' . $language_prefix);
  }
}
?>

basic.inc

<?php
abstract class my_module_Basic_Migration extends Migration {
  public function
__construct($arguments) {
   
parent::__construct($arguments);
   
ini_set('auto_detect_line_endings', TRUE);
  }
}
?>

content_type_1.inc

<?php
class ContentType1Migration extends my_module_Basic_Migration {
  public function
__construct($arguments) {
   
parent::__construct($arguments);
   
$this->description = t('Import ContentType1 CSV-file');
   
$columns = array(
     
// "Source": ('Fieldname', 'Description')
     
0 => array('csv_id', t('CSV id')),
     
1 => array('title', t('Title')),
      ...
    );
   
$this->source = new MigrateSourceCSV(
     
DRUPAL_ROOT . '/' . drupal_get_path('module', 'my_module') . '/data_sources/Content_type_1/content_type_1.' . $arguments['language_prefix'] . '.csv',
     
$columns,
      array(
       
'header_rows' => 1,
       
'embedded_newlines' => TRUE
     
)
    );
   
$this->destination = new MigrateDestinationNode('content_type_1');
   
$this->map = new MigrateSQLMap($this->machineName,
      array(
       
'csv_id' => array(
         
'type' => 'int',
         
'unsigned' => TRUE,
         
'not null' => TRUE,
        )
      ),
     
MigrateDestinationNode::getKeySchema()
    );
    if (
$arguments['language_prefix'] != 'en') {
     
$this->addSoftDependencies(array('ContentType1_en'));
    }

   
// Mapped fields
   
$this->addFieldMapping('title', 'title')
      ->
defaultValue('');
   
$this->addFieldMapping('language')
      ->
defaultValue(str_replace('_', '-', $arguments['language_prefix']));
   
// tnid
   
if ($arguments['language_prefix'] != 'en') {
     
$this->addFieldMapping('tnid', 'csv_id')
        ->
sourceMigration('ContentType1_en');
    }
  }

  public function
complete($entity, stdClass $row) {
   
// Put the tnid for english content after it is created.
   
if ($this->arguments['language_prefix'] == 'en') {
     
$entity->tnid = $entity->nid;
     
node_save($entity);
    }
  }
}
?>

content_type_2.inc

Will be described in https://drupal.org/node/2218857.

Example files:

content_type_1.en.csv

"CSV ID","Title"
1,"Title 1"
2,"Title 2"
3,"Title 3"

content_type_1.fr.csv

"CSV ID","Title"
1,"Titre 1"
2,"Titre 2"
3,"Titre 3"

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.