class LocaleConfigSubscriber
Same name in other branches
- 9 core/modules/locale/src/LocaleConfigSubscriber.php \Drupal\locale\LocaleConfigSubscriber
- 10 core/modules/locale/src/LocaleConfigSubscriber.php \Drupal\locale\LocaleConfigSubscriber
- 11.x core/modules/locale/src/LocaleConfigSubscriber.php \Drupal\locale\LocaleConfigSubscriber
Updates strings translation when configuration translations change.
This reacts to the updates of translated active configuration and configuration language overrides. When those updates involve configuration which was available as default configuration, we need to feed back changes to any item which was originally part of that configuration to the interface translation storage. Those updated translations are saved as customized, so further community translation updates will not undo user changes.
This subscriber does not respond to deleting active configuration or deleting configuration translations. The locale storage is additive and we cannot be sure that only a given configuration translation used a source string. So we should not remove the translations from locale storage in these cases. The configuration or override would itself be deleted either way.
By design locale module only deals with sources in English.
Hierarchy
- class \Drupal\locale\LocaleConfigSubscriber implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
Expanded class hierarchy of LocaleConfigSubscriber
See also
\Drupal\locale\LocaleConfigManager
1 string reference to 'LocaleConfigSubscriber'
- locale.services.yml in core/
modules/ locale/ locale.services.yml - core/modules/locale/locale.services.yml
1 service uses LocaleConfigSubscriber
- locale.config_subscriber in core/
modules/ locale/ locale.services.yml - Drupal\locale\LocaleConfigSubscriber
File
-
core/
modules/ locale/ src/ LocaleConfigSubscriber.php, line 34
Namespace
Drupal\localeView source
class LocaleConfigSubscriber implements EventSubscriberInterface {
/**
* The configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The typed configuration manager.
*
* @var \Drupal\locale\LocaleConfigManager
*/
protected $localeConfigManager;
/**
* Constructs a LocaleConfigSubscriber.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory.
* @param \Drupal\locale\LocaleConfigManager $locale_config_manager
* The typed configuration manager.
*/
public function __construct(ConfigFactoryInterface $config_factory, LocaleConfigManager $locale_config_manager) {
$this->configFactory = $config_factory;
$this->localeConfigManager = $locale_config_manager;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[LanguageConfigOverrideEvents::SAVE_OVERRIDE] = 'onOverrideChange';
$events[LanguageConfigOverrideEvents::DELETE_OVERRIDE] = 'onOverrideChange';
$events[ConfigEvents::SAVE] = 'onConfigSave';
return $events;
}
/**
* Updates the locale strings when a translated active configuration is saved.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
* The configuration event.
*/
public function onConfigSave(ConfigCrudEvent $event) {
// Only attempt to feed back configuration translation changes to locale if
// the update itself was not initiated by locale data changes.
if (!InstallerKernel::installationAttempted() && !$this->localeConfigManager
->isUpdatingTranslationsFromLocale()) {
$config = $event->getConfig();
$langcode = $config->get('langcode') ?: 'en';
$this->updateLocaleStorage($config, $langcode);
}
}
/**
* Updates the locale strings when a configuration override is saved/deleted.
*
* @param \Drupal\language\Config\LanguageConfigOverrideCrudEvent $event
* The language configuration event.
*/
public function onOverrideChange(LanguageConfigOverrideCrudEvent $event) {
// Only attempt to feed back configuration override changes to locale if
// the update itself was not initiated by locale data changes.
if (!InstallerKernel::installationAttempted() && !$this->localeConfigManager
->isUpdatingTranslationsFromLocale()) {
$translation_config = $event->getLanguageConfigOverride();
$langcode = $translation_config->getLangcode();
$reference_config = $this->configFactory
->getEditable($translation_config->getName())
->get();
$this->updateLocaleStorage($translation_config, $langcode, $reference_config);
}
}
/**
* Update locale storage based on configuration translations.
*
* @param \Drupal\Core\Config\StorableConfigBase $config
* Active configuration or configuration translation override.
* @param string $langcode
* The language code of $config.
* @param array $reference_config
* (Optional) Reference configuration to check against if $config was an
* override. This allows us to update locale keys for data not in the
* override but still in the active configuration.
*/
protected function updateLocaleStorage(StorableConfigBase $config, $langcode, array $reference_config = []) {
$name = $config->getName();
if ($this->localeConfigManager
->isSupported($name) && locale_is_translatable($langcode)) {
$translatables = $this->localeConfigManager
->getTranslatableDefaultConfig($name);
$this->processTranslatableData($name, $config->get(), $translatables, $langcode, $reference_config);
}
}
/**
* Process the translatable data array with a given language.
*
* @param string $name
* The configuration name.
* @param array $config
* The active configuration data or override data.
* @param array|\Drupal\Core\StringTranslation\TranslatableMarkup[] $translatable
* The translatable array structure.
* @see \Drupal\locale\LocaleConfigManager::getTranslatableData()
* @param string $langcode
* The language code to process the array with.
* @param array $reference_config
* (Optional) Reference configuration to check against if $config was an
* override. This allows us to update locale keys for data not in the
* override but still in the active configuration.
*/
protected function processTranslatableData($name, array $config, array $translatable, $langcode, array $reference_config = []) {
foreach ($translatable as $key => $item) {
if (!isset($config[$key])) {
if (isset($reference_config[$key])) {
$this->resetExistingTranslations($name, $translatable[$key], $reference_config[$key], $langcode);
}
continue;
}
if (is_array($item)) {
$reference_config_item = isset($reference_config[$key]) ? $reference_config[$key] : [];
$this->processTranslatableData($name, $config[$key], $item, $langcode, $reference_config_item);
}
else {
$this->saveCustomizedTranslation($name, $item->getUntranslatedString(), $item->getOption('context'), $config[$key], $langcode);
}
}
}
/**
* Reset existing locale translations to their source values.
*
* Goes through $translatable to reset any existing translations to the source
* string, so prior translations would not reappear in the configuration.
*
* @param string $name
* The configuration name.
* @param array|\Drupal\Core\StringTranslation\TranslatableMarkup $translatable
* Either a possibly nested array with TranslatableMarkup objects at the
* leaf items or a TranslatableMarkup object directly.
* @param array|string $reference_config
* Either a possibly nested array with strings at the leaf items or a string
* directly. Only those $translatable items that are also present in
* $reference_config will get translations reset.
* @param string $langcode
* The language code of the translation being processed.
*/
protected function resetExistingTranslations($name, $translatable, $reference_config, $langcode) {
if (is_array($translatable)) {
foreach ($translatable as $key => $item) {
if (isset($reference_config[$key])) {
// Process further if the key still exists in the reference active
// configuration and the default translation but not the current
// configuration override.
$this->resetExistingTranslations($name, $item, $reference_config[$key], $langcode);
}
}
}
elseif (!is_array($reference_config)) {
$this->saveCustomizedTranslation($name, $translatable->getUntranslatedString(), $translatable->getOption('context'), $reference_config, $langcode);
}
}
/**
* Saves a translation string and marks it as customized.
*
* @param string $name
* The configuration name.
* @param string $source
* The source string value.
* @param string $context
* The source string context.
* @param string $new_translation
* The translation string.
* @param string $langcode
* The language code of the translation.
*/
protected function saveCustomizedTranslation($name, $source, $context, $new_translation, $langcode) {
$locale_translation = $this->localeConfigManager
->getStringTranslation($name, $langcode, $source, $context);
if (!empty($locale_translation)) {
// Save this translation as custom if it was a new translation and not the
// same as the source. (The interface prefills translation values with the
// source). Or if there was an existing (non-empty) translation and the
// user changed it (even if it was changed back to the original value).
// Otherwise the translation file would be overwritten with the locale
// copy again later.
$existing_translation = $locale_translation->getString();
if ($locale_translation->isNew() && $source != $new_translation || !$locale_translation->isNew() && (empty($existing_translation) && $source != $new_translation || !empty($existing_translation) && $new_translation != $existing_translation)) {
$locale_translation->setString($new_translation)
->setCustomized(TRUE)
->save();
}
}
}
}
Members
Title Sort descending | Modifiers | Object type | Summary |
---|---|---|---|
LocaleConfigSubscriber::$configFactory | protected | property | The configuration factory. |
LocaleConfigSubscriber::$localeConfigManager | protected | property | The typed configuration manager. |
LocaleConfigSubscriber::getSubscribedEvents | public static | function | |
LocaleConfigSubscriber::onConfigSave | public | function | Updates the locale strings when a translated active configuration is saved. |
LocaleConfigSubscriber::onOverrideChange | public | function | Updates the locale strings when a configuration override is saved/deleted. |
LocaleConfigSubscriber::processTranslatableData | protected | function | Process the translatable data array with a given language. |
LocaleConfigSubscriber::resetExistingTranslations | protected | function | Reset existing locale translations to their source values. |
LocaleConfigSubscriber::saveCustomizedTranslation | protected | function | Saves a translation string and marks it as customized. |
LocaleConfigSubscriber::updateLocaleStorage | protected | function | Update locale storage based on configuration translations. |
LocaleConfigSubscriber::__construct | public | function | Constructs a LocaleConfigSubscriber. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.