Problem/Motivation

When migrating contents (from a CSV file) to a multilingual content type using Entity Translation (ie. Multilingual support is Enabled, with field translation ), translated fields values are properly migrated (using the *:language subfield and array values for both the field and the subfield) but entity translations are not created.

Using the following code

class MyContentMigration extends Migration {
  function __construct($arguments) {
    // ...
    $this->addFieldMapping('language')->defaultValue('en');
    // ...
    $this->addFieldMapping('body', 'description');
    $this->addFieldMapping('body:language')->defaultValue(array('en', 'fr'));
    $this->addFieldMapping('body:format')->defaultValue(filter_default_format());
    // ...
  }
  function prepareRow($row) {
    $row->description = array($row->description, $row->fr_description);
    return TRUE;
  }

The Translate tab for the imported contents does not list any available translations (ie. only the original English is there). When inspected via the Devel tab, I can see both the English and French value for the body field (see translated-body-field.png), but no French translation (see missing-french-translation.png).

Either something is missing in my Migration class in order to let the Entity Translation module known about the French translation of the node. Or something changed since since #1537076: Handle language subfield on a value-by-value basis was fixed.

#1537076: Handle language subfield on a value-by-value basis

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

pbuyle’s picture

In http://drupal.stackexchange.com/a/66653/177, the author overrides the Migration::prepare($entity, stdClass $row) method in to set both the field values in multiple languages (which I did through the *:language subfield) and to set $entity->translations (which is what I seems to be missing). If this is indeed the way to do it, something is missing in Migrate as this look like should be handled through a destination field.

joseph.olstad’s picture

Investigated this issue and try to help others with the following notes:

Noticed differences in latest dev code related to patch comment#5 on #1537076: Handle language subfield on a value-by-value basis however according to my tests so far the current dec 10 dev build of migrate seems to work fine without patches in this use case.

Lessons learned:

I noticed that when following steps outlined in #1537076: Handle language subfield on a value-by-value basis

fields() used in MigrateSQLMap when adding language array in prepare or prepareRow cannot be used as parameters, instead use the other language's field.

For example when assigning an array of DepartmentEN and DepartmentFR in preparerow to DepartmentEN, the this field DepartmentEN can no longer be used as a parameter "fields()" to MigrateSQLMap, however DepartmentFR can, so in this case use DepartmentFR as a parameter rather than DepartmentEN. If you choose the DepartmentEN field you'll get an error message something like: "Column count doesn't match value count at row". However in this case when using the DepartmentFR field it works because MigrateSQLMap expects field(s) and not array(s) of field(s) as parameter(s).

<?php
class MyContentMigration extends Migration {
  public function __construct($arguments) {
    // ...
    $this->map = new MigrateSQLMap($this->machineName,
        array(
           'Project_Code' => array('type' => 'varchar',
                           'length' => 255,
                           'not null' => TRUE,
                           'description' => 'Project Code/ Code du Projet',
                          ),
          'DepartmentFR' => array('type' => 'varchar',
                           'length' => 255,
                           'not null' => TRUE,
                           'description' => 'Ministère responsable',
                          ),
        ),
        MigrateDestinationNode::getKeySchema()
      );
    // Create a MigrateSource object, which manages retrieving the input data.
    $this->source = new MigrateSourceCSV($arguments['source_file'], $this->csvcolumns(), array(), $this->fields());
    // ...
    $this->addFieldMapping('body', 'DepartmentEN');
    $this->addFieldMapping('body:language')->defaultValue(array('en', 'fr'));
    // ...
  } //end public function __construct

// ...
  public function prepareRow($row) {
   $row->language = array('en', 'fr');
   $row->DepartmentEN = array($row->DepartmentEN, $row->DepartmentFR);
   // https://drupal.org/comment/5883324#comment-5883324
  }
// ...
?>

I have been able to get this method to work.

Reminder

"To get your field translations to work properly with your migrate module"

  1. make sure your content type has field translations enabled
  2. you also have to enable the "translations" in:
<?php
// ...
// stuff
// ...
public function prepare(&$entity, $row) {

   $entity->language='en';//set the original language , doesn't matter which language but has to be consistent
   $entity->translations = (object) array(
                    'original' => 'en',
                    'data' => array(
                            'en' => array(
                                    'entity_type' => 'node',
                                    'entity_id' => $entity->nid,
                                    'language' => 'en',
                                    'source' => '',
                                    'uid' => '0',
                                    'status' => '1',
                                    'translate' => '0',
                            ),
                            'fr' => array(
                                    'entity_type' => 'node',
                                    'entity_id' => $entity->nid,
                                    'language' => 'fr',
                                    'source' => 'en',
                                    'uid' => '1',
                                    'status' => '1',
                                    'translate' => '0',

                            ),
                    )
            );
}
//...
//more stuff
//...
?>
joseph.olstad’s picture

Assigned: Unassigned » joseph.olstad
Issue summary: View changes
mikeryan’s picture

Category: Support request » Feature request
Status: Active » Closed (duplicate)

The Migrate module itself does not provide support for contributed modules - migration support for other modules belongs in the contributed module itself. There is an existing issue in the Entity Translation queue to add migration support: #929402: Add support for migrate module

mikeryan’s picture

SandraVdv’s picture

If you do it in the prepareRow or only in the prepare, does he update the entities if you run the migrations and add the entity_translation code afterwards? Because it seems to me that none of the values have changed in the source, so he doesn't do anything? Or not?
What if a language disappears?

I found this example:

function prepare($entity, stdClass $row){

    $entity->language = 'el';       
    $entity->title_field['el'][0]['value'] = $row->name;
    $entity->title_field['en'][0]['value'] = $row->name_en;
    $entity->translations = (object) array(
                    'original' => 'el',
                    'data' => array(
                            'el' => array(
                                    'entity_type' => 'node',
                                    'entity_id' => $entity->nid,
                                    'language' => 'el',
                                    'source' => '',
                                    'uid' => '0',
                                    'status' => '1',
                                    'translate' => '0',

                            ),
                            'en' => array(
                                    'entity_type' => 'node',
                                    'entity_id' => $entity->nid,
                                    'language' => 'en',
                                    'source' => 'el',
                                    'uid' => '1',
                                    'status' => '1',
                                    'translate' => '0',

                            ),
                    )
            );
 }

But what happens if the name_en is empty all of a sudden? The translation is not removed I think?

titouille’s picture

My two cents :

above methods to add entity_translation informations doesn't work. But with this method translations are added into entity_translation table :

  public function prepare(&$entity, $row) {
    
    $handler = entity_translation_get_handler($entity->type, $entity);
    $translation = array(
      'translate' => 0,
      'status' => 1,
      'language' => 'fr',
      'source' => 'en',
    );
    $handler->setTranslation($translation, $entity);
  }

In the full version, i have a class inherited with a $add_translation protected variable, and I set the flag to TRUE or FALSE in the prepareRow method to know if I must add the translation set for my content in the prepare method.

Hope this help :-)

jeff.hartman’s picture

I'm dealing with a similar issue with term entities and I'm not sure what to do.

My source vocabulary is set to Localize. The term and fields are all set to 'und' (nothing has actually been translated so it's fine to use the name and description properties from the taxonomy_term_data table). (Oddly I have another vocabulary where all terms and fields are set to 'en', and I get the same result described below.)

My destination, however, is using Field Translation (available in the late May release of the Entity Translation module). In my vocabulary the name and the description properties have been replaced with fields (i.e. name_field and destination_field).

I need to migrate this vocabulary and have the:

  • term row in taxonomy_term_data set to 'en' (i.e. from 'und' or 'en' in source to 'en' in destination)
  • name in field_data_name_field set to 'en' (i.e. from 'und' or 'en' in source to 'en' in destination)
  • description in field_data_description_field set to 'en' (i.e. from 'und' or 'en' in source to 'en' in destination)
  • other untranslated fields on the term set to 'und'

To set the term to 'en', it's not a big deal:

public function prepare($entity, stdClass $row) {
  $entity->language = 'en';
}

I've tried to set the name_field and description_field values similarly (see below), but I continue to get rows for 'und' as well.

  public function prepare($entity, stdClass $row) {
    $entity->language = 'en';

    $entity->name_field['en'][0]['value'] = $row->name;

    $entity->description_field['en'][0]['value'] = $row->description; // this could come from description for description_field. Same result.
    $entity->description_field['en'][0]['format'] = 'panopoly_wysiwyg_text';
  }

Any help would be most appreciated.