Problem/Motivation

When a new language is created in the user interface, \Drupal\language\Config\LanguageConfigFactoryOverride::installLanguageOverrides() is called with the language code of the newly created language so that all language overrides for that language that may be available in any shipped modules or, in particular, the install profile get installed.

If a language is being created during a config sync, this should not happen, however, because any language overrides that should end up in the target storage should be part of the sync.

But on top of just being unnecessary CPU this actually causes a problem resulting in the entire config sync failing: If a module or profile ships a language override for a config entity and that override will also be created as part of the config sync, then a

Deleted and replaced configuration entity

error will be raised.

Steps to reproduce

  1. Have a site without the German language and a with a body field on the article node type
  2. Add the German language and translate the body field (for example using Config Translation)
  3. Export the configuration and attempt to import it on another instance of the site
    You should see something like
    +-------------+----------------------------------------+-----------+
    | Collection  | Config                                 | Operation |
    +-------------+----------------------------------------+-----------+
    |             | language.entity.de                     | Create    |
    | language.de | field.field.node.article.body          | Create    |
    +-------------+----------------------------------------+-----------+
    

    as output of drush cim

You will be greeted with:

  The import failed due to the following reasons:                              
  Deleted and replaced configuration entity "field.field.node.article.body"   

Instead of the import succeeding.

Proposed resolution

Explicitly check that no config sync is happening in \Drupal\language\Entity\ConfigurableLanguage::postSave() before calling \Drupal\language\Config\LanguageConfigFactoryOverride::installLanguageOverrides().

Remaining tasks

User interface changes

-

Introduced terminology

-

API changes

-

Data model changes

-

Release notes snippet

Issue fork drupal-3545595

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

tstoeckler created an issue. See original summary.

tstoeckler’s picture

Issue summary: View changes

tstoeckler’s picture

Status: Active » Needs review

This needs some tests before landing, but would like some confirmation on the fix before delving into that so marking "Needs review".

smustgrave’s picture

Status: Needs review » Needs work

I don't see any issue with the approach.

Only question is if it gets to this point will it attempt to install the language overrides later (after config import). Just want to make sure Drupal does just go "we tried" and moves on.

Else that's my only concern. Hope that helps.

tstoeckler’s picture

So the scenario I had on my project was the one described in the issue summary so the language overrides did end up being installed (as part of the config import). If they had not been part of the to-be-imported configuration presumably the site would have ended up without the overrides, which then is the expected outcome (but to be clear I did not verify that as of yet). I don't see any point that the language overrides would be re-added later.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

tuutti made their first commit to this issue’s fork.

tuutti’s picture

We've been having this issue on a site install from existing configuration as well. Our modules ship language overrides in config/install/language/fi. When the import creates the fi language, postSave() installs those overrides, and when the importer then processes the language.fi collection, every one of them hits the "Deleted and replaced" branch in ConfigImporter::checkOp().

A fresh install logged 274 "Deleted and replaced" errors, and because of #3633776, the config import batch adds the same errors to its results again on every batch call, so these 274 errors were reported about 185,000 times, drush printed 554,285 error lines, and the install took about 29 minutes. With the MR, the same install logged no errors and took about 13 minutes.