Commit 8c457c9d authored by Gábor Hojtsy's avatar Gábor Hojtsy

Issue #2886609 by quietone, Jo Fitzgerald, jhodgdon, masipila, heddn, Gábor...

Issue #2886609 by quietone, Jo Fitzgerald, jhodgdon, masipila, heddn, Gábor Hojtsy, mikeryan: Migrate D6 i18n loacalized translations of taxonomy terms
parent 284b4202
id: d6_taxonomy_term_localized_translation
label: Taxonomy localized term translations
migration_tags:
- Drupal 6
- Content
source:
plugin: d6_term_localized_translation
translations: true
process:
# If you are using this file to build a custom migration consider removing
# the tid field to allow incremental migrations.
tid: tid
langcode: language
vid:
plugin: migration
migration: d6_taxonomy_vocabulary
source: vid
name:
-
plugin: callback
source:
- name_translated
- name
callable: array_filter
-
plugin: callback
callable: current
description:
-
plugin: callback
source:
- description_translated
- description
callable: array_filter
-
plugin: callback
callable: current
destination:
plugin: entity:taxonomy_term
translations: true
migration_dependencies:
required:
- d6_taxonomy_term
......@@ -9856,6 +9856,30 @@
'objectindex' => '0',
'format' => '0',
))
->values(array(
'lid' => '1679',
'objectid' => '14',
'type' => 'term',
'property' => 'name',
'objectindex' => '14',
'format' => '0',
))
->values(array(
'lid' => '1680',
'objectid' => '15',
'type' => 'term',
'property' => 'name',
'objectindex' => '15',
'format' => '0',
))
->values(array(
'lid' => '1681',
'objectid' => '14',
'type' => 'term',
'property' => 'description',
'objectindex' => '14',
'format' => '0',
))
->execute();
$connection->schema()->createTable('i18n_variable', array(
......@@ -22357,6 +22381,27 @@
'source' => 'I really, really, really love migrating',
'version' => '1',
))
->values(array(
'lid' => '1679',
'location' => 'term:14:name',
'textgroup' => 'taxonomy',
'source' => 'Talos IV',
'version' => '1',
))
->values(array(
'lid' => '1680',
'location' => 'term:15:name',
'textgroup' => 'taxonomy',
'source' => 'Vulcan',
'version' => '1',
))
->values(array(
'lid' => '1681',
'location' => 'term:14:description',
'textgroup' => 'taxonomy',
'source' => 'The home of Captain Christopher Pike.',
'version' => '1',
))
->execute();
$connection->schema()->createTable('locales_target', array(
......@@ -27409,6 +27454,30 @@
'plural' => '0',
'i18n_status' => '0',
))
->values(array(
'lid' => '1672',
'translation' => 'fr - Type',
'language' => 'fr',
'plid' => '0',
'plural' => '0',
'i18n_status' => '0',
))
->values(array(
'lid' => '1679',
'translation' => 'fr - Talos IV',
'language' => 'fr',
'plid' => '0',
'plural' => '0',
'i18n_status' => '0',
))
->values(array(
'lid' => '1681',
'translation' => 'fr - The home of Captain Christopher Pike.',
'language' => 'fr',
'plid' => '0',
'plural' => '0',
'i18n_status' => '0',
))
->values(array(
'lid' => '66',
'translation' => 'zu - CCK - Aucune Intégration aux Vues',
......@@ -27505,6 +27574,30 @@
'plural' => '0',
'i18n_status' => '0',
))
->values(array(
'lid' => '1672',
'translation' => 'zu - Type',
'language' => 'zu',
'plid' => '0',
'plural' => '0',
'i18n_status' => '0',
))
->values(array(
'lid' => '1680',
'translation' => 'zu - Vulcan',
'language' => 'zu',
'plid' => '0',
'plural' => '0',
'i18n_status' => '0',
))
->values(array(
'lid' => '1681',
'translation' => 'zu - The home of Captain Christopher Pike.',
'language' => 'zu',
'plid' => '0',
'plural' => '0',
'i18n_status' => '0',
))
->execute();
$connection->schema()->createTable('menu_custom', array(
......@@ -40593,6 +40686,28 @@
'weight' => '0',
'file' => 'sites/all/modules/i18n/i18n.admin.inc',
))
->values(array(
'path' => 'admin/settings/language/i18n/variables',
'load_functions' => '',
'to_arg_functions' => '',
'access_callback' => 'user_access',
'access_arguments' => 'a:1:{i:0;s:29:"administer site configuration";}',
'page_callback' => 'drupal_get_form',
'page_arguments' => 'a:1:{i:0;s:25:"i18n_admin_variables_form";}',
'fit' => '31',
'number_parts' => '5',
'tab_parent' => 'admin/settings/language/i18n',
'tab_root' => 'admin/settings/language',
'title' => 'Variables',
'title_callback' => 't',
'title_arguments' => '',
'type' => '128',
'block_callback' => '',
'description' => 'Multilingual variables.',
'position' => '',
'weight' => '0',
'file' => 'sites/all/modules/i18n/i18n.admin.inc',
))
->values(array(
'path' => 'admin/settings/language/overview',
'load_functions' => '',
......@@ -46668,6 +46783,69 @@
'language' => '',
'trid' => '0',
))
->values(array(
'tid' => '9',
'vid' => '3',
'name' => 'fr - term 4 of vocabulary 3',
'description' => '',
'weight' => '0',
'language' => 'fr',
'trid' => '1',
))
->values(array(
'tid' => '10',
'vid' => '3',
'name' => 'zu - term 4 of vocabulary 3',
'description' => '',
'weight' => '0',
'language' => 'zu',
'trid' => '1',
))
->values(array(
'tid' => '11',
'vid' => '3',
'name' => 'term 7 of vocabulary 3',
'description' => '',
'weight' => '0',
'language' => 'en',
'trid' => '2',
))
->values(array(
'tid' => '12',
'vid' => '3',
'name' => 'fr - term 7 of vocabulary 3',
'description' => '',
'weight' => '0',
'language' => 'fr',
'trid' => '2',
))
->values(array(
'tid' => '13',
'vid' => '3',
'name' => 'zu - term 7 of vocabulary 3',
'description' => '',
'weight' => '0',
'language' => 'zu',
'trid' => '2',
))
->values(array(
'tid' => '14',
'vid' => '5',
'name' => 'Talos IV',
'description' => 'The home of Captain Christopher Pike.',
'weight' => '0',
'language' => '',
'trid' => '0',
))
->values(array(
'tid' => '15',
'vid' => '5',
'name' => 'Vulcan',
'description' => '',
'weight' => '0',
'language' => '',
'trid' => '0',
))
->execute();
$connection->schema()->createTable('term_hierarchy', array(
......@@ -46719,6 +46897,34 @@
'tid' => '8',
'parent' => '0',
))
->values(array(
'tid' => '9',
'parent' => '0',
))
->values(array(
'tid' => '10',
'parent' => '0',
))
->values(array(
'tid' => '11',
'parent' => '0',
))
->values(array(
'tid' => '12',
'parent' => '0',
))
->values(array(
'tid' => '13',
'parent' => '0',
))
->values(array(
'tid' => '14',
'parent' => '0',
))
->values(array(
'tid' => '15',
'parent' => '0',
))
->values(array(
'tid' => '3',
'parent' => '2',
......@@ -47247,8 +47453,8 @@
'signature' => '',
'signature_format' => '0',
'created' => '0',
'access' => '1494966478',
'login' => '1494966280',
'access' => '1521962400',
'login' => '1521961881',
'status' => '1',
'timezone' => NULL,
'language' => '',
......@@ -48317,7 +48523,7 @@
))
->values(array(
'name' => 'i18ntaxonomy_vocabulary',
'value' => 'a:2:{i:1;s:1:"3";i:2;s:1:"2";}',
'value' => 'a:4:{i:1;s:1:"3";i:2;s:1:"2";i:3;s:1:"3";i:5;s:1:"1";}',
))
->values(array(
'name' => 'i18n_lock_node_article',
......@@ -81,7 +81,7 @@ protected function getEntityCounts() {
'shortcut_set' => 1,
'action' => 23,
'menu' => 8,
'taxonomy_term' => 8,
'taxonomy_term' => 15,
'taxonomy_vocabulary' => 7,
'tour' => 4,
'user' => 7,
......@@ -109,7 +109,7 @@ protected function getEntityCountsIncremental() {
$counts['file'] = 9;
$counts['menu_link_content'] = 11;
$counts['node'] = 18;
$counts['taxonomy_term'] = 9;
$counts['taxonomy_term'] = 16;
$counts['user'] = 8;
$counts['view'] = 16;
return $counts;
......
<?php
namespace Drupal\taxonomy\Plugin\migrate\source\d6;
use Drupal\migrate\Row;
/**
* Gets i18n taxonomy terms from source database.
*
* @MigrateSource(
* id = "d6_term_localized_translation",
* source_module = "i18ntaxonomy"
* )
*/
class TermLocalizedTranslation extends Term {
/**
* {@inheritdoc}
*/
public function query() {
// Ideally, the query would return rows for each language for each taxonomy
// term with the translations for both the name and description or just the
// name translation or just the description translation. That query quickly
// became complex and would be difficult to maintain.
// Therefore, build a query based on i18nstrings table where each row has
// the translation for only one property, either name or description. The
// method prepareRow() is then used to obtain the translation for the other
// property.
$query = parent::query();
$query->addField('td', 'language', 'td.language');
// Add in the property, which is either name or description.
$query->leftJoin('i18n_strings', 'i18n', 'td.tid = i18n.objectid');
$query->isNotNull('i18n.lid');
$query->addField('i18n', 'lid');
$query->addField('i18n', 'property');
// Add in the translation for the property.
$query->innerJoin('locales_target', 'lt', 'i18n.lid = lt.lid');
$query->addField('lt', 'language', 'lt.language');
$query->addField('lt', 'translation');
return $query;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
$language = $row->getSourceProperty('ltlanguage');
$row->setSourceProperty('language', $language);
$tid = $row->getSourceProperty('tid');
// If this row has been migrated it is a duplicate then skip it.
if ($this->idMap->lookupDestinationIds(['tid' => $tid, 'language' => $language])) {
return FALSE;
}
// Save the translation for this property.
$property = $row->getSourceProperty('property');
$row->setSourceProperty($property . '_translated', $row->getSourceProperty('translation'));
// Get the translation, if one exists, for the property not already in the
// row.
$other_property = ($property == 'name') ? 'description' : 'name';
$query = $this->select('i18n_strings', 'i18n')
->fields('i18n', ['lid'])
->condition('i18n.property', $other_property)
->condition('i18n.objectid', $tid);
$query->leftJoin('locales_target', 'lt', 'i18n.lid = lt.lid');
$query->condition('lt.language', $language);
$query->addField('lt', 'translation');
$results = $query->execute()->fetchAssoc();
$row->setSourceProperty($other_property . '_translated', $results['translation']);
parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function fields() {
$fields = [
'language' => $this->t('Language for this term.'),
'name_translated' => $this->t('Term name translation.'),
'description_translated' => $this->t('Term description translation.'),
];
return parent::fields() + $fields;
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['language']['type'] = 'string';
$ids['language']['alias'] = 'lt';
return parent::getIds() + $ids;
}
}
<?php
namespace Drupal\Tests\taxonomy\Kernel\Migrate\d6;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\TermInterface;
/**
* Tests migration of localized translated taxonomy terms.
*
* @group migrate_drupal_6
*/
class MigrateTermLocalizedTranslationTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'content_translation',
'language',
'menu_ui',
'node',
'taxonomy',
];
/**
* The cached taxonomy tree items, keyed by vid and tid.
*
* @var array
*/
protected $treeData = [];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('taxonomy_term');
$this->installConfig(static::$modules);
$this->executeMigrations([
'language',
'd6_node_type',
'd6_field',
'd6_taxonomy_vocabulary',
'd6_field_instance',
'd6_taxonomy_term',
'd6_taxonomy_term_localized_translation',
]);
}
/**
* Validates 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);
}
/**
* Asserts 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];
$this->assertEquals($parent_ids, array_filter($term->parents), "Term $tid has correct parents in taxonomy tree");
}
/**
* Tests the Drupal 6 i18n localized taxonomy term to Drupal 8 migration.
*/
public function testTranslatedLocalizedTaxonomyTerms() {
$this->assertEntity(14, 'en', 'Talos IV', 'vocabulary_name_much_longer_than', 'The home of Captain Christopher Pike.', NULL, '0', []);
$this->assertEntity(15, 'en', 'Vulcan', 'vocabulary_name_much_longer_than', NULL, NULL, '0', []);
/** @var \Drupal\taxonomy\TermInterface $entity */
$entity = Term::load(14);
$this->assertTrue($entity->hasTranslation('fr'));
$translation = $entity->getTranslation('fr');
$this->assertSame('fr - Talos IV', $translation->label());
$this->assertSame('fr - The home of Captain Christopher Pike.', $translation->getDescription());
$this->assertTrue($entity->hasTranslation('zu'));
$translation = $entity->getTranslation('zu');
$this->assertSame('Talos IV', $translation->label());
$this->assertSame('zu - The home of Captain Christopher Pike.', $translation->getDescription());
$entity = Term::load(15);
$this->assertFalse($entity->hasTranslation('fr'));
$this->assertTrue($entity->hasTranslation('zu'));
$translation = $entity->getTranslation('zu');
$this->assertSame('zu - Vulcan', $translation->label());
$this->assertSame('', $translation->getDescription());
}
}
<?php
namespace Drupal\Tests\taxonomy\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests D6 i18n term localized source plugin.
*
* @covers \Drupal\taxonomy\Plugin\migrate\source\d6\TermLocalizedTranslation
* @group taxonomy
*/
class TermLocalizedTranslationTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['taxonomy', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['term_data'] = [
[
'tid' => 1,
'vid' => 5,
'name' => 'name value 1',
'description' => 'description value 1',
'weight' => 0,
'language' => NULL,
],
[
'tid' => 2,
'vid' => 6,
'name' => 'name value 2',
'description' => 'description value 2',
'weight' => 0,
'language' => NULL,
],
[
'tid' => 3,
'vid' => 6,
'name' => 'name value 3',
'description' => 'description value 3',
'weight' => 0,
'language' => NULL,
],
[
'tid' => 4,
'vid' => 5,
'name' => 'name value 4',
'description' => 'description value 4',
'weight' => 1,
'language' => NULL,
],
];
$tests[0]['source_data']['term_hierarchy'] = [
[
'tid' => 1,
'parent' => 0,
],
[
'tid' => 2,
'parent' => 0,
],
[
'tid' => 3,
'parent' => 0,
],
[
'tid' => 4,
'parent' => 1,
],
];
$tests[0]['source_data']['i18n_strings'] = [
[
'lid' => 6,
'objectid' => 1,
'type' => 'term',
'property' => 'name',
'objectindex' => '1',
'format' => 0,
],
[
'lid' => 7,
'objectid' => 1,
'type' => 'term',
'property' => 'description',
'objectindex' => '1',
'format' => 0,
],
[
'lid' => 8,
'objectid' => 3,
'type' => 'term',
'property' => 'name',
'objectindex' => '3',
'format' => 0,
],
];
$tests[0]['source_data']['locales_target'] = [
[
'lid' => 6,
'language' => 'fr',
'translation' => 'fr - name value 1 translation',
'plid' => 0,
'plural' => 0,
'i18n_status' => 0,
],
[
'lid' => 7,
'language' => 'fr',
'translation' => 'fr - description value 1 translation',
'plid' => 0,
'plural' => 0,
'i18n_status' => 0,
],
[
'lid' => 8,
'language' => 'zu',
'translation' => 'zu - description value 2 translation',
'plid' => 0,
'plural' => 0,
'i18n_status' => 0,
],
];
<