diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php
index 0072f0c..a81f258 100644
--- a/core/lib/Drupal/Core/Language/LanguageManager.php
+++ b/core/lib/Drupal/Core/Language/LanguageManager.php
@@ -81,6 +81,31 @@ public function getLanguageTypes() {
   /**
    * {@inheritdoc}
    */
+  public function getDefinedLanguageTypesInfo() {
+    // This needs to have the same return value as
+    // language_language_type_info(), so that even if the Language module is
+    // not defined, users of this information, such as the Views module, can
+    // access names and descriptions of the default language types.
+    return array(
+      LanguageInterface::TYPE_INTERFACE => array(
+        'name' => t('User interface text'),
+        'description' => t('Order of language detection methods for user interface text. If a translation of user interface text is available in the detected language, it will be displayed.'),
+        'locked' => TRUE,
+      ),
+      LanguageInterface::TYPE_CONTENT => array(
+        'name' => t('Content'),
+        'description' => t('Order of language detection methods for content. If a version of content is available in the detected language, it will be displayed.'),
+        'locked' => TRUE,
+      ),
+      LanguageInterface::TYPE_URL => array(
+        'locked' => TRUE,
+      ),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) {
     return $this->getDefaultLanguage();
   }
@@ -120,7 +145,9 @@ public function getLanguages($flags = LanguageInterface::STATE_CONFIGURABLE) {
     // Add the site's default language if flagged as allowed value.
     if ($flags & LanguageInterface::STATE_SITE_DEFAULT) {
       $default = isset($default) ? $default : $this->getDefaultLanguage();
-      // Rename the default language.
+      // Rename the default language. But we do not want to do this globally,
+      // if we're acting on a global object, so clone the object first.
+      $default = clone $default;
       $default->name = $this->t("Site's default language (@lang_name)", array('@lang_name' => $default->name));
       $filtered_languages['site_default'] = $default;
     }
diff --git a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
index b3f0272..28583b0 100644
--- a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
+++ b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
@@ -34,19 +34,32 @@ public function isMultilingual();
    * Returns an array of the available language types.
    *
    * @return array
-   *   An array of language type names.
+   *   An array of language type machine names.
    */
   public function getLanguageTypes();
 
   /**
+   * Returns information about all defined language types.
+   *
+   * @return array
+   *   An associative array of language type information arrays keyed by
+   *   language type machine name, in the format of
+   *   hook_language_types_info(). In some implementing classes, this is based
+   *   on information from hook_language_types_info() and
+   *   hook_language_types_info_alter().
+   */
+  public function getDefinedLanguageTypesInfo();
+
+  /**
    * Returns the current language for the given type.
    *
    * @param string $type
-   *   (optional) The language type, e.g. the interface or the content language.
-   *   Defaults to \Drupal\Core\Language\LanguageInterface::TYPE_INTERFACE.
+   *   (optional) The language type; e.g., the interface or the content
+   *   language. Defaults to
+   *   \Drupal\Core\Language\LanguageInterface::TYPE_INTERFACE.
    *
    * @return \Drupal\Core\Language\LanguageInterface
-   *   A language object for the given type.
+   *   The current language object for the given type of language.
    */
   public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE);
 
diff --git a/core/modules/comment/config/install/views.view.comments_recent.yml b/core/modules/comment/config/install/views.view.comments_recent.yml
index 674c8a8..7efdf8f 100644
--- a/core/modules/comment/config/install/views.view.comments_recent.yml
+++ b/core/modules/comment/config/install/views.view.comments_recent.yml
@@ -229,7 +229,7 @@ display:
           content: 'No comments available.'
           tokenize: false
           plugin_id: text_custom
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
   block_1:
     provider: block
@@ -240,7 +240,7 @@ display:
     display_options:
       block_description: 'Recent comments'
       block_category: 'Lists (Views)'
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       allow:
         items_per_page: true
diff --git a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_field_filters.yml b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_field_filters.yml
index 692c5d5..9073802 100644
--- a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_field_filters.yml
+++ b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_field_filters.yml
@@ -160,7 +160,7 @@ display:
       footer: {  }
       empty: {  }
       arguments: {  }
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
   page_tc:
     display_plugin: page
@@ -169,7 +169,7 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-title-filter
       display_description: ''
@@ -180,7 +180,7 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-body-paris
       display_description: ''
@@ -241,7 +241,7 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-title-paris
       display_description: ''
@@ -301,7 +301,7 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-body-filter
       display_description: ''
diff --git a/core/modules/field/src/Plugin/views/field/Field.php b/core/modules/field/src/Plugin/views/field/Field.php
index 4705437..9eabe0f 100644
--- a/core/modules/field/src/Plugin/views/field/Field.php
+++ b/core/modules/field/src/Plugin/views/field/Field.php
@@ -290,20 +290,18 @@ public function query($use_groupby = FALSE) {
       $this->ensureMyTable();
       $this->addAdditionalFields($fields);
 
-      // Filter by langcode, if field translation is enabled.
+      // If we are grouping by something on this field, we want to group by
+      // the displayed value, which is translated. So, we need to figure out
+      // which language should be used to translate the value. See also
+      // $this->field_langcode().
       $field = $field_definition;
       if ($field->isTranslatable() && !empty($this->view->display_handler->options['field_langcode_add_to_query'])) {
         $column = $this->tableAlias . '.langcode';
-        // By the same reason as field_language the field might be
-        // LanguageInterface::LANGCODE_NOT_SPECIFIED in reality so allow it as
-        // well.
-        // @see this::field_langcode()
-        $default_langcode = language_default()->id;
-        $langcode = str_replace(
-          array('***CURRENT_LANGUAGE***', '***DEFAULT_LANGUAGE***'),
-          array($this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT), $default_langcode),
-          $this->view->display_handler->options['field_langcode']
-        );
+        $langcode = $this->view->display_handler->options['field_langcode'];
+        $substitutions = static::queryLanguageSubstitutions();
+        if (isset($substitutions[$langcode])) {
+          $langcode = $substitutions[$langcode];
+        }
         $placeholder = $this->placeholder();
         $langcode_fallback_candidates = $this->languageManager->getFallbackCandidates($langcode, array('operation' => 'views_query', 'data' => $this));
         $this->query->addWhereExpression(0, "$column IN($placeholder) OR $column IS NULL", array($placeholder => $langcode_fallback_candidates));
@@ -915,12 +913,11 @@ protected function addSelfTokens(&$tokens, $item) {
    */
   function field_langcode(EntityInterface $entity) {
     if ($this->getFieldDefinition()->isTranslatable()) {
-      $default_langcode = language_default()->id;
-      $langcode = str_replace(
-        array('***CURRENT_LANGUAGE***', '***DEFAULT_LANGUAGE***'),
-        array($this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->id, $default_langcode),
-        $this->view->display_handler->options['field_langcode']
-      );
+      $langcode = $this->view->display_handler->options['field_langcode'];
+      $substitutions = static::queryLanguageSubstitutions();
+      if (isset($substitutions[$langcode])) {
+        $langcode = $substitutions[$langcode];
+      }
 
       // Give the Entity Field API a chance to fallback to a different language
       // (or LanguageInterface::LANGCODE_NOT_SPECIFIED), in case the field has
diff --git a/core/modules/language/src/ConfigurableLanguageManagerInterface.php b/core/modules/language/src/ConfigurableLanguageManagerInterface.php
index 3b52cd4..f3b2ff2 100644
--- a/core/modules/language/src/ConfigurableLanguageManagerInterface.php
+++ b/core/modules/language/src/ConfigurableLanguageManagerInterface.php
@@ -44,22 +44,11 @@ public function setNegotiator(LanguageNegotiatorInterface $negotiator);
    * through the user interface.
    *
    * @return array
-   *   An array of language type names.
+   *   An array of language type machine names.
    */
   public function getDefinedLanguageTypes();
 
   /**
-   * Returns information about all defined language types.
-   *
-   * @return array
-   *   An associative array of language type information arrays keyed by type
-   *   names. Based on information from hook_language_types_info().
-   *
-   * @see hook_language_types_info()
-   */
-  public function getDefinedLanguageTypesInfo();
-
-  /**
    * Stores language types configuration.
    *
    * @param array
diff --git a/core/modules/node/config/install/views.view.content.yml b/core/modules/node/config/install/views.view.content.yml
index 132ffee..6229a32 100644
--- a/core/modules/node/config/install/views.view.content.yml
+++ b/core/modules/node/config/install/views.view.content.yml
@@ -536,7 +536,7 @@ display:
         operator: AND
         groups:
           1: AND
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
     display_plugin: default
     display_title: Master
@@ -558,7 +558,7 @@ display:
         description: 'Find and manage content'
         menu_name: admin
         weight: -10
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
     display_plugin: page
     display_title: Page
diff --git a/core/modules/node/config/install/views.view.frontpage.yml b/core/modules/node/config/install/views.view.frontpage.yml
index 1e27e9c..af7cd23 100644
--- a/core/modules/node/config/install/views.view.frontpage.yml
+++ b/core/modules/node/config/install/views.view.frontpage.yml
@@ -130,7 +130,7 @@ display:
               - views
           operator: in
           value:
-            '***CURRENT_LANGUAGE***': '***CURRENT_LANGUAGE***'
+            language_content: 'language_content'
           group: 1
           exposed: false
           expose:
@@ -240,7 +240,7 @@ display:
       relationships: {  }
       fields: {  }
       arguments: {  }
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
     display_plugin: default
     display_title: Master
@@ -249,7 +249,7 @@ display:
   page_1:
     display_options:
       path: node
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
     display_plugin: page
     display_title: Page
@@ -286,5 +286,5 @@ display:
           view_mode: rss
           links: false
         provider: views
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_filters.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_filters.yml
index 410622a..9812a54 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_filters.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_filters.yml
@@ -173,7 +173,7 @@ display:
       empty: {  }
       relationships: {  }
       arguments: {  }
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
   page_tf:
     display_plugin: page
@@ -182,7 +182,7 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-title-filter
       display_description: ''
@@ -255,7 +255,7 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-body-filter
       display_description: ''
@@ -326,7 +326,7 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-body-paris
       display_description: ''
@@ -398,7 +398,7 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-title-paris
       display_description: ''
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml
index 68fb2d5..8ecac76 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml
@@ -300,7 +300,7 @@ display:
           validate_options: {  }
           plugin_id: language
           provider: views
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
   page_1:
     display_plugin: page
@@ -309,6 +309,6 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-language
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_field_filters.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_field_filters.yml
index 372c0f5..4a84614 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_field_filters.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_field_filters.yml
@@ -145,7 +145,7 @@ display:
       empty: {  }
       relationships: {  }
       arguments: {  }
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
   page_dc:
     display_plugin: page
@@ -154,7 +154,7 @@ display:
     position: 3
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       display_description: ''
       path: test-desc-filter
@@ -215,7 +215,7 @@ display:
     position: 3
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       display_description: ''
       path: test-desc-paris
@@ -277,7 +277,7 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-name-filter
       display_description: ''
@@ -288,7 +288,7 @@ display:
     position: 1
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       path: test-name-paris
       display_description: ''
@@ -348,7 +348,7 @@ display:
     position: 3
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       display_description: ''
       path: test-field-paris
@@ -410,7 +410,7 @@ display:
     position: 3
     provider: views
     display_options:
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
       display_description: ''
       path: test-field-filter
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_tid_field.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_tid_field.yml
index 6f2bf4f..00ed470 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_tid_field.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_taxonomy_tid_field.yml
@@ -172,5 +172,5 @@ display:
       empty: {  }
       relationships: {  }
       arguments: {  }
-      field_langcode: '***CURRENT_LANGUAGE***'
+      field_langcode: 'language_content'
       field_langcode_add_to_query: null
diff --git a/core/modules/views/src/Plugin/views/PluginBase.php b/core/modules/views/src/Plugin/views/PluginBase.php
index 132ceec..d2a1ec2 100644
--- a/core/modules/views/src/Plugin/views/PluginBase.php
+++ b/core/modules/views/src/Plugin/views/PluginBase.php
@@ -2,13 +2,15 @@
 
 /**
  * @file
- * Definition of Drupal\views\Plugin\views\PluginBase.
+ * Contains \Drupal\views\Plugin\views\PluginBase.
  */
 
 namespace Drupal\views\Plugin\views;
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Language\LanguageManagerInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Plugin\PluginBase as ComponentPluginBase;
 use Drupal\Core\Render\Element;
@@ -44,6 +46,13 @@
 abstract class PluginBase extends ComponentPluginBase implements ContainerFactoryPluginInterface {
 
   /**
+   * Include negotiated languages when listing languages.
+   *
+   * @see \Drupal\views\Plugin\views\PluginBase::listLanguages()
+   */
+  const INCLUDE_NEGOTIATED = 16;
+
+  /**
    * Options for this plugin will be held here.
    *
    * @var array
@@ -439,4 +448,87 @@ public function getDependencies() {
     return array();
   }
 
+  /**
+   * Makes an array of languages, optionally including special languages.
+   *
+   * @param int $flags
+   *   (optional) Flags for which languages to return (additive). By default,
+   *   returns all languages plus site default language. Options:
+   *   - \Drupal\Core\Language::STATE_ALL: All languages (configurable and
+   *     default).
+   *   - \Drupal\Core\Language::STATE_CONFIGURABLE: Configurable languages.
+   *   - \Drupal\Core\Language::STATE_LOCKED: Locked languages.
+   *   - \Drupal\Core\Language::STATE_SITE_DEFAULT: Add site default language;
+   *     note that this is not included in STATE_ALL.
+   *   - \Drupal\views\Plugin\views\PluginBase::INCLUDE_NEGOTIATED: Add
+   *     negotiated language types.
+   *
+   * @return array
+   *   An array of language names, keyed by the language code. Negotiated and
+   *   special languages have special codes that are substituted in queries by
+   *   static::queryLanguageSubstitutions().
+   */
+  function listLanguages($flags = 0) {
+    // The default value of $flags is zero, because you cannot put | in
+    // a function signature. Set the correct default here, if nothing was
+    // passed in (zero is not really a sensible option).
+    if (!$flags) {
+      $flags = (LanguageInterface::STATE_ALL | LanguageInterface::STATE_SITE_DEFAULT);
+    }
+
+    $manager = \Drupal::languageManager();
+    $list = array();
+
+    // The Language Manager class takes care of the STATE_SITE_DEFAULT case.
+    // It comes in with ID set to 'site_default'.
+    $languages = $manager->getLanguages($flags);
+    foreach ($languages as $id => $language) {
+      $list[$id] = t($language->name);
+    }
+
+    // Add in negotiated languages, if requested.
+    if ($flags & PluginBase::INCLUDE_NEGOTIATED) {
+      $types = $manager->getDefinedLanguageTypesInfo();
+      foreach ($types as $id => $type) {
+        // Omit unnamed types. These are things like language_url, which are
+        // not configurable and do not need to be in this list.
+        if (isset($type['name'])) {
+          $list[ $id] = t('Language selected for !type', array('!type' => $type['name']));
+        }
+      }
+    }
+
+    return $list;
+  }
+
+  /**
+   * Returns substitutions for Views queries for languages.
+   *
+   * This is needed so that the language options returned by
+   * $this->listLanguages() are able to be used in queries. It is called
+   * by the Views module implementation of hook_views_query_substitutions()
+   * to get the language-related substitutions.
+   *
+   * @return array
+   *   An array in the format of hook_views_query_substitutions() that gives
+   *   the query substitutions needed for the special language types.
+   */
+  static function queryLanguageSubstitutions() {
+    $changes = array();
+    $manager = \Drupal::languageManager();
+
+    // Handle default language.
+    $default = $manager->getDefaultLanguage()->id;
+    $changes['site_default'] = $default;
+
+    // Handle negotiated languages.
+    $types = $manager->getDefinedLanguageTypesInfo();
+    foreach ($types as $id => $type) {
+      if (isset($type['name'])) {
+        $changes[$id] = $manager->getCurrentLanguage($id)->id;
+      }
+    }
+
+    return $changes;
+  }
 }
diff --git a/core/modules/views/src/Plugin/views/argument/LanguageArgument.php b/core/modules/views/src/Plugin/views/argument/LanguageArgument.php
index c73ca6b..f6b9687 100644
--- a/core/modules/views/src/Plugin/views/argument/LanguageArgument.php
+++ b/core/modules/views/src/Plugin/views/argument/LanguageArgument.php
@@ -46,7 +46,7 @@ function title() {
    *   language was not found.
    */
   function language($langcode) {
-    $languages = views_language_list();
+    $languages = $this->listLanguages();
     return isset($languages[$langcode]) ? $languages[$langcode] : t('Unknown language');
   }
 
diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
index 31f30bc..3ab78fd 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
@@ -579,7 +579,7 @@ protected function defineOptions() {
         'bool' => TRUE,
       ),
       'field_langcode' => array(
-        'default' => '***CURRENT_LANGUAGE***',
+        'default' => LanguageInterface::TYPE_CONTENT,
       ),
       'field_langcode_add_to_query' => array(
         'default' => TRUE,
@@ -1245,19 +1245,13 @@ public function optionsSummary(&$categories, &$options) {
       'desc' => t('Allow to set some advanced settings for the query plugin'),
     );
 
-    $languages = array(
-        '***CURRENT_LANGUAGE***' => t("Current user's language"),
-        '***DEFAULT_LANGUAGE***' => t("Default site language"),
-        LanguageInterface::LANGCODE_NOT_SPECIFIED => t('Language neutral'),
-    );
-    if (\Drupal::moduleHandler()->moduleExists('language')) {
-      $languages = array_merge($languages, language_list());
-    }
+    $language_options = $this->listLanguages(LanguageInterface::STATE_ALL | LanguageInterface::STATE_SITE_DEFAULT | PluginBase::INCLUDE_NEGOTIATED);
+
     $options['field_langcode'] = array(
       'category' => 'other',
       'title' => t('Field Language'),
-      'value' => $languages[$this->getOption('field_langcode')],
-      'desc' => t('All fields which support translations will be displayed in the selected language.'),
+      'value' => $language_options[$this->getOption('field_langcode')],
+      'desc' => t('All fields that support translations will be displayed in the selected language.'),
     );
 
     $access_plugin = $this->getPlugin('access');
@@ -1619,12 +1613,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
         // an entity base table. Also, we make sure that there's at least one
         // entity type with a translation handler attached.
         if (in_array($this->view->storage->get('base_table'), $translatable_entity_tables)) {
-          $languages = array(
-            '***CURRENT_LANGUAGE***' => t("Current user's language"),
-            '***DEFAULT_LANGUAGE***' => t("Default site language"),
-            LanguageInterface::LANGCODE_NOT_SPECIFIED => t('Language neutral'),
-          );
-          $languages = array_merge($languages, views_language_list());
+          $languages = $this->listLanguages(LanguageInterface::STATE_ALL | LanguageInterface::STATE_SITE_DEFAULT | PluginBase::INCLUDE_NEGOTIATED);
 
           $form['field_langcode'] = array(
             '#type' => 'select',
diff --git a/core/modules/views/src/Plugin/views/filter/LanguageFilter.php b/core/modules/views/src/Plugin/views/filter/LanguageFilter.php
index 8b08f33..67d6a4f 100644
--- a/core/modules/views/src/Plugin/views/filter/LanguageFilter.php
+++ b/core/modules/views/src/Plugin/views/filter/LanguageFilter.php
@@ -7,6 +7,9 @@
 
 namespace Drupal\views\Plugin\views\filter;
 
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\views\Plugin\views\PluginBase;
+
 /**
  * Provides filtering by language.
  *
@@ -16,16 +19,13 @@
  */
 class LanguageFilter extends InOperator {
 
+  /**
+   * {@inheritdoc}
+   */
   public function getValueOptions() {
     if (!isset($this->value_options)) {
       $this->value_title = t('Language');
-      $languages = array(
-        '***CURRENT_LANGUAGE***' => t("Current user's language"),
-        '***DEFAULT_LANGUAGE***' => t("Default site language"),
-      );
-      $languages = array_merge($languages, views_language_list());
-      $this->value_options = $languages;
+      $this->value_options = $this->listLanguages(LanguageInterface::STATE_ALL |LanguageInterface::STATE_SITE_DEFAULT | PluginBase::INCLUDE_NEGOTIATED);
     }
   }
-
 }
diff --git a/core/modules/views/views.api.php b/core/modules/views/views.api.php
index e5c8c50..6527b2d 100644
--- a/core/modules/views/views.api.php
+++ b/core/modules/views/views.api.php
@@ -569,8 +569,8 @@ function hook_views_query_substitutions(ViewExecutable $view) {
   return array(
     '***CURRENT_VERSION***' => \Drupal::VERSION,
     '***CURRENT_TIME***' => REQUEST_TIME,
-    '***CURRENT_LANGUAGE***' => \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->id,
-    '***DEFAULT_LANGUAGE***' => \Drupal::languageManager()->getDefaultLanguage()->id,
+    LanguageInterface::TYPE_CONTENT => \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->id,
+    'site_default' => \Drupal::languageManager()->getDefaultLanguage()->id,
   );
 }
 
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index 3294836..8ecf065 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -13,7 +13,6 @@
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Database\Query\AlterableInterface;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Render\Element;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\views\Plugin\Derivative\ViewsLocalTask;
@@ -481,34 +480,6 @@ function views_add_contextual_links(&$render_element, $location, ViewExecutable
 }
 
 /**
- * Prepares a list of language names.
- *
- * This is a wrapper around \Drupal::languageManager()->getLanguages() to return
- * a plain key value array.
- *
- * @param string $field
- *   The field of the language object which should be used as the value of the
- *   array.
- * @param int $flags
- *   (optional) Specifies the state of the languages that have to be returned.
- *   It can be: LanguageInterface::STATE_CONFIGURABLE,
- *   LanguageInterface::STATE_LOCKED, LanguageInterface::STATE_ALL.
- *
- * @return array
- *   An array of language names (or $field) keyed by the langcode.
- *
- * @see locale_language_list()
- */
-function views_language_list($field = 'name', $flags = LanguageInterface::STATE_ALL) {
-  $languages = \Drupal::languageManager()->getLanguages($flags);
-  $list = array();
-  foreach ($languages as $language) {
-    $list[$language->id] = ($field == 'name') ? t($language->name) : $language->$field;
-  }
-  return $list;
-}
-
-/**
  * Implements hook_ENTITY_TYPE_create() for 'field_instance_config'.
  */
 function views_field_instance_config_create(FieldInstanceConfigInterface $field_instance) {
diff --git a/core/modules/views/views.views_execution.inc b/core/modules/views/views.views_execution.inc
index 96b5006..5f19999 100644
--- a/core/modules/views/views.views_execution.inc
+++ b/core/modules/views/views.views_execution.inc
@@ -7,17 +7,22 @@
 
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\views\ViewExecutable;
+use Drupal\views\Plugin\views\PluginBase;
 
 /**
  * Implements hook_views_query_substitutions().
  *
- * Substitute current time; this works with cached queries.
+ * Makes the following substitutions:
+ * - Current time; this works with cached queries.
+ * - Drupal version.
+ * - Special language codes; see
+ *   \Drupal\views\Plugin\views\PluginBase::listLanguages().
  */
 function views_views_query_substitutions(ViewExecutable $view) {
-  return array(
+  $substitutions = array(
     '***CURRENT_VERSION***' => \Drupal::VERSION,
     '***CURRENT_TIME***' => REQUEST_TIME,
-    '***CURRENT_LANGUAGE***' => \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->id,
-    '***DEFAULT_LANGUAGE***' => \Drupal::languageManager()->getDefaultLanguage()->id,
-  );
+  ) + PluginBase::queryLanguageSubstitutions();
+
+  return $substitutions;
 }
diff --git a/core/modules/views_ui/src/Tests/ViewEditTest.php b/core/modules/views_ui/src/Tests/ViewEditTest.php
index b88ed43..358b044 100644
--- a/core/modules/views_ui/src/Tests/ViewEditTest.php
+++ b/core/modules/views_ui/src/Tests/ViewEditTest.php
@@ -94,7 +94,7 @@ public function testEditFormOtherOptions() {
     $this->drupalGet('admin/structure/views/view/test_view');
     $langcode_url = 'admin/structure/views/nojs/display/test_view/default/field_langcode';
     $this->assertLinkByHref($langcode_url);
-    $this->assertLink(t("Current user's language"));
+    $this->assertLink(t('Negotiated !name language', array('!name' => t('Content'))));
     // Click the link and check the form before language is added.
     $this->drupalGet($langcode_url);
     $this->assertResponse(200);
@@ -106,7 +106,7 @@ public function testEditFormOtherOptions() {
 
     $this->drupalGet('admin/structure/views/nojs/display/test_display/page_1/field_langcode');
     $this->assertResponse(200);
-    $this->assertFieldByName('field_langcode', '***CURRENT_LANGUAGE***');
+    $this->assertFieldByName('field_langcode', 'language_content');
     $this->assertFieldByName('field_langcode_add_to_query', TRUE);
   }
 
