diff --git a/core/modules/language/migration_templates/d6_language_negotiation_settings.yml b/core/modules/language/migration_templates/d6_language_negotiation_settings.yml
new file mode 100644
index 0000000..bc5c133
--- /dev/null
+++ b/core/modules/language/migration_templates/d6_language_negotiation_settings.yml
@@ -0,0 +1,30 @@
+id: d6_language_negotiation_settings
+label: Language negotiation settings
+migration_tags:
+  - Drupal 6
+source:
+  plugin: variable
+  variables:
+    - language_negotiation
+process:
+  session/parameter:
+    plugin: default_value
+    default_value: 'language'
+  selected_langcode:
+    plugin: default_value
+    default_value: 'site_default'
+  url/source:
+    plugin: static_map
+    source: language_negotiation
+    map:
+      # LANGUAGE_NEGOTIATION_NONE = 0
+      # LANGUAGE_NEGOTIATION_PATH_DEFAULT = 1
+      # LANGUAGE_NEGOTIATION_PATH = 2
+      # LANGUAGE_NEGOTIATION_DOMAIN = 3
+      0: path_prefix
+      1: path_prefix
+      2: path_prefix
+      3: domain
+destination:
+  plugin: config
+  config_name: language.negotiation
diff --git a/core/modules/language/migration_templates/d6_language_prefixes_and_domains.yml b/core/modules/language/migration_templates/d6_language_prefixes_and_domains.yml
new file mode 100644
index 0000000..a26714c
--- /dev/null
+++ b/core/modules/language/migration_templates/d6_language_prefixes_and_domains.yml
@@ -0,0 +1,25 @@
+id: d6_language_prefixes_and_domains
+label: Language prefixes and domains
+migration_tags:
+  - Drupal 6
+source:
+  plugin: language
+  fetch_all: true
+  negotiation: true
+process:
+  'url/prefixes':
+    plugin: array_map
+    source: languages
+    key: language
+    value: prefix
+  'url/domains':
+    plugin: language_domains
+    source: languages
+    key: language
+    value: domain
+destination:
+  plugin: config
+  config_name: language.negotiation
+migration_dependencies:
+  required:
+    - language
diff --git a/core/modules/language/migration_templates/d6_language_types.yml b/core/modules/language/migration_templates/d6_language_types.yml
new file mode 100644
index 0000000..05ce300
--- /dev/null
+++ b/core/modules/language/migration_templates/d6_language_types.yml
@@ -0,0 +1,52 @@
+id: d6_language_types
+label: Language types
+migration_tags:
+  - Drupal 6
+source:
+  plugin: variable
+  variables:
+    - language_negotiation
+process:
+  all:
+    plugin: default_value
+    default_value:
+      - 'language_interface'
+      - 'language_content'
+      - 'language_url'
+  configurable:
+    plugin: default_value
+    default_value:
+      - 'language_interface'
+  negotiation/language_content/enabled:
+    plugin: default_value
+    default_value:
+      'language-interface': 0
+  negotiation/language_url/enabled:
+    plugin: default_value
+    default_value:
+      'language-url': 0
+      'language-url-fallback': 1
+  negotiation/language_interface/enabled:
+    plugin: static_map
+    source: language_negotiation
+    map:
+      # LANGUAGE_NEGOTIATION_NONE = 0
+      # LANGUAGE_NEGOTIATION_PATH_DEFAULT = 1
+      # LANGUAGE_NEGOTIATION_PATH = 2
+      # LANGUAGE_NEGOTIATION_DOMAIN = 3
+      0:
+        'language-selected': 0
+      1:
+        'language-url': 0
+        'language-selected': 1
+      2:
+        'language-url': 0
+        'language-user': 1
+        'language-browser': 2
+        'language-selected': 3
+      3:
+        'language-url': 0
+        'language-selected': 1
+destination:
+  plugin: config
+  config_name: language.types
diff --git a/core/modules/language/src/Plugin/migrate/process/LanguageDomains.php b/core/modules/language/src/Plugin/migrate/process/LanguageDomains.php
new file mode 100644
index 0000000..4d01caa
--- /dev/null
+++ b/core/modules/language/src/Plugin/migrate/process/LanguageDomains.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Drupal\language\Plugin\migrate\process;
+
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\Plugin\migrate\process\Array_map;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * This plugin makes sure that no domain is empty if domain negotiation is used.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "language_domains",
+ *   handle_multiples = TRUE
+ * )
+ */
+class LanguageDomains extends Array_map {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    if ($row->hasSourceProperty('negotiation')) {
+      $negotiation = unserialize($row->getSourceProperty('negotiation'));
+
+      // Check if domain negotiation is used (LANGUAGE_NEGOTIATION_DOMAIN = 3).
+      if ($negotiation == '3') {
+        global $base_url;
+
+        foreach ($value as $old_key => $old_value) {
+          if (empty($old_value['domain'])) {
+            // The default language domain might be empty.
+            // If it is, use the current domain.
+            $value[$old_key]['domain'] = parse_url($base_url, PHP_URL_HOST);
+          }
+          else {
+            // Only keep the host part of the domain.
+            $value[$old_key]['domain'] = parse_url($old_value['domain'], PHP_URL_HOST);
+          }
+        }
+      }
+    }
+
+    return parent::transform($value, $migrate_executable, $row, $destination_property);
+  }
+
+}
diff --git a/core/modules/language/src/Plugin/migrate/source/Language.php b/core/modules/language/src/Plugin/migrate/source/Language.php
index 01a0ccf..44d7213 100644
--- a/core/modules/language/src/Plugin/migrate/source/Language.php
+++ b/core/modules/language/src/Plugin/migrate/source/Language.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\language\Plugin\migrate\source;
 
+use Drupal\migrate\Row;
 use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
 
 /**
@@ -49,4 +50,29 @@ public function query() {
     return $this->select('languages')->fields('languages');
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareRow(Row $row) {
+    if (isset($this->configuration['fetch_all']) && $this->configuration['fetch_all']) {
+      // Get an array of all languages.
+      $languages = $this->query()->execute()->fetchAll();
+      $row->setSourceProperty('languages', $languages);
+    }
+
+    if (isset($this->configuration['negotiation']) && $this->configuration['negotiation']) {
+      // Get the language negotiation method.
+      // We need it to find out if domain negotiation is used and thus fill in
+      // the default language domain, which may be empty.
+      $negotiation = $this->select('variable', 'v')
+        ->fields('v', array('value'))
+        ->condition('name', 'language_negotiation')
+        ->execute()
+        ->fetchField();
+      $row->setSourceProperty('negotiation', $negotiation);
+    }
+
+    return parent::prepareRow($row);
+  }
+
 }
diff --git a/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageNegotiationSettingsTest.php b/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageNegotiationSettingsTest.php
new file mode 100644
index 0000000..7e60e25
--- /dev/null
+++ b/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateLanguageNegotiationSettingsTest.php
@@ -0,0 +1,167 @@
+<?php
+
+namespace Drupal\Tests\language\Kernel\Migrate\d6;
+
+use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
+use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
+
+/**
+ * Tests the migration of language negotiation and language types.
+ *
+ * @group migrate_drupal_6
+ */
+class MigrateLanguageNegotiationSettingsTest extends MigrateDrupal6TestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['language'];
+
+  /**
+   * Tests the migration with LANGUAGE_NEGOTIATION_PATH_DEFAULT.
+   */
+  public function testLanguageNegotiationWithDefaultPathPrefix() {
+    $this->executeMigrations([
+      'language',
+      'd6_language_negotiation_settings',
+      'd6_language_prefixes_and_domains',
+      'd6_language_types',
+    ]);
+
+    $config = $this->config('language.negotiation');
+    $this->assertSame($config->get('session.parameter'), 'language');
+    $this->assertSame($config->get('url.source'), LanguageNegotiationUrl::CONFIG_PATH_PREFIX);
+    $this->assertSame($config->get('selected_langcode'), 'site_default');
+    $expected_prefixes = [
+      'en' => '',
+      'fr' => 'fr',
+      'zu' => 'zu',
+    ];
+    $this->assertSame($config->get('url.prefixes'), $expected_prefixes);
+
+    $config = $this->config('language.types');
+    $this->assertSame($config->get('all'), ['language_interface', 'language_content', 'language_url']);
+    $this->assertSame($config->get('configurable'), ['language_interface']);
+    $this->assertSame($config->get('negotiation.language_content.enabled'), ['language-interface' => 0]);
+    $this->assertSame($config->get('negotiation.language_url.enabled'), ['language-url' => 0, 'language-url-fallback' => 1]);
+    $expected_language_interface = [
+      'language-url' => 0,
+      'language-selected' => 1,
+    ];
+    $this->assertSame($config->get('negotiation.language_interface.enabled'), $expected_language_interface);
+  }
+
+  /**
+   * Tests the migration with LANGUAGE_NEGOTIATION_NONE.
+   */
+  public function testLanguageNegotiationWithNoNegotiation() {
+    $this->sourceDatabase->update('variable')
+      ->fields(array('value' => serialize(0)))
+      ->condition('name', 'language_negotiation')
+      ->execute();
+
+    $this->executeMigrations([
+      'language',
+      'd6_language_negotiation_settings',
+      'd6_language_prefixes_and_domains',
+      'd6_language_types',
+    ]);
+
+    $config = $this->config('language.negotiation');
+    $this->assertSame($config->get('session.parameter'), 'language');
+    $this->assertSame($config->get('url.source'), LanguageNegotiationUrl::CONFIG_PATH_PREFIX);
+    $this->assertSame($config->get('selected_langcode'), 'site_default');
+
+    $config = $this->config('language.types');
+    $this->assertSame($config->get('all'), ['language_interface', 'language_content', 'language_url']);
+    $this->assertSame($config->get('configurable'), ['language_interface']);
+    $this->assertSame($config->get('negotiation.language_content.enabled'), ['language-interface' => 0]);
+    $this->assertSame($config->get('negotiation.language_url.enabled'), ['language-url' => 0, 'language-url-fallback' => 1]);
+    $expected_language_interface = [
+      'language-selected' => 0,
+    ];
+    $this->assertSame($config->get('negotiation.language_interface.enabled'), $expected_language_interface);
+  }
+
+  /**
+   * Tests the migration with LANGUAGE_NEGOTIATION_PATH.
+   */
+  public function testLanguageNegotiationWithPathPrefix() {
+    $this->sourceDatabase->update('variable')
+      ->fields(array('value' => serialize(2)))
+      ->condition('name', 'language_negotiation')
+      ->execute();
+
+    $this->executeMigrations([
+      'language',
+      'd6_language_negotiation_settings',
+      'd6_language_prefixes_and_domains',
+      'd6_language_types',
+    ]);
+
+    $config = $this->config('language.negotiation');
+    $this->assertSame($config->get('session.parameter'), 'language');
+    $this->assertSame($config->get('url.source'), LanguageNegotiationUrl::CONFIG_PATH_PREFIX);
+    $this->assertSame($config->get('selected_langcode'), 'site_default');
+    $expected_prefixes = [
+      'en' => '',
+      'fr' => 'fr',
+      'zu' => 'zu',
+    ];
+    $this->assertSame($config->get('url.prefixes'), $expected_prefixes);
+
+    $config = $this->config('language.types');
+    $this->assertSame($config->get('all'), ['language_interface', 'language_content', 'language_url']);
+    $this->assertSame($config->get('configurable'), ['language_interface']);
+    $this->assertSame($config->get('negotiation.language_content.enabled'), ['language-interface' => 0]);
+    $this->assertSame($config->get('negotiation.language_url.enabled'), ['language-url' => 0, 'language-url-fallback' => 1]);
+    $expected_language_interface = [
+      'language-url' => 0,
+      'language-user' => 1,
+      'language-browser' => 2,
+      'language-selected' => 3,
+    ];
+    $this->assertSame($config->get('negotiation.language_interface.enabled'), $expected_language_interface);
+  }
+
+  /**
+   * Tests the migration with LANGUAGE_NEGOTIATION_DOMAIN.
+   */
+  public function testLanguageNegotiationWithDomain() {
+    $this->sourceDatabase->update('variable')
+      ->fields(array('value' => serialize(3)))
+      ->condition('name', 'language_negotiation')
+      ->execute();
+
+    $this->executeMigrations([
+      'language',
+      'd6_language_negotiation_settings',
+      'd6_language_prefixes_and_domains',
+      'd6_language_types',
+    ]);
+
+    global $base_url;
+    $config = $this->config('language.negotiation');
+    $this->assertSame($config->get('session.parameter'), 'language');
+    $this->assertSame($config->get('url.source'), LanguageNegotiationUrl::CONFIG_DOMAIN);
+    $this->assertSame($config->get('selected_langcode'), 'site_default');
+    $expected_domains = [
+      'en' => parse_url($base_url, PHP_URL_HOST),
+      'fr' => 'fr.drupal.org',
+      'zu' => 'zu.drupal.org',
+    ];
+    $this->assertSame($config->get('url.domains'), $expected_domains);
+
+    $config = $this->config('language.types');
+    $this->assertSame($config->get('all'), ['language_interface', 'language_content', 'language_url']);
+    $this->assertSame($config->get('configurable'), ['language_interface']);
+    $this->assertSame($config->get('negotiation.language_content.enabled'), ['language-interface' => 0]);
+    $this->assertSame($config->get('negotiation.language_url.enabled'), ['language-url' => 0, 'language-url-fallback' => 1]);
+    $expected_language_interface = [
+      'language-url' => 0,
+      'language-selected' => 1,
+    ];
+    $this->assertSame($config->get('negotiation.language_interface.enabled'), $expected_language_interface);
+  }
+
+}
diff --git a/core/modules/migrate/src/Plugin/migrate/process/Array_map.php b/core/modules/migrate/src/Plugin/migrate/process/Array_map.php
new file mode 100644
index 0000000..ba4ef63
--- /dev/null
+++ b/core/modules/migrate/src/Plugin/migrate/process/Array_map.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Drupal\migrate\Plugin\migrate\process;
+
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\Row;
+
+/**
+ * This plugin maps an array based on the 'key' and 'value' configuration.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "array_map",
+ *   handle_multiples = TRUE
+ * )
+ */
+class Array_map extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    $new_value = [];
+
+    foreach ($value as $old_key => $old_value) {
+      $new_value[$old_value[$this->configuration['key']]] = $old_value[$this->configuration['value']];
+    }
+
+    return $new_value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function multiple() {
+    return TRUE;
+  }
+
+}
diff --git a/core/modules/migrate_drupal/tests/fixtures/drupal6.php b/core/modules/migrate_drupal/tests/fixtures/drupal6.php
index 347b2f2..5e599be 100644
--- a/core/modules/migrate_drupal/tests/fixtures/drupal6.php
+++ b/core/modules/migrate_drupal/tests/fixtures/drupal6.php
@@ -9812,7 +9812,7 @@
   'enabled' => '1',
   'plurals' => '2',
   'formula' => '($n>1)',
-  'domain' => '',
+  'domain' => 'http://fr.drupal.org',
   'prefix' => 'fr',
   'weight' => '0',
   'javascript' => '047746d30d76aa44a54db9923c7c5fb0',
@@ -9825,7 +9825,7 @@
   'enabled' => '1',
   'plurals' => '0',
   'formula' => '',
-  'domain' => '',
+  'domain' => 'http://zu.drupal.org',
   'prefix' => 'zu',
   'weight' => '0',
   'javascript' => '',
diff --git a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
index b53069e..668e698 100644
--- a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
+++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
@@ -278,10 +278,22 @@ class MigrateUpgradeForm extends ConfirmFormBase {
       'source_module' => 'locale',
       'destination_module' => 'language',
     ],
+    'd6_language_negotiation_settings' => [
+      'source_module' => 'locale',
+      'destination_module' => 'language',
+    ],
     'd7_language_negotiation_settings' => [
       'source_module' => 'locale',
       'destination_module' => 'language',
     ],
+    'd6_language_prefixes_and_domains' => [
+      'source_module' => 'locale',
+      'destination_module' => 'language',
+    ],
+    'd6_language_types' => [
+      'source_module' => 'locale',
+      'destination_module' => 'language',
+    ],
     'language' => [
       'source_module' => 'locale',
       'destination_module' => 'language',
