diff -u b/core/lib/Drupal/Core/Config/CachedStorage.php b/core/lib/Drupal/Core/Config/CachedStorage.php
--- b/core/lib/Drupal/Core/Config/CachedStorage.php
+++ b/core/lib/Drupal/Core/Config/CachedStorage.php
@@ -87,10 +87,11 @@
     // The names array is passed by reference and will only contain the names of
     // config object not found after the method call.
     // @see \Drupal\Core\Cache\CacheBackendInterface::getMultiple()
-    $names = $this->getCacheKeys($names);
-    $cached_list = $this->cache->getMultiple($names);
+    $cids = $this->getCacheKeys($names);
+    $cached_list = $this->cache->getMultiple($cids);
 
-    if (!empty($names)) {
+    if (!empty($cids)) {
+      $names = $this->getNamesFromCacheKeys($cids);
       $list = $this->storage->readMultiple($names);
       // Cache configuration objects that were loaded from the storage, cache
       // missing configuration objects as an explicit FALSE.
@@ -100,8 +101,8 @@
     }
 
     // Add the configuration objects from the cache to the list.
-    foreach ($cached_list as $name => $cache) {
-      $list[$this->getNameFromCacheKey($name)] = $cache->data;
+    foreach ($cached_list as $cid => $cache) {
+      $list[$this->getNameFromCacheKey($cid)] = $cache->data;
     }
 
     // Ensure that only existing configuration objects are returned, filter out
@@ -241,6 +242,14 @@
   /**
    * Gets the cache key for a configuration object name.
    *
+   * In the default implementation of CachedStorage this simply returns the
+   * name. In more complex implementations this allows different versions of
+   * the same configuration object to cached. Since the maximum length of a
+   * configuration object name is 250 characters this should never add more than
+   * 5 characters to the cache key.
+   *
+   * @see \Drupal\language\Config\LanguageStorage::getCacheKey()
+   *
    * @param string $name
    *   The configuration object name.
    *
@@ -278,2 +287,15 @@
   }
+
+  /**
+   * Converts an array of cache keys into an array of configuration object names.
+   *
+   * @param string $key
+   *   The cache key.
+   *
+   * @return string
+   *   The configuration object name.
+   */
+  protected function getNamesFromCacheKeys($keys) {
+    return $keys;
+  }
 }
diff -u b/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php
--- b/core/lib/Drupal/Core/Config/ConfigFactory.php
+++ b/core/lib/Drupal/Core/Config/ConfigFactory.php
@@ -326,9 +326,9 @@
    */
   public function getSortedConfigFactoryOverrides() {
     if (!isset($this->sortedConfigFactoryOverrides)) {
-      // Sort the negotiators according to priority.
+      // Sort the override objects according to priority.
       krsort($this->configFactoryOverrides);
-      // Merge nested negotiators from $this->configFactoryOverrides into
+      // Merge nested override objects from $this->configFactoryOverrides into
       // $this->sortedConfigFactoryOverrides.
       $this->sortedConfigFactoryOverrides = array();
       foreach ($this->configFactoryOverrides as $overrides) {
diff -u b/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
--- b/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -72,14 +72,14 @@
   /**
    * {@inheritdoc}
    */
-  public function installDefaultConfig($type, $extension_name) {
+  public function installDefaultConfig($type, $name) {
     // Get all default configuration owned by this extension.
     $source_storage = new ExtensionInstallStorage($this->activeStorage);
-    $config_to_install = $source_storage->listAll($extension_name . '.');
+    $config_to_install = $source_storage->listAll($name . '.');
 
     // Work out if this extension provides default configuration for any other
     // enabled extensions.
-    $config_dir = drupal_get_path($type, $extension_name) . '/config';
+    $config_dir = drupal_get_path($type, $name) . '/config';
     if (is_dir($config_dir)) {
       if (is_dir($config_dir . '/schema')) {
         // Refresh the schema cache if installing default configuration and the
@@ -87,8 +87,8 @@
         $this->typedConfig->clearCachedDefinitions();
       }
       $default_storage = new FileStorage($config_dir);
-      $other_module_config = array_filter($default_storage->listAll(), function ($value) use ($extension_name) {
-        return !preg_match('/^' . $extension_name . '\./', $value);
+      $other_module_config = array_filter($default_storage->listAll(), function ($value) use ($name) {
+        return !preg_match('/^' . $name . '\./', $value);
       });
 
       // Read enabled extensions directly from configuration to avoid circular
@@ -107,18 +107,18 @@
     if (!empty($config_to_install)) {
       $old_state = $this->configFactory->getOverrideState();
       $this->configFactory->setOverrideState(FALSE);
-      foreach ($config_to_install as $name) {
+      foreach ($config_to_install as $config_name) {
         // Only import new config.
-        if ($this->activeStorage->exists($name)) {
+        if ($this->activeStorage->exists($config_name)) {
           continue;
         }
 
-        $new_config = new Config($name, $this->activeStorage, $this->typedConfig, $this->eventDispatcher);
-        $data = $source_storage->read($name);
+        $new_config = new Config($config_name, $this->activeStorage, $this->typedConfig, $this->eventDispatcher);
+        $data = $source_storage->read($config_name);
         if ($data !== FALSE) {
           $new_config->setData($data);
         }
-        if ($entity_type = $this->configManager->getEntityTypeIdByName($name)) {
+        if ($entity_type = $this->configManager->getEntityTypeIdByName($config_name)) {
           $this->configManager
             ->getEntityManager()
             ->getStorageController($entity_type)
@@ -134,7 +134,7 @@
 
     // Allow configFactory overrides to respond to installation.
     foreach ($this->configFactory->getSortedConfigFactoryOverrides() as $config_override) {
-      $config_override->install($type, $extension_name);
+      $config_override->install($type, $name);
     }
   }
 
reverted:
--- b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
+++ a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
@@ -30,11 +30,11 @@
    *
    * @param string $type
    *   The extension type; e.g., 'module' or 'theme'.
+   * @param string $name
-   * @param string $extension_name
    *   The name of the module or theme to install default configuration for.
    *
    * @see \Drupal\Core\Config\ExtensionInstallStorage
    */
+  public function installDefaultConfig($type, $name);
-  public function installDefaultConfig($type, $extension_name);
 
 }
diff -u b/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php
--- b/core/lib/Drupal/Core/Config/FileStorage.php
+++ b/core/lib/Drupal/Core/Config/FileStorage.php
@@ -243,7 +243,7 @@
   }
 
   /**
-   * Sets rhe filesystem path for configuration objects.
+   * Sets the filesystem path for configuration objects.
    *
    * @param string $directory
    *   The filesystem path for configuration objects.
diff -u b/core/lib/Drupal/Core/Datetime/Date.php b/core/lib/Drupal/Core/Datetime/Date.php
--- b/core/lib/Drupal/Core/Datetime/Date.php
+++ b/core/lib/Drupal/Core/Datetime/Date.php
@@ -215,14 +215,10 @@
    */
   protected function dateFormat($format, $langcode) {
     if (!isset($this->dateFormats[$format][$langcode])) {
-      if ($this->languageManager->isConfigurable()) {
-        $original_language = $this->languageManager->getConfigOverrideLanguage();
-        $this->languageManager->setConfigOverrideLanguage(new Language(array('id' => $langcode)));
-      }
+      $original_language = $this->languageManager->getConfigOverrideLanguage();
+      $this->languageManager->setConfigOverrideLanguage(new Language(array('id' => $langcode)));
       $this->dateFormats[$format][$langcode] = $this->dateFormatStorage->load($format);
-      if ($this->languageManager->isConfigurable()) {
-        $this->languageManager->setConfigOverrideLanguage($original_language);
-      }
+      $this->languageManager->setConfigOverrideLanguage($original_language);
     }
     return $this->dateFormats[$format][$langcode];
   }
diff -u b/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php
--- b/core/lib/Drupal/Core/Language/LanguageManager.php
+++ b/core/lib/Drupal/Core/Language/LanguageManager.php
@@ -331,9 +331,22 @@
 
   /**
    * {@inheritdoc}
+   *
+   * This function is a noop since the configuration can not be overridden by
+   * language unless the Language module is enabled. This replaces the default
+   * language manger with a configurable language manager.
+   *
+   * @see \Drupal\language\ConfigurableLanguageManager::setConfigOverrideLanguage()
    */
-  public function isConfigurable() {
-    return FALSE;
+  public function setConfigOverrideLanguage(Language $language) {
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfigOverrideLanguage() {
+    return $this->getCurrentLanguage();
   }
 
 }
diff -u b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
--- b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
+++ b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
@@ -170,10 +170,21 @@
 
   /**
-   * Determines if thr language manager is configurable or not.
+   * Sets the configuration override language.
    *
-   * @return bool
-   *   TRUE if the LanguageManager is configurable, FALSE if not.
+   * @param \Drupal\Core\Language\Language $language
+   *   The language to override configuration with.
+   *
+   * @return $this
+   *   The language manager.
+   */
+  public function setConfigOverrideLanguage(Language $language);
+
+  /**
+   * Gets the current configuration override language.
+   *
+   * @return \Drupal\Core\Language\Language $language
+   *   The current configuration override language.
    */
-  public function isConfigurable();
+  public function getConfigOverrideLanguage();
 
 }
diff -u b/core/modules/language/language.services.yml b/core/modules/language/language.services.yml
--- b/core/modules/language/language.services.yml
+++ b/core/modules/language/language.services.yml
@@ -11,9 +11,17 @@
     class: Drupal\language\EventSubscriber\ConfigSubscriber
     tags:
       - { name: event_subscriber }
+  language.cache_config:
+    class: Drupal\Core\Cache\CacheBackendInterface
+    tags:
+      - { name: cache.bin }
+      - { name: persist }
+    factory_method: get
+    factory_service: cache_factory
+    arguments: [language_config]
   language.config_storage:
     class: Drupal\language\Config\LanguageStorage
-    arguments: ['@cache.config']
+    arguments: ['@language.cache_config']
     tags:
       - { name: persist }
   language.config_factory_override:
diff -u b/core/modules/language/lib/Drupal/language/Config/LanguageStorage.php b/core/modules/language/lib/Drupal/language/Config/LanguageStorage.php
--- b/core/modules/language/lib/Drupal/language/Config/LanguageStorage.php
+++ b/core/modules/language/lib/Drupal/language/Config/LanguageStorage.php
@@ -111,7 +111,7 @@
    * {@inheritdoc}
    */
   protected function getCacheKey($name) {
-    return 'language.' . $this->langcode . ':' . $name;
+    return $this->langcode . ':' . $name;
   }
 
   /**
@@ -133,6 +133,16 @@
   }
 
   /**
+   * {@inheritdoc}
+   */
+  protected function getNamesFromCacheKeys($keys) {
+    foreach ($keys as &$key) {
+      $key = $this->getNameFromCacheKey($key);
+    }
+    return $keys;
+  }
+
+  /**
    * Discovers is the directory for the langcode exists.
    *
    * @return bool
diff -u b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
--- b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
+++ b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
@@ -438,9 +438,2 @@
 
-  /**
-   * {@inheritdoc}
-   */
-  public function isConfigurable() {
-    return TRUE;
-  }
-
 }
diff -u b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
--- b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
+++ b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
@@ -17,11 +17,6 @@
 interface ConfigurableLanguageManagerInterface extends LanguageManagerInterface {
 
   /**
-   * TRUE if the LanguageManager is configurable. Default implementation is FALSE.
-   */
-  const CONFIGURABLE = TRUE;
-
-  /**
    * Injects the request object.
    *
    * @param \Symfony\Component\HttpFoundation\Request
@@ -84,26 +79,7 @@
   public function updateLockedLanguageWeights();
 
   /**
-   * Sets the configuration override language.
-   *
-   * @param \Drupal\Core\Language\Language $language
-   *   The language to override configuration with.
-   *
-   * @return $this
-   *   The configurable language manager.
-   */
-  public function setConfigOverrideLanguage(Language $language);
-
-  /**
-   * Gets the current configuration override language.
-   *
-   * @return \Drupal\Core\Language\Language $language
-   *   The current configuration override language.
-   */
-  public function getConfigOverrideLanguage();
-
-  /**
-   * Gets language override configuration object.
+   * Gets a language override configuration object.
    *
    * @param $name
    *   The configuration object name.
diff -u b/core/modules/user/user.module b/core/modules/user/user.module
--- b/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1380,15 +1380,13 @@
  */
 function user_mail($key, &$message, $params) {
   $token_service = \Drupal::token();
+  $language_manager = \Drupal::languageManager();
   $langcode = $message['langcode'];
   $variables = array('user' => $params['account']);
 
   $language = language_load($params['account']->getPreferredLangcode());
-  $language_manager = \Drupal::languageManager();
-  if ($language_manager->isConfigurable()) {
-    $original_language = $language_manager->getConfigOverrideLanguage();
-    $language_manager->setConfigOverrideLanguage($language);
-  }
+  $original_language = $language_manager->getConfigOverrideLanguage();
+  $language_manager->setConfigOverrideLanguage($language);
   $mail_config = \Drupal::config('user.mail');
 
    // We do not sanitize the token replacement, since the output of this
@@ -1397,9 +1395,7 @@
   $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);
 
-  if ($language_manager->isConfigurable()) {
-    $language_manager->setConfigOverrideLanguage($original_language);
-  }
+  $language_manager->setConfigOverrideLanguage($original_language);
 
 }
 
only in patch2:
unchanged:
--- a/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php
+++ b/core/modules/ckeditor/lib/Drupal/ckeditor/Tests/CKEditorTest.php
@@ -336,7 +336,7 @@ function testLanguages() {
    * Tests that CKEditor plugins participate in JS translation.
    */
   function testJSTranslation() {
-    $this->enableModules(array('locale'));
+    $this->enableModules(array('language', 'locale'));
     $this->installSchema('locale', 'locales_source');
     $this->installSchema('locale', 'locales_location');
     $editor = entity_load('editor', 'filtered_html');
only in patch2:
unchanged:
--- a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
@@ -79,9 +79,8 @@ public function testDefaultConfig() {
     $default_config_storage = new TestInstallStorage();
 
     foreach ($default_config_storage->listAll() as $config_name) {
-      // @todo: remove once migration (https://drupal.org/node/2183957) and
-      // translation (https://drupal.org/node/2168609) schemas are in.
-      if (strpos($config_name, 'migrate.migration') === 0 || strpos($config_name, 'language.config') === 0) {
+      // @todo: remove once migration (https://drupal.org/node/2183957).
+      if (strpos($config_name, 'migrate.migration') === 0) {
         continue;
       }
 
only in patch2:
unchanged:
--- a/core/modules/language/language.install
+++ b/core/modules/language/language.install
@@ -6,6 +6,26 @@
  */
 
 /**
+ * Implements hook_install().
+ */
+function language_install() {
+  // Get all the existing modules that are enabled and install any language
+  // configuration.
+  $language_config_override = \Drupal::service('language.config_factory_override');
+  foreach (array_keys(\Drupal::moduleHandler()->getModuleList()) as $module) {
+    $language_config_override->install('module', $module);
+  }
+  /** @var \Drupal\Core\Extension\ThemeHandler $theme_handler */
+  $theme_handler = \Drupal::service('theme_handler');
+  foreach ($theme_handler->listInfo() as $theme) {
+    if ($theme->status) {
+      $language_config_override->install('theme', $theme->name);
+    }
+  }
+  \Drupal::configFactory()->reset();
+}
+
+/**
  * Implements hook_uninstall().
  */
 function language_uninstall() {
only in patch2:
unchanged:
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php
@@ -20,7 +20,7 @@ class MenuRouterRebuildTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('locale', 'menu_test');
+  public static $modules = array('language', 'menu_test');
 
   /**
    * {@inheritdoc}
@@ -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::languageManager()->setConfigOverrideLanguage(language_load('nl'));
     menu_router_rebuild();
 
     // Check that the language context was not used for building the menu item.
