Problem/Motivation
#253157: Add "Translate own content" permission, rename "Translate content" to "Translate all content" was committed in earlier versions of Drupal 8 which allowed users to translate their own content. However, this feature was later removed from the core and it made https://www.drupal.org/node/1776752 obsolete.
Nowadays, multilingual community sites still have a requirement to allow users to translate their own content.
Proposed resolution
Add a new single global permission, allowing the user to translate any content (entity) that the user can edit.
Remaining tasks
None
User interface changes
The permission currently looks like:
translate editable entities:
title: 'Manage translations for any entity that the user can edit'
API changes
Data model changes
Comment | File | Size | Author |
---|---|---|---|
#49 | 2972308-49.patch | 18.76 KB | johnwebdev |
#48 | 2972308-47.patch | 62.08 KB | jpatel657 |
#41 | interdiff_35-41.txt | 694 bytes | johnwebdev |
#41 | allow-users-to-translate-editable-content-2972308-41.patch | 18.82 KB | johnwebdev |
#35 | interdiff_26-35.txt | 767 bytes | johnwebdev |
Comments
Comment #2
mbovan CreditAttribution: mbovan at MD Systems GmbH commentedConnecting with a related issue.
Comment #3
mbovan CreditAttribution: mbovan at MD Systems GmbH commentedInitial patch that allows translations with
translate editable content
permission.Comment #4
googletorp CreditAttribution: googletorp as a volunteer and at Reveal IT commentedI think we should have a test for this.
Comment #5
mbovan CreditAttribution: mbovan at MD Systems GmbH commentedAdded translation access UI tests for node entities.
Comment #6
plachThis solution makes sense to me, as it brings back the ability to translate own content without complicating too much the translation permissions.
What about
translate editable entities
for consistency with the global permission?This permission is slightly different from the other "Translate ..." ones because it also includes create/edit/delete permission over translations (implied by the edit access), whereas the other ones alone only grant access to the translation overview page. I'm wondering whether we can differentiate its name a bit more to make this clearer. Maybe something like "Manage translations for any entity editable by the user"? Or maybe we could add a description along those lines?
I think this test should be merged with the ones in
ContentTranslationWorkflowsTest
to make sure we are not introducing regressions in the two workflows CT supports. I manually tested this patch and it seems it's all working fine, but it would be good to have automated tests proving that.Btw, while testing this I found #2974146: Content translation overview operation links may lead to an access denied page.
Comment #7
mbovan CreditAttribution: mbovan at MD Systems GmbH commentedThanks for the review @plach.
Addressed #6.1, #6.2, #6.3.
Comment #8
plachThis is looking good, thanks!
Why are these changes needed?
User translator is a confusing name: I read the comments multiple times to figure out the difference with the regular translator with no luck. What about renaming it to
entityOwner
?Can we move this block at the bottom of the test? This way all other roles are tested with the same entity, otherwise we might leave the door open to weird edge cases.
Comment #9
mbovan CreditAttribution: mbovan at MD Systems GmbH commentedThanks!
1.
Apparently, this code was never reached with the existing tests as editors don't have enough permissions to edit/delete translations while translators don't have sufficient permissions to edit/delete content.
Since the entity owner case tests this part, "Edit"/"Delete" buttons are displayed second in the list (Original content "Edit"/"Delete" buttons are first and there is no Italian translation). Thus, index 1.
The previous change that ensured the order of languages is not needed anymore.
2. ✔
3. ✔
The change request draft is available at https://www.drupal.org/node/2975283.
Comment #10
mbovan CreditAttribution: mbovan at MD Systems GmbH commentedThe missing #9 patch. :)
Comment #11
plachLooks good to me!
@berdir asked in Slack about this:
First of all, I have to admit CT's access control implementation is definitely not straightforward and it might be possible to simplify it. I didn't follow the conversion to the new routing system and how the "old" access callbacks were migrated, however after looking at the code for a while, I think it's safe to assume this difference:
CTH::translateAccess()
is meant to check whether the user can perform a particular operation on a translation. This logic can be altered per entity type if a dedicated CTH is defined.content_translation_translate_access
is meant to check whether the user has any translation permission, and is meant to control access to the translation overview. This logic can also be altered per entity type, however this is done via a legacy entity info key.Comment #12
catchWould be good to get a second opinion on the permission name, so tagging for usability review. It would be nice to find something that's more self-explanatory (without the description) if we could, but apart from 'translate entities if editable' which is a mouthful and not necessarily better, I can't think of anything.
Comment #13
xjmSetting NR for #12. Thanks!
Comment #14
xjmAlso I'm not sure this belongs in the release notes; there is no disruption from the change that site owners would need to be aware of as the current implementation simply adds a new permission. The change record should be sufficient. Thanks!
Comment #16
jigariusGreat! Works very well with the content side of things. However, it didn't work with menu links. I have given a user to update menus and menu links with hook_entity_access(). I can see the "traduire" link in the contextual menus, but when I click on it, I get access denied.
Update: Right after I posted this comment, I found that things work well with menu links as well.
Comment #17
BerdirSo, I realized that we are missing support for content_translation_language_fallback_candidates_entity_view_alter(). That has its own hardcoded access check and does *not* use either of the other two API's :-/.
I've started working on that and testing it, but realized again that we literally have inconsistencies in our inconsistencies:
* First there is the problem that viewing an entity on its own route doesn't trigger that hook anymore, see #2978048: Unpublished translations should fallback to the original language because that uses a different context. So we can only reproduce that by viewing the translation through another entity and the entity reference formatter.
* Second, entities that have their own status (and corresponding access logic) behave completely different behavior from entities that don't and only have a content translation status, which only affects translations. Specifically, the first result in an access denied without the other issue while the second will actually allow access to the translation. Both will be standardized/fixed with the other issue.
To test this, I access the translation both through the route as well as an entity reference field on another entity. With the other issue, we can update that to make the two checks consistent.
After that, I realized that we have some cacheability issues as well, because checking entity access can do anything, for example the edit own permission that we happen to be testing here, that means we need to vary the result by-user. Managed to test that by accessing the entity with two users with the same edit own permission but only one is the owner. And refactored the access checking and logic in the hook to pass that through. I also re-used the handler translation access API in there.
Comment #18
BerdirI realized that the access check should only be done in case the entity is not published.
Forgot that this is only done here, so I created #3016788: content_translation_language_fallback_candidates_entity_view_alter() should only check access if the entity is unpublished but now closed it again.
Comment #20
jigariusThe same should also be done for config translation after this one gets merged. I tried setting up webforms and provide granular access to some roles - it was a nightmare! Currently, a person can either translate all config or they cannot translate anything. So a similar change in that sector will also be a huge leap for translations.
Comment #22
BerdirBoth before and after, the logic is basically that you need *update* access to *view* an unpublished translation.
I'm wondering if this shouldn't just check $entity->access('view') instead, which will consider the language.
For example, we have a use case that allows access to an unpublished node through a special URL token, similar to https://www.drupal.org/project/preview_link for exmple.
That works fine for the default translation, which considers the view access operation, but it doesn't show any translation as they are filtered out by this logic.
It does come with a non-trivial overhead, checking access is expensive, especially when using node grants, but we can keep the logic to only do that if the node is unpublished.
Comment #23
BerdirHm, so one problem is that unpublished access in core is very inconsistent, there's only a permission to access your own, and only the content_translation module offers an access all unpublished content permission.
I decided to extend it so that we are checking both, first translate and then fallback to entity view access of that specific translation.
Comment #26
BerdirFixing the test by converting that test to use EntityTestMulRevPub and added a dedicated permission to view unpublished tranlsations, this allows to test the entity view access part and it also makes view_unpublished_translation vs. view_unpublished_translation_reference more consistent. In the referenced issue, we will then be able to change it to always 200 and the correct translation, so basically merge those two keys together again.
Comment #27
benjifisherFor the permission names, I suggest following the example of #2914486: Add granular permissions to the Layout Builder. For example,
'%entity_type: Configure layout overrides for @entity_type_plural that the user can edit'
This is closer to what I see in the issue summary here ("allow translating content that the user can edit") than what I see in the latest patch ("Manage translations for any entity editable by the user").
After quite a lot of discussion on that issue, I think it was decided to use fairly long titles instead of adding descriptions.
For final usability review, it will help to update the issue summary with the text used in the patch. I am adding a tag for that task.
Comment #28
geek-merlinTested this manually on a distribution with group content permissions. It fixes the issue of group content editable but not translatable.
Comment #30
Erso CreditAttribution: Erso commentedGreetings,
For who are having problem "own content's translating" , I have found a round way to do.
1-Make a "H" view for your "Z" content. (fictional example names)
2-Take permission to view of Z content from all of users.
3-Give permission to see "See own content for Z" to your users, "able to translate Z", "add translate", "edit translate", "delete translate".
4-For H view, disable SQL rewriting add contexual filter to your link to connecting url with right node (for example with unique naming).
5-Use rabbit hole to transfer Z content visitors to H view. So even they don't have rights to see Z content type, with disabled SQL rewriting, they may see it without able to reach translate page.
With this, you may give proper permissions for translation. Yes it gives you a lot of workings, no more layout or node display and increase view usage, but I reached total solution . We need a general update on all of permission page's details and some rights. I hope this solution would be helpful for some.
Have a nice day.
Comment #31
michaelvanh CreditAttribution: michaelvanh commentedTested this patch with drupal 8.7, so far it seems to work well without issues. Any chance this type of patch could be committed to the core in a reasonable timeframe? Looks like a key feature for a user based application.
Comment #33
s-jack CreditAttribution: s-jack commentedThank you for creating the #26 patch.
It is extremely disappointing that this issue has been postponed from 8.3 to 8.8.
I want to apply this #26 patch, but is it possible to revert?
Even if a patch is applied to my test site, I'm worried that it may affect the database.
Comment #34
johnwebdev CreditAttribution: johnwebdev commentedUpdated the issue summary to reflect what is currently going on in the patch as per #27.
Comment #35
johnwebdev CreditAttribution: johnwebdev commentedFixed deprecation notice.
Comment #36
johnwebdev CreditAttribution: johnwebdev commentedComment #37
benjifisher@johndevman:
Thanks for updating the issue summary to match the current patch.
I still think that you should follow the example of the Layout Builder module (as I said in #27): long title, no description, "that the user can edit" rather than "editable by the user".
Reference: #2914486: Add granular permissions to the Layout Builder and the related change record Made translations permissions more granular (translate all and translate own).
From Comment #6, it looks as though the permission used to be closer to my suggestion. I do not see any discussion of the permission name after my comment in #27.
Even if you disagree with what the Usability team came up with for the Layout Builder, I hope you will agree that consistency is a good thing (for usability, maintainability, probably other reasons). Please use wording similar to what the Layout Builder settled on: something like
Note that I replaced "entity" with "content". This is consistent with Word Choice (part of User interface standards > Interface text in the Develop guide):
I think that is accurate. I have not looked at the code, but Comment #20 implies that this issue only affects content entities, not config.
Comment #38
benjifisherComment #39
BerdirUsing entity is consistent with existing permissions in the content translation module though. You can see that in the context of this patch.
I think the use of content for entities is tricky, because not all entities are content and next to using content for nodes, you need a way to separate it, and be able to say this affects all (content) entities, and this other permission only affects nodes/content.
(I do agree with the wording otherwise)
Comment #40
benjifisherIn other words, it is too late to be consistent?
OK, I think we can agree on this:
with no description.
Comment #41
johnwebdev CreditAttribution: johnwebdev commentedThank you @benjifisher!
I've updated the permission title and removed the description.
Comment #42
benjifisherThe interdiff looks good. I am updating the issue description and removing the "needs usability review" tag.
I have not done any code review nor testing, so I will leave it to someone else to decide whether it is RTBC.
Comment #43
johnzzonHad a look at the patch and it looks great!
Comment #44
mpp CreditAttribution: mpp commentedSmall nitpick on language but other than that RTBC++
+ title: 'Manage translations for any entity the user can edit'
Comment #45
johnwebdev CreditAttribution: johnwebdev commentedThis should probably be filed against 9.1.x now.
Comment #46
catchPatch looks sensible to me, but it needs a re-roll against 9.1.x
Comment #47
jpatel657 CreditAttribution: jpatel657 at Trigyn Technologies Ltd commentedComment #48
jpatel657 CreditAttribution: jpatel657 at Trigyn Technologies Ltd commentedReroll has been done.
Comment #49
johnwebdev CreditAttribution: johnwebdev commentedRerolled.
#48 That patch contains a .orig file and is not correct.
Comment #50
johnwebdev CreditAttribution: johnwebdev commentedComment #51
henriklarsson CreditAttribution: henriklarsson at Kodamera AB commentedReroll looks good. Back to RTBC!
Comment #52
catchFixed these on commit and pushed to 9.1.x, thanks!
Comment #54
johnwebdev CreditAttribution: johnwebdev commentedPublished the change record