Problem/Motivation
When creating an initial Draft in a new translation, it's not saving as the default revision, which means that node_field_data isn't being populated for that language. This leads to issues with Drupal views.
Steps to reproduce
- Install Drupal 11.2.x
- Enable the modules Content Translation, Content Moderation.
- Assign the Editorial workflow to the Basic page content type.
- Enable Translations on the Basic Page content type.
- Add a second language, I'm using Japanese.
- Create a published version of an English page.
- Create a draft version of that same page in Japanese.
Here are the issues:
- on /admin/content, only the English translation shows up
- on /admin/content/moderated, the Japanese translation shows up correctly, but the Content type field is empty
If you publish the Japanese page, and then set it back to draft, both the issues above are solved.
Proposed resolution
Consider updating the default revision when a new translation draft is first created. We update the default revision when a new entity is created, so it's similar behaviour to get translations to function in the same way.
| Comment | File | Size | Author |
|---|---|---|---|
| #37 | interdiff_31-37.txt | 4.81 KB | v.dovhaliuk |
| #37 | content-moderation-unpublished-translation-3088790-37.patch | 4.69 KB | v.dovhaliuk |
| #31 | interdiff_10-31.txt | 4.55 KB | fathima.asmat |
| #31 | content-moderation-unpublished-translation-3088790-31.patch | 4.81 KB | fathima.asmat |
| #25 | 3088790-25.patch | 1.16 KB | anchal_gupta |
Issue fork drupal-3088790
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
zolt_toth commentedI have tried the very same process without the content moderation and workflow modules being enabled. In this case the node_field_data table will contain all needed values, and the sample view will be able to list all node revisions, so maybe the problem is in the content moderation module.
Comment #3
zolt_toth commentedComment #4
zolt_toth commentedThe Drupal\Core\Entity\Sql\SqlContentEntityStorage.php should update the node_field_data table on the line 967. It works like this: removes all records for the given nid and creates new ones for each available language versions. But this line will not be reached, since the newly created revision will not be considered as "default revision", and this line is in a code block with such condition. As far, as I have seen, the content moderation module sets somehow this "default revision" value, and this is the cause of the inconsistent database state. I would appreciate if someone from the module developers would be as kind as to look into this issue. I need a quick solution, so I am going to insert the missing node_field_data record with a post save hook, but this does not seem to be a nice method. I think it is a critical bug, since some other modules (in my case the views module) joins the node values via the node_field_data table expecting that all language versions of a node has a record in this table.
Comment #5
zolt_toth commentedI have solved my problem somehow, but because of the Drupal transaction handling it is quite painful... When you get any usable event, you cannot check the existence of the node_field_data record, because it will be inserted by the Drupal transaction handling later. In an entity_translation_insert hook I register a shutdown function (register_shutdown_function), and when that is called I check the existence of the node_field_data record of the inserted translation, and if it fails, check the existence of the node_field_revision record with the given translation language, too (it is to check if the revision actually has been successfully created + I copy all relevant data from the resulting node_field_revision record to the node_field_data table). I will try to change the title of this issue for something more eye-catching, because executing simple foolproof operations an inconsistent database status can be achieved.
Comment #6
zolt_toth commentedComment #7
sergiuteaca commentedI have the same problem.
One of the downsides of this bug is that the Delete button is not available for the draft translation.
@zolt_toth I have found another workaround.
The default_revision is overridden in
ModerationStateConstraintValidator.php, where it takes the configuration set in the current Workflow. If you edit the configuration file for that workflow by setting default_revision to TRUE for Draft state and import the configuration then there will be created a node_field_data entry for all draft translations in that workflow.And no code changes will be needed.
I also found this thread for UI code/UI changes that will have the same effect.
Comment #8
sam152 commentedComment #9
bahuma20Pushing the version to 9.1.x-dev as it still exists so this issue doesn't get lost.
Comment #10
bahuma20I've found out that this could be fixed in the
\Drupal\content_moderation\EntityOperations::entityPresave()method.There is determined if a revision should be set as default revision.
We should treat new translations as if they were new nodes and therefore set them as default revision when they are created.
I've attached a patch that does this.
Comment #11
bahuma20Comment #15
joachim commentedI think we saw this on our site, though we didn't figure out how to reproduce it.
The problem in our DB was that the most recent vid of the node was missing one of its rows. It should have a row for each language, but was missing Chinese. However, older vids did have Chinese translations.
So the translations tab presumably queries for the latest revision, and then looks to see which languages this has. It finds no Chinese – therefore, it shows no Chinese translation.
But when you go to add a Chinese translation, the node form queries for the most recent revision in Chinese, and finds one. So the form contains field values which are already translated.
Saving the node in Chinese creates a new revision across all languages (with the unaffected languages simple copies, AFAIK), and so then the problem is fixed.
Comment #16
rp7 commentedI can reproduce this issue. The (draft) translation is not available in the node_field_data table and this results the translation is not returned in, for example,
$node->getTranslation('hu')or$node->getTranslationLanguages().To reproduce this programmatically:
Comment #17
kunalkursija commented@bahuma20 - I think marking revisions as 'default' only makes sense for 'published' and 'archived' states and they make node status 1 & 0 respectively(i.e: Just what the default editorial workflow does).
With patch in #10, No doubt an entry to 'node_field_data' is made. But one problem I noticed after applying the patch was we are losing access to the 'latest version' tab for the newly created translations.
Comment #19
andrew answer commentedThe #10 patch is good for a new drafts; but we need to fix existing drafts (without publishing, which is not always possible, because of draft can be still in 'approval' phase).
The only way I found is set all Drafts to Archived state and back; this works because it creates default revisions in workflow.
Comment #20
gung wang commentedThis patch is working on my site (Drupal 9.2.18).
However, there is another issue about the "Draft" of French translation:
- the orphan data (fr) is still in the table
node_field_revisionafter I deleted the translation of French (fr)- See queries:
I applied this patch (https://www.drupal.org/project/drupal/issues/2815779), but it seems not working. The orphaned translation (Draft) is still in the table
node_field_revisionComment #22
seanb#10 solved my issues in content revision views (for example, we can now show the node type for translations created as a draft).
Regarding #17
Since the translation has never been published, having a "latest version" tab for the new translation wouldn't make sense from my perspective. When creating a new node as a draft (not a translation), we also don't show the "latest version" tab. The latest version only makes sense to me when there is a published / unpublished version to compare it to.
Looking at the failing tests, all fails seem to be testing behaviour that feels "broken". So +1 for this change from me.
Comment #24
eduardo morales alberti+1 to this, but it should treat the translations that already have the draft version but do not have a default revision.
Comment #25
anchal_gupta commentedRerolled patch #10 against 10.1x.
Comment #27
eduardo morales albertiTests were reviewed.
Comment #28
phot0x_sami_m commentedHello, just ran into this issue! Wondering if there is any update or fix fix planned for this still as I think it's a pretty breaking change - I can help resolve the issue but do we know what is causing it?
Comment #29
dabblela commentedI had implemented this same fix (in a slightly different way) and it was causing data loss so I want to caution everyone against using the patches here.
Steps to reproduce:
- Installation of Drupal this patch + content moderation and moderation/translation enabled on a content type
- Enable two languages (Spanish and French)
- Create a published node in English
- Create a published translation in Spanish
- Save a draft of the Spanish translation
- Create a new draft translation in French
The default Spanish translation is actually deleted from
node_field_data, so if you visit the published Spanish page you'll get the English version, and if you visit the revisions page for Spanish you will get the English revisions.Setting the default translation causes this bit of code to fire in \Drupal\Core\Entity\Sql\SqlContentEntityStorage::saveToSharedTables:
which actually deletes all of the node's records from the
node_field_data. They're supposed to be repopulated by$node->save(), however when a node is saved from the add translation form it only has the source and new translation languages so the table never gets fully repopulated.Comment #30
dabblela commentedFollowing up on #29, I created #3329066: Creating a new translation may delete translations with drafts with some more information. The data loss actually comes from a core issue, but this patch makes it more likely to happen.
Comment #31
fathima.asmat commentedPatch 6 works for new translations but does not affect existing draft translation that should be treated as default revision when there isn't a published translation. So we may need something like:
Patch attached.
Comment #32
fathima.asmat commentedComment #34
dabblela commentedAgreed with @fathima.asmat, this definitely needs a way to update the default revision of a translation that has never been published. I think it can be done with this code, but I'm a little wary of potentially looping through every revision of a node so I took a different approach.
I was able to fix the issue here by:
1) applying the patch from #3150294: New translations for moderated nodes are not created in the initial workflow state
2) setting the default moderation state to "Default moderation state" and
3) creating a new state called "Pre-published" with "Default revision" enabled
This approach has worked better in testing with modules that use `hasTranslationChanges` (eg, paragraphs), I think because the default revision field is set earlier in the entity save process.
Comment #35
mibfire commentedhttps://www.drupal.org/project/drupal/issues/3088790#comment-14937914
This patch doesn't work in the following case:
However this scenario works with https://www.drupal.org/files/issues/2020-06-09/3088790-10.patch and https://www.drupal.org/project/drupal/issues/3329066#comment-14962117 patches. Plus this works with https://www.drupal.org/project/drupal/issues/3088790#comment-14839675 too.
Comment #37
v.dovhaliuk commentedA new patch resolves an issue if Content Moderation is enabled for the Taxonomy, and
$revision_ids = $storage->revisionIds($entity);throws an errorundefined method <code>revisionIds()Comment #40
thomwilhelm commentedOK so I ran into this issue recently, clearly translations + content moderation is a very complicated subject in Drupal, but I thought it would just be worth doing a bit of research into why this happens now.
So I'm working on a site that uses translations + the old workbench moderation module, and have been looking into migrating to content moderation. Everything went pretty well, but some of our internal Functional tests were broken in a strange way. Namely the following case (basically comment #16 on this ticket):
Now when you go to any view that relies on node_field_data, the Japanese version of the page isn't there. In our case this mean it wasn't appearing on both /admin/content and a custom view we'd built to show pages that were "Draft content".
I started digging into whether this was an issue on Vanilla Drupal 11 and I found that is it. The draft version of the Japanese page doesn't appear at all on /admin/content, and while it does appear on the view of moderated content /admin/content/moderated, it's Content type field is empty.
Basically a new entity will be saved as the default revision (even being created in draft), but a new translation will not. This is due to the logic that's in content_moderation/src/EntityOperations::preSave:
If you review isDefaultRevisionPublished, in content moderation this returns true if any of the translations are published (which in this case, the English translation is published) so this returns TRUE. Whereas in workbench moderation it was only checking if the translation language was published (which in this case would have been Japanese) so this returns FALSE.
As content moderation forked workbench moderation, you can see this behaviour diverged in core here: https://www.drupal.org/project/drupal/issues/2862988
In that issue, if you read comment #13 and #14 you can see basically the same issue we are experiencing now was discovered, and the following fix was added:
Which is interesting as that's basically the same logic this issue has landed on. So when this this get removed?
This
$entity->isNewTranslation()line was then removed as part of the following issue: https://www.drupal.org/project/drupal/issues/2860097To try and move this forward, I've rebased the MR created by @EduardoMoralesAlberti onto a new MR targeting Drupal 11.x, added some extra test cases to the Content type label not appearing in the moderated content view, and made an attempt to fix up any behaviour that this changes (note: it's still marked as failing, but I believe that's due to unrelated issues in CI).
I'd welcome any feedback from anyone more familiar with translations / content moderation.
Comment #41
thomwilhelm commentedComment #42
smustgrave commentedHaven't reviewed yet but issue summary should follow the standard template please. Current steps are saying install Drupal 8.7.8 so definitely out of date.
Thanks!
Comment #43
thomwilhelm commentedCreating a new up to date issue summary with a clear test case.
Comment #46
smustgrave commentedThis will need a rebase.
Am going to voice a concern though that all the test updates make me nervous. That may they were updated just to get to green but could be causing a regression
Would like sub-maintainer review of this eventually.
Thanks!
Comment #47
thomwilhelm commentedBranch is up to date against the latest main. Pipeline failed but I believe that's unrelated to these changes.
Agree ideally we wouldn't be changing tests, however the proposed change in this issue required the changes that were made.
Comment #48
mahdeI am facing similar issue and not sure if it's related.
Steps to reproduce:
When creating the French draft, I see the field values from the Draft version ff the English page instead of the Published English version.
Then, If I deleted the French draft page and add it again it works fine and pull data from the published English.
Also, I have noticed that the French revisions are having the wrong moderation state in the revision list and all of them are showing published.
Also, if I delete the translation and add it again, I keep see the old (deleted) revisions for French translation in the revisions list.