diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 0f46eb3..103cbbc 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -2500,14 +2500,29 @@ function language_list($flags = Language::STATE_CONFIGURABLE) {
     // Fill in master language list based on current configuration.
     $default = language_default();
     if (language_multilingual() || module_exists('language')) {
-      // Use language module configuration if available.
-      $languages = db_query('SELECT * FROM {language} ORDER BY weight ASC, name ASC')->fetchAllAssoc('langcode', PDO::FETCH_ASSOC);
+      // Use language module configuration if available. We can not use
+      // entity_load_multiple() because this breaks during updates.
+      $language_entities = config_get_storage_names_with_prefix('language.entity');
+      uasort($language_entities, function ($a, $b) {
+        $a_weight = isset($a['weight']) ? $a['weight'] : 0;
+        $b_weight = isset($b['weight']) ? $b['weight'] : 0;
+        if ($a_weight == $b_weight) {
+          return strnatcasecmp($a['label'], $b['label']);
+        }
+        return ($a_weight < $b_weight) ? -1 : 1;
+      });
 
       // Initialize default property so callers have an easy reference and can
       // save the same object without data loss.
-      foreach ($languages as $langcode => $info) {
-        $info['default'] = ($langcode == $default->langcode);
-        $languages[$langcode] = new Language($info);
+      foreach ($language_entities as $langcode => $info) {
+        $languages[$langcode] = new Language(array(
+          'default' => ($info['id'] == $default->langcode),
+          'name' => $info['label'],
+          'langcode' => $info['id'],
+          'direction' => $info['direction'],
+          'locked' => $info['locked'],
+          'weight' => $info['weight'],
+        ));
       }
     }
     else {
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php b/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php
index cee642e..cd8ef17 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigLocaleOverride.php
@@ -64,7 +64,6 @@ function testConfigLocaleOverride() {
    */
   function testConfigLocaleUserOverride() {
     $this->installSchema('system', 'variable');
-    $this->installSchema('language', 'language');
     language_save(new Language(array(
       'name' => 'French',
       'langcode' => 'fr',
@@ -162,7 +161,6 @@ function testConfigLocaleUserAndGlobalOverride() {
     $conf['config_test.system']['404'] = 'global herp';
 
     $this->installSchema('system', 'variable');
-    $this->installSchema('language', 'language');
     language_save(new Language(array(
       'name' => 'French',
       'langcode' => 'fr',
diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
index ae52f2e..8952bcb 100644
--- a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
@@ -36,7 +36,6 @@ public static function getInfo() {
 
   function setUp() {
     parent::setUp();
-    $this->installSchema('language', array('language'));
     $this->installSchema('node', array('node_type'));
 
     $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
diff --git a/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php b/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php
index 2d73a24..172eee9 100644
--- a/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php
+++ b/core/modules/hal/lib/Drupal/hal/Tests/NormalizerTestBase.php
@@ -60,7 +60,6 @@ function setUp() {
     parent::setUp();
     $this->installSchema('system', array('variable', 'url_alias'));
     $this->installSchema('user', array('users'));
-    $this->installSchema('language', array('language'));
     $this->installSchema('entity_test', array('entity_test'));
     $this->installConfig(array('field'));
 
diff --git a/core/modules/language/language.install b/core/modules/language/language.install
index 17828fd..1f9ad4e 100644
--- a/core/modules/language/language.install
+++ b/core/modules/language/language.install
@@ -5,6 +5,9 @@
  * Install, update and uninstall functions for the language module.
  */
 
+use Drupal\Component\Uuid\Uuid;
+use Drupal\Core\Language\Language;
+
 /**
  * Implements hook_install().
  *
@@ -51,55 +54,6 @@ function language_uninstall() {
 }
 
 /**
- * Implements hook_schema().
- */
-function language_schema() {
-  $schema['language'] = array(
-    'description' => 'List of all available languages in the system.',
-    'fields' => array(
-      'langcode' => array(
-        'type' => 'varchar',
-        'length' => 12,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => "Language code, e.g. 'de' or 'en-US'.",
-      ),
-      'name' => array(
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Language name.',
-      ),
-      'direction' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Direction of language (Left-to-Right = 0, Right-to-Left = 1).',
-      ),
-      'weight' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Weight, used in lists of languages.',
-      ),
-      'locked' => array(
-        'type' => 'int',
-        'size' => 'tiny',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'A boolean indicating whether the administrator can edit or delete the language.',
-      ),
-    ),
-    'primary key' => array('langcode'),
-    'indexes' => array(
-      'list' => array('weight', 'name'),
-    ),
-  );
-  return $schema;
-}
-
-/**
  * Implements hook_enable().
  */
 function language_enable() {
@@ -127,3 +81,26 @@ function language_requirements($phase) {
     language_negotiation_include();
   }
 }
+
+/**
+ * Migrate all languages to configuration.
+ *
+ * @ingroup config_upgrade
+ */
+function language_update_8000() {
+  $manifest_ids = array();
+  $result = db_query('SELECT * FROM {language}');
+  $uuid = new Uuid();
+  foreach ($result as $language) {
+    config('language.entity.' . $language->langcode)
+      ->set('id', $language->langcode)
+      ->set('uuid', $uuid->generate())
+      ->set('label', $language->name)
+      ->set('direction', $language->direction)
+      ->set('weight', $language->weight)
+      ->set('locked', $language->locked)
+      ->set('status', 1)
+      ->set('langcode', Language::LANGCODE_NOT_SPECIFIED)
+      ->save();
+  }
+}
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 6b45fa1..8877d0c 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -471,23 +471,37 @@ function language_get_default_langcode($entity_type, $bundle) {
  * API function to add or update a language.
  *
  * @param $language
- *   Language object with properties corresponding to 'language' table columns.
+ *   Language object with properties corresponding to the 'language'
+ *   configuration properties.
  */
 function language_save($language) {
-  $language->is_new = !(bool) db_query_range('SELECT 1 FROM {language} WHERE langcode = :langcode', 0, 1, array(':langcode' => $language->langcode))->fetchField();
+  $language_entity = entity_load('language_entity', $language->langcode);
+  if (!$language_entity) {
+    $language->is_new = TRUE;
+    $language_entity = entity_create('language_entity', array(
+      'id' => $language->langcode,
+    ));
+  }
+  else {
+    $language->is_new = FALSE;
+  }
 
   // Let other modules modify $language before saved.
   module_invoke_all('language_presave', $language);
 
+  $language_entity->label = isset($language->name) ? $language->name : '';
+  $language_entity->direction = isset($language->direction) ? $language->direction : '0';
+  $language_entity->locked = isset($language->locked) ? $language->locked : '0';
+  $language_entity->weight = isset($language->weight) ? $language->weight : '0';
+
   // Save the record and inform others about the change.
+  $language_entity->save();
   $t_args = array('%language' => $language->name, '%langcode' => $language->langcode);
   if ($language->is_new) {
-    drupal_write_record('language', $language);
     module_invoke_all('language_insert', $language);
     watchdog('language', 'The %language (%langcode) language has been created.', $t_args);
   }
   else {
-    drupal_write_record('language', $language, array('langcode'));
     module_invoke_all('language_update', $language);
     watchdog('language', 'The %language (%langcode) language has been updated.', $t_args);
   }
@@ -523,7 +537,14 @@ function language_save($language) {
  * @see language_multilingual()
  */
 function language_update_count() {
-  variable_set('language_count', db_query('SELECT COUNT(langcode) FROM {language} WHERE locked = 0')->fetchField());
+  $count = 0;
+  $languages = entity_load_multiple('language_entity', NULL, TRUE);
+  foreach ($languages as $language) {
+    if (!$language->locked) {
+      $count++;
+    }
+  }
+  variable_set('language_count', $count);
 }
 
 /**
@@ -543,9 +564,7 @@ function language_delete($langcode) {
     module_invoke_all('language_delete', $language);
 
     // Remove the language.
-    db_delete('language')
-      ->condition('langcode', $language->langcode)
-      ->execute();
+    entity_delete_multiple('language_entity', array($language->langcode));
 
     language_update_count();
 
@@ -801,16 +820,23 @@ function language_set_browser_drupal_langcode_mappings($mappings) {
  * Updates locked system language weights.
  */
 function language_update_locked_weights() {
+  $max_weight = 0;
+
   // Get maximum weight to update the system languages to keep them on bottom.
-  $max_weight = db_query('SELECT MAX(weight) FROM {language} WHERE locked = 0')->fetchField();
+  $languages = entity_load_multiple('language_entity', NULL, TRUE);
+  foreach ($languages as $language) {
+    if (!$language->locked && $language->weight > $max_weight) {
+      $max_weight = $language->weight;
+    }
+  }
+
   // Loop locked languages to maintain the existing order.
   foreach (language_list(Language::STATE_LOCKED) as $language) {
     $max_weight++;
     // Update system languages weight.
-    db_update('language')
-      ->fields(array('weight' => $max_weight))
-      ->condition('langcode', $language->langcode)
-      ->execute();
+    config('language.entity.' . $language->langcode)
+      ->set('weight', $max_weight)
+      ->save();
   }
 }
 
diff --git a/core/modules/language/language.views.inc b/core/modules/language/language.views.inc
deleted file mode 100644
index 2ec7e3a..0000000
--- a/core/modules/language/language.views.inc
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-
-/**
- * @file
- * Provide views data and handlers for language.module.
- *
- * @ingroup views_module_handlers
- */
-
-/**
- * Implements hook_views_data().
- */
-function language_views_data() {
-  $data['language']['table']['group']  = t('Language');
-
-  $data['language']['table']['base'] = array(
-    'field' => 'langcode',
-    'title' => t('Language'),
-    'help' => t('A language used in drupal.'),
-  );
-
-  $data['language']['langcode'] = array(
-    'title' => t('Language code'),
-    'help' => t("Language code, e.g. 'de' or 'en-US'."),
-    'field' => array(
-      'id' => 'standard',
-    ),
-    'filter' => array(
-      'id' => 'string'
-    ),
-    'argument' => array(
-      'id' => 'string',
-    ),
-    'sort' => array(
-      'id' => 'standard',
-    ),
-  );
-
-  $data['language']['name'] = array(
-    'title' => t('Language name'),
-    'help' => t("Language name, e.g. 'German' or 'English'."),
-    'field' => array(
-      'id' => 'standard',
-    ),
-    'filter' => array(
-      'id' => 'string'
-    ),
-    'argument' => array(
-      'id' => 'string',
-    ),
-    'sort' => array(
-      'id' => 'standard',
-    ),
-  );
-
-  $data['language']['direction'] = array(
-    'title' => t('Direction'),
-    'help' => t('Direction of language (Left-to-Right = 0, Right-to-Left = 1).'),
-    'field' => array(
-      'id' => 'numeric',
-    ),
-    'filter' => array(
-      'id' => 'numeric'
-    ),
-    'argument' => array(
-      'id' => 'numeric',
-    ),
-    'sort' => array(
-      'id' => 'standard',
-    ),
-  );
-
-  $data['language']['weight'] = array(
-    'title' => t('Weight'),
-    'help' => t('Weight, used in lists of languages.'),
-    'field' => array(
-      'id' => 'numeric',
-    ),
-    'filter' => array(
-      'id' => 'numeric'
-    ),
-    'argument' => array(
-      'id' => 'numeric',
-    ),
-    'sort' => array(
-      'id' => 'standard',
-    ),
-  );
-
-  $data['language']['locked'] = array(
-    'title' => t('Locked'),
-    'help' => t('A boolean indicating whether the administrator can edit or delete the language.'),
-    'field' => array(
-      'id' => 'boolean',
-    ),
-    'filter' => array(
-      'id' => 'boolean',
-    ),
-    'argument' => array(
-      'id' => 'numeric',
-    ),
-    'sort' => array(
-      'id' => 'standard',
-    ),
-  );
-
-  return $data;
-}
diff --git a/core/modules/language/lib/Drupal/language/LanguageInterface.php b/core/modules/language/lib/Drupal/language/LanguageInterface.php
new file mode 100644
index 0000000..35db887
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/LanguageInterface.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\Plugin\Core\Entity\LanguageInterface.
+ */
+
+namespace Drupal\language;
+
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+
+/**
+ * Provides an interface defining a language entity.
+ */
+interface LanguageInterface extends ConfigEntityInterface {
+
+}
diff --git a/core/modules/language/lib/Drupal/language/Plugin/Core/Entity/Language.php b/core/modules/language/lib/Drupal/language/Plugin/Core/Entity/Language.php
new file mode 100644
index 0000000..d1d70de
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/Plugin/Core/Entity/Language.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\Plugin\Core\Entity\Language.
+ */
+
+namespace Drupal\language\Plugin\Core\Entity;
+
+use Drupal\Core\Entity\Annotation\EntityType;
+use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\language\LanguageInterface;
+
+/**
+ * Defines the Language entity.
+ *
+ * @EntityType(
+ *   id = "language_entity",
+ *   label = @Translation("Language"),
+ *   module = "language",
+ *   controllers = {
+ *     "storage" = "Drupal\Core\Config\Entity\ConfigStorageController"
+ *   },
+ *   config_prefix = "language.entity",
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "label" = "label",
+ *     "uuid" = "uuid"
+ *   }
+ * )
+ */
+class Language extends ConfigEntityBase implements LanguageInterface {
+
+  /**
+   * The language ID (machine name).
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The language UUID.
+   *
+   * This is assigned automatically when the language is created.
+   *
+   * @var string
+   */
+  public $uuid;
+
+  /**
+   * The human-readable label for the language.
+   *
+   * @var string
+   */
+  public $label;
+
+  /**
+   * The direction of language (Left-to-Right = 0, Right-to-Left = 1).
+   *
+   * @var integer
+   */
+  public $direction = '';
+
+  /**
+   * The weight of the language, used in lists of languages.
+   *
+   * @var integer
+   */
+  public $weight = 0;
+
+  /**
+   * Flag indicating whether this language is locked or not.
+   *
+   * @var bool
+   */
+  public $locked = FALSE;
+
+}
diff --git a/core/modules/language/lib/Drupal/language/Tests/Condition/LanguageConditionTest.php b/core/modules/language/lib/Drupal/language/Tests/Condition/LanguageConditionTest.php
index e98a8d3..2cae70c 100644
--- a/core/modules/language/lib/Drupal/language/Tests/Condition/LanguageConditionTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/Condition/LanguageConditionTest.php
@@ -48,7 +48,6 @@ public static function getInfo() {
   protected function setUp() {
     parent::setUp();
 
-    $this->installSchema('language', 'language');
     // This is needed for language_default().
     // @todo remove this when language_default() no longer needs variable_get().
     $this->installSchema('system', 'variable');
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationTest.php
index 770337c..4bce384 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationTest.php
@@ -159,7 +159,16 @@ protected function checkConfigurableLanguageWeight($state = 'by default') {
    *   Maximum weight of configurable languages.
    */
   protected function getHighestConfigurableLanguageWeight(){
-    return db_query('SELECT MAX(weight) FROM {language} WHERE locked = 0')->fetchField();
+    $max_weight = 0;
+
+    $languages = entity_load_multiple('language_entity', NULL, TRUE);
+    foreach ($languages as $language) {
+      if (!$language->locked && $language->weight > $max_weight) {
+        $max_weight = $language->weight;
+      }
+    }
+
+    return $max_weight;
   }
 
 }
diff --git a/core/modules/language/lib/Drupal/language/Tests/Views/LanguageTestBase.php b/core/modules/language/lib/Drupal/language/Tests/Views/LanguageTestBase.php
index 9057a5a..978c8dc 100644
--- a/core/modules/language/lib/Drupal/language/Tests/Views/LanguageTestBase.php
+++ b/core/modules/language/lib/Drupal/language/Tests/Views/LanguageTestBase.php
@@ -24,7 +24,6 @@
 
   protected function setUp() {
     parent::setUp();
-    $this->installSchema('language', 'language');
     $this->installSchema('system', 'variable');
 
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
index 9733be6..99520e9 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
@@ -31,7 +31,6 @@ function setUp() {
     parent::setUp();
     $this->installSchema('user', array('role_permission', 'users_roles'));
     $this->installSchema('system', array('variable', 'url_alias'));
-    $this->installSchema('language', 'language');
 
     // Create the default languages.
     $default_language = language_save(language_default());
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php
index 8b5b19b..11c26d4 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityQueryTest.php
@@ -56,7 +56,6 @@ public static function getInfo() {
   function setUp() {
     parent::setUp();
     $this->installSchema('entity_test', array('entity_test_mulrev', 'entity_test_mulrev_property_data', 'entity_test_mulrev_property_revision'));
-    $this->installSchema('language', array('language'));
     $this->installSchema('system', array('variable'));
     $figures = drupal_strtolower($this->randomName());
     $greetings = drupal_strtolower($this->randomName());
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
index 919565c..d75c711 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
@@ -31,7 +31,6 @@ public static function getInfo() {
   function setUp() {
     parent::setUp();
     $this->installSchema('system', 'variable');
-    $this->installSchema('language', 'language');
     $this->installSchema('entity_test', array(
       'entity_test_mul',
       'entity_test_mul_property_data',
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/DependencyTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/DependencyTest.php
index 96955cd..b88e0bf 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/DependencyTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/DependencyTest.php
@@ -39,8 +39,9 @@ function testEnableWithoutDependency() {
 
     $this->assertModules(array('translation_entity', 'language'), TRUE);
 
-    // Assert that the language tables were enabled.
-    $this->assertTableCount('language', TRUE);
+    // Assert that the language YAML files were created.
+    $storage = $this->container->get('config.storage');
+    $this->assertTrue(count($storage->listAll('language.entity.')) > 0, 'Language config entity files exist.');
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php
index ba62946..d213be8 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php
@@ -42,6 +42,21 @@ public function testLanguageUpgrade() {
     db_update('users')->fields(array('language' => 'ca'))->condition('uid', '1')->execute();
     $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
 
+    // Check that the configuration for the 'Catalan' language is correct.
+    $config = \Drupal::config('language.entity.ca')->get();
+    // We cannot predict the value of the UUID, we just check it's present.
+    $this->assertFalse(empty($config['uuid']));
+    unset($config['uuid']);
+    $this->assertEqual($config, array(
+      'id' => 'ca',
+      'label' => 'Catalan',
+      'direction' => 0,
+      'weight' => 0,
+      'locked' => 0,
+      'status' => 1,
+      'langcode' => Language::LANGCODE_NOT_SPECIFIED,
+    ));
+
     // Ensure Catalan was properly upgraded to be the new default language.
     $this->assertTrue(language_default()->langcode == 'ca', 'Catalan is the default language');
     $languages = language_list(Language::STATE_ALL);
diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php
index 78e768c..d81446d 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Handler/HandlerAllTest.php
@@ -33,7 +33,6 @@ class HandlerAllTest extends HandlerTestBase {
     'file',
     'forum',
     'history',
-    'language',
     'locale',
     'node',
     'search',
diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/WizardPluginBaseUnitTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/WizardPluginBaseUnitTest.php
index b191e9a..20c0109 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Wizard/WizardPluginBaseUnitTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/WizardPluginBaseUnitTest.php
@@ -43,7 +43,6 @@ public static function getInfo() {
   protected function setUp() {
     parent::setUp();
 
-    $this->installSchema('language', 'language');
     $this->installSchema('system', 'variable');
 
     $this->enableModules(array('views_ui'));
