Loading core/lib/Drupal/Core/Config/Plugin/Validation/Constraint/LangcodeRequiredIfTranslatableValuesConstraint.php +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ class LangcodeRequiredIfTranslatableValuesConstraint extends SymfonyConstraint { public function __construct( public string $missingMessage = "The @name config object must specify a language code, because it contains translatable values.", public string $entityMessage = "The @name config object must specify a language code, because it is a configuration entity.", public string $superfluousMessage = "The @name config object does not contain any translatable values, so it should not specify a language code.", ?array $groups = NULL, mixed $payload = NULL, Loading core/lib/Drupal/Core/Config/Plugin/Validation/Constraint/LangcodeRequiredIfTranslatableValuesConstraintValidator.php +9 −3 Original line number Diff line number Diff line Loading @@ -33,9 +33,15 @@ public function validate(mixed $value, Constraint $constraint): void { assert(in_array('langcode', $mapping->getValidKeys(), TRUE)); $is_translatable = $mapping->hasTranslatableElements(); if ($is_translatable && !array_key_exists('langcode', $value)) { $this->context->buildViolation($constraint->missingMessage) $is_config_entity = \Drupal::service('config.manager')->getEntityTypeIdByName($mapping->getName()) !== NULL; // Require a langcode for translatable configuration and for config // entities. Configuration entities that currently do not have translatable // elements but do not have a langcode key are not valid because they may // receive translatable elements later outside of the entity's control, // eg. third party settings. if (($is_translatable || $is_config_entity) && !array_key_exists('langcode', $value)) { $this->context->buildViolation($is_config_entity ? $constraint->entityMessage : $constraint->missingMessage) ->setParameter('@name', $mapping->getName()) ->addViolation(); return; Loading core/modules/locale/src/LocaleConfigManager.php +5 −5 Original line number Diff line number Diff line Loading @@ -618,12 +618,12 @@ public function updateDefaultConfigLangcodes() { // module is enabled later, then some configuration may not exist // anymore. if (!$config->isNew()) { $typed_config = $this->typedConfigManager->createFromNameAndData($config->getName(), $config->getRawData()); $langcode = $config->get('langcode'); // Only set a `langcode` if this config actually contains translatable // data. // @see \Drupal\Core\Config\Plugin\Validation\Constraint\LangcodeRequiredIfTranslatableValuesConstraint if (!empty($this->getTranslatableData($typed_config)) && (empty($langcode) || $langcode == 'en')) { $typed_config = $this->typedConfigManager->createFromNameAndData($config->getName(), $config->getRawData()); // Translatable simple configuration and any configuration entity // should get the site language code even when they do not currently // have translatable data. if (($this->configManager->getEntityTypeIdByName($config->getName()) || !empty($this->getTranslatableData($typed_config))) && (empty($langcode) || $langcode == 'en')) { $config->set('langcode', $default_langcode)->save(); } } Loading core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationMultipleLanguageTest.php +25 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,8 @@ public function testTranslationsLoaded(): void { // Spanish is always an override (never used as installation language). $this->assertEquals('Anonymous es', $override_es->get('anonymous')); // Verify that config entities get the correct language assumptions. $this->verifyConfigLanguageAssumptions(); } /** Loading @@ -187,4 +189,27 @@ protected function verifyImportedStringsTranslated(): void { } } /** * Verifies config entity and simple config langcode assumptions. */ protected function verifyConfigLanguageAssumptions(): void { if ($this->langcode === 'en') { return; } $config_factory = \Drupal::configFactory(); foreach (['language.entity.de', 'language.entity.es'] as $config_name) { $this->assertEquals( $this->langcode, $config_factory->get($config_name)->get('langcode'), "Config entity '$config_name' should use the installation language langcode." ); } $this->assertNull( $config_factory->get('system.performance')->get('langcode'), 'Non-entity config without translatable data should not be rewritten to the installation language.' ); } } Loading
core/lib/Drupal/Core/Config/Plugin/Validation/Constraint/LangcodeRequiredIfTranslatableValuesConstraint.php +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ class LangcodeRequiredIfTranslatableValuesConstraint extends SymfonyConstraint { public function __construct( public string $missingMessage = "The @name config object must specify a language code, because it contains translatable values.", public string $entityMessage = "The @name config object must specify a language code, because it is a configuration entity.", public string $superfluousMessage = "The @name config object does not contain any translatable values, so it should not specify a language code.", ?array $groups = NULL, mixed $payload = NULL, Loading
core/lib/Drupal/Core/Config/Plugin/Validation/Constraint/LangcodeRequiredIfTranslatableValuesConstraintValidator.php +9 −3 Original line number Diff line number Diff line Loading @@ -33,9 +33,15 @@ public function validate(mixed $value, Constraint $constraint): void { assert(in_array('langcode', $mapping->getValidKeys(), TRUE)); $is_translatable = $mapping->hasTranslatableElements(); if ($is_translatable && !array_key_exists('langcode', $value)) { $this->context->buildViolation($constraint->missingMessage) $is_config_entity = \Drupal::service('config.manager')->getEntityTypeIdByName($mapping->getName()) !== NULL; // Require a langcode for translatable configuration and for config // entities. Configuration entities that currently do not have translatable // elements but do not have a langcode key are not valid because they may // receive translatable elements later outside of the entity's control, // eg. third party settings. if (($is_translatable || $is_config_entity) && !array_key_exists('langcode', $value)) { $this->context->buildViolation($is_config_entity ? $constraint->entityMessage : $constraint->missingMessage) ->setParameter('@name', $mapping->getName()) ->addViolation(); return; Loading
core/modules/locale/src/LocaleConfigManager.php +5 −5 Original line number Diff line number Diff line Loading @@ -618,12 +618,12 @@ public function updateDefaultConfigLangcodes() { // module is enabled later, then some configuration may not exist // anymore. if (!$config->isNew()) { $typed_config = $this->typedConfigManager->createFromNameAndData($config->getName(), $config->getRawData()); $langcode = $config->get('langcode'); // Only set a `langcode` if this config actually contains translatable // data. // @see \Drupal\Core\Config\Plugin\Validation\Constraint\LangcodeRequiredIfTranslatableValuesConstraint if (!empty($this->getTranslatableData($typed_config)) && (empty($langcode) || $langcode == 'en')) { $typed_config = $this->typedConfigManager->createFromNameAndData($config->getName(), $config->getRawData()); // Translatable simple configuration and any configuration entity // should get the site language code even when they do not currently // have translatable data. if (($this->configManager->getEntityTypeIdByName($config->getName()) || !empty($this->getTranslatableData($typed_config))) && (empty($langcode) || $langcode == 'en')) { $config->set('langcode', $default_langcode)->save(); } } Loading
core/tests/Drupal/FunctionalTests/Installer/InstallerTranslationMultipleLanguageTest.php +25 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,8 @@ public function testTranslationsLoaded(): void { // Spanish is always an override (never used as installation language). $this->assertEquals('Anonymous es', $override_es->get('anonymous')); // Verify that config entities get the correct language assumptions. $this->verifyConfigLanguageAssumptions(); } /** Loading @@ -187,4 +189,27 @@ protected function verifyImportedStringsTranslated(): void { } } /** * Verifies config entity and simple config langcode assumptions. */ protected function verifyConfigLanguageAssumptions(): void { if ($this->langcode === 'en') { return; } $config_factory = \Drupal::configFactory(); foreach (['language.entity.de', 'language.entity.es'] as $config_name) { $this->assertEquals( $this->langcode, $config_factory->get($config_name)->get('langcode'), "Config entity '$config_name' should use the installation language langcode." ); } $this->assertNull( $config_factory->get('system.performance')->get('langcode'), 'Non-entity config without translatable data should not be rewritten to the installation language.' ); } }