Mercurial > hg > isophonics-drupal-site
comparison core/modules/locale/src/LocaleConfigSubscriber.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\locale; | |
4 | |
5 use Drupal\Core\Config\ConfigCrudEvent; | |
6 use Drupal\Core\Config\ConfigEvents; | |
7 use Drupal\Core\Config\ConfigFactoryInterface; | |
8 use Drupal\Core\Config\StorableConfigBase; | |
9 use Drupal\language\Config\LanguageConfigOverrideCrudEvent; | |
10 use Drupal\language\Config\LanguageConfigOverrideEvents; | |
11 use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
12 | |
13 /** | |
14 * Updates strings translation when configuration translations change. | |
15 * | |
16 * This reacts to the updates of translated active configuration and | |
17 * configuration language overrides. When those updates involve configuration | |
18 * which was available as default configuration, we need to feed back changes | |
19 * to any item which was originally part of that configuration to the interface | |
20 * translation storage. Those updated translations are saved as customized, so | |
21 * further community translation updates will not undo user changes. | |
22 * | |
23 * This subscriber does not respond to deleting active configuration or deleting | |
24 * configuration translations. The locale storage is additive and we cannot be | |
25 * sure that only a given configuration translation used a source string. So | |
26 * we should not remove the translations from locale storage in these cases. The | |
27 * configuration or override would itself be deleted either way. | |
28 * | |
29 * By design locale module only deals with sources in English. | |
30 * | |
31 * @see \Drupal\locale\LocaleConfigManager | |
32 */ | |
33 class LocaleConfigSubscriber implements EventSubscriberInterface { | |
34 | |
35 /** | |
36 * The configuration factory. | |
37 * | |
38 * @var \Drupal\Core\Config\ConfigFactoryInterface | |
39 */ | |
40 protected $configFactory; | |
41 | |
42 /** | |
43 * The typed configuration manager. | |
44 * | |
45 * @var \Drupal\locale\LocaleConfigManager | |
46 */ | |
47 protected $localeConfigManager; | |
48 | |
49 /** | |
50 * Constructs a LocaleConfigSubscriber. | |
51 * | |
52 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory | |
53 * The configuration factory. | |
54 * @param \Drupal\locale\LocaleConfigManager $locale_config_manager | |
55 * The typed configuration manager. | |
56 */ | |
57 public function __construct(ConfigFactoryInterface $config_factory, LocaleConfigManager $locale_config_manager) { | |
58 $this->configFactory = $config_factory; | |
59 $this->localeConfigManager = $locale_config_manager; | |
60 } | |
61 | |
62 /** | |
63 * {@inheritdoc} | |
64 */ | |
65 public static function getSubscribedEvents() { | |
66 $events[LanguageConfigOverrideEvents::SAVE_OVERRIDE] = 'onOverrideChange'; | |
67 $events[LanguageConfigOverrideEvents::DELETE_OVERRIDE] = 'onOverrideChange'; | |
68 $events[ConfigEvents::SAVE] = 'onConfigSave'; | |
69 return $events; | |
70 } | |
71 | |
72 /** | |
73 * Updates the locale strings when a translated active configuration is saved. | |
74 * | |
75 * @param \Drupal\Core\Config\ConfigCrudEvent $event | |
76 * The configuration event. | |
77 */ | |
78 public function onConfigSave(ConfigCrudEvent $event) { | |
79 // Only attempt to feed back configuration translation changes to locale if | |
80 // the update itself was not initiated by locale data changes. | |
81 if (!drupal_installation_attempted() && !$this->localeConfigManager->isUpdatingTranslationsFromLocale()) { | |
82 $config = $event->getConfig(); | |
83 $langcode = $config->get('langcode') ?: 'en'; | |
84 $this->updateLocaleStorage($config, $langcode); | |
85 } | |
86 } | |
87 | |
88 /** | |
89 * Updates the locale strings when a configuration override is saved/deleted. | |
90 * | |
91 * @param \Drupal\language\Config\LanguageConfigOverrideCrudEvent $event | |
92 * The language configuration event. | |
93 */ | |
94 public function onOverrideChange(LanguageConfigOverrideCrudEvent $event) { | |
95 // Only attempt to feed back configuration override changes to locale if | |
96 // the update itself was not initiated by locale data changes. | |
97 if (!drupal_installation_attempted() && !$this->localeConfigManager->isUpdatingTranslationsFromLocale()) { | |
98 $translation_config = $event->getLanguageConfigOverride(); | |
99 $langcode = $translation_config->getLangcode(); | |
100 $reference_config = $this->configFactory->getEditable($translation_config->getName())->get(); | |
101 $this->updateLocaleStorage($translation_config, $langcode, $reference_config); | |
102 } | |
103 } | |
104 | |
105 /** | |
106 * Update locale storage based on configuration translations. | |
107 * | |
108 * @param \Drupal\Core\Config\StorableConfigBase $config | |
109 * Active configuration or configuration translation override. | |
110 * @param string $langcode | |
111 * The language code of $config. | |
112 * @param array $reference_config | |
113 * (Optional) Reference configuration to check against if $config was an | |
114 * override. This allows us to update locale keys for data not in the | |
115 * override but still in the active configuration. | |
116 */ | |
117 protected function updateLocaleStorage(StorableConfigBase $config, $langcode, array $reference_config = []) { | |
118 $name = $config->getName(); | |
119 if ($this->localeConfigManager->isSupported($name) && locale_is_translatable($langcode)) { | |
120 $translatables = $this->localeConfigManager->getTranslatableDefaultConfig($name); | |
121 $this->processTranslatableData($name, $config->get(), $translatables, $langcode, $reference_config); | |
122 } | |
123 } | |
124 | |
125 /** | |
126 * Process the translatable data array with a given language. | |
127 * | |
128 * @param string $name | |
129 * The configuration name. | |
130 * @param array $config | |
131 * The active configuration data or override data. | |
132 * @param array|\Drupal\Core\StringTranslation\TranslatableMarkup[] $translatable | |
133 * The translatable array structure. | |
134 * @see \Drupal\locale\LocaleConfigManager::getTranslatableData() | |
135 * @param string $langcode | |
136 * The language code to process the array with. | |
137 * @param array $reference_config | |
138 * (Optional) Reference configuration to check against if $config was an | |
139 * override. This allows us to update locale keys for data not in the | |
140 * override but still in the active configuration. | |
141 */ | |
142 protected function processTranslatableData($name, array $config, array $translatable, $langcode, array $reference_config = []) { | |
143 foreach ($translatable as $key => $item) { | |
144 if (!isset($config[$key])) { | |
145 if (isset($reference_config[$key])) { | |
146 $this->resetExistingTranslations($name, $translatable[$key], $reference_config[$key], $langcode); | |
147 } | |
148 continue; | |
149 } | |
150 if (is_array($item)) { | |
151 $reference_config = isset($reference_config[$key]) ? $reference_config[$key] : []; | |
152 $this->processTranslatableData($name, $config[$key], $item, $langcode, $reference_config); | |
153 } | |
154 else { | |
155 $this->saveCustomizedTranslation($name, $item->getUntranslatedString(), $item->getOption('context'), $config[$key], $langcode); | |
156 } | |
157 } | |
158 } | |
159 | |
160 /** | |
161 * Reset existing locale translations to their source values. | |
162 * | |
163 * Goes through $translatable to reset any existing translations to the source | |
164 * string, so prior translations would not reappear in the configuration. | |
165 * | |
166 * @param string $name | |
167 * The configuration name. | |
168 * @param array|\Drupal\Core\StringTranslation\TranslatableMarkup $translatable | |
169 * Either a possibly nested array with TranslatableMarkup objects at the | |
170 * leaf items or a TranslatableMarkup object directly. | |
171 * @param array|string $reference_config | |
172 * Either a possibly nested array with strings at the leaf items or a string | |
173 * directly. Only those $translatable items that are also present in | |
174 * $reference_config will get translations reset. | |
175 * @param string $langcode | |
176 * The language code of the translation being processed. | |
177 */ | |
178 protected function resetExistingTranslations($name, $translatable, $reference_config, $langcode) { | |
179 if (is_array($translatable)) { | |
180 foreach ($translatable as $key => $item) { | |
181 if (isset($reference_config[$key])) { | |
182 // Process further if the key still exists in the reference active | |
183 // configuration and the default translation but not the current | |
184 // configuration override. | |
185 $this->resetExistingTranslations($name, $item, $reference_config[$key], $langcode); | |
186 } | |
187 } | |
188 } | |
189 elseif (!is_array($reference_config)) { | |
190 $this->saveCustomizedTranslation($name, $translatable->getUntranslatedString(), $translatable->getOption('context'), $reference_config, $langcode); | |
191 } | |
192 } | |
193 | |
194 /** | |
195 * Saves a translation string and marks it as customized. | |
196 * | |
197 * @param string $name | |
198 * The configuration name. | |
199 * @param string $source | |
200 * The source string value. | |
201 * @param string $context | |
202 * The source string context. | |
203 * @param string $new_translation | |
204 * The translation string. | |
205 * @param string $langcode | |
206 * The language code of the translation. | |
207 */ | |
208 protected function saveCustomizedTranslation($name, $source, $context, $new_translation, $langcode) { | |
209 $locale_translation = $this->localeConfigManager->getStringTranslation($name, $langcode, $source, $context); | |
210 if (!empty($locale_translation)) { | |
211 // Save this translation as custom if it was a new translation and not the | |
212 // same as the source. (The interface prefills translation values with the | |
213 // source). Or if there was an existing (non-empty) translation and the | |
214 // user changed it (even if it was changed back to the original value). | |
215 // Otherwise the translation file would be overwritten with the locale | |
216 // copy again later. | |
217 $existing_translation = $locale_translation->getString(); | |
218 if (($locale_translation->isNew() && $source != $new_translation) || | |
219 (!$locale_translation->isNew() && ((empty($existing_translation) && $source != $new_translation) || ((!empty($existing_translation) && $new_translation != $existing_translation))))) { | |
220 $locale_translation | |
221 ->setString($new_translation) | |
222 ->setCustomized(TRUE) | |
223 ->save(); | |
224 } | |
225 } | |
226 } | |
227 | |
228 } |