From 81543e175507a6e558e0837324f9dcb5cff2d63a Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Tue, 11 Jun 2019 17:13:02 +0300
Subject: [PATCH] =?UTF-8?q?Issue=20#2979966=20by=20quietone,=20PieterDC,?=
 =?UTF-8?q?=20masipila,=20heddn,=20G=C3=A1bor=20Hojtsy:=20Migrate=20D7=20i?=
 =?UTF-8?q?18n=20taxonomy=20term=20language?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../migrations/d7_taxonomy_term_language.yml  |  45 ++++++
 .../src/Plugin/migrate/source/d7/Term.php     |   9 ++
 .../d7/MigrateTaxonomyTermLanguageTest.php    | 136 ++++++++++++++++++
 3 files changed, 190 insertions(+)
 create mode 100644 core/modules/taxonomy/migrations/d7_taxonomy_term_language.yml
 create mode 100644 core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermLanguageTest.php

diff --git a/core/modules/taxonomy/migrations/d7_taxonomy_term_language.yml b/core/modules/taxonomy/migrations/d7_taxonomy_term_language.yml
new file mode 100644
index 000000000000..277e1660016b
--- /dev/null
+++ b/core/modules/taxonomy/migrations/d7_taxonomy_term_language.yml
@@ -0,0 +1,45 @@
+id: d7_taxonomy_term_language
+label: Taxonomy term language
+migration_tags:
+  - Drupal 7
+  - Content
+  - Multilingual
+deriver: Drupal\taxonomy\Plugin\migrate\D7TaxonomyTermDeriver
+source:
+  plugin: d7_taxonomy_term
+process:
+  # If you are using this file to build a custom migration consider removing
+  # the tid field to allow incremental migrations.
+  tid: tid
+  vid:
+    plugin: migration_lookup
+    migration: d7_taxonomy_vocabulary
+    source: vid
+  name: name
+  'description/value': description
+  'description/format': format
+  weight: weight
+  # Only attempt to stub real (non-zero) parents.
+  parent_id:
+    -
+      plugin: skip_on_empty
+      method: process
+      source: parent
+    -
+      plugin: migration_lookup
+      migration: d7_taxonomy_term
+  parent:
+    plugin: default_value
+    default_value: 0
+    source: '@parent_id'
+  forum_container: is_container
+  changed: timestamp
+  langcode: language
+destination:
+  plugin: entity:taxonomy_term
+  destination_module: content_translation
+migration_dependencies:
+  required:
+    - d7_taxonomy_vocabulary
+  optional:
+    - d7_field_instance
diff --git a/core/modules/taxonomy/src/Plugin/migrate/source/d7/Term.php b/core/modules/taxonomy/src/Plugin/migrate/source/d7/Term.php
index 18d94ff5d092..72c5fb9ab703 100644
--- a/core/modules/taxonomy/src/Plugin/migrate/source/d7/Term.php
+++ b/core/modules/taxonomy/src/Plugin/migrate/source/d7/Term.php
@@ -32,6 +32,9 @@ public function query() {
       $query->condition('tv.machine_name', (array) $this->configuration['bundle'], 'IN');
     }
 
+    if ($this->getDatabase()->schema()->fieldExists('taxonomy_vocabulary', 'i18n_mode')) {
+      $query->addField('tv', 'i18n_mode');
+    }
     return $query;
   }
 
@@ -68,6 +71,12 @@ public function prepareRow(Row $row) {
     $entity_translatable = $this->isEntityTranslatable('taxonomy_term') && in_array($vocabulary, $translatable_vocabularies, TRUE);
     $source_language = $this->getEntityTranslationSourceLanguage('taxonomy_term', $tid);
     $language = $entity_translatable && $source_language ? $source_language : $default_language['language'];
+
+    // If this is an i18n translation.
+    $i18n_mode = $row->get('i18n_mode');
+    if ($i18n_mode) {
+      $language = $row->get('language');
+    }
     $row->setSourceProperty('language', $language);
 
     // Get Field API field values.
diff --git a/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermLanguageTest.php b/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermLanguageTest.php
new file mode 100644
index 000000000000..49436ce8a23f
--- /dev/null
+++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d7/MigrateTaxonomyTermLanguageTest.php
@@ -0,0 +1,136 @@
+<?php
+
+namespace Drupal\Tests\taxonomy\Kernel\Migrate\d7;
+
+use Drupal\taxonomy\Entity\Term;
+use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
+use Drupal\taxonomy\TermInterface;
+
+/**
+ * Test migration of translated taxonomy terms.
+ *
+ * @group migrate_drupal_7
+ */
+class MigrateTaxonomyTermLanguageTest extends MigrateDrupal7TestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'comment',
+    'datetime',
+    'image',
+    'language',
+    'link',
+    'menu_ui',
+    // Required for translation migrations.
+    'migrate_drupal_multilingual',
+    'node',
+    'taxonomy',
+    'telephone',
+    'text',
+  ];
+
+  /**
+   * The cached taxonomy tree items, keyed by vid and tid.
+   *
+   * @var array
+   */
+  protected $treeData = [];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->installEntitySchema('comment');
+    $this->installEntitySchema('file');
+
+    $this->migrateTaxonomyTerms();
+    $this->executeMigrations([
+      'language',
+      'd7_user_role',
+      'd7_user',
+      'd7_taxonomy_term_language',
+    ]);
+  }
+
+  /**
+   * Validate a migrated term contains the expected values.
+   *
+   * @param int $id
+   *   Entity ID to load and check.
+   * @param string $expected_language
+   *   The language code for this term.
+   * @param string $expected_label
+   *   The label the migrated entity should have.
+   * @param string $expected_vid
+   *   The parent vocabulary the migrated entity should have.
+   * @param string $expected_description
+   *   The description the migrated entity should have.
+   * @param string $expected_format
+   *   The format the migrated entity should have.
+   * @param int $expected_weight
+   *   The weight the migrated entity should have.
+   * @param array $expected_parents
+   *   The parent terms the migrated entity should have.
+   * @param int $expected_field_integer_value
+   *   The value the migrated entity field should have.
+   * @param int $expected_term_reference_tid
+   *   The term reference ID the migrated entity field should have.
+   */
+  protected function assertEntity($id, $expected_language, $expected_label, $expected_vid, $expected_description = '', $expected_format = NULL, $expected_weight = 0, array $expected_parents = [], $expected_field_integer_value = NULL, $expected_term_reference_tid = NULL) {
+    /** @var \Drupal\taxonomy\TermInterface $entity */
+    $entity = Term::load($id);
+    $this->assertInstanceOf(TermInterface::class, $entity);
+    $this->assertSame($expected_language, $entity->language()->getId());
+    $this->assertSame($expected_label, $entity->label());
+    $this->assertSame($expected_vid, $entity->bundle());
+    $this->assertSame($expected_description, $entity->getDescription());
+    $this->assertSame($expected_format, $entity->getFormat());
+    $this->assertSame($expected_weight, $entity->getWeight());
+    $this->assertHierarchy($expected_vid, $id, $expected_parents);
+  }
+
+  /**
+   * Assert that a term is present in the tree storage, with the right parents.
+   *
+   * @param string $vid
+   *   Vocabulary ID.
+   * @param int $tid
+   *   ID of the term to check.
+   * @param array $parent_ids
+   *   The expected parent term IDs.
+   */
+  protected function assertHierarchy($vid, $tid, array $parent_ids) {
+    if (!isset($this->treeData[$vid])) {
+      $tree = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid);
+      $this->treeData[$vid] = [];
+      foreach ($tree as $item) {
+        $this->treeData[$vid][$item->tid] = $item;
+      }
+    }
+
+    $this->assertArrayHasKey($tid, $this->treeData[$vid], "Term $tid exists in taxonomy tree");
+    $term = $this->treeData[$vid][$tid];
+    // PostgreSQL, MySQL and SQLite may not return the parent terms in the same
+    // order so sort before testing.
+    sort($parent_ids);
+    $actual_terms = array_filter($term->parents);
+    sort($actual_terms);
+    $this->assertEquals($parent_ids, $actual_terms, "Term $tid has correct parents in taxonomy tree");
+  }
+
+  /**
+   * Tests the Drupal 7 i18n taxonomy term to Drupal 8 migration.
+   */
+  public function testTranslatedTaxonomyTerms() {
+    $this->assertEntity(19, 'und', 'Jupiter Station', 'vocablocalized', 'Holographic research.', 'filtered_html', '0', []);
+    $this->assertEntity(20, 'und', 'DS9', 'vocablocalized', 'Terok Nor', 'filtered_html', '0', []);
+    $this->assertEntity(21, 'en', 'High council', 'vocabtranslate', NULL, NULL, '0', []);
+    $this->assertEntity(22, 'fr', 'fr - High council', 'vocabtranslate', NULL, NULL, '0', []);
+    $this->assertEntity(23, 'is', 'is - High council', 'vocabtranslate', NULL, NULL, '0', []);
+    $this->assertEntity(24, 'fr', 'FR - Crewman', 'vocabfixed', NULL, NULL, '0', []);
+  }
+
+}
-- 
GitLab