diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc
index a7257c7..510dd64 100644
--- a/includes/bootstrap.inc
+++ b/includes/bootstrap.inc
@@ -2599,7 +2599,7 @@ function language_list($field = 'language') {
   if (!isset($languages)) {
     $default = language_default();
     if (drupal_multilingual() || module_exists('locale')) {
-      $languages['language'] = db_query('SELECT * FROM {languages} ORDER BY weight ASC, name ASC')->fetchAllAssoc('language');
+      $languages['language'] = db_query('SELECT * FROM {language} ORDER BY weight ASC, name ASC')->fetchAllAssoc('language');
       // Users cannot uninstall the native English language. However, we allow
       // it to be hidden from the installed languages. Therefore, at least one
       // other language must be enabled then.
diff --git a/includes/gettext.inc b/includes/gettext.inc
index a3d2a7c..ce5dfe4 100644
--- a/includes/gettext.inc
+++ b/includes/gettext.inc
@@ -397,7 +397,7 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
           // Get the plural formula and update in database.
           if (isset($header["Plural-Forms"]) && $p = _locale_import_parse_plural_forms($header["Plural-Forms"], $file->uri)) {
             list($nplurals, $plural) = $p;
-            db_update('languages')
+            db_update('language')
               ->fields(array(
                 'plurals' => $nplurals,
                 'formula' => $plural,
@@ -406,7 +406,7 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
               ->execute();
           }
           else {
-            db_update('languages')
+            db_update('language')
               ->fields(array(
                 'plurals' => 0,
                 'formula' => '',
diff --git a/includes/install.core.inc b/includes/install.core.inc
index 7405f9f..f8fd0c1 100644
--- a/includes/install.core.inc
+++ b/includes/install.core.inc
@@ -1133,7 +1133,7 @@ function install_find_locales($profilename) {
   foreach ($locales as $key => $locale) {
     // The locale (file name) might be drupal-7.2.cs.po instead of cs.po.
     $locales[$key]->langcode = preg_replace('!^(.+\.)?([^\.]+)$!', '\2', $locale->name);
-    // Language codes cannot exceed 12 characters to fit into the {languages}
+    // Language codes cannot exceed 12 characters to fit into the {language}
     // table.
     if (strlen($locales[$key]->langcode) > 12) {
       unset($locales[$key]);
@@ -1398,7 +1398,7 @@ function install_import_locales(&$install_state) {
       'native' => $install_locale,
       'default' => TRUE,
     );
-    locale_language_save($language);
+    language_save($language);
   }
   else {
     // A known predefined language, details will be filled in properly.
@@ -1406,7 +1406,7 @@ function install_import_locales(&$install_state) {
       'language' => $install_locale,
       'default' => TRUE,
     );
-    locale_language_save($language);
+    language_save($language);
   }
 
   // Collect files to import for this language.
diff --git a/includes/locale.inc b/includes/locale.inc
index 906a36e..42aa2b7 100644
--- a/includes/locale.inc
+++ b/includes/locale.inc
@@ -472,68 +472,6 @@ function locale_string_is_safe($string) {
 }
 
 /**
- * API function to add or update a language.
- *
- * @param $language
- *   Language object with properties corresponding to 'languages' table columns.
- */
-function locale_language_save($language) {
-  $language->is_new = !(bool) db_query_range('SELECT 1 FROM {languages} WHERE language = :language', 0, 1, array(':language' => $language->language))->fetchField();
-  // Default prefix on language code if not provided otherwise.
-  if (!isset($language->prefix)) {
-    $language->prefix = $language->language;
-  }
-
-  // If name was not set, we add a predefined language.
-  if (!isset($language->name)) {
-    include_once DRUPAL_ROOT . '/includes/standard.inc';
-    $predefined = standard_language_list();
-    $language->name = $predefined[$language->language][0];
-    $language->native = isset($predefined[$language->language][1]) ? $predefined[$language->language][1] : $predefined[$language->language][0];
-    $language->direction = isset($predefined[$language->language][2]) ? $predefined[$language->language][2] : LANGUAGE_LTR;
-  }
-
-  // Set to enabled for the default language and unless specified otherwise.
-  if (!empty($language->default) || !isset($language->enabled)) {
-    $language->enabled = TRUE;
-  }
-  // Let other modules modify $language before saved.
-  module_invoke_all('locale_language_presave', $language);
-
-  // Save the record and inform others about the change.
-  if ($language->is_new) {
-    drupal_write_record('languages', $language);
-    module_invoke_all('locale_language_insert', $language);
-    watchdog('locale', 'The %language (%langcode) language has been created.', array('%language' => $language->name, '%langcode' => $language->language));
-  }
-  else {
-    drupal_write_record('languages', $language, array('language'));
-    module_invoke_all('locale_language_update', $language);
-    watchdog('locale', 'The %language (%langcode) language has been updated.', array('%language' => $language->name, '%langcode' => $language->language));
-  }
-
-  if (!empty($language->default)) {
-    // Set the new version of this language as default in a variable.
-    $default_language = language_default();
-    variable_set('language_default', $language);
-  }
-
-  // Update language count based on enabled language count.
-  variable_set('language_count', db_query('SELECT COUNT(language) FROM {languages} WHERE enabled = 1')->fetchField());
-
-  // Kill the static cache in language_list().
-  drupal_static_reset('language_list');
-
-  // @todo move these two cache clears out. See http://drupal.org/node/1293252
-  // Changing the language settings impacts the interface.
-  cache_clear_all('*', 'cache_page', TRUE);
-  // Force JavaScript translation file re-creation for the modified language.
-  _locale_invalidate_js($language->language);
-
-  return $language;
-}
-
-/**
  * Parses a JavaScript file, extracts strings wrapped in Drupal.t() and
  * Drupal.formatPlural() and inserts them into the database.
  */
@@ -753,7 +691,7 @@ function _locale_rebuild_js($langcode = NULL) {
   // deleted). Act only if some operation was executed that changed the hash
   // code.
   if ($status && $changed_hash) {
-    db_update('languages')
+    db_update('language')
       ->fields(array(
         'javascript' => $language->javascript,
       ))
diff --git a/modules/comment/comment.install b/modules/comment/comment.install
index 0213808..9c4a2d8 100644
--- a/modules/comment/comment.install
+++ b/modules/comment/comment.install
@@ -168,7 +168,7 @@ function comment_schema() {
         'description' => "The comment author's home page address from the comment form, if user is anonymous, and the 'Anonymous users may/must leave their contact information' setting is turned on.",
       ),
       'language' => array(
-        'description' => 'The {languages}.language of this comment.',
+        'description' => 'The {language}.language of this comment.',
         'type' => 'varchar',
         'length' => 12,
         'not null' => TRUE,
diff --git a/modules/field/field.multilingual.inc b/modules/field/field.multilingual.inc
index 4497074..4b0b1d9 100644
--- a/modules/field/field.multilingual.inc
+++ b/modules/field/field.multilingual.inc
@@ -60,23 +60,23 @@
  */
 
 /**
- * Implements hook_locale_language_insert().
+ * Implements hook_language_insert().
  */
-function field_locale_language_insert() {
+function field_language_insert() {
   field_info_cache_clear();
 }
 
 /**
- * Implements hook_locale_language_update().
+ * Implements hook_language_update().
  */
-function field_locale_language_update() {
+function field_language_update() {
   field_info_cache_clear();
 }
 
 /**
- * Implements hook_locale_language_delete().
+ * Implements hook_language_delete().
  */
-function field_locale_language_delete() {
+function field_language_delete() {
   field_info_cache_clear();
 }
 
diff --git a/modules/field/tests/field.test b/modules/field/tests/field.test
index 99eeb8a..a6d46fe 100644
--- a/modules/field/tests/field.test
+++ b/modules/field/tests/field.test
@@ -2649,7 +2649,7 @@ class FieldTranslationsTestCase extends FieldTestCase {
         'name' => $this->randomString(),
         'native' => $this->randomString(),
       );
-      locale_language_save($language);
+      language_save($language);
     }
   }
 
diff --git a/modules/language/language.api.php b/modules/language/language.api.php
new file mode 100644
index 0000000..a5369e9
--- /dev/null
+++ b/modules/language/language.api.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Hooks provided by the Language module.
+ */
+
+/**
+ * @addtogroup hooks
+ * @{
+ */
+
+
+/**
+ * React to a language about to be added or updated in the system.
+ *
+ * @param $language
+ *   A language object.
+ */
+function hook_language_presave($language) {
+  if ($language->default) {
+    // React to a new default language.
+    example_new_default_language($language);
+  }
+}
+
+/**
+ * React to a language that was just added to the system.
+ *
+ * @param $language
+ *   A language object.
+ */
+function hook_language_insert($language) {
+  example_refresh_permissions();
+}
+
+/**
+ * React to a language that was just updated in the system.
+ *
+ * @param $language
+ *   A language object.
+ */
+function hook_language_update($language) {
+  example_refresh_permissions();
+}
+
+/**
+ * Allow modules to react before the deletion of a language.
+ *
+ * @param $language
+ *   The language object of the language that is about to be deleted.
+ */
+function hook_language_delete($language) {
+  // On nodes with this language, unset the language
+  db_update('node')
+    ->fields(array('language' => ''))
+    ->condition('language', $language->language)
+    ->execute();
+}
+
+/**
+ * @} End of "addtogroup hooks".
+ */
diff --git a/modules/language/language.info b/modules/language/language.info
new file mode 100644
index 0000000..edf37b9
--- /dev/null
+++ b/modules/language/language.info
@@ -0,0 +1,6 @@
+name = Language
+description = Lets you configure a number of languages to be used on your website.
+package = Core
+version = VERSION
+core = 8.x
+configure = admin/config/regional/language
diff --git a/modules/language/language.install b/modules/language/language.install
new file mode 100644
index 0000000..6e05625
--- /dev/null
+++ b/modules/language/language.install
@@ -0,0 +1,117 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the language module.
+ */
+
+/**
+ * Implements hook_install().
+ */
+function language_install() {
+  // Add the default language to the database too.
+  language_save(language_default());
+}
+
+/**
+ * Implements hook_uninstall().
+ */
+function language_uninstall() {
+  // Clear variables.
+  variable_del('language_default');
+  variable_del('language_count');
+
+  // Switch back to English: with a $language->language value different from 'en'
+  // successive calls of t() might result in calling locale(), which in turn might
+  // try to query the unexisting {locales_source} and {locales_target} tables.
+  drupal_language_initialize();
+}
+
+/**
+ * Implements hook_schema().
+ */
+function language_schema() {
+  $schema['language'] = array(
+    'description' => 'List of all available languages in the system.',
+    'fields' => array(
+      'language' => 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 in English.',
+      ),
+      'native' => array(
+        'type' => 'varchar',
+        'length' => 64,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'Native language name.',
+      ),
+      'direction' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'Direction of language (Left-to-Right = 0, Right-to-Left = 1).',
+      ),
+      'enabled' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'Enabled flag (1 = Enabled, 0 = Disabled).',
+      ),
+      'plurals' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'Number of plural indexes in this language.',
+      ),
+      'formula' => array(
+        'type' => 'varchar',
+        'length' => 128,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'Plural formula in PHP code to evaluate to get plural indexes.',
+      ),
+      'domain' => array(
+        'type' => 'varchar',
+        'length' => 128,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'Domain to use for this language.',
+      ),
+      'prefix' => array(
+        'type' => 'varchar',
+        'length' => 128,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'Path prefix to use for this language.',
+      ),
+      'weight' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'Weight, used in lists of languages.',
+      ),
+      'javascript' => array(
+        'type' => 'varchar',
+        'length' => 64,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'Location of JavaScript translation file.',
+      ),
+    ),
+    'primary key' => array('language'),
+    'indexes' => array(
+      'list' => array('weight', 'name'),
+    ),
+  );
+  return $schema;
+}
diff --git a/modules/language/language.module b/modules/language/language.module
new file mode 100644
index 0000000..51c7e46
--- /dev/null
+++ b/modules/language/language.module
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ *   Add language handling functionality to Drupal.
+ */
+
+/**
+ * API function to add or update a language.
+ *
+ * @param $language
+ *   Language object with properties corresponding to 'language' table columns.
+ */
+function language_save($language) {
+  $language->is_new = !(bool) db_query_range('SELECT 1 FROM {language} WHERE language = :language', 0, 1, array(':language' => $language->language))->fetchField();
+  // Default prefix on language code if not provided otherwise.
+  if (!isset($language->prefix)) {
+    $language->prefix = $language->language;
+  }
+
+  // If name was not set, we add a predefined language.
+  if (!isset($language->name)) {
+    include_once DRUPAL_ROOT . '/includes/standard.inc';
+    $predefined = standard_language_list();
+    $language->name = $predefined[$language->language][0];
+    $language->native = isset($predefined[$language->language][1]) ? $predefined[$language->language][1] : $predefined[$language->language][0];
+    $language->direction = isset($predefined[$language->language][2]) ? $predefined[$language->language][2] : LANGUAGE_LTR;
+  }
+
+  // Set to enabled for the default language and unless specified otherwise.
+  if (!empty($language->default) || !isset($language->enabled)) {
+    $language->enabled = TRUE;
+  }
+  // Let other modules modify $language before saved.
+  module_invoke_all('language_presave', $language);
+
+  // Save the record and inform others about the change.
+  if ($language->is_new) {
+    drupal_write_record('language', $language);
+    module_invoke_all('language_insert', $language);
+    watchdog('language', 'The %language (%langcode) language has been created.', array('%language' => $language->name, '%langcode' => $language->language));
+  }
+  else {
+    drupal_write_record('language', $language, array('language'));
+    module_invoke_all('language_update', $language);
+    watchdog('language', 'The %language (%langcode) language has been updated.', array('%language' => $language->name, '%langcode' => $language->language));
+  }
+
+  if (!empty($language->default)) {
+    // Set the new version of this language as default in a variable.
+    $default_language = language_default();
+    variable_set('language_default', $language);
+  }
+
+  // Update language count based on enabled language count.
+  variable_set('language_count', db_query('SELECT COUNT(language) FROM {language} WHERE enabled = 1')->fetchField());
+
+  // Kill the static cache in language_list().
+  drupal_static_reset('language_list');
+
+  return $language;
+}
+
+/**
+ * Delete a language.
+ *
+ * @param $langcode
+ *   Language code of the language to be deleted.
+ * @return
+ *   TRUE if language is successfully deleted. Otherwise FALSE.
+ */
+function language_delete($langcode) {
+  $languages = language_list();
+  if (isset($languages[$langcode])) {
+    $language = $languages[$langcode];
+    module_invoke_all('language_delete', $language);
+    db_delete('language')
+      ->condition('language', $language->language)
+      ->execute();
+    if ($language->enabled) {
+      variable_set('language_count', variable_get('language_count', 1) - 1);
+    }
+    drupal_static_reset('language_list');
+    watchdog('language', 'The %language (%langcode) language has been removed.', array('%language' => $language->name, '%langcode' => $language->language));
+    return TRUE;
+  }
+  return FALSE;
+}
diff --git a/modules/locale/locale.admin.inc b/modules/locale/locale.admin.inc
index e17ed7c..370d717 100644
--- a/modules/locale/locale.admin.inc
+++ b/modules/locale/locale.admin.inc
@@ -182,7 +182,7 @@ function locale_language_overview_form_submit($form, &$form_state) {
       }
     }
 
-    locale_language_save($language);
+    language_save($language);
   }
 
   drupal_set_message(t('Configuration saved.'));
@@ -355,7 +355,7 @@ function locale_languages_add_custom_form_submit($form, &$form_state) {
     'native' => $form_state['values']['native'],
     'direction' => $form_state['values']['direction'],
   );
-  locale_language_save($language);
+  language_save($language);
   drupal_set_message(t('The language %language has been created and can now be used. More information is available on the <a href="@locale-help">help screen</a>.', array('%language' => t($form_state['values']['name']), '@locale-help' => url('admin/help/locale'))));
   locale_languages_add_set_batch($langcode);
   $form_state['redirect'] = 'admin/config/regional/language';
@@ -372,7 +372,7 @@ function locale_languages_add_predefined_form_submit($form, &$form_state) {
   $language = (object) array(
     'language' => $langcode,
   );
-  locale_language_save($language);
+  language_save($language);
   drupal_set_message(t('The language %language has been created and can now be used. More information is available on the <a href="@locale-help">help screen</a>.', array('%language' => t($predefined[$langcode][0]), '@locale-help' => url('admin/help/locale'))));
   locale_languages_add_set_batch($langcode);
   $form_state['redirect'] = 'admin/config/regional/language';
@@ -417,7 +417,7 @@ function locale_languages_edit_form_submit($form, &$form_state) {
   $language->name = $form_state['values']['name'];
   $language->native = $form_state['values']['native'];
   $language->direction = $form_state['values']['direction'];
-  locale_language_save($language);
+  language_save($language);
   $form_state['redirect'] = 'admin/config/regional/language';
 }
 
@@ -458,7 +458,7 @@ function locale_languages_delete_form_submit($form, &$form_state) {
   $languages = language_list();
   $language = $languages[$langcode];
 
-  $success = locale_language_delete($langcode);
+  $success = language_delete($langcode);
 
   if ($success) {
     $variables = array('%locale' => $language->name);
@@ -813,7 +813,7 @@ function locale_language_providers_url_form_submit($form, &$form_state) {
     }
 
     // Save the prefix and domain settings for each language.
-    locale_language_save($language);
+    language_save($language);
   }
 
   drupal_set_message(t('Configuration saved.'));
diff --git a/modules/locale/locale.api.php b/modules/locale/locale.api.php
index 7b2712e..2c97470 100644
--- a/modules/locale/locale.api.php
+++ b/modules/locale/locale.api.php
@@ -165,53 +165,6 @@ function hook_language_fallback_candidates_alter(array &$fallback_candidates) {
   $fallback_candidates = array_reverse($fallback_candidates);
 }
 
- /**
- * React to a language about to be added or updated in the system.
- *
- * @param $language
- *   A language object.
- */
-function hook_locale_language_presave($language) {
-  if ($language->default) {
-    // React to a new default language.
-    example_new_default_language($language);
-  }
-}
-
-/**
- * React to a language that was just added to the system.
- *
- * @param $language
- *   A language object.
- */
-function hook_locale_language_insert($language) {
-  example_refresh_permissions();
-}
-
-/**
- * React to a language that was just updated in the system.
- *
- * @param $language
- *   A language object.
- */
-function hook_locale_language_update($language) {
-  example_refresh_permissions();
-}
-
-/**
- * Allow modules to react before the deletion of a language.
- *
- * @param $language
- *   The language object of the language that is about to be deleted.
- */
-function hook_locale_language_delete($language) {
-  // On nodes with this language, unset the language
-  db_update('node')
-    ->fields(array('language' => ''))
-    ->condition('language', $language->language)
-    ->execute();
-}
-
 /**
  * @} End of "addtogroup hooks".
  */
diff --git a/modules/locale/locale.bulk.inc b/modules/locale/locale.bulk.inc
index 51f80a6..e2449aa 100644
--- a/modules/locale/locale.bulk.inc
+++ b/modules/locale/locale.bulk.inc
@@ -73,7 +73,7 @@ function locale_translate_import_form_submit($form, &$form_state) {
       $language = (object) array(
         'language' => $langcode,
       );
-      locale_language_save($language);
+      language_save($language);
       drupal_set_message(t('The language %language has been created.', array('%language' => t($predefined[$langcode][0]))));
     }
 
diff --git a/modules/locale/locale.info b/modules/locale/locale.info
index 748d274..28bbd03 100644
--- a/modules/locale/locale.info
+++ b/modules/locale/locale.info
@@ -1,7 +1,7 @@
 name = Locale
-description = Adds language handling functionality and enables the translation of the user interface to languages other than English.
+description = Provides language negotiation functionality and user interface translation to languages other than English.
 package = Core
 version = VERSION
 core = 8.x
+dependencies[] = language
 files[] = locale.test
-configure = admin/config/regional/language
diff --git a/modules/locale/locale.install b/modules/locale/locale.install
index 7fbc81d..f553b35 100644
--- a/modules/locale/locale.install
+++ b/modules/locale/locale.install
@@ -6,27 +6,6 @@
  */
 
 /**
- * Implements hook_install().
- */
-function locale_install() {
-  // locales_source.source and locales_target.target are not used as binary
-  // fields; non-MySQL database servers need to ensure the field type is text
-  // and that LIKE produces a case-sensitive comparison.
-
-  db_insert('languages')
-    ->fields(array(
-      'language' => 'en',
-      'name' => 'English',
-      'native' => 'English',
-      'direction' => 0,
-      'enabled' => 1,
-      'weight' => 0,
-      'javascript' => '',
-    ))
-    ->execute();
-}
-
-/**
  * Implements hook_uninstall().
  */
 function locale_uninstall() {
@@ -34,7 +13,7 @@ function locale_uninstall() {
   $locale_js_directory = 'public://' . variable_get('locale_js_directory', 'languages');
 
   if (is_dir($locale_js_directory)) {
-    $files = db_query('SELECT language, javascript FROM {languages}');
+    $files = db_query('SELECT language, javascript FROM {language}');
     foreach ($files as $file) {
       if (!empty($file->javascript)) {
         file_unmanaged_delete($locale_js_directory . '/' . $file->language . '_' . $file->javascript . '.js');
@@ -47,8 +26,6 @@ function locale_uninstall() {
   }
 
   // Clear variables.
-  variable_del('language_default');
-  variable_del('language_count');
   variable_del('language_types');
   variable_del('locale_language_negotiation_url_part');
   variable_del('locale_language_negotiation_session_param');
@@ -68,101 +45,12 @@ function locale_uninstall() {
   foreach (node_type_get_types() as $type => $content_type) {
     $setting = variable_del("language_content_type_$type");
   }
-
-  // Switch back to English: with a $language->language value different from 'en'
-  // successive calls of t() might result in calling locale(), which in turn might
-  // try to query the unexisting {locales_source} and {locales_target} tables.
-  drupal_language_initialize();
-
 }
 
 /**
  * Implements hook_schema().
  */
 function locale_schema() {
-  $schema['languages'] = array(
-    'description' => 'List of all available languages in the system.',
-    'fields' => array(
-      'language' => 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 in English.',
-      ),
-      'native' => array(
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Native language name.',
-      ),
-      'direction' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Direction of language (Left-to-Right = 0, Right-to-Left = 1).',
-      ),
-      'enabled' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Enabled flag (1 = Enabled, 0 = Disabled).',
-      ),
-      'plurals' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Number of plural indexes in this language.',
-      ),
-      'formula' => array(
-        'type' => 'varchar',
-        'length' => 128,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Plural formula in PHP code to evaluate to get plural indexes.',
-      ),
-      'domain' => array(
-        'type' => 'varchar',
-        'length' => 128,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Domain to use for this language.',
-      ),
-      'prefix' => array(
-        'type' => 'varchar',
-        'length' => 128,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Path prefix to use for this language.',
-      ),
-      'weight' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Weight, used in lists of languages.',
-      ),
-      'javascript' => array(
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Location of JavaScript translation file.',
-      ),
-    ),
-    'primary key' => array('language'),
-    'indexes' => array(
-      'list' => array('weight', 'name'),
-    ),
-  );
-
   $schema['locales_source'] = array(
     'description' => 'List of English source strings.',
     'fields' => array(
@@ -224,7 +112,7 @@ function locale_schema() {
         'length' => 12,
         'not null' => TRUE,
         'default' => '',
-        'description' => 'Language code. References {languages}.language.',
+        'description' => 'Language code. References {language}.language.',
       ),
       'plid' => array(
         'type' => 'int',
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index 2037c35..1da2368 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -605,6 +605,43 @@ function locale_modules_disabled($modules) {
   locale_modules_enabled($modules);
 }
 
+/**
+ * Implements hook_language_insert().
+ */
+function locale_language_insert($language) {
+  // @todo move these two cache clears out. See http://drupal.org/node/1293252
+  // Changing the language settings impacts the interface.
+  cache('page')->flush();
+  // Force JavaScript translation file re-creation for the modified language.
+  _locale_invalidate_js($language->language);
+}
+
+/**
+ * Implements hook_language_update().
+ */
+function locale_language_update($language) {
+  locale_language_insert($language);
+}
+
+/**
+ * Implements hook_language_delete().
+ */
+function locale_language_delete($language) {
+  // Remove translations first.
+  db_delete('locales_target')
+    ->condition('language', $language->language)
+    ->execute();
+
+  _locale_invalidate_js($language->language);
+
+  // Changing the language settings impacts the interface.
+  cache('page')->flush();
+
+  // Clearing all locale cache from database
+  cache()->delete('locale:' . $language->language);
+}
+
+
 // ---------------------------------------------------------------------------------
 // Locale core functionality
 
@@ -783,51 +820,6 @@ function locale_language_list($field = 'name', $all = FALSE) {
 }
 
 /**
- * Delete a language.
- *
- * @param $langcode
- *   Language code of the language to be deleted.
- * @return
- *   TRUE if language is successfully deleted. Otherwise FALSE.
- */
-function locale_language_delete($langcode) {
-  $languages = language_list();
-  if (isset($languages[$langcode])) {
-    $language = $languages[$langcode];
-
-    module_invoke_all('locale_language_delete', $language);
-
-    // Remove translations first.
-    db_delete('locales_target')
-      ->condition('language', $language->language)
-      ->execute();
-
-    // Remove the language.
-    db_delete('languages')
-      ->condition('language', $language->language)
-      ->execute();
-
-    if ($language->enabled) {
-      variable_set('language_count', variable_get('language_count', 1) - 1);
-    }
-
-    drupal_static_reset('language_list');
-    _locale_invalidate_js($language->language);
-
-    // Changing the language settings impacts the interface:
-    cache('page')->flush();
-
-    // Clearing all locale cache from database
-    cache()->delete('locale:' . $language->language);
-
-    $variables = array('%locale' => $language->name);
-    watchdog('locale', 'The language %locale has been removed.', $variables);
-    return TRUE;
-  }
-  return FALSE;
-}
-
-/**
  * Implements hook_modules_installed().
  */
 function locale_modules_installed($modules) {
diff --git a/modules/locale/locale.test b/modules/locale/locale.test
index b94f565..9b62da7 100644
--- a/modules/locale/locale.test
+++ b/modules/locale/locale.test
@@ -420,7 +420,7 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
 
     // Retrieve the JavaScript translation hash code for the custom language to
     // check that the translation file has been properly built.
-    $file = db_select('languages', 'l')
+    $file = db_select('language', 'l')
       ->fields('l', array('javascript'))
       ->condition('language', $langcode)
       ->execute()
@@ -681,7 +681,7 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 9, '%update' => 0, '%delete' => 0)), t('The translation file was successfully imported.'));
 
     // This import should have saved plural forms to have 2 variants.
-    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 2, t('Plural number initialized.'));
+    $this->assert(db_query("SELECT plurals FROM {language} WHERE language = 'fr'")->fetchField() == 2, t('Plural number initialized.'));
 
     // Ensure we were redirected correctly.
     $this->assertEqual($this->getUrl(), url('admin/config/regional/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
@@ -727,7 +727,7 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->assertText(t('No strings available.'), t('String not overwritten by imported string.'));
 
     // This import should not have changed number of plural forms.
-    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 2, t('Plural numbers untouched.'));
+    $this->assert(db_query("SELECT plurals FROM {language} WHERE language = 'fr'")->fetchField() == 2, t('Plural numbers untouched.'));
 
     // Try importing a .po file with overriding strings, and ensure existing
     // strings are overwritten.
@@ -747,7 +747,7 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), t('String overwritten by imported string.'));
     // This import should have changed number of plural forms.
-    $this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 3, t('Plural numbers changed.'));
+    $this->assert(db_query("SELECT plurals FROM {language} WHERE language = 'fr'")->fetchField() == 3, t('Plural numbers changed.'));
   }
 
   /**
@@ -1142,7 +1142,7 @@ class LocaleUninstallFunctionalTest extends DrupalWebTestCase {
    * Check if the values of the Locale variables are correct after uninstall.
    */
   function testUninstallProcess() {
-    $locale_module = array('locale');
+    $locale_module = array('locale', 'language');
 
     // Add a new language and optionally set it as default.
     require_once DRUPAL_ROOT . '/includes/locale.inc';
@@ -1153,7 +1153,7 @@ class LocaleUninstallFunctionalTest extends DrupalWebTestCase {
       'native' => 'Français',
       'default' => $this->language == 'fr',
     );
-    locale_language_save($language);
+    language_save($language);
 
     // Check the UI language.
     drupal_language_initialize();
@@ -1175,7 +1175,7 @@ class LocaleUninstallFunctionalTest extends DrupalWebTestCase {
     $edit = array('translations[fr]' => 'french translation');
     $this->drupalPost('admin/config/regional/translate/edit/' . $string->lid, $edit, t('Save translations'));
     _locale_rebuild_js('fr');
-    $file = db_query('SELECT javascript FROM {languages} WHERE language = :language', array(':language' => 'fr'))->fetchObject();
+    $file = db_query('SELECT javascript FROM {language} WHERE language = :language', array(':language' => 'fr'))->fetchObject();
     $js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/fr_' . $file->javascript . '.js';
     $this->assertTrue($result = file_exists($js_file), t('JavaScript file created: %file', array('%file' => $result ? $js_file : t('none'))));
 
@@ -1984,11 +1984,11 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
     $language = (object) array(
       'language' => $langcode_browser_fallback,
     );
-    locale_language_save($language);
+    language_save($language);
     $language = (object) array(
       'language' => $langcode,
     );
-    locale_language_save($language);
+    language_save($language);
 
     // We will look for this string in the admin/config screen to see if the
     // corresponding translated string is shown.
@@ -2133,7 +2133,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
     $language = (object) array(
       'language' => $langcode_browser_fallback,
     );
-    locale_language_save($language);
+    language_save($language);
     $languages = language_list();
 
     // Enable the path prefix for the default language: this way any unprefixed
@@ -2280,7 +2280,7 @@ class LocaleMultilingualFieldsFunctionalTest extends DrupalWebTestCase {
       'name' => 'Italian',
       'native' => 'Italiano',
     );
-    locale_language_save($language);
+    language_save($language);
 
     // Enable URL language detection and selection.
     $edit = array('language[enabled][locale-url]' => '1');
diff --git a/modules/node/node.install b/modules/node/node.install
index 3f732a4..dcef82a 100644
--- a/modules/node/node.install
+++ b/modules/node/node.install
@@ -33,7 +33,7 @@ function node_schema() {
         'default' => '',
       ),
       'language' => array(
-        'description' => 'The {languages}.language of this node.',
+        'description' => 'The {language}.language of this node.',
         'type' => 'varchar',
         'length' => 12,
         'not null' => TRUE,
diff --git a/modules/node/node.module b/modules/node/node.module
index 0c3cfb7..69332ff 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -3948,9 +3948,9 @@ function node_file_download_access($field, $entity_type, $entity) {
 }
 
 /**
- * Implements hook_locale_language_delete().
+ * Implements hook_language_delete().
  */
-function node_locale_language_delete($language) {
+function node_language_delete($language) {
   // On nodes with this language, unset the language
   db_update('node')
     ->fields(array('language' => ''))
diff --git a/modules/system/system.install b/modules/system/system.install
index 24933e2..4d2e0bb 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -770,7 +770,7 @@ function system_schema() {
         'not null' => TRUE,
       ),
       'language' => array(
-        'description' => 'A {languages}.language for this format to be used with.',
+        'description' => 'A {language}.language for this format to be used with.',
         'type' => 'varchar',
         'length' => 12,
         'not null' => TRUE,
diff --git a/modules/system/system.test b/modules/system/system.test
index f84bc78..5a205b3 100644
--- a/modules/system/system.test
+++ b/modules/system/system.test
@@ -379,10 +379,10 @@ class ModuleDependencyTestCase extends ModuleTestCase {
     $this->drupalPost('admin/modules', $edit, t('Save configuration'));
     $this->assertText(t('Some required modules must be enabled'), t('Dependency required.'));
 
-    $this->assertModules(array('translation', 'locale'), FALSE);
+    $this->assertModules(array('translation', 'locale', 'language'), FALSE);
 
     // Assert that the locale tables weren't enabled.
-    $this->assertTableCount('languages', FALSE);
+    $this->assertTableCount('language', FALSE);
     $this->assertTableCount('locale', FALSE);
 
     $this->drupalPost(NULL, NULL, t('Continue'));
@@ -391,7 +391,7 @@ class ModuleDependencyTestCase extends ModuleTestCase {
     $this->assertModules(array('translation', 'locale'), TRUE);
 
     // Assert that the locale tables were enabled.
-    $this->assertTableCount('languages', TRUE);
+    $this->assertTableCount('language', TRUE);
     $this->assertTableCount('locale', TRUE);
   }
 
@@ -1219,7 +1219,7 @@ class DateTimeFunctionalTest extends DrupalWebTestCase {
       'language' => 'de',
       'default' => TRUE,
     );
-    locale_language_save($language);
+    language_save($language);
 
     $date_format = array(
       'type' => 'short',
