Original language entity content got overwritten when updating translated entity for multilingual site

Created on 13 January 2023, almost 2 years ago
Updated 28 April 2024, 8 months ago

Problem/Motivation

tldr;
The translated entity was never updated on save after upgrading module to alpha3.

When updating a translation for a block_content, the translated content did not appear on the translated entity but appears on the original source language entity instead after saving it. This happens on translatable node content types as well.

The root cause is happening from conflict_entity_prepare_form line 118, where it overridden the entity set within form_object, which is further used by content_translation module on content_translation.module line 391 to retrieve its entity object again and down the line it determine the active langcode to update the target translation of the entity being saved.

In short, the entity fetched from conflict_entity_prepare_form has an activeLangcode = "x-default", while the translated entity should be saved has its activeLangcode = "en" (when x-default langcode being zh-hant), the latter was overridden by "x-default".

@file conflict.module

function conflict_entity_prepare_form(EntityInterface $entity, $operation, FormStateInterface $form_state) {
  if (!$entity->isNew() && !$form_state->isCached()) {
    $conflict_entity_original_hash = $form_state->getUserInput()['conflict_entity_original_hash'] ?? NULL;
    if ($conflict_entity_original_hash) {
      $original_entity = \Drupal::keyValueExpirable('conflict_original_entity')->get($conflict_entity_original_hash);
      if ($original_entity) {
        $original_entity = unserialize($original_entity);
        /** @var \Drupal\Core\Entity\EntityFormInterface $form_object */
        $form_object = $form_state->getFormObject();
        $form_object->setEntity($original_entity);             <---- root cause on this line
        $form_state->set('conflict-exchanged-entity', TRUE);
      }
    }
  }
}
@file content_translation.module

function content_translation_form_alter(array &$form, FormStateInterface $form_state) {
  $form_object = $form_state->getFormObject();
  if (!($form_object instanceof ContentEntityFormInterface)) {
    return;
  }
  $entity = $form_object->getEntity();   <--- the entity content_translation wants to fetch
  $op = $form_object->getOperation();
}

Steps to reproduce

  1. Install fresh Drupal 9.5.1
  2. Select a language other then English on installation "Chinese, Traditional"
  3. Enable module content_translation, config_translation, conflict 8.x-2.0-alpha3
  4. Add a second language at [site:url]/admin/config/regional/language
  5. Enable content type 'article' translation config at /admin/structure/types/manage/article, leave default language as "Site's default language"
  6. Create a new node for article node 1 by default language (TITLE: This is not English)
  7. Create new translation for English on node 1 (Title: This is English ), new translation and contents are created as normal
  8. Update your translation at /en/node/1 edit with (Title: This is English v2), save, and the translation is not changed.
  9. Check /node/1 and it has (Title: This is English v2)
  1. Update node translation and save.
  2. Original node title and content was overridden

Proposed resolution

Rewrite conflict_entity_prepare_form to respect and set the translated entity in its form_object.

P.S. We downgraded our module alpha2 temporarily before this issue is resolved.

Remaining tasks

User interface changes

API changes

Data model changes

πŸ› Bug report
Status

Fixed

Version

2.0

Component

Code

Created by

πŸ‡ΉπŸ‡ΌTaiwan g-brodiei

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.

  • πŸ‡ΉπŸ‡ΌTaiwan g-brodiei

    Changing to critical as this bug deletes node, paragraph contents.

  • Thank you so much to the OP for creating this issue report I broke my site a month ago and could not figure out which update it was.

    For anyone with this issue, until their is a patch, use the alpha2 version by using

    composer require drupal/conflict:2.0.0-alpha2

  • πŸ‡ΉπŸ‡ΌTaiwan g-brodiei

    Glad it helped @mattea.turnbull! We were affected while updating one of Acquia's distribution lightning/workflow.

    Rewriting title for easier understanding.

  • Thanks @mattea.turnbull. Downgrading to alpha 2 worked. We are using acquia/blt-project and with latest upgrade we moved to alpha 3 introduced issue.

  • First commit to issue fork.
  • πŸ‡¨πŸ‡¦Canada wilco

    I think I may have found a solution around the problem highlighted in this issue.

    I am including a patch file for those that wish to use this immediately.

    Basically, the proceedure conflict_entity_load() attempts to clone an entity that has yet to have been fully loaded. The problem is this entity is only partially complete when compared against the RouteMatch Object the form uses in certain instances. Imagine a Node or Taxonomy Term which is built using multilingual mechanism.

    While inspecting the source of the complete object vs the cloned object I noted a lack of translation elements.

    By ensuring the entity being loaded is in fact of instance TranslatableInterface we actually get a better cloned entity. Thus, resolving these incorrect conflicts.

  • πŸ‡¨πŸ‡¦Canada wilco

    Fixed the patched file. Seems to now want to apply properly.

  • @wilco opened merge request.
  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    Is there a category higher than "critical" ?

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    Would be nice to have automated test coverage for this but ya, critical fix that needs to go in asap, I suggest to put the fix in and follow up with a new issue to add automated test coverage.

  • πŸ‡³πŸ‡±Netherlands Martijn Houtman

    Confirmed this is happening on several of our sites as well. Thanks for catching this, it took me some time to find out the conflict module was the culprit.

    Confirmed patch #10 fixes the issue.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    The patch works well however due to the lack of support in this project we've chosen to uninstall the conflict module instead of patch it.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    I have sent a message to three project maintainers about this critical issue. I also sent messages to maintainers 2 months ago as well. This is a repeat.

    @dww, @drumm and @hchonov have been notified of the severity of this issue. It absolutely must be resolved asap. Patch 10 works perfectly.

  • Status changed to Needs review over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States dww

    If this is so urgent and ready, why is the status only β€œactive”?

    I’m unavailable for the next few days, but I hope to take a closer look later this week.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    @dww, it's RTBC+ by @wilco , @Martijn Houtman and myself. I assure you this is a critical fix that is needed and that patch 10 is the correct solution. It was a very tough issue to figure out and plagued two of the projects I worked on for several months before @wilco figured it out. I found a workaround which was to enable the editorial workflow on media entities. With that said, no one should be forced to use a workflow in order to prevent data loss.

  • Status changed to RTBC over 1 year ago
  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    Test scenario setup steps:

    1. Install Drupal core 9.5.8
    2. enable the content_translation module
    3. Enable translation on a node bundle
    4. Enable translation on a media bundle
    5. composer require drupal/conflict
    6. install the "conflict" module
    7. DO NOT use workflow, do not install the workflow module
    8. add a node of the translateable type, translate the media entity
    9. add a media entity of the translatable type, translate the media entity
    10. publish the media entity
    11. publish the node entity
    12. edit the node translation and publish it
    13. edit the media translation and publish it
    14. edit the node translation again, notice that it clobbers the other language
    15. edit the media translation again, notice that it clobbers the other language
    16. Delete your node translation, it will clobber the entity
    17. Delete your media translation, it will clobber the entity


    so, why is this critical?

    • data loss on edit translation
    • data loss on delete translation

    To fix the problem:

    three choices:

    1. Uninstall the conflict module
    2. Rather than uninstall the conflict module, use patch 10
    3. Rather than use the patch, install the workflow module and add the entity into a workflow (workaround, but still breaks taxonomy term translation also).

    The best fix is patch 10.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    @dww , three lines of code is all that is needed, please have a look at patch 10.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    FYI , all my projects no longer use this module because of this issue is being ignored. This is a critical issue that needs to be fixed and it's only 3 lines of code.

  • What does this module do and what are the consequences of uninstalling it. This was a major high stress event when this broke and I'd like to evaluate if I should drop it vs applying the patch.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    @mattea.turnbull, either option use patch or uninstall the module will fix the regression. If you uninstall this module you won't have the regression however if you apply the patch you'll benefit from automatic conflict resolution if two people publish or edit a draft content at the same time.

    Meanwhile I have put in a request to take over maintainership of this project.
    #3381341: Offer to maintain the conflict module β†’

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    My offer to maintain this project has been ignored for more than 6 weeks after several attempts to reach the maintainers.

    Pushing offer to the ownership queue.
    #3381341: Offer to maintain the conflict module β†’

  • Status changed to Needs work about 1 year ago
  • πŸ‡©πŸ‡ͺGermany hchonov πŸ‡ͺπŸ‡ΊπŸ‡©πŸ‡ͺπŸ‡§πŸ‡¬

    The current patch is altering in which language the entity is being loaded as snapshot in conflict_entity_load(). The cause is to be searched at the place that is using it and not loading it. This is only covering up the bug that might come up at a harder place to search for later. So please check about the usages of $entity->{EntityConflictHandlerInterface::CONFLICT_ENTITY_ORIGINAL}. If we would accept the current change then $entity->language() and $entity->{EntityConflictHandlerInterface::CONFLICT_ENTITY_ORIGINAL}->language() will return a different language which would be inconsistent.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    Until this is resolved, maintaining recommendation to uninstall this module when using more than one language as this is a critical bug causing data loss.

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    There was a core commit made today that "might" improve this situation, I haven't tested it.

    πŸ› Creating a new translation may delete translations with drafts Fixed

  • With the patch I had been getting constant, 'you have a conflict' statements and stuff not saving in drupal 10.01. I have uninstalled conflict and that resolved those issues (previously in drupal 9.5 I never saw that dialog or had issues).

    I also had to uninstall autosave_form (unrelated to this but it seemed to break in drupal 10.0.1 with multilingual site).

    I am having issues where after I save French (my secondary language) it takes up to 5 minutes to display the saved changes onto the front end of the site (if you have any clue what updated with drupal 10 that would cause that?)

    Mattea

  • I'm currently testing content_lock module as an alternative to using the conflict module.

  • πŸ‡ΊπŸ‡¦Ukraine serg.linkin

    We are currently trying to use #10 πŸ› Original language entity content got overwritten when updating translated entity for multilingual site RTBC patch with Drupal 9.5.11. But it breaks jsonapi responses that check access to individual resources or unpublished translations, for example, with ERR_EMPTY_RESPONSE or '50x' server status code.

    So I've improved it by using the 'entity_upcast' context to fix this, based on the jsonapi module code.

  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 7.3 & MySQL 5.7
    last update about 1 year ago
    1 pass
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 7.4 & MySQL 8
    last update about 1 year ago
    1 pass
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 7.4 & MySQL 8
    last update about 1 year ago
    1 pass
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 7.3 & MySQL 5.7
    last update about 1 year ago
    1 pass
  • πŸ‡·πŸ‡ΈSerbia levmyshkin Novi Sad, Serbia

    Hi mattea.turnbull, I went here because I already use Content Lock module coupled with Conflict module. Because Authors need to have ability to lock translation revision, not locking entire node. And I also have this problem.

  • Status changed to Needs review 9 months ago
  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    Patch #31 seems like a very safe change to make with the extra validation compared with patch #11

  • Status changed to Fixed 8 months ago
  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    oops somehow authored by incorrectly credited, it was Wilco that did this patch, I got wilco and serg.linkin in the comments.

    https://www.drupal.org/project/conflict/releases/3.0.0-alpha4 β†’

    d.o removed the automatic author option, I must have put the wrong id in

  • πŸ‡¨πŸ‡¦Canada joseph.olstad

    Committed #31, tagged and released

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024