diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_language.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_language.yml
new file mode 100644
index 0000000..cd6f8d2
--- /dev/null
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_language.yml
@@ -0,0 +1,14 @@
+id: d6_language
+source:
+  plugin: d6_language
+process:
+  id: language
+  label: name
+  direction: direction
+  weight: weight
+  locked:
+    plugin: default_value
+    default_value: false
+  status: enabled
+destination:
+  plugin: entity:language_entity
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Language.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Language.php
new file mode 100644
index 0000000..e34e60a1
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Plugin/migrate/source/d6/Language.php
@@ -0,0 +1,99 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Plugin\migrate\source\d6\Language.
+ */
+
+namespace Drupal\migrate_drupal\Plugin\migrate\source\d6;
+
+use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
+
+/**
+ * Drupal 6 language source from database.
+ *
+ * @MigrateSource(
+ *   id="d6_language"
+ * )
+ */
+class Language extends DrupalSqlBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $query = $this->select('languages', 'l')
+      ->fields('l', array('language', 'name', 'native',
+        'direction', 'enabled', 'plurals', 'formula', 'domain',
+        'prefix', 'weight', 'javascript'));
+    $query->orderBy('weight');
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function runQuery() {
+    $languages = array();
+    $iterator = parent::runQuery();
+
+    // As in Drupal 6 we couldn't remove English for real, we add it in case it
+    // was not there.
+    $englishWasFound = false;
+    foreach ($iterator as $language) {
+      $englishWasFound |= $language['language'] == 'en';
+      $languages[] = $language;
+    }
+    if (!$englishWasFound) {
+      $languages[] = array(
+        'language' => 'en',
+        'name' => 'English',
+        'native' => 'English',
+        'direction' => 0,
+        'enabled' => 1,
+        'plurals' => 0,
+        'formula' => '($n>1)',
+        'domain' => '',
+        'prefix' => '',
+        'weight' => 100,
+        'javascript' => '',
+      );
+    }
+    return new \ArrayIterator($languages);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fields() {
+    return array(
+      'language' => t("Language code, e.g. 'de' or 'en-US'."),
+      'name' => t('Language name in English.'),
+      'native' => t('Native language name.'),
+      'direction' => t('Direction of language (Left-to-Right = 0, Right-to-Left = 1).'),
+      'enabled' => t('Enabled flag (1 = Enabled, 0 = Disabled).'),
+      'plurals' => t('Number of plural indexes in this language.'),
+      'formula' => t('Plural formula in PHP code to evaluate to get plural indexes.'),
+      'domain' => t('Domain to use for this language.'),
+      'prefix' => t('Path prefix to use for this language.'),
+      'weight' => t('Weight, used in lists of languages.'),
+      'javascript' => t('Location of JavaScript translation file.'),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getIds() {
+    $ids['language']['type'] = 'string';
+    return $ids;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checkRequirements() {
+    return $this->moduleExists('locale');
+  }
+
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Language.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Language.php
new file mode 100644
index 0000000..e85e370
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Language.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\Dump\Drupal6Language.
+ */
+
+namespace Drupal\migrate_drupal\Tests\Dump;
+
+/**
+ * Database dump for testing language migration.
+ */
+class Drupal6Language extends Drupal6DumpBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $this->createTable('languages', array(
+      'fields' => array(
+        'language' => array(
+          'type' => 'varchar',
+          'length' => 12,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'name' => array(
+          'type' => 'varchar',
+          'length' => 64,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'native' => array(
+          'type' => 'varchar',
+          'length' => 64,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'direction' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'enabled' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'plurals' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'formula' => array(
+          'type' => 'varchar',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'domain' => array(
+          'type' => 'varchar',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'prefix' => array(
+          'type' => 'varchar',
+          'length' => 128,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+        'weight' => array(
+          'type' => 'int',
+          'not null' => TRUE,
+          'default' => 0,
+        ),
+        'javascript' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => TRUE,
+          'default' => '',
+        ),
+      ),
+      'primary key' => array(
+        'language',
+      ),
+      'indexes' => array(
+        'list' => array(
+          'weight',
+          'name',
+        ),
+      ),
+      'module' => 'locale',
+      'name' => 'languages',
+    ));
+    $this->database->insert('languages')->fields(array(
+      'language',
+      'name',
+      'native',
+      'direction',
+      'enabled',
+      'plurals',
+      'formula',
+      'domain',
+      'prefix',
+      'weight',
+      'javascript',
+    ))
+      ->values(array(
+        'language' => 'es',
+        'name' => 'Spanish',
+        'native' => 'Español',
+        'direction' => '0',
+        'enabled' => '1',
+        'plurals' => '0',
+        'formula' => '',
+        'domain' => 'http://es.example.com',
+        'prefix' => 'en',
+        'weight' => '0',
+        'javascript' => '',
+      ))
+      ->values(array(
+        'language' => 'fr',
+        'name' => 'French',
+        'native' => 'Français',
+        'direction' => '0',
+        'enabled' => '1',
+        'plurals' => '2',
+        'formula' => '($n>1)',
+        'domain' => '',
+        'prefix' => 'fr',
+        'weight' => '-3',
+        'javascript' => '51e92dcfe1491f4595b9df7f3b287753',
+      ))
+      ->execute();
+
+    $this->setModuleVersion('locale', '6001');
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateLanguageTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateLanguageTest.php
new file mode 100644
index 0000000..4cab5bd
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateLanguageTest.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateLanguageTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\Core\Language\Language;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\MigrateMessage;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+class MigrateLanguageTest extends MigrateDrupalTestBase {
+
+  public static $modules = array('language', 'migrate_drupal');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate languages to language.entity.*.yml',
+      'description'  => 'Upgrade languages to language.entity.*.yml',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_language');
+    $dumps = array(
+      drupal_get_path('module', 'migrate_drupal') . '/lib/Drupal/migrate_drupal/Tests/Dump/Drupal6Language.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  function testLanguage() {
+    $language_es = \Drupal::languageManager()->getLanguage('es');
+    $this->assertEqual($language_es->id, 'es');
+    $this->assertEqual($language_es->name, 'Spanish');
+    $this->assertEqual($language_es->direction, Language::DIRECTION_LTR);
+    $this->assertEqual($language_es->locked, FALSE);
+    $this->assertEqual($language_es->weight, 0);
+
+    $language_fr = \Drupal::languageManager()->getLanguage('fr');
+    $this->assertEqual($language_fr->id, 'fr');
+    $this->assertEqual($language_fr->name, 'French');
+    $this->assertEqual($language_fr->direction, Language::DIRECTION_LTR);
+    $this->assertEqual($language_fr->locked, FALSE);
+    $this->assertEqual($language_fr->weight, -3);
+
+    // Ensure that English is there even if was not in the language list.
+    $language_en = \Drupal::languageManager()->getLanguage('en');
+    $this->assertEqual($language_en->id, 'en');
+    $this->assertEqual($language_en->name, 'English');
+    $this->assertEqual($language_en->direction, Language::DIRECTION_LTR);
+    $this->assertEqual($language_en->locked, FALSE);
+    $this->assertEqual($language_en->weight, 100);
+  }
+
+}
diff --git a/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/LanguageSourceTest.php b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/LanguageSourceTest.php
new file mode 100644
index 0000000..d0ee581
--- /dev/null
+++ b/core/modules/migrate_drupal/tests/Drupal/migrate_drupal/Tests/source/d6/LanguageSourceTest.php
@@ -0,0 +1,145 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\source\d6\LanguageSourceTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\source\d6;
+
+use Drupal\migrate\Tests\MigrateSqlSourceTestCase;
+
+/**
+ * Tests language migration from D6 to D8.
+ *
+ * @group migrate_drupal
+ * @group Drupal
+ */
+class LanguageSourceTest extends MigrateSqlSourceTestCase {
+
+  // The plugin system is not working during unit testing so the source plugin
+  // class needs to be manually specified.
+  const PLUGIN_CLASS = 'Drupal\migrate_drupal\Plugin\migrate\source\d6\Language';
+
+  // The fake Migration configuration entity.
+  protected $migrationConfiguration = array(
+    // The ID of the entity, can be any string.
+    'id' => 'test',
+    // Leave it empty for now.
+    'idlist' => array(),
+    // This needs to be the identifier of the actual key: cid for comment, nid
+    // for node and so on.
+    'source' => array(
+      'plugin' => 'drupal6_language',
+    ),
+    'sourceIds' => array(
+      'language' => array(
+        // This is where the field schema would go but for now we need to
+        // specify the table alias for the key. Most likely this will be the
+        // same as BASE_ALIAS.
+        'alias' => 'l',
+      ),
+    ),
+    'destinationIds' => array(
+      'id' => array(
+        // This is where the field schema would go.
+      ),
+    ),
+  );
+
+  protected $expectedResults = array(
+    array(
+      'language' => 'es',
+      'name' => 'Spanish',
+      'native' => 'Español',
+      'direction' => 0,
+      'enabled' => 1,
+      'plurals' => 0,
+      'formula' => '',
+      'domain' => '',
+      'prefix' => 'es',
+      'weight' => -3,
+      'javascript' => '',
+    ),
+    array(
+      'language' => 'fr',
+      'name' => 'French',
+      'native' => 'Français',
+      'direction' => 0,
+      'enabled' => 1,
+      'plurals' => 0,
+      'formula' => '',
+      'domain' => '',
+      'prefix' => '',
+      'weight' => 0,
+      'javascript' => '',
+    ),
+    array(
+      'language' => 'en',
+      'name' => 'English',
+      'native' => 'English',
+      'direction' => 0,
+      'plurals' => 0,
+      'formula' => '($n>1)',
+      'domain' => '',
+      'prefix' => '',
+      'weight' => 100,
+      'javascript' => '',
+    ),
+  );
+
+  protected $databaseContents = array(
+    'languages' => array(
+      array(
+        'language' => 'es',
+        'name' => 'Spanish',
+        'native' => 'Español',
+        'direction' => 0,
+        'enabled' => 1,
+        'plurals' => 0,
+        'formula' => '',
+        'domain' => '',
+        'prefix' => 'es',
+        'weight' => -3,
+        'javascript' => '',
+      ),
+      array(
+        'language' => 'fr',
+        'name' => 'French',
+        'native' => 'Français',
+        'direction' => 0,
+        'enabled' => 1,
+        'plurals' => 0,
+        'formula' => '',
+        'domain' => '',
+        'prefix' => '',
+        'weight' => 0,
+        'javascript' => '',
+      ),
+    ));
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'D6 language source functionality',
+      'description' => 'Tests D6 language source plugin.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+}
+
+
+use Drupal\Core\Database\Connection;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\migrate_drupal\Plugin\migrate\source\d6\Language;
+
+class TestLanguage extends Language {
+  function setDatabase(Connection $database) {
+    $this->database = $database;
+  }
+  function setModuleHandler(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+}
