From e029e6cdb521ade09f9be6556ecf926e1b33f293 Mon Sep 17 00:00:00 2001 From: catch <catch@35733.no-reply.drupal.org> Date: Fri, 17 Mar 2023 17:35:34 +0000 Subject: [PATCH] =?UTF-8?q?Issue=20#2806009=20by=20alexpott,=20JvE,=20Berd?= =?UTF-8?q?ir,=20Dmitriy.trt,=20jhodgdon,=20lokapujya,=20VladimirAus,=20G?= =?UTF-8?q?=C3=A1bor=20Hojtsy,=20Jose=20Reyero,=20Anybody,=20kristiaanvand?= =?UTF-8?q?eneynde,=20Sutharsan,=20casey,=20smustgrave,=20nod=5F:=20Instal?= =?UTF-8?q?ling=20a=20module=20causes=20translations=20to=20be=20overwritt?= =?UTF-8?q?en?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/includes/install.core.inc | 2 +- core/modules/locale/locale.bulk.inc | 33 +++++++++- core/modules/locale/locale.module | 29 +-------- .../locale/src/LocaleConfigManager.php | 30 +++++++++ .../schema/locale_test_translate.schema.yml | 2 + .../locale_test_translate.module | 12 ++++ .../LocaleConfigTranslationImportTest.php | 62 +++++++++++++++++++ 7 files changed, 139 insertions(+), 31 deletions(-) diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 6584680de656..e3136e755eb8 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1841,7 +1841,7 @@ function install_finish_translations(&$install_state) { } // Creates configuration translations. - $batches[] = locale_config_batch_update_components([], array_keys($languages)); + $batches[] = locale_config_batch_update_components([], array_keys($languages), [], TRUE); return $batches; } diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc index 6c7a986bcd01..eb68d9d32c24 100644 --- a/core/modules/locale/locale.bulk.inc +++ b/core/modules/locale/locale.bulk.inc @@ -538,14 +538,19 @@ function locale_translate_delete_translation_files(array $projects = [], array $ * @param array $components * (optional) Array of component lists indexed by type. If not present or it * is an empty array, it will update all components. + * @param bool $update_default_config_langcodes + * Determines whether default configuration langcodes should be updated. This + * Should only happen during site and extension install. * * @return array * The batch definition. */ -function locale_config_batch_update_components(array $options, array $langcodes = [], array $components = []) { +function locale_config_batch_update_components(array $options, array $langcodes = [], array $components = [], bool $update_default_config_langcodes = FALSE) { $langcodes = $langcodes ? $langcodes : array_keys(\Drupal::languageManager()->getLanguages()); if ($langcodes && $names = Locale::config()->getComponentNames($components)) { - return locale_config_batch_build($names, $langcodes, $options); + // If the component list is empty we need to ensure that all configuration + // in the default collection is using the site's default langcode. + return locale_config_batch_build($names, $langcodes, $options, $update_default_config_langcodes); } } @@ -560,19 +565,27 @@ function locale_config_batch_update_components(array $options, array $langcodes * (optional) An array with options that can have the following elements: * - 'finish_feedback': Whether or not to give feedback to the user when the * batch is finished. Defaults to TRUE. + * @param bool $update_default_config_langcodes + * Determines whether default configuration langcodes should be updated. This + * Should only happen during site and extension install. * * @return array * The batch definition. * * @see locale_config_batch_refresh_name() */ -function locale_config_batch_build(array $names, array $langcodes, array $options = []) { +function locale_config_batch_build(array $names, array $langcodes, array $options = [], bool $update_default_config_langcodes = FALSE) { $options += ['finish_feedback' => TRUE]; $batch_builder = (new BatchBuilder()) ->setFile(\Drupal::service('extension.list.module')->getPath('locale') . '/locale.bulk.inc') ->setTitle(t('Updating configuration translations')) ->setInitMessage(t('Starting configuration update')) ->setErrorMessage(t('Error updating configuration translations')); + + if ($update_default_config_langcodes && \Drupal::languageManager()->getDefaultLanguage()->getId() !== 'en') { + $batch_builder->addOperation('locale_config_batch_set_config_langcodes'); + } + $i = 0; $batch_names = []; foreach ($names as $name) { @@ -596,6 +609,20 @@ function locale_config_batch_build(array $names, array $langcodes, array $option return $batch_builder->toArray(); } +/** + * Implements callback_batch_operation(). + * + * Updates default configuration when new modules or themes are installed. + * + * @param array|\ArrayAccess $context + * The batch context. + */ +function locale_config_batch_set_config_langcodes(&$context) { + Locale::config()->updateDefaultConfigLangcodes(); + $context['finished'] = 1; + $context['message'] = t('Updated default configuration to %langcode', ['%langcode' => \Drupal::languageManager()->getDefaultLanguage()->getId()]); +} + /** * Implements callback_batch_operation(). * diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 021af78b59ad..c06ea62bb237 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -319,8 +319,6 @@ function locale_get_plural($count, $langcode = NULL) { * Implements hook_modules_installed(). */ function locale_modules_installed($modules) { - locale_system_set_config_langcodes(); - $components['module'] = $modules; locale_system_update($components); } @@ -337,8 +335,6 @@ function locale_module_preuninstall($module) { * Implements hook_themes_installed(). */ function locale_themes_installed($themes) { - locale_system_set_config_langcodes(); - $components['theme'] = $themes; locale_system_update($components); } @@ -370,28 +366,7 @@ function locale_cron() { * Updates default configuration when new modules or themes are installed. */ function locale_system_set_config_langcodes() { - // Need to rewrite some default configuration language codes if the default - // site language is not English. - $default_langcode = \Drupal::languageManager()->getDefaultLanguage()->getId(); - if ($default_langcode != 'en') { - // Update active configuration copies of all prior shipped configuration if - // they are still English. It is not enough to change configuration shipped - // with the components just installed, because installing a component such - // as views or tour module may bring in default configuration from prior - // components. - $names = Locale::config()->getComponentNames(); - foreach ($names as $name) { - $config = \Drupal::configFactory()->reset($name)->getEditable($name); - // Should only update if still exists in active configuration. If locale - // module is enabled later, then some configuration may not exist anymore. - if (!$config->isNew()) { - $langcode = $config->get('langcode'); - if (empty($langcode) || $langcode == 'en') { - $config->set('langcode', $default_langcode)->save(); - } - } - } - } + Locale::config()->updateDefaultConfigLangcodes(); } /** @@ -435,7 +410,7 @@ function locale_system_update(array $components) { // components. Do this even if import is not enabled because parsing new // configuration may expose new source strings. $module_handler->loadInclude('locale', 'inc', 'locale.bulk'); - if ($batch = locale_config_batch_update_components([])) { + if ($batch = locale_config_batch_update_components([], [], [], TRUE)) { batch_set($batch); } } diff --git a/core/modules/locale/src/LocaleConfigManager.php b/core/modules/locale/src/LocaleConfigManager.php index 2ebdd735c938..bb265cbc8b0c 100644 --- a/core/modules/locale/src/LocaleConfigManager.php +++ b/core/modules/locale/src/LocaleConfigManager.php @@ -649,4 +649,34 @@ protected function filterOverride(array $override_data, array $translatable) { return $filtered_data; } + /** + * Updates default configuration when new modules or themes are installed. + */ + public function updateDefaultConfigLangcodes() { + $this->isUpdatingFromLocale = TRUE; + // Need to rewrite some default configuration language codes if the default + // site language is not English. + $default_langcode = $this->languageManager->getDefaultLanguage()->getId(); + if ($default_langcode != 'en') { + // Update active configuration copies of all prior shipped configuration if + // they are still English. It is not enough to change configuration shipped + // with the components just installed, because installing a component such + // as views or tour module may bring in default configuration from prior + // components. + $names = $this->getComponentNames(); + foreach ($names as $name) { + $config = $this->configFactory->reset($name)->getEditable($name); + // Should only update if still exists in active configuration. If locale + // module is enabled later, then some configuration may not exist anymore. + if (!$config->isNew()) { + $langcode = $config->get('langcode'); + if (empty($langcode) || $langcode == 'en') { + $config->set('langcode', $default_langcode)->save(); + } + } + } + } + $this->isUpdatingFromLocale = FALSE; + } + } diff --git a/core/modules/locale/tests/modules/locale_test_translate/config/schema/locale_test_translate.schema.yml b/core/modules/locale/tests/modules/locale_test_translate/config/schema/locale_test_translate.schema.yml index 93e57c698dc8..df9fd824a251 100644 --- a/core/modules/locale/tests/modules/locale_test_translate/config/schema/locale_test_translate.schema.yml +++ b/core/modules/locale/tests/modules/locale_test_translate/config/schema/locale_test_translate.schema.yml @@ -8,3 +8,5 @@ locale_test_translate.settings: type: label translatable_default_with_no_translation: type: label + key_set_during_install: + type: boolean diff --git a/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module b/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module index e55d4dc486eb..ed7911df9ae0 100644 --- a/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module +++ b/core/modules/locale/tests/modules/locale_test_translate/locale_test_translate.module @@ -20,3 +20,15 @@ function locale_test_translate_system_info_alter(&$info, Extension $file, $type) $info['hidden'] = FALSE; } } + +/** + * Implements hook_modules_installed(). + * + * @see \Drupal\Tests\locale\Functional\LocaleConfigTranslationImportTest::testConfigTranslationWithForeignLanguageDefault + */ +function locale_test_translate_modules_installed($modules, $is_syncing) { + // Ensure that writing to configuration during install does not cause + // \Drupal\locale\LocaleConfigSubscriber to create incorrect translations due + // the configuration langcode and data being out-of-sync. + \Drupal::configFactory()->getEditable('locale_test_translate.settings')->set('key_set_during_install', TRUE)->save(); +} diff --git a/core/modules/locale/tests/src/Functional/LocaleConfigTranslationImportTest.php b/core/modules/locale/tests/src/Functional/LocaleConfigTranslationImportTest.php index 72db6ef1b5e7..de506587d3f9 100644 --- a/core/modules/locale/tests/src/Functional/LocaleConfigTranslationImportTest.php +++ b/core/modules/locale/tests/src/Functional/LocaleConfigTranslationImportTest.php @@ -305,4 +305,66 @@ public function testLocaleRemovalAndConfigOverridePreserve() { $this->assertEquals($expected, $override->get()); } + /** + * Tests setting a non-English language as default and importing configuration. + */ + public function testConfigTranslationWithNonEnglishLanguageDefault() { + /** @var \Drupal\Core\Extension\ModuleInstallerInterface $module_installer */ + $module_installer = $this->container->get('module_installer'); + ConfigurableLanguage::createFromLangcode('af')->save(); + + $module_installer->install(['locale']); + $this->resetAll(); + /** @var \Drupal\locale\StringStorageInterface $local_storage */ + $local_storage = $this->container->get('locale.storage'); + + $source_string = 'Locale can translate'; + $translation_string = 'Locale can translate Afrikaans'; + + // Create a translation for the "Locale can translate" string, this string + // can be found in the "locale_test_translate" module's install config. + $source = $local_storage->createString([ + 'source' => $source_string, + ])->save(); + $local_storage->createTranslation([ + 'lid' => $source->getId(), + 'language' => 'af', + 'translation' => $translation_string, + ])->save(); + + // Verify that we can find the newly added string translation, it is not a + // customized translation. + $translation = $local_storage->findTranslation([ + 'source' => $source_string, + 'language' => 'af', + ]); + $this->assertEquals($translation_string, $translation->getString()); + $this->assertFalse((bool) $translation->customized); + + // Uninstall the "locale_test_translate" module, verify that we can still + // find the string translation. + $module_installer->uninstall(['locale_test_translate']); + $this->resetAll(); + $translation = $local_storage->findTranslation([ + 'source' => $source_string, + 'language' => 'af', + ]); + $this->assertEquals($translation_string, $translation->getString()); + + // Set the default language to "Afrikaans" and re-enable the + // "locale_test_translate" module. + $this->config('system.site')->set('default_langcode', 'af')->save(); + $module_installer->install(['locale_test_translate']); + $this->resetAll(); + + // Verify that enabling the "locale_test_translate" module didn't cause + // the string translation to be overwritten. + $translation = $local_storage->findTranslation([ + 'source' => $source_string, + 'language' => 'af', + ]); + $this->assertEquals($translation_string, $translation->getString()); + $this->assertFalse((bool) $translation->customized); + } + } -- GitLab