diff --git a/core/lib/Drupal/Core/Config/ConfigFactory.php b/core/lib/Drupal/Core/Config/ConfigFactory.php
index 0e7826e..dcfa4f4 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 639b483..04bfe81 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 038dbd6..4a84033 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -155,6 +155,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();
   }
diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php
index d1048ea..535b14c 100644
--- a/core/lib/Drupal/Core/Config/ConfigManager.php
+++ b/core/lib/Drupal/Core/Config/ConfigManager.php
@@ -149,6 +149,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) . '/config/schema';
     if (is_dir($schema_dir)) {
       // Refresh the schema cache if uninstalling an extension that provides
diff --git a/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php
index 14268e9..3f47027 100644
--- a/core/lib/Drupal/Core/Config/FileStorage.php
+++ b/core/lib/Drupal/Core/Config/FileStorage.php
@@ -241,4 +241,14 @@ public function deleteAll($prefix = '') {
 
     return $success;
   }
+
+  /**
+   * Sets the filesystem path for configuration objects.
+   *
+   * @param string $directory
+   *   The filesystem path for configuration objects.
+   */
+  public function setDirectory($directory) {
+    $this->directory = $directory;
+  }
 }
diff --git a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php b/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
index b7424f3..4f3174d 100644
--- a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
@@ -79,9 +79,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/language.config.de.config_test.system.yml b/core/modules/config/tests/config_test/config/language/de/config_test.system.yml
similarity index 100%
rename from core/modules/config/tests/config_test/config/language.config.de.config_test.system.yml
rename to core/modules/config/tests/config_test/config/language/de/config_test.system.yml
diff --git a/core/modules/config/tests/config_test/config/language.config.en.config_test.system.yml b/core/modules/config/tests/config_test/config/language/en/config_test.system.yml
similarity index 100%
rename from core/modules/config/tests/config_test/config/language.config.en.config_test.system.yml
rename to core/modules/config/tests/config_test/config/language/en/config_test.system.yml
diff --git a/core/modules/config/tests/config_test/config/language.config.fr.config_test.system.yml b/core/modules/config/tests/config_test/config/language/fr/config_test.system.yml
similarity index 100%
rename from core/modules/config/tests/config_test/config/language.config.fr.config_test.system.yml
rename to core/modules/config/tests/config_test/config/language/fr/config_test.system.yml
diff --git a/core/modules/language/language.install b/core/modules/language/language.install
new file mode 100644
index 0000000..8825db3
--- /dev/null
+++ b/core/modules/language/language.install
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the language module.
+ */
+
+/**
+ * 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();
+}
diff --git a/core/modules/language/language.services.yml b/core/modules/language/language.services.yml
index acfb3fa..83a31ff 100644
--- a/core/modules/language/language.services.yml
+++ b/core/modules/language/language.services.yml
@@ -11,8 +11,21 @@ services:
     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\LanguageOverrideStorage
+    arguments: ['@language.cache_config']
+    tags:
+      - { name: persist }
   language.config_factory_override:
     class: Drupal\language\Config\LanguageConfigFactoryOverride
-    arguments: ['@config.storage', '@event_dispatcher', '@config.typed']
+    arguments: ['@language.config_storage', '@event_dispatcher', '@config.typed']
     tags:
       - { name: config.factory.override, priority: -254 }
diff --git a/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverride.php b/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverride.php
index bfadec0..4c678ff 100644
--- a/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverride.php
+++ b/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverride.php
@@ -8,6 +8,7 @@
 namespace Drupal\language\Config;
 
 use Drupal\Core\Config\Config;
+use Drupal\Core\Config\FileStorage;
 use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\Config\TypedConfigManagerInterface;
 use Drupal\Core\Language\Language;
@@ -22,7 +23,7 @@ class LanguageConfigFactoryOverride implements LanguageConfigFactoryOverrideInte
   /**
    * The configuration storage.
    *
-   * @var \Drupal\Core\Config\StorageInterface
+   * @var \Drupal\language\Config\LanguageOverrideStorageInterface
    */
   protected $storage;
 
@@ -50,14 +51,14 @@ class LanguageConfigFactoryOverride implements LanguageConfigFactoryOverrideInte
   /**
    * Constructs the LanguageConfigFactoryOverride object.
    *
-   * @param \Drupal\Core\Config\StorageInterface $storage
+   * @param \Drupal\language\Config\LanguageOverrideStorageInterface $storage
    *   The configuration storage engine.
    * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
    *   An event dispatcher instance to use for configuration events.
    * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config
    *   The typed configuration manager.
    */
-  public function __construct(StorageInterface $storage, EventDispatcherInterface $event_dispatcher, TypedConfigManagerInterface $typed_config) {
+  public function __construct(LanguageOverrideStorageInterface $storage, EventDispatcherInterface $event_dispatcher, TypedConfigManagerInterface $typed_config) {
     $this->storage = $storage;
     $this->eventDispatcher = $event_dispatcher;
     $this->typedConfigManager = $typed_config;
@@ -67,72 +68,29 @@ 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) {
+      return $this->storage->readMultiple($names);
     }
-    return $data;
   }
 
   /**
    * {@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 = clone $this->storage;
+    $data = $storage->setLangcode($langcode)->read($name);
+    $override = new LanguageConfigOverride($name, $this->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.
+   * {@inheritdoc}
    */
-  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.
-   */
-  protected function getLanguageConfigName($langcode, $name) {
-     if (strpos($name, static::LANGUAGE_CONFIG_PREFIX) === 0) {
-      return FALSE;
-    }
-    return static::LANGUAGE_CONFIG_PREFIX . '.' . $langcode . '.' . $name;
+  public function getStorage() {
+    return $this->storage;
   }
 
   /**
@@ -154,6 +112,7 @@ public function getLanguage() {
    */
   public function setLanguage(Language $language = NULL) {
     $this->language = $language;
+    $this->storage->setLangcode($this->language->id);
     return $this;
   }
 
@@ -162,7 +121,58 @@ public function setLanguage(Language $language = NULL) {
    */
   public function setLanguageFromDefault(LanguageDefault $language_default = NULL) {
     $this->language = $language_default ? $language_default->get() : NULL;
+    $this->storage->setLangcode($this->language->id);
     return $this;
   }
 
+  /**
+   * {@inheritdoc}
+   *
+   * @todo maybe this should be done somewhere else?
+   */
+  public function install($type, $name) {
+    // Work out if this extension provides default language overrides.
+    $config_dir = drupal_get_path($type, $name) . '/config/language';
+    if (is_dir($config_dir)) {
+      // List all the directories.
+      // \DirectoryIterator on Windows requires an absolute path.
+      $it  = new \DirectoryIterator(realpath($config_dir));
+      foreach ($it as $dir) {
+        if (!$dir->isDot() && $dir->isDir() ) {
+          $default_language_config = new FileStorage($dir->getPathname());
+          $this->storage->setLangcode($dir->getFilename());
+          foreach ($default_language_config->listAll() as $config_name) {
+            $data = $default_language_config->read($config_name);
+            $config = new LanguageConfigOverride($config_name, $this->storage, $this->typedConfigManager);
+            $config->setData($data)->save();
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @todo maybe this should be done somewhere else?
+   */
+  public function uninstall($type, $name) {
+    // Can not use ConfigurableLanguageManager::getLanguages() since that would
+    // create a circular dependency.
+    $language_directory = config_get_config_directory() .'/language';
+    if (is_dir(($language_directory))) {
+      $it  = new \DirectoryIterator(realpath($language_directory));
+      foreach ($it as $dir) {
+        if (!$dir->isDot() && $dir->isDir() ) {
+          $this->storage->setLangcode($dir->getFilename());
+          $config_names = $this->storage->listAll($name . '.');
+          foreach ($config_names as $config_name) {
+            $config = new LanguageConfigOverride($config_name, $this->storage, $this->typedConfig);
+            $config->delete();
+          }
+        }
+      }
+    }
+  }
+
 }
diff --git a/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverrideInterface.php b/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverrideInterface.php
index 1c3de55..43fcd41 100644
--- a/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverrideInterface.php
+++ b/core/modules/language/lib/Drupal/language/Config/LanguageConfigFactoryOverrideInterface.php
@@ -62,4 +62,9 @@ public function setLanguageFromDefault(LanguageDefault $language_default = NULL)
    */
   public function getOverride($langcode, $name);
 
+  /**
+   * Returns the storage instance.
+   */
+  public function getStorage();
+
 }
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/Config/LanguageOverrideStorage.php b/core/modules/language/lib/Drupal/language/Config/LanguageOverrideStorage.php
new file mode 100644
index 0000000..e9a10cb
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/Config/LanguageOverrideStorage.php
@@ -0,0 +1,159 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\Config\LanguageOverrideStorage.
+ */
+
+namespace Drupal\language\Config;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Config\CachedStorage;
+use Drupal\Core\Config\FileStorage;
+
+/**
+ * Defines storage for language configuration overrides.
+ */
+class LanguageOverrideStorage extends CachedStorage implements LanguageOverrideStorageInterface {
+
+  /**
+   * Language code that determines the configuration override storage directory.
+   *
+   * @var string
+   */
+  protected $langcode;
+
+  /**
+   * Tracks whether the directory exists to prevent excessive file system reads.
+   *
+   * @var bool
+   */
+  protected $directoryExists;
+
+  /**
+   * Constructs a new LanguageOverrideStorage.
+   *
+   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
+   *   A cache backend instance to use for caching.
+   */
+  public function __construct(CacheBackendInterface $cache) {
+    $this->cache = $cache;
+  }
+
+  /**
+   * Gets the override configuration directory for a language code.
+   *
+   * @param string $langcode
+   *   The language code to get the directory for.
+   *
+   * @return string
+   *   The directory where the language override configuration is stored.
+   */
+  protected function getDirectory($langcode) {
+    return config_get_config_directory(CONFIG_ACTIVE_DIRECTORY) . '/language/' . $langcode;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function write($name, array $data) {
+    $this->ensureDirectory();
+    return parent::write($name, $data);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function delete($name) {
+    if ($this->hasDirectory()) {
+      return parent::delete($name);
+    }
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function listAll($prefix = '') {
+    if ($this->hasDirectory()) {
+      return parent::listAll($prefix);
+    }
+    return array();
+  }
+
+  /**
+   * Creates a directory if necessary.
+   */
+  protected function ensureDirectory() {
+    if (!$this->hasDirectory()) {
+      drupal_mkdir($this->directory, NULL, TRUE);
+      $this->directoryExists = TRUE;
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setLangcode($langcode) {
+    // Reset directory check.
+    $this->directoryExists = NULL;
+    $this->langcode = $langcode;
+    $this->directory = $this->getDirectory($langcode);
+    if (empty($this->storage)) {
+      $this->storage = new FileStorage($this->directory);
+    }
+    else {
+      $this->storage->setDirectory($this->directory);
+    }
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getCacheKey($name) {
+    return $this->langcode . ':' . $name;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getCacheKeys(array $names) {
+    foreach ($names as $name) {
+      $names[$name] = $this->getCacheKey($name);
+    }
+    return $names;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getNameFromCacheKey($key) {
+    // Remove everything before the semicolon.
+    return substr($key, strpos($key, ':') + 1);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getNamesFromCacheKeys($keys) {
+    foreach ($keys as $key) {
+      $keys[$key] = $this->getNameFromCacheKey($key);
+    }
+    return $keys;
+  }
+
+  /**
+   * Discovers is the directory for the language exists.
+   *
+   * @return bool
+   *   TRUE if the directory exists, FALSE if not.
+   */
+  protected function hasDirectory() {
+    if (!isset($this->directoryExists)) {
+      $this->directoryExists = is_dir($this->directory);
+    }
+    return $this->directoryExists;
+  }
+
+}
diff --git a/core/modules/language/lib/Drupal/language/Config/LanguageOverrideStorageInterface.php b/core/modules/language/lib/Drupal/language/Config/LanguageOverrideStorageInterface.php
new file mode 100644
index 0000000..5e31cc8
--- /dev/null
+++ b/core/modules/language/lib/Drupal/language/Config/LanguageOverrideStorageInterface.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\Config\LanguageOverrideStorageInterface.
+ */
+
+namespace Drupal\language\Config;
+
+use Drupal\Core\Config\StorageCacheInterface;
+use Drupal\Core\Config\StorageInterface;
+
+interface LanguageOverrideStorageInterface extends StorageInterface, StorageCacheInterface {
+
+  /**
+   * Sets the langcode to determine the override configuration directory to use.
+   *
+   * @param string $langcode
+   *   The language langcode to get the directory for.
+   *
+   * @return $this
+   *   The language configuration storage.
+   */
+  public function setLangcode($langcode);
+
+}
diff --git a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
index 5cd3d8e..9aaa13f 100644
--- a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
+++ b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManager.php
@@ -408,4 +408,13 @@ public function getLanguageConfigOverride($langcode, $name) {
     return $this->configFactoryOverride->getOverride($langcode, $name);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getLanguageOverrideStorage($langcode) {
+    // Clone the language override storage so a process could compare language
+    // overrides if it wanted to.
+    $storage = clone $this->configFactoryOverride->getStorage();
+    return $storage->setLancgode($langcode);
+  }
 }
diff --git a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
index d2f4f36..4f7fd24 100644
--- a/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
+++ b/core/modules/language/lib/Drupal/language/ConfigurableLanguageManagerInterface.php
@@ -86,7 +86,7 @@ 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);
diff --git a/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php b/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php
index 3c0dc57..50e2f40 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->getLanguageOverrideStorage($langcode);
+    foreach ($storage->listAll() as $name) {
+      $this->languageManager->getLanguageConfigOverride($langcode, $name)->delete();
     }
   }
 
diff --git a/core/modules/system/tests/modules/menu_test/config/language.config.nl.menu_test.menu_item.yml b/core/modules/system/tests/modules/menu_test/config/language/nl/menu_test.menu_item.yml
similarity index 100%
rename from core/modules/system/tests/modules/menu_test/config/language.config.nl.menu_test.menu_item.yml
rename to core/modules/system/tests/modules/menu_test/config/language/nl/menu_test.menu_item.yml
diff --git a/core/modules/tour/tests/tour_test/config/language.config.it.tour.tour.tour-test.yml b/core/modules/tour/tests/tour_test/config/language/it/tour.tour.tour-test.yml
similarity index 100%
rename from core/modules/tour/tests/tour_test/config/language.config.it.tour.tour.tour-test.yml
rename to core/modules/tour/tests/tour_test/config/language/it/tour.tour.tour-test.yml
