UPDATED SUMMARY.
When using content moderation with content translation it is very difficult as a developer to work with these two systems and develop features that work correctly and properly for all languages. A good example of this is the revisions tab which will only label a single revision as "current revision" - which shows on the last language which was saved. If you look at the attached image revisioning_1.png you will see that since the EN version was the last one saved, it is labelled "current revision" and the revisions on the FR side do not have a current revision even though it "kinda" is the one at the top.
Delving deeper into it, a develop discovers that the revisions shown on the revisions tab don't exactly match what you see in the database:
SELECT * FROM `node_revision` WHERE `nid` = '9932'
nid vid langcode revision_uid revision_timestamp revision_log revision_default
9932 91525 en 1 1744226538 NULL 1
9932 91526 en 1 1744226558 NULL 1
9932 91527 en 1 1744226702 NULL 1
9932 91528 en 1 1744226729 NULL 1In the above table one can see that ALL revision are EN, which is quite a head scratcher for a non-core dev.
And, then when looking at content_moderation_state_field_data:
SELECT * FROM `content_moderation_state_field_data` WHERE `content_entity_id` = '9932'
id revision_id langcode uid workflow moderation_state content_entity_type_id content_entity_id content_entity_revision_id default_langcode revision_translation_affected
9731 91148 en 1 editorial draft node 9932 91528 1 1
9731 91148 fr 1 editorial draft node 9932 91528 0 NULLHere you have both language referencing the 'current version' 91528.
And, if you look at the content_moderation_state_field_revision:
SELECT * FROM `content_moderation_state_field_revision` WHERE `content_entity_id` = '9932'
id revision_id langcode uid workflow moderation_state content_entity_type_id content_entity_id content_entity_revision_id default_langcode revision_translation_affected
9731 91145 en 1 editorial draft node 9932 91525 1 1
9731 91146 en 1 editorial draft node 9932 91526 1 NULL
9731 91146 fr 1 editorial draft node 9932 91526 0 1
9731 91147 en 1 editorial draft node 9932 91527 1 NULL
9731 91147 fr 1 editorial draft node 9932 91527 0 1
9731 91148 en 1 editorial draft node 9932 91528 1 1
9731 91148 fr 1 editorial draft node 9932 91528 0 NULL
This is confusing because there lots of entries here. And, if you transition the node in both languages to published you get this:
9731 91149 en 1 editorial published node 9932 91529 1 1
9731 91149 fr 1 editorial draft node 9932 91529 0 NULL
9731 91150 en 1 editorial published node 9932 91530 1 NULL
9731 91150 fr 1 editorial published node 9932 91530 0 1Just to add to the confusion, you get entries for both languages for each revision with different states!
As mentioned in the comments in code you can eventually figure out how to get things like the latest published English and the Latest published French versions using the methods developed around latest translation affected. I have found this on sites with a lot of revisions to not be very performant. I created the cm_revision_delete module to at least prune some revisions to reduce the DB size.
I am not sure what the fix is here, I really respect the awesomeness of the core devs that built this. As a developer that builds websites for the Canadian Government where the translations of all content must match by law, I have had some challenges working with content_moderation / content_translations to meet certain requirement such as "All language translations must be published at the same time".
I hope this information helps.
| Comment | File | Size | Author |
|---|---|---|---|
| #19 | revisioning_1.png | 243.68 KB | joel_osc |
Comments
Comment #3
jasonawantAdding, what I think is a related issue #2784201: Track the latest_revision and latest_revision_translation_affected ID in the entity data table for revisionable entity types
Comment #4
jasonawantI've referenced this issue from #3088341: Add ability to query on most recent language specific revision
Comment #6
mikemccaffrey@jasonawant I was not familiar with how drupal handles this stuff, and so I dug into it a bit, and I am left appalled.
The reason that the node_revision table only contains the language code for the original language is because the different languages don't get their own revisions. When you edit the content for one language for a node, and it creates a new revision, it actually duplicates all of the content for all of the fields for all of the languages that have been translated.
Hopefully, I am not actually correct about this, because the amount of duplicate data generated by this process would be insane.
Comment #7
keats76 commented@mikemccaffrey I think you are correct. We are coming to the same realization at about the same time. Our database has been growing VERY large (Paragraphs, Content Moderation, Translation and Revisions). This is ugly.
Comment #8
keats76 commented* An entity that is both revisionable and translatable has all the features
* described above: every revision can contain one or more translations. The
* canonical variant of the entity is the default translation of the default
* revision. Any revision will be initially loaded as the default translation,
* the other revision translations can be instantiated from this one. If a
* translation has changes in a certain revision, the translation is considered
* "affected" by that revision, and will be flagged as such via the
* "revision_translation_affected" field. With the built-in UI, every time a new
* revision is saved, the changes for the edited translations will be stored,
* while all field values for the other translations will be copied as-is.
* However, if multiple translations of the default revision are being
* subsequently modified without creating a new revision when saving, they will
* all be affected by the default revision. Additionally, all revision
* translations will be affected when saving a revision containing changes for
* untranslatable fields. On the other hand, pending revisions are not supposed
* to contain multiple affected translations, even when they are being
* manipulated via the API.
Comment #9
keats76 commentedAs far as I can tell, if you are using Content Moderation and Language Translation, there is no way to tell which revision is tied to which language since ALL revisions contain a copy of ALL languages. This really boggles my mind.
They tried to solve for the problem by introducing the "revision_translation_affected" flag. That flag is set for the translation that is updated. However, if any of the fields on your entities are untranslatable, then the flag is cascaded to ALL translations. It's really hard to wrap your head around, but under fairly common situations, you will not be able to tell which translation was updated. This throws off the Revisions tab and makes managing revisions in a multi-lingual environment with Content Moderation VERY difficult.
:(
Comment #11
bohemier commentedI agree... this is an important issue for multilingual workflows...
Comment #14
yuseferi commentedany update on this ? because it looks very wired we still haven't this on Drupal 9.3!!!
Comment #18
acbramley commentedIt's very hard to tell from the IS and comments what we're trying to achieve here or what the problem is. We need an IS update with a clear description of the issue, including steps to reproduce.
Comment #19
joel_osc commentedComment #20
joel_osc commented