Creating a new translation may delete translations with drafts

Created on 23 December 2022, almost 2 years ago
Updated 25 September 2023, about 1 year ago

Problem/Motivation

When creating a new translation with content moderation enabled, a certain combination of published and draft translations can cause:
1) existing translations to be deleted
2) hook_entity_translation_delete to be invoked when it shouldn't be.

Issue 1 is when you create a published translation, create a new draft of that translation, and then add a new published translation, that first translation will be deleted.

\Drupal\content_translation\Controller\ContentTranslationController::add calls getLatestTranslationAffectedRevisionId which loads a version of the node that is missing translation(s) if those translations have a default revision and a newer draft revision. When the new published translation is saved, it causes this bit of code to fire in \Drupal\Core\Entity\Sql\SqlContentEntityStorage::saveToSharedTables:

// Delete and insert to handle removed values.
      $this->database->delete($table_name)
        ->condition($key, $value)
        ->execute();

which deletes all of the node's records from the node_field_data. They're supposed to be repopulated by $node->save(), but since the $node object is missing the translation languages that never happens.

Issue 2 happens when you save the new translation as a draft instead of published. Because the node is missing a translation language, hook_entity_translation_delete() will be invoked for the missing translation(s). Although this behavior doesn't cause data loss by itself, the nature of that hook means there is likely some data loss in contrib modules. I saw this in the paragraphs_asymmetric_translation_widgets and xmlsitemap modules.

Steps to reproduce

Issue 1:
- Install Drupal with standard profile and enable content translation and content moderation
- Enable 2 additional languages: Spanish and French
- Add the default "editorial" workflow to the "Basic page" content type and enable translation
- Create a new published node in English with the body "English"
- Create a new published translation in Spanish with the body "Spanish"
- Add a new draft of the Spanish translation with the body "Spanish draft"
- Add a new published French translation (any body)
- Try and visit the published Spanish version of the node (should be /es/node/1)

Expected: You see the Spanish translation of the node, with the body text "Spanish"
Actual: You see the English translation of the node, with the body text "English"

Issue 2:
- Install Drupal with standard profile and enable content translation and content moderation
- Enable 2 additional languages: Spanish and French
- Add the default "editorial" workflow to the "Basic page" content type and enable translation
- Create a new published node in English with the body "English"
- Create a new published translation in Spanish with the body "Spanish"
- Add a new draft of the Spanish translation with the body "Spanish draft"
- Add some debug information (a breakpoint, dblog message, etc) to content_moderation_entity_delete() to inspect the entity being passed in
- Add a new draft French translation (any body)

Expected: content_moderation_entity_delete() is never called
Actual: content_moderation_entity_delete() is called with the Spanish translation

I've tested this with Drupal versions back to 9.3.

Proposed resolution

This patch populates the node object with existing translations so that they are present when a translation is added.

Remaining tasks

Review
commit

User interface changes

TBD

API changes

TBD

Data model changes

TBD

Release notes snippet

TBD

🐛 Bug report
Status

Fixed

Version

10.1

Component
Content moderation 

Last updated 16 days ago

Created by

🇺🇸United States dabblela

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024