Draft: feat: #3591596 ALTERNATE Propagate component instance updates to content/config translations; introduce `StagedLanguageConfigOverride` to treat both similarly

Alternative approach to !1163 (closed). This was largely AI-generated, with strict guardrails imposed by @wimleers, and instructed to use !1263 as a reference. (See below if interested in seeing the high-level guardrails.)

Comparison with !1163 (closed)

  • ~33% smaller: !1163: 15 files, +2987, −136 at !1163 (8d2ce541)) 🆚 this MR 25 files changed, 2198 insertions(+), 292 deletions(-) at c01a527d
    • … but now with an ADR!
    • … and more capable, better prepared for the future (see next bullets)
  • basically does what @wimleers proposed late on Friday June 19 at !1163 (comment 1263859) and which @penyaskito seemed favorable to
    • (one of @penyaskito's concerns was that it'd take too much time to get StagedLanguageConfigOverride to work, but it shares a lot of code with StagedConfigUpdate)
    • also pairs beautifully with !1263!
  • and also addresses the concerns @wimleers raised on Thursday June 18 at !1163 (comment 1262438), for which this is the tl;dr

What this does

  • 🟢 (same as !1163 (closed)) Propagates component instance version updates symmetrically to all non-default translations, for both content entities and config entities. Before this MR, updating a component's version applied changes only to the default-translation component tree; every non-default translation still held inputs shaped for the old version, violating the ADR #12 invariant.
  • 🟢 (same as !1163 (closed)) For content entities: each non-default translation's ComponentTreeItemList is reconciled in-memory immediately after the default-translation update. Removed props are pruned, new props are seeded from the default translation, non-translatable props are synced, translatable props are preserved.
  • 🆕 🚀 (different from !1163 (closed)) For config entities: reconciliation stages mutations as StagedLanguageConfigOverride config entities — the same auto-save pattern used by StagedConfigUpdate — so "Spanish translation of page region sidebar" appears explicitly in the review-and-publish UI, not as a silent side effect (NOTE: !1263 will make sure it doesn't appear in the UI anymore, but it'll still be present in the auto-save store. The UI will start showing the auto-saved translations again when either i) Canvas adds asymmetrical translation support or ii) direct editing of translations in the Canvas UI)
  • 🟢 (same as !1163 (closed)) When publishing a content entity, publish all auto-saved translations, too. (as of !1271 (448689fa))
  • 🆕 🚀 When publishing a config entity, publish all auto-saved translations, too.
  • 🆕 🚀 (different from !1163 (closed)) ADR #13 documents all architectural decisions. TranslationPropagationTestBase extracts the shared test fixture into a base class used by both ConfigEntityTranslationPropagationTest and ContentEntityTranslationPropagationTest.

AI use, imposed constraints, and instructed direction

AI use disclosure: significant parts of this MR were authored with AI assistance (Claude Sonnet 4.6) per Drupal.org's AI policy (https://www.drupal.org/docs/develop/issues/issue-procedures-and-etiquette/policy-on-the-use-of-ai-when-contributing-to-drupal). All generated code was reviewed by @wimleers . ⚠️ Still to be reviewed & tested by Wim: the test coverage + actually using it end-to-end.

This is the direction I (@wimleers) after having thoroughly reviewed @penyaskito's !1263 I thought to be likely viable and simpler:

  Based on everything you now know about this MR; create a completely new branch, with the same end result, but a completely different approach, with the following constraints:

  1. Do not introduce new services, instead just update *at most* \Drupal\canvas\ComponentSource\ComponentSourceManager::updateComponentInstances() (any signature or logic change alllowed)
  2. Modifying the signature of ComponentInstanceInputsConfigSchemaGeneratorInterface (any existing methods, or adding new methods) is allowed
  3. Modifying implementations of that interface is allowed
  4. Strongly encouraged: expand ComponentTreeItem(List) with additional methods.

  Explore in a new branch called `3591596-alt` (already checked out) whether it's viable to achieve the same with those constraints and this general idea:
  1. add new methods to ComponentTreeItem(List)
  2. update existing infra (per the above constraints) as needed
  3. 1+2 to allow the existing updater infra to still target the default translation of a content/config entity, but to then use a ComponentTreeItem::reconcileWithUpdatedDefaultTranslation($item_before, $item_after) method (which throws an exception if it is called on the
  non-default translation) to perform the reconciling

  IOW: the idea is to "push down" the fundamental logic into the lowest level concept (a component instance, represented by ComponentTreeItem), to maximally leverage existing abstractions instead of inventing new ones.

Closes #3591596

Edited by Wim Leers

Merge request reports

Loading