diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php
index 5d3756e..f4e44d1 100644
--- a/core/lib/Drupal/Core/Config/ConfigFactory.php
+++ b/core/lib/Drupal/Core/Config/ConfigFactory.php
@@ -312,4 +312,11 @@ public function addOverride(ConfigFactoryOverrideInterface $config_factory_overr
     $this->configFactoryOverrides[] = $config_factory_override;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getOverrides() {
+    return $this->configFactoryOverrides;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php b/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php
index 55eb6f6..cafd3fd 100644
--- a/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php
+++ b/core/lib/Drupal/Core/Config/ConfigFactoryInterface.php
@@ -134,4 +134,11 @@ public function listAll($prefix = '');
    */
   public function addOverride(ConfigFactoryOverrideInterface $config_factory_override);
 
+  /**
+   * Get all added configuration factory override instances.
+   *
+   * @return ConfigFactoryOverrideInterface[]
+   *   The configuration factory override instances.
+   */
+  public function getOverrides();
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php b/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php
index 06e1f3f..96c8d48 100644
--- a/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php
+++ b/core/lib/Drupal/Core/Config/ConfigFactoryOverrideInterface.php
@@ -32,4 +32,24 @@ public function loadOverrides($names);
    */
   public function getCacheSuffix();
 
+  /**
+   * Reacts to default configuration installation during extension install.
+   *
+   * @param string $type
+   *   The type of extension being installed. Either 'module' or 'theme'.
+   * @param string $name
+   *   The name of the extension.
+   */
+  public function install($type, $name);
+
+  /**
+   * Reacts to configuration removal during extension uninstallation.
+   *
+   * @param string $type
+   *   The type of extension being uninstalled. Either 'module' or 'theme'.
+   * @param string $name
+   *   The name of the extension.
+   */
+  public function uninstall($type, $name);
+
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index a22907b..6a78cf2 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -87,25 +87,18 @@ public function __construct(ConfigFactoryInterface $config_factory, StorageInter
   /**
    * {@inheritdoc}
    */
-  public function installDefaultConfig($type, $name) {
+  public function getConfigToInstall($type, $name, $collection = StorageInterface::DEFAULT_COLLECTION) {
     // Get all default configuration owned by this extension.
-    $source_storage = $this->getSourceStorage();
+    $source_storage = $this->getSourceStorage($collection);
     $config_to_install = $source_storage->listAll($name . '.');
 
     $extension_path = drupal_get_path($type, $name);
-    // If the extension provides configuration schema clear the definitions.
-    if (is_dir($extension_path . '/' . InstallStorage::CONFIG_SCHEMA_DIRECTORY)) {
-      // Refresh the schema cache if installing default configuration and the
-      // extension has a configuration schema directory.
-      $this->typedConfig->clearCachedDefinitions();
-    }
-
     // If not installing the core base system default configuration, work out if
     // this extension provides default configuration for any other enabled
     // extensions.
     if ($type !== 'core' && is_dir($extension_path . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY)) {
       $enabled_extensions = $other_module_config = array();
-      $default_storage = new FileStorage($extension_path . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY);
+      $default_storage = new FileStorage($extension_path . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY, $collection);
       $other_module_config = array_filter($default_storage->listAll(), function ($value) use ($name) {
         return !preg_match('/^' . $name . '\./', $value);
       });
@@ -123,10 +116,26 @@ public function installDefaultConfig($type, $name) {
 
       $config_to_install = array_merge($config_to_install, $other_module_config);
     }
+    return $config_to_install;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function installDefaultConfig($type, $name) {
+    $extension_path = drupal_get_path($type, $name);
+    // If the extension provides configuration schema clear the definitions.
+    if (is_dir($extension_path . '/' . InstallStorage::CONFIG_SCHEMA_DIRECTORY)) {
+      // Refresh the schema cache if installing default configuration and the
+      // extension has a configuration schema directory.
+      $this->typedConfig->clearCachedDefinitions();
+    }
+
+    $config_to_install = $this->getConfigToInstall($type, $name);
 
     if (!empty($config_to_install)) {
       // Order the configuration to install in the order of dependencies.
-      $data = $source_storage->readMultiple($config_to_install);
+      $data = $this->getSourceStorage()->readMultiple($config_to_install);
       $dependency_manager = new ConfigDependencyManager();
       $sorted_config = $dependency_manager
         ->setData($data)
@@ -138,12 +147,12 @@ public function installDefaultConfig($type, $name) {
       // Remove configuration that already exists in the active storage.
       $sorted_config = array_diff($sorted_config, $this->activeStorage->listAll());
 
-      foreach ($sorted_config as $name) {
-        $new_config = new Config($name, $this->activeStorage, $this->eventDispatcher, $this->typedConfig);
-        if ($data[$name] !== FALSE) {
-          $new_config->setData($data[$name]);
+      foreach ($sorted_config as $config_name) {
+        $new_config = new Config($config_name, $this->activeStorage, $this->eventDispatcher, $this->typedConfig);
+        if ($data[$config_name] !== FALSE) {
+          $new_config->setData($data[$config_name]);
         }
-        if ($entity_type = $this->configManager->getEntityTypeIdByName($name)) {
+        if ($entity_type = $this->configManager->getEntityTypeIdByName($config_name)) {
 
           // If we are syncing do not create configuration entities. Pluggable
           // configuration entities can have dependencies on modules that are
@@ -159,8 +168,8 @@ public function installDefaultConfig($type, $name) {
             ->getStorage($entity_type);
           // It is possible that secondary writes can occur during configuration
           // creation. Updates of such configuration are allowed.
-          if ($this->activeStorage->exists($name)) {
-            $id = $entity_storage->getIDFromConfigName($name, $entity_storage->getEntityType()->getConfigPrefix());
+          if ($this->activeStorage->exists($config_name)) {
+            $id = $entity_storage->getIDFromConfigName($config_name, $entity_storage->getEntityType()->getConfigPrefix());
             $entity = $entity_storage->load($id);
             foreach ($new_config->get() as $property => $value) {
               $entity->set($property, $value);
@@ -179,6 +188,12 @@ public function installDefaultConfig($type, $name) {
       }
       $this->configFactory->setOverrideState($old_state);
     }
+
+    // Allow configuration factory overrides to respond to installation.
+    foreach ($this->configFactory->getOverrides() as $config_override) {
+      $config_override->install($type, $name);
+    }
+
     // Reset all the static caches and list caches.
     $this->configFactory->reset();
   }
@@ -200,16 +215,16 @@ public function resetSourceStorage() {
   }
 
   /**
-   * Gets the configuration storage that provides the default configuration.
-   *
-   * @return \Drupal\Core\Config\StorageInterface
-   *   The configuration storage that provides the default configuration.
+   * {@inheritdoc}
    */
-  public function getSourceStorage() {
+  public function getSourceStorage($collection = StorageInterface::DEFAULT_COLLECTION) {
     if (!isset($this->sourceStorage)) {
       // Default to using the ExtensionInstallStorage which searches extension's
       // config directories for default configuration.
-      $this->sourceStorage = new ExtensionInstallStorage($this->activeStorage);
+      $this->sourceStorage = new ExtensionInstallStorage($this->activeStorage, ExtensionInstallStorage::CONFIG_INSTALL_DIRECTORY, $collection);
+    }
+    if ($this->sourceStorage->getCollectionName() != $collection) {
+      $this->sourceStorage = $this->sourceStorage->createCollection($collection);
     }
     return $this->sourceStorage;
   }
diff --git a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
index efa3d54..93d331f 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
@@ -13,6 +13,28 @@
 interface ConfigInstallerInterface {
 
   /**
+   * Gets a list of configuration object names to install.
+   *
+   * It searches all the default configuration directories for all installed
+   * extensions to locate any configuration with its name prefix. Additionally,
+   * the default configuration directory for the extension being installed is
+   * searched to discover if it contains default configuration that is owned by
+   * other enabled extensions.
+   *
+   * @param string $type
+   *   The extension type; e.g., 'module' or 'theme'.
+   * @param string $name
+   *   The name of the module or theme to install default configuration for.
+   * @param string $collection
+   *   (optional) The configuration collection. Defaults to the default
+   *   collection.
+   *
+   * @return array
+   *   The list of configuration object names to install.
+   */
+  public function getConfigToInstall($type, $name, $collection = StorageInterface::DEFAULT_COLLECTION);
+
+  /**
    * Installs the default configuration of a given extension.
    *
    * When an extension is installed, it searches all the default configuration
@@ -48,6 +70,17 @@ public function installDefaultConfig($type, $name);
   public function setSourceStorage(StorageInterface $storage);
 
   /**
+   * Gets the configuration storage that provides the default configuration.
+   *
+   * @param string $collection
+   *   The configuration collection.
+   *
+   * @return \Drupal\Core\Config\StorageInterface
+   *   The configuration storage that provides the default configuration.
+   */
+  public function getSourceStorage($collection = StorageInterface::DEFAULT_COLLECTION);
+
+  /**
    * Resets the configuration storage that provides the default configuration.
    *
    * @return self
diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php
index 139aaf0..e6e9d85 100644
--- a/core/lib/Drupal/Core/Config/ConfigManager.php
+++ b/core/lib/Drupal/Core/Config/ConfigManager.php
@@ -160,6 +160,11 @@ public function uninstall($type, $name) {
     foreach ($config_names as $config_name) {
       $this->configFactory->get($config_name)->delete();
     }
+    // Allow configuration factory overrides to respond to uninstallation.
+    foreach ($this->configFactory->getOverrides() as $config_override) {
+      $config_override->uninstall($type, $name);
+    }
+
     $schema_dir = drupal_get_path($type, $name) . '/' . InstallStorage::CONFIG_SCHEMA_DIRECTORY;
     if (is_dir($schema_dir)) {
       // Refresh the schema cache if uninstalling an extension that provides
diff --git a/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
index 813efeb..5d771c7 100644
--- a/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
+++ b/core/lib/Drupal/Core/Config/ExtensionInstallStorage.php
@@ -32,9 +32,10 @@ class ExtensionInstallStorage extends InstallStorage {
    *   The directory to scan in each extension to scan for files. Defaults to
    *   'config'.
    */
-  public function __construct(StorageInterface $config_storage, $directory = self::CONFIG_INSTALL_DIRECTORY) {
+  public function __construct(StorageInterface $config_storage, $directory = self::CONFIG_INSTALL_DIRECTORY, $collection = self::DEFAULT_COLLECTION) {
     $this->configStorage = $config_storage;
     $this->directory = $directory;
+    $this->collection = $collection;
   }
 
   /**
@@ -73,5 +74,17 @@ protected function getAllFolders() {
     }
     return $this->folders;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function createCollection($collection) {
+    return new static(
+      $this->configStorage,
+      $this->directory,
+      $collection
+    );
+  }
+
 }
 
diff --git a/core/lib/Drupal/Core/Config/InstallStorage.php b/core/lib/Drupal/Core/Config/InstallStorage.php
index 2db0944..028fa9c 100644
--- a/core/lib/Drupal/Core/Config/InstallStorage.php
+++ b/core/lib/Drupal/Core/Config/InstallStorage.php
@@ -53,8 +53,9 @@ class InstallStorage extends FileStorage {
    *   The directory to scan in each extension to scan for files. Defaults to
    *   'config'.
    */
-  public function __construct($directory = self::CONFIG_INSTALL_DIRECTORY) {
+  public function __construct($directory = self::CONFIG_INSTALL_DIRECTORY, $collection = self::DEFAULT_COLLECTION) {
     $this->directory = $directory;
+    $this->collection = $collection;
   }
 
   /**
@@ -198,7 +199,7 @@ public function getComponentNames($type, array $list) {
    *   The configuration folder name for this component.
    */
   protected function getComponentFolder($type, $name) {
-    return drupal_get_path($type, $name) . '/' . $this->directory;
+    return drupal_get_path($type, $name) . '/' . $this->getCollectionDirectory();
   }
 
   /**
diff --git a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php b/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
index df1b335..e90a058 100644
--- a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
@@ -51,9 +51,9 @@ 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) schemas
+      // are in.
+      if (strpos($config_name, 'migrate.migration') === 0) {
         continue;
       }
 
diff --git a/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverrider.php b/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverrider.php
index 106df3d..355869f 100644
--- a/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverrider.php
+++ b/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverrider.php
@@ -40,5 +40,17 @@ public function getCacheSuffix() {
     return 'ConfigOverrider';
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function install($type, $name) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function uninstall($type, $name) {
+  }
+
 }
 
diff --git a/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverriderLowPriority.php b/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverriderLowPriority.php
index a9a435e..19ea21e 100644
--- a/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverriderLowPriority.php
+++ b/core/modules/config/tests/config_override/lib/Drupal/config_override/ConfigOverriderLowPriority.php
@@ -41,5 +41,17 @@ public function getCacheSuffix() {
     return 'ConfigOverriderLowPriority';
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function install($type, $name) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function uninstall($type, $name) {
+  }
+
 }
 
diff --git a/core/modules/config/tests/config_test/config/install/language.config.de.config_test.system.yml b/core/modules/config/tests/config_test/config/install/language/de/config_test.system.yml
similarity index 100%
rename from core/modules/config/tests/config_test/config/install/language.config.de.config_test.system.yml
rename to core/modules/config/tests/config_test/config/install/language/de/config_test.system.yml
diff --git a/core/modules/config/tests/config_test/config/install/language.config.en.config_test.system.yml b/core/modules/config/tests/config_test/config/install/language/en/config_test.system.yml
similarity index 100%
rename from core/modules/config/tests/config_test/config/install/language.config.en.config_test.system.yml
rename to core/modules/config/tests/config_test/config/install/language/en/config_test.system.yml
diff --git a/core/modules/config/tests/config_test/config/install/language.config.fr.config_test.system.yml b/core/modules/config/tests/config_test/config/install/language/fr/config_test.system.yml
similarity index 100%
rename from core/modules/config/tests/config_test/config/install/language.config.fr.config_test.system.yml
rename to core/modules/config/tests/config_test/config/install/language/fr/config_test.system.yml
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 fb3ba88..13311d9 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
@@ -15,6 +15,7 @@
 use Drupal\Core\Form\BaseFormIdInterface;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Language\Language;
+use Drupal\language\Config\LanguageConfigOverride;
 use Drupal\language\ConfigurableLanguageManagerInterface;
 use Drupal\locale\StringStorageInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -352,7 +353,7 @@ protected function buildConfigForm(Element $schema, $config_data, $base_config_d
    *   Set the configuration in this language.
    * @param \Drupal\Core\Config\Config $base_config
    *   Base configuration values, in the source language.
-   * @param \Drupal\Core\Config\Config $config_translation
+   * @param \Drupal\language\Config\LanguageConfigOverride $config_translation
    *   Translation configuration override data.
    * @param array $config_values
    *   A simple one dimensional or recursive array:
@@ -372,7 +373,7 @@ protected function buildConfigForm(Element $schema, $config_data, $base_config_d
    * @return array
    *   Translation configuration override data.
    */
-  protected function setConfig(Language $language, Config $base_config, Config $config_translation, array $config_values, $shipped_config = FALSE) {
+  protected function setConfig(Language $language, Config $base_config, LanguageConfigOverride $config_translation, array $config_values, $shipped_config = FALSE) {
     foreach ($config_values as $key => $value) {
       if (is_array($value) && !isset($value['translation'])) {
         // Traverse into this level in the configuration.
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index f35da4d..6a71fc7 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -441,6 +441,8 @@ function language_save($language) {
   $language_entity->save();
   $t_args = array('%language' => $language->name, '%langcode' => $language->id);
   if ($language->is_new) {
+    // Install any available language configuration overrides for the language.
+    \Drupal::service('language.config_factory_override')->installLanguageOverrides($language->getId());
     watchdog('language', 'The %language (%langcode) language has been created.', $t_args);
   }
   else {
diff --git a/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverride.php b/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverride.php
index bfadec0..76a384a 100644
--- a/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverride.php
+++ b/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverride.php
@@ -7,7 +7,8 @@
 
 namespace Drupal\language\Config;
 
-use Drupal\Core\Config\Config;
+use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Config\ExtensionInstallStorage;
 use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\Config\TypedConfigManagerInterface;
 use Drupal\Core\Language\Language;
@@ -22,9 +23,19 @@ class LanguageConfigFactoryOverride implements LanguageConfigFactoryOverrideInte
   /**
    * The configuration storage.
    *
+   * Do not access this directly. Should be accessed through self::getStorage()
+   * so that the cache of storages per langcode is used.
+   *
    * @var \Drupal\Core\Config\StorageInterface
    */
-  protected $storage;
+  protected $baseStorage;
+
+  /**
+   * An array of configuration storages keyed by langcode.
+   *
+   * @var \Drupal\Core\Config\StorageInterface[]
+   */
+  protected $storages;
 
   /**
    * The typed config manager.
@@ -58,7 +69,7 @@ class LanguageConfigFactoryOverride implements LanguageConfigFactoryOverrideInte
    *   The typed configuration manager.
    */
   public function __construct(StorageInterface $storage, EventDispatcherInterface $event_dispatcher, TypedConfigManagerInterface $typed_config) {
-    $this->storage = $storage;
+    $this->baseStorage = $storage;
     $this->eventDispatcher = $event_dispatcher;
     $this->typedConfigManager = $typed_config;
   }
@@ -67,72 +78,34 @@ public function __construct(StorageInterface $storage, EventDispatcherInterface
    * {@inheritdoc}
    */
   public function loadOverrides($names) {
-    $data = array();
-    $language_names = $this->getLanguageConfigNames($names);
-    if ($language_names) {
-      $data = $this->storage->readMultiple(array_values($language_names));
-      // Re-key the data array to use configuration names rather than override
-      // names.
-      $prefix_length = strlen(static::LANGUAGE_CONFIG_PREFIX . '.' . $this->language->id) + 1;
-      foreach ($data as $key => $value) {
-        unset($data[$key]);
-        $key = substr($key, $prefix_length);
-        $data[$key] = $value;
-      }
+    if ($this->language) {
+      $storage = $this->getStorage($this->language->getId());
+      return $storage->readMultiple($names);
     }
-    return $data;
+    return array();
   }
 
   /**
    * {@inheritdoc}
    */
   public function getOverride($langcode, $name) {
-    $override_name = $this->getLanguageConfigName($langcode, $name);
-    $overrides = $this->storage->read($override_name);
-    $config = new Config($override_name, $this->storage, $this->eventDispatcher, $this->typedConfigManager);
-    if (!empty($overrides)) {
-      $config->initWithData($overrides);
+    $storage = $this->getStorage($langcode);
+    $data = $storage->read($name);
+    $override = new LanguageConfigOverride($name, $storage, $this->typedConfigManager);
+    if (!empty($data)) {
+      $override->initWithData($data);
     }
-    return $config;
+    return $override;
   }
 
   /**
-   * Generate a list of configuration names based on base names.
-   *
-   * @param array $names
-   *   List of configuration names.
-   *
-   * @return array
-   *   List of configuration names for language override files if applicable.
-   */
-  protected function getLanguageConfigNames(array $names) {
-    $language_names = array();
-    if (isset($this->language)) {
-      foreach ($names as $name) {
-        if ($language_name = $this->getLanguageConfigName($this->language->id, $name)) {
-          $language_names[$name] = $language_name;
-        }
-      }
-    }
-    return $language_names;
-  }
-
-  /**
-   * Get language override name for given language and configuration name.
-   *
-   * @param string $langcode
-   *   Language code.
-   * @param string $name
-   *   Configuration name.
-   *
-   * @return bool|string
-   *   Configuration name or FALSE if not applicable.
+   * {@inheritdoc}
    */
-  protected function getLanguageConfigName($langcode, $name) {
-     if (strpos($name, static::LANGUAGE_CONFIG_PREFIX) === 0) {
-      return FALSE;
+  public function getStorage($langcode) {
+    if (!isset($this->storages[$langcode])) {
+      $this->storages[$langcode] = $this->baseStorage->createCollection($this->createConfigCollectionName($langcode));
     }
-    return static::LANGUAGE_CONFIG_PREFIX . '.' . $langcode . '.' . $name;
+    return $this->storages[$langcode];
   }
 
   /**
@@ -165,4 +138,72 @@ public function setLanguageFromDefault(LanguageDefault $language_default = NULL)
     return $this;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function install($type, $name) {
+    $config_installer = \Drupal::service('config.installer');
+    // Work out if this extension provides default language overrides.
+    foreach (\Drupal::languageManager()->getLanguages() as $language) {
+      $collection = $this->createConfigCollectionName($language->getId());
+      $config_to_install = $config_installer->getConfigToInstall($type, $name, $collection);
+      $storage = $this->getStorage($language->getId());
+      // Remove configuration that already exists in the active storage.
+      $config_to_install = array_diff($config_to_install, $storage->listAll());
+      $data = $config_installer->getSourceStorage($collection)->readMultiple($config_to_install);
+      foreach ($data as $config_name => $config_data) {
+        $config = new LanguageConfigOverride($config_name, $storage, $this->typedConfigManager);
+        $config->setData($config_data)->save();
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function installLanguageOverrides($langcode) {
+    $enabled_extensions = array();
+    $extension_config = $this->baseStorage->read('core.extension');
+    $enabled_extensions += array_keys($extension_config['module']);
+    $enabled_extensions += array_keys($extension_config['theme']);
+
+    $install_storage = new ExtensionInstallStorage($this->baseStorage, ExtensionInstallStorage::CONFIG_INSTALL_DIRECTORY, $this->createConfigCollectionName($langcode));
+    $storage = $this->getStorage($langcode);
+
+    $config_to_install = $install_storage->listAll();
+    // Only install language overrides for enable modules.
+    $config_to_install = array_filter($config_to_install, function ($config_name) use ($enabled_extensions) {
+      $provider = Unicode::substr($config_name, 0, strpos($config_name, '.'));
+      return in_array($provider, $enabled_extensions);
+    });
+    foreach ($config_to_install as $config_name) {
+      $data = $install_storage->read($config_name);
+      $config = new LanguageConfigOverride($config_name, $storage, $this->typedConfigManager);
+      $config->setData($data)->save();
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function uninstall($type, $name) {
+    foreach (\Drupal::languageManager()->getLanguages() as $language) {
+      $storage = $this->getStorage($language->getId());
+      $storage->deleteAll($name . '.');
+    }
+  }
+
+  /**
+   * Creates a configuration collection name based on a langcode.
+   *
+   * @param $langcode
+   *   The langcode.
+   *
+   * @return string
+   *   The configuration collection name for a langcode.
+   */
+  protected function createConfigCollectionName($langcode) {
+    return 'language.' . $langcode;
+  }
+
 }
diff --git a/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverrideInterface.php b/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverrideInterface.php
index 1c3de55..1d3a43b 100644
--- a/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverrideInterface.php
+++ b/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverrideInterface.php
@@ -17,11 +17,6 @@
 interface LanguageConfigFactoryOverrideInterface extends ConfigFactoryOverrideInterface {
 
   /**
-   * Prefix for all language configuration files.
-   */
-  const LANGUAGE_CONFIG_PREFIX = 'language.config';
-
-  /**
    * Gets the language object used to override configuration data.
    *
    * @return \Drupal\Core\Language\Language
@@ -62,4 +57,23 @@ public function setLanguageFromDefault(LanguageDefault $language_default = NULL)
    */
   public function getOverride($langcode, $name);
 
+  /**
+   * Returns the storage instance for a particular langcode.
+   *
+   * @param string $langcode
+   *   Language code.
+   *
+   * @return \Drupal\language\Config\LanguageOverrideStorageInterface
+   *   The language override storage object.
+   */
+  public function getStorage($langcode);
+
+  /**
+   * Installs available language configuration overrides for a given langcode.
+   *
+   * @param string $langcode
+   *   Language code.
+   */
+  public function installLanguageOverrides($langcode);
+
 }
diff --git a/core/modules/language/lib/Drupal/language/Config/LanguageConfigOverride.php b/core/modules/language/lib/Drupal/language/Config/LanguageConfigOverride.php
new file mode 100644
index 0000000..6ed2b11
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/Config/LanguageConfigOverride.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\Config\LanguageConfigOverride.
+ */
+
+namespace Drupal\language\Config;
+
+use Drupal\Core\Config\StorableConfigBase;
+use Drupal\Core\Config\StorageInterface;
+use Drupal\Core\Config\TypedConfigManagerInterface;
+
+/**
+ * Defines language configuration overrides.
+ */
+class LanguageConfigOverride extends StorableConfigBase {
+
+  /**
+   * Constructs a language override object.
+   *
+   * @param string $name
+   *   The name of the configuration object being overridden.
+   * @param \Drupal\Core\Config\StorageInterface $storage
+   *   A storage controller object to use for reading and writing the
+   *   configuration override.
+   * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
+   *   The typed configuration manager service.
+   */
+  public function __construct($name, StorageInterface $storage, TypedConfigManagerInterface $typed_config) {
+    $this->name = $name;
+    $this->storage = $storage;
+    $this->typedConfigManager = $typed_config;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save() {
+    // Validate the configuration object name before saving.
+    static::validateName($this->name);
+
+    // If there is a schema for this configuration object, cast all values to
+    // conform to the schema.
+    if ($this->typedConfigManager->hasConfigSchema($this->name)) {
+      // Ensure that the schema wrapper has the latest data.
+      $this->schemaWrapper = NULL;
+      foreach ($this->data as $key => $value) {
+        $this->data[$key] = $this->castValue($key, $value);
+      }
+    }
+
+    $this->storage->write($this->name, $this->data);
+    $this->isNew = FALSE;
+    $this->originalData = $this->data;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function delete() {
+    // @todo Consider to remove the pruning of data for Config::delete().
+    $this->data = array();
+    $this->storage->delete($this->name);
+    $this->isNew = TRUE;
+    $this->originalData = $this->data;
+    return $this;
+  }
+
+}
diff --git a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
index 101449c..b28e02b 100644
--- a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
+++ b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
@@ -410,6 +410,13 @@ public function getLanguageConfigOverride($langcode, $name) {
   /**
    * {@inheritdoc}
    */
+  public function getLanguageConfigOverrideStorage($langcode) {
+    return $this->configFactoryOverride->getStorage($langcode);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getStandardLanguageListWithoutConfigured() {
     $languages = $this->getLanguages();
     $predefined = $this->getStandardLanguageList();
diff --git a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
index 9bbf2ce..0007524 100644
--- a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
+++ b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
@@ -91,12 +91,24 @@ public function updateLockedLanguageWeights();
    * @param string $name
    *   The language configuration object name.
    *
-   * @return \Drupal\Core\Config\Config
+   * @return \Drupal\language\Config\LanguageConfigOverride
    *   The language config override object.
    */
   public function getLanguageConfigOverride($langcode, $name);
 
   /**
+   * Gets a language config override storage object.
+   *
+   * @param string $langcode
+   *   The language code for the override.
+   *
+   * @param \Drupal\Core\Config\StorageInterface $storage
+   *   A storage object to use for reading and writing the
+   *   configuration override.
+   */
+  public function getLanguageConfigOverrideStorage($langcode);
+
+  /**
    * Returns the standard language list excluding already configured languages.
    *
    * @return array
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageConfigOverrideImportTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageConfigOverrideImportTest.php
new file mode 100644
index 0000000..9df51e3
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageConfigOverrideImportTest.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\Tests\LanguageConfigOverrideImportTest.
+ */
+
+namespace Drupal\language\Tests;
+
+use Drupal\Core\Config\FileStorage;
+use Drupal\Core\Language\Language;
+use Drupal\simpletest\WebTestBase;
+
+class LanguageConfigOverrideImportTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('language', 'config', 'locale', 'config_translation');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Language config override synchronize',
+      'description' => 'Ensures the language config overrides can be synchronized.',
+      'group' => 'Language',
+    );
+  }
+
+  /**
+   *
+   */
+  public function testConfigOverrideImport() {
+    language_save(new Language(array(
+      'name' => 'French',
+      'id' => 'fr',
+    )));
+    /* @var \Drupal\Core\Config\StorageInterface $staging */
+    $staging = \Drupal::service('config.storage.staging');
+    $this->copyConfig(\Drupal::service('config.storage'), $staging);
+
+    \Drupal::moduleHandler()->uninstall(array('language'));
+    // Ensure that the current site has no overrides registered to the
+    // ConfigFactory.
+    $this->rebuildContainer();
+
+    /* @var \Drupal\Core\Config\StorageInterface $override_staging */
+    $override_staging = new FileStorage(config_get_config_directory(CONFIG_STAGING_DIRECTORY) . '/language/fr');
+    // Create some overrides in staging.
+    $override_staging->write('system.site', array('name' => 'FR default site name'));
+    $override_staging->write('system.maintenance', array('message' => 'FR message: @site is currently under maintenance. We should be back shortly. Thank you for your patience'));
+
+    $this->configImporter()->import();
+    $this->rebuildContainer();
+    \Drupal::service('router.builder')->rebuild();
+
+    $override = \Drupal::languageManager()->getLanguageConfigOverride('fr', 'system.site');
+    $this->assertEqual('FR default site name', $override->get('name'));
+    $this->drupalGet('fr');
+    $this->assertText('FR default site name');
+
+    $this->drupalLogin($this->root_user);
+    $this->drupalGet('admin/config/development/maintenance/translate/fr/edit');
+    $this->assertText('FR message: @site is currently under maintenance. We should be back shortly. Thank you for your patience');
+  }
+}
diff --git a/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php b/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php
index 3c0dc57..f731b13 100644
--- a/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php
+++ b/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php
@@ -230,9 +230,9 @@ public function getStringNames(array $lids) {
    *   Language code to delete.
    */
   public function deleteLanguageTranslations($langcode) {
-    $locale_name = LanguageConfigFactoryOverrideInterface::LANGUAGE_CONFIG_PREFIX . '.' . $langcode . '.';
-    foreach ($this->configStorage->listAll($locale_name) as $name) {
-      $this->configStorage->delete($name);
+    $storage = $this->languageManager->getLanguageConfigOverrideStorage($langcode);
+    foreach ($storage->listAll() as $name) {
+      $this->languageManager->getLanguageConfigOverride($langcode, $name)->delete();
     }
   }
 
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigManagerTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigManagerTest.php
index bdde87f..50cbc7d 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigManagerTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigManagerTest.php
@@ -42,7 +42,7 @@ public function testHasTranslation() {
     $this->installConfig(array('locale_test'));
     $locale_config_manager = \Drupal::service('locale.config.typed');
 
-    $language = new Language(array('id' => 'de'));
+    $language = language_save(new Language(array('id' => 'de')));
     $result = $locale_config_manager->hasTranslation('locale_test.no_translation', $language);
     $this->assertFalse($result, 'There is no translation for locale_test.no_translation configuration.');
 
diff --git a/core/modules/locale/tests/modules/locale_test/config/install/language.config.de.locale_test.translation.yml b/core/modules/locale/tests/modules/locale_test/config/install/language/de/locale_test.translation.yml
similarity index 100%
rename from core/modules/locale/tests/modules/locale_test/config/install/language.config.de.locale_test.translation.yml
rename to core/modules/locale/tests/modules/locale_test/config/install/language/de/locale_test.translation.yml
diff --git a/core/modules/system/tests/modules/menu_test/config/install/language.config.nl.menu_test.menu_item.yml b/core/modules/system/tests/modules/menu_test/config/install/language/nl/menu_test.menu_item.yml
similarity index 100%
rename from core/modules/system/tests/modules/menu_test/config/install/language.config.nl.menu_test.menu_item.yml
rename to core/modules/system/tests/modules/menu_test/config/install/language/nl/menu_test.menu_item.yml
diff --git a/core/modules/tour/tests/tour_test/config/install/language.config.it.tour.tour.tour-test.yml b/core/modules/tour/tests/tour_test/config/install/language/it/tour.tour.tour-test.yml
similarity index 100%
rename from core/modules/tour/tests/tour_test/config/install/language.config.it.tour.tour.tour-test.yml
rename to core/modules/tour/tests/tour_test/config/install/language/it/tour.tour.tour-test.yml
