diff -u b/core/modules/locale/src/LocaleConfigManager.php b/core/modules/locale/src/LocaleConfigManager.php --- b/core/modules/locale/src/LocaleConfigManager.php +++ b/core/modules/locale/src/LocaleConfigManager.php @@ -122,13 +122,14 @@ } /** - * Gets array of translated strings for translatable configuration. + * Gets array of translated strings for Locale translatable configuration. * * @param string $name * Configuration object name. * * @return array - * Array of translatable elements of the default configuration in $name. + * Array of Locale translatable elements of the default configuration in + * $name. */ public function getTranslatableDefaultConfig($name) { if ($this->isSupported($name)) { @@ -563,31 +564,25 @@ foreach ($langcodes as $langcode) { $processed = $this->processTranslatableData($name, $active, $translatable, $langcode); // If the language code is not the same as the active storage - // language, we should update a configuration override. + // language, we should update the configuration override. if ($langcode != $active_langcode) { $override = $this->languageManager->getLanguageConfigOverride($langcode, $name); - $data = []; - if (!$override->isNew()) { - // Filter out any locale managed overrides from the existing - // override. - $data = $this->filterOverride($override->get(), $translatable); - } + // Filter out locale managed configuration keys so that translations + // removed from Locale will be reflected in the config override. + $data = $this->filterOverride($override->get(), $translatable); if (!empty($processed)) { - // Update translation data in configuration override. + // Merge in the Locale managed translations with existing data. $data = NestedArray::mergeDeepArray(array($data, $processed), TRUE); } - if (!empty($data)) { - // If there were translatable elements besides locale managed - // items, save with only those, and remove the ones managed - // by locale only. - $this->saveTranslationOverride($name, $langcode, $data); + if (empty($data) && !$override->isNew()) { + // The configuration override contains Locale overrides that no + // longer exist. + $this->deleteTranslationOverride($name, $langcode); $count++; } - else if (!$override->isNew()) { - // Delete language override if there is no data left at all. - // This means all prior translations in the override were locale - // managed. - $this->deleteTranslationOverride($name, $langcode); + elseif (!empty($data)) { + // Update translation data in configuration override. + $this->saveTranslationOverride($name, $langcode, $data); $count++; } } diff -u b/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php b/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php --- b/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php +++ b/core/modules/locale/src/Tests/LocaleConfigTranslationImportTest.php @@ -7,6 +7,7 @@ namespace Drupal\locale\Tests; +use Drupal\locale\Locale; use Drupal\simpletest\WebTestBase; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Core\Url; @@ -130,2 +131,95 @@ + /** + * Test removing a string from Locale deletes configuration translations. + */ + function testLocaleRemovalAndConfigOverrideDelete() { + // Enable locale, block and config_translation modules. + $this->container->get('module_installer')->install(['locale']); + $this->resetAll(); + + $admin_user = $this->drupalCreateUser(array('administer modules', 'administer site configuration', 'administer languages', 'access administration pages', 'administer permissions', 'translate interface')); + $this->drupalLogin($admin_user); + + // Enable import of translations. By default this is disabled for automated + // tests. + $this->config('locale.settings') + ->set('translation.import_enabled', TRUE) + ->save(); + + // Add predefined language. + $this->drupalPostForm('admin/config/regional/language/add', ['predefined_langcode' => 'af'], t('Add language')); + + $override = \Drupal::languageManager()->getLanguageConfigOverride('af', 'locale_test_translate.settings'); + $this->assertEqual(['translatable_default_with_translation' => 'Locale can translate Afrikaans'], $override->get()); + + // Remove the string from translation to simulate a Locale removal. Note + // that is no current way of doing this in the UI. + $locale_storage = \Drupal::service('locale.storage'); + $string = $locale_storage->findString(array('source' => 'Locale can translate')); + \Drupal::service('locale.storage')->delete($string); + // Force a rebuild of config translations. + $count = Locale::config()->updateConfigTranslations(['locale_test_translate.settings'], ['af']); + $this->assertEqual($count, 1, 'Correct count of updated translations'); + + $override = \Drupal::languageManager()->getLanguageConfigOverride('af', 'locale_test_translate.settings'); + $this->assertEqual([], $override->get()); + $this->assertTrue($override->isNew(), 'The configuration override was deleted when the Locale string was deleted.'); + } + + /** + * Test removing a string from Locale changes configuration translations. + */ + function testLocaleRemovalAndConfigOverridePreserve() { + // Enable locale, block and config_translation modules. + $this->container->get('module_installer')->install(['locale']); + $this->resetAll(); + + $admin_user = $this->drupalCreateUser(array('administer modules', 'administer site configuration', 'administer languages', 'access administration pages', 'administer permissions', 'translate interface')); + $this->drupalLogin($admin_user); + + // Enable import of translations. By default this is disabled for automated + // tests. + $this->config('locale.settings') + ->set('translation.import_enabled', TRUE) + ->save(); + + // Add predefined language. + $this->drupalPostForm('admin/config/regional/language/add', ['predefined_langcode' => 'af'], t('Add language')); + + $override = \Drupal::languageManager()->getLanguageConfigOverride('af', 'locale_test_translate.settings'); + // Update test configuration. + $override + ->set('translatable_no_default', 'This translation is preserved') + ->set('translatable_default_with_no_translation', 'This translation is preserved') + ->save(); + $expected = [ + 'translatable_default_with_translation' => 'Locale can translate Afrikaans', + 'translatable_no_default' => 'This translation is preserved', + 'translatable_default_with_no_translation' => 'This translation is preserved' + ]; + $this->assertEqual($expected, $override->get()); + + // Set the translated string to empty. + $search = array( + 'string' => 'Locale can translate', + 'langcode' => 'af', + 'translation' => 'all', + ); + $this->drupalPostForm('admin/config/regional/translate', $search, t('Filter')); + $textareas = $this->xpath('//textarea'); + $textarea = current($textareas); + $lid = (string) $textarea[0]['name']; + $edit = array( + $lid => '', + ); + $this->drupalPostForm('admin/config/regional/translate', $edit, t('Save translations')); + + $override = \Drupal::languageManager()->getLanguageConfigOverride('af', 'locale_test_translate.settings'); + $expected = [ + 'translatable_no_default' => 'This translation is preserved', + 'translatable_default_with_no_translation' => 'This translation is preserved' + ]; + $this->assertEqual($expected, $override->get()); + } + }