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.
Comments
Comment #2
miro_dietikerThis 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.
Comment #3
BerdirOk, 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.
Comment #4
BerdirThis 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.
Comment #6
BerdirCleaned 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.
Comment #8
BerdirTest 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().
Comment #9
plachJust a couple of things I noticed while looking at this:
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 :)
TranslatableInterface should be enough here, I guess we already assume we are dealing with a revisionable entity type :)
Comment #10
miro_dietikerWill commit after quick update and passes. :-)
Comment #11
BerdirMissed 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.
Comment #13
miro_dietikerPassed, committed. Awesome. :-)
Comment #15
maximpodorov CreditAttribution: maximpodorov commentedThese changes introduce the new problem: #2984027: Incorrect manipulation of default revision flag