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