diff --git a/core/lib/Drupal/Component/Utility/SortArray.php b/core/lib/Drupal/Component/Utility/SortArray.php
index 64ceb89..e505863 100644
--- a/core/lib/Drupal/Component/Utility/SortArray.php
+++ b/core/lib/Drupal/Component/Utility/SortArray.php
@@ -119,6 +119,25 @@ public static function sortByWeightAndTitleKey($a, $b, $weight_key = 'weight', $
   }
 
   /**
+   * Sorts a structured array first by weight, then by label.
+   *
+   * @param array $a
+   *   The first item to compare.
+   * @param array $b
+   *   The second item to compare.
+   * @param string $weight_key
+   *   (optional) The weight key to use. Defaults to 'weight'.
+   * @param string $title_key
+   *   (optional) The title key to use. Defaults to 'label'.
+   *
+   * @return int
+   *   The comparison result for uasort().
+   */
+  public static function sortByWeightAndLabelKey($a, $b, $weight_key = 'weight', $title_key = 'label') {
+    return self::sortByWeightAndTitleKey($a, $b, $weight_key, $title_key);
+  }
+
+  /**
    * Sorts a string array item by an arbitrary key.
    *
    * @param array $a
diff --git a/core/lib/Drupal/Core/Language/Language.php b/core/lib/Drupal/Core/Language/Language.php
index f1a1cbe..bbc46d1 100644
--- a/core/lib/Drupal/Core/Language/Language.php
+++ b/core/lib/Drupal/Core/Language/Language.php
@@ -207,7 +207,7 @@ public function __construct(array $options = array()) {
    *   The array of language objects keyed by langcode.
    */
   public static function sort(&$languages) {
-    uasort($languages, 'Drupal\Component\Utility\SortArray::sortByWeightAndTitleKey');
+    uasort($languages, 'Drupal\Component\Utility\SortArray::sortByWeightAndLabelKey');
   }
 
 }
diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php
index 6ddf673..c680052 100644
--- a/core/lib/Drupal/Core/Language/LanguageManager.php
+++ b/core/lib/Drupal/Core/Language/LanguageManager.php
@@ -142,6 +142,14 @@ public function getLanguages($flags = Language::STATE_CONFIGURABLE) {
   /**
    * {@inheritdoc}
    */
+  public function getNativeLanguages() {
+    // In a language unaware site we don't have translated languages.
+    return $this->getLanguages();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getLanguage($langcode) {
     $languages = $this->getLanguages(Language::STATE_ALL);
     return isset($languages[$langcode]) ? $languages[$langcode] : NULL;
diff --git a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
index 16c7c01..32f0b61 100644
--- a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
+++ b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
@@ -91,6 +91,15 @@ public function getDefaultLanguage();
   public function getLanguages($flags = Language::STATE_CONFIGURABLE);
 
   /**
+   * Returns a list of languages set up on the site in their native form.
+   *
+   * @return array
+   *   An associative array of languages, keyed by the language code, ordered
+   *   by weight ascending and name ascending.
+   */
+  public function getNativeLanguages();
+
+  /**
    * Returns a language object from the given language code.
    *
    * @param string $langcode
diff --git a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
index a7fb8f6..8311974 100644
--- a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
+++ b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
@@ -261,7 +261,7 @@ public function getLanguages($flags = Language::STATE_CONFIGURABLE) {
       $default = $this->getDefaultLanguage();
       $this->languages = array($default->id => $default);
 
-      // Retrieve the config storage to list available languages.
+      // Retrieve a list of languages from configuration storage.
       $prefix = 'language.entity.';
       $storage = $this->configFactory->get($prefix . Language::LANGCODE_NOT_SPECIFIED)->getStorage();
       $config_ids = $storage->listAll($prefix);
@@ -292,6 +292,46 @@ public function getLanguages($flags = Language::STATE_CONFIGURABLE) {
   /**
    * {@inheritdoc}
    */
+  public function getNativeLanguages() {
+    $languages = array();
+    $default = $this->getDefaultLanguage();
+
+    // Retrieve the config storage to list available languages.
+    $prefix = 'language.entity.';
+    $storage = $this->configFactory->get($prefix . Language::LANGCODE_NOT_SPECIFIED)->getStorage();
+    $config_ids = $storage->listAll($prefix);
+
+    $langcodes = array_map(function($value) use ($prefix) {
+      return str_replace($prefix, '', $value);
+    }, $config_ids);
+    // Instantiate languages from config objects.
+    $original_language = $this->configFactory->getLanguage();
+    $i = 0;
+
+    foreach ($config_ids as $config_id) {
+      $langcode = $langcodes[$i];
+      $data = $this->configFactory->get($config_id)->get();
+      // Initialize default property so callers have an easy reference and can
+      // save the same object without data loss.
+      $data['default'] = ($langcode == $default->id);
+      $data['name'] = $data['label'];
+      $language = new Language($data);
+      if (!$language->locked) {
+        $languages[$langcode] = $language;
+      }
+      ++$i;
+    }
+    $this->configFactory->setLanguage($original_language);
+
+    // Sort the language list by weight.
+    Language::sort($languages);
+
+    return $languages;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function updateLockedLanguageWeights() {
     $max_weight = 0;
 
diff --git a/core/modules/language/lib/Drupal/language/Plugin/LanguageNegotiation/LanguageNegotiationSession.php b/core/modules/language/lib/Drupal/language/Plugin/LanguageNegotiation/LanguageNegotiationSession.php
index e56278d..2414d6f 100644
--- a/core/modules/language/lib/Drupal/language/Plugin/LanguageNegotiation/LanguageNegotiationSession.php
+++ b/core/modules/language/lib/Drupal/language/Plugin/LanguageNegotiation/LanguageNegotiationSession.php
@@ -131,7 +131,7 @@ function getLanguageSwitchLinks(Request $request, $type, $path) {
     $query = array();
     parse_str($request->getQueryString(), $query);
 
-    foreach ($this->languageManager->getLanguages() as $language) {
+    foreach ($this->languageManager->getNativeLanguages() as $language) {
       $langcode = $language->id;
       $links[$langcode] = array(
         'href' => $path,
diff --git a/core/modules/language/lib/Drupal/language/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php b/core/modules/language/lib/Drupal/language/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php
index eacb5c4..71a93ca 100644
--- a/core/modules/language/lib/Drupal/language/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php
+++ b/core/modules/language/lib/Drupal/language/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php
@@ -188,7 +188,7 @@ public function processOutbound($path, &$options = array(), Request $request = N
   function getLanguageSwitchLinks(Request $request, $type, $path) {
     $links = array();
 
-    foreach ($this->languageManager->getLanguages() as $language) {
+    foreach ($this->languageManager->getNativeLanguages() as $language) {
       $links[$language->id] = array(
         'href' => $path,
         'title' => $language->name,
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageSwitchingTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageSwitchingTest.php
index b4c4616..65445c2 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageSwitchingTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageSwitchingTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\language\Tests;
 
+use Drupal\Core\Config\FileStorage;
 use Drupal\Core\Language\Language;
 use Drupal\simpletest\WebTestBase;
 
@@ -20,7 +21,7 @@ class LanguageSwitchingTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('language', 'block', 'language_test');
+  public static $modules = array('locale', 'language', 'block', 'language_test');
 
   public static function getInfo() {
     return array(
@@ -42,23 +43,26 @@ function setUp() {
    * Functional tests for the language switcher block.
    */
   function testLanguageBlock() {
-    // Enable the language switching block..
-    $block = $this->drupalPlaceBlock('language_block:' . Language::TYPE_INTERFACE, array(
-      'id' => 'test_language_block',
-      // Ensure a 2-byte UTF-8 sequence is in the tested output.
-      'label' => $this->randomName(8) . '×',
-    ));
-
     // Add language.
     $edit = array(
       'predefined_langcode' => 'fr',
     );
     $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
 
+    // Set the native language name.
+    $this->saveNativeLanguageName('fr', 'Français');
+
     // Enable URL language detection and selection.
     $edit = array('language_interface[enabled][language-url]' => '1');
     $this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
 
+    // Enable the language switching block.
+    $block = $this->drupalPlaceBlock('language_block:' . Language::TYPE_INTERFACE, array(
+      'id' => 'test_language_block',
+      // Ensure a 2-byte UTF-8 sequence is in the tested output.
+      'label' => $this->randomName(8) . '×',
+    ));
+
     $this->doTestLanguageBlockAuthenticated($block->label());
     $this->doTestLanguageBlockAnonymous($block->label());
   }
@@ -134,6 +138,7 @@ protected function doTestLanguageBlockAnonymous($block_label) {
       'active' => array(),
       'inactive' => array(),
     );
+    $labels = array();
     foreach ($language_switcher->ul->li as $link) {
       $classes = explode(" ", (string) $link['class']);
       list($langcode) = array_intersect($classes, array('en', 'fr'));
@@ -150,9 +155,12 @@ protected function doTestLanguageBlockAnonymous($block_label) {
       else {
         $anchors['inactive'][] = $langcode;
       }
+
+      $labels[] = (string) $link->a;
     }
     $this->assertIdentical($links, array('active' => array('en'), 'inactive' => array('fr')), 'Only the current language list item is marked as active on the language switcher block.');
     $this->assertIdentical($anchors, array('active' => array('en'), 'inactive' => array('fr')), 'Only the current language anchor is marked as active on the language switcher block.');
+    $this->assertIdentical($labels, array('English', 'Français'), 'The language links labels are in their own language on the language switcher block.');
   }
 
   /**
@@ -283,4 +291,19 @@ protected function doTestLanguageLinkActiveClassAnonymous() {
     $this->assertTrue(isset($links[0]), t('A link generated by :function to the current :language page with langcode :langcode is marked active.', array(':function' => $function_name, ':language' => $current_language, ':langcode' => $langcode)));
   }
 
+  /**
+   * Saves the native name of a language entity in configuration as a label.
+   *
+   * @param string $langcode
+   *   The language code of the language.
+   * @param string $label
+   *   The native name of the language.
+   */
+  private function saveNativeLanguageName($langcode, $label) {
+    $file_storage = new FileStorage($this->configDirectories[CONFIG_ACTIVE_DIRECTORY]);
+    $file_storage->write('language.config.' . $langcode . '.language.entity.' . $langcode,
+      array('label' => $label)
+    );
+  }
+
 }
