Problem/Motivation
There were a lot of optimizations for node revisions and translations shortly before 8.0. However, they caused a regression when trying to view revisions of a node that is not translated into the current language.
NodeController::revisionOverview() is supposed to filter the list of revisions to only show those revisions that affect the currently shown translation of the node.
In case that the requested node translation doesn't exist and a language fallback was applied, the list of revisions is erroneously empty instead of showing the revisions that affected the fallback translation.
Proposed resolution
Filter the list of revisions by the current language of the node (with language fallbacks applied) instead of the current content language.
Remaining tasks
None.
User interface changes
None.
API changes
None.
Data model changes
None.
Comment | File | Size | Author |
---|---|---|---|
#57 | revisions_for_node_without_transl-2713587-57.patch | 4.93 KB | tduong |
#57 | interdiff-2713587-40-57.txt | 978 bytes | tduong |
#40 | revisions_for_node_without_transl-2713587-40-test_only.patch | 3.45 KB | tduong |
#40 | interdiff-2713587-38-40.txt | 2.13 KB | tduong |
#38 | interdiff-2713587-35-38.txt | 843 bytes | tduong |
Comments
Comment #2
Gábor HojtsyHm, that may be a bit confusing, given the view tab deals with fallback, so you would see something, go to its revisions and see something else :/
Comment #3
BerdirWhat would be confusing exactly? My suggestion or what's there at the moment?
IMHO, the UX of the language filtering is *really* bad right now. For example, at the moment, you might not even see the current revision if it didn't change in your current language.
The changes that we made might have improved things for some use cases, but we also made three steps backwards for many other scenarios:
* Default revision might not be visible, as mentioned. IMHO, we should always display that.
* No indication that some revisions might not be shown
* No revisions at all if node doesn't have a translation for the current language.
Comment #4
Gábor HojtsySo the current behavior may have flaws, but what you see in View is what you see in Edit is what you see revisions for in Revisions, right? I think that is generally a good pattern. I can see how that is problematic when View falls back on other things but Revisions does not. Since you are using admin language as well, do you think this is related to #2677778: Administration pages language setting makes it impossible to edit content translations for some roles and/or #2189267: When content language detection is different from interface language detection, the detected language is not applied to the rendered content?
Comment #5
BerdirNo, that's not the case.
Just create content and select "Not specified" as language. You can view it, you can edit it, everything works fine. But there are no visible revisions, never will be.
View has a fallback, edit in a way too, revisions has no fallback at all.
Filtering only makes sense if an entity has more than one language, and even there it is IMHO filtering too much.
Comment #6
Gábor HojtsyI think we agree that if there is only one language, it should not filter. I am not sure about including eg. the current revision if its not in the current language, if you revert to there and loose translations, that will be a data loss. (Or that revert needs to work differently from the others).
Comment #7
tduong CreditAttribution: tduong at MD Systems GmbH commentedCan reproduce. Here a patch and test. Needs to be improved, but now I have to leave. I'll do it tomorrow.
Comment #9
BerdirWhat you are testing now is changing the language of a node. That's slightly different to the defined case. Lets make a new node instead with some revisions.
Comment #10
tduong CreditAttribution: tduong at MD Systems GmbH commentedTesting with new node (langcode as UND), site langcode as EN, edit node settings langcode as EN and create new revision, checking revisions overview where both revision messages are displayed.
Comment #12
BerdirA comment that explains this condition would be good. Explain when and how we filter.
Don't change the language code. Just keep it UND. We just need two revisions so the revisions tab is visible at all.
Comment #13
tduong CreditAttribution: tduong at MD Systems GmbH commentedDone.
Comment #15
tduong CreditAttribution: tduong at MD Systems GmbH commentedChanged comments and dropped some unneeded lines.
Comment #16
Gábor Hojtsy@berdir asked me to review this issue. The meat of the fix is as follows:
I agree this fix is an improvement. The comment needs English cleanup though. (Update: crossposted, seems like this got fixed in the meantime).
Comment #18
mkalkbrennerFirst, showing all revisions when the node is 'untranslated' is how it is meant to work!
So we don't need to discuss that :-)
But I'm not sure if this "cosmetic" patch is the right solution.
Obviously function hasTranslation() doesn't handle LANGCODE_NOT_SPECIFIED or LANGCODE_NOT_APPLICABLE:
I wonder if the change timestamp tracking works for these nodes where the revision table is currently erroneously empty. The ChangedItem code uses hasTranslation() as well.
As far as I remember plach and myself were of the opinion that there's always a "translation". I wonder if the LANGCODE_NOT_SPECIFIED key exists in the $this->translations array above.
Comment #19
BerdirI think hasTranslation() works fine for those language codes.
However, the "current content language" is never UND. It's en or de or something. So hasTranslation('en') correctly returns FALSE.
Note that UND is just one of the cases that this patch fixes. Another is looking at a node that is EN and has no translations and your current content language is DE. Then this will also show all revisions, which IMHO is correct, an empty table there weird in that case.
However, if you go one step further, you can just as easily run into the following scenario if you have 3 languages: You have an EN node with a DE translation and your current content language is ES. What should you see then? IMHO, I'd prefer all revisions over an confusing empty table, possibly with a message that says that the node has no translation for your current content language and that everything is shown?
My initial proposal of checking hasTranslation() of the current revision would "solve" that as well and in that case, also show all revisions.
Also, repeating my question from above, what about the current default revision? IMHO, I'd expect that to be visible always. That *is* what is being used right now, even if it didn't change the current language. So I'd expect that to be always visible?
Comment #20
mkalkbrennerComment #22
mkalkbrennerWhich node view is shown in that case? I second Gabor that the revision table should be in sync with the view.
Comment #23
mkalkbrennerOK, like expected, my test only patch from #20 fails.
I think it shows that the problem with the revisions table is just one symptom.
When saving a new revision of a ContentEntity having LANGCODE_NOT_SPECIFIED its changed timestamp isn't updated.
I'm sure we'll find more issues regarding the languages LANGCODE_NOT_SPECIFIED and LANGCODE_NOT_APPLICABLE.
I think that requires a deeper inspection of the issue...
Comment #24
BerdirWhat you get is the node in the language that Drupal chose for you, with fallbacks applied.
If you want the same behavior as node view, then you need switch the $langcode from the current content language to the current language of the node.
also, your test if flawed. ChangedItem uses the REQUEST_TIME constant. sleep(1) does nothing to change that. You can't change it like that, you need to edit the node through the UI to do that.
Comment #25
mkalkbrennerYes, you're right! My fault.
I had a closer look at the test. It first creates a node in 'en' and then switches its langcode to 'und'.
It seems that the function call hasTranslation('und') returns TRUE afterwards. So the ChangedItem seems to work as it should.
So when your content language is 'es' and there's no corresponding translation of the node, it falls back to its 'und' translation, right? (At least in common setups.)
Lets assume that a site has three languages: 'en', 'de' and 'es'.
A node is "translated" to 'en' and 'und'.
If the content language is set to 'en' the English translation will be shown. If the content language is set to 'de' or 'es' the node's 'und' translation will be shown as fall back, right?
If we agree that the content of the revision table should be in sync with the current node view, the revision table has to show the revisions that affected the 'und' translation if the content language is set to 'de' or 'es'.
This will not happen with the latest patch which just handles the case that the node only consists of a single language (better: a single translation).
From my point o view the right solution would be to apply the language fallback first if necessary before filtering the content of the revisions table. This should solve the initial bug report here and my more complex example.
BTW I proposed a more sophisticated revisions tab when we worked on translation revisions. But this has been refused by the maintainers. I therefor created https://www.drupal.org/project/revision_ui to incubate a really good solution. I hope to find the time to work on this soon.
Comment #26
Gábor HojtsyI don't think its valid that an entity has a 'und' language and something else. It either does not have a 'und' language or it only has a 'und' language, right?
Comment #27
BerdirYes, you can't translate to or from UND anyway. But the example still makes sense, just switch UND with any other "real" langcode.
As I said, upcasting automatically applies the language fallback. So if we do what you are suggesting, we already have the node in the correct language and would just filter on that. Fine with me, solves my problems mostly too. I still think it would be worth to show the language somehow, since it might not be visible in the backend. And figure out what to do with the default revision.
Comment #28
tduong CreditAttribution: tduong at MD Systems GmbH commentedIn the code: get the node language instead of current content language.
In the test:
Now what is displayed...
IMO it should display all language revisions at least in one place (e.g. for the original node revisions, like I also check in the test), but agree that if there are a lot of revisions it could be a "noisy view" then sure we need to display also the "revision langcode" for each row. What should be the correct result ?
Comment #31
mkalkbrennerWe had a long discussion about this before 8.0.0 release. The consensus was not to do that because Drupal 7 didn't do that as well. In Drupal 7 every translation had it's own revisions.
From the user's perspective displaying all revisions across all translation would be a new feature compared to Drupal 7.
As I already mentioned in #18 initially I totally agree, that we have a bug here, but it should not be mixed with that new feature.
That new feature is not that easy, because after just displaying all revisions across the translations you have to decide about the revision revert strategy. Could you revert hardly to any previous revision even if it means that you remove translations?
Again, a lot of questions like that have been discussed already.
Solving that requires a sophisticated UI protected by access rights.
I can invite you to join the Revision UI module for that.
Lets fix the bug now.
Comment #32
BerdirAgreed, showing all is a separate topic.
About the Revision UI. entity.module has a generic revision UI now, I think you should consider improving that instead of making another module that then wouldn't be compatible with that. It's not yet used for node, but we can change that.
Comment #33
tduong CreditAttribution: tduong at MD Systems GmbH commentedYep, agree it should be a separate issue.
Sorry, missing explanation: what I mean is that could be nice to just show all available revisions of a node, somewhere, like a "neutral history" of all revisions made, like chronological revisions overview (host or translated node). I don't know, it's just a personal opinion about a nice and clean overview feature I appreciate to use in any app/in general. Or maybe I'm just strange ;P
So, back to this bug issue, in the end what it is supposed to display is like it is in the test, right ? Why is it different for the UI... ?
Comment #34
BerdirAdding the @var is kind of unrelated now, since we don't use $node_storage anywhere where it wasn't already before.
$single_language can go away with the new approach, it doesn't matter anymore.
By getting the language from the node, we know that we always have at least one revision to show.
Since we remove $single_language, we need to update the comment, the first part doesn't matter anymore, remove it and the otherwise:
Only show revisions that are affected by the language that is being displayed.
Comment #35
tduong CreditAttribution: tduong at MD Systems GmbH commentedDone.
Comment #37
BerdirThere is no otherwise anymore. There is only one case. just keep the second sentence, without otherwise.
Comment #38
tduong CreditAttribution: tduong at MD Systems GmbH commentedDone.
Comment #39
mkalkbrennerJust to verify, is the difference described in #28 between the UI and the tests gone?
The deprecated entityManager() method is used multiple times in this controller. We should replace them all or none of them.
The setUp() of the test already contains ConfigurableLanguage::createFromLangcode('it')->save().
I suggest to remove these lines here and to add one additional language in the setUp() function.
Maybe that's too much, but I would like to see a test for the expected behavior if the languages of TYPE_CONTENT and TYPE_INTERFACE are set to different values.
Comment #40
tduong CreditAttribution: tduong at MD Systems GmbH commentedYep, now everything works as in the test.
1. I guess we want these fixes in another separate issue. Reverted it.
2. Done.
3. Discussed with @Berdir and he said that it is not necessary, we don't do anything here about TYPE_CONTENT and TYPE_INTERFACE that needs to be tested.
Comment #41
tduong CreditAttribution: tduong at MD Systems GmbH commentedCreated follow-up #2721573: Replace deprecated entityManager() in NodeController for comment #39.1
Comment #43
mkalkbrennerLooks good.
Comment #44
catchSo for me personally, I think we should just show all revisions - that's the actual revision history of the node.
Also:
Reverting doesn't delete anything, it creates a new revision and sets that as the default, so you can always get back to the previous state. Also what if you wanted to revert specifically to drop a translation you just added?
Patch itself looks fine, and I'm OK committing this - but can we open a follow-up - I don't think the issue summary nor the patch really covers everything going on in this issue.
Comment #45
alexpottI agree with @catch that the IS needs updating to reflect the current patch.
Reading through all the issue comments makes me feel a follow up issue to address the originally proposed solution of showing all revisions somewhere should be created - but as pointed out several times on issue that'd be a new feature.
Comment #46
catchOpened the follow-up #2722307: Consider showing all revisions on the revision overview.
Comment #47
tduong CreditAttribution: tduong at MD Systems GmbH commentedIS updated.
Comment #48
tduong CreditAttribution: tduong at MD Systems GmbH commentedComment #49
tduong CreditAttribution: tduong at MD Systems GmbH commentedComment #50
juliaschwarz CreditAttribution: juliaschwarz commentedI have the same problem with the Diff module: #2716087: Needs tests: Language is chosen from content not from context
Comment #51
mkalkbrenner@tudog has updated the issue summary.
But isn't it easier?
Problem/Motivation
NodeController::revisionOverview() is supposed to filter the list of revisions to only show those revisions that affect the currently shown translation of the node.
In case that the requested node translation doesn't exist and a language fallback was applied, the list of revisions is erroneously empty instead of showing the revisions that affected the fallback translation.
Proposed resolution
Filter the list of revisions by the translation language of the currently shown node instead of the requested translation.
Comment #52
Berdirrequested translation vs currently shown node isn't clear to me, otherwise that seems to be on the right track.
I would use the terms "Current content language" instead of "requested translation" and "Current language of the node (with language fallbacks applied) instead of "translation language of the currently shown node". The fallback stuff is important difference between the two cases.
Comment #53
tduong CreditAttribution: tduong at MD Systems GmbH commentedUpdated IS as suggested in the comments above.
Comment #54
mkalkbrennerI triggered a re-test in #40 and removed the Remaining tasks from the IS because this potential issue already exists regardless of the proposed patch here and is covered by #2722307: Consider showing all revisions on the revision overview.
Comment #55
mkalkbrennerre-test of #40 passed
Comment #56
catchComment #57
tduong CreditAttribution: tduong at MD Systems GmbH commentedFixed the 2 marked sniff violations. Needed a while to figure out that it was only about the unused import line :p
Comment #58
BerdirBack to RTBC then.
Comment #61
catchCommitted/pushed to 8.2.x and cherry-picked to 8.1.x. Thanks!
Comment #62
Gábor HojtsyYay, thanks!