Problem/Motivation
Deleting a translation leaves behind orphaned revisions that can never be retrieved using the UI. The easiest way to describe the problem is to read the steps to reproduce that show the content of the node_field_revision table.
- Steps to reproduce:
- Install Standard profile in English and enable
content_translationmodule - Add a language (for example French) (
admin/config/regional/language) - Enable content translation of article bundles (
admin/config/regional/content-language) - Create an English article
mysql> select nid, vid, langcode from node_field_revision; +-----+-----+----------+ | nid | vid | langcode | +-----+-----+----------+ | 2 | 6 | en | +-----+-----+----------+ 1 row in set (0.00 sec) - Edit the edit English article (you now have 2 revisions)
mysql> select nid, vid, langcode from node_field_revision; +-----+-----+----------+ | nid | vid | langcode | +-----+-----+----------+ | 2 | 6 | en | | 2 | 7 | en | +-----+-----+----------+ 2 rows in set (0.00 sec) - Create a French translation
mysql> select nid, vid, langcode from node_field_revision; +-----+-----+----------+ | nid | vid | langcode | +-----+-----+----------+ | 2 | 8 | fr | | 2 | 6 | en | | 2 | 7 | en | | 2 | 8 | en | +-----+-----+----------+ 4 rows in set (0.01 sec) - Edit the English node
mysql> select nid, vid, langcode from node_field_revision; +-----+-----+----------+ | nid | vid | langcode | +-----+-----+----------+ | 2 | 8 | fr | | 2 | 9 | fr | | 2 | 6 | en | | 2 | 7 | en | | 2 | 8 | en | | 2 | 9 | en | +-----+-----+----------+ 6 rows in set (0.00 sec) - Delete the French translation
mysql> select nid, vid, langcode from node_field_revision; +-----+-----+----------+ | nid | vid | langcode | +-----+-----+----------+ | 2 | 8 | fr | | 2 | 6 | en | | 2 | 7 | en | | 2 | 8 | en | | 2 | 9 | en | +-----+-----+----------+ 5 rows in set (0.00 sec) - At this point:
- although we have a row for a French translation the node is showing as untranslated on
node/2/translations - And on the revisions tab you can only revert to revision 6 & 7.
- although we have a row for a French translation the node is showing as untranslated on
- Hacking the URL to revert to revision 8... does magic and the french translation appears again...
mysql> select nid, vid, langcode from node_field_revision; +-----+-----+----------+ | nid | vid | langcode | +-----+-----+----------+ | 2 | 8 | fr | | 2 | 10 | fr | | 2 | 6 | en | | 2 | 7 | en | | 2 | 8 | en | | 2 | 9 | en | | 2 | 10 | en | +-----+-----+----------+ 7 rows in set (0.00 sec)
We need decide what the expected behaviour should be. i don't think deleting the current translation revision is the expected behaviour. It is a halfway house between removing all revisions that pertain to the translation and just creating a new revision without the translation.
Discovered whilst working on #1239558: Deleting an entity with revisions and file/image field does not release file usage of non-default revisions, causing files to linger.
Proposed resolution
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #19 | 8x9x-2815779-19.patch | 1.02 KB | joseph.olstad |
| #19 | 8x8x-2815779-19.patch | 1.02 KB | joseph.olstad |
| #19 | 8x7x-2815779-19.patch | 1.02 KB | joseph.olstad |
| #10 | interdiff-2815779-7-10.txt | 921 bytes | mohit_aghera |
| #10 | 2815779-10.patch | 1.02 KB | mohit_aghera |
Comments
Comment #2
hchonov1. The node is showing as untranslated as you have removed the french translation from the default revision and now the default revision (revision id 9) has only the english translation.
2. I've thought that on the revisions tab you can revert only the actual translation, but I am not sure why revision id 8 is not listed there. And it is strange that while you revert the english translation you get back the french one.
If the translation is removed from all available revisions then the history is also lost which in some cases might be undesirable as well.
Comment #3
alexpottWell, if revisions are on, the totally non-destructive possibility is just creating a new revision without the translation. And then there is no delete of anything. Which is how I expected it to behave.
Comment #4
alexpottSo one problem with the current approach is that if the translation contains a sensitive file (maybe one containing passwords or wsomething) without being able to delete it through the UI you have no way to delete the orphaned revision. Which bring #2722307: Move translation based conditions into database query on revisions overview page into play.
Comment #5
hchonov+1
If we remove a translation through the UI then I would expect exactly the same to happen.
Comment #6
timmillwoodIt seems there are two options
Option 2 seems to be the better solution but goes against how Drupal works on a single language site. If there was one language and we delete it the whole entities goes, we don't just created a new revision (although we should).
Comment #7
hchonovThere is no difference between a single or multi language site. Consider having an entity with multiple translations and deleting the translations one after another resulting into an entity with a single translation and removing it at the end deletes the whole entity.
Lets see if there are some test failures if we create a new revision when removing a translation through the UI.
Comment #10
mohit_aghera commentedRe-rolling patch and try to update testing errors in patch.
Comment #13
matsbla commentedThis makes it more difficult for sites to comply with GDPR as it can be difficult to remove unlawful personal data.
Comment #14
hchonovWell this depends on how you look at it. If we consider revisions as a backup, then everything is fine. We only have to ensure that the revisions cannot be accessed. If you still want to delete a specific translation from all revisions, then this is still possible even with the current issue:
If desired we probably could provide an API method which will perform those steps e.g.
\Drupal\Core\Entity\TranslatableRevisionableStorageInterface::removeTranslationFromAllRevisions($entity_id, $langcode)Should we cover this in the current issue and do we really need such a method?
Comment #15
matsbla commentedI don't think this is the case. If the revision contains personal information that should never have been added, or the information that a user have the right to get removed, it doesn't really matter if it is published or not. To comply with GDPR the data need to be irreversible deleted. Here is an issues with a similar problem #2945956: Allow removing translations in pending revisions
Comment #19
joseph.olstadstraight up reroll.
I'm observing the orphaned revisions in 8.7.10 using a default language and a second language.
patch seems to help. However, what I'm really trying to figure out is why there's a new english revision when I only updated the translation.
The reason why I started looking for a patch is because I'm trying to resolve a bug with forward draft revisions in a second language when using access_unpublished the non-default language access key doesn't bypass the access , and if I force it, the english revision is shown, I debugged deeply, and came accross the orphaned revisions, and was looking into why content moderation seems to behave this way. I haven't found a patch that satisfies yet.
node_revisions only ever has the default language revision, node_field_revision has the other language and default language.
node_field_revisions has twice as many entries as node_revision
select nid, vid, langcode, revision_uid, revision_log from node_revision where nid = 7460 order by vid desc ;
select nid,vid,langcode,status, title,uid,default_langcode,content_translation_source from node_field_revision where nid =7460 order by vid desc;
Comment #20
joseph.olstadfound a patch that might address what I am looking for
#2725523: Add a revision_parent field to revisionable entities
Comment #25
hkirsman commentedAfter adding the patch I could not see a decrease in entries in node_revision table after deleting translation.
Also worth mentioning that this issue also creates revision pages potentially listing 0 revisions (or less than it should) as the query is made against all revisions for node (even the orphaned ones). This fixes it https://www.drupal.org/project/drupal/issues/2916172
Comment #29
smustgrave commentedThis issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.
Did not test
But for tests requested in #7
Comment #31
marcusml commentedThis doesn't seem to be true (anymore at least). I'm currently trying to clean up translations from old revisions. Removing a translation from a revision and calling save() on it results in a new revision being created with the translation removed. Instead of the translation being removed from the loaded revision.
I haven't yet found a way in which the Entity API allows me to remove a translation from a revision. Setting
$revision->setNewRevision(FALSE);doesn't make it work either.Comment #32
facine commented@marcusml, you need to set syncing flag to TRUE or a new revision will be created.
https://www.drupal.org/project/drupal/issues/2803717#comment-13080838
Comment #33
liam morland