3 namespace Drupal\Tests\locale\Kernel;
5 use Drupal\language\Entity\ConfigurableLanguage;
6 use Drupal\locale\Locale;
7 use Drupal\locale\StringInterface;
8 use Drupal\locale\TranslationString;
9 use Drupal\KernelTests\KernelTestBase;
12 * Tests that shipped configuration translations are updated correctly.
16 class LocaleConfigSubscriberTest extends KernelTestBase {
21 public static $modules = ['language', 'locale', 'system', 'locale_test'];
24 * The configurable language manager used in this test.
26 * @var \Drupal\language\ConfigurableLanguageManagerInterface
28 protected $languageManager;
31 * The configuration factory used in this test.
33 * @var \Drupal\Core\Config\ConfigFactoryInterface
35 protected $configFactory;
38 * The string storage used in this test.
40 * @var \Drupal\locale\StringStorageInterface;
42 protected $stringStorage;
45 * The locale configuration manager used in this test.
47 * @var \Drupal\locale\LocaleConfigManager
49 protected $localeConfigManager;
54 protected function setUp() {
57 $this->setUpDefaultLanguage();
59 $this->installSchema('locale', ['locales_source', 'locales_target', 'locales_location']);
61 $this->setupLanguages();
63 $this->installConfig(['locale_test']);
64 // Simulate this hook invoked which would happen if in a non-kernel test
65 // or normal environment.
66 // @see locale_modules_installed()
67 // @see locale_system_update()
68 locale_system_set_config_langcodes();
69 $langcodes = array_keys(\Drupal::languageManager()->getLanguages());
70 $names = Locale::config()->getComponentNames();
71 Locale::config()->updateConfigTranslations($names, $langcodes);
73 $this->configFactory = $this->container->get('config.factory');
74 $this->stringStorage = $this->container->get('locale.storage');
75 $this->localeConfigManager = $this->container->get('locale.config_manager');
76 $this->languageManager = $this->container->get('language_manager');
82 * Sets up default language for this test.
84 protected function setUpDefaultLanguage() {
85 // Keep the default English.
89 * Sets up languages needed for this test.
91 protected function setUpLanguages() {
92 ConfigurableLanguage::createFromLangcode('de')->save();
96 * Sets up the locale storage strings to be in line with configuration.
98 protected function setUpLocale() {
99 // Set up the locale database the same way we have in the config samples.
100 $this->setUpNoTranslation('locale_test.no_translation', 'test', 'Test', 'de');
101 $this->setUpTranslation('locale_test.translation', 'test', 'English test', 'German test', 'de');
105 * Tests creating translations of shipped configuration.
107 public function testCreateTranslation() {
108 $config_name = 'locale_test.no_translation';
110 $this->saveLanguageOverride($config_name, 'test', 'Test (German)', 'de');
111 $this->assertTranslation($config_name, 'Test (German)', 'de');
115 * Tests importing community translations of shipped configuration.
117 public function testLocaleCreateTranslation() {
118 $config_name = 'locale_test.no_translation';
120 $this->saveLocaleTranslationData($config_name, 'test', 'Test', 'Test (German)', 'de');
121 $this->assertTranslation($config_name, 'Test (German)', 'de', FALSE);
125 * Tests updating translations of shipped configuration.
127 public function testUpdateTranslation() {
128 $config_name = 'locale_test.translation';
130 $this->saveLanguageOverride($config_name, 'test', 'Updated German test', 'de');
131 $this->assertTranslation($config_name, 'Updated German test', 'de');
135 * Tests updating community translations of shipped configuration.
137 public function testLocaleUpdateTranslation() {
138 $config_name = 'locale_test.translation';
140 $this->saveLocaleTranslationData($config_name, 'test', 'English test', 'Updated German test', 'de');
141 $this->assertTranslation($config_name, 'Updated German test', 'de', FALSE);
145 * Tests deleting translations of shipped configuration.
147 public function testDeleteTranslation() {
148 $config_name = 'locale_test.translation';
150 $this->deleteLanguageOverride($config_name, 'test', 'English test', 'de');
151 // Instead of deleting the translation, we need to keep a translation with
152 // the source value and mark it as customized to prevent the deletion being
153 // reverted by importing community translations.
154 $this->assertTranslation($config_name, 'English test', 'de');
158 * Tests deleting community translations of shipped configuration.
160 public function testLocaleDeleteTranslation() {
161 $config_name = 'locale_test.translation';
163 $this->deleteLocaleTranslationData($config_name, 'test', 'English test', 'de');
164 $this->assertNoTranslation($config_name, 'de');
168 * Sets up a configuration string without a translation.
170 * The actual configuration is already available by installing locale_test
171 * module, as it is done in LocaleConfigSubscriberTest::setUp(). This sets up
172 * the necessary source string and verifies that everything is as expected to
173 * avoid false positives.
175 * @param string $config_name
176 * The configuration name.
178 * The configuration key.
179 * @param string $source
181 * @param string $langcode
184 protected function setUpNoTranslation($config_name, $key, $source, $langcode) {
185 $this->localeConfigManager->updateConfigTranslations([$config_name], [$langcode]);
186 $this->assertNoConfigOverride($config_name, $key, $source, $langcode);
187 $this->assertNoTranslation($config_name, $langcode);
192 * Sets up a configuration string with a translation.
194 * The actual configuration is already available by installing locale_test
195 * module, as it is done in LocaleConfigSubscriberTest::setUp(). This sets up
196 * the necessary source and translation strings and verifies that everything
197 * is as expected to avoid false positives.
199 * @param string $config_name
200 * The configuration name.
202 * The configuration key.
203 * @param string $source
205 * @param string $translation
206 * The translation string.
207 * @param string $langcode
209 * @param bool $is_active
210 * Whether the update will affect the active configuration.
212 protected function setUpTranslation($config_name, $key, $source, $translation, $langcode, $is_active = FALSE) {
213 // Create source and translation strings for the configuration value and add
214 // the configuration name as a location. This would be performed by
215 // locale_translate_batch_import() invoking
216 // LocaleConfigManager::updateConfigTranslations() normally.
217 $this->localeConfigManager->reset();
218 $this->localeConfigManager
219 ->getStringTranslation($config_name, $langcode, $source, '')
220 ->setString($translation)
221 ->setCustomized(FALSE)
223 $this->configFactory->reset($config_name);
224 $this->localeConfigManager->reset();
225 $this->localeConfigManager->updateConfigTranslations([$config_name], [$langcode]);
228 $this->assertActiveConfig($config_name, $key, $translation, $langcode);
231 $this->assertConfigOverride($config_name, $key, $translation, $langcode);
233 $this->assertTranslation($config_name, $translation, $langcode, FALSE);
237 * Saves a language override.
239 * This will invoke LocaleConfigSubscriber through the event dispatcher. To
240 * make sure the configuration was persisted correctly, the configuration
241 * value is checked. Because LocaleConfigSubscriber temporarily disables the
242 * override state of the configuration factory we check that the correct value
243 * is restored afterwards.
245 * @param string $config_name
246 * The configuration name.
248 * The configuration key.
249 * @param string $value
250 * The configuration value to save.
251 * @param string $langcode
254 protected function saveLanguageOverride($config_name, $key, $value, $langcode) {
255 $translation_override = $this->languageManager
256 ->getLanguageConfigOverride($langcode, $config_name);
257 $translation_override
260 $this->configFactory->reset($config_name);
262 $this->assertConfigOverride($config_name, $key, $value, $langcode);
266 * Saves translation data from locale module.
268 * This will invoke LocaleConfigSubscriber through the event dispatcher. To
269 * make sure the configuration was persisted correctly, the configuration
270 * value is checked. Because LocaleConfigSubscriber temporarily disables the
271 * override state of the configuration factory we check that the correct value
272 * is restored afterwards.
274 * @param string $config_name
275 * The configuration name.
277 * The configuration key.
278 * @param string $source
280 * @param string $translation
281 * The translation string to save.
282 * @param string $langcode
284 * @param bool $is_active
285 * Whether the update will affect the active configuration.
287 protected function saveLocaleTranslationData($config_name, $key, $source, $translation, $langcode, $is_active = FALSE) {
288 $this->localeConfigManager->reset();
289 $this->localeConfigManager
290 ->getStringTranslation($config_name, $langcode, $source, '')
291 ->setString($translation)
293 $this->localeConfigManager->reset();
294 $this->localeConfigManager->updateConfigTranslations([$config_name], [$langcode]);
295 $this->configFactory->reset($config_name);
298 $this->assertActiveConfig($config_name, $key, $translation, $langcode);
301 $this->assertConfigOverride($config_name, $key, $translation, $langcode);
306 * Deletes a language override.
308 * This will invoke LocaleConfigSubscriber through the event dispatcher. To
309 * make sure the configuration was persisted correctly, the configuration
310 * value is checked. Because LocaleConfigSubscriber temporarily disables the
311 * override state of the configuration factory we check that the correct value
312 * is restored afterwards.
314 * @param string $config_name
315 * The configuration name.
317 * The configuration key.
318 * @param string $source_value
319 * The source configuration value to verify the correct value is returned
320 * from the configuration factory after the deletion.
321 * @param string $langcode
324 protected function deleteLanguageOverride($config_name, $key, $source_value, $langcode) {
325 $translation_override = $this->languageManager
326 ->getLanguageConfigOverride($langcode, $config_name);
327 $translation_override
330 $this->configFactory->reset($config_name);
332 $this->assertNoConfigOverride($config_name, $key, $source_value, $langcode);
336 * Deletes translation data from locale module.
338 * This will invoke LocaleConfigSubscriber through the event dispatcher. To
339 * make sure the configuration was persisted correctly, the configuration
340 * value is checked. Because LocaleConfigSubscriber temporarily disables the
341 * override state of the configuration factory we check that the correct value
342 * is restored afterwards.
344 * @param string $config_name
345 * The configuration name.
347 * The configuration key.
348 * @param string $source_value
349 * The source configuration value to verify the correct value is returned
350 * from the configuration factory after the deletion.
351 * @param string $langcode
354 protected function deleteLocaleTranslationData($config_name, $key, $source_value, $langcode) {
355 $this->localeConfigManager
356 ->getStringTranslation($config_name, $langcode, $source_value, '')
358 $this->localeConfigManager->reset();
359 $this->localeConfigManager->updateConfigTranslations([$config_name], [$langcode]);
360 $this->configFactory->reset($config_name);
362 $this->assertNoConfigOverride($config_name, $key, $source_value, $langcode);
366 * Ensures configuration override is not present anymore.
368 * @param string $config_name
369 * The configuration name.
370 * @param string $langcode
374 * TRUE if the assertion succeeded, FALSE otherwise.
376 protected function assertNoConfigOverride($config_name, $langcode) {
377 $config_langcode = $this->configFactory->getEditable($config_name)->get('langcode');
378 $override = $this->languageManager->getLanguageConfigOverride($langcode, $config_name);
379 return $this->assertNotEqual($config_langcode, $langcode) && $this->assertEqual($override->isNew(), TRUE);
383 * Ensures configuration was saved correctly.
385 * @param string $config_name
386 * The configuration name.
388 * The configuration key.
389 * @param string $value
390 * The configuration value.
391 * @param string $langcode
395 * TRUE if the assertion succeeded, FALSE otherwise.
397 protected function assertConfigOverride($config_name, $key, $value, $langcode) {
398 $config_langcode = $this->configFactory->getEditable($config_name)->get('langcode');
399 $override = $this->languageManager->getLanguageConfigOverride($langcode, $config_name);
400 return $this->assertNotEqual($config_langcode, $langcode) && $this->assertEqual($override->get($key), $value);
404 * Ensures configuration was saved correctly.
406 * @param string $config_name
407 * The configuration name.
409 * The configuration key.
410 * @param string $value
411 * The configuration value.
412 * @param string $langcode
416 * TRUE if the assertion succeeded, FALSE otherwise.
418 protected function assertActiveConfig($config_name, $key, $value, $langcode) {
419 $config = $this->configFactory->getEditable($config_name);
421 $this->assertEqual($config->get('langcode'), $langcode) &&
422 $this->assertIdentical($config->get($key), $value);
426 * Ensures no translation exists.
428 * @param string $config_name
429 * The configuration name.
430 * @param string $langcode
434 * TRUE if the assertion succeeded, FALSE otherwise.
436 protected function assertNoTranslation($config_name, $langcode) {
437 $strings = $this->stringStorage->getTranslations([
438 'type' => 'configuration',
439 'name' => $config_name,
440 'language' => $langcode,
441 'translated' => TRUE,
443 return $this->assertIdentical([], $strings);
447 * Ensures a translation exists and is marked as customized.
449 * @param string $config_name
450 * The configuration name.
451 * @param string $translation
453 * @param string $langcode
455 * @param bool $customized
456 * Whether or not the string should be asserted to be customized or not
460 * TRUE if the assertion succeeded, FALSE otherwise.
462 protected function assertTranslation($config_name, $translation, $langcode, $customized = TRUE) {
463 // Make sure a string exists.
464 $strings = $this->stringStorage->getTranslations([
465 'type' => 'configuration',
466 'name' => $config_name,
467 'language' => $langcode,
468 'translated' => TRUE,
470 $pass = $this->assertIdentical(1, count($strings));
471 $string = reset($strings);
472 if ($this->assertTrue($string instanceof StringInterface)) {
473 /** @var \Drupal\locale\StringInterface $string */
474 $pass = $pass && $this->assertIdentical($translation, $string->getString());
475 $pass = $pass && $this->assertTrue($string->isTranslation());
476 if ($this->assertTrue($string instanceof TranslationString)) {
477 /** @var \Drupal\locale\TranslationString $string */
478 // Make sure the string is marked as customized so that it does not get
479 // overridden when the string translations are updated.
480 return $pass && $this->assertEqual($customized, $string->customized);