diff --git a/core/lib/Drupal/Core/StringTranslation/TranslationWrapper.php b/core/lib/Drupal/Core/StringTranslation/TranslationWrapper.php index 1285cb7..c69b705 100644 --- a/core/lib/Drupal/Core/StringTranslation/TranslationWrapper.php +++ b/core/lib/Drupal/Core/StringTranslation/TranslationWrapper.php @@ -60,6 +60,29 @@ public function __construct($string, array $arguments = array(), array $options } /** + * Get the string value stored in this translation wrapper. + * + * @return string + * The string stored in this wrapper. + */ + public function getString() { + return $this->string; + } + + /** + * Get a specific option from this translation wrapper. + * + * @param $name + * Option name. + * + * @return mixed + * The value of this option or empty string of option is not set. + */ + public function getOption($name) { + return isset($this->options[$name]) ? $this->options[$name] : ''; + } + + /** * Implements the magic __toString() method. */ public function __toString() { diff --git a/core/modules/config_translation/src/ConfigNamesMapper.php b/core/modules/config_translation/src/ConfigNamesMapper.php index b681b33..e771d3a 100644 --- a/core/modules/config_translation/src/ConfigNamesMapper.php +++ b/core/modules/config_translation/src/ConfigNamesMapper.php @@ -465,7 +465,7 @@ public function hasTranslatable() { */ public function hasTranslation(LanguageInterface $language) { foreach ($this->getConfigNames() as $name) { - if ($this->localeConfigManager->hasTranslation($name, $language)) { + if ($this->localeConfigManager->hasTranslation($name, $language->getId())) { return TRUE; } } diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc index 357aaf8..a4677ca 100644 --- a/core/modules/locale/locale.bulk.inc +++ b/core/modules/locale/locale.bulk.inc @@ -324,7 +324,7 @@ function locale_translate_batch_refresh(array &$context) { } elseif ($name = array_shift($context['sandbox']['refresh']['names'])) { // Refresh all languages for one object at a time. - $count = locale_config_update_multiple(array($name), $context['sandbox']['refresh']['languages']); + $count = Locale::config()->updateConfigTranslations(array($name), $context['sandbox']['refresh']['languages']); $context['results']['stats']['config'] += $count; // Inherit finished information from the "parent" string lookup step so // visual display of status will make sense. @@ -532,7 +532,7 @@ function locale_translate_delete_translation_files(array $projects = array(), ar * The batch definition. */ function locale_config_batch_update_components(array $options, array $langcodes = array(), array $components = array()) { - $langcodes = $langcodes ? $langcodes : array_keys(locale_translatable_language_list()); + $langcodes = $langcodes ? $langcodes : array_keys(\Drupal::languageManager()->getLanguages()); if ($langcodes && $names = \Drupal\locale\Locale::config()->getComponentNames($components)) { return locale_config_batch_build($names, $langcodes, $options); } @@ -606,7 +606,7 @@ function locale_config_batch_refresh_name(array $names, array $langcodes, array if (!isset($context['result']['stats']['config'])) { $context['result']['stats']['config'] = 0; } - $context['result']['stats']['config'] += locale_config_update_multiple($names, $langcodes); + $context['result']['stats']['config'] += Locale::config()->updateConfigTranslations($names, $langcodes); foreach ($names as $name) { $context['result']['names'][] = $name; } @@ -639,41 +639,3 @@ function locale_config_batch_finished($success, array $results) { } } } - -/** - * Updates all configuration for names / languages. - * - * @param array $names - * Array of names of configuration objects to update. - * @param array $langcodes - * (optional) Array of language codes to update. Defaults to all languages. - * - * @return int - * Number of configuration objects retranslated. - */ -function locale_config_update_multiple(array $names, array $langcodes = array()) { - /** @var \Drupal\language\ConfigurableLanguageManagerInterface $language_manager */ - $language_manager = \Drupal::languageManager(); - $locale_config_manager = Locale::config(); - - $langcodes = $langcodes ? $langcodes : array_keys(locale_translatable_language_list()); - $count = 0; - foreach ($names as $name) { - $wrapper = $locale_config_manager->get($name); - foreach ($langcodes as $langcode) { - $translation = $wrapper->getValue() ? $wrapper->getTranslation($langcode)->getValue() : NULL; - if ($translation) { - $locale_config_manager->saveTranslationData($name, $langcode, $translation); - $count++; - } - else { - // Do not bother deleting language overrides which do not exist in the - // first place. - if (!$language_manager->getLanguageConfigOverride($langcode, $name)->isNew()) { - $locale_config_manager->deleteTranslationData($name, $langcode); - } - } - } - } - return $count; -} diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 971b47d..ef70fab 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -24,6 +24,7 @@ use Drupal\Core\Language\LanguageInterface; use Drupal\language\ConfigurableLanguageInterface; use Drupal\Component\Utility\Crypt; +use Drupal\locale\Locale; /** * Regular expression pattern used to localize JavaScript strings. @@ -226,7 +227,7 @@ function locale_configurable_language_delete(ConfigurableLanguageInterface $lang locale_translate_delete_translation_files(array(), array($language->id())); // Remove translated configuration objects. - \Drupal\locale\Locale::config()->deleteLanguageTranslations($language->id()); + Locale::config()->deleteLanguageTranslations($language->id()); // Changing the language settings impacts the interface: _locale_invalidate_js($language->id()); @@ -313,6 +314,7 @@ function locale_get_plural($count, $langcode = NULL) { */ function locale_modules_installed($modules) { $components['module'] = $modules; + locale_system_set_config_langcodes($components); locale_system_update($components); } @@ -329,6 +331,7 @@ function locale_module_preuninstall($module) { */ function locale_themes_installed($themes) { $components['theme'] = $themes; + locale_system_set_config_langcodes($components); locale_system_update($components); } @@ -356,6 +359,41 @@ function locale_cron() { } /** + * Update default configuration when new modules or themes are installed. + * + * @param array $components + * An array of arrays of component (theme and/or module) names to import + * translations for, indexed by type. + */ +function locale_system_set_config_langcodes(array $components) { + // Need to rewrite some default configuration language codes if the default + // site language is not English. + $default_langcode = \Drupal::languageManager()->getDefaultLanguage()->getId(); + if ($default_langcode != 'en') { + // If just installed the locale module, we need to update all prior + // shipped configuration to the foreign site language. Otherwise keep the + // components list received to just update the shipped configuration just + // imported. + if (isset($components['module']) && in_array('locale', $components['module'])) { + $components = array(); + } + $names = Locale::config()->getComponentNames($components); + + foreach ($names as $name) { + $config = \Drupal::configFactory()->getEditable($name); + // Should only update if still exists in active configuration. If locale + // module is enabled later, then some configuration may not exist anymore. + if (!$config->isNew()) { + $langcode = $config->get('langcode'); + if (empty($langcode) || $langcode == 'en') { + $config->set('langcode', $default_langcode)->save(); + } + } + } + } +} + +/** * Imports translations when new modules or themes are installed. * * This function will start a batch to import translations for the added @@ -412,7 +450,7 @@ function locale_system_remove($components) { module_load_include('compare.inc', 'locale'); \Drupal::moduleHandler()->loadInclude('locale', 'bulk.inc'); // Delete configuration translations. - \Drupal\locale\Locale::config()->deleteComponentTranslations($components, array_keys($language_list)); + Locale::config()->deleteComponentTranslations($components, array_keys($language_list)); // Only when projects are removed, the translation files and records will be // deleted. Not each disabled module will remove a project, e.g., sub @@ -1020,19 +1058,14 @@ function _locale_refresh_translations($langcodes, $lids = array()) { /** * Refreshes configuration after string translations have been updated. * - * The information that will be refreshed includes: - * - JavaScript translations. - * - Locale cache. - * * @param array $langcodes * Language codes for updated translations. * @param array $lids * List of string identifiers that have been updated / created. */ function _locale_refresh_configuration(array $langcodes, array $lids) { - if ($lids && $langcodes && $names = \Drupal\locale\Locale::config()->getStringNames($lids)) { - \Drupal::moduleHandler()->loadInclude('locale', 'bulk.inc'); - locale_config_update_multiple($names, $langcodes); + if ($lids && $langcodes && $names = Locale::config()->getStringNames($lids)) { + Locale::config()->updateConfigTranslations($names, $langcodes); } } diff --git a/core/modules/locale/locale.services.yml b/core/modules/locale/locale.services.yml index 27cef2c..95683b3 100644 --- a/core/modules/locale/locale.services.yml +++ b/core/modules/locale/locale.services.yml @@ -22,6 +22,6 @@ services: - { name: stream_wrapper, scheme: translations } locale.config_subscriber: class: Drupal\locale\LocaleConfigSubscriber - arguments: ['@locale.storage', '@config.factory', '@locale.config.typed'] + arguments: ['@locale.storage', '@config.factory', '@locale.config.typed', '@language_manager'] tags: - { name: event_subscriber } diff --git a/core/modules/locale/src/LocaleConfigManager.php b/core/modules/locale/src/LocaleConfigManager.php index aee2d59..1d1762f 100644 --- a/core/modules/locale/src/LocaleConfigManager.php +++ b/core/modules/locale/src/LocaleConfigManager.php @@ -12,6 +12,9 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Language\LanguageInterface; use Drupal\language\ConfigurableLanguageManagerInterface; +use Drupal\Core\TypedData\TraversableTypedDataInterface; +use Drupal\Core\TypedData\TypedDataInterface; +use Drupal\Core\StringTranslation\TranslationWrapper; /** * Manages localized configuration type plugins. @@ -99,61 +102,113 @@ public function __construct(StorageInterface $config_storage, StorageInterface $ } /** - * Gets locale wrapper with typed configuration data. + * Gets array of translation wrappers for translatable configuration. * * @param string $name * Configuration object name. * - * @return \Drupal\locale\LocaleTypedConfig - * Locale-wrapped configuration element. - */ - public function get($name) { - // Read default and current configuration data. - $default = $this->installStorageRead($name); - $updated = $this->configStorage->read($name); - // We get only the data that didn't change from default. - $data = $this->compareConfigData($default, $updated); - $definition = $this->typedConfigManager->getDefinition($name); - $data_definition = $this->typedConfigManager->buildDataDefinition($definition, $data); - // Unless the configuration has a explicit language code we assume English. - $langcode = isset($default['langcode']) ? $default['langcode'] : 'en'; - $wrapper = new LocaleTypedConfig($data_definition, $name, $langcode, $this, $this->typedConfigManager, $this->languageManager); - $wrapper->setValue($data); - return $wrapper; + * @return array + * Array of translatable elements of the default configuration in $name. + */ + public function getTranslatableDefaultConfig($name) { + if ($this->isSupported($name)) { + // Create typed configuration wrapper based on install storage data. + $data = $this->installStorageRead($name); + $type_definition = $this->typedConfigManager->getDefinition($name); + $data_definition = $this->typedConfigManager->buildDataDefinition($type_definition, $data); + $typed_config = $this->typedConfigManager->create($data_definition, $data); + return $this->getTranslatableData($typed_config); + } } /** - * Compares default configuration with updated data. + * Gets translatable configuration data for a typed configuration element. * - * @param array $default - * Default configuration data. - * @param array|false $updated - * Current configuration data, or FALSE if no configuration data existed. + * @param \Drupal\Core\TypedData\TypedDataInterface $element + * Typed configuration element. * - * @return array - * The elements of default configuration that haven't changed. + * @return array|\Drupal\Core\StringTranslation\TranslationWrapper + * Configuration data children of $element filtered to translatable children + * returned in a nested array modeled after the structure of the + * configuration. The leaf elements are TranslationWrapper instances to + * translate later as needed. */ - protected function compareConfigData(array $default, $updated) { - // Speed up comparison, specially for install operations. - if ($default === $updated) { - return $default; + protected function getTranslatableData(TypedDataInterface $element) { + $translatable = array(); + if ($element instanceof TraversableTypedDataInterface) { + foreach ($element as $key => $property) { + $value = $this->getTranslatableData($property); + if (!empty($value)) { + $translatable[$key] = $value; + } + } } - $result = array(); - foreach ($default as $key => $value) { - if (isset($updated[$key])) { - if (is_array($value)) { - $result[$key] = $this->compareConfigData($value, $updated[$key]); + else { + $definition = $element->getDataDefinition(); + if (!empty($definition['translatable'])) { + $options = array(); + if (isset($definition['translation context'])) { + $options['context'] = $definition['translation context']; } - elseif ($value === $updated[$key]) { - $result[$key] = $value; + return new TranslationWrapper($element->getValue(), array(), $options); + } + } + return $translatable; + } + + /** + * Process the translatable data array with a given language. + * + * If the given language is translatable, will return the translated copy + * which will only contain strings that had translations. If the given + * language is English and is not translatable, will return a simplified + * array of the English source strings only. + * + * @param string $name + * The configuration name. + * @param array $active + * The active configuration data. + * @param array $translatable + * The translatable array structure, see this::getTranslatableData(). + * @param string $langcode + * The language code to process the array with + * + * @return array + * Processed translatable data array. Will only contain translations + * different from source strings or in case of untranslatable English, the + * source strings themselves. + */ + protected function processTranslatableData($name, array $active, array $translatable, $langcode) { + $translated = array(); + foreach ($translatable as $key => $item) { + if (!isset($active[$key])) { + continue; + } + if (is_array($item)) { + // Only add this key if there was a translated value underneath. + $value = $this->processTranslatableData($name, $active[$key], $item, $langcode); + if (!empty($value)) { + $translated[$key] = $value; + } + } + else { + /** @var \Drupal\Core\StringTranslation\TranslationWrapper $item */ + if ($langcode != 'en' || locale_translate_english()) { + $value = $this->translateString($name, $langcode, $item->getString(), $item->getOption('context')); + } + else { + $value = $item->getString(); + } + if (!empty($value)) { + $translated[$key] = $value; } } } - return $result; + return $translated; } /** - * Saves translated configuration data. + * Saves translated configuration override. * * @param string $name * Configuration object name. @@ -162,13 +217,27 @@ protected function compareConfigData(array $default, $updated) { * @param array $data * Configuration data to be saved, that will be only the translated values. */ - public function saveTranslationData($name, $langcode, array $data) { + public function saveTranslationOverride($name, $langcode, array $data) { $this->isUpdating = TRUE; $this->languageManager->getLanguageConfigOverride($langcode, $name)->setData($data)->save(); $this->isUpdating = FALSE; } /** + * Saves translated configuration data. + * + * @param string $name + * Configuration object name. + * @param array $data + * Configuration data to be saved with translations merged in. + */ + public function saveTranslationActive($name, array $data) { + $this->isUpdating = TRUE; + $this->configFactory->getEditable($name)->setData($data)->save(); + $this->isUpdating = FALSE; + } + + /** * Deletes translated configuration data. * * @param string $name @@ -176,7 +245,7 @@ public function saveTranslationData($name, $langcode, array $data) { * @param string $langcode * Language code. */ - public function deleteTranslationData($name, $langcode) { + public function deleteTranslationOverride($name, $langcode) { $this->isUpdating = TRUE; $this->languageManager->getLanguageConfigOverride($langcode, $name)->delete(); $this->isUpdating = FALSE; @@ -192,7 +261,7 @@ public function deleteTranslationData($name, $langcode) { * @return array * Array of configuration object names. */ - public function getComponentNames(array $components) { + public function getComponentNames(array $components = array()) { $components = array_filter($components); if ($components) { $names = array(); @@ -222,7 +291,7 @@ public function deleteComponentTranslations(array $components, array $langcodes) if ($names && $langcodes) { foreach ($names as $name) { foreach ($langcodes as $langcode) { - $this->deleteTranslationData($name, $langcode); + $this->deleteTranslationOverride($name, $langcode); } } } @@ -334,18 +403,81 @@ public function translateString($name, $langcode, $source, $context) { * * @param string $name * Configuration name. - * @param \Drupal\Core\Language\LanguageInterface $language - * A language object. + * @param string $langcode + * A language code. * * @return bool * A boolean indicating if a language has configuration translations. */ - public function hasTranslation($name, LanguageInterface $language) { - $translation = $this->languageManager->getLanguageConfigOverride($language->getId(), $name); + public function hasTranslation($name, $langcode) { + $translation = $this->languageManager->getLanguageConfigOverride($langcode, $name); return !$translation->isNew(); } /** + * Returns the original language code for this shipped configuration. + * + * @param $name + * The configuration name. + * + * @return null|string + * Language code of the original shipped configuration. NULL if no such + * default configuration. + */ + public function defaultConfigLangcode($name) { + $shipped = $this->installStorageRead($name); + if (!empty($shipped)) { + return !empty($shipped['langcode']) ? $shipped['langcode'] : 'en'; + } + } + + /** + * Returns the current language code for this active configuration. + * + * @param $name + * The configuration name. + * + * @return null|string + * Language code of the current active configuration. NULL if no such active + * configuration. + */ + public function activeConfigLangcode($name) { + $active = $this->configStorage->read($name); + if (!empty($active)) { + return !empty($active['langcode']) ? $active['langcode'] : 'en'; + } + } + + /** + * Whether the given configuration is supported for interface translation. + * + * @param $name + * The configuration name. + * + * @return bool + * TRUE if interface translation is supported. + */ + public function isSupported($name) { + return $this->defaultConfigLangcode($name) == 'en' && !is_null($this->activeConfigLangcode($name)); + } + + /** + * Whether the given configuration is supported for interface translation. + * + * @param $name + * The configuration name. + * + * @return bool + * TRUE if the configuration both exists as default and active configuration + * and their language codes don't match. + */ + public function isTranslatedConfig($name) { + $default_langcode = $this->defaultConfigLangcode($name); + $active_langcode = $this->activeConfigLangcode($name); + return !is_null($default_langcode) && !is_null($active_langcode) && $default_langcode != $active_langcode; + } + + /** * Indicates whether configuration translations are currently being updated. * * @return bool @@ -356,6 +488,89 @@ public function isUpdatingConfigTranslations() { } /** + * Updates all configuration translations for the names / languages provided. + * + * To be used when interface translation changes result in the need to update + * configuration translations to keep them in sync. + * + * @param array $names + * Array of names of configuration objects to update. + * @param array $langcodes + * (optional) Array of language codes to update. Defaults to all + * configurable languages. + * + * @return int + * Number of configuration objects updated (saved). + */ + public function updateConfigTranslations(array $names, array $langcodes = array()) { + $langcodes = $langcodes ? $langcodes : array_keys($this->languageManager->getLanguages()); + $count = 0; + foreach ($names as $name) { + // Only deal with configuration which was shipped. + if (!$this->isSupported($name)) { + continue; + } + + $translatable = $this->getTranslatableDefaultConfig($name); + $active_langcode = $this->activeConfigLangcode($name); + $active = $this->configStorage->read($name); + + foreach ($langcodes as $langcode) { + $processed = $this->processTranslatableData($name, $active, $translatable, $langcode); + if (empty($processed)) { + continue; + } + if ($langcode != $active_langcode) { + // If the language code is not the same as the active storage + // language, we should update a configuration override. + if ($processed) { + // Update translation data in configuration override. + $this->saveTranslationOverride($name, $langcode, $processed); + $count++; + } + elseif (!$this->languageManager->getLanguageConfigOverride($langcode, $name)->isNew()) { + // Delete language override if override exists. + $this->deleteTranslationOverride($name, $langcode); + } + } + elseif ($langcode != 'en' || locale_translate_english()) { + // If the language code is the active storage language, we should + // update. If it is English, we should only update if English is also + // translatable. + $active = $this->mergeToActiveConfig($active, $processed); + $this->saveTranslationActive($name, $active); + } + } + } + return $count; + } + + /** + * Merge translation data to the active configuration data. + * + * @param array $active + * Active configuration array. + * @param array $translated + * Translated configuration array. + * @return array + * The merged array. Only items from $active will be present merged with + * alternate value items from $translated. + */ + protected function mergeToActiveConfig(array $active, array $translated) { + foreach ($translated as $key => $item) { + if (isset($active[$key])) { + if (is_array($item)) { + $active[$key] = $this->mergeToActiveConfig($active[$key], $translated[$key]); + } + else { + $active[$key] = $item; + } + } + } + return $active; + } + + /** * Read a configuration from install storage or default languages. * * @param string $name diff --git a/core/modules/locale/src/LocaleConfigSubscriber.php b/core/modules/locale/src/LocaleConfigSubscriber.php index 6c42d50..d76db9d 100644 --- a/core/modules/locale/src/LocaleConfigSubscriber.php +++ b/core/modules/locale/src/LocaleConfigSubscriber.php @@ -7,7 +7,11 @@ namespace Drupal\locale; use Drupal\Core\Config\Config; +use Drupal\Core\Config\ConfigEvents; use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\Config\ConfigInstallerEvent; +use Drupal\Core\Config\StorageInterface; +use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\TypedData\TraversableTypedDataInterface; use Drupal\language\Config\LanguageConfigOverride; use Drupal\language\Config\LanguageConfigOverrideCrudEvent; @@ -49,6 +53,13 @@ class LocaleConfigSubscriber implements EventSubscriberInterface { protected $localeConfigManager; /** + * The language manager. + * + * @var \Drupal\Core\Language\LanguageManagerInterface + */ + protected $languageManager; + + /** * Constructs a LocaleConfigSubscriber. * * @param \Drupal\locale\StringStorageInterface $string_storage @@ -58,29 +69,29 @@ class LocaleConfigSubscriber implements EventSubscriberInterface { * @param \Drupal\locale\LocaleConfigManager $locale_config_manager * The typed configuration manager. */ - public function __construct(StringStorageInterface $string_storage, ConfigFactoryInterface $config_factory, LocaleConfigManager $locale_config_manager) { + public function __construct(StringStorageInterface $string_storage, ConfigFactoryInterface $config_factory, LocaleConfigManager $locale_config_manager, LanguageManagerInterface $language_manager) { $this->stringStorage = $string_storage; $this->configFactory = $config_factory; $this->localeConfigManager = $locale_config_manager; + $this->languageManager = $language_manager; } /** * {@inheritdoc} */ public static function getSubscribedEvents() { - $events[LanguageConfigOverrideEvents::SAVE_OVERRIDE] = 'onSave'; - $events[LanguageConfigOverrideEvents::DELETE_OVERRIDE] = 'onDelete'; + $events[LanguageConfigOverrideEvents::SAVE_OVERRIDE] = 'onOverrideSave'; + $events[LanguageConfigOverrideEvents::DELETE_OVERRIDE] = 'onOverrideDelete'; return $events; } - /** * Updates the translation strings when shipped configuration is saved. * * @param \Drupal\language\Config\LanguageConfigOverrideCrudEvent $event * The language configuration event. */ - public function onSave(LanguageConfigOverrideCrudEvent $event) { + public function onOverrideSave(LanguageConfigOverrideCrudEvent $event) { // Do not mark strings as customized when community translations are being // imported. if ($this->localeConfigManager->isUpdatingConfigTranslations()) { @@ -99,7 +110,7 @@ public function onSave(LanguageConfigOverrideCrudEvent $event) { * @param \Drupal\language\Config\LanguageConfigOverrideCrudEvent $event * The language configuration event. */ - public function onDelete(LanguageConfigOverrideCrudEvent $event) { + public function onOverrideDelete(LanguageConfigOverrideCrudEvent $event) { if ($this->localeConfigManager->isUpdatingConfigTranslations()) { $callable = [$this, 'deleteTranslation']; } @@ -123,13 +134,14 @@ public function onDelete(LanguageConfigOverrideCrudEvent $event) { * A callable to apply to each translatable string of the configuration. */ protected function updateTranslationStrings(LanguageConfigOverrideCrudEvent $event, $callable) { + return; $translation_config = $event->getLanguageConfigOverride(); $name = $translation_config->getName(); // Only do anything if the configuration was shipped. if ($this->stringStorage->getLocations(['type' => 'configuration', 'name' => $name])) { $source_config = $this->configFactory->getEditable($name); - $schema = $this->localeConfigManager->get($name)->getTypedConfig(); + $schema = $this->localeConfigManager->getTranslatableDefaultConfig($name)->getTypedConfig(); $this->traverseSchema($schema, $source_config, $translation_config, $callable); } } @@ -201,7 +213,7 @@ protected function saveTranslation($source_value, $langcode, $translation_value * (optional) The translation string value. If omitted, a customized string * with the source value will be saved. * - * @see \Drupal\locale\LocaleConfigSubscriber::onDelete() + * @see \Drupal\locale\LocaleConfigSubscriber::onOverrideDelete() */ protected function saveCustomizedTranslation($source_value, $langcode, $translation_value = NULL) { if ($translation = $this->getTranslation($source_value, $langcode, TRUE)) { @@ -225,7 +237,7 @@ protected function saveCustomizedTranslation($source_value, $langcode, $translat * @param string $langcode * The language code of the translation. * - * @see \Drupal\locale\LocaleConfigSubscriber::onDelete() + * @see \Drupal\locale\LocaleConfigSubscriber::onOverrideDelete() */ protected function deleteTranslation($source_value, $langcode) { if ($translation = $this->getTranslation($source_value, $langcode, FALSE)) { diff --git a/core/modules/locale/src/LocaleTypedConfig.php b/core/modules/locale/src/LocaleTypedConfig.php deleted file mode 100644 index ca31a38..0000000 --- a/core/modules/locale/src/LocaleTypedConfig.php +++ /dev/null @@ -1,209 +0,0 @@ -langcode = $langcode; - $this->localeConfig = $locale_config; - $this->typedConfigManager = $typed_config; - $this->languageManager = $language_manager; - } - - /** - * Gets wrapped typed config object. - */ - public function getTypedConfig() { - return $this->typedConfigManager->create($this->definition, $this->value); - } - - /** - * {@inheritdoc} - */ - public function getTranslation($langcode) { - $options = array( - 'source' => $this->langcode, - 'target' => $langcode, - ); - $data = $this->getElementTranslation($this->getTypedConfig(), $options); - return $this->typedConfigManager->create($this->definition, $data); - } - - /** - * {@inheritdoc} - */ - public function language() { - return $this->languageManager->getLanguage($this->langcode); - } - - /** - * Checks whether we can translate these languages. - * - * @param string $from_langcode - * Source language code. - * @param string $to_langcode - * Destination language code. - * - * @return bool - * TRUE if this translator supports translations for these languages. - */ - protected function canTranslate($from_langcode, $to_langcode) { - if ($from_langcode == 'en') { - return TRUE; - } - return FALSE; - } - - /** - * Gets translated configuration data for a typed configuration element. - * - * @param \Drupal\Core\TypedData\TypedDataInterface $element - * Typed configuration element. - * @param array $options - * Array with translation options that must contain the keys defined in - * \Drupal\locale\LocaleTypedConfig::translateElement(). - * - * @return array - * Configuration data translated to the requested language if available, - * an empty array otherwise. - */ - protected function getElementTranslation(TypedDataInterface $element, array $options) { - $translation = array(); - if ($element instanceof TraversableTypedDataInterface) { - $translation = $this->getArrayTranslation($element, $options); - } - elseif ($this->translateElement($element, $options)) { - $translation = $element->getValue(); - } - return $translation; - } - - /** - * Gets translated configuration data for a traversable element. - * - * @param \Drupal\Core\TypedData\TraversableTypedDataInterface $element - * Typed configuration array element. - * @param array $options - * Array with translation options that must contain the keys defined in - * \Drupal\locale\LocaleTypedConfig::translateElement(). - * - * @return array - * Configuration data translated to the requested language. - */ - protected function getArrayTranslation(TraversableTypedDataInterface $element, array $options) { - $translation = array(); - foreach ($element as $key => $property) { - $value = $this->getElementTranslation($property, $options); - if (!empty($value)) { - $translation[$key] = $value; - } - } - return $translation; - } - - /** - * Translates element's value if it fits our translation criteria. - * - * For an element to be translatable by locale module it needs to be of base - * type 'string' and have 'translatable = TRUE' in the element's definition. - * Translatable elements may use these additional keys in their data - * definition: - * - 'translatable', FALSE to opt out of translation. - * - 'translation context', to define the string context. - * - * @param \Drupal\Core\TypedData\TypedDataInterface $element - * Configuration element. - * @param array $options - * Array with translation options that must contain the following keys: - * - 'source', Source language code. - * - 'target', Target language code. - * - * @return bool - * Whether the element fits the translation criteria. - */ - protected function translateElement(TypedDataInterface $element, array $options) { - if ($this->canTranslate($options['source'], $options['target'])) { - $definition = $element->getDataDefinition(); - $value = $element->getValue(); - if ($value && !empty($definition['translatable'])) { - $context = isset($definition['translation context']) ? $definition['translation context'] : ''; - if ($translation = $this->localeConfig->translateString($this->name, $options['target'], $value, $context)) { - $element->setValue($translation); - return TRUE; - } - } - } - // The element does not have a translation. - return FALSE; - } - -} diff --git a/core/modules/locale/src/Tests/LocaleConfigSubscriberTest.php b/core/modules/locale/src/Tests/LocaleConfigSubscriberTest.php index f3f7415..6b2e27d 100644 --- a/core/modules/locale/src/Tests/LocaleConfigSubscriberTest.php +++ b/core/modules/locale/src/Tests/LocaleConfigSubscriberTest.php @@ -162,7 +162,7 @@ public function testLocaleDeleteTranslation() { */ protected function setUpNoTranslation($config_name, $key, $source) { // Add a source string with the configuration name as a location. This gets - // called from locale_config_update_multiple() normally. + // called from LocaleConfigManager::updateConfigTranslations() normally. $this->localeConfigManager->translateString($config_name, $this->langcode, $source, ''); $this->languageManager ->setConfigOverrideLanguage(ConfigurableLanguage::load($this->langcode)); @@ -192,8 +192,8 @@ protected function setUpNoTranslation($config_name, $key, $source) { protected function setUpTranslation($config_name, $key, $source, $translation) { // Create source and translation strings for the configuration value and add // the configuration name as a location. This would be performed by - // locale_translate_batch_import() and locale_config_update_multiple() - // normally. + // locale_translate_batch_import() and + // LocaleConfigManager::updateConfigTranslations() normally. $source_object = $this->stringStorage->createString([ 'source' => $source, 'context' => '', @@ -256,7 +256,7 @@ protected function saveLanguageOverride($config_name, $key, $value) { */ protected function saveLocaleTranslationData($config_name, $key, $value) { $this->localeConfigManager - ->saveTranslationData($config_name, $this->langcode, [$key => $value]); + ->saveTranslationOverride($config_name, $this->langcode, [$key => $value]); $this->configFactory->reset($config_name); $this->assertConfigValue($config_name, $key, $value); @@ -308,7 +308,7 @@ protected function deleteLanguageOverride($config_name, $key, $source_value) { * from the configuration factory after the deletion. */ protected function deleteLocaleTranslationData($config_name, $key, $source_value) { - $this->localeConfigManager->deleteTranslationData($config_name, $this->langcode); + $this->localeConfigManager->deleteTranslationOverride($config_name, $this->langcode); $this->configFactory->reset($config_name); $this->assertConfigValue($config_name, $key, $source_value); diff --git a/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php b/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php index 27f120d..afd6de9 100644 --- a/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php +++ b/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php @@ -79,7 +79,7 @@ public function testConfigTranslation() { ); $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); - $wrapper = $this->container->get('locale.config.typed')->get('system.site'); + $wrapper = $this->container->get('locale.config.typed')->getTranslatableDefaultConfig('system.site'); // Get translation and check we've only got the site name. $translation = $wrapper->getTranslation($langcode); @@ -109,7 +109,7 @@ public function testConfigTranslation() { ); $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); - $wrapper = $this->container->get('locale.config.typed')->get('core.date_format.medium'); + $wrapper = $this->container->get('locale.config.typed')->getTranslatableDefaultConfig('core.date_format.medium'); // Get translation and check we've only got the site name. $translation = $wrapper->getTranslation($langcode); @@ -162,7 +162,7 @@ public function testConfigTranslation() { $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. - $wrapper = $this->container->get('locale.config.typed')->get('image.style.medium'); + $wrapper = $this->container->get('locale.config.typed')->getTranslatableDefaultConfig('image.style.medium'); $translation = $wrapper->getTranslation($langcode); $property = $translation->get('label');