Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 66 |
LocaleConfigSubscriber | |
0.00% |
0 / 1 |
|
0.00% |
0 / 8 |
1056 | |
0.00% |
0 / 66 |
__construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
getSubscribedEvents | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
onConfigSave | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 6 |
|||
onOverrideChange | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 7 |
|||
updateLocaleStorage | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 6 |
|||
processTranslatableData | |
0.00% |
0 / 1 |
42 | |
0.00% |
0 / 16 |
|||
resetExistingTranslations | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 11 |
|||
saveCustomizedTranslation | |
0.00% |
0 / 1 |
90 | |
0.00% |
0 / 12 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\locale\LocaleConfigSubscriber. | |
*/ | |
namespace Drupal\locale; | |
use Drupal\Core\Config\ConfigCrudEvent; | |
use Drupal\Core\Config\ConfigEvents; | |
use Drupal\Core\Config\ConfigFactoryInterface; | |
use Drupal\Core\Config\StorableConfigBase; | |
use Drupal\language\Config\LanguageConfigOverrideCrudEvent; | |
use Drupal\language\Config\LanguageConfigOverrideEvents; | |
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
/** | |
* 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. | |
* | |
* @see \Drupal\locale\LocaleConfigManager | |
*/ | |
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 (!drupal_installation_attempted() && !$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 (!drupal_installation_attempted() && !$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 = array()) { | |
$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 = array()) { | |
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 = isset($reference_config[$key]) ? $reference_config[$key] : array(); | |
$this->processTranslatableData($name, $config[$key], $item, $langcode, $reference_config); | |
} | |
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(); | |
} | |
} | |
} | |
} |