diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php
index eed4f89..469634a 100644
--- a/core/lib/Drupal/Core/Config/Config.php
+++ b/core/lib/Drupal/Core/Config/Config.php
@@ -101,13 +101,6 @@ class Config {
   protected $storage;
 
   /**
-   * Whether the configuration object has already been loaded.
-   *
-   * @var bool
-   */
-  protected $isLoaded = FALSE;
-
-  /**
    * The config schema wrapper object for this configuration object.
    *
    * @var \Drupal\Core\Config\Schema\Element
@@ -154,7 +147,6 @@ public function __construct($name, StorageInterface $storage, EventDispatcher $e
    *   The configuration object.
    */
   public function initWithData(array $data) {
-    $this->isLoaded = TRUE;
     $this->settingsOverrides = array();
     $this->languageOverrides = array();
     $this->moduleOverrides = array();
@@ -228,9 +220,6 @@ public static function validateName($name) {
    *   TRUE if this configuration object does not exist in storage.
    */
   public function isNew() {
-    if (!$this->isLoaded) {
-      $this->load();
-    }
     return $this->isNew;
   }
 
@@ -255,9 +244,6 @@ public function isNew() {
    *   The data that was requested.
    */
   public function get($key = '') {
-    if (!$this->isLoaded) {
-      $this->load();
-    }
     if (!isset($this->overriddenData)) {
       $this->setOverriddenData();
     }
@@ -287,8 +273,6 @@ public function get($key = '') {
    */
   public function setData(array $data) {
     $this->replaceData($data);
-    // A load would destroy the data just set (for example on import).
-    $this->isLoaded = TRUE;
     return $this;
   }
 
@@ -409,10 +393,6 @@ protected function resetOverriddenData() {
    *   The configuration object.
    */
   public function set($key, $value) {
-    if (!$this->isLoaded) {
-      $this->load();
-    }
-
     // The dot/period is a reserved character; it may appear between keys, but
     // not within keys.
     $parts = explode('.', $key);
@@ -436,9 +416,6 @@ public function set($key, $value) {
    *   The configuration object.
    */
   public function clear($key) {
-    if (!$this->isLoaded) {
-      $this->load();
-    }
     $parts = explode('.', $key);
     if (count($parts) == 1) {
       unset($this->data[$key]);
@@ -451,27 +428,6 @@ public function clear($key) {
   }
 
   /**
-   * Loads configuration data into this object.
-   *
-   * @return \Drupal\Core\Config\Config
-   *   The configuration object.
-   */
-  public function load() {
-    $this->isLoaded = FALSE;
-    $data = $this->storage->read($this->name);
-    if ($data === FALSE) {
-      $this->isNew = TRUE;
-      $this->replaceData(array());
-    }
-    else {
-      $this->isNew = FALSE;
-      $this->replaceData($data);
-    }
-    $this->isLoaded = TRUE;
-    return $this;
-  }
-
-  /**
    * Saves the configuration object.
    *
    * @return \Drupal\Core\Config\Config
@@ -491,9 +447,6 @@ public function save() {
       }
     }
 
-    if (!$this->isLoaded) {
-      $this->load();
-    }
     $this->storage->write($this->name, $this->data);
     $this->isNew = FALSE;
     $this->notify('save');
@@ -546,9 +499,6 @@ protected function notify($config_event_name) {
    *   The configuration object.
    */
   public function merge(array $data_to_merge) {
-    if (!$this->isLoaded) {
-      $this->load();
-    }
     // Preserve integer keys so that configuration keys are not changed.
     $this->replaceData(NestedArray::mergeDeepArray(array($this->data, $data_to_merge), TRUE));
     return $this;
@@ -644,9 +594,6 @@ public function getLanguage() {
    *   The raw data.
    */
   public function getRawData() {
-    if (!$this->isLoaded) {
-      $this->load();
-    }
     return $this->data;
   }
 
diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php
index 8aeb301..3ed5423 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\LanguageManagerInterface;
 use Symfony\Component\EventDispatcher\EventDispatcher;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
@@ -55,9 +56,16 @@ class ConfigFactory implements EventSubscriberInterface {
   /**
    * The language object used to override configuration data.
    *
+   * @var \Drupal\Core\Language\LanguageManagerInterface
+   */
+  protected $languageManager;
+
+  /**
+   * The language object used to override configuration data.
+   *
    * @var \Drupal\Core\Language\Language
    */
-  protected $language;
+  protected $enforcedLanguage;
 
   /**
    * Cached configuration objects.
@@ -82,16 +90,16 @@ 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
+   * @param \Drupal\Core\Language\LanguageManagerInterface::
+   *   (optional) The language manager 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, LanguageManagerInterface $language_manager = NULL) {
     $this->storage = $storage;
     $this->eventDispatcher = $event_dispatcher;
     $this->typedConfigManager = $typed_config;
-    $this->language = $language;
+    $this->languageManager = $language_manager;
   }
 
   /**
@@ -141,12 +149,13 @@ public function get($name) {
         // If the configuration object does not exist in the configuration
         // storage or static cache create a new object and add it to the static
         // cache.
-        $this->cache[$cache_key] = new Config($name, $this->storage, $this->eventDispatcher, $this->typedConfigManager, $this->language);
+        $this->cache[$cache_key] = new Config($name, $this->storage, $this->eventDispatcher, $this->typedConfigManager, $this->getLanguage());
 
         if ($this->canOverride($name)) {
-          // Get and apply any language overrides.
-          if ($this->language) {
-            $language_overrides = $this->storage->read($this->getLanguageConfigName($this->language->id, $name));
+          // Get and apply any language overrides if there is a language and
+          // this is not a language override config object already.
+          if ($this->getLanguage() && $this->getLanguageConfigName($this->getLanguage()->id, $name)) {
+            $language_overrides = $this->storage->read($this->getLanguageConfigName($this->getLanguage()->id, $name));
           }
           else {
             $language_overrides = FALSE;
@@ -226,7 +235,7 @@ public function loadMultiple(array $names) {
         }
         $cache_key = $this->getCacheKey($name);
 
-        $this->cache[$cache_key] = new Config($name, $this->storage, $this->eventDispatcher, $this->typedConfigManager, $this->language);
+        $this->cache[$cache_key] = new Config($name, $this->storage, $this->eventDispatcher, $this->typedConfigManager, $this->getLanguage());
         $this->cache[$cache_key]->initWithData($data);
         if ($this->canOverride($name)) {
           if (isset($language_names[$name]) && isset($storage_data[$language_names[$name]])) {
@@ -256,7 +265,7 @@ public function loadMultiple(array $names) {
    *   An array of overrides keyed by the configuration object name.
    */
   protected function loadModuleOverrides(array $names) {
-    $configOverridesEvent = new ConfigModuleOverridesEvent($names, $this->language);
+    $configOverridesEvent = new ConfigModuleOverridesEvent($names, $this->getLanguage());
     $this->eventDispatcher->dispatch('config.module.overrides', $configOverridesEvent);
     return $configOverridesEvent->getOverrides();
   }
@@ -308,7 +317,7 @@ public function rename($old_name, $new_name) {
     }
 
     $new_cache_key = $this->getCacheKey($new_name);
-    $this->cache[$new_cache_key] = new Config($new_name, $this->storage, $this->eventDispatcher, $this->typedConfigManager, $this->language);
+    $this->cache[$new_cache_key] = new Config($new_name, $this->storage, $this->eventDispatcher, $this->typedConfigManager, $this->getLanguage());
     $this->cache[$new_cache_key]->load();
     return $this->cache[$new_cache_key];
   }
@@ -326,8 +335,8 @@ public function getCacheKey($name) {
     $can_override = $this->canOverride($name);
     $cache_key = $name . ':' . ($can_override ? 'overrides' : 'raw');
 
-    if ($can_override && isset($this->language)) {
-      $cache_key =  $cache_key . ':' . $this->language->id;
+    if ($can_override && $this->getLanguage()) {
+      $cache_key =  $cache_key . ':' . $this->getLanguage()->id;
     }
     return $cache_key;
   }
@@ -360,7 +369,22 @@ public function clearStaticCache() {
   }
 
   /**
-   * Set the language to be used in configuration overrides.
+   * Sets the language manager, which will be used for language overrides.
+   *
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_$manager
+   *   The language manager to be set on the config factory. Used to override
+   *   configuration by language.
+   *
+   * @return $this
+   *   The config factory object.
+   */
+  public function setLanguageManager(LanguageManagerInterface $language_manager = NULL) {
+    $this->languageManager = $language_manager;
+    return $this;
+  }
+
+  /**
+   * Enforce a given language for language overrides.
    *
    * @param \Drupal\Core\Language\Language $language
    *   The language object to be set on the config factory. Used to override
@@ -368,19 +392,36 @@ public function clearStaticCache() {
    *
    * @return \Drupal\Core\Config\ConfigFactory
    *   The config factory object.
+   *
+   * @see \Drupal\Core\Config\ConfigFactory::removeEnforcedLanguage()
    */
-  public function setLanguage(Language $language = NULL) {
-    $this->language = $language;
+  public function enforceLanguage(Language $language = NULL) {
+    $this->enforcedLanguage = $language;
     return $this;
   }
 
   /**
+   * Removes an enforced language, falling back to the current language.
+   */
+  public function resetEnforcedLanguage() {
+    $this->enforcedLanguage = NULL;
+  }
+
+  /**
    * Gets the language Used to override configuration.
    *
    * @return \Drupal\Core\Language\Language
    */
   public function getLanguage() {
-    return $this->language;
+    // If there is an enforced language, return it.
+    if ($this->enforcedLanguage) {
+      return $this->enforcedLanguage;
+    }
+    // Only return a language if there is a language manager and this is
+    // a multilingual site.
+    if ($this->languageManager && $this->languageManager->isMultilingual()) {
+      return $this->languageManager->getCurrentLanguage();
+    }
   }
 
   /**
@@ -397,9 +438,9 @@ public function getLanguage() {
    */
   public function getLanguageConfigNames(array $names) {
     $language_names = array();
-    if (isset($this->language)) {
+    if ($this->getLanguage()) {
       foreach ($names as $name) {
-        if ($language_name = $this->getLanguageConfigName($this->language->id, $name)) {
+        if ($language_name = $this->getLanguageConfigName($this->getLanguage()->id, $name)) {
           $language_names[$name] = $language_name;
         }
       }
diff --git a/core/lib/Drupal/Core/Datetime/Date.php b/core/lib/Drupal/Core/Datetime/Date.php
index 18f2425..b1ad23a 100644
--- a/core/lib/Drupal/Core/Datetime/Date.php
+++ b/core/lib/Drupal/Core/Datetime/Date.php
@@ -215,11 +215,10 @@ protected function t($string, array $args = array(), array $options = array()) {
    */
   protected function dateFormat($format, $langcode) {
     if (!isset($this->dateFormats[$format][$langcode])) {
-      // Enter a language specific context so the right date format is loaded.
-      $original_language = $this->configFactory->getLanguage();
-      $this->configFactory->setLanguage(new Language(array('id' => $langcode)));
+      // Enforce the requested language so the right date format is loaded.
+      $this->configFactory->enforceLanguage(new Language(array('id' => $langcode)));
       $this->dateFormats[$format][$langcode] = $this->dateFormatStorage->load($format);
-      $this->configFactory->setLanguage($original_language);
+      $this->configFactory->resetEnforcedLanguage();
     }
     return $this->dateFormats[$format][$langcode];
   }
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index 0160119..47139e1 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -416,7 +416,7 @@ protected function initializeContainer() {
 
       // If 'container.modules' is wrong, the container must be rebuilt.
       if (!isset($this->moduleList)) {
-        $this->moduleList = $this->container->get('config.factory')->get('system.module')->load()->get('enabled');
+        $this->moduleList = $this->container->get('config.factory')->get('system.module')->get('enabled');
       }
       if (array_keys($this->moduleList) !== array_keys($container_modules)) {
         $persist = $this->getServicesToPersist();
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php b/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php
index 4d7bdf9..fd05563 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigLanguageOverride.php
@@ -33,7 +33,7 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
     $this->installConfig(array('config_test'));
-    \Drupal::configFactory()->setLanguage(language_default());
+    \Drupal::configFactory()->setLanguageManager(\Drupal::languageManager());
   }
 
   /**
@@ -52,11 +52,11 @@ function testConfigLanguageOverride() {
       'id' => 'de',
     )));
 
-    \Drupal::configFactory()->setLanguage(language_load('fr'));
+    \Drupal::configFactory()->enforceLanguage(language_load('fr'));
     $config = \Drupal::config('config_test.system');
     $this->assertIdentical($config->get('foo'), 'fr bar');
 
-    \Drupal::configFactory()->setLanguage(language_load('de'));
+    \Drupal::configFactory()->enforceLanguage(language_load('de'));
     $config = \Drupal::config('config_test.system');
     $this->assertIdentical($config->get('foo'), 'de bar');
 
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigOverridesPriorityTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigOverridesPriorityTest.php
index 7657376..4d577d0 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigOverridesPriorityTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigOverridesPriorityTest.php
@@ -60,7 +60,7 @@ public function testOverridePriorities() {
       'name' => 'French',
       'id' => 'fr',
     ));
-    $config_factory->setLanguage($language);
+    $config_factory->enforceLanguage($language);
     $language_config_name = $config_factory->getLanguageConfigName($language->id, 'system.site');
     $config_factory
       ->get($language_config_name)
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php b/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php
index 9295b81..3a2e46f 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/Form/ConfigTranslationFormBase.php
@@ -171,8 +171,7 @@ public function buildForm(array $form, array &$form_state, Request $request = NU
     $this->configFactory->enableOverrides();
 
     // Set the translation target language on the configuration factory.
-    $original_language = $this->configFactory->getLanguage();
-    $this->configFactory->setLanguage($this->language);
+    $this->configFactory->enforceLanguage($this->language);
 
     // Add some information to the form state for easier form altering.
     $form_state['config_translation_mapper'] = $this->mapper;
@@ -197,8 +196,8 @@ public function buildForm(array $form, array &$form_state, Request $request = NU
       '#button_type' => 'primary',
     );
 
-    // Set the configuration language back.
-    $this->configFactory->setLanguage($original_language);
+    // Reset the enforced language, fall back to the current language.
+    $this->configFactory->resetEnforcedLanguage();
 
     return $form;
   }
diff --git a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
index 49c7ea4..6fc1e32 100644
--- a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
+++ b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
@@ -107,7 +107,7 @@ public function __construct(ConfigFactory $config_factory, ModuleHandlerInterfac
    * {@inheritdoc}
    */
   public function initConfigOverrides() {
-    $this->configFactory->setLanguage($this->getCurrentLanguage());
+    $this->configFactory->setLanguageManager($this);
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php
index 7cb4df5..e93a32d 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php
@@ -48,7 +48,7 @@ function setUp() {
    */
   public function testMenuRouterRebuildContext() {
     // Enter a language context before rebuilding the menu router tables.
-    \Drupal::configFactory()->setLanguage(language_load('nl'));
+    \Drupal::configFactory()->enforceLanguage(language_load('nl'));
     menu_router_rebuild();
 
     // Check that the language context was not used for building the menu item.
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 88862d5..321631c 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1334,10 +1334,8 @@ function user_mail($key, &$message, $params) {
   $langcode = $message['langcode'];
   $variables = array('user' => $params['account']);
 
-  $original_language = \Drupal::configFactory()->getLanguage();
-
   $language = language_load($params['account']->getPreferredLangcode());
-  \Drupal::configFactory()->setLanguage($language);
+  \Drupal::configFactory()->enforceLanguage($language);
   $mail_config = \Drupal::config('user.mail');
 
    // We do not sanitize the token replacement, since the output of this
@@ -1346,7 +1344,7 @@ function user_mail($key, &$message, $params) {
   $message['subject'] .= $token_service->replace($mail_config->get($key . '.subject'), $variables, $token_options);
   $message['body'][] = $token_service->replace($mail_config->get($key . '.body'), $variables, $token_options);
 
-  \Drupal::configFactory()->setLanguage($original_language);
+  \Drupal::configFactory()->resetEnforcedLanguage();
 }
 
 /**
