Fields Content Deletions of (already Translated) Entity Content are not reflected in new Translations updates

Created on 3 May 2022, about 3 years ago
Updated 28 February 2023, about 2 years ago

Problem/Motivation

When some field content is deleted from an already Translated Content Entity it is not reflected in its Translations updates.
The field is still present with the same (translated) content from the previous version/revision ...
This happens to me both in the source Content and both in Paragraphs (or other fieldable entities) attached/referenced to the source Content.

Steps to reproduce

  1. Create a Content Entity (assume a Node) with Title and a text field (assume it is called "text_field"), and fill both of them with some content (Version 1);
  2. Require Translation (let's assume for Spanish Language) for the Node Content Entity, and have them accepted back. Both the Title and the "text_field" will have their Spanish Translation (Version 1) ...
  3. Amend the Title field content (Version 2) and just delete the content for the "text_field" (that becomes empty).
  4. Re-require the Translation (for Spanish Language) for the Node Content Entity.
  5. I expect the Title field to have the Spanish Translation updated to its Version 2 and the "text_field" now empty (correctly reflecting the source field state). But the "text_field" is instead still filled with the Spanish Translation (Version 1) ... and this is wrong/un-wanted.

This is a general problem that we are experiencing, and also with referenced Paragraphs: when a Paragraphs field is updated as empty, its translation update will still include its previous translation.

Proposed resolution

From my TMGMT inspection it looks to me that these issues are caused from the logic used to update Content Entity existing translations, from the tmgmt_content submodule, in the Drupal\tmgmt_content\Plugin\tmgmt\SourceContentEntitySource::doSaveTranslations method: https://git.drupalcode.org/project/tmgmt/-/blob/8.x-1.x/sources/content/...

If the Content Entity Translations already exists then ONLY the fields part of the new incoming translations data are updated ...

Instead it could be appropriate, in case of already existing Translation, always remove it (along all its already existing and translated fields) and recreate it from skracth with the new incoming translation ones: as a result only the fields part of the new updated translation will be part of the updated Entity Content Translation, that would perfectly match its source updates, also in terms of deletions.

🐛 Bug report
Status

Needs review

Version

1.0

Component

Core

Created by

🇮🇹Italy itamair

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.

  • 🇩🇪Germany D34dMan Hamburg

    I see that, for such cases the ui does detect that the field item was removed.

    Was wondering if it could be possible to "uncheck" the row so that it is not considered for translation. I tried adding an empty field value, but it won't allow me to submit the form :)

  • Status changed to Needs work 4 months ago
  • 🇨🇭Switzerland berdir Switzerland

    I don't think this approach is correct, we don't know if there are any fields that aren't handled by TMGMT and should in fact be kept, things that are manually translated. As shown in the failing test, that is, per comment there, a deliberate decision.

    So I think it's unlikely that this will be committed.

    Also, per 🐛 Error when creating new translation Active this seems to fail on the latest version.

  • 🇺🇸United States euk

    In my application I am working with two languages - EN and ES. I have node entities referencing paragraphs with fields referencing other paragraphs. The translations seems to be failing on the nested paragraphs (or maybe any embeddable entities). That is when this patch is applied. Long story short - the patch does not seem to account for nested/referenced entities such as paragraphs.

    I don't know the internal mechanics of the translations that deep, so can't really tell what is happening under the hood, but the Drupal\tmgmt_content\Plugin\tmgmt\SourceContentEntitySource::doSaveTranslations has the following flow when it comes to translating a node with a referenced paragraph:

    - on the first call it deletes existing translation of the parent node entity (if the translation exists) - this is a change the patch introduced,
    - then it recreates a fake translation with the original untranslated values (source language), gets the actual translation for the target language, then
    - goes over parent entity's fields - sets translated values, then
    - goes over embeddable fields - and attempts to set values for each embedded field's item (in my case paragraph) by recursively calling itself with the paragraph as the entity to operate on.

    When the initial doSaveTranslations call is made, the passed in node entity has the default (source) language set as the active language, and when the second recursive call is made for a referenced entity (paragraph in my case) - the passed in referenced entity has now the target language set as the active language. The doSaveTranslations method once again attempts to delete existing translation for the passed in entity (paragraph this time) and then goes over the same workflow - paragraph own fields, referenced entities' fields.

    It fails on line 528:

    527:  if ($manager->isEnabled($translation->getEntityTypeId(), $translation->bundle())) {
    528:    $manager->getTranslationMetadata($translation)->setSource($entity->language()->getId());
    529:  }
    

    Not entirely sure what is the purpose of the line 528, but calling setSource() eventually leads to getTranslatedField, where there the following unexpected condition happens:

      protected function getTranslatedField($name, $langcode) {
        if ($this->translations[$this->activeLangcode]['status'] == static::TRANSLATION_REMOVED) {
          throw new \InvalidArgumentException("The entity object refers to a removed translation ({$this->activeLangcode}) and cannot be manipulated.");
        }
    

    $this->translations[$this->activeLangcode]['status'] is actually NULL, but the "==" makes it equal to static::TRANSLATION_REMOVED which is 0. Changing the operator to "===" solves the issue for me.

    This however does not address the origin of the issue, which I believe is the way nested paragraphs are being processed after the patch is applied - the source should not be set to the target language on the line 528.

  • 🇺🇸United States euk

    Performed more testing and troubleshooting - no luck. Then looked at the dates - it has been almost 3 years since the patch was added. Back then TMGMT was v1.0. I removed the patch and everything worked as expected. The issue described in this ticket seems to be gone, which means the patch is no longer needed. Removing patch also fixes 🐛 Error when creating new translation Active

    This needs review and testing.

  • 🇺🇸United States euk
Production build 0.71.5 2024