When saving a Draft, ContentEntityStorageBase checks to see each language of an entity to see if there are any translation changes. Because ERR makes new revisions on each save all translations come back as saved. This is a problem as of 8.4.x with the new revision_translation_affected flag because it overwrites any drafts on other languages.

Here's a use case,

1. Install Paragraphs
2. Patch Paragraphs to support asymmetrical translations: #2461695: Support asymmetric translations
3. Enable Content Moderation
4. Create a new node in a language, say en, with multiple paragraphs. Save and publish this translation.
5. Add a translation of that node, say es. Save and publish this translation.

So far, everything above should work as expected. Drafts is where things break,

1. Edit the en translation and save a draft, notice that revision_translation_affected is 1 for both translations. Because we only have one translation being drafted this is okay, our draft is saved without issue and the UI shows the draft as expected.
2. Edit the es translation and save a draft. Now, there's a new revision with revision_translation_affected set to 1 for both translations.

At this point, the es draft just "overwrote" the en draft. In reality the en draft is still there, but because revision_translation_affected is set to 1 for both translations we've lost out ability to access the en draft through the Drupal UI.

This is related to #2935070: Always new revision even we have no changes. I understand why each save creates revisions for the paragraph entities, but it's breaking forward revisions when using Paragraphs.

I'm happy to help with a patch, this is affecting a production website so I'm looking to get it fixed. Looking for some direction to start with though so I don't go down the wrong path.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

markhuot created an issue. See original summary.

miro_dietiker’s picture

This has been identified in Paragraphs in the related issue. There will be actions to take in ERR, Paragraphs and likely Core as well to fix this.

You start best with reviewing the test coverage in the related issue and maybe improve it if we will need to test more. Fixing is going to be hard and will likely first address the case without asymmetric translation.

Berdir’s picture

Ok, here we go.

I did *not* test this yet with paragraphs, this just contains an API test. So please make sure that this works when using paragraphs with the async translation widget patches.

If you still experience issues, have a close look at how many entities/translations you have and if the content of the other translations is changing when you cange a certain translation. You can also look at the translations that are affected by a given revision by looking at the /revisions page of each translations, you should not be seeing any revisions from other translations there.

Berdir’s picture

+++ b/src/Plugin/Field/FieldType/EntityReferenceRevisionsItem.php
@@ -254,24 +255,35 @@ class EntityReferenceRevisionsItem extends EntityReferenceItem implements Option
+      // The item is considered to be affected if the field is either
+      // untranslatable or there are translation changes. This prevents
+      // that new revisions are created on translatable fields for all
+      // translations every time the entity is saved.
+      $is_affected = !$this->getFieldDefinition()->isTranslatable() || ($host instanceof TranslatableRevisionableInterface && $host->hasTranslationChanges());

This is the crucial part.. only creating a new revision if the current host translation has translation changes.

Performance is a concern here, since calculating that multiple times in a request is quite slow. But the problem is that \Drupal\Core\Entity\ContentEntityBase::isRevisionTranslationAffected() is at that point not yet re-calculated that only happens after the preSave() hook/field plugin method calls.

Status: Needs review » Needs work

The last submitted patch, 3: entity_reference_revisions-translatable-field-2953343-3.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Berdir’s picture

Cleaned up a weird test that was no failing which was due to some static cache side effects, not sure how it did *not* fail before. Also improved comments on some assertions there that were very confusing.

Status: Needs review » Needs work

The last submitted patch, 6: entity_reference_revisions-translatable-field-2953343-6.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Berdir’s picture

Test wasn't properly fixed yet, was actually not only the static cache, using the old object meant it didn't have parent fields yet and was saving again in postSave().

plach’s picture

Just a couple of things I noticed while looking at this:

  1. +++ b/src/Plugin/Field/FieldType/EntityReferenceRevisionsItem.php
    @@ -254,24 +255,35 @@ class EntityReferenceRevisionsItem extends EntityReferenceItem implements Option
    +      // The item is considered to be affected if the field is either
    +      // untranslatable or there are translation changes. This prevents
    +      // that new revisions are created on translatable fields for all
    +      // translations every time the entity is saved.
    

    I think the comments should say that this prevents all revision translation from being marked as affected, because we do get a new revision translation value for each field regardless.

    Also, does not wrap at 80 chars :)

  2. +++ b/src/Plugin/Field/FieldType/EntityReferenceRevisionsItem.php
    @@ -254,24 +255,35 @@ class EntityReferenceRevisionsItem extends EntityReferenceItem implements Option
    +      $is_affected = !$this->getFieldDefinition()->isTranslatable() || ($host instanceof TranslatableRevisionableInterface && $host->hasTranslationChanges());
    

    TranslatableInterface should be enough here, I guess we already assume we are dealing with a revisionable entity type :)

miro_dietiker’s picture

Status: Needs review » Needs work

Will commit after quick update and passes. :-)

Berdir’s picture

Missed that review.

1. Improved the comment.

2. I used (and kept) this interface because below, we also call things like $host->isNewRevision() and then PHPStorm complains that those don't exist on TranslatableInterface, by using that other interface, I have all methods covered that I'm calling on $host.

  • miro_dietiker committed 65067ad on 8.x-1.x authored by Berdir
    Issue #2953343 by Berdir, markhuot, miro_dietiker, plach: Experimental...
miro_dietiker’s picture

Status: Needs review » Fixed

Passed, committed. Awesome. :-)

Status: Fixed » Closed (fixed)

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

maximpodorov’s picture

These changes introduce the new problem: #2984027: Incorrect manipulation of default revision flag