diff --git a/core/modules/language/migration_templates/default_language.yml b/core/modules/language/migration_templates/default_language.yml
index d7e52ad..f7c3cfe 100644
--- a/core/modules/language/migration_templates/default_language.yml
+++ b/core/modules/language/migration_templates/default_language.yml
@@ -4,9 +4,7 @@ migration_tags:
   - Drupal 6
   - Drupal 7
 source:
-  plugin: variable
-  variables:
-    - language_default
+  plugin: language_default
 process:
   default_langcode:
     -
diff --git a/core/modules/language/src/Plugin/migrate/source/LanguageDefault.php b/core/modules/language/src/Plugin/migrate/source/LanguageDefault.php
new file mode 100644
index 0000000..4a44446
--- /dev/null
+++ b/core/modules/language/src/Plugin/migrate/source/LanguageDefault.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace Drupal\language\Plugin\migrate\source;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ *  Provides a source plugin for the default language variable.
+ *
+ * @MigrateSource(
+ *   id = "language_default"
+ * )
+ */
+class LanguageDefault extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function initializeIterator() {
+    return new \ArrayIterator(array($this->values()));
+  }
+
+  /**
+   * Return the value of the language_default variable.
+   *
+   * @return array
+   *   An associative array where the key is the variable name and the value is
+   *   the value found in the database. If the variable does not exists, return
+   *   English instead of nothing.
+   */
+  protected function values() {
+    // Create an ID field so we can record migration in the map table.
+    $values['id'] = 'language_default';
+    $results = $this->prepareQuery()->execute()->fetchAllKeyed();
+
+    // If the variable does not exist, we still need to return an object since
+    // it will be passed to the callback process plugin with get_object_vars()
+    // as callable and then the Extract process plugin.
+    if (empty($results)) {
+      $results['language_default'] = 'O:8:"stdClass":1:{s:8:"language";s:2:"en";}';
+    }
+
+    return $values + array_map('unserialize', $results);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return ['language_default' => 'language_default'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    return $this->getDatabase()
+      ->select('variable', 'v')
+      ->fields('v', array('name', 'value'))
+      ->condition('name', 'language_default');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['id']['type'] = 'string';
+    return $ids;
+  }
+
+}
diff --git a/core/modules/language/tests/src/Kernel/Migrate/MigrateDefaultLanguageTrait.php b/core/modules/language/tests/src/Kernel/Migrate/MigrateDefaultLanguageTrait.php
index deb6020..0f97698 100644
--- a/core/modules/language/tests/src/Kernel/Migrate/MigrateDefaultLanguageTrait.php
+++ b/core/modules/language/tests/src/Kernel/Migrate/MigrateDefaultLanguageTrait.php
@@ -53,4 +53,24 @@ protected function doTestMigration($langcode, $existing = TRUE) {
     }
   }
 
+  /**
+   * Helper method to test the migration with unset variable.
+   */
+  protected function doTestMigrationWithUnsetVariable() {
+    // Delete the language_default variable.
+    $this->sourceDatabase->delete('variable')
+      ->condition('name', 'language_default' )
+      ->execute();
+
+    $this->startCollectingMessages();
+    $this->executeMigrations(['language', 'default_language']);
+    $messages = $this->migration->getIdMap()->getMessageIterator()->fetchAll();
+
+    // Make sure there's no migration exceptions.
+    $this->assertEmpty($messages);
+
+    // Make sure the default langcode is 'en', since it was the default on D6 & D7.
+    $this->assertIdentical('en', $this->config('system.site')->get('default_langcode'));
+  }
+
 }
diff --git a/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateDefaultLanguageTest.php b/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateDefaultLanguageTest.php
index 20beb96..645af29 100644
--- a/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateDefaultLanguageTest.php
+++ b/core/modules/language/tests/src/Kernel/Migrate/d6/MigrateDefaultLanguageTest.php
@@ -33,4 +33,11 @@ public function testMigrationWithNonExistentLanguage() {
     $this->doTestMigration('tv', FALSE);
   }
 
+  /**
+   * Tests language_default migration with unset variable.
+   */
+  public function testMigrationWithUnsetVariable() {
+    $this->doTestMigrationWithUnsetVariable();
+  }
+
 }
diff --git a/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateDefaultLanguageTest.php b/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateDefaultLanguageTest.php
index 0e584e5..79769bc 100644
--- a/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateDefaultLanguageTest.php
+++ b/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateDefaultLanguageTest.php
@@ -33,4 +33,11 @@ public function testMigrationWithNonExistentLanguage() {
     $this->doTestMigration('tv', FALSE);
   }
 
+  /**
+   * Tests language_default migration with unset variable.
+   */
+  public function testMigrationWithUnsetVariable() {
+    $this->doTestMigrationWithUnsetVariable();
+  }
+
 }
