diff --git a/core/modules/config_translation/migrations/d7_menu_translation.yml b/core/modules/config_translation/migrations/d7_menu_translation.yml
new file mode 100644
index 0000000..d22fedc
--- /dev/null
+++ b/core/modules/config_translation/migrations/d7_menu_translation.yml
@@ -0,0 +1,29 @@
+id: d7_menu_translation
+label: Menu translation
+ - Configuration
+ - Multilingual
+source:
+ plugin: d7_menu_translation
+process:
+ id:
+ -
+ plugin: migration_lookup
+ migration: d7_menu
+ source: menu_name
+ -
+ plugin: skip_on_empty
+ method: row
+ langcode: language
+ property:
+ plugin: static_map
+ source: property
+ map:
+ title: label
+ description: description
+ translation: translation
+destination:
+ plugin: entity:menu
+ destination_module: config_translation
+migration_dependencies:
+ required:
+ - d7_menu
diff --git a/core/modules/config_translation/migrations/state/config_translation.migrate_drupal.yml b/core/modules/config_translation/migrations/state/config_translation.migrate_drupal.yml
index 5c7b5fd..5255213 100644
--- a/core/modules/config_translation/migrations/state/config_translation.migrate_drupal.yml
+++ b/core/modules/config_translation/migrations/state/config_translation.migrate_drupal.yml
@@ -4,6 +4,7 @@ finished:
7:
i18n_variable: config_translation
i18n_taxonomy: config_translation
+ i18n_menu: config_translation
not_finished:
6:
# language content comment settings.
diff --git a/core/modules/config_translation/src/Plugin/migrate/source/d7/MenuTranslation.php b/core/modules/config_translation/src/Plugin/migrate/source/d7/MenuTranslation.php
new file mode 100644
index 0000000..d7c83c2
--- /dev/null
+++ b/core/modules/config_translation/src/Plugin/migrate/source/d7/MenuTranslation.php
@@ -0,0 +1,89 @@
+select('menu_custom', 'm')
+ ->fields('m')
+ ->fields('i18n', [
+ 'lid',
+ 'textgroup',
+ 'context',
+ 'objectid',
+ 'type',
+ 'property',
+ 'objectindex',
+ 'format',
+ ])
+ ->fields('lt', [
+ 'lid',
+ 'translation',
+ 'language',
+ 'plid',
+ 'plural',
+ 'i18n_status',
+ ])
+ ->condition('i18n.textgroup', 'menu')
+ ->isNotNull('lt.lid');
+
+ $query->addField('m', 'language', 'm_language');
+ $query->leftJoin('i18n_string', 'i18n', 'i18n.objectid = m.menu_name');
+ $query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
+
+ return $query;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function fields() {
+ return [
+ 'menu_name' => $this->t('The menu name'),
+ 'title' => $this->t('The menu title'),
+ 'description' => $this->t('A description of the menu'),
+ 'title_translated' => $this->t('Menu title translation.'),
+ 'description_translated' => $this->t('Menu description translation.'),
+ 'i18n_mode' => $this->t('Multilingual mode'),
+ 'lid' => $this->t('Language string ID'),
+ 'textgroup' => $this->t('A module defined group of translations'),
+ 'context' => $this->t('Full string ID for quick search: type:objectid:property.'),
+ 'objectid' => $this->t('Object ID'),
+ 'type' => $this->t('Object type for this string'),
+ 'property' => $this->t('Object property for this string'),
+ 'objectindex' => $this->t('Integer value of Object ID'),
+ 'format' => $this->t('The {filter_format}.format of the string'),
+ 'translation' => $this->t('Translation'),
+ 'language' => $this->t('Language code'),
+ 'plid' => $this->t('Parent lid'),
+ 'plural' => $this->t('Plural index number'),
+ 'i18n_status' => $this->t('Translation needs update'),
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getIds() {
+ $ids['menu_name']['type'] = 'string';
+ $ids['language']['type'] = 'string';
+ $ids['language']['alias'] = 'lt';
+ $ids['property']['type'] = 'string';
+ return $ids;
+ }
+
+}
diff --git a/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateMenuTranslationTest.php b/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateMenuTranslationTest.php
new file mode 100644
index 0000000..1fcb59e
--- /dev/null
+++ b/core/modules/config_translation/tests/src/Kernel/Migrate/d7/MigrateMenuTranslationTest.php
@@ -0,0 +1,67 @@
+installSchema('locale',
+ ['locales_source', 'locales_target', 'locales_location']);
+ $this->executeMigrations([
+ 'language',
+ 'd7_menu',
+ 'd7_menu_translation',
+ ]);
+ }
+
+ /**
+ * Tests migration of menu translations.
+ */
+ public function testMenuTranslation() {
+ $language_manager = \Drupal::service('language_manager');
+
+ $config_translation = $language_manager->getLanguageConfigOverride('is', 'system.menu.main');
+ $this->assertSame('is - Main menu', $config_translation->get('label'));
+ $this->assertSame('is - Main menu description', $config_translation->get('description'));
+
+ $config_translation = $language_manager->getLanguageConfigOverride('fr', 'system.menu.main');
+ $this->assertSame('fr - Main menu', $config_translation->get('label'));
+ $this->assertSame('fr - Main menu description', $config_translation->get('description'));
+
+ // Translate and localize menu.
+ $config_translation = $language_manager->getLanguageConfigOverride('fr', 'system.menu.menu-test-menu');
+ $this->assertSame('fr - Test menu description', $config_translation->get('description'));
+
+ // No translations for fixed language menu.
+ $config_translation = $language_manager->getLanguageConfigOverride('fr', 'menu-fixedlang');
+ $this->assertNull($config_translation->get('description'));
+ $this->assertNull($config_translation->get('description'));
+ $config_translation = $language_manager->getLanguageConfigOverride('is', 'menu-fixedlang');
+ $this->assertNull($config_translation->get('description'));
+ $this->assertNull($config_translation->get('description'));
+ }
+
+}
diff --git a/core/modules/config_translation/tests/src/Kernel/Plugin/migrate/source/d7/MenuTranslationTest.php b/core/modules/config_translation/tests/src/Kernel/Plugin/migrate/source/d7/MenuTranslationTest.php
new file mode 100644
index 0000000..d628e34
--- /dev/null
+++ b/core/modules/config_translation/tests/src/Kernel/Plugin/migrate/source/d7/MenuTranslationTest.php
@@ -0,0 +1,102 @@
+ 'navigation',
+ 'title' => 'Navigation',
+ 'description' => 'Navigation description',
+ 'language' => 'und',
+ 'i18n_mode' => 0,
+ ],
+ [
+ 'menu_name' => 'menu-name-2',
+ 'title' => 'menu custom value 2',
+ 'description' => 'menu custom description value 2',
+ 'language' => 'und',
+ 'i18n_mode' => 0,
+ ],
+ ];
+ $tests[0]['source_data']['i18n_string'] = [
+ [
+ 'lid' => 1,
+ 'textgroup' => 'menu',
+ 'context' => ' menu:navigation:description',
+ 'objectid' => 'navigation',
+ 'type' => 'menu',
+ 'property' => 'description',
+ 'objectindex' => 0,
+ 'format' => '',
+ ],
+ [
+ 'lid' => 2,
+ 'textgroup' => 'menu',
+ 'context' => ' menu:navigation:title',
+ 'objectid' => 'navigation',
+ 'type' => 'menu',
+ 'property' => 'title',
+ 'objectindex' => 0,
+ 'format' => '',
+ ],
+ ];
+ $tests[0]['source_data']['locales_target'] = [
+ [
+ 'lid' => 1,
+ 'translation' => 'navigation description translation',
+ 'language' => 'fr',
+ 'plid' => 0,
+ 'plural' => 0,
+ 'i18n_status' => 0,
+ ],
+ [
+ 'lid' => 2,
+ 'translation' => 'navigation translation',
+ 'language' => 'fr',
+ 'plid' => 0,
+ 'plural' => 0,
+ 'i18n_status' => 0,
+ ],
+ ];
+ $tests[0]['expected_results'] = [
+ [
+ 'menu_name' => 'navigation',
+ 'type' => 'menu',
+ 'property' => 'description',
+ 'translation' => 'navigation description translation',
+ 'language' => 'fr',
+ 'objectid' => 'navigation',
+ ],
+ [
+ 'menu_name' => 'navigation',
+ 'type' => 'menu',
+ 'property' => 'title',
+ 'translation' => 'navigation translation',
+ 'language' => 'fr',
+ 'objectid' => 'navigation',
+ ],
+ ];
+ return $tests;
+ }
+
+}
diff --git a/core/modules/migrate_drupal/tests/fixtures/drupal7.php b/core/modules/migrate_drupal/tests/fixtures/drupal7.php
index f34c6e1..59f076d 100644
--- a/core/modules/migrate_drupal/tests/fixtures/drupal7.php
+++ b/core/modules/migrate_drupal/tests/fixtures/drupal7.php
@@ -18336,6 +18336,36 @@
'objectindex' => '0',
'format' => '',
))
+->values(array(
+ 'lid' => '800',
+ 'textgroup' => 'menu',
+ 'context' => 'menu:main-menu:title',
+ 'objectid' => 'main-menu',
+ 'type' => 'menu',
+ 'property' => 'title',
+ 'objectindex' => '0',
+ 'format' => '',
+))
+->values(array(
+ 'lid' => '801',
+ 'textgroup' => 'menu',
+ 'context' => 'menu:main-menu:description',
+ 'objectid' => 'main-menu',
+ 'type' => 'menu',
+ 'property' => 'description',
+ 'objectindex' => '0',
+ 'format' => '',
+))
+->values(array(
+ 'lid' => '802',
+ 'textgroup' => 'menu',
+ 'context' => 'menu:menu-test-menu:description',
+ 'objectid' => 'menu-test-menu',
+ 'type' => 'menu',
+ 'property' => 'description',
+ 'objectindex' => '0',
+ 'format' => '',
+))
->execute();
$connection->schema()->createTable('i18n_translation_set', array(
'fields' => array(
@@ -19904,6 +19934,46 @@
'plural' => '0',
'i18n_status' => '0',
))
+->values(array(
+ 'lid' => '800',
+ 'translation' => 'is - Main menu',
+ 'language' => 'is',
+ 'plid' => '0',
+ 'plural' => '0',
+ 'i18n_status' => '0',
+))
+->values(array(
+ 'lid' => '801',
+ 'translation' => 'is - Main menu description',
+ 'language' => 'is',
+ 'plid' => '0',
+ 'plural' => '0',
+ 'i18n_status' => '0',
+))
+->values(array(
+ 'lid' => '800',
+ 'translation' => 'fr - Main menu',
+ 'language' => 'fr',
+ 'plid' => '0',
+ 'plural' => '0',
+ 'i18n_status' => '0',
+))
+->values(array(
+ 'lid' => '801',
+ 'translation' => 'fr - Main menu description',
+ 'language' => 'fr',
+ 'plid' => '0',
+ 'plural' => '0',
+ 'i18n_status' => '0',
+))
+->values(array(
+ 'lid' => '802',
+ 'translation' => 'fr - Test menu description',
+ 'language' => 'fr',
+ 'plid' => '0',
+ 'plural' => '0',
+ 'i18n_status' => '0',
+))
->execute();
$connection->schema()->createTable('menu_custom', array(
'fields' => array(
diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php
index 0e5d21b..ea2911a 100644
--- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php
+++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/Upgrade7Test.php
@@ -185,8 +185,8 @@ protected function getMissingPaths() {
return [
'i18n',
'i18n_field',
- 'i18n_string',
'i18n_menu',
+ 'i18n_string',
'i18n_taxonomy',
'i18n_translation',
'locale',
diff --git a/core/modules/system/migrations/d7_menu.yml b/core/modules/system/migrations/d7_menu.yml
index ce97f65..5853193 100644
--- a/core/modules/system/migrations/d7_menu.yml
+++ b/core/modules/system/migrations/d7_menu.yml
@@ -17,5 +17,9 @@ process:
user-menu: account
label: title
description: description
+ langcode:
+ plugin: default_value
+ source: language
+ default_value: und
destination:
plugin: entity:menu
diff --git a/core/modules/system/src/Plugin/migrate/source/Menu.php b/core/modules/system/src/Plugin/migrate/source/Menu.php
index a97878f..14296f1 100644
--- a/core/modules/system/src/Plugin/migrate/source/Menu.php
+++ b/core/modules/system/src/Plugin/migrate/source/Menu.php
@@ -25,11 +25,19 @@ public function query() {
* {@inheritdoc}
*/
public function fields() {
- return [
+ $fields = [
'menu_name' => $this->t('The menu name. Primary key.'),
'title' => $this->t('The human-readable name of the menu.'),
'description' => $this->t('A description of the menu'),
];
+
+ if ($this->database->schema()->fieldExists('menu_custom', 'language')) {
+ $fields += [
+ 'language' => $this->t('Menu language.'),
+ 'i8n_mode' => $this->t('Menu i18n mode.'),
+ ];
+ }
+ return $fields;
}
/**
diff --git a/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateMenuTest.php b/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateMenuTest.php
index 455be2a..3e05e13 100644
--- a/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateMenuTest.php
+++ b/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateMenuTest.php
@@ -26,14 +26,17 @@ protected function setUp() {
*
* @param $id
* The menu ID.
+ * @param string $language
+ * The menu language.
* @param $label
* The menu label.
* @param $description
* The menu description.
*/
- protected function assertEntity($id, $label, $description) {
+ protected function assertEntity($id, $language, $label, $description) {
$navigation_menu = Menu::load($id);
$this->assertSame($id, $navigation_menu->id());
+ $this->assertSame($language, $navigation_menu->language()->getId());
$this->assertSame($label, $navigation_menu->label());
$this->assertSame($description, $navigation_menu->getDescription());
}
@@ -42,11 +45,12 @@ protected function assertEntity($id, $label, $description) {
* Tests the Drupal 7 menu to Drupal 8 migration.
*/
public function testMenu() {
- $this->assertEntity('main', 'Main menu', 'The Main menu is used on many sites to show the major sections of the site, often in a top navigation bar.');
- $this->assertEntity('admin', 'Management', 'The Management menu contains links for administrative tasks.');
- $this->assertEntity('menu-test-menu', 'Test Menu', 'Test menu description.');
- $this->assertEntity('tools', 'Navigation', 'The Navigation menu contains links intended for site visitors. Links are added to the Navigation menu automatically by some modules.');
- $this->assertEntity('account', 'User menu', 'The User menu contains links related to the user\'s account, as well as the \'Log out\' link.');
+ $this->assertEntity('main', 'und', 'Main menu', 'The Main menu is used on many sites to show the major sections of the site, often in a top navigation bar.');
+ $this->assertEntity('admin', 'und', 'Management', 'The Management menu contains links for administrative tasks.');
+ $this->assertEntity('menu-test-menu', 'und', 'Test Menu', 'Test menu description.');
+ $this->assertEntity('tools', 'und', 'Navigation', 'The Navigation menu contains links intended for site visitors. Links are added to the Navigation menu automatically by some modules.');
+ $this->assertEntity('account', 'und', 'User menu', 'The User menu contains links related to the user\'s account, as well as the \'Log out\' link.');
+ $this->assertEntity('menu-fixedlang', 'is', 'FixedLang', '');
// Test that we can re-import using the ConfigEntityBase destination.
Database::getConnection('default', 'migrate')