diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index f65ab4c..4f6235f 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -207,6 +207,13 @@ const LANGUAGE_NOT_APPLICABLE = 'zxx';
 const LANGUAGE_MULTIPLE = 'mul';
 
 /**
+ * The language code used when referring to all languages.
+ *
+ * @todo W3C uses this for 'Allar', need to find a better code.
+ */
+const LANGUAGE_ALL = 'all';
+
+/**
  * The type of language used to define the content language.
  */
 const LANGUAGE_TYPE_CONTENT = 'language_content';
@@ -232,6 +239,11 @@ const LANGUAGE_LTR = 0;
 const LANGUAGE_RTL = 1;
 
 /**
+ * Flag for language list extension to add locked languages.
+ */
+const LANGUAGE_ADD_LOCKED = 2;
+
+/**
  * Time of the current request in seconds elapsed since the Unix Epoch.
  *
  * This differs from $_SERVER['REQUEST_TIME'], which is stored as a float
@@ -2572,32 +2584,48 @@ function language_multilingual() {
 /**
  * Returns a list of configured languages.
  *
+ * @param $flags
+ *   (optional) A flag of LANGUAGE_ADD_LOCKED depending on the need for locked
+ *   (special) languages in the returned list.
+ *
  * @return
  *   An associative array of languages, keyed by the language code, ordered by
  *   weight ascending and name ascending.
  */
-function language_list() {
+function language_list($flags = NULL) {
+
   $languages = &drupal_static(__FUNCTION__);
+
   // Initialize master language list.
   if (!isset($languages)) {
+    // Initialize local language list cache.
+    $languages = array();
+
+    // 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');
+      $languages = db_query('SELECT *, 0 as `default` FROM {language} ORDER BY weight ASC, name ASC')->fetchAllAssoc('langcode');
+      $languages[$default->langcode]->default = 1;
     }
     else {
       // No language module, so use the default language only.
-      $languages = array($default->langcode => $default);
+      $languages[$default->langcode] = $default;
     }
+  }
 
-    // Initialize default property so callers have an easy reference and can
-    // save the same object without data loss.
-    foreach ($languages as $langcode => $language) {
-      $languages[$langcode]->default = ($langcode == $default->langcode);
+  // Filter the full list of languages based on the criteria in $flags. By
+  // default we remove the disabled and locked languages, but the caller may
+  // request for those languages to be added as well.
+  $filtered_languages = array();
+  foreach ($languages as $langcode => $language) {
+    if ($language->locked && !($flags & LANGUAGE_ADD_LOCKED)) {
+      continue;
     }
+    $filtered_languages[$langcode] = $language;
   }
 
-  return $languages;
+  return $filtered_languages;
 }
 
 /**
@@ -2610,7 +2638,7 @@ function language_list() {
  *   A fully-populated language object or FALSE.
  */
 function language_load($langcode) {
-  $languages = language_list();
+  $languages = language_list(LANGUAGE_ADD_LOCKED);
   return isset($languages[$langcode]) ? $languages[$langcode] : FALSE;
 }
 
@@ -2649,6 +2677,7 @@ function language_default() {
     'name' => 'English',
     'direction' => 0,
     'weight' => 0,
+    'locked' => 0,
   ));
   $default->default = TRUE;
   return $default;
diff --git a/core/includes/update.inc b/core/includes/update.inc
index fb6f450..2454e0e 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -189,37 +189,68 @@ function update_prepare_d8_language() {
     // Update language count.
     variable_set('language_count', db_query('SELECT COUNT(language) FROM {languages}')->fetchField());
 
-    // Rename the languages table to language.
-    db_rename_table('languages', 'language');
-
-    // Install/enable the language module. We need to use the update specific
-    // version of this function to ensure schema conflicts don't happen due to
-    // our updated data.
-    $modules = array('language');
-    update_module_add_to_system($modules);
-    update_module_enable($modules);
-
-    // Rename 'language' column to 'langcode'.
-    db_drop_primary_key('language');
-    $langcode_spec = array(
-      'type' => 'varchar',
-      'length' => 12,
-      'not null' => TRUE,
-      'default' => '',
-      'description' => "Language code, e.g. 'de' or 'en-US'.",
-    );
-    db_change_field('language', 'language', 'langcode', $langcode_spec, array('primary key' => array('langcode')));
+    // Rename language column to langcode and set it again as the primary key.
+    if (db_field_exists('language', 'language')) {
+      db_drop_primary_key('language');
+      $langcode_spec = array(
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => "Language code, e.g. 'de' or 'en-US'.",
+      );
+      db_change_field('language', 'language', 'langcode', $langcode_spec, array('primary key' => array('langcode')));
+    }
 
-    // Update the 'language_default' system variable with the langcode change.
+    // Update the 'language_default' system variable, if configured.
     $language_default = variable_get('language_default');
-    if (!empty($language_default)) {
-      if (isset($language_default->language)) {
-        $language_default->langcode = $language_default->language;
-        unset($language_default->language);
-      }
-      unset($language_default->enabled);
+    if (!empty($language_default) && isset($language_default->language)) {
+      $language_default->langcode = $language_default->language;
+      unset($language_default->language);
       variable_set('language_default', $language_default);
     }
+
+    // Adds the locked column and saves the special languages.
+    if (!db_field_exists('language', 'locked')) {
+      $locked_spec = array(
+        'type' => 'int',
+        'size' => 'tiny',
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'A boolean indicating whether the administrator can edit or delete the language.',
+      );
+      db_add_field('language', 'locked', $locked_spec);
+
+      $max_weight = db_query('SELECT MAX(weight) FROM {language}')->fetchField();
+      $languages = array();
+      $languages[LANGUAGE_NOT_SPECIFIED] = array(
+        'langcode' => LANGUAGE_NOT_SPECIFIED,
+        'name' => 'Not specified',
+        'weight' => ++$max_weight,
+      );
+      $languages[LANGUAGE_NOT_APPLICABLE] = array(
+        'langcode' => LANGUAGE_NOT_APPLICABLE,
+        'name' => 'Not applicable',
+        'weight' => ++$max_weight,
+      );
+      $languages[LANGUAGE_MULTIPLE] = array(
+        'langcode' => LANGUAGE_MULTIPLE,
+        'name' => 'Multiple',
+        'weight' => ++$max_weight,
+      );
+      foreach ($languages as $language) {
+        db_insert('language')
+          ->fields(array(
+            'langcode' => $language['langcode'],
+            'name' => $language['name'],
+            'weight' => $language['weight'],
+            // These languages are locked, default to enabled.
+            'locked' => 1,
+            'enabled' => 1,
+          ))
+          ->execute();
+      }
+    }
   }
 }
 
diff --git a/core/lib/Drupal/Core/Language/Language.php b/core/lib/Drupal/Core/Language/Language.php
index 9b9223d..86bc8d3 100644
--- a/core/lib/Drupal/Core/Language/Language.php
+++ b/core/lib/Drupal/Core/Language/Language.php
@@ -21,7 +21,6 @@ class Language {
   public $name = 'English';
   public $langcode = 'en';
   public $direction = 0;
-  public $enabled = 1;
   public $weight = 0;
   public $default = FALSE;
   public $method_id = NULL;
diff --git a/core/modules/block/block.admin.inc b/core/modules/block/block.admin.inc
index 2b98d2a..48f618e 100644
--- a/core/modules/block/block.admin.inc
+++ b/core/modules/block/block.admin.inc
@@ -418,9 +418,9 @@ function block_admin_configure($form, &$form_state, $module, $delta) {
       $default_language_type = $setting->type;
     }
 
-    // Fetch the enabled languages.
-    $enabled_languages = language_list(TRUE);
-    foreach ($enabled_languages as $language) {
+    // Fetch languages.
+    $languages = language_list(LANGUAGE_ADD_LOCKED);
+    foreach ($languages as $language) {
       // @TODO $language->name is not wrapped with t(), it should be replaced
       // by CMI translation implementation.
       $langcodes_options[$language->langcode] = $language->name;
diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc
index f054bf1..c4a947e 100644
--- a/core/modules/field/field.multilingual.inc
+++ b/core/modules/field/field.multilingual.inc
@@ -165,14 +165,14 @@ function _field_language_suggestion($available_langcodes, $langcode_suggestion,
 /**
  * Returns available content language codes.
  *
- * The language codes that may be associated to fields include
- * LANGUAGE_NOT_SPECIFIED.
+ * The languages that may be associated to fields may include
+ * LANGUAGE_NOT_SPECIFIED, LANGUAGE_NOT_APPLICABLE and LANGUAGE_MULTIPLE.
  *
  * @return
  *   An array of language codes.
  */
 function field_content_languages() {
-  return array_keys(language_list() + array(LANGUAGE_NOT_SPECIFIED => NULL));
+  return array_keys(language_list(LANGUAGE_ADD_LOCKED));
 }
 
 /**
@@ -243,8 +243,8 @@ function field_has_translation_handler($entity_type, $handler = NULL) {
  *   A valid language code.
  */
 function field_valid_language($langcode, $default = TRUE) {
-  $enabled_languages = field_content_languages();
-  if (in_array($langcode, $enabled_languages)) {
+  $languages = field_content_languages();
+  if (in_array($langcode, $languages)) {
     return $langcode;
   }
   global $language_content;
diff --git a/core/modules/field/tests/field.test b/core/modules/field/tests/field.test
index 9a850d9..226209a 100644
--- a/core/modules/field/tests/field.test
+++ b/core/modules/field/tests/field.test
@@ -2749,11 +2749,11 @@ class FieldTranslationsTestCase extends FieldTestCase {
 
     // Test hook_field_languages() invocation on a translatable field.
     variable_set('field_test_field_available_languages_alter', TRUE);
-    $enabled_langcodes = field_content_languages();
+    $langcodes = field_content_languages();
     $available_langcodes = field_available_languages($this->entity_type, $this->field);
     foreach ($available_langcodes as $delta => $langcode) {
       if ($langcode != 'xx' && $langcode != 'en') {
-        $this->assertTrue(in_array($langcode, $enabled_langcodes), t('%language is an enabled language.', array('%language' => $langcode)));
+        $this->assertTrue(in_array($langcode, $langcodes), t('%language is an enabled language.', array('%language' => $langcode)));
       }
     }
     $this->assertTrue(in_array('xx', $available_langcodes), t('%language was made available.', array('%language' => 'xx')));
@@ -2952,7 +2952,7 @@ class FieldTranslationsTestCase extends FieldTestCase {
       do {
         // Index 0 is reserved for the requested language, this way we ensure
         // that no field is actually populated with it.
-        $langcode = $enabled_langcodes[mt_rand(1, count($enabled_langcodes) - 1)];
+        $langcode = $langcodes[mt_rand(1, count($langcodes) - 1)];
       }
       while (isset($langcodes[$langcode]));
       $langcodes[$langcode] = TRUE;
@@ -2962,7 +2962,7 @@ class FieldTranslationsTestCase extends FieldTestCase {
     // Test multiple-fields display languages for untranslatable entities.
     field_test_entity_info_translatable($entity_type, FALSE);
     drupal_static_reset('field_language');
-    $requested_langcode = $enabled_langcodes[0];
+    $requested_langcode = $langcodes[0];
     $display_langcodes = field_language($entity_type, $entity, NULL, $requested_langcode);
     foreach ($instances as $instance) {
       $field_name = $instance['field_name'];
diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc
index c124b9e..8251114 100644
--- a/core/modules/language/language.admin.inc
+++ b/core/modules/language/language.admin.inc
@@ -10,7 +10,7 @@
  */
 function language_admin_overview_form($form, &$form_state) {
   drupal_static_reset('language_list');
-  $languages = language_list();
+  $languages = language_list(LANGUAGE_ADD_LOCKED);
   $default = language_default();
 
   $form['languages'] = array(
@@ -28,8 +28,24 @@ function language_admin_overview_form($form, &$form_state) {
 
   foreach ($languages as $langcode => $language) {
     $form['languages'][$langcode]['#weight'] = $language->weight;
+    $title = check_plain($language->name);
+    $description = '';
+    switch ($langcode) {
+      case LANGUAGE_NOT_APPLICABLE:
+        $description = t('For language independent content.');
+        break;
+      case LANGUAGE_NOT_SPECIFIED:
+        $description = t('Use this when the language is not (yet) known.');
+        break;
+      case LANGUAGE_MULTIPLE:
+        $description = t('Use this when multiple languages can be assigned, such as a multilingual PDF.');
+        break;
+    }
+    if (!empty($description)) {
+      $title .= '<div class="description">' . $description . '</div>';
+    }
     $form['languages'][$langcode]['name'] = array(
-      '#markup' => check_plain($language->name),
+      '#markup' => $title,
     );
     $form['languages'][$langcode]['default'] = array(
       '#type' => 'radio',
@@ -53,17 +69,22 @@ function language_admin_overview_form($form, &$form_state) {
       '#theme_wrappers' => array('language_admin_operations'),
       '#weight' => 100,
     );
-    $form['languages'][$langcode]['operations']['edit'] = array(
-      '#type' => 'link',
-      '#title' => t('edit'),
-      '#href' => 'admin/config/regional/language/edit/' . $langcode,
-    );
-    $form['languages'][$langcode]['operations']['delete'] = array(
-      '#type' => 'link',
-      '#title' => t('delete'),
-      '#href' => 'admin/config/regional/language/delete/' . $langcode,
-      '#access' => $langcode != $default->langcode,
-    );
+    if (empty($language->locked)) {
+      $form['languages'][$langcode]['operations']['edit'] = array(
+        '#type' => 'link',
+        '#title' => t('edit'),
+        '#href' => 'admin/config/regional/language/edit/' . $langcode,
+      );
+      $form['languages'][$langcode]['operations']['delete'] = array(
+        '#type' => 'link',
+        '#title' => t('delete'),
+        '#href' => 'admin/config/regional/language/delete/' . $langcode,
+        '#access' => $langcode != $default->langcode,
+      );
+    }
+    else{
+      $form['languages'][$langcode]['default']['#disabled'] = TRUE;
+    }
   }
 
   $form['actions'] = array('#type' => 'actions');
@@ -140,7 +161,7 @@ function theme_language_admin_overview_form_table($variables) {
  * Process language overview form submissions, updating existing languages.
  */
 function language_admin_overview_form_submit($form, &$form_state) {
-  $languages = language_list();
+  $languages = language_list(LANGUAGE_ADD_LOCKED);
   $old_default = language_default();
 
   foreach ($languages as $langcode => $language) {
@@ -291,7 +312,7 @@ function language_admin_add_custom_form_validate($form, &$form_state) {
     // Reuse the editing form validation routine if we add a custom language.
     language_admin_edit_form_validate($form, $form_state);
 
-    $languages = language_list();
+    $languages = language_list(LANGUAGE_ADD_LOCKED);
     if (isset($languages[$langcode])) {
      form_set_error('langcode', t('The language %language (%langcode) already exists.', array('%language' => $languages[$langcode]->name, '%langcode' => $langcode)));
     }
diff --git a/core/modules/language/language.install b/core/modules/language/language.install
index 5a962fa..da3ab8e 100644
--- a/core/modules/language/language.install
+++ b/core/modules/language/language.install
@@ -12,8 +12,13 @@
  * system on multilingual sites without needing any preliminary configuration.
  */
 function language_install() {
-  // Add the default language to the database too.
+  // Add the default language at first so that language_list() returns this in
+  // language_special_languages().
   language_save(language_default());
+  $languages = language_special_languages();
+  foreach ($languages as $language) {
+    language_save($language);
+  }
 
   // Enable URL language detection for each configurable language type.
   require_once DRUPAL_ROOT . '/core/includes/language.inc';
@@ -23,6 +28,43 @@ function language_install() {
 }
 
 /**
+ * List of special languages to install on a site.
+ *
+ * @return
+ *   An array of language objects.
+ */
+function language_special_languages() {
+  $locked_language = array(
+    'default' => FALSE,
+    'locked' => TRUE,
+    'enabled' => TRUE,
+  );
+  $languages = language_list(LANGUAGE_ADD_LOCKED);
+
+  // Language list is ordered by weight, get the biggest one.
+  $keys = array_keys($languages);
+  $max_weight = $languages[array_pop($keys)]->weight;
+  $languages = array();
+
+  $languages[LANGUAGE_NOT_SPECIFIED] = (object) (array(
+    'langcode' => LANGUAGE_NOT_SPECIFIED,
+    'name' => t('Not specified'),
+    'weight' => ++$max_weight,
+  ) + $locked_language);
+  $languages[LANGUAGE_NOT_APPLICABLE] = (object) (array(
+    'langcode' => LANGUAGE_NOT_APPLICABLE,
+    'name' => t('Not applicable'),
+    'weight' => ++$max_weight,
+  ) + $locked_language);
+  $languages[LANGUAGE_MULTIPLE] = (object) (array(
+    'langcode' => LANGUAGE_MULTIPLE,
+    'name' => t('Multiple'),
+    'weight' => ++$max_weight,
+  ) + $locked_language);
+  return $languages;
+}
+
+/**
  * Implements hook_uninstall().
  */
 function language_uninstall() {
@@ -82,6 +124,13 @@ function language_schema() {
         '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(
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 7acc783..006d3df 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -39,7 +39,7 @@ function language_help($path, $arg) {
 
     case 'admin/structure/block/manage/%/%':
       if ($arg[4] == 'language' && $arg[5] == 'language_interface') {
-        return '<p>' . t('This block is only shown if <a href="@languages">at least two languages are enabled</a> and <a href="@configuration">language negotiation</a> is set to <em>URL</em> or <em>Session</em>.', array('@languages' => url('admin/config/regional/language'), '@configuration' => url('admin/config/regional/language/detection'))) . '</p>';
+        return '<p>' . t('With multiple languages enabled, registered users can select their preferred language and authors can assign a specific language to content.') . '</p>';
       }
       break;
   }
@@ -77,14 +77,16 @@ function language_menu() {
     'title' => 'Edit language',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('language_admin_edit_form', 5),
-    'access arguments' => array('administer languages'),
+    'access callback' => 'language_access_language_edit_or_delete',
+    'access arguments' => array(5),
     'file' => 'language.admin.inc',
   );
   $items['admin/config/regional/language/delete/%language'] = array(
     'title' => 'Confirm delete',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('language_admin_delete_form', 5),
-    'access arguments' => array('administer languages'),
+    'access callback' => 'language_access_language_edit_or_delete',
+    'access arguments' => array(5),
     'file' => 'language.admin.inc',
   );
 
@@ -119,6 +121,13 @@ function language_menu() {
 }
 
 /**
+ * Editing or deleting locked languages should not be possible.
+ */
+function language_access_language_edit_or_delete($language) {
+  return !$language->locked && user_access('administer languages');
+}
+
+/**
  * Implements hook_permission().
  */
 function language_permission() {
@@ -187,8 +196,8 @@ function language_save($language) {
     variable_set('language_default', $language);
   }
 
-  // Update language count based on enabled language count.
-  variable_set('language_count', db_query('SELECT COUNT(langcode) FROM {language}')->fetchField());
+  // Update language count based on unlocked language count.
+  variable_set('language_count', db_query('SELECT COUNT(langcode) FROM {language} WHERE locked = 0')->fetchField());
 
   // Kill the static cache in language_list().
   drupal_static_reset('language_list');
@@ -205,8 +214,8 @@ function language_save($language) {
  *   TRUE if language is successfully deleted. Otherwise FALSE.
  */
 function language_delete($langcode) {
-  $languages = language_list();
-  if (isset($languages[$langcode])) {
+  $languages = language_list(LANGUAGE_ADD_LOCKED);
+  if (isset($languages[$langcode]) && !$languages[$langcode]->locked) {
     $language = $languages[$langcode];
 
     module_invoke_all('language_delete', $language);
@@ -388,6 +397,10 @@ function language_modules_disabled($modules) {
  * Implements hook_language_insert().
  */
 function language_language_insert($language) {
+  if (!empty($language->locked)) {
+    return;
+  }
+
   language_negotiation_include();
 
   // Add new language to the list of language prefixes.
@@ -405,6 +418,10 @@ function language_language_insert($language) {
  * Implements hook_language_update().
  */
 function language_language_update($language) {
+  if (!empty($language->locked)) {
+    return;
+  }
+
   language_negotiation_include();
 
   // If the language is the default, then ensure that no other languages have
@@ -521,15 +538,16 @@ function language_url_outbound_alter(&$path, &$options, $original_path) {
       $callbacks = array_keys($callbacks);
     }
 
+    // No language dependent path allowed in this mode.
+    if (empty($callbacks)) {
+      unset($options['language']);
+      return;
+    }
+
     foreach ($callbacks as $callback) {
       if (function_exists($callback)) {
         $callback($path, $options);
       }
     }
-
-    // No language dependent path allowed in this mode.
-    if (empty($callbacks)) {
-      unset($options['language']);
-    }
   }
 }
diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc
index 4d560e7..3601f61 100644
--- a/core/modules/language/language.negotiation.inc
+++ b/core/modules/language/language.negotiation.inc
@@ -362,7 +362,7 @@ function language_url_rewrite_url(&$path, &$options) {
     $options['language'] = $language_url;
   }
   // We allow only enabled languages here.
-  elseif (!isset($languages[$options['language']->langcode])) {
+  elseif (is_object($options['language']) && !isset($languages[$options['language']->langcode])) {
     unset($options['language']);
     return;
   }
@@ -371,7 +371,7 @@ function language_url_rewrite_url(&$path, &$options) {
     switch (variable_get('language_negotiation_url_part', LANGUAGE_NEGOTIATION_URL_PREFIX)) {
       case LANGUAGE_NEGOTIATION_URL_DOMAIN:
         $domains = language_negotiation_url_domains();
-        if (!empty($domains[$options['language']->langcode])) {
+        if (is_object($options['language']) && !empty($domains[$options['language']->langcode])) {
           // Ask for an absolute URL with our modified base_url.
           global $is_https;
           $url_scheme = ($is_https) ? 'https://' : 'http://';
@@ -390,7 +390,7 @@ function language_url_rewrite_url(&$path, &$options) {
 
       case LANGUAGE_NEGOTIATION_URL_PREFIX:
         $prefixes = language_negotiation_url_prefixes();
-        if (!empty($prefixes[$options['language']->langcode])) {
+        if (is_object($options['language']) &&!empty($prefixes[$options['language']->langcode])) {
           $options['prefix'] = $prefixes[$options['language']->langcode] . '/';
         }
         break;
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index 8f26052..bca04c8 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -28,7 +28,7 @@ function _locale_translate_seek() {
   if (!($query = _locale_translate_seek_query())) {
     $query = array(
       'translation' => 'all',
-      'language' => 'all',
+      'language' => LANGUAGE_ALL,
       'customized' => 'all',
       'string' => '',
     );
@@ -68,7 +68,7 @@ function _locale_translate_seek() {
   }
 
   $limit_language = NULL;
-  if ($query['language'] != LANGUAGE_SYSTEM && $query['language'] != 'all') {
+  if ($query['language'] != LANGUAGE_SYSTEM && $query['language'] != LANGUAGE_ALL) {
     $sql_query->condition('language', $query['language']);
     $limit_language = $query['language'];
   }
@@ -171,7 +171,7 @@ function locale_translation_filters() {
 
   $filters['language'] = array(
     'title' => t('Language'),
-    'options' => array_merge(array('all' => t('All languages'), LANGUAGE_SYSTEM => t('System (English)')), $language_options),
+    'options' => array_merge(array(LANGUAGE_ALL => t('All languages'), LANGUAGE_SYSTEM => t('System (English)')), $language_options),
   );
 
   $filters['translation'] = array(
@@ -356,6 +356,7 @@ function locale_translate_edit_form($form, &$form_state, $lid) {
   if (!locale_translate_english()) {
     unset($languages['en']);
   }
+
   // Store languages to iterate for validation and submission of the form.
   $form_state['langcodes'] = array_keys($languages);
   $plural_formulas = variable_get('locale_translation_plurals', array());
diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc
index ac362e8..f6ac8b5 100644
--- a/core/modules/node/node.admin.inc
+++ b/core/modules/node/node.admin.inc
@@ -106,10 +106,10 @@ function node_filters() {
 
   // Language filter if language support is present.
   if (language_multilingual()) {
-    $languages = language_list();
-    $language_options = array(LANGUAGE_NOT_SPECIFIED => t('- None -'));
+    $languages = language_list(LANGUAGE_ADD_LOCKED);
     foreach ($languages as $langcode => $language) {
-      $language_options[$langcode] = $language->name;
+      // Make locked languages appear special in the list.
+      $language_options[$langcode] = $language->locked ? t('- @name -', array('@name' => $language->name)) : $language->name;
     }
     $filters['language'] = array(
       'title' => t('language'),
@@ -474,7 +474,7 @@ function node_admin_nodes() {
   $nodes = node_load_multiple($nids);
 
   // Prepare the list of nodes.
-  $languages = language_list();
+  $languages = language_list(LANGUAGE_ADD_LOCKED);
   $destination = drupal_get_destination();
   $options = array();
   foreach ($nodes as $node) {
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 8dbc060..18b040c 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -2651,8 +2651,9 @@ function node_form_search_form_alter(&$form, $form_state) {
 
     // Languages:
     $language_options = array();
-    foreach (language_list() as $langcode => $language) {
-      $language_options[$langcode] = $language->name;
+    foreach (language_list(LANGUAGE_ADD_LOCKED) as $langcode => $language) {
+      // Make locked languages appear special in the list.
+      $language_options[$langcode] = $language->locked ? t('- @name -', array('@name' => $language->name)) : $language->name;
     }
     if (count($language_options) > 1) {
       $form['advanced']['language'] = array(
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index a43ff62..f52462a 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -187,17 +187,17 @@ function node_form($form, &$form_state, Node $node) {
   $form['#node'] = $node;
 
   if (variable_get('node_type_language_' . $node->type, 0) && module_exists('language')) {
-    $languages = language_list();
+    $languages = language_list(LANGUAGE_ADD_LOCKED);
     $language_options = array();
     foreach ($languages as $langcode => $language) {
-      $language_options[$langcode] = $language->name;
+      // Make locked languages appear special in the list.
+      $language_options[$langcode] = $language->locked ? t('- @name -', array('@name' => $language->name)) : $language->name;
     }
     $form['langcode'] = array(
       '#type' => 'select',
       '#title' => t('Language'),
-      '#default_value' => (isset($node->langcode) ? $node->langcode : ''),
+      '#default_value' => (isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED),
       '#options' => $language_options,
-      '#empty_value' => LANGUAGE_NOT_SPECIFIED,
     );
   }
   else {
diff --git a/core/modules/openid/openid.module b/core/modules/openid/openid.module
index 3881320..034c7c2 100644
--- a/core/modules/openid/openid.module
+++ b/core/modules/openid/openid.module
@@ -263,11 +263,11 @@ function openid_form_user_register_form_alter(&$form, &$form_state) {
         $candidate_langcodes[] = $parts[0] . '-' . $parts[2];
         $candidate_langcodes[] = $parts[0] . '-' . $parts[1] . '-' . $parts[2];
       }
-      $enabled_languages = language_list();
+      $languages = language_list();
       // Iterate over the generated permutations starting with the longest (most
       // specific) strings.
       foreach (array_reverse($candidate_langcodes) as $candidate_langcode) {
-        if (isset($enabled_languages[$candidate_langcode])) {
+        if (isset($languages[$candidate_langcode])) {
           $form['language']['preferred_langcode']['#type'] = 'hidden';
           $form['language']['preferred_langcode']['#value'] = $candidate_langcode;
           // Skip the rest of the foreach to not overwrite the specific
diff --git a/core/modules/system/tests/upgrade/upgrade.language.test b/core/modules/system/tests/upgrade/upgrade.language.test
index 91e1fec..72567e0 100644
--- a/core/modules/system/tests/upgrade/upgrade.language.test
+++ b/core/modules/system/tests/upgrade/upgrade.language.test
@@ -37,7 +37,7 @@ class LanguageUpgradePathTestCase extends UpgradePathTestCase {
 
     // Ensure Catalan was properly upgraded to be the new default language.
     $this->assertTrue(language_default()->langcode == 'ca', t('Catalan is the default language'));
-    $languages = language_list();
+    $languages = language_list(LANGUAGE_ADD_LOCKED);
     foreach ($languages as $language) {
       $this->assertTrue($language->default == ($language->langcode == 'ca'), t('@language default property properly set', array('@language' => $language->name)));
     }
diff --git a/core/modules/translation/translation.module b/core/modules/translation/translation.module
index b2c0635..730bdb3 100644
--- a/core/modules/translation/translation.module
+++ b/core/modules/translation/translation.module
@@ -197,7 +197,7 @@ function translation_node_view(Node $node, $view_mode) {
   // If the site has no translations or is not multilingual we have no content
   // translation links to display.
   if (isset($node->tnid) && language_multilingual() && $translations = translation_node_get_translations($node->tnid)) {
-    $languages = language_list();
+    $languages = language_list(LANGUAGE_ADD_LOCKED);
 
     // There might be a language provider enabled defining custom language
     // switch links which need to be taken into account while generating the
@@ -210,9 +210,9 @@ function translation_node_view(Node $node, $view_mode) {
     $links = array();
 
     foreach ($translations as $langcode => $translation) {
-      // Do not show links to the same node or to unpublished translations.
+      // Do not show links to the same node, to unpublished translations or to
+      // translations in disabled languages.
       if ($translation->status && isset($languages[$langcode]) && $langcode != $node->langcode) {
-        $language = $languages[$langcode];
         $key = "translation_$langcode";
 
         if (isset($custom_links->links[$langcode])) {
@@ -221,8 +221,8 @@ function translation_node_view(Node $node, $view_mode) {
         else {
           $links[$key] = array(
             'href' => "node/{$translation->nid}",
-            'title' => $language->name,
-            'language' => $language,
+            'title' => language_name($langcode),
+            'language' => $languages[$langcode],
           );
         }
 
