From 30a5046e35a31f3f441bf09d15063dfd52757fe4 Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Mon, 8 Dec 2014 16:25:00 +0000
Subject: [PATCH] =?UTF-8?q?Issue=20#2355909=20by=20penyaskito,=20alexpott,?=
 =?UTF-8?q?=20G=C3=A1bor=20Hojtsy,=20DuaelFr:=20language.settings=20config?=
 =?UTF-8?q?=20is=20not=20scalable?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 core/modules/aggregator/src/FeedForm.php      |   1 +
 .../block_content/src/BlockContentForm.php    |  14 +-
 .../src/BlockContentTypeForm.php              |   3 +-
 core/modules/comment/src/CommentForm.php      |   5 +-
 core/modules/comment/src/CommentTypeForm.php  |   3 +-
 .../comment/src/Tests/CommentLanguageTest.php |   2 +-
 core/modules/contact/src/MessageForm.php      |   4 +-
 .../content_translation.admin.inc             |   2 +-
 .../content_translation.admin.js              |   2 +-
 .../content_translation.module                |   2 +-
 .../ContentTranslationContextualLinksTest.php |  10 +-
 .../Tests/ContentTranslationSettingsTest.php  |  15 +-
 .../config/schema/language.schema.yml         |  46 ++-
 core/modules/language/language.module         | 133 +++-----
 .../src/ContentLanguageSettingsException.php  |  13 +
 .../src/ContentLanguageSettingsInterface.php  |  85 +++++
 .../src/Element/LanguageConfiguration.php     |  13 +-
 .../src/Entity/ContentLanguageSettings.php    | 213 ++++++++++++
 .../src/Form/ContentLanguageSettingsForm.php  |  18 +-
 .../src/Tests/EntityDefaultLanguageTest.php   |  10 +-
 .../src/Tests/LanguageConfigSchemaTest.php    |  10 +-
 .../LanguageConfigurationElementTest.php      | 104 ++++--
 .../language_elements_test.info.yml           |   2 +
 .../src/Form/LanguageConfigurationElement.php |   5 +-
 .../Form/LanguageConfigurationElementTest.php |   2 +-
 .../Unit/ContentLanguageSettingsUnitTest.php  | 321 ++++++++++++++++++
 .../locale/src/Tests/LocaleContentTest.php    |   4 +-
 .../src/Form/MenuLinkContentForm.php          |  12 +-
 .../menu_ui/src/Tests/MenuLanguageTest.php    |  16 +-
 core/modules/node/node.install                |  14 -
 core/modules/node/node.module                 |   5 +-
 core/modules/node/src/NodeForm.php            |   5 +-
 core/modules/node/src/NodeTypeForm.php        |   3 +-
 .../src/Tests/NodeFieldMultilingualTest.php   |   2 +-
 .../node/src/Tests/NodeTranslationUITest.php  |   2 +-
 .../src/Tests/NodeTypeInitialLanguageTest.php |   4 +-
 .../path/src/Tests/PathLanguageTest.php       |   2 +-
 core/modules/system/entity.api.php            |   5 +-
 .../Entity/EntityTranslationFormTest.php      |   2 +-
 core/modules/taxonomy/src/TermForm.php        |   5 +-
 .../taxonomy/src/Tests/TermLanguageTest.php   |   8 +-
 .../src/Tests/VocabularyLanguageTest.php      |  29 +-
 core/modules/taxonomy/src/VocabularyForm.php  |  25 +-
 .../src/Tests/SearchMultilingualTest.php      |   2 +-
 44 files changed, 904 insertions(+), 279 deletions(-)
 create mode 100644 core/modules/language/src/ContentLanguageSettingsException.php
 create mode 100644 core/modules/language/src/ContentLanguageSettingsInterface.php
 create mode 100644 core/modules/language/src/Entity/ContentLanguageSettings.php
 create mode 100644 core/modules/language/tests/src/Unit/ContentLanguageSettingsUnitTest.php

diff --git a/core/modules/aggregator/src/FeedForm.php b/core/modules/aggregator/src/FeedForm.php
index 251bb44845d3..ea6714ebf804 100644
--- a/core/modules/aggregator/src/FeedForm.php
+++ b/core/modules/aggregator/src/FeedForm.php
@@ -29,6 +29,7 @@ public function form(array $form, FormStateInterface $form_state) {
     // @todo: convert to a language selection widget defined in the base field.
     //   Blocked on https://drupal.org/node/2226493 which adds a generic
     //   language widget.
+    // Language module may expose or hide this element, see language_form_alter().
     $form['langcode'] = array(
       '#title' => $this->t('Language'),
       '#type' => 'language_select',
diff --git a/core/modules/block_content/src/BlockContentForm.php b/core/modules/block_content/src/BlockContentForm.php
index 769a7f30fdba..877c180c606a 100644
--- a/core/modules/block_content/src/BlockContentForm.php
+++ b/core/modules/block_content/src/BlockContentForm.php
@@ -13,6 +13,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -103,22 +104,13 @@ public function form(array $form, FormStateInterface $form_state) {
     // names.
     $form['#attributes']['class'][0] = drupal_html_class('block-' . $block->bundle() . '-form');
 
-    if ($this->moduleHandler->moduleExists('language')) {
-      $language_configuration = language_get_default_configuration('block_content', $block->bundle());
-
-      // Set the correct default language.
-      if ($block->isNew()) {
-        $language_default = $this->languageManager->getCurrentLanguage($language_configuration['langcode']);
-        $block->langcode->value = $language_default->getId();
-      }
-    }
-
     $form['langcode'] = array(
       '#title' => $this->t('Language'),
       '#type' => 'language_select',
       '#default_value' => $block->getUntranslated()->language()->getId(),
       '#languages' => LanguageInterface::STATE_ALL,
-      '#access' => isset($language_configuration['language_show']) && $language_configuration['language_show'],
+      // Language module may expose or hide this element, see language_form_alter().
+      '#access' => FALSE,
     );
 
     $form['advanced'] = array(
diff --git a/core/modules/block_content/src/BlockContentTypeForm.php b/core/modules/block_content/src/BlockContentTypeForm.php
index 3e40858588d2..8cde318f013f 100644
--- a/core/modules/block_content/src/BlockContentTypeForm.php
+++ b/core/modules/block_content/src/BlockContentTypeForm.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\language\Entity\ContentLanguageSettings;
 
 /**
  * Base form for category edit forms.
@@ -65,7 +66,7 @@ public function form(array $form, FormStateInterface $form_state) {
         '#group' => 'additional_settings',
       );
 
-      $language_configuration = language_get_default_configuration('block_content', $block_type->id());
+      $language_configuration = ContentLanguageSettings::loadByEntityTypeBundle('block_content', $block_type->id());
       $form['language']['language_configuration'] = array(
         '#type' => 'language_configuration',
         '#entity_information' => array(
diff --git a/core/modules/comment/src/CommentForm.php b/core/modules/comment/src/CommentForm.php
index 35e033d95714..1062358cb51d 100644
--- a/core/modules/comment/src/CommentForm.php
+++ b/core/modules/comment/src/CommentForm.php
@@ -17,6 +17,7 @@
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -161,13 +162,13 @@ public function form(array $form, FormStateInterface $form_state) {
       $form['author']['name']['#attributes']['data-drupal-default-value'] = $this->config('user.settings')->get('anonymous');
     }
 
-    $language_configuration = \Drupal::moduleHandler()->invoke('language', 'get_default_configuration', array('comment', $comment->getTypeId()));
     $form['langcode'] = array(
       '#title' => t('Language'),
       '#type' => 'language_select',
       '#default_value' => $comment->getUntranslated()->language()->getId(),
       '#languages' => Language::STATE_ALL,
-      '#access' => isset($language_configuration['language_show']) && $language_configuration['language_show'],
+      // Language module may expose or hide this element, see language_form_alter().
+      '#access' => FALSE,
     );
 
     // Add author email and homepage fields depending on the current user.
diff --git a/core/modules/comment/src/CommentTypeForm.php b/core/modules/comment/src/CommentTypeForm.php
index 1f2cb34c26e6..db9361aa18e5 100644
--- a/core/modules/comment/src/CommentTypeForm.php
+++ b/core/modules/comment/src/CommentTypeForm.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Psr\Log\LoggerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -132,7 +133,7 @@ public function form(array $form, FormStateInterface $form_state) {
         '#group' => 'additional_settings',
       );
 
-      $language_configuration = language_get_default_configuration('comment', $comment_type->id());
+      $language_configuration = ContentLanguageSettings::loadByEntityTypeBundle('comment', $comment_type->id());
       $form['language']['language_configuration'] = array(
         '#type' => 'language_configuration',
         '#entity_information' => array(
diff --git a/core/modules/comment/src/Tests/CommentLanguageTest.php b/core/modules/comment/src/Tests/CommentLanguageTest.php
index 03007bfc150e..0ddba12aa6ba 100644
--- a/core/modules/comment/src/Tests/CommentLanguageTest.php
+++ b/core/modules/comment/src/Tests/CommentLanguageTest.php
@@ -44,7 +44,7 @@ protected function setUp() {
     $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
 
     // Set "Article" content type to use multilingual support.
-    $edit = array('language_configuration[language_show]' => TRUE);
+    $edit = array('language_configuration[language_alterable]' => TRUE);
     $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
 
     // Enable content language negotiation UI.
diff --git a/core/modules/contact/src/MessageForm.php b/core/modules/contact/src/MessageForm.php
index 0e280cb45acc..290ddbfdbad8 100644
--- a/core/modules/contact/src/MessageForm.php
+++ b/core/modules/contact/src/MessageForm.php
@@ -98,13 +98,13 @@ public function form(array $form, FormStateInterface $form_state) {
       $form['preview']['message'] = $this->entityManager->getViewBuilder('contact_message')->view($message, 'full');
     }
 
-    $language_configuration = $this->moduleHandler->invoke('language', 'get_default_configuration', array('contact_message', $message->getContactForm()->id()));
     $form['langcode'] = array(
       '#title' => $this->t('Language'),
       '#type' => 'language_select',
       '#default_value' => $message->getUntranslated()->language()->getId(),
       '#languages' => Language::STATE_ALL,
-      '#access' => isset($language_configuration['language_show']) && $language_configuration['language_show'],
+      // Language module may expose or hide this element, see language_form_alter().
+      '#access' => FALSE,
     );
 
     $form['name'] = array(
diff --git a/core/modules/content_translation/content_translation.admin.inc b/core/modules/content_translation/content_translation.admin.inc
index 3f08c9a8cbc6..6b87a15423b6 100644
--- a/core/modules/content_translation/content_translation.admin.inc
+++ b/core/modules/content_translation/content_translation.admin.inc
@@ -266,7 +266,7 @@ function content_translation_form_language_content_settings_validate(array $form
         }
 
         $values = $bundle_settings['settings']['language'];
-        if (empty($values['language_show']) && \Drupal::languageManager()->isLanguageLocked($values['langcode'])) {
+        if (empty($values['language_alterable']) && \Drupal::languageManager()->isLanguageLocked($values['langcode'])) {
           foreach (\Drupal::languageManager()->getLanguages(LanguageInterface::STATE_LOCKED) as $language) {
             $locked_languages[] = $language->getName();
           }
diff --git a/core/modules/content_translation/content_translation.admin.js b/core/modules/content_translation/content_translation.admin.js
index 109cb34fa524..c10efa1bfe38 100644
--- a/core/modules/content_translation/content_translation.admin.js
+++ b/core/modules/content_translation/content_translation.admin.js
@@ -90,7 +90,7 @@
         var $settings = $bundleSettings.nextUntil('.bundle-settings');
         var $fieldSettings = $settings.filter('.field-settings');
         if ($target.is(':checked')) {
-          $bundleSettings.find('.operations :input[name$="[language_show]"]').prop('checked', true);
+          $bundleSettings.find('.operations :input[name$="[language_alterable]"]').prop('checked', true);
           $fieldSettings.find('.translatable :input').prop('checked', true);
           $settings.show();
         }
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index ffa5d89b6601..df1e07756649 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -675,7 +675,7 @@ function content_translation_language_configuration_element_process(array $eleme
 function content_translation_language_configuration_element_validate($element, FormStateInterface $form_state, array $form) {
   $key = $form_state->get(['content_translation', 'key']);
   $values = $form_state->getValue($key);
-  if (!$values['language_show'] && $values['content_translation'] && \Drupal::languageManager()->isLanguageLocked($values['langcode'])) {
+  if (!$values['language_alterable'] && $values['content_translation'] && \Drupal::languageManager()->isLanguageLocked($values['langcode'])) {
     foreach (\Drupal::languageManager()->getLanguages(LanguageInterface::STATE_LOCKED) as $language) {
       $locked_languages[] = $language->getName();
     }
diff --git a/core/modules/content_translation/src/Tests/ContentTranslationContextualLinksTest.php b/core/modules/content_translation/src/Tests/ContentTranslationContextualLinksTest.php
index b8234b31b683..31728271c0c7 100644
--- a/core/modules/content_translation/src/Tests/ContentTranslationContextualLinksTest.php
+++ b/core/modules/content_translation/src/Tests/ContentTranslationContextualLinksTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Serialization\Json;
 use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Drupal\node\Entity\NodeType;
 use Drupal\simpletest\WebTestBase;
 
@@ -100,11 +101,10 @@ protected function setUp() {
       ->save();
 
     // Enable content translation.
-    $configuration = array(
-      'langcode' => language_default()->getId(),
-      'language_show' => TRUE,
-    );
-    language_save_default_configuration('node', $this->bundle, $configuration);
+    ContentLanguageSettings::loadByEntityTypeBundle('node', $this->bundle)
+      ->setLanguageAlterable(TRUE)
+      ->setDefaultLangcode(\Drupal::languageManager()->getDefaultLanguage()->getId())
+      ->save();
     // Create a translator user.
     $permissions = array(
       'access contextual links',
diff --git a/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php b/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php
index fa7488a43472..a2620ec5d47b 100644
--- a/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php
+++ b/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Field\Entity\BaseFieldOverride;
 use Drupal\Core\Language\Language;
 use Drupal\field\Entity\FieldConfig;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -93,7 +94,7 @@ function testSettingsUI() {
     $edit = array(
       'entity_types[comment]' => TRUE,
       'settings[comment][comment_article][settings][language][langcode]' => Language::LANGCODE_NOT_SPECIFIED,
-      'settings[comment][comment_article][settings][language][language_show]' => FALSE,
+      'settings[comment][comment_article][settings][language][language_alterable]' => FALSE,
       'settings[comment][comment_article][translatable]' => TRUE,
       'settings[comment][comment_article][fields][comment_body]' => TRUE,
     );
@@ -105,7 +106,7 @@ function testSettingsUI() {
     $edit = array(
       'entity_types[comment]' => TRUE,
       'settings[comment][comment_article][settings][language][langcode]' => 'current_interface',
-      'settings[comment][comment_article][settings][language][language_show]' => TRUE,
+      'settings[comment][comment_article][settings][language][language_alterable]' => TRUE,
       'settings[comment][comment_article][translatable]' => TRUE,
       'settings[comment][comment_article][fields][comment_body]' => TRUE,
       // Override both comment subject fields to untranslatable.
@@ -137,9 +138,9 @@ function testSettingsUI() {
     $this->assertTrue($definitions['name']->isTranslatable() && !$definitions['user_id']->isTranslatable(), 'Base field bundle overrides were correctly altered.');
 
     // Test that language settings are correctly stored.
-    $language_configuration = language_get_default_configuration('comment', 'comment_article');
-    $this->assertEqual($language_configuration['langcode'], 'current_interface', 'The default language for article comments is set to the current interface language.');
-    $this->assertTrue($language_configuration['language_show'], 'The language selector for article comments is shown.');
+    $language_configuration = ContentLanguageSettings::loadByEntityTypeBundle('comment', 'comment_article');
+    $this->assertEqual($language_configuration->getDefaultLangcode(), 'current_interface', 'The default language for article comments is set to the current interface language.');
+    $this->assertTrue($language_configuration->isLanguageAlterable(), 'The language selector for article comments is shown.');
 
     // Verify language widget appears on comment type form.
     $this->drupalGet('admin/structure/comment/manage/comment_article');
@@ -162,7 +163,7 @@ function testSettingsUI() {
     $edit = array(
       'entity_types[node]' => TRUE,
       'settings[node][article][settings][language][langcode]' => 'current_interface',
-      'settings[node][article][settings][language][language_show]' => TRUE,
+      'settings[node][article][settings][language][language_alterable]' => TRUE,
       'settings[node][article][translatable]' => TRUE,
       'settings[node][article][fields][title]' => TRUE
     );
@@ -259,7 +260,7 @@ function testFieldTranslatableSettingsUI() {
     // Note: this field is not translatable when enable bundle translatability.
     $edit = array(
       'entity_types[node]' => TRUE,
-      'settings[node][article][settings][language][language_show]' => TRUE,
+      'settings[node][article][settings][language][language_alterable]' => TRUE,
       'settings[node][article][translatable]' => TRUE,
       'settings[node][article][fields][article_text]' => TRUE,
     );
diff --git a/core/modules/language/config/schema/language.schema.yml b/core/modules/language/config/schema/language.schema.yml
index 2633fdc01fa3..24025f2cfca7 100644
--- a/core/modules/language/config/schema/language.schema.yml
+++ b/core/modules/language/config/schema/language.schema.yml
@@ -101,34 +101,30 @@ language.entity.*:
       type: boolean
       label: 'Locked'
 
-language.settings:
-  type: mapping
-  label: 'Language settings'
+language.content_settings.*.*:
+  type: config_entity
+  label: 'Content Language Settings'
   mapping:
-    entities:
+    id:
+      type: string
+      label: 'ID'
+    target_entity_type_id:
+      type: string
+      label: 'Entity Type ID'
+    target_bundle:
+      type:  string
+      label: 'Bundle'
+    default_langcode:
+      type: string
+      label: 'Default language'
+    language_alterable:
+      type: boolean
+      label: 'Allow to alter the language'
+    third_party_settings:
       type: sequence
-      label: 'Entity type'
+      label: 'Third party settings'
       sequence:
-        - type: sequence
-          label: 'Bundle'
-          sequence:
-            - type: mapping
-              label: 'Custom language settings'
-              mapping:
-                language:
-                  type: mapping
-                  label: 'Custom language settings'
-                  mapping:
-                    default_configuration:
-                      type: mapping
-                      label: 'Default language'
-                      mapping:
-                        langcode:
-                          type: string
-                          label: 'Default language'
-                        language_show:
-                          type: boolean
-                          label: 'Show language selector on create and edit pages'
+        - type: content_settings.third_party.[%key]
 
 condition.plugin.language:
   type: condition.plugin
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 6901c91c579c..bb5cbef0247e 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -5,14 +5,17 @@
  * Add language handling functionality to Drupal.
  */
 
+use Drupal\Component\Utility\String;
+use Drupal\Core\Entity\ContentEntityFormInterface;
+use Drupal\Core\Entity\EntityFormInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\language\ConfigurableLanguageInterface;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUI;
 use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
 use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrlFallback;
-use Drupal\node\NodeTypeInterface;
 
 /**
  * Implements hook_help().
@@ -176,92 +179,35 @@ function language_process_language_select($element) {
 function language_configuration_element_submit(&$form, FormStateInterface $form_state) {
   // Iterate through all the language_configuration elements and save their
   // values.
+  // In case we are editing a bundle, we must check the new bundle name,
+  // because e.g. hook_ENTITY_update fired before.
   if ($language = $form_state->get('language')) {
     foreach ($language as $element_name => $values) {
-      language_save_default_configuration($values['entity_type'], $values['bundle'],  $form_state->getValue($element_name));
+      $entity_type_id = $values['entity_type'];
+      $bundle = $values['bundle'];
+      $form_object = $form_state->getFormObject();
+      if ($form_object instanceof EntityFormInterface && !$form_object->getEntity()->isNew() && in_array($form_object->getOperation(), ['default', 'edit'])) {
+        /** @var EntityFormInterface $form_object */
+        $entity = $form_object->getEntity();
+        if ($entity->getEntityType()->getBundleOf()) {
+          $bundle = $entity->id();
+        }
+      }
+      $config = ContentLanguageSettings::loadByEntityTypeBundle($entity_type_id, $bundle);
+      $config->setDefaultLangcode($form_state->getValue(array($element_name, 'langcode')));
+      $config->setLanguageAlterable($form_state->getValue(array($element_name, 'language_alterable')));
+      $config->save();
     }
   }
 }
 
 /**
- * Saves a language configuration that is attached to an entity type and bundle.
- *
- * @param string $entity_type
- *   A string representing the entity type.
- * @param string $bundle
- *   A string representing the bundle.
- * @param array $values
- *   An array holding the values to be saved having the following keys:
- *   - langcode: the language code.
- *   - language_show: if the language element should be hidden or not.
- */
-function language_save_default_configuration($entity_type, $bundle, $values = array()) {
-  \Drupal::config('language.settings')->set(language_get_default_configuration_settings_key($entity_type, $bundle), array('langcode' => $values['langcode'], 'language_show' => $values['language_show']))->save();
-}
-
-/**
- * Returns the language configuration stored for an entity type and bundle.
- *
- * @param string $entity_type
- *   A string representing the entity type.
- * @param string $bundle
- *   A string representing the bundle.
- *
- * @return array
- *   An array with the following keys:
- *   - langcode: the language code.
- *   - language_show: if the language element is hidden or not.
- */
-function language_get_default_configuration($entity_type, $bundle) {
-  $configuration = \Drupal::config('language.settings')->get(language_get_default_configuration_settings_key($entity_type, $bundle));
-  if (is_null($configuration)) {
-    $configuration = array();
-  }
-  $configuration += array('langcode' => LanguageInterface::LANGCODE_SITE_DEFAULT, 'language_show' => FALSE);
-  return $configuration;
-}
-
-/**
- * Clears the default language configuration for an entity type and bundle.
- *
- * @param string $entity_type
- *   A string representing the entity type.
- * @param string $bundle
- *   A string representing the bundle.
- */
-function language_clear_default_configuration($entity_type, $bundle) {
-  \Drupal::config('language.settings')->clear(language_get_default_configuration_settings_key($entity_type, $bundle))->save();
-}
-
-/**
- * Returns the root name of the variables used to store the configuration.
- *
- * Based on the entity type and bundle, the variables used to store the
- * configuration will have a common root name.
- *
- * @param string $entity_type
- *   A string representing the entity type.
- * @param string $bundle
- *   A string representing the bundle.
- *
- * @return string
- *   The root name of the variables.
- */
-function language_get_default_configuration_settings_key($entity_type, $bundle) {
-  // Replace all the characters that are not letters, numbers or "_" with "_".
-  $entity_type = preg_replace('/[^0-9a-zA-Z_]/', "_", $entity_type);
-  $bundle = preg_replace('/[^0-9a-zA-Z_]/', "_", $bundle);
-  return 'entities.' . $entity_type . '.' . $bundle . '.language.default_configuration';
-}
-
-/**
- * Implements hook_ENTITY_TYPE_update() for node_type entities.
+ * Implements hook_entity_bundle_rename().
  */
-function language_node_type_update(NodeTypeInterface $type) {
-  if ($type->original->id() != $type->id()) {
-    language_save_default_configuration('node', $type->id(), language_get_default_configuration('node', $type->original->id()));
-    language_clear_default_configuration('node', $type->original->id());
-  }
+function language_entity_bundle_rename($entity_type_id, $bundle_old, $bundle_new) {
+  ContentLanguageSettings::loadByEntityTypeBundle($entity_type_id, $bundle_old)
+    ->setTargetBundle($bundle_new)
+    ->save();
 }
 
 /**
@@ -276,15 +222,11 @@ function language_node_type_update(NodeTypeInterface $type) {
  *   The language code.
  */
 function language_get_default_langcode($entity_type, $bundle) {
-  $configuration = language_get_default_configuration($entity_type, $bundle);
-
-  if (!isset($configuration['langcode'])) {
-    $configuration['langcode'] = LanguageInterface::LANGCODE_SITE_DEFAULT;
-  }
+  $configuration = ContentLanguageSettings::loadByEntityTypeBundle($entity_type, $bundle);
 
   $default_value = NULL;
   $language_interface = \Drupal::languageManager()->getCurrentLanguage();
-  switch ($configuration['langcode']) {
+  switch ($configuration->getDefaultLangcode()) {
     case LanguageInterface::LANGCODE_SITE_DEFAULT:
       $default_value = \Drupal::languageManager()->getDefaultLanguage()->getId();
       break;
@@ -310,7 +252,7 @@ function language_get_default_langcode($entity_type, $bundle) {
 
   // If we still do not have a default value, just return the value stored in
   // the configuration; it has to be an actual language code.
-  return $configuration['langcode'];
+  return $configuration->getDefaultLangcode();
 }
 
 /**
@@ -504,6 +446,25 @@ function language_form_system_regional_settings_alter(&$form, FormStateInterface
   $form['#submit'][] = 'language_system_regional_settings_form_submit';
 }
 
+/**
+ * Implements hook_form_alter().
+ */
+function language_form_alter(&$form, FormStateInterface $form_state, $form_id) {
+  // Content entity forms may have added a langcode field. But content language
+  // configuration should decide if it should be exposed or not in the forms.
+  $form_object = $form_state->getFormObject();
+  if ($form_object instanceof ContentEntityFormInterface && isset($form['langcode'])) {
+    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
+    $entity_type_id = $form_object->getEntity()->getEntityTypeId();
+    $bundle = $form_object->getEntity()->bundle();
+    $entity_type = Drupal::entityManager()->getDefinition($entity_type_id);
+    if ($entity_type->isTranslatable()) {
+      $language_configuration = ContentLanguageSettings::loadByEntityTypeBundle($entity_type_id, $bundle);
+      $form['langcode']['#access'] = $language_configuration->isLanguageAlterable();
+    }
+  }
+}
+
 /**
  * Form submission handler for system_regional_settings().
  *
diff --git a/core/modules/language/src/ContentLanguageSettingsException.php b/core/modules/language/src/ContentLanguageSettingsException.php
new file mode 100644
index 000000000000..75592f52c6eb
--- /dev/null
+++ b/core/modules/language/src/ContentLanguageSettingsException.php
@@ -0,0 +1,13 @@
+<?php
+
+/*
+ * @file
+ * Contains \Drupal\language\ContentLanguageSettingsException.
+ */
+
+namespace Drupal\language;
+
+/**
+ * Exception thrown by ContentLanguageSettings when target bundle is not set.
+ */
+class ContentLanguageSettingsException extends \RuntimeException {}
diff --git a/core/modules/language/src/ContentLanguageSettingsInterface.php b/core/modules/language/src/ContentLanguageSettingsInterface.php
new file mode 100644
index 000000000000..56f847293301
--- /dev/null
+++ b/core/modules/language/src/ContentLanguageSettingsInterface.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\ContentLanguageSettingsInterface.
+ */
+
+namespace Drupal\language;
+
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\Core\Config\Entity\ThirdPartySettingsInterface;
+
+/**
+ * Provides an interface defining language settings for content entities.
+ */
+interface ContentLanguageSettingsInterface extends ConfigEntityInterface, ThirdPartySettingsInterface {
+
+  /**
+   * Gets the entity type ID this config applies to.
+   *
+   * @return string
+   */
+  public function getTargetEntityTypeId();
+
+  /**
+   * Gets the bundle this config applies to.
+   *
+   * @return string
+   */
+  public function getTargetBundle();
+
+  /**
+   * Sets the bundle this config applies to.
+   *
+   * @param string $target_bundle
+   *   The bundle.
+   *
+   * @return $this
+   */
+  public function setTargetBundle($target_bundle);
+
+  /**
+   * Sets the default language code.
+   *
+   * @param string $default_langcode
+   *   The default language code.
+   *
+   * @return $this;
+   */
+  public function setDefaultLangcode($default_langcode);
+
+  /**
+   * Gets the default language code.
+   *
+   * @return string
+   */
+  public function getDefaultLangcode();
+
+  /**
+   * Sets if the language must be alterable or not.
+   *
+   * @param bool $language_alterable
+   *   Flag indicating if the language must be alterable.
+   *
+   * @return $this
+   */
+  public function setLanguageAlterable($language_alterable);
+
+  /**
+   * Checks if the language is alterable or not.
+   *
+   * @return bool
+   */
+  public function isLanguageAlterable();
+
+  /**
+   * Checks if this config object contains the default values in every property.
+   *
+   * @return bool
+   *   True if all the properties contain the default values. False otherwise.
+   */
+  public function isDefaultConfiguration();
+
+}
+
diff --git a/core/modules/language/src/Element/LanguageConfiguration.php b/core/modules/language/src/Element/LanguageConfiguration.php
index 5ae8b0022170..ad998f71ada9 100644
--- a/core/modules/language/src/Element/LanguageConfiguration.php
+++ b/core/modules/language/src/Element/LanguageConfiguration.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Render\Element\FormElement;
+use Drupal\language\Entity\ContentLanguageSettings;
 
 /**
  * Provides language element configuration.
@@ -40,24 +41,26 @@ public static function processLanguageConfiguration(&$element, FormStateInterfac
     // Avoid validation failure since we are moving the '#options' key in the
     // nested 'language' select element.
     unset($element['#options']);
+    /** @var ContentLanguageSettings $default_config */
+    $default_config = $element['#default_value'];
     $element['langcode'] = array(
       '#type' => 'select',
       '#title' => t('Default language'),
       '#options' => $options + static::getDefaultOptions(),
       '#description' => t('Explanation of the language options is found on the <a href="@languages_list_page">languages list page</a>.', array('@languages_list_page' => \Drupal::url('language.admin_overview'))),
-      '#default_value' => isset($element['#default_value']['langcode']) ? $element['#default_value']['langcode'] : NULL,
+      '#default_value' => ($default_config != NULL) ? $default_config->getDefaultLangcode() : LanguageInterface::LANGCODE_SITE_DEFAULT,
     );
 
-    $element['language_show'] = array(
+    $element['language_alterable'] = array(
       '#type' => 'checkbox',
       '#title' => t('Show language selector on create and edit pages'),
-      '#default_value' => isset($element['#default_value']['language_show']) ? $element['#default_value']['language_show'] : NULL,
+      '#default_value' => ($default_config != NULL) ? $default_config->isLanguageAlterable() : FALSE,
     );
 
     // Add the entity type and bundle information to the form if they are set.
     // They will be used, in the submit handler, to generate the names of the
-    // variables that will store the settings and are a way to uniquely identify
-    // the entity.
+    // configuration entities that will store the settings and are a way to uniquely
+    // identify the entity.
     $language = $form_state->get('language') ?: [];
     $language += array(
       $element['#name'] => array(
diff --git a/core/modules/language/src/Entity/ContentLanguageSettings.php b/core/modules/language/src/Entity/ContentLanguageSettings.php
new file mode 100644
index 000000000000..607fb4cd580f
--- /dev/null
+++ b/core/modules/language/src/Entity/ContentLanguageSettings.php
@@ -0,0 +1,213 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\Entity\ContentLanguageSettings.
+ */
+
+namespace Drupal\language\Entity;
+
+use Drupal\Component\Utility\String;
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Config\Entity\ThirdPartySettingsTrait;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\language\ContentLanguageSettingsException;
+use Drupal\language\ContentLanguageSettingsInterface;
+
+/**
+ * Defines the ContentLanguageSettings entity.
+ *
+ * @ConfigEntityType(
+ *   id = "language_content_settings",
+ *   label = @Translation("Content Language Settings"),
+ *   admin_permission = "administer languages",
+ *   config_prefix = "content_settings",
+ *   entity_keys = {
+ *     "id" = "id"
+ *   },
+ * )
+ */
+class ContentLanguageSettings extends ConfigEntityBase implements ContentLanguageSettingsInterface {
+
+  use ThirdPartySettingsTrait;
+
+  /**
+   * The id. Combination of $target_entity_type_id.$target_bundle.
+   *
+   * @var string
+   */
+  protected $id;
+
+  /**
+   * The entity type ID (machine name).
+   *
+   * @var string
+   */
+  protected $target_entity_type_id;
+
+  /**
+   * The bundle (machine name).
+   *
+   * @var string
+   */
+  protected $target_bundle;
+
+  /**
+   * The default language code.
+   *
+   * @var string
+   */
+  protected $default_langcode = LanguageInterface::LANGCODE_SITE_DEFAULT;
+
+  /**
+   * Indicates if the language is alterable or not.
+   *
+   * @var bool
+   */
+  protected $language_alterable = FALSE;
+
+  /**
+   * Constructs a ContentLanguageSettings object.
+   *
+   * In most cases, Field entities are created via
+   * entity_create('field_config', $values), where $values is the same
+   * parameter as in this constructor.
+   *
+   * @param array $values
+   *   An array of the referring entity bundle with:
+   *   - target_entity_type_id: The entity type.
+   *   - target_bundle: The bundle.
+   *   Other array elements will be used to set the corresponding properties on
+   *   the class; see the class property documentation for details.
+   *
+   * @see entity_create()
+   */
+  public function __construct(array $values, $entity_type = 'language_content_settings') {
+    if (empty($values['target_entity_type_id'])) {
+      throw new ContentLanguageSettingsException('Attempt to create content language settings without a target_entity_type_id.');
+    }
+    if (empty($values['target_bundle'])) {
+      throw new ContentLanguageSettingsException('Attempt to create content language settings without a target_bundle.');
+    }
+    parent::__construct($values, $entity_type);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function id() {
+    return $this->target_entity_type_id . '.' . $this->target_bundle;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTargetEntityTypeId() {
+    return $this->target_entity_type_id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTargetBundle() {
+    return $this->target_bundle;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setTargetBundle($target_bundle) {
+    $this->target_bundle = $target_bundle;
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setDefaultLangcode($default_langcode) {
+    $this->default_langcode = $default_langcode;
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefaultLangcode() {
+    return $this->default_langcode;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setLanguageAlterable($language_alterable) {
+    $this->language_alterable = $language_alterable;
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isLanguageAlterable() {
+    return $this->language_alterable;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preSave(EntityStorageInterface $storage) {
+    $this->id = $this->id();
+    parent::preSave($storage);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isDefaultConfiguration() {
+    return (!$this->language_alterable && $this->default_langcode == LanguageInterface::LANGCODE_SITE_DEFAULT);
+  }
+
+  /**
+   * Loads a content language config entity based on the entity type and bundle.
+   *
+   * @param string $entity_type_id
+   *   ID of the entity type.
+   * @param string $bundle
+   *   Bundle name.
+   *
+   * @return $this
+   *   The content language config entity if one exists. Otherwise, returns
+   *   default values.
+   */
+  public static function loadByEntityTypeBundle($entity_type_id, $bundle) {
+    if ($entity_type_id == NULL || $bundle == NULL) {
+      return NULL;
+    }
+    $config = \Drupal::entityManager()->getStorage('language_content_settings')->load($entity_type_id . '.' . $bundle);
+    if ($config == NULL) {
+      $config = ContentLanguageSettings::create(['target_entity_type_id' => $entity_type_id, 'target_bundle' => $bundle]);
+    }
+    return $config;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies() {
+    parent::calculateDependencies();
+    $bundle_entity_type_id = $this->entityManager()->getDefinition($this->target_entity_type_id)->getBundleEntityType();
+    if ($bundle_entity_type_id != 'bundle') {
+      // If the target entity type uses entities to manage its bundles then
+      // depend on the bundle entity.
+      if (!$bundle_entity = $this->entityManager()->getStorage($bundle_entity_type_id)->load($this->target_bundle)) {
+        throw new \LogicException(String::format('Missing bundle entity, entity type %type, entity id %bundle.', array('%type' => $bundle_entity_type_id, '%bundle' => $this->target_bundle)));
+      }
+      $this->addDependency('config', $bundle_entity->getConfigDependencyName());
+    }
+    return $this->dependencies;
+  }
+
+}
diff --git a/core/modules/language/src/Form/ContentLanguageSettingsForm.php b/core/modules/language/src/Form/ContentLanguageSettingsForm.php
index a415379b5757..1e8985038d5b 100644
--- a/core/modules/language/src/Form/ContentLanguageSettingsForm.php
+++ b/core/modules/language/src/Form/ContentLanguageSettingsForm.php
@@ -11,7 +11,7 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\ConfigFormBase;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Language\LanguageInterface;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -76,11 +76,11 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
       // Check whether we have any custom setting.
       foreach ($bundles[$entity_type_id] as $bundle => $bundle_info) {
-        $conf = language_get_default_configuration($entity_type_id, $bundle);
-        if (!empty($conf['language_show']) || $conf['langcode'] != LanguageInterface::LANGCODE_SITE_DEFAULT) {
+        $config = ContentLanguageSettings::loadByEntityTypeBundle($entity_type_id, $bundle);
+        if (!$config->isDefaultConfiguration()) {
           $default[$entity_type_id] = $entity_type_id;
         }
-        $language_configuration[$entity_type_id][$bundle] = $conf;
+        $language_configuration[$entity_type_id][$bundle] = $config;
       }
     }
 
@@ -145,16 +145,14 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
-    $config = $this->config('language.settings');
     foreach ($form_state->getValue('settings') as $entity_type => $entity_settings) {
       foreach ($entity_settings as $bundle => $bundle_settings) {
-        $config->set(language_get_default_configuration_settings_key($entity_type, $bundle), array(
-          'langcode' => $bundle_settings['settings']['language']['langcode'],
-          'language_show' => $bundle_settings['settings']['language']['language_show'],
-        ));
+        $config = ContentLanguageSettings::loadByEntityTypeBundle($entity_type, $bundle);
+        $config->setDefaultLangcode($bundle_settings['settings']['language']['langcode'])
+          ->setLanguageAlterable($bundle_settings['settings']['language']['language_alterable'])
+          ->save();
       }
     }
-    $config->save();
     drupal_set_message($this->t('Settings successfully updated.'));
   }
 
diff --git a/core/modules/language/src/Tests/EntityDefaultLanguageTest.php b/core/modules/language/src/Tests/EntityDefaultLanguageTest.php
index 12c211dc7353..fa1a7595e4d9 100644
--- a/core/modules/language/src/Tests/EntityDefaultLanguageTest.php
+++ b/core/modules/language/src/Tests/EntityDefaultLanguageTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\language\Tests;
 
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Drupal\simpletest\KernelTestBase;
 
 /**
@@ -110,10 +111,11 @@ protected function createContentType($name, $langcode) {
       'create_body' => FALSE,
     ));
     $content_type->save();
-    language_save_default_configuration('node', $name, array(
-      'langcode' => $langcode,
-      'language_show' => FALSE,
-    ));
+    ContentLanguageSettings::loadByEntityTypeBundle('node', $name)
+      ->setLanguageAlterable(FALSE)
+      ->setDefaultLangcode($langcode)
+      ->save();
+
   }
 
   /**
diff --git a/core/modules/language/src/Tests/LanguageConfigSchemaTest.php b/core/modules/language/src/Tests/LanguageConfigSchemaTest.php
index aeddc2bc4fc7..56dd719eda87 100644
--- a/core/modules/language/src/Tests/LanguageConfigSchemaTest.php
+++ b/core/modules/language/src/Tests/LanguageConfigSchemaTest.php
@@ -56,20 +56,20 @@ function testValidLanguageConfigSchema() {
 
     // Enable translation for menu link.
     $edit['entity_types[menu_link_content]'] = TRUE;
-    $edit['settings[menu_link_content][menu_link_content][settings][language][language_show]'] = TRUE;
+    $edit['settings[menu_link_content][menu_link_content][settings][language][language_alterable]'] = TRUE;
 
     // Enable translation for user.
     $edit['entity_types[user]'] = TRUE;
-    $edit['settings[user][user][settings][language][language_show]'] = TRUE;
+    $edit['settings[user][user][settings][language][language_alterable]'] = TRUE;
     $edit['settings[user][user][settings][language][langcode]'] = 'en';
 
     $this->drupalPostForm($settings_path, $edit, t('Save configuration'));
 
-    $config_data = \Drupal::config('language.settings')->get();
+    $config_data = \Drupal::config('language.content_settings.menu_link_content.menu_link_content');
     // Make sure configuration saved correctly.
-    $this->assertTrue($config_data['entities']['menu_link_content']['menu_link_content']['language']['default_configuration']['language_show']);
+    $this->assertTrue($config_data->get('language_alterable'));
 
-    $this->assertConfigSchema(\Drupal::service('config.typed'), 'language.settings', $config_data);
+    $this->assertConfigSchema(\Drupal::service('config.typed'), $config_data->getName(), $config_data->get());
   }
 
 }
diff --git a/core/modules/language/src/Tests/LanguageConfigurationElementTest.php b/core/modules/language/src/Tests/LanguageConfigurationElementTest.php
index 9b2d82d27912..fb50294b41ed 100644
--- a/core/modules/language/src/Tests/LanguageConfigurationElementTest.php
+++ b/core/modules/language/src/Tests/LanguageConfigurationElementTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -23,7 +24,7 @@ class LanguageConfigurationElementTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('node', 'language', 'language_elements_test');
+  public static $modules = array('taxonomy', 'node', 'language', 'language_elements_test');
 
   /**
    * Tests the language settings have been saved.
@@ -31,30 +32,30 @@ class LanguageConfigurationElementTest extends WebTestBase {
   public function testLanguageConfigurationElement() {
     $this->drupalGet('language-tests/language_configuration_element');
     $edit['lang_configuration[langcode]'] = 'current_interface';
-    $edit['lang_configuration[language_show]'] = FALSE;
+    $edit['lang_configuration[language_alterable]'] = FALSE;
     $this->drupalPostForm(NULL, $edit, 'Save');
-    $lang_conf = language_get_default_configuration('some_custom_type', 'some_bundle');
+    $lang_conf = ContentLanguageSettings::loadByEntityTypeBundle('entity_test', 'some_bundle');
 
     // Check that the settings have been saved.
-    $this->assertEqual($lang_conf['langcode'], 'current_interface');
-    $this->assertFalse($lang_conf['language_show']);
+    $this->assertEqual($lang_conf->getDefaultLangcode(), 'current_interface');
+    $this->assertFalse($lang_conf->isLanguageAlterable());
     $this->drupalGet('language-tests/language_configuration_element');
     $this->assertOptionSelected('edit-lang-configuration-langcode', 'current_interface');
-    $this->assertNoFieldChecked('edit-lang-configuration-language-show');
+    $this->assertNoFieldChecked('edit-lang-configuration-language-alterable');
 
     // Reload the page and save again.
     $this->drupalGet('language-tests/language_configuration_element');
     $edit['lang_configuration[langcode]'] = 'authors_default';
-    $edit['lang_configuration[language_show]'] = TRUE;
+    $edit['lang_configuration[language_alterable]'] = TRUE;
     $this->drupalPostForm(NULL, $edit, 'Save');
-    $lang_conf = language_get_default_configuration('some_custom_type', 'some_bundle');
+    $lang_conf = ContentLanguageSettings::loadByEntityTypeBundle('entity_test', 'some_bundle');
 
     // Check that the settings have been saved.
-    $this->assertEqual($lang_conf['langcode'], 'authors_default');
-    $this->assertTrue($lang_conf['language_show']);
+    $this->assertEqual($lang_conf->getDefaultLangcode(), 'authors_default');
+    $this->assertTrue($lang_conf->isLanguageAlterable());
     $this->drupalGet('language-tests/language_configuration_element');
     $this->assertOptionSelected('edit-lang-configuration-langcode', 'authors_default');
-    $this->assertFieldChecked('edit-lang-configuration-language-show');
+    $this->assertFieldChecked('edit-lang-configuration-language-alterable');
   }
 
   /**
@@ -70,13 +71,21 @@ public function testDefaultLangcode() {
     }
 
     // Fixed language.
-    language_save_default_configuration('custom_type', 'custom_bundle', array('langcode' => 'bb', 'language_show' => TRUE));
-    $langcode = language_get_default_langcode('custom_type', 'custom_bundle');
+    ContentLanguageSettings::loadByEntityTypeBundle('entity_test', 'custom_bundle')
+      ->setLanguageAlterable(TRUE)
+      ->setDefaultLangcode('bb')
+      ->save();
+
+    $langcode = language_get_default_langcode('entity_test', 'custom_bundle');
     $this->assertEqual($langcode, 'bb');
 
     // Current interface.
-    language_save_default_configuration('custom_type', 'custom_bundle', array('langcode' => 'current_interface', 'language_show' => TRUE));
-    $langcode = language_get_default_langcode('custom_type', 'custom_bundle');
+    ContentLanguageSettings::loadByEntityTypeBundle('entity_test', 'custom_bundle')
+      ->setLanguageAlterable(TRUE)
+      ->setDefaultLangcode('current_interface')
+      ->save();
+
+    $langcode = language_get_default_langcode('entity_test', 'custom_bundle');
     $language_interface = \Drupal::languageManager()->getCurrentLanguage();
     $this->assertEqual($langcode, $language_interface->getId());
 
@@ -87,8 +96,11 @@ public function testDefaultLangcode() {
     $this->assertTrue($configurable_language->isDefault(), 'The en language entity is flagged as the default language.');
 
     \Drupal::config('system.site')->set('langcode', 'cc')->save();
-    language_save_default_configuration('custom_type', 'custom_bundle', array('langcode' => LanguageInterface::LANGCODE_SITE_DEFAULT, 'language_show' => TRUE));
-    $langcode = language_get_default_langcode('custom_type', 'custom_bundle');
+    ContentLanguageSettings::loadByEntityTypeBundle('entity_test','custom_bundle')
+      ->setLanguageAlterable(TRUE)
+      ->setDefaultLangcode(LanguageInterface::LANGCODE_SITE_DEFAULT)
+      ->save();
+    $langcode = language_get_default_langcode('entity_test', 'custom_bundle');
     $this->assertEqual($langcode, 'cc');
 
     // Ensure the language entity default value is correct.
@@ -107,7 +119,13 @@ public function testDefaultLangcode() {
     $some_user->preferred_langcode = 'bb';
     $some_user->save();
     $this->drupalLogin($some_user);
-    language_save_default_configuration('custom_type', 'some_bundle', array('langcode' => 'authors_default', 'language_show' => TRUE));
+    ContentLanguageSettings::create([
+      'target_entity_type_id' => 'entity_test',
+      'target_bundle' => 'some_bundle',
+    ])->setLanguageAlterable(TRUE)
+      ->setDefaultLangcode('authors_default')
+      ->save();
+
     $this->drupalGet('language-tests/language_configuration_element_test');
     $this->assertOptionSelected('edit-langcode', 'bb');
   }
@@ -125,19 +143,59 @@ public function testNodeTypeUpdate() {
     $this->drupalLogin($admin_user);
     $edit = array(
       'language_configuration[langcode]' => 'current_interface',
-      'language_configuration[language_show]' => TRUE,
+      'language_configuration[language_alterable]' => TRUE,
     );
     $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
     // Check the language default configuration for the articles.
-    $configuration = language_get_default_configuration('node', 'article');
-    $this->assertEqual($configuration, array('langcode' => 'current_interface', 'language_show' => TRUE), 'The default language configuration has been saved on the Article content type.');
+    $configuration = ContentLanguageSettings::loadByEntityTypeBundle('node', 'article');
+    $uuid = $configuration->uuid();
+    $this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been saved on the Article content type.');
+    $this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been saved on the Article content type.');
     // Rename the article content type.
     $edit = array(
       'type' => 'article_2'
     );
     $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
     // Check that we still have the settings for the new node type.
-    $configuration = language_get_default_configuration('node', 'article_2');
-    $this->assertEqual($configuration, array('langcode' => 'current_interface', 'language_show' => TRUE), 'The default language configuration has been kept on the new Article content type.');
+    $configuration = ContentLanguageSettings::loadByEntityTypeBundle('node', 'article_2');
+    $this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been kept on the new Article content type.');
+    $this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been kept on the new Article content type.');
+    $this->assertEqual($configuration->uuid(), $uuid, 'The language configuration uuid has been kept on the new Article content type.');
   }
+
+  /**
+   * Tests that the configuration is updated when a vocabulary is changed.
+   */
+  public function testTaxonomyVocabularyUpdate() {
+    $vocabulary = entity_create('taxonomy_vocabulary', array(
+      'name' => 'Country',
+      'vid' => 'country',
+    ));
+    $vocabulary->save();
+
+    $admin_user = $this->drupalCreateUser(array('administer taxonomy'));
+    $this->drupalLogin($admin_user);
+    $edit = array(
+      'default_language[langcode]' => 'current_interface',
+      'default_language[language_alterable]' => TRUE,
+    );
+    $this->drupalPostForm('admin/structure/taxonomy/manage/country', $edit, t('Save'));
+
+    // Check the language default configuration.
+    $configuration = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', 'country');
+    $uuid = $configuration->uuid();
+    $this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been saved on the Country vocabulary.');
+    $this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been saved on the Country vocabulary.');
+    // Rename the vocabulary.
+    $edit = array(
+      'vid' => 'nation'
+    );
+    $this->drupalPostForm('admin/structure/taxonomy/manage/country', $edit, t('Save'));
+    // Check that we still have the settings for the new vocabulary.
+    $configuration = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', 'nation');
+    $this->assertEqual($configuration->getDefaultLangcode(), 'current_interface', 'The default language configuration has been kept on the new Country vocabulary.');
+    $this->assertTrue($configuration->isLanguageAlterable(), 'The alterable language configuration has been kept on the new Country vocabulary.');
+    $this->assertEqual($configuration->uuid(), $uuid, 'The language configuration uuid has been kept on the new Country vocabulary.');
+  }
+
 }
diff --git a/core/modules/language/tests/language_elements_test/language_elements_test.info.yml b/core/modules/language/tests/language_elements_test/language_elements_test.info.yml
index d8a3da1f562b..52ed2859be35 100644
--- a/core/modules/language/tests/language_elements_test/language_elements_test.info.yml
+++ b/core/modules/language/tests/language_elements_test/language_elements_test.info.yml
@@ -4,3 +4,5 @@ description: 'Support module for the language form elements tests.'
 core: 8.x
 package: Testing
 version: VERSION
+dependencies:
+  - entity_test
diff --git a/core/modules/language/tests/language_elements_test/src/Form/LanguageConfigurationElement.php b/core/modules/language/tests/language_elements_test/src/Form/LanguageConfigurationElement.php
index f9a0e1bb743d..8dea61c92a48 100644
--- a/core/modules/language/tests/language_elements_test/src/Form/LanguageConfigurationElement.php
+++ b/core/modules/language/tests/language_elements_test/src/Form/LanguageConfigurationElement.php
@@ -8,6 +8,7 @@
 
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\language\Entity\ContentLanguageSettings;
 
 /**
  * A form containing a language configuration element.
@@ -25,12 +26,12 @@ public function getFormID() {
    * {@inheritdoc}
    */
   public function buildForm(array $form, FormStateInterface $form_state) {
-    $conf = language_get_default_configuration('some_custom_type', 'some_bundle');
+    $conf = ContentLanguageSettings::loadByEntityTypeBundle('entity_test', 'some_bundle');
 
     $form['lang_configuration'] = array(
       '#type' => 'language_configuration',
       '#entity_information' => array(
-        'entity_type' => 'some_custom_type',
+        'entity_type' => 'entity_test',
         'bundle' => 'some_bundle',
       ),
       '#default_value' => $conf,
diff --git a/core/modules/language/tests/language_elements_test/src/Form/LanguageConfigurationElementTest.php b/core/modules/language/tests/language_elements_test/src/Form/LanguageConfigurationElementTest.php
index 130c069e9aba..eda727a7a933 100644
--- a/core/modules/language/tests/language_elements_test/src/Form/LanguageConfigurationElementTest.php
+++ b/core/modules/language/tests/language_elements_test/src/Form/LanguageConfigurationElementTest.php
@@ -28,7 +28,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     $form['langcode'] = array(
       '#title' => t('Language select'),
       '#type' => 'language_select',
-      '#default_value' => language_get_default_langcode('custom_type', 'some_bundle'),
+      '#default_value' => language_get_default_langcode('entity_test', 'some_bundle'),
     );
     return $form;
   }
diff --git a/core/modules/language/tests/src/Unit/ContentLanguageSettingsUnitTest.php b/core/modules/language/tests/src/Unit/ContentLanguageSettingsUnitTest.php
new file mode 100644
index 000000000000..fdacb693bf12
--- /dev/null
+++ b/core/modules/language/tests/src/Unit/ContentLanguageSettingsUnitTest.php
@@ -0,0 +1,321 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\language\Unit\ContentLanguageSettingsUnitTest.
+ */
+
+namespace Drupal\Tests\language\Unit;
+
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Drupal\language\Entity\ContentLanguageSettings;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\language\Entity\ContentLanguageSettings
+ * @group language
+ */
+class ContentLanguageSettingsUnitTest extends UnitTestCase {
+
+  /**
+   * The entity type used for testing.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $entityType;
+
+  /**
+   * The entity manager used for testing.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $entityManager;
+
+  /**
+   * The ID of the type of the entity under test.
+   *
+   * @var string
+   */
+  protected $entityTypeId;
+
+  /**
+   * The UUID generator used for testing.
+   *
+   * @var \Drupal\Component\Uuid\UuidInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $uuid;
+
+  /**
+   * The typed configuration manager used for testing.
+   *
+   * @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $typedConfigManager;
+
+  /**
+   * The typed configuration manager used for testing.
+   *
+   * @var \Drupal\Core\Config\Entity\ConfigEntityStorage|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $configEntityStorageInterface;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    $this->entityTypeId = $this->randomMachineName();
+    $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+
+    $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
+
+    $this->uuid = $this->getMock('\Drupal\Component\Uuid\UuidInterface');
+
+    $this->typedConfigManager = $this->getMock('Drupal\Core\Config\TypedConfigManagerInterface');
+
+    $this->configEntityStorageInterface = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
+
+    $container = new ContainerBuilder();
+    $container->set('entity.manager', $this->entityManager);
+    $container->set('uuid', $this->uuid);
+    $container->set('config.typed', $this->typedConfigManager);
+    $container->set('config.storage', $this->configEntityStorageInterface);
+    \Drupal::setContainer($container);
+  }
+
+  /**
+   * @covers ::calculateDependencies
+   */
+  public function testCalculateDependencies() {
+    // Mock the interfaces necessary to create a dependency on a bundle entity.
+    $bundle_entity = $this->getMock('Drupal\Core\Config\Entity\ConfigEntityInterface');
+    $bundle_entity->expects($this->any())
+      ->method('getConfigDependencyName')
+      ->will($this->returnValue('test.test_entity_type.id'));
+
+    $storage = $this->getMock('\Drupal\Core\Config\Entity\ConfigEntityStorageInterface');
+    $storage->expects($this->any())
+      ->method('load')
+      ->with('test_bundle')
+      ->will($this->returnValue($bundle_entity));
+
+    $this->entityManager->expects($this->any())
+      ->method('getStorage')
+      ->with('bundle_entity_type')
+      ->will($this->returnValue($storage));
+
+    $target_entity_type = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+    $target_entity_type->expects($this->any())
+      ->method('getBundleEntityType')
+      ->will($this->returnValue('bundle_entity_type'));
+
+    $this->entityManager->expects($this->any())
+      ->method('getDefinition')
+      ->with('test_entity_type')
+      ->will($this->returnValue($target_entity_type));
+
+    $config = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_bundle',
+    ), 'language_content_settings');
+    $dependencies = $config->calculateDependencies();
+    $this->assertContains('test.test_entity_type.id', $dependencies['config']);
+  }
+
+  /**
+   * @covers ::id()
+   */
+  public function testId() {
+    $config = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_bundle',
+    ), 'language_content_settings');
+    $this->assertSame('test_entity_type.test_bundle', $config->id());
+  }
+
+  /**
+   * @covers ::getTargetEntityTypeId()
+   */
+  public function testTargetEntityTypeId() {
+    $config = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_bundle',
+    ), 'language_content_settings');
+    $this->assertSame('test_entity_type', $config->getTargetEntityTypeId());
+  }
+
+  /**
+   * @covers ::getTargetBundle()
+   */
+  public function testTargetBundle() {
+    $config = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_bundle',
+    ), 'language_content_settings');
+    $this->assertSame('test_bundle', $config->getTargetBundle());
+  }
+
+  /**
+   * @covers ::getDefaultLangcode()
+   * @covers ::setDefaultLangcode()
+   *
+   * @dataProvider providerDefaultLangcode
+   */
+  public function testDefaultLangcode(ContentLanguageSettings $config, $expected) {
+    $this->assertSame($expected, $config->getDefaultLangcode());
+  }
+
+  public function providerDefaultLangcode() {
+    $langcode = $this->randomMachineName();
+    $config = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_bundle',
+    ), 'language_content_settings');
+    $config->setDefaultLangcode($langcode);
+
+    $defaultConfig = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_default_language_bundle',
+    ), 'language_content_settings');
+
+    return [
+      [$config, $langcode],
+      [$defaultConfig, LanguageInterface::LANGCODE_SITE_DEFAULT],
+    ];
+  }
+
+  /**
+   * @covers ::setLanguageAlterable()
+   * @covers ::isLanguageAlterable()
+   *
+   * @dataProvider providerLanguageAlterable
+   */
+  public function testLanguageAlterable(ContentLanguageSettings $config, $expected) {
+    $this->assertSame($expected, $config->isLanguageAlterable());
+  }
+
+  public function providerLanguageAlterable() {
+    $alterableConfig = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_bundle',
+    ), 'language_content_settings');
+    $alterableConfig->setLanguageAlterable(true);
+
+    $nonAlterableConfig = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_fixed_language_bundle',
+    ), 'language_content_settings');
+    $nonAlterableConfig->setLanguageAlterable(false);
+
+    $defaultConfig = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_default_language_bundle',
+    ), 'language_content_settings');
+
+    return [
+      [$alterableConfig, true],
+      [$nonAlterableConfig, false],
+      [$defaultConfig, false],
+    ];
+  }
+
+  /**
+   * @covers ::isDefaultConfiguration()
+   *
+   * @dataProvider providerIsDefaultConfiguration
+   */
+  public function testIsDefaultConfiguration(ContentLanguageSettings $config, $expected) {
+    $this->assertSame($expected, $config->isDefaultConfiguration());
+  }
+
+  public function providerIsDefaultConfiguration() {
+    $alteredLanguage= new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_bundle',
+    ), 'language_content_settings');
+    $alteredLanguage->setLanguageAlterable(true);
+
+    $alteredDefaultLangcode = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_fixed_language_bundle',
+    ), 'language_content_settings');
+    $alteredDefaultLangcode->setDefaultLangcode($this->randomMachineName());
+
+    $defaultConfig = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_default_language_bundle',
+    ), 'language_content_settings');
+
+    return [
+      [$alteredLanguage, false],
+      [$alteredDefaultLangcode, false],
+      [$defaultConfig, true],
+    ];
+  }
+
+  /**
+   * @covers ::loadByEntityTypeBundle()
+   *
+   * @dataProvider providerLoadByEntityTypeBundle
+   */
+  public function testLoadByEntityTypeBundle($config_id, ContentLanguageSettings $existing_config = NULL, $expected_langcode, $expected_language_alterable) {
+    list($type, $bundle) = explode('.', $config_id);
+
+    $nullConfig = new ContentLanguageSettings(array(
+      'target_entity_type_id' => $type,
+      'target_bundle' => $bundle,
+    ), 'language_content_settings');
+    $this->configEntityStorageInterface
+      ->expects($this->any())
+      ->method('load')
+      ->with($config_id)
+      ->will($this->returnValue($existing_config));
+    $this->configEntityStorageInterface
+      ->expects($this->any())
+      ->method('create')
+      ->will($this->returnValue($nullConfig));
+
+    $this->entityManager
+      ->expects($this->any())
+      ->method('getStorage')
+      ->with('language_content_settings')
+      ->will($this->returnValue($this->configEntityStorageInterface));
+    $this->entityManager->expects($this->any())
+      ->method('getEntityTypeFromClass')
+      ->with('Drupal\language\Entity\ContentLanguageSettings')
+      ->willReturn('language_content_settings');
+
+    $config = ContentLanguageSettings::loadByEntityTypeBundle($type, $bundle);
+
+    $this->assertSame($expected_langcode, $config->getDefaultLangcode());
+    $this->assertSame($expected_language_alterable, $config->isLanguageAlterable());
+  }
+
+  public function providerLoadByEntityTypeBundle() {
+    $alteredLanguage= new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_bundle',
+    ), 'language_content_settings');
+    $alteredLanguage->setLanguageAlterable(true);
+
+    $langcode = $this->randomMachineName();
+    $alteredDefaultLangcode = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_fixed_language_bundle',
+    ), 'language_content_settings');
+    $alteredDefaultLangcode->setDefaultLangcode($langcode);
+
+    $defaultConfig = new ContentLanguageSettings(array(
+      'target_entity_type_id' => 'test_entity_type',
+      'target_bundle' => 'test_default_language_bundle',
+    ), 'language_content_settings');
+
+    return [
+      ['test_entity_type.test_bundle', $alteredLanguage, LanguageInterface::LANGCODE_SITE_DEFAULT, true],
+      ['test_entity_type.test_fixed_language_bundle', $alteredDefaultLangcode, $langcode, false],
+      ['test_entity_type.test_default_language_bundle', $defaultConfig, LanguageInterface::LANGCODE_SITE_DEFAULT, false],
+      ['test_entity_type.null_bundle', NULL, LanguageInterface::LANGCODE_SITE_DEFAULT, false],
+    ];
+  }
+
+}
diff --git a/core/modules/locale/src/Tests/LocaleContentTest.php b/core/modules/locale/src/Tests/LocaleContentTest.php
index 1bef062c6955..f1364f30c0e2 100644
--- a/core/modules/locale/src/Tests/LocaleContentTest.php
+++ b/core/modules/locale/src/Tests/LocaleContentTest.php
@@ -84,7 +84,7 @@ public function testContentTypeLanguageConfiguration() {
     $this->drupalGet("admin/structure/types/manage/{$type2->type}");
     $this->assertText(t('Language settings'), 'Multilingual support widget present on content type configuration form.');
     $edit = array(
-      'language_configuration[language_show]' => TRUE,
+      'language_configuration[language_alterable]' => TRUE,
     );
     $this->drupalPostForm("admin/structure/types/manage/{$type2->type}", $edit, t('Save content type'));
     $this->assertRaw(t('The content type %type has been updated.', array('%type' => $type2->name)));
@@ -156,7 +156,7 @@ public function testContentTypeDirLang() {
     // Set the content type to use multilingual support.
     $this->drupalGet("admin/structure/types/manage/{$type->type}");
     $edit = array(
-      'language_configuration[language_show]' => TRUE,
+      'language_configuration[language_alterable]' => TRUE,
     );
     $this->drupalPostForm("admin/structure/types/manage/{$type->type}", $edit, t('Save content type'));
     $this->assertRaw(t('The content type %type has been updated.', array('%type' => $type->name)));
diff --git a/core/modules/menu_link_content/src/Form/MenuLinkContentForm.php b/core/modules/menu_link_content/src/Form/MenuLinkContentForm.php
index 4fb93b224dfb..256b23a9b804 100644
--- a/core/modules/menu_link_content/src/Form/MenuLinkContentForm.php
+++ b/core/modules/menu_link_content/src/Form/MenuLinkContentForm.php
@@ -257,19 +257,13 @@ public function form(array $form, FormStateInterface $form_state) {
       '#weight' => -2,
     );
 
-    $language_configuration = $this->moduleHandler->invoke('language', 'get_default_configuration', array('menu_link_content', 'menu_link_content'));
-    if ($this->entity->isNew()) {
-      $default_language = isset($language_configuration['langcode']) ? $language_configuration['langcode'] : $this->languageManager->getDefaultLanguage()->getId();
-    }
-    else {
-      $default_language = $this->entity->getUntranslated()->language()->getId();
-    }
     $form['langcode'] = array(
       '#title' => t('Language'),
       '#type' => 'language_select',
-      '#default_value' => $default_language,
+      '#default_value' =>  $this->entity->getUntranslated()->language()->getId(),
       '#languages' => Language::STATE_ALL,
-      '#access' => !empty($language_configuration['language_show']),
+      // Language module may expose or hide this element, see language_form_alter().
+      '#access' => FALSE,
     );
 
     $default = $this->entity->getMenuName() . ':' . $this->entity->getParentId();
diff --git a/core/modules/menu_ui/src/Tests/MenuLanguageTest.php b/core/modules/menu_ui/src/Tests/MenuLanguageTest.php
index f74fb099edbd..3c920b75c4e2 100644
--- a/core/modules/menu_ui/src/Tests/MenuLanguageTest.php
+++ b/core/modules/menu_ui/src/Tests/MenuLanguageTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\Unicode;
 use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Drupal\system\Entity\Menu;
 
 /**
@@ -60,7 +61,10 @@ function testMenuLanguage() {
       'langcode' => 'aa',
     );
     $this->drupalPostForm('admin/structure/menu/add', $edit, t('Save'));
-    language_save_default_configuration('menu_link_content', 'menu_link_content',  array('langcode' => 'bb', 'language_show' => TRUE));
+    ContentLanguageSettings::loadByEntityTypeBundle('menu_link_content', 'menu_link_content')
+      ->setDefaultLangcode('bb')
+      ->setLanguageAlterable(TRUE)
+      ->save();
 
     // Check menu language.
     $this->assertOptionSelected('edit-langcode', $edit['langcode'], 'The menu language was correctly selected.');
@@ -85,7 +89,10 @@ function testMenuLanguage() {
     ));
 
     // Edit menu link default, changing it to cc.
-    language_save_default_configuration('menu_link_content', 'menu_link_content',  array('langcode' => 'cc', 'language_show' => TRUE));
+    ContentLanguageSettings::loadByEntityTypeBundle('menu_link_content', 'menu_link_content')
+      ->setDefaultLangcode('cc')
+      ->setLanguageAlterable(TRUE)
+      ->save();
 
     // Add a menu link.
     $link_title = $this->randomString();
@@ -122,7 +129,10 @@ function testMenuLanguage() {
     $this->assertOptionSelected('edit-langcode', 'bb', 'The menu link language was correctly selected.');
 
     // Edit menu to hide the language select on menu link item add.
-     language_save_default_configuration('menu_link_content', 'menu_link_content',  array('langcode' => 'cc', 'language_show' => FALSE));
+    ContentLanguageSettings::loadByEntityTypeBundle('menu_link_content', 'menu_link_content')
+      ->setDefaultLangcode('cc')
+      ->setLanguageAlterable(FALSE)
+      ->save();
 
     // Check that the language selector is not available on menu link add page.
     $this->drupalGet("admin/structure/menu/manage/$menu_name/add");
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index 36c7d75e53cb..6f8f53adb695 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -8,7 +8,6 @@
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Uuid\Uuid;
 use Drupal\Core\Url;
-use Drupal\Core\Language\Language;
 
 /**
  * Implements hook_requirements().
@@ -149,21 +148,8 @@ function node_install() {
 
 /**
  * Implements hook_uninstall().
- *
- * @see node_ranking()
- * @see _node_rankings()
  */
 function node_uninstall() {
-  // Delete node type variables.
-  $types = \Drupal::configFactory()->listAll('node.type.');
-  foreach ($types as $config_name) {
-    $type = \Drupal::config($config_name)->get('type');
-    if (\Drupal::moduleHandler()->moduleExists('language')) {
-      $key = language_get_default_configuration_settings_key('node', $type);
-      \Drupal::config('language.settings')->clear($key)->save();
-    }
-  }
-
   // Delete remaining general module variables.
   \Drupal::state()->delete('node.node_access_needs_rebuild');
 }
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index c6cce777f323..2f1d40884a8a 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -15,6 +15,7 @@
 use Drupal\Core\Render\Element;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Url;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Symfony\Component\HttpFoundation\Response;
 use Drupal\Core\Database\StatementInterface;
 use Drupal\Core\Database\Query\AlterableInterface;
@@ -378,8 +379,8 @@ function node_entity_extra_field_info() {
     // Visibility of the ordering of the language selector is the same as on the
     // node/add form.
     if ($module_language_enabled) {
-      $configuration = language_get_default_configuration('node', $bundle->type);
-      if ($configuration['language_show']) {
+      $configuration = ContentLanguageSettings::loadByEntityTypeBundle('node', $bundle->type);
+      if ($configuration->isLanguageAlterable()) {
         $extra['node'][$bundle->type]['form']['langcode'] = array(
           'label' => t('Language'),
           'description' => $description,
diff --git a/core/modules/node/src/NodeForm.php b/core/modules/node/src/NodeForm.php
index 7e0a854ce595..16b1a01634ce 100644
--- a/core/modules/node/src/NodeForm.php
+++ b/core/modules/node/src/NodeForm.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Drupal\user\TempStoreFactory;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\user\Entity\User;
@@ -108,13 +109,13 @@ public function form(array $form, FormStateInterface $form_state) {
       '#default_value' => $node->getChangedTime(),
     );
 
-    $language_configuration = \Drupal::moduleHandler()->invoke('language', 'get_default_configuration', array('node', $node->getType()));
     $form['langcode'] = array(
       '#title' => t('Language'),
       '#type' => 'language_select',
       '#default_value' => $node->getUntranslated()->language()->getId(),
       '#languages' => LanguageInterface::STATE_ALL,
-      '#access' => isset($language_configuration['language_show']) && $language_configuration['language_show'],
+      // Language module may expose or hide this element, see language_form_alter().
+      '#access' => FALSE,
     );
 
     $form['advanced'] = array(
diff --git a/core/modules/node/src/NodeTypeForm.php b/core/modules/node/src/NodeTypeForm.php
index 9335b1bd4410..8a0f2a64a102 100644
--- a/core/modules/node/src/NodeTypeForm.php
+++ b/core/modules/node/src/NodeTypeForm.php
@@ -13,6 +13,7 @@
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
+use Drupal\language\Entity\ContentLanguageSettings;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -166,7 +167,7 @@ public function form(array $form, FormStateInterface $form_state) {
         '#group' => 'additional_settings',
       );
 
-      $language_configuration = language_get_default_configuration('node', $type->id());
+      $language_configuration = ContentLanguageSettings::loadByEntityTypeBundle('node', $type->id());
       $form['language']['language_configuration'] = array(
         '#type' => 'language_configuration',
         '#entity_information' => array(
diff --git a/core/modules/node/src/Tests/NodeFieldMultilingualTest.php b/core/modules/node/src/Tests/NodeFieldMultilingualTest.php
index d00ffcdba3a7..35113891dce7 100644
--- a/core/modules/node/src/Tests/NodeFieldMultilingualTest.php
+++ b/core/modules/node/src/Tests/NodeFieldMultilingualTest.php
@@ -46,7 +46,7 @@ protected function setUp() {
 
     // Set "Basic page" content type to use multilingual support.
     $edit = array(
-      'language_configuration[language_show]' => TRUE,
+      'language_configuration[language_alterable]' => TRUE,
     );
     $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
     $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), 'Basic page content type has been updated.');
diff --git a/core/modules/node/src/Tests/NodeTranslationUITest.php b/core/modules/node/src/Tests/NodeTranslationUITest.php
index 97f0f605ebc6..cd29ad287a97 100644
--- a/core/modules/node/src/Tests/NodeTranslationUITest.php
+++ b/core/modules/node/src/Tests/NodeTranslationUITest.php
@@ -42,7 +42,7 @@ protected function setUp() {
 
     // Display the language selector.
     $this->drupalLogin($this->administrator);
-    $edit = array('language_configuration[language_show]' => TRUE);
+    $edit = array('language_configuration[language_alterable]' => TRUE);
     $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
     $this->drupalLogin($this->translator);
   }
diff --git a/core/modules/node/src/Tests/NodeTypeInitialLanguageTest.php b/core/modules/node/src/Tests/NodeTypeInitialLanguageTest.php
index 971d0915014a..1aa3c4f7680d 100644
--- a/core/modules/node/src/Tests/NodeTypeInitialLanguageTest.php
+++ b/core/modules/node/src/Tests/NodeTypeInitialLanguageTest.php
@@ -39,7 +39,7 @@ protected function setUp() {
   function testNodeTypeInitialLanguageDefaults() {
     $this->drupalGet('admin/structure/types/manage/article');
     $this->assertOptionSelected('edit-language-configuration-langcode', LanguageInterface::LANGCODE_SITE_DEFAULT, 'The default initial language is the site default.');
-    $this->assertNoFieldChecked('edit-language-configuration-language-show', 'Language selector is hidden by default.');
+    $this->assertNoFieldChecked('edit-language-configuration-language-alterable', 'Language selector is hidden by default.');
 
     // Tests if the language field cannot be rearranged on the manage fields tab.
     $this->drupalGet('admin/structure/types/manage/article/fields');
@@ -62,7 +62,7 @@ function testNodeTypeInitialLanguageDefaults() {
     // Tests the initial language after changing the site default language.
     // First unhide the language selector.
     $edit = array(
-      'language_configuration[language_show]' => TRUE,
+      'language_configuration[language_alterable]' => TRUE,
     );
     $this->drupalPostForm('admin/structure/types/manage/article', $edit, t('Save content type'));
     $this->drupalGet('node/add/article');
diff --git a/core/modules/path/src/Tests/PathLanguageTest.php b/core/modules/path/src/Tests/PathLanguageTest.php
index f87b5a3d6f87..e5f70652ea06 100644
--- a/core/modules/path/src/Tests/PathLanguageTest.php
+++ b/core/modules/path/src/Tests/PathLanguageTest.php
@@ -56,7 +56,7 @@ protected function setUp() {
       'settings[node][page][translatable]' => 1,
       'settings[node][page][fields][path]' => 1,
       'settings[node][page][fields][body]' => 1,
-      'settings[node][page][settings][language][language_show]' => 1,
+      'settings[node][page][settings][language][language_alterable]' => 1,
     );
     $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
 
diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php
index e3019e07424d..189e8a2c82e3 100644
--- a/core/modules/system/entity.api.php
+++ b/core/modules/system/entity.api.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Entity\DynamicallyFieldableEntityStorageInterface;
 use Drupal\Core\Field\BaseFieldDefinition;
 use Drupal\Core\Render\Element;
+use Drupal\language\Entity\ContentLanguageSettings;
 
 /**
  * @defgroup entity_crud Entity CRUD, editing, and view hooks
@@ -1911,8 +1912,8 @@ function hook_entity_extra_field_info() {
     // Visibility of the ordering of the language selector is the same as on the
     // node/add form.
     if ($module_language_enabled) {
-      $configuration = language_get_default_configuration('node', $bundle->type);
-      if ($configuration['language_show']) {
+      $configuration = ContentLanguageSettings::loadByEntityTypeBundle('node', $bundle->type);
+      if ($configuration->isLanguageAlterable()) {
         $extra['node'][$bundle->type]['form']['language'] = array(
           'label' => t('Language'),
           'description' => $description,
diff --git a/core/modules/system/src/Tests/Entity/EntityTranslationFormTest.php b/core/modules/system/src/Tests/Entity/EntityTranslationFormTest.php
index 59da34d05287..510294d92567 100644
--- a/core/modules/system/src/Tests/Entity/EntityTranslationFormTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityTranslationFormTest.php
@@ -80,7 +80,7 @@ function testEntityFormLanguage() {
 
     // Enable language selector.
     $this->drupalGet('admin/structure/types/manage/page');
-    $edit = array('language_configuration[language_show]' => TRUE, 'language_configuration[langcode]' => LanguageInterface::LANGCODE_NOT_SPECIFIED);
+    $edit = array('language_configuration[language_alterable]' => TRUE, 'language_configuration[langcode]' => LanguageInterface::LANGCODE_NOT_SPECIFIED);
     $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
     $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), 'Basic page content type has been updated.');
 
diff --git a/core/modules/taxonomy/src/TermForm.php b/core/modules/taxonomy/src/TermForm.php
index 2136b0f750c6..2e7097ce4e41 100644
--- a/core/modules/taxonomy/src/TermForm.php
+++ b/core/modules/taxonomy/src/TermForm.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\ContentEntityForm;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\language\Entity\ContentLanguageSettings;
 
 /**
  * Base for controller for taxonomy term edit forms.
@@ -28,13 +29,13 @@ public function form(array $form, FormStateInterface $form_state) {
     $form_state->set(['taxonomy', 'parent'], $parent);
     $form_state->set(['taxonomy', 'vocabulary'], $vocabulary);
 
-    $language_configuration = $this->moduleHandler->moduleExists('language') ? language_get_default_configuration('taxonomy_term', $vocabulary->id()) : FALSE;
     $form['langcode'] = array(
       '#type' => 'language_select',
       '#title' => $this->t('Language'),
       '#languages' => LanguageInterface::STATE_ALL,
       '#default_value' => $term->getUntranslated()->language()->getId(),
-      '#access' => !empty($language_configuration['language_show']),
+      // Language module may expose or hide this element, see language_form_alter().
+      '#access' => FALSE,
     );
 
     $form['relations'] = array(
diff --git a/core/modules/taxonomy/src/Tests/TermLanguageTest.php b/core/modules/taxonomy/src/Tests/TermLanguageTest.php
index 71caceec557d..4096e4bb54d5 100644
--- a/core/modules/taxonomy/src/Tests/TermLanguageTest.php
+++ b/core/modules/taxonomy/src/Tests/TermLanguageTest.php
@@ -41,7 +41,7 @@ protected function setUp() {
   function testTermLanguage() {
     // Configure the vocabulary to not hide the language selector.
     $edit = array(
-      'default_language[language_show]' => TRUE,
+      'default_language[language_alterable]' => TRUE,
     );
     $this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
 
@@ -77,7 +77,7 @@ function testDefaultTermLanguage() {
     // default language of the terms fixed.
     $edit = array(
       'default_language[langcode]' => 'bb',
-      'default_language[language_show]' => TRUE,
+      'default_language[language_alterable]' => TRUE,
     );
     $this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
     $this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
@@ -86,7 +86,7 @@ function testDefaultTermLanguage() {
     // Make the default language of the terms to be the current interface.
     $edit = array(
       'default_language[langcode]' => 'current_interface',
-      'default_language[language_show]' => TRUE,
+      'default_language[language_alterable]' => TRUE,
     );
     $this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
     $this->drupalGet('aa/admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
@@ -99,7 +99,7 @@ function testDefaultTermLanguage() {
     \Drupal::config('system.site')->set('langcode', 'cc')->save();
     $edit = array(
       'default_language[langcode]' => LanguageInterface::LANGCODE_SITE_DEFAULT,
-      'default_language[language_show]' => TRUE,
+      'default_language[language_alterable]' => TRUE,
     );
     $this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
     $this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
diff --git a/core/modules/taxonomy/src/Tests/VocabularyLanguageTest.php b/core/modules/taxonomy/src/Tests/VocabularyLanguageTest.php
index 07e3831b44b2..c172257561bc 100644
--- a/core/modules/taxonomy/src/Tests/VocabularyLanguageTest.php
+++ b/core/modules/taxonomy/src/Tests/VocabularyLanguageTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\Unicode;
 use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\language\Entity\ContentLanguageSettings;
 
 /**
  * Tests the language functionality for vocabularies.
@@ -79,7 +80,7 @@ function testVocabularyDefaultLanguageForTerms() {
       'name' => $this->randomMachineName(),
       'vid' => Unicode::strtolower($this->randomMachineName()),
       'default_language[langcode]' => 'bb',
-      'default_language[language_show]' => TRUE,
+      'default_language[language_alterable]' => TRUE,
     );
     $vid = $edit['vid'];
     $this->drupalPostForm('admin/structure/taxonomy/add', $edit, t('Save'));
@@ -89,41 +90,41 @@ function testVocabularyDefaultLanguageForTerms() {
     $this->assertResponse(200, 'The vocabulary has been created.');
 
     // Check that the language settings were saved.
-    $language_settings = language_get_default_configuration('taxonomy_term', $edit['vid']);
-    $this->assertEqual($language_settings['langcode'], 'bb', 'The langcode was saved.');
-    $this->assertTrue($language_settings['language_show'], 'The visibility setting was saved.');
+    $language_settings = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', $edit['vid']);
+    $this->assertEqual($language_settings->getDefaultLangcode(), 'bb', 'The langcode was saved.');
+    $this->assertTrue($language_settings->isLanguageAlterable(), 'The visibility setting was saved.');
 
     // Check that the correct options are selected in the interface.
     $this->assertOptionSelected('edit-default-language-langcode', 'bb', 'The correct default language for the terms of this vocabulary is selected.');
-    $this->assertFieldChecked('edit-default-language-language-show', 'Show language selection option is checked.');
+    $this->assertFieldChecked('edit-default-language-language-alterable', 'Show language selection option is checked.');
 
     // Edit the vocabulary and check that the new settings are updated.
     $edit = array(
       'default_language[langcode]' => 'aa',
-      'default_language[language_show]' => FALSE,
+      'default_language[language_alterable]' => FALSE,
     );
     $this->drupalPostForm('admin/structure/taxonomy/manage/' . $vid, $edit, t('Save'));
 
     // And check again the settings and also the interface.
-    $language_settings = language_get_default_configuration('taxonomy_term', $vid);
-    $this->assertEqual($language_settings['langcode'], 'aa', 'The langcode was saved.');
-    $this->assertFalse($language_settings['language_show'], 'The visibility setting was saved.');
+    $language_settings = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', $vid);
+    $this->assertEqual($language_settings->getDefaultLangcode(), 'aa', 'The langcode was saved.');
+    $this->assertFalse($language_settings->isLanguageAlterable(), 'The visibility setting was saved.');
 
     $this->drupalGet('admin/structure/taxonomy/manage/' . $vid);
     $this->assertOptionSelected('edit-default-language-langcode', 'aa', 'The correct default language for the terms of this vocabulary is selected.');
-    $this->assertNoFieldChecked('edit-default-language-language-show', 'Show language selection option is not checked.');
+    $this->assertNoFieldChecked('edit-default-language-language-alterable', 'Show language selection option is not checked.');
 
     // Check that language settings are changed after editing vocabulary.
     $edit = array(
       'name' => $this->randomMachineName(),
       'default_language[langcode]' => 'authors_default',
-      'default_language[language_show]' => FALSE,
+      'default_language[language_alterable]' => FALSE,
     );
     $this->drupalPostForm('admin/structure/taxonomy/manage/' . $vid, $edit, t('Save'));
 
     // Check that we have the new settings.
-    $new_settings = language_get_default_configuration('taxonomy_term', $vid);
-    $this->assertEqual($new_settings['langcode'], 'authors_default', 'The langcode was saved.');
-    $this->assertFalse($new_settings['language_show'], 'The new visibility setting was saved.');
+    $new_settings = ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', $vid);
+    $this->assertEqual($new_settings->getDefaultLangcode(), 'authors_default', 'The langcode was saved.');
+    $this->assertFalse($new_settings->isLanguageAlterable(), 'The new visibility setting was saved.');
   }
 }
diff --git a/core/modules/taxonomy/src/VocabularyForm.php b/core/modules/taxonomy/src/VocabularyForm.php
index 34dc3ed5277a..dc8b6b1958bf 100644
--- a/core/modules/taxonomy/src/VocabularyForm.php
+++ b/core/modules/taxonomy/src/VocabularyForm.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\language\Entity\ContentLanguageSettings;
 
 /**
  * Base form for vocabulary edit forms.
@@ -73,7 +74,7 @@ public function form(array $form, FormStateInterface $form_state) {
           'entity_type' => 'taxonomy_term',
           'bundle' => $vocabulary->id(),
         ),
-        '#default_value' => language_get_default_configuration('taxonomy_term', $vocabulary->id()),
+        '#default_value' => ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', $vocabulary->id()),
       );
     }
     // Set the hierarchy to "multiple parents" by default. This simplifies the
@@ -93,12 +94,6 @@ protected function actions(array $form, FormStateInterface $form_state) {
     // If we are displaying the delete confirmation skip the regular actions.
     if (!$form_state->get('confirm_delete')) {
       $actions = parent::actions($form, $form_state);
-      // Add the language configuration submit handler. This is needed because
-      // the submit button has custom submit handlers.
-      if ($this->moduleHandler->moduleExists('language')) {
-        array_unshift($actions['submit']['#submit'], 'language_configuration_element_submit');
-        array_unshift($actions['submit']['#submit'], '::languageConfigurationSubmit');
-      }
       // We cannot leverage the regular submit handler definition because we
       // have button-specific ones here. Hence we need to explicitly set it for
       // the submit action, otherwise it would be ignored.
@@ -112,22 +107,6 @@ protected function actions(array $form, FormStateInterface $form_state) {
     }
   }
 
-  /**
-   * Submit handler to update the bundle for the default language configuration.
-   */
-  public function languageConfigurationSubmit(array &$form, FormStateInterface $form_state) {
-    $vocabulary = $this->entity;
-    // Delete the old language settings for the vocabulary, if the machine name
-    // is changed.
-    if ($vocabulary && $vocabulary->id() && $vocabulary->id() != $form_state->getValue('vid')) {
-      language_clear_default_configuration('taxonomy_term', $vocabulary->id());
-    }
-    // Since the machine name is not known yet, and it can be changed anytime,
-    // we have to also update the bundle property for the default language
-    // configuration in order to have the correct bundle value.
-    $form_state->set(['language', 'default_language', 'bundle'], $form_state->getValue('vid'));
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/views/src/Tests/SearchMultilingualTest.php b/core/modules/views/src/Tests/SearchMultilingualTest.php
index 97213c3c189f..4750f0b75621 100644
--- a/core/modules/views/src/Tests/SearchMultilingualTest.php
+++ b/core/modules/views/src/Tests/SearchMultilingualTest.php
@@ -45,7 +45,7 @@ public function testMultilingualSearchFilter() {
     // Create a content type and make it translatable.
     $type = $this->drupalCreateContentType();
     $edit = array(
-      'language_configuration[language_show]' => TRUE,
+      'language_configuration[language_alterable]' => TRUE,
     );
     $this->drupalPostForm('admin/structure/types/manage/' . $type->type, $edit, t('Save content type'));
     $edit = array(
-- 
GitLab