From 6f6a2f3d633cf93e442e3ae6a0d1de7266ae5837 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Sat, 25 Jan 2014 22:00:48 +0000
Subject: [PATCH] =?UTF-8?q?Issue=20#2108599=20by=20alexpott,=20G=C3=A1bor?=
 =?UTF-8?q?=20Hojtsy,=20vijaycs85:=20Convert=20language=5Fdefault=20to=20C?=
 =?UTF-8?q?MI.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 core/core.services.yml                        |  4 ++
 core/includes/install.core.inc                | 44 +++++++------
 core/includes/install.inc                     | 13 +++-
 core/lib/Drupal/Core/Config/Config.php        | 61 +++++++++++++++++++
 core/lib/Drupal/Core/Config/ConfigFactory.php | 26 +++++---
 core/lib/Drupal/Core/DrupalKernel.php         | 13 ++++
 .../Drupal/Core/Language/LanguageDefault.php  | 54 ++++++++++++++++
 .../Drupal/Core/Language/LanguageManager.php  | 18 ++++--
 .../Language/LanguageManagerInterface.php     |  3 +
 .../Drupal/block/Tests/BlockLanguageTest.php  |  2 -
 .../config/Tests/ConfigLanguageOverride.php   | 15 ++++-
 .../Tests/ConfigLanguageOverrideWebTest.php   | 15 +++++
 core/modules/language/language.install        |  3 -
 core/modules/language/language.module         |  7 ++-
 core/modules/language/language.services.yml   |  4 ++
 .../language/ConfigurableLanguageManager.php  | 26 ++------
 .../ConfigurableLanguageManagerInterface.php  |  5 --
 .../lib/Drupal/language/Entity/Language.php   | 14 +++++
 .../EventSubscriber/ConfigSubscriber.php      | 42 +++++++++++++
 .../LanguageRequestSubscriber.php             | 15 ++++-
 .../DeleteDefaultLanguageException.php        | 13 ++++
 .../language/Exception/LanguageException.php  | 13 ++++
 .../language/LanguageServiceProvider.php      | 34 ++++++++++-
 .../Tests/Condition/LanguageConditionTest.php |  3 -
 .../Tests/LanguageConfigurationTest.php       |  3 +-
 .../Tests/LanguageDependencyInjectionTest.php | 32 ++++++----
 .../Tests/LanguagePathMonolingualTest.php     |  4 ++
 .../language/Tests/LanguageTestBase.php       |  2 +-
 .../LanguageUILanguageNegotiationTest.php     | 20 +++---
 .../locale/Tests/LocaleUninstallTest.php      |  3 +-
 .../Drupal/simpletest/DrupalUnitTestBase.php  |  4 ++
 .../lib/Drupal/simpletest/TestBase.php        |  6 +-
 .../system/Tests/Theme/TwigTransTest.php      |  9 ++-
 33 files changed, 428 insertions(+), 102 deletions(-)
 create mode 100644 core/lib/Drupal/Core/Language/LanguageDefault.php
 create mode 100644 core/modules/language/lib/Drupal/language/EventSubscriber/ConfigSubscriber.php
 create mode 100644 core/modules/language/lib/Drupal/language/Exception/DeleteDefaultLanguageException.php
 create mode 100644 core/modules/language/lib/Drupal/language/Exception/LanguageException.php

diff --git a/core/core.services.yml b/core/core.services.yml
index 9a9f773b1cc1..f1608031ffa2 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -228,6 +228,10 @@ services:
     arguments: ['@event_dispatcher', '@service_container', '@controller_resolver']
   language_manager:
     class: Drupal\Core\Language\LanguageManager
+    arguments: ['@language.default']
+  language.default:
+    class: Drupal\Core\Language\LanguageDefault
+    arguments: ['%language.default_values%']
   string_translator.custom_strings:
     class: Drupal\Core\StringTranslation\Translator\CustomStrings
     arguments: ['@settings']
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 9b0dc940b540..7286eeee16c7 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -299,22 +299,20 @@ function install_begin_request(&$install_state) {
     exit;
   }
 
-  // Register the 'language_manager' service.
-  $container->register('language_manager', 'Drupal\Core\Language\LanguageManager');
-
-  // If we have a language selected and it is not yet saved in the system
-  // (eg. pre-database data screens we are unable to persistently store
-  // the default language), we should set language_default so the proper
-  // language is used to display installer pages as early as possible.
-  // The language list is stored in configuration and cannot be saved either
-  // until later in the process. Language negotiation bootstrapping needs
-  // the new default language to be in the list though, so inject it in.
-  if (!empty($install_state['parameters']['langcode']) && language_default()->id != $install_state['parameters']['langcode']) {
-    $GLOBALS['conf']['language_default'] = array('id' => $install_state['parameters']['langcode']);
-
-    $languages = &drupal_static('language_list');
-    $languages[$install_state['parameters']['langcode']] = new Language($GLOBALS['conf']['language_default']);
+  // If we have a language selected and it is not yet saved in the system (eg.
+  // pre-database data screens we are unable to persistently store the default
+  // language), we should set language_default so the proper language is used to
+  // display installer pages as early as possible.
+  $default_language_values = Language::$defaultValues;
+  if (!empty($install_state['parameters']['langcode']) && $default_language_values['id'] != $install_state['parameters']['langcode']) {
+    $default_language_values = array('id' => $install_state['parameters']['langcode']);
   }
+  // Register the 'language_manager' service.
+  $container->setParameter('language.default_values', $default_language_values);
+  $container->register('language.default', 'Drupal\Core\Language\LanguageDefault')
+    ->addArgument('%language.default_values%');
+  $container->register('language_manager', 'Drupal\Core\Language\LanguageManager')
+    ->addArgument(new Reference('language.default'));
 
   require_once __DIR__ . '/../modules/system/system.install';
   require_once __DIR__ . '/common.inc';
@@ -383,13 +381,18 @@ function install_begin_request(&$install_state) {
       ->addArgument(new Reference('config.storage.schema'))
       ->addArgument(new Reference('cache.config'));
 
+    $container->setParameter('language.default_values', Language::$defaultValues);
+    $container->register('language.default', 'Drupal\Core\Language\LanguageDefault')
+      ->addArgument('%language.default_values%');
+
     $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory')
       ->addArgument(new Reference('config.storage'))
       ->addArgument(new Reference('event_dispatcher'))
       ->addArgument(new Reference('config.typed'));
 
     // Register the 'language_manager' service.
-    $container->register('language_manager', 'Drupal\Core\Language\LanguageManager');
+    $container->register('language_manager', 'Drupal\Core\Language\LanguageManager')
+      ->addArgument(new Reference('language.default'));
 
     // Register the translation services.
     install_register_translation_service($container);
@@ -474,6 +477,12 @@ function install_begin_request(&$install_state) {
       ->addArgument(new Reference('module_handler'))
       ->addArgument(new Reference('cache.cache'))
       ->addArgument(new Reference('info_parser'));
+
+    // Overrides can not work at this point since this would cause the
+    // ConfigFactory to try to load language override configuration which is not
+    // supported by \Drupal\Core\Config\InstallStorage since loading a
+    // non-existing file would throw an exception.
+    $container->get('config.factory')->disableOverrides();
   }
 
   // Set the request in the kernel to the new created Request above
@@ -1009,7 +1018,7 @@ function install_verify_requirements(&$install_state) {
  */
 function install_base_system(&$install_state) {
   // Install system.module.
-  drupal_install_system();
+  drupal_install_system($install_state);
 
   // Call file_ensure_htaccess() to ensure that all of Drupal's standard
   // directories (e.g., the public files directory and config directory) have
@@ -2686,7 +2695,6 @@ function install_configure_form_submit($form, &$form_state) {
   \Drupal::config('system.site')
     ->set('name', $form_state['values']['site_name'])
     ->set('mail', $form_state['values']['site_mail'])
-    ->set('langcode', language_default()->id)
     ->save();
 
   \Drupal::config('system.date')
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 87783f6c379c..8c91dc86dadf 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -604,8 +604,12 @@ function drupal_verify_profile($install_state) {
  *
  * Separated from the installation of other modules so core system
  * functions can be made available while other modules are installed.
+ *
+ * @param array $install_state
+ *   An array of information about the current installation state. This is used
+ *   to set the default language.
  */
-function drupal_install_system() {
+function drupal_install_system($install_state) {
   // Create tables.
   drupal_install_schema('system');
 
@@ -643,6 +647,13 @@ function drupal_install_system() {
 
   \Drupal::service('config.installer')->installDefaultConfig('module', 'system');
 
+  // Ensure default language is saved.
+  if (isset($install_state['parameters']['langcode'])) {
+    \Drupal::config('system.site')
+      ->set('langcode', $install_state['parameters']['langcode'])
+      ->save();
+  }
+
   module_invoke('system', 'install');
 }
 
diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php
index eed4f894e69b..9c6bd3f19fd1 100644
--- a/core/lib/Drupal/Core/Config/Config.php
+++ b/core/lib/Drupal/Core/Config/Config.php
@@ -69,6 +69,13 @@ class Config {
    */
   protected $data;
 
+  /**
+   * The original data of the configuration object.
+   *
+   * @var array
+   */
+  protected $originalData;
+
   /**
    * The current runtime data.
    *
@@ -160,6 +167,7 @@ public function initWithData(array $data) {
     $this->moduleOverrides = array();
     $this->isNew = FALSE;
     $this->replaceData($data);
+    $this->originalData = $this->data;
     return $this;
   }
 
@@ -467,6 +475,7 @@ public function load() {
       $this->isNew = FALSE;
       $this->replaceData($data);
     }
+    $this->originalData = $this->data;
     $this->isLoaded = TRUE;
     return $this;
   }
@@ -497,6 +506,7 @@ public function save() {
     $this->storage->write($this->name, $this->data);
     $this->isNew = FALSE;
     $this->notify('save');
+    $this->originalData = $this->data;
     return $this;
   }
 
@@ -513,6 +523,7 @@ public function delete() {
     $this->isNew = TRUE;
     $this->resetOverriddenData();
     $this->notify('delete');
+    $this->originalData = $this->data;
     return $this;
   }
 
@@ -650,5 +661,55 @@ public function getRawData() {
     return $this->data;
   }
 
+  /**
+   * Gets original data from this configuration object.
+   *
+   * Original data is the data as it is immediately after loading from
+   * configuration storage before any changes. If this is a new configuration
+   * object it will be an empty array.
+   *
+   * @see \Drupal\Core\Config\Config::get()
+   *
+   * @param string $key
+   *   A string that maps to a key within the configuration data.
+   * @param bool $apply_overrides
+   *   Apply any overrides to the original data. Defaults to TRUE.
+   *
+   * @return mixed
+   *   The data that was requested.
+   */
+  public function getOriginal($key = '', $apply_overrides = TRUE) {
+    if (!$this->isLoaded) {
+      $this->load();
+    }
+
+    if ($apply_overrides) {
+      // Apply overrides.
+      $original_data = $this->originalData;
+      if (isset($this->languageOverrides) && is_array($this->languageOverrides)) {
+        $original_data = NestedArray::mergeDeepArray(array($original_data, $this->languageOverrides), TRUE);
+      }
+      if (isset($this->moduleOverrides) && is_array($this->moduleOverrides)) {
+        $original_data = NestedArray::mergeDeepArray(array($original_data, $this->moduleOverrides), TRUE);
+      }
+      if (isset($this->settingsOverrides) && is_array($this->settingsOverrides)) {
+        $original_data = NestedArray::mergeDeepArray(array($original_data, $this->settingsOverrides), TRUE);
+      }
+    }
+
+    if (empty($key)) {
+      return $original_data;
+    }
+    else {
+      $parts = explode('.', $key);
+      if (count($parts) == 1) {
+        return isset($original_data[$key]) ? $original_data[$key] : NULL;
+      }
+      else {
+        $value = NestedArray::getValue($original_data, $parts, $key_exists);
+        return $key_exists ? $value : NULL;
+      }
+    }
+  }
 }
 
diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php
index 8aeb30152050..e277787e6816 100644
--- a/core/lib/Drupal/Core/Config/ConfigFactory.php
+++ b/core/lib/Drupal/Core/Config/ConfigFactory.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Config;
 
 use Drupal\Core\Language\Language;
+use Drupal\Core\Language\LanguageDefault;
 use Symfony\Component\EventDispatcher\EventDispatcher;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
@@ -82,16 +83,11 @@ class ConfigFactory implements EventSubscriberInterface {
    *   An event dispatcher instance to use for configuration events.
    * @param \Drupal\Core\Config\TypedConfigManager $typed_config
    *   The typed configuration manager.
-   * @param \Drupal\Core\Language\Language
-   *   (optional) The language for this configuration. The config factory will
-   *   use it to override configuration data if language overrides are
-   *   available.
    */
-  public function __construct(StorageInterface $storage, EventDispatcher $event_dispatcher, TypedConfigManager $typed_config, Language $language = NULL) {
+  public function __construct(StorageInterface $storage, EventDispatcher $event_dispatcher, TypedConfigManager $typed_config) {
     $this->storage = $storage;
     $this->eventDispatcher = $event_dispatcher;
     $this->typedConfigManager = $typed_config;
-    $this->language = $language;
   }
 
   /**
@@ -360,7 +356,7 @@ public function clearStaticCache() {
   }
 
   /**
-   * Set the language to be used in configuration overrides.
+   * Sets the language to be used in configuration overrides.
    *
    * @param \Drupal\Core\Language\Language $language
    *   The language object to be set on the config factory. Used to override
@@ -374,6 +370,22 @@ public function setLanguage(Language $language = NULL) {
     return $this;
   }
 
+  /**
+   * Sets the language for configuration overrides using the default language.
+   *
+   * @param \Drupal\Core\Language\LanguageDefault $language_default
+   *   The default language service. This sets the initial language on the
+   *   config factory to the site's default. The language can be used to
+   *   override configuration data if language overrides are available.
+   *
+   * @return \Drupal\Core\Config\ConfigFactory
+   *   The config factory object.
+   */
+  public function setLanguageFromDefault(LanguageDefault $language_default) {
+    $this->language = $language_default->get();
+    return $this;
+  }
+
   /**
    * Gets the language Used to override configuration.
    *
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index 016011966d7a..e2a03a7e2d50 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -13,6 +13,7 @@
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\ServiceProviderInterface;
 use Drupal\Core\DependencyInjection\YamlFileLoader;
+use Drupal\Core\Language\Language;
 use Symfony\Component\Config\Loader\LoaderInterface;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
@@ -516,6 +517,18 @@ protected function buildContainer() {
     }
     $container->setParameter('container.namespaces', $namespaces);
 
+    // Store the default language values on the container. This is so that the
+    // default language can be configured using the configuration factory. This
+    // avoids the circular dependencies that would created by
+    // \Drupal\language\LanguageServiceProvider::alter() and allows the default
+    // language to not be English in the installer.
+    $system = BootstrapConfigStorageFactory::get()->read('system.site');
+    $default_language_values = Language::$defaultValues;
+    if ($default_language_values['id'] != $system['langcode']) {
+      $default_language_values = array('id' => $system['langcode'], 'default' => TRUE);
+    }
+    $container->setParameter('language.default_values', $default_language_values);
+
     // Register synthetic services.
     $container->register('class_loader')->setSynthetic(TRUE);
     $container->register('kernel', 'Symfony\Component\HttpKernel\KernelInterface')->setSynthetic(TRUE);
diff --git a/core/lib/Drupal/Core/Language/LanguageDefault.php b/core/lib/Drupal/Core/Language/LanguageDefault.php
new file mode 100644
index 000000000000..ad58ebe97e35
--- /dev/null
+++ b/core/lib/Drupal/Core/Language/LanguageDefault.php
@@ -0,0 +1,54 @@
+<?php
+
+namespace Drupal\Core\Language;
+
+/**
+ * Provides a simple get and set wrapper to a language object.
+ *
+ * The default language must be provided without dependencies since it is both
+ * configured and a dependency of the configuration system. The LanguageDefault
+ * object is a container service. The default values are stored on the container
+ * by \Drupal\Core\DrupalKernel::buildContainer(). This allows services to
+ * override this parameter in a ServiceProvider, for example,
+ * \Drupal\language\LanguageServiceProvider::alter().
+ */
+class LanguageDefault {
+
+  /**
+   * The default language.
+   *
+   * @var \Drupal\Core\Language\Language
+   */
+  protected $language;
+
+  /**
+   * Constructs the default language object.
+   *
+   * @param array $default_values
+   */
+  public function __construct(array $default_values) {
+    $this->set(new Language($default_values));
+  }
+
+  /**
+   * Gets the default language.
+   *
+   * @return \Drupal\Core\Language\Language
+   *   The default language.
+   */
+  public function get() {
+    return $this->language;
+  }
+
+  /**
+   * Sets the default language.
+   *
+   * @param \Drupal\Core\Language\Language $language
+   *   The default language.
+   */
+  public function set(Language $language) {
+    $language->default = TRUE;
+    $this->language = $language;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php
index d21cb9f1ef6d..2bd3f202a757 100644
--- a/core/lib/Drupal/Core/Language/LanguageManager.php
+++ b/core/lib/Drupal/Core/Language/LanguageManager.php
@@ -32,10 +32,20 @@ class LanguageManager implements LanguageManagerInterface {
   /**
    * The default language object.
    *
-   * @var \Drupal\Core\Language\Language
+   * @var \Drupal\Core\Language\LanguageDefault
    */
   protected $defaultLanguage;
 
+  /**
+   * Constructs the language manager.
+   *
+   * @param \Drupal\Core\Language\Language $default_language
+   *   The default language.
+   */
+  public function __construct(LanguageDefault $default_language) {
+    $this->defaultLanguage = $default_language;
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -83,16 +93,14 @@ public function getCurrentLanguage($type = Language::TYPE_INTERFACE) {
    * {@inheritdoc}
    */
   public function reset($type = NULL) {
+    return $this;
   }
 
   /**
    * {@inheritdoc}
    */
   public function getDefaultLanguage() {
-    if (!isset($this->defaultLanguage)) {
-      $this->defaultLanguage = new Language(Language::$defaultValues);
-    }
-    return $this->defaultLanguage;
+    return $this->defaultLanguage->get();
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
index 159c39c63297..16c7c01068ba 100644
--- a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
+++ b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
@@ -62,6 +62,9 @@ public function getCurrentLanguage($type = Language::TYPE_INTERFACE);
    *   (optional) The language type to reset as a string, e.g.,
    *   Language::TYPE_INTERFACE, or NULL to reset all language types. Defaults
    *   to NULL.
+   *
+   * @return \Drupal\Core\Language\LanguageManagerInterface
+   *   The language manager that has been reset.
    */
   public function reset($type = NULL);
 
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockLanguageTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockLanguageTest.php
index e2bb9dac73c5..246e92cb4ec2 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockLanguageTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockLanguageTest.php
@@ -73,8 +73,6 @@ public function testLanguageBlockVisibility() {
     );
     $this->drupalPostForm('admin/config/regional/settings', $edit, t('Save configuration'));
 
-    // Reset the static cache of the language list.
-    $this->container->get('language_manager')->reset();
     // Check that a page has a block.
     $this->drupalGet('en');
     $this->assertText('Powered by Drupal', 'The body of the custom block appears on the page.');
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php b/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php
index 4d7bdf942252..2f939507ae8f 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php
@@ -33,16 +33,29 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
     $this->installConfig(array('config_test'));
-    \Drupal::configFactory()->setLanguage(language_default());
   }
 
   /**
    * Tests locale override based on language.
    */
   function testConfigLanguageOverride() {
+    // The default configuration factory does not have the default language
+    // injected unless the Language module is enabled.
+    $config = \Drupal::config('config_test.system');
+    $this->assertIdentical($config->get('foo'), 'bar');
+
+    // \Drupal\language\LanguageServiceProvider::alter() calls
+    // \Drupal\Core\Config\ConfigFactory::setLanguageFromDefault() to set the
+    // language when the Language module is enabled. This test ensures that
+    // English overrides work.
+    \Drupal::configFactory()->setLanguageFromDefault(\Drupal::service('language.default'));
     $config = \Drupal::config('config_test.system');
     $this->assertIdentical($config->get('foo'), 'en bar');
 
+    // Ensure that the raw data is not translated.
+    $raw = $config->getRawData();
+    $this->assertIdentical($raw['foo'], 'bar');
+
     language_save(new Language(array(
       'name' => 'French',
       'id' => 'fr',
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverrideWebTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverrideWebTest.php
index d8412b45f7e5..3ffb54fc2e90 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverrideWebTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverrideWebTest.php
@@ -65,6 +65,21 @@ function testSiteNameTranslation() {
     // @see \Drupal\Core\PathProcessor::processInbound()
     $this->drupalGet('xx');
     $this->assertText('XX site name');
+
+    // Set the xx language to be the default language and delete the English
+    // language so the site is no longer multilingual and confirm configuration
+    // overrides still work.
+    $language_manager = \Drupal::languageManager()->reset();
+    $this->assertTrue($language_manager->isMultilingual(), 'The test site is multilingual.');
+    $language = \Drupal::languageManager()->getLanguage('xx');
+    $language->default = TRUE;
+    language_save($language);
+    language_delete('en');
+    $this->assertFalse($language_manager->isMultilingual(), 'The test site is monolingual.');
+
+    $this->drupalGet('xx');
+    $this->assertText('XX site name');
+
   }
 
 }
diff --git a/core/modules/language/language.install b/core/modules/language/language.install
index 37388311d445..fedc2b479399 100644
--- a/core/modules/language/language.install
+++ b/core/modules/language/language.install
@@ -32,9 +32,6 @@ function language_install() {
  * Implements hook_uninstall().
  */
 function language_uninstall() {
-  // Clear variables.
-  variable_del('language_default');
-
   // Clear variables.
   foreach (\Drupal::languageManager()->getDefinedLanguageTypes() as $type) {
     variable_del("language_negotiation_$type");
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 883ab881742e..e31807f5c86f 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -5,6 +5,7 @@
  * Add language handling functionality to Drupal.
  */
 
+use Drupal\Component\PhpStorage\PhpStorageFactory;
 use Drupal\Core\Language\Language;
 use Drupal\language\ConfigurableLanguageManager;
 use Drupal\language\ConfigurableLanguageManagerInterface;
@@ -469,8 +470,10 @@ function language_save($language) {
   }
 
   if (!empty($language->default)) {
-    // Set the new version of this language as default in a variable.
-    variable_set('language_default', (array) $language);
+    // Update the config. Saving the configuration fires and event that causes
+    // the container to be rebuilt.
+    \Drupal::config('system.site')->set('langcode', $language->id)->save();
+    \Drupal::service('language.default')->set($language);
   }
 
   $language_manager = \Drupal::languageManager();
diff --git a/core/modules/language/language.services.yml b/core/modules/language/language.services.yml
index 81aede72a9c2..422644af2473 100644
--- a/core/modules/language/language.services.yml
+++ b/core/modules/language/language.services.yml
@@ -7,3 +7,7 @@ services:
     arguments: ['@language_manager', '@plugin.manager.language_negotiation_method', '@config.factory', '@settings']
     calls:
       - [initLanguageManager]
+  language.config_subscriber:
+    class: Drupal\language\EventSubscriber\ConfigSubscriber
+    tags:
+      - { name: event_subscriber }
diff --git a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
index 49c7ea42ac3a..9de37262434b 100644
--- a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
+++ b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Config\ConfigFactory;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\Language;
+use Drupal\Core\Language\LanguageDefault;
 use Drupal\Core\Language\LanguageManager;
 use Symfony\Component\HttpFoundation\Request;
 
@@ -98,18 +99,12 @@ public static function rebuildServices() {
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler service.
    */
-  public function __construct(ConfigFactory $config_factory, ModuleHandlerInterface $module_handler) {
+  public function __construct(LanguageDefault $default_language, ConfigFactory $config_factory, ModuleHandlerInterface $module_handler) {
+    $this->defaultLanguage = $default_language;
     $this->configFactory = $config_factory;
     $this->moduleHandler = $module_handler;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function initConfigOverrides() {
-    $this->configFactory->setLanguage($this->getCurrentLanguage());
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -217,7 +212,6 @@ public function reset($type = NULL) {
       $this->languageTypes = NULL;
       $this->languageTypesInfo = NULL;
       $this->languages = NULL;
-      $this->defaultLanguage = NULL;
       if ($this->negotiator) {
         $this->negotiator->reset();
       }
@@ -225,6 +219,7 @@ public function reset($type = NULL) {
     elseif (isset($this->negotiatedLanguages[$type])) {
       unset($this->negotiatedLanguages[$type]);
     }
+    return $this;
   }
 
   /**
@@ -250,19 +245,6 @@ public function setNegotiator(LanguageNegotiatorInterface $negotiator) {
     $this->negotiatedLanguages = array();
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getDefaultLanguage() {
-    if (!isset($this->defaultLanguage)) {
-      // @todo Convert to CMI https://drupal.org/node/1827038 and
-      //   https://drupal.org/node/2108599.
-      $default_info = variable_get('language_default', Language::$defaultValues);
-      $this->defaultLanguage = new Language($default_info + array('default' => TRUE));
-    }
-    return $this->defaultLanguage;
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
index c9a13d655d4d..02c820544554 100644
--- a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
+++ b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
@@ -78,9 +78,4 @@ public function saveLanguageTypesConfiguration(array $config);
    */
   public function updateLockedLanguageWeights();
 
-  /**
-   * Initializes per-language overrides for configuration.
-   */
-  public function initConfigOverrides();
-
 }
diff --git a/core/modules/language/lib/Drupal/language/Entity/Language.php b/core/modules/language/lib/Drupal/language/Entity/Language.php
index 60b06a149a90..d9d6c3fbe862 100644
--- a/core/modules/language/lib/Drupal/language/Entity/Language.php
+++ b/core/modules/language/lib/Drupal/language/Entity/Language.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\language\Exception\DeleteDefaultLanguageException;
 use Drupal\language\LanguageInterface;
 
 /**
@@ -97,4 +98,17 @@ public function preSave(EntityStorageControllerInterface $storage_controller) {
     $this->langcode = 'en';
   }
 
+  /**
+   * {@inheritdoc}
+   *
+   * @throws \RuntimeException
+   */
+  public static function preDelete(EntityStorageControllerInterface $storage_controller, array $entities) {
+    $default_language = \Drupal::service('language.default')->get();
+    foreach ($entities as $entity) {
+      if ($entity->id() == $default_language->id) {
+        throw new DeleteDefaultLanguageException('Can not delete the default language');
+      }
+    }
+  }
 }
diff --git a/core/modules/language/lib/Drupal/language/EventSubscriber/ConfigSubscriber.php b/core/modules/language/lib/Drupal/language/EventSubscriber/ConfigSubscriber.php
new file mode 100644
index 000000000000..819c2d341f59
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/EventSubscriber/ConfigSubscriber.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\EventSubscriber\ConfigSubscriber.
+ */
+
+namespace Drupal\language\EventSubscriber;
+
+use Drupal\Component\PhpStorage\PhpStorageFactory;
+use Drupal\Core\Config\ConfigEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Deletes the container if default language has changed.
+ */
+class ConfigSubscriber implements EventSubscriberInterface {
+
+  /**
+   * Causes the container to be rebuilt on the next request.
+   *
+   * @param ConfigEvent $event
+   *   The configuration event.
+   */
+  public function onConfigSave(ConfigEvent $event) {
+    $saved_config = $event->getConfig();
+    if ($saved_config->getName() == 'system.site' && $saved_config->get('langcode') != $saved_config->getOriginal('langcode')) {
+      // Trigger a container rebuild on the next request by deleting compiled
+      // from PHP storage.
+      PhpStorageFactory::get('service_container')->deleteAll();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  static function getSubscribedEvents() {
+    $events['config.save'][] = array('onConfigSave', 0);
+    return $events;
+  }
+
+}
diff --git a/core/modules/language/lib/Drupal/language/EventSubscriber/LanguageRequestSubscriber.php b/core/modules/language/lib/Drupal/language/EventSubscriber/LanguageRequestSubscriber.php
index c9551f440fed..26c81901d501 100644
--- a/core/modules/language/lib/Drupal/language/EventSubscriber/LanguageRequestSubscriber.php
+++ b/core/modules/language/lib/Drupal/language/EventSubscriber/LanguageRequestSubscriber.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\language\EventSubscriber;
 
+use Drupal\Core\Config\ConfigFactory;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\Translator\TranslatorInterface;
@@ -50,6 +51,13 @@ class LanguageRequestSubscriber implements EventSubscriberInterface {
    */
   protected $currentUser;
 
+  /**
+   * The configuration factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactory
+   */
+  protected $configFactory;
+
   /**
    * Constructs a LanguageRequestSubscriber object.
    *
@@ -61,12 +69,15 @@ class LanguageRequestSubscriber implements EventSubscriberInterface {
    *   The translation service.
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current active user.
+   * @param \Drupal\Core\Config\ConfigFactory $config_factory
+   *   The configuration factory.
    */
-  public function __construct(ConfigurableLanguageManagerInterface $language_manager, LanguageNegotiatorInterface $negotiator, TranslatorInterface $translation, AccountInterface $current_user) {
+  public function __construct(ConfigurableLanguageManagerInterface $language_manager, LanguageNegotiatorInterface $negotiator, TranslatorInterface $translation, AccountInterface $current_user, ConfigFactory $config_factory) {
     $this->languageManager = $language_manager;
     $this->negotiator = $negotiator;
     $this->translation = $translation;
     $this->currentUser = $current_user;
+    $this->configFactory = $config_factory;
   }
 
   /**
@@ -83,7 +94,7 @@ public function onKernelRequestLanguage(GetResponseEvent $event) {
       if ($this->languageManager instanceof ConfigurableLanguageManagerInterface) {
         $this->languageManager->setNegotiator($this->negotiator);
         $this->languageManager->setRequest($request);
-        $this->languageManager->initConfigOverrides();
+        $this->configFactory->setLanguage($this->languageManager->getCurrentLanguage());
       }
       // After the language manager has initialized, set the default langcode
       // for the string translations.
diff --git a/core/modules/language/lib/Drupal/language/Exception/DeleteDefaultLanguageException.php b/core/modules/language/lib/Drupal/language/Exception/DeleteDefaultLanguageException.php
new file mode 100644
index 000000000000..2235aa2a26a2
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/Exception/DeleteDefaultLanguageException.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\Exception\DeleteDefaultLanguageException.
+ */
+
+namespace Drupal\language\Exception;
+
+/**
+ * Exception thrown when deleting the default language.
+ */
+class DeleteDefaultLanguageException extends LanguageException {}
diff --git a/core/modules/language/lib/Drupal/language/Exception/LanguageException.php b/core/modules/language/lib/Drupal/language/Exception/LanguageException.php
new file mode 100644
index 000000000000..80d2fb942104
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/Exception/LanguageException.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\Exception\DeleteDefaultLanguageException.
+ */
+
+namespace Drupal\language\Exception;
+
+/**
+ * A base exception thrown in any language system operations.
+ */
+class LanguageException extends \RuntimeException {}
diff --git a/core/modules/language/lib/Drupal/language/LanguageServiceProvider.php b/core/modules/language/lib/Drupal/language/LanguageServiceProvider.php
index 28a719dc28a4..8c11ecaee717 100644
--- a/core/modules/language/lib/Drupal/language/LanguageServiceProvider.php
+++ b/core/modules/language/lib/Drupal/language/LanguageServiceProvider.php
@@ -18,6 +18,8 @@
  */
 class LanguageServiceProvider extends ServiceProviderBase {
 
+  const CONFIG_PREFIX = 'language.entity.';
+
   /**
    * {@inheritdoc}
    */
@@ -29,7 +31,8 @@ public function register(ContainerBuilder $container) {
         ->addArgument(new Reference('language_manager'))
         ->addArgument(new Reference('language_negotiator'))
         ->addArgument(new Reference('string_translation'))
-        ->addArgument(new Reference('current_user'));
+        ->addArgument(new Reference('current_user'))
+        ->addArgument(new Reference('config.factory'));
 
       $container->register('path_processor_language', 'Drupal\language\HttpKernel\PathProcessorLanguage')
         ->addTag('path_processor_inbound', array('priority' => 300))
@@ -50,6 +53,14 @@ public function alter(ContainerBuilder $container) {
     $definition->setClass('Drupal\language\ConfigurableLanguageManager')
       ->addArgument(new Reference('config.factory'))
       ->addArgument(new Reference('module_handler'));
+    if ($default_language_values = $this->getDefaultLanguageValues()) {
+      $container->setParameter('language.default_values', $default_language_values);
+      // Ensure that configuration can be localised if the site is monolingual
+      // but the Language module is enabled. This is the case for monolingual
+      // sites not in English.
+      $definition = $container->getDefinition('config.factory');
+      $definition->addMethodCall('setLanguageFromDefault', array(new Reference('language.default')));
+    }
   }
 
   /**
@@ -59,7 +70,9 @@ public function alter(ContainerBuilder $container) {
    *   TRUE if the site is multilingual, FALSE otherwise.
    */
   protected function isMultilingual() {
-    $prefix = 'language.entity.';
+    // Assign the prefix to a local variable so it can be used in an anonymous
+    // function.
+    $prefix = static::CONFIG_PREFIX;
     // @todo Try to swap out for config.storage to take advantage of database
     //   and caching. This might prove difficult as this is called before the
     //   container has finished building.
@@ -70,4 +83,21 @@ protected function isMultilingual() {
     return count($config_ids) > 1;
   }
 
+  /**
+   * Gets the default language values.
+   *
+   * @return array|bool
+   *   Returns the default language values for the language configured in
+   *   system.site:langcode if the corresponding configuration entity exists,
+   *   otherwise FALSE.
+   */
+  protected function getDefaultLanguageValues() {
+    $config_storage = BootstrapConfigStorageFactory::get();
+    $system = $config_storage->read('system.site');
+    $default_language = $config_storage->read(static::CONFIG_PREFIX . $system['langcode']);
+    if (is_array($default_language)) {
+      return $default_language + array('default' => TRUE);
+    }
+    return FALSE;
+  }
 }
diff --git a/core/modules/language/lib/Drupal/language/Tests/Condition/LanguageConditionTest.php b/core/modules/language/lib/Drupal/language/Tests/Condition/LanguageConditionTest.php
index ed029fa74fdb..a9cec74fd986 100644
--- a/core/modules/language/lib/Drupal/language/Tests/Condition/LanguageConditionTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/Condition/LanguageConditionTest.php
@@ -48,9 +48,6 @@ public static function getInfo() {
   protected function setUp() {
     parent::setUp();
 
-    // This is needed for language_default().
-    // @todo remove this when language_default() no longer needs variable_get().
-    $this->installSchema('system', 'variable');
     $this->installConfig(array('language'));
 
     // Setup English.
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationTest.php
index 6f9c5523d47f..6093263d6a8d 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageConfigurationTest.php
@@ -106,7 +106,8 @@ function testLanguageConfiguration() {
 
     // Remove English language and add a new Language to check if langcode of
     // Language entity is 'en'.
-    $this->assert(language_delete('en'), 'Deleted English language.');
+    $this->drupalPostForm('admin/config/regional/language/delete/en', array(), t('Delete'));
+    $this->assertRaw(t('The %language (%langcode) language has been removed.', array('%language' => 'English', '%langcode' => 'en')));
     $edit = array(
       'predefined_langcode' => 'de',
     );
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php
index 969a836ccaa0..938f515e8595 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\Language\Language;
+use Drupal\language\Exception\DeleteDefaultLanguageException;
 
 /**
  * Test for dependency injected language object.
@@ -49,30 +50,37 @@ function testDependencyInjectedNewLanguage() {
    * @see \Drupal\Core\Language\Language
    */
   function testDependencyInjectedNewDefaultLanguage() {
+    $default_language = language_default();
     // Change the language default object to different values.
-    $new_language_default = array(
+    $new_language_default = new Language(array(
       'id' => 'fr',
       'name' => 'French',
       'direction' => 0,
       'weight' => 0,
       'method_id' => 'language-default',
       'default' => TRUE,
-    );
-    variable_set('language_default', $new_language_default);
-
-    // Initialize the language system.
-    $this->languageManager->init();
+    ));
+    language_save($new_language_default);
 
     // The language system creates a Language object which contains the
     // same properties as the new default language object.
-    $expected = new Language($new_language_default);
-    $result = $this->languageManager->getCurrentLanguage();
-    foreach ($expected as $property => $value) {
-      $this->assertEqual($expected->$property, $result->$property, format_string('The dependency injected language object %prop property equals the default language object %prop property.', array('%prop' => $property)));
+    $result = \Drupal::languageManager()->getCurrentLanguage();
+    $this->assertIdentical($result->id, 'fr');
+
+    // Delete the language to check that we fallback to the default.
+    try {
+      language_delete('fr');
+      $this->fail('Expected DeleteDefaultLanguageException thrown.');
+    }
+    catch (DeleteDefaultLanguageException $e) {
+      $this->pass('Expected DeleteDefaultLanguageException thrown.');
     }
 
-    // Delete the language_default variable we previously set.
-    variable_del('language_default');
+    // Re-save the previous default language and the delete should work.
+    language_save($default_language);
+    language_delete('fr');
+    $result = \Drupal::languageManager()->getCurrentLanguage();
+    $this->assertIdentical($result->id, $default_language->id);
   }
 
 }
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguagePathMonolingualTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguagePathMonolingualTest.php
index 840f8fc5071d..799795ec9e10 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguagePathMonolingualTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguagePathMonolingualTest.php
@@ -50,6 +50,10 @@ function setUp() {
     // Delete English.
     $this->drupalPostForm('admin/config/regional/language/delete/en', array(), t('Delete'));
 
+    // Changing the default language causes a container rebuild. Therefore need
+    // to rebuild the container in the test environment.
+    $this->rebuildContainer();
+
     // Verify that French is the only language.
     $this->container->get('language_manager')->reset();
     $this->assertFalse(\Drupal::languageManager()->isMultilingual(), 'Site is mono-lingual');
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageTestBase.php b/core/modules/language/lib/Drupal/language/Tests/LanguageTestBase.php
index 70a512204f8a..a1780b78c7c8 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageTestBase.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageTestBase.php
@@ -14,6 +14,7 @@
  */
 abstract class LanguageTestBase extends DrupalUnitTestBase {
 
+  public static $modules = array('system', 'language', 'language_test');
   /**
    * The language manager.
    *
@@ -34,7 +35,6 @@ abstract class LanguageTestBase extends DrupalUnitTestBase {
   protected function setUp() {
     parent::setUp();
 
-    $this->enableModules(array('system', 'language', 'language_test'));
     $this->installSchema('system', array('variable'));
     $this->installConfig(array('language'));
 
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php
index 1a07175b830a..bc43db297da4 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageUILanguageNegotiationTest.php
@@ -94,8 +94,14 @@ function testUILanguageNegotiation() {
     $language_domain = 'example.cn';
 
     // Setup the site languages by installing two languages.
+    // Set the default language in order for the translated string to be registered
+    // into database when seen by t(). Without doing this, our target string
+    // is for some reason not found when doing translate search. This might
+    // be some bug.
+    $default_language = language_default();
     $language = new Language(array(
       'id' => $langcode_browser_fallback,
+      'default' => TRUE,
     ));
     language_save($language);
     $language = new Language(array(
@@ -107,17 +113,15 @@ function testUILanguageNegotiation() {
     // corresponding translated string is shown.
     $default_string = 'Configure languages for content and the user interface';
 
-    // Set the default language in order for the translated string to be registered
-    // into database when seen by t(). Without doing this, our target string
-    // is for some reason not found when doing translate search. This might
-    // be some bug.
-    $this->container->get('language_manager')->reset();
-    $languages = language_list();
-    variable_set('language_default', (array) $languages['vi']);
     // First visit this page to make sure our target string is searchable.
     $this->drupalGet('admin/config');
+
     // Now the t()'ed string is in db so switch the language back to default.
-    variable_del('language_default');
+    // This will rebuild the container so we need to rebuild the container in
+    // the test environment.
+    language_save($default_language);
+    \Drupal::config('language.negotiation')->set('url.prefixes.en', '')->save();
+    $this->rebuildContainer();
 
     // Translate the string.
     $language_browser_fallback_string = "In $langcode_browser_fallback In $langcode_browser_fallback In $langcode_browser_fallback";
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
index 989ac42907b4..9f24b8946e51 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Language\Language;
+use Drupal\Core\Language\LanguageDefault;
 use Drupal\Core\Language\LanguageManager;
 use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSelected;
 use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
@@ -95,7 +96,7 @@ function testUninstallProcess() {
     // Change language negotiation options.
     drupal_load('module', 'locale');
     // Pick only core language types.
-    $language_manager = new LanguageManager();
+    $language_manager = new LanguageManager(new LanguageDefault(Language::$defaultValues));
     $default_types = $language_manager->getLanguageTypes();
     \Drupal::config('language.types')->set('configurable', $default_types + array('language_custom' => TRUE))->save();
     $config = array_flip(array_keys(\Drupal::service('plugin.manager.language_negotiation_method')->getDefinitions()));
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
index 25754891e3af..0e4024369400 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/DrupalUnitTestBase.php
@@ -10,6 +10,7 @@
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
+use Drupal\Core\Language\Language;
 use Symfony\Component\DependencyInjection\Reference;
 use Drupal\Core\Database\Database;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -155,6 +156,9 @@ public function containerBuild(ContainerBuilder $container) {
     // Keep the container object around for tests.
     $this->container = $container;
 
+    // Set the default language on the minimal container.
+    $this->container->setParameter('language.default_values', Language::$defaultValues);
+
     $container->register('lock', 'Drupal\Core\Lock\NullLockBackend');
     $this->settingsSet('cache', array('default' => 'cache.backend.memory'));
 
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 78b154e8de89..bca0239f38e2 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -1003,7 +1003,11 @@ private function prepareEnvironment() {
     $this->container = new ContainerBuilder();
 
     // @todo Remove this once this class has no calls to t() and format_plural()
-    $this->container->register('language_manager', 'Drupal\Core\Language\LanguageManager');
+    $this->container->setParameter('language.default_values', Language::$defaultValues);
+    $this->container->register('language.default', 'Drupal\Core\Language\LanguageDefault')
+      ->addArgument('%language.default_values%');
+    $this->container->register('language_manager', 'Drupal\Core\Language\LanguageManager')
+      ->addArgument(new Reference('language.default'));
     $this->container->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager')
       ->addArgument(new Reference('language_manager'));
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php
index 8ce7d1a6fdde..0aa1f1f9bf80 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/TwigTransTest.php
@@ -80,11 +80,10 @@ protected function setUp() {
     $this->installLanguages();
 
     // Assign Lolspeak (xx) to be the default language.
-    $edit = array('site_default_language' => 'xx');
-    $this->drupalPostForm('admin/config/regional/settings', $edit, t('Save configuration'));
-
-    // Reset the static cache of the language list.
-    $this->container->get('language_manager')->reset();
+    $language = \Drupal::languageManager()->getLanguage('xx');
+    $language->default = TRUE;
+    language_save($language);
+    $this->rebuildContainer();
 
     // Check that lolspeak is the default language for the site.
     $this->assertEqual(language_default()->id, 'xx', 'Lolspeak is the default language');
-- 
GitLab