diff --git a/core/core.services.yml b/core/core.services.yml
index b1f3db8..fa8078b 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -264,8 +264,6 @@ services:
   config.storage.schema:
     class: Drupal\Core\Config\ExtensionInstallStorage
     arguments: ['@config.storage', 'config/schema']
-  config.storage.installer:
-    class: Drupal\Core\Config\InstallStorage
   config.typed:
     class: Drupal\Core\Config\TypedConfigManager
     arguments: ['@config.storage', '@config.storage.schema', '@cache.discovery', '@module_handler']
diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php
index 3d5adad..c180847 100644
--- a/core/lib/Drupal/Core/Language/LanguageManager.php
+++ b/core/lib/Drupal/Core/Language/LanguageManager.php
@@ -233,27 +233,16 @@ public function getLanguageSwitchLinks($type, Url $url) {
   }
 
   /**
-   * Some common languages with their English and native names.
-   *
-   * Language codes are defined by the W3C language tags document for
-   * interoperability. Language codes typically have a language and, optionally,
-   * a script or regional variant name. See:
-   * http://www.w3.org/International/articles/language-tags/ for more
-   * information.
-   *
-   * This list is based on languages available from localize.drupal.org. See
-   * http://localize.drupal.org/issues for information on how to add languages
-   * there.
-   *
-   * The "Left-to-right marker" comments and the enclosed UTF-8 markers are to
-   * make otherwise strange looking PHP syntax natural (to not be displayed in
-   * right to left). See http://drupal.org/node/128866#comment-528929.
-   *
-   * @return array
-   *   An array of language code to language name information.
-   *   Language name information itself is an array of English and native names.
+   * @inheritdoc
    */
   public static function getStandardLanguageList() {
+    // This list is based on languages available from localize.drupal.org. See
+    // http://localize.drupal.org/issues for information on how to add languages
+    // there.
+    //
+    // The "Left-to-right marker" comments and the enclosed UTF-8 markers are to
+    // make otherwise strange looking PHP syntax natural (to not be displayed in
+    // right to left). See http://drupal.org/node/128866#comment-528929.
     return array(
       'af' => array('Afrikaans', 'Afrikaans'),
       'am' => array('Amharic', 'አማርኛ'),
diff --git a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
index c29dd33..b536a00 100644
--- a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
+++ b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php
@@ -208,4 +208,19 @@ public function setConfigOverrideLanguage(LanguageInterface $language = NULL);
    */
   public function getConfigOverrideLanguage();
 
+  /**
+   * Some common languages with their English and native names.
+   *
+   * Language codes are defined by the W3C language tags document for
+   * interoperability. Language codes typically have a language and, optionally,
+   * a script or regional variant name. See:
+   * http://www.w3.org/International/articles/language-tags/ for more
+   * information.
+   *
+   * @return array
+   *   An array of language code to language name information. Language name
+   *   information itself is an array of English and native names.
+   */
+  public static function getStandardLanguageList();
+
 }
diff --git a/core/modules/config/src/Tests/ConfigInstallTest.php b/core/modules/config/src/Tests/ConfigInstallTest.php
index fe9a6b6..00ec4fa 100644
--- a/core/modules/config/src/Tests/ConfigInstallTest.php
+++ b/core/modules/config/src/Tests/ConfigInstallTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\config\Tests;
 
+use Drupal\Core\Config\InstallStorage;
 use Drupal\Core\Config\PreExistingConfigException;
 use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\Config\UnmetDependenciesException;
@@ -223,7 +224,8 @@ public function testDependencyChecking() {
   function testLanguage() {
     $this->installModules(['config_test_language']);
     // Test imported configuration with implicit language code.
-    $data = $this->container->get('config.storage.installer')->read('config_test.dynamic.dotted.english');
+    $storage = new InstallStorage();
+    $data = $storage->read('config_test.dynamic.dotted.english');
     $this->assertTrue(!isset($data['langcode']));
     $this->assertEqual(
       $this->config('config_test.dynamic.dotted.english')->get('langcode'),
@@ -231,7 +233,7 @@ function testLanguage() {
     );
 
     // Test imported configuration with explicit language code.
-    $data = $this->container->get('config.storage.installer')->read('config_test.dynamic.dotted.french');
+    $data = $storage->read('config_test.dynamic.dotted.french');
     $this->assertEqual($data['langcode'], 'fr');
     $this->assertEqual(
       $this->config('config_test.dynamic.dotted.french')->get('langcode'),
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 8e4a6c2..6bdc5aa 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -407,23 +407,30 @@ function locale_system_update(array $components) {
   // Skip running the translation imports if in the installer,
   // because it would break out of the installer flow. We have
   // built-in support for translation imports in the installer.
-  if (!drupal_installation_attempted() && locale_translatable_language_list() && \Drupal::config('locale.settings')->get('translation.import_enabled')) {
-    module_load_include('compare.inc', 'locale');
-
-    // Update the list of translatable projects and start the import batch.
-    // Only when new projects are added the update batch will be triggered. Not
-    // each enabled module will introduce a new project. E.g. sub modules.
-    $projects = array_keys(locale_translation_build_projects());
-    if ($list = array_intersect($list, $projects)) {
-      module_load_include('fetch.inc', 'locale');
-      // Get translation status of the projects, download and update
-      // translations.
-      $options = _locale_translation_default_update_options();
-      $batch = locale_translation_batch_update_build($list, array(), $options);
-      batch_set($batch);
+  if (!drupal_installation_attempted() && locale_translatable_language_list()) {
+    if (\Drupal::config('locale.settings')->get('translation.import_enabled')) {
+      module_load_include('compare.inc', 'locale');
+
+      // Update the list of translatable projects and start the import batch.
+      // Only when new projects are added the update batch will be triggered.
+      // Not each enabled module will introduce a new project. E.g. sub modules.
+      $projects = array_keys(locale_translation_build_projects());
+      if ($list = array_intersect($list, $projects)) {
+        module_load_include('fetch.inc', 'locale');
+        // Get translation status of the projects, download and update
+        // translations.
+        $options = _locale_translation_default_update_options();
+        $batch = locale_translation_batch_update_build($list, [], $options);
+        batch_set($batch);
+      }
     }
+
+    // Construct a batch to update configuration for all components. Installing
+    // this component may have installed configuration from any number of other
+    // components. Do this even if import is not enabled because parsing new
+    // configuration may expose new source strings.
     \Drupal::moduleHandler()->loadInclude('locale', 'bulk.inc');
-    if ($batch = locale_config_batch_update_components(array(), array(), $components)) {
+    if ($batch = locale_config_batch_update_components([])) {
       batch_set($batch);
     }
   }
diff --git a/core/modules/locale/locale.services.yml b/core/modules/locale/locale.services.yml
index ff2bfc2..393866b 100644
--- a/core/modules/locale/locale.services.yml
+++ b/core/modules/locale/locale.services.yml
@@ -1,7 +1,11 @@
 services:
+  locale.default.config.storage:
+    class: Drupal\locale\LocaleDefaultConfigStorage
+    arguments: ['@config.storage', '@language_manager']
+    public: false
   locale.config_manager:
     class: Drupal\locale\LocaleConfigManager
-    arguments: ['@config.storage', '@config.storage.installer', '@locale.storage', '@config.factory', '@config.typed', '@language_manager']
+    arguments: ['@config.storage', '@locale.storage', '@config.factory', '@config.typed', '@language_manager', '@locale.default.config.storage']
   locale.storage:
     class: Drupal\locale\StringDatabaseStorage
     arguments: ['@database']
diff --git a/core/modules/locale/src/LocaleConfigManager.php b/core/modules/locale/src/LocaleConfigManager.php
index da21bca..d96c758 100644
--- a/core/modules/locale/src/LocaleConfigManager.php
+++ b/core/modules/locale/src/LocaleConfigManager.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\InstallStorage;
 use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\Config\TypedConfigManagerInterface;
 use Drupal\Core\StringTranslation\TranslationWrapper;
@@ -45,13 +46,6 @@ class LocaleConfigManager {
   protected $configStorage;
 
   /**
-   * The storage instance for reading default configuration data.
-   *
-   * @var \Drupal\Core\Config\StorageInterface
-   */
-  protected $installStorage;
-
-  /**
    * The string storage for reading and writing translations.
    *
    * @var \Drupal\locale\StringStorageInterface;
@@ -96,13 +90,17 @@ class LocaleConfigManager {
   protected $isUpdatingFromLocale = FALSE;
 
   /**
+   * The locale default config storage instance.
+   *
+   * @var \Drupal\locale\LocaleDefaultConfigStorage
+   */
+  protected $defaultConfigStorage;
+
+  /**
    * Creates a new typed configuration manager.
    *
    * @param \Drupal\Core\Config\StorageInterface $config_storage
    *   The storage object to use for reading configuration data.
-   * @param \Drupal\Core\Config\StorageInterface $install_storage
-   *   The storage object to use for reading default configuration
-   *   data.
    * @param \Drupal\locale\StringStorageInterface $locale_storage
    *   The locale storage to use for reading string translations.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
@@ -111,14 +109,16 @@ class LocaleConfigManager {
    *   The typed configuration manager.
    * @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager
    *   The language manager.
+   * @param \Drupal\locale\LocaleDefaultConfigStorage $default_config_storage
+   *   The locale default configuration storage.
    */
-  public function __construct(StorageInterface $config_storage, StorageInterface $install_storage, StringStorageInterface $locale_storage, ConfigFactoryInterface $config_factory, TypedConfigManagerInterface $typed_config, ConfigurableLanguageManagerInterface $language_manager) {
+  public function __construct(StorageInterface $config_storage, StringStorageInterface $locale_storage, ConfigFactoryInterface $config_factory, TypedConfigManagerInterface $typed_config, ConfigurableLanguageManagerInterface $language_manager, LocaleDefaultConfigStorage $default_config_storage) {
     $this->configStorage = $config_storage;
-    $this->installStorage = $install_storage;
     $this->localeStorage = $locale_storage;
     $this->configFactory = $config_factory;
     $this->typedConfigManager = $typed_config;
     $this->languageManager = $language_manager;
+    $this->defaultConfigStorage = $default_config_storage;
   }
 
   /**
@@ -133,7 +133,7 @@ public function __construct(StorageInterface $config_storage, StorageInterface $
   public function getTranslatableDefaultConfig($name) {
     if ($this->isSupported($name)) {
       // Create typed configuration wrapper based on install storage data.
-      $data = $this->installStorageRead($name);
+      $data = $this->defaultConfigStorage->read($name);
       $type_definition = $this->typedConfigManager->getDefinition($name);
       $data_definition = $this->typedConfigManager->buildDataDefinition($type_definition, $data);
       $typed_config = $this->typedConfigManager->create($data_definition, $data);
@@ -293,12 +293,12 @@ public function getComponentNames(array $components = array()) {
       foreach ($components as $type => $list) {
         // InstallStorage::getComponentNames returns a list of folders keyed by
         // config name.
-        $names = array_merge($names, $this->installStorageComponents($type, $list));
+        $names = array_merge($names, $this->defaultConfigStorage->getComponentNames($type, $list));
       }
       return $names;
     }
     else {
-      return $this->installStorageAll();
+      return $this->defaultConfigStorage->listAll();
     }
   }
 
@@ -474,7 +474,7 @@ public function hasTranslation($name, $langcode) {
    *   configuration exists.
    */
   public function getDefaultConfigLangcode($name) {
-    $shipped = $this->installStorageRead($name);
+    $shipped = $this->defaultConfigStorage->read($name);
     if (!empty($shipped)) {
       return !empty($shipped['langcode']) ? $shipped['langcode'] : 'en';
     }
@@ -635,81 +635,4 @@ protected function filterOverride(array $override_data, array $translatable) {
     return $filtered_data;
   }
 
-  /**
-   * Read a configuration from install storage or default languages.
-   *
-   * @param string $name
-   *   Configuration object name.
-   *
-   * @return array
-   *   Configuration data from install storage or default language.
-   */
-  protected function installStorageRead($name) {
-    if ($this->installStorage->exists($name)) {
-      return $this->installStorage->read($name);
-    }
-    elseif (strpos($name, 'language.entity.') === 0) {
-      // Simulate default languages as if they were shipped as default
-      // configuration.
-      $langcode = str_replace('language.entity.', '', $name);
-      $predefined_languages = $this->languageManager->getStandardLanguageList();
-      if (isset($predefined_languages[$langcode])) {
-        $data = $this->configStorage->read($name);
-        $data['label'] = $predefined_languages[$langcode][0];
-        return $data;
-      }
-    }
-  }
-
-  /**
-   * Return the list of configuration in install storage and current languages.
-   *
-   * @return array
-   *   List of configuration in install storage and current languages.
-   */
-  protected function installStorageAll() {
-    $languages = $this->predefinedConfiguredLanguages();
-    return array_unique(array_merge($this->installStorage->listAll(), $languages));
-  }
-
-  /**
-   * Get all configuration names and folders for a list of modules or themes.
-   *
-   * @param string $type
-   *   Type of components: 'module' | 'theme' | 'profile'
-   * @param array $list
-   *   Array of theme or module names.
-   *
-   * @return array
-   *   Configuration names provided by that component. In case of language
-   *   module this list is extended with configured languages that have
-   *   predefined names as well.
-   */
-  protected function installStorageComponents($type, array $list) {
-    $names = array_keys($this->installStorage->getComponentNames($type, $list));
-    if ($type == 'module' && in_array('language', $list)) {
-      $languages = $this->predefinedConfiguredLanguages();
-      $names = array_unique(array_merge($names, $languages));
-    }
-    return $names;
-  }
-
-  /**
-   * Compute the list of configuration names that match predefined languages.
-   *
-   * @return array
-   *   The list of configuration names that match predefined languages.
-   */
-  protected function predefinedConfiguredLanguages() {
-    $names = $this->configStorage->listAll('language.entity.');
-    $predefined_languages = $this->languageManager->getStandardLanguageList();
-    foreach ($names as $id => $name) {
-      $langcode = str_replace('language.entity.', '', $name);
-      if (!isset($predefined_languages[$langcode])) {
-        unset($names[$id]);
-      }
-    }
-    return array_values($names);
-  }
-
 }
diff --git a/core/modules/locale/src/LocaleDefaultConfigStorage.php b/core/modules/locale/src/LocaleDefaultConfigStorage.php
new file mode 100644
index 0000000..5828f61
--- /dev/null
+++ b/core/modules/locale/src/LocaleDefaultConfigStorage.php
@@ -0,0 +1,165 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\locale\LocaleDefaultConfigStorage.
+ */
+
+namespace Drupal\locale;
+
+use Drupal\Core\Config\InstallStorage;
+use Drupal\Core\Config\StorageInterface;
+use Drupal\language\ConfigurableLanguageManagerInterface;
+
+/**
+ * Provides access to default configuration for locale integration.
+ *
+ * Allows unified access to default configuration from one of three sources:
+ * - Required default configuration (config/install/*)
+ * - Optional default configuration (config/optional/*)
+ * - Predefined languages mocked as default configuration (list defined in
+ *   LocaleConfigManagerInterface::getStandardLanguageList())
+ *
+ * These sources are considered equal in terms of how locale module interacts
+ * with them for translation. Their translatable source strings are exposed
+ * for interface translation and participate in remote translation updates.
+ */
+class LocaleDefaultConfigStorage {
+
+  /**
+   * The storage instance for reading configuration data.
+   *
+   * @var \Drupal\Core\Config\StorageInterface
+   */
+  protected $configStorage;
+
+  /**
+   * The language manager.
+   *
+   * @var \Drupal\language\ConfigurableLanguageManagerInterface
+   */
+  protected $languageManager;
+
+  /**
+   * The storage instance for reading required default configuration data.
+   *
+   * @var \Drupal\Core\Config\StorageInterface
+   */
+  protected $requiredInstallStorage;
+
+  /**
+   * The storage instance for reading optional default configuration data.
+   *
+   * @var \Drupal\Core\Config\StorageInterface
+   */
+  protected $optionalInstallStorage;
+
+  /**
+   * Constructs a LocaleDefaultConfigStorage.
+   *
+   * @param \Drupal\Core\Config\StorageInterface $config_storage
+   *   The storage object to use for reading configuration data.
+   * @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager
+   *   The language manager.
+   */
+  public function __construct(StorageInterface $config_storage, ConfigurableLanguageManagerInterface $language_manager) {
+    $this->configStorage = $config_storage;
+    $this->languageManager = $language_manager;
+
+    $this->requiredInstallStorage = new InstallStorage();
+    $this->optionalInstallStorage = new InstallStorage(InstallStorage::CONFIG_OPTIONAL_DIRECTORY);
+  }
+
+  /**
+   * Read a configuration from install storage or default languages.
+   *
+   * @param string $name
+   *   Configuration object name.
+   *
+   * @return array
+   *   Configuration data from install storage or default language.
+   */
+  public function read($name) {
+    if ($this->requiredInstallStorage->exists($name)) {
+      return $this->requiredInstallStorage->read($name);
+    }
+    elseif ($this->optionalInstallStorage->exists($name)) {
+      return $this->optionalInstallStorage->read($name);
+    }
+    elseif (strpos($name, 'language.entity.') === 0) {
+      // Simulate default languages as if they were shipped as default
+      // configuration.
+      $langcode = str_replace('language.entity.', '', $name);
+      $predefined_languages = $this->languageManager->getStandardLanguageList();
+      if (isset($predefined_languages[$langcode])) {
+        $data = $this->configStorage->read($name);
+        $data['label'] = $predefined_languages[$langcode][0];
+        return $data;
+      }
+    }
+  }
+
+  /**
+   * Return the list of configuration in install storage and current languages.
+   *
+   * @return array
+   *   List of configuration in install storage and current languages.
+   */
+  public function listAll() {
+    $languages = $this->predefinedConfiguredLanguages();
+    return array_unique(
+      array_merge(
+        $this->requiredInstallStorage->listAll(),
+        $this->optionalInstallStorage->listAll(),
+        $languages
+      )
+    );
+  }
+
+  /**
+   * Get all configuration names and folders for a list of modules or themes.
+   *
+   * @param string $type
+   *   Type of components: 'module' | 'theme' | 'profile'
+   * @param array $list
+   *   Array of theme or module names.
+   *
+   * @return array
+   *   Configuration names provided by that component. In case of language
+   *   module this list is extended with configured languages that have
+   *   predefined names as well.
+   */
+  public function getComponentNames($type, array $list) {
+    $names = array_unique(
+      array_merge(
+        array_keys($this->requiredInstallStorage->getComponentNames($type, $list)),
+        array_keys($this->optionalInstallStorage->getComponentNames($type, $list))
+      )
+    );
+    if ($type == 'module' && in_array('language', $list)) {
+      $languages = $this->predefinedConfiguredLanguages();
+      $names = array_unique(array_merge($names, $languages));
+    }
+    return $names;
+  }
+
+  /**
+   * Compute the list of configuration names that match predefined languages.
+   *
+   * @return array
+   *   The list of configuration names that match predefined languages.
+   */
+  protected function predefinedConfiguredLanguages() {
+    $names = $this->configStorage->listAll('language.entity.');
+    $predefined_languages = $this->languageManager->getStandardLanguageList();
+    foreach ($names as $id => $name) {
+      $langcode = str_replace('language.entity.', '', $name);
+      if (!isset($predefined_languages[$langcode])) {
+        unset($names[$id]);
+      }
+    }
+    return array_values($names);
+  }
+
+}
+
diff --git a/core/modules/locale/src/Tests/LocaleConfigSubscriberTest.php b/core/modules/locale/src/Tests/LocaleConfigSubscriberTest.php
index 24017fd..376ec44 100644
--- a/core/modules/locale/src/Tests/LocaleConfigSubscriberTest.php
+++ b/core/modules/locale/src/Tests/LocaleConfigSubscriberTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\locale\Tests;
 
 use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\locale\Locale;
 use Drupal\locale\StringInterface;
 use Drupal\locale\TranslationString;
 use Drupal\simpletest\KernelTestBase;
@@ -22,7 +23,7 @@ class LocaleConfigSubscriberTest extends KernelTestBase {
   /**
    * {@inheritdoc}
    */
-  public static $modules = ['language', 'locale'];
+  public static $modules = ['language', 'locale', 'system'];
 
   /**
    * The configurable language manager used in this test.
@@ -61,6 +62,7 @@ protected function setUp() {
     $this->setUpDefaultLanguage();
 
     $this->installSchema('locale', ['locales_source', 'locales_target', 'locales_location']);
+    $this->installSchema('system', ['queue']);
 
     $this->setupLanguages();
 
@@ -68,7 +70,12 @@ protected function setUp() {
     $this->installConfig(['locale_test']);
     // Simulate this hook invoked which would happen if in a non-kernel test
     // or normal environment.
-    locale_modules_installed(array('locale_test'));
+    // @see locale_modules_installed()
+    // @see locale_system_update()
+    locale_system_set_config_langcodes();
+    $langcodes = array_keys(\Drupal::languageManager()->getLanguages());
+    $names = \Drupal\locale\Locale::config()->getComponentNames();
+    Locale::config()->updateConfigTranslations($names, $langcodes);
 
     $this->configFactory = $this->container->get('config.factory');
     $this->stringStorage = $this->container->get('locale.storage');
diff --git a/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php b/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php
index 4535b9b..64ea797 100644
--- a/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php
+++ b/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php
@@ -19,6 +19,13 @@
 class LocaleConfigTranslationTest extends WebTestBase {
 
   /**
+   * The language code used.
+   *
+   * @var string
+   */
+  protected $langcode;
+
+  /**
    * Modules to enable.
    *
    * @var array
@@ -38,28 +45,28 @@ protected function setUp() {
     $this->config('locale.settings')
       ->set('translation.import_enabled', TRUE)
       ->save();
-  }
 
-  /**
-   * Tests basic configuration translation.
-   */
-  public function testConfigTranslation() {
     // Add custom language.
-    $langcode = 'xx';
+    $this->langcode = 'xx';
     $admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages', 'translate interface', 'administer modules', 'access site-wide contact form', 'administer contact forms', 'administer site configuration'));
     $this->drupalLogin($admin_user);
     $name = $this->randomMachineName(16);
     $edit = array(
       'predefined_langcode' => 'custom',
-      'langcode' => $langcode,
+      'langcode' => $this->langcode,
       'label' => $name,
       'direction' => LanguageInterface::DIRECTION_LTR,
     );
     $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
     // Set path prefix.
-    $edit = array("prefix[$langcode]" => $langcode);
+    $edit = ["prefix[$this->langcode]" => $this->langcode];
     $this->drupalPostForm('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
+  }
 
+  /**
+   * Tests basic configuration translation.
+   */
+  public function testConfigTranslation() {
     // Check that the maintenance message exists and create translation for it.
     $source = '@site is currently under maintenance. We should be back shortly. Thank you for your patience.';
     $string = $this->storage->findString(array('source' => $source, 'context' => '', 'type' => 'configuration'));
@@ -69,7 +76,7 @@ public function testConfigTranslation() {
     $message = $this->randomMachineName(20);
     $search = array(
       'string' => $string->source,
-      'langcode' => $langcode,
+      'langcode' => $this->langcode,
       'translation' => 'all',
     );
     $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
@@ -82,7 +89,7 @@ public function testConfigTranslation() {
     $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations'));
 
     // Get translation and check we've only got the message.
-    $translation = \Drupal::languageManager()->getLanguageConfigOverride($langcode, 'system.maintenance')->get();
+    $translation = \Drupal::languageManager()->getLanguageConfigOverride($this->langcode, 'system.maintenance')->get();
     $this->assertEqual(count($translation), 1, 'Got the right number of properties after translation.');
     $this->assertEqual($translation['message'], $message);
 
@@ -93,7 +100,7 @@ public function testConfigTranslation() {
     // Translate using the UI so configuration is refreshed.
     $search = array(
       'string' => $string->source,
-      'langcode' => $langcode,
+      'langcode' => $this->langcode,
       'translation' => 'all',
     );
     $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
@@ -105,12 +112,12 @@ public function testConfigTranslation() {
     );
     $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations'));
 
-    $translation = \Drupal::languageManager()->getLanguageConfigOverride($langcode, 'core.date_format.medium')->get();
+    $translation = \Drupal::languageManager()->getLanguageConfigOverride($this->langcode, 'core.date_format.medium')->get();
     $this->assertEqual($translation['pattern'], 'D', 'Got the right date format pattern after translation.');
 
     // Formatting the date 8 / 27 / 1985 @ 13:37 EST with pattern D should
     // display "Tue".
-    $formatted_date = format_date(494015820, $type = 'medium', NULL, NULL, $langcode);
+    $formatted_date = format_date(494015820, $type = 'medium', NULL, NULL, $this->langcode);
     $this->assertEqual($formatted_date, 'Tue', 'Got the right formatted date using the date format translation pattern.');
 
     // Assert strings from image module config are not available.
@@ -127,7 +134,7 @@ public function testConfigTranslation() {
     $this->assertTrue(isset($locations['configuration']) && isset($locations['configuration']['image.style.medium']), 'Configuration string has been created with the right location');
 
     // Check the string is unique and has no translation yet.
-    $translations = $this->storage->getTranslations(array('language' => $langcode, 'type' => 'configuration', 'name' => 'image.style.medium'));
+    $translations = $this->storage->getTranslations(['language' => $this->langcode, 'type' => 'configuration', 'name' => 'image.style.medium']);
     $this->assertEqual(count($translations), 1);
     $translation = reset($translations);
     $this->assertEqual($translation->source, $string->source);
@@ -137,7 +144,7 @@ public function testConfigTranslation() {
     $image_style_label = $this->randomMachineName(20);
     $search = array(
       'string' => $string->source,
-      'langcode' => $langcode,
+      'langcode' => $this->langcode,
       'translation' => 'all',
     );
     $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
@@ -149,12 +156,12 @@ public function testConfigTranslation() {
     $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations'));
 
     // Check the right single translation has been created.
-    $translations = $this->storage->getTranslations(array('language' => $langcode, 'type' => 'configuration', 'name' => 'image.style.medium'));
+    $translations = $this->storage->getTranslations(['language' => $this->langcode, 'type' => 'configuration', 'name' => 'image.style.medium']);
     $translation = reset($translations);
     $this->assertTrue(count($translations) == 1 && $translation->source == $string->source && $translation->translation == $image_style_label, 'Got only one translation for image configuration.');
 
     // Try more complex configuration data.
-    $translation = \Drupal::languageManager()->getLanguageConfigOverride($langcode, 'image.style.medium')->get();
+    $translation = \Drupal::languageManager()->getLanguageConfigOverride($this->langcode, 'image.style.medium')->get();
     $this->assertEqual($translation['label'], $image_style_label, 'Got the right translation for image style name after translation');
 
     // Uninstall the module.
@@ -169,7 +176,7 @@ public function testConfigTranslation() {
     $category_label = $this->randomMachineName(20);
     $search = array(
       'string' => 'Website feedback',
-      'langcode' => $langcode,
+      'langcode' => $this->langcode,
       'translation' => 'all',
     );
     $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter'));
@@ -183,7 +190,7 @@ public function testConfigTranslation() {
     // Check if this category displayed in this language will use the
     // translation. This test ensures the entity loaded from the request
     // upcasting will already work.
-    $this->drupalGet($langcode . '/contact/feedback');
+    $this->drupalGet($this->langcode . '/contact/feedback');
     $this->assertText($category_label);
 
     // Check if the UI does not show the translated String.
@@ -191,4 +198,54 @@ public function testConfigTranslation() {
     $this->assertFieldById('edit-label', 'Website feedback', 'Translation is not loaded for Edit Form.');
   }
 
+  /**
+   * Test translatability of optional configuration in locale.
+   */
+  public function testOptionalConfiguration() {
+    $this->assertNodeConfig(FALSE, FALSE);
+    // Enable the node module.
+    $this->drupalPostForm('admin/modules', ['modules[Core][node][enable]' => "1"], t('Save configuration'));
+    $this->drupalPostForm(NULL, [], t('Continue'));
+    $this->rebuildContainer();
+    $this->assertNodeConfig(TRUE, FALSE);
+    // Enable the views module (which node provides some optional config for).
+    $this->drupalPostForm('admin/modules', ['modules[Core][views][enable]' => "1"], t('Save configuration'));
+    $this->rebuildContainer();
+    $this->assertNodeConfig(TRUE, TRUE);
+  }
+
+  /**
+   * Check that node configuration source strings are made available in locale.
+   *
+   * @param bool $required
+   *   Whether to assume a sample of the required default configuration is
+   *   present.
+   * @param bool $optional
+   *   Whether to assume a sample of the optional default configuration is
+   *   present.
+   */
+  protected function assertNodeConfig($required, $optional) {
+    // Check the required default configuration in node module.
+    $string = $this->storage->findString(['source' => 'Make content sticky', 'context' => '', 'type' => 'configuration']);
+    if ($required) {
+      $this->assertFalse($this->config('system.action.node_make_sticky_action')->isNew());
+      $this->assertTrue($string, 'Node action text can be found with node module.');
+    }
+    else {
+      $this->assertTrue($this->config('system.action.node_make_sticky_action')->isNew());
+      $this->assertFalse($string, 'Node action text can not be found without node module.');
+    }
+
+    // Check the optional default configuration in node module.
+    $string = $this->storage->findString(['source' => 'No front page content has been created yet.', 'context' => '', 'type' => 'configuration']);
+    if ($optional) {
+      $this->assertFalse($this->config('views.view.frontpage')->isNew());
+      $this->assertTrue($string, 'Node view text can be found with node and views modules.');
+    }
+    else {
+      $this->assertTrue($this->config('views.view.frontpage')->isNew());
+      $this->assertFalse($string, 'Node view text can not be found without node and/or views modules.');
+    }
+  }
+
 }
