diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 25e9b9a..6232cbc 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -2709,14 +2709,22 @@ function language_list($flags = LANGUAGE_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. Always reset the entity
+      // cache as the language objects are statically cached.
+      $language_entities = entity_load_multiple('language', NULL, TRUE);
+      uasort($language_entities, 'language_entity_sort');
 
       // 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' => ($langcode == $default->langcode),
+          'name' => $info->name,
+          'langcode' => $langcode,
+          '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 24b7063..ee338a3 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 b40bffa..a24ddb4 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 b16c53b..90f8b86 100644
--- a/core/modules/language/language.install
+++ b/core/modules/language/language.install
@@ -5,6 +5,8 @@
  * Install, update and uninstall functions for the language module.
  */
 
+use Drupal\Component\Uuid\Uuid;
+
 /**
  * Implements hook_install().
  *
@@ -51,55 +53,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() {
@@ -117,3 +70,32 @@ function language_disable() {
   // will be FALSE, because the language module is disabled.
   variable_set('language_count', 1);
 }
+
+/**
+ * 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('langcode', $language->langcode)
+      ->set('name', $language->name)
+      ->set('direction', $language->direction)
+      ->set('weight', $language->weight)
+      ->set('locked', $language->locked)
+      ->set('langcode', LANGUAGE_NOT_SPECIFIED)
+      ->set('uuid', $uuid->generate())
+      ->save();
+
+    $manifest_ids[] = $language->langcode;
+  }
+
+  if (!empty($manifest_ids)) {
+    update_config_manifest_add('language.entity', $manifest_ids);
+  }
+}
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 476246f..fdad72b 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -209,6 +209,18 @@ function language_entity_supported() {
 }
 
 /**
+ * Helper callback for uasort() to sort configuration entities by weight and label.
+ */
+function language_entity_sort($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->name, $b->name);
+  }
+  return ($a_weight < $b_weight) ? -1 : 1;
+}
+
+/**
  * Implements hook_element_info_alter().
  */
 function language_element_info_alter(&$type) {
@@ -469,23 +481,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', $language->langcode);
+  if (!$language_entity) {
+    $language->is_new = TRUE;
+    $language_entity = entity_create('language', array(
+      'langcode' => $language->langcode,
+    ));
+  }
+  else {
+    $language->is_new = FALSE;
+  }
 
   // Let other modules modify $language before saved.
   module_invoke_all('language_presave', $language);
 
+  $language_entity->name = 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);
   }
@@ -521,7 +547,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', NULL, TRUE);
+  foreach ($languages as $language) {
+    if (!$language->locked) {
+      $count++;
+    }
+  }
+  variable_set('language_count', $count);
 }
 
 /**
@@ -541,9 +574,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', array($language->langcode));
 
     language_update_count();
 
@@ -850,16 +881,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', 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_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/Plugin/Core/Entity/Language.php b/core/modules/language/lib/Drupal/language/Plugin/Core/Entity/Language.php
new file mode 100644
index 0000000..b3af000
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/Plugin/Core/Entity/Language.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field\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;
+
+/**
+ * Defines the Language entity.
+ *
+ * @EntityType(
+ *   id = "language",
+ *   label = @Translation("Language"),
+ *   module = "language",
+ *   controllers = {
+ *     "storage" = "Drupal\Core\Config\Entity\ConfigStorageController"
+ *   },
+ *   config_prefix = "language.entity",
+ *   entity_keys = {
+ *     "id" = "langcode",
+ *     "label" = "name",
+ *     "uuid" = "uuid"
+ *   }
+ * )
+ */
+class Language extends ConfigEntityBase {
+
+  /**
+   * The language ID (machine name).
+   *
+   * @var string
+   */
+  public $langcode;
+
+  /**
+   * 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 $name;
+
+  /**
+   * 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;
+
+  /**
+   * Overrides Drupal\Core\Entity\Entity::id().
+   */
+  public function id() {
+    return $this->langcode;
+  }
+
+}
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 b2d0bda..8d5f44d 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationTest.php
@@ -158,7 +158,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', 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 c29e4f3..71e2601 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/EntityTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
index f5c1c52..003b3ac 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 e561ab7..7380c20 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 = drupal_container()->get('config.storage');
+    $this->assertTrue(count($storage->listAll('language.entity.')) > 0, 'Language config entity files exist.');
   }
 
   /**
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 529d4f1..8d1e36e 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'));
