diff --git a/core/lib/Drupal/Core/Config/CachedStorage.php b/core/lib/Drupal/Core/Config/CachedStorage.php
index beb8c09..2067b40 100644
--- a/core/lib/Drupal/Core/Config/CachedStorage.php
+++ b/core/lib/Drupal/Core/Config/CachedStorage.php
@@ -68,22 +68,14 @@ public function exists($name) {
    */
   public function read($name) {
     if ($cache = $this->cache->get($name)) {
-      // The cache backend supports primitive data types, but only an array
-      // represents valid config object data.
-      if (is_array($cache->data)) {
-        return $cache->data;
-      }
+      // The cache contains either the cached configuration data or FALSE
+      // if the configuration file does not exist.
+      return $cache->data;
     }
-    // Read from the storage on a cache miss and cache the data, if any.
+    // Read from the storage on a cache miss and cache the data. Also cache
+    // information about missing configuration objects.
     $data = $this->storage->read($name);
-    if ($data !== FALSE) {
-      $this->cache->set($name, $data, CacheBackendInterface::CACHE_PERMANENT);
-    }
-    // If the cache contained bogus data and there is no data in the storage,
-    // wipe the cache entry.
-    elseif ($cache) {
-      $this->cache->delete($name);
-    }
+    $this->cache->set($name, $data, CacheBackendInterface::CACHE_PERMANENT);
     return $data;
   }
 
@@ -99,9 +91,10 @@ public function readMultiple(array $names) {
 
     if (!empty($names)) {
       $list = $this->storage->readMultiple($names);
-      // Cache configuration objects that were loaded from the storage.
-      foreach ($list as $name => $data) {
-        $this->cache->set($name, $data, CacheBackendInterface::CACHE_PERMANENT);
+      // Cache configuration objects that were loaded from the storage, cache
+      // missing configuration objects as an explicit FALSE.
+      foreach ($names as $name) {
+        $this->cache->set($name, isset($list[$name]) ? $list[$name] : FALSE, CacheBackendInterface::CACHE_PERMANENT);
       }
     }
 
@@ -110,7 +103,9 @@ public function readMultiple(array $names) {
       $list[$name] = $cache->data;
     }
 
-    return $list;
+    // Ensure that only existing configuration objects are returned, filter out
+    // cached information about missing objects.
+    return array_filter($list);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php
index eed4f89..4e86727 100644
--- a/core/lib/Drupal/Core/Config/Config.php
+++ b/core/lib/Drupal/Core/Config/Config.php
@@ -67,7 +67,7 @@ class Config {
    *
    * @var array
    */
-  protected $data;
+  protected $data = array();
 
   /**
    * The current runtime data.
@@ -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..2487069 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,8 +317,8 @@ 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]->load();
+    $this->cache[$new_cache_key] = new Config($new_name, $this->storage, $this->eventDispatcher, $this->typedConfigManager, $this->getLanguage());
+    $this->cache[$new_cache_key]->initWithData($this->storage->read($new_name));
     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,35 @@ 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.
+    if ($this->languageManager) {
+      return $this->languageManager->getCurrentLanguage();
+    }
   }
 
   /**
@@ -397,9 +437,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/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php
index 0feabdf..8d76db3 100644
--- a/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -296,7 +296,6 @@ protected function importInvokeOwner() {
         // Config::validateName($name);
         if ($entity_type = config_get_entity_type_by_name($name)) {
           $old_config = new Config($name, $this->storageComparer->getTargetStorage(), $this->eventDispatcher, $this->typedConfigManager);
-          $old_config->load();
 
           $data = $this->storageComparer->getSourceStorage()->read($name);
           $new_config = new Config($name, $this->storageComparer->getTargetStorage(), $this->eventDispatcher, $this->typedConfigManager);
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/rest/lib/Drupal/rest/Routing/ResourceRoutes.php b/core/modules/rest/lib/Drupal/rest/Routing/ResourceRoutes.php
index ef1b93f..9dc764a 100644
--- a/core/modules/rest/lib/Drupal/rest/Routing/ResourceRoutes.php
+++ b/core/modules/rest/lib/Drupal/rest/Routing/ResourceRoutes.php
@@ -62,7 +62,7 @@ public static function create(ContainerInterface $container) {
    */
   public function routes() {
     $routes = array();
-    $enabled_resources = $this->config->get('rest.settings')->load()->get('resources');
+    $enabled_resources = $this->config->get('rest.settings')->get('resources');
 
     // Iterate over all enabled resource plugins.
     foreach ($enabled_resources as $id => $enabled_methods) {
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();
 }
 
 /**
