Chris@0: configFactory = $config_factory; Chris@0: $this->localeConfigManager = $locale_config_manager; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public static function getSubscribedEvents() { Chris@0: $events[LanguageConfigOverrideEvents::SAVE_OVERRIDE] = 'onOverrideChange'; Chris@0: $events[LanguageConfigOverrideEvents::DELETE_OVERRIDE] = 'onOverrideChange'; Chris@0: $events[ConfigEvents::SAVE] = 'onConfigSave'; Chris@0: return $events; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Updates the locale strings when a translated active configuration is saved. Chris@0: * Chris@0: * @param \Drupal\Core\Config\ConfigCrudEvent $event Chris@0: * The configuration event. Chris@0: */ Chris@0: public function onConfigSave(ConfigCrudEvent $event) { Chris@0: // Only attempt to feed back configuration translation changes to locale if Chris@0: // the update itself was not initiated by locale data changes. Chris@0: if (!drupal_installation_attempted() && !$this->localeConfigManager->isUpdatingTranslationsFromLocale()) { Chris@0: $config = $event->getConfig(); Chris@0: $langcode = $config->get('langcode') ?: 'en'; Chris@0: $this->updateLocaleStorage($config, $langcode); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Updates the locale strings when a configuration override is saved/deleted. Chris@0: * Chris@0: * @param \Drupal\language\Config\LanguageConfigOverrideCrudEvent $event Chris@0: * The language configuration event. Chris@0: */ Chris@0: public function onOverrideChange(LanguageConfigOverrideCrudEvent $event) { Chris@0: // Only attempt to feed back configuration override changes to locale if Chris@0: // the update itself was not initiated by locale data changes. Chris@0: if (!drupal_installation_attempted() && !$this->localeConfigManager->isUpdatingTranslationsFromLocale()) { Chris@0: $translation_config = $event->getLanguageConfigOverride(); Chris@0: $langcode = $translation_config->getLangcode(); Chris@0: $reference_config = $this->configFactory->getEditable($translation_config->getName())->get(); Chris@0: $this->updateLocaleStorage($translation_config, $langcode, $reference_config); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Update locale storage based on configuration translations. Chris@0: * Chris@0: * @param \Drupal\Core\Config\StorableConfigBase $config Chris@0: * Active configuration or configuration translation override. Chris@0: * @param string $langcode Chris@0: * The language code of $config. Chris@0: * @param array $reference_config Chris@0: * (Optional) Reference configuration to check against if $config was an Chris@0: * override. This allows us to update locale keys for data not in the Chris@0: * override but still in the active configuration. Chris@0: */ Chris@0: protected function updateLocaleStorage(StorableConfigBase $config, $langcode, array $reference_config = []) { Chris@0: $name = $config->getName(); Chris@0: if ($this->localeConfigManager->isSupported($name) && locale_is_translatable($langcode)) { Chris@0: $translatables = $this->localeConfigManager->getTranslatableDefaultConfig($name); Chris@0: $this->processTranslatableData($name, $config->get(), $translatables, $langcode, $reference_config); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Process the translatable data array with a given language. Chris@0: * Chris@0: * @param string $name Chris@0: * The configuration name. Chris@0: * @param array $config Chris@0: * The active configuration data or override data. Chris@0: * @param array|\Drupal\Core\StringTranslation\TranslatableMarkup[] $translatable Chris@0: * The translatable array structure. Chris@0: * @see \Drupal\locale\LocaleConfigManager::getTranslatableData() Chris@0: * @param string $langcode Chris@0: * The language code to process the array with. Chris@0: * @param array $reference_config Chris@0: * (Optional) Reference configuration to check against if $config was an Chris@0: * override. This allows us to update locale keys for data not in the Chris@0: * override but still in the active configuration. Chris@0: */ Chris@0: protected function processTranslatableData($name, array $config, array $translatable, $langcode, array $reference_config = []) { Chris@0: foreach ($translatable as $key => $item) { Chris@0: if (!isset($config[$key])) { Chris@0: if (isset($reference_config[$key])) { Chris@0: $this->resetExistingTranslations($name, $translatable[$key], $reference_config[$key], $langcode); Chris@0: } Chris@0: continue; Chris@0: } Chris@0: if (is_array($item)) { Chris@0: $reference_config = isset($reference_config[$key]) ? $reference_config[$key] : []; Chris@0: $this->processTranslatableData($name, $config[$key], $item, $langcode, $reference_config); Chris@0: } Chris@0: else { Chris@0: $this->saveCustomizedTranslation($name, $item->getUntranslatedString(), $item->getOption('context'), $config[$key], $langcode); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Reset existing locale translations to their source values. Chris@0: * Chris@0: * Goes through $translatable to reset any existing translations to the source Chris@0: * string, so prior translations would not reappear in the configuration. Chris@0: * Chris@0: * @param string $name Chris@0: * The configuration name. Chris@0: * @param array|\Drupal\Core\StringTranslation\TranslatableMarkup $translatable Chris@0: * Either a possibly nested array with TranslatableMarkup objects at the Chris@0: * leaf items or a TranslatableMarkup object directly. Chris@0: * @param array|string $reference_config Chris@0: * Either a possibly nested array with strings at the leaf items or a string Chris@0: * directly. Only those $translatable items that are also present in Chris@0: * $reference_config will get translations reset. Chris@0: * @param string $langcode Chris@0: * The language code of the translation being processed. Chris@0: */ Chris@0: protected function resetExistingTranslations($name, $translatable, $reference_config, $langcode) { Chris@0: if (is_array($translatable)) { Chris@0: foreach ($translatable as $key => $item) { Chris@0: if (isset($reference_config[$key])) { Chris@0: // Process further if the key still exists in the reference active Chris@0: // configuration and the default translation but not the current Chris@0: // configuration override. Chris@0: $this->resetExistingTranslations($name, $item, $reference_config[$key], $langcode); Chris@0: } Chris@0: } Chris@0: } Chris@0: elseif (!is_array($reference_config)) { Chris@0: $this->saveCustomizedTranslation($name, $translatable->getUntranslatedString(), $translatable->getOption('context'), $reference_config, $langcode); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Saves a translation string and marks it as customized. Chris@0: * Chris@0: * @param string $name Chris@0: * The configuration name. Chris@0: * @param string $source Chris@0: * The source string value. Chris@0: * @param string $context Chris@0: * The source string context. Chris@0: * @param string $new_translation Chris@0: * The translation string. Chris@0: * @param string $langcode Chris@0: * The language code of the translation. Chris@0: */ Chris@0: protected function saveCustomizedTranslation($name, $source, $context, $new_translation, $langcode) { Chris@0: $locale_translation = $this->localeConfigManager->getStringTranslation($name, $langcode, $source, $context); Chris@0: if (!empty($locale_translation)) { Chris@0: // Save this translation as custom if it was a new translation and not the Chris@0: // same as the source. (The interface prefills translation values with the Chris@0: // source). Or if there was an existing (non-empty) translation and the Chris@0: // user changed it (even if it was changed back to the original value). Chris@0: // Otherwise the translation file would be overwritten with the locale Chris@0: // copy again later. Chris@0: $existing_translation = $locale_translation->getString(); Chris@0: if (($locale_translation->isNew() && $source != $new_translation) || Chris@0: (!$locale_translation->isNew() && ((empty($existing_translation) && $source != $new_translation) || ((!empty($existing_translation) && $new_translation != $existing_translation))))) { Chris@0: $locale_translation Chris@0: ->setString($new_translation) Chris@0: ->setCustomized(TRUE) Chris@0: ->save(); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: }