Problem/Motivation
In current HEAD, when you delete an entity translation, the entire entity is deleted. Also, the UI of the delete forms for both the source entity and the translation do not make too much sense.
Steps to reproduce:
- enable the language and content translation modules, add a second language and enable translation support for nodes
- add a node in the site's default language and a translation for it
- go to
<secondary_language>/node/<nid>/delete
and delete the translation - observe how the original entity (the source translation) has been removed as well
Proposed resolution
Fix the delete forms and their UI. Here's some before/after screenshots:
Before - source node:
Before - node translation:
After - source node:
After - node translation:
Remaining tasks
Reviews: Done
User interface changes
The entity delete forms are now in a shippable state :)
API changes
Nope.
Comment | File | Size | Author |
---|---|---|---|
#144 | ct-delete-2486177-143.patch | 43.99 KB | plach |
#94 | Screen Shot 2015-05-14 at 1.12.57 AM.png | 28.17 KB | webchick |
#94 | Screen Shot 2015-05-14 at 1.08.54 AM.png | 31.33 KB | webchick |
#94 | Screen Shot 2015-05-14 at 1.09.25 AM.png | 37.92 KB | webchick |
#94 | Screen Shot 2015-05-14 at 1.00.38 AM.png | 40.09 KB | webchick |
Comments
Comment #1
amateescu CreditAttribution: amateescu for Drupal Association commentedAnd an initial patch.
Comment #4
amateescu CreditAttribution: amateescu for Drupal Association commentedFixed the log deletion message. The test-only patch from #1 is unaffected by this update and showed the correct failures.
Comment #5
dawehnerJust from looking at that it feels super wrong that a delete entity form, cares about translations ... kinda and also has some special behaviour.
You really don't need the ternary
Comment #6
dawehnerIt feels for me like clicking delete should always describe that we delete the entire thing.
Comment #7
amateescu CreditAttribution: amateescu for Drupal Association commentedThanks for reviewing :)
#5.1: As long as
ContentEntityInterface
provides the translation API throughTranslatableInterface
, me and @plach agreed that the genericContentEntityDeleteForm
has to take that into account.#5.2: Heh, fixed.
Are you referring to something else than the "After - source node:" screenshot from the issue summary?
Comment #8
Bojhan CreditAttribution: Bojhan as a volunteer commentedI agree with dawehner here. What about having "Delete" and then "Delete (only this translation)".
Comment #9
amateescu CreditAttribution: amateescu for Drupal Association commented@Bojhan, do you mean "Delete" in the delete form for the source language (the one that also has a warning now) and "Delete (only this translation)" in the delete form of the translation?
Edit: If we look at the "after" screenshots from the IS, that would mean:
"Delete (all translations)" => "Delete"
"Delete (this translation)" => "Delete (only this translation)"
Comment #10
dawehnerI think we talk about the actual node form?
Comment #11
Gábor HojtsyShould there be some way to delete the original translation as well?
Comment #12
Bojhan CreditAttribution: Bojhan as a volunteer commentedI talked to YesCT about this, we agreed that the current approach is OK. Having deleting on only the source.
But we should do some optimisations:
Comment #13
YesCT CreditAttribution: YesCT commentedI think we should see where we get redirected to after the deletion of one translation.
I suspect/hope it redirects to view on the actual node.
Then, someone who might be wondering why the node is not gone, would pick the delete tab there, and it would there delete everything.
If it happens like that, then I think we do not as much need any words on the translation delete which says how to delete the whole thing, cause they will discover it and then they will know.
Comment #14
yoroy CreditAttribution: yoroy commentedAgreed with the optimisations Bojhan outlines. I don't think we need parentheses though.
So just have "Delete Romanian translation".
And, yes to what YesCT said as well.
Comment #15
disasm CreditAttribution: disasm at AppliedTrust commentedWorking on this now at LA sprint. I've replicated the issue.
Comment #16
disasm CreditAttribution: disasm at AppliedTrust commentedFirst stab at this. This tackles point 1 in #12.
Comment #17
disasm CreditAttribution: disasm at AppliedTrust commentedAlso, after deleting a translation, it redirects to the front page in the translation that was just deleted (so if you delete German, it redirects to mysite.com/de). I think this would be less confusing if we made it redirect to the node view of the translation that was just deleted.
Comment #18
YesCT CreditAttribution: YesCT commentedso, should we only worry about nodes or more generally content?
OR more specifically, should we leave the content and node alone and make a submitForm() in a TranslationDeleteForm .. ?
this of overriding the addition of submitForm() on the ContentEntityDeleteForm class.
which is why it is redirecting to the front. and not the redirect put in that other submitForm().
Comment #19
disasm CreditAttribution: disasm at AppliedTrust commentedI've been talking with @YesCT about this. The behavior occurring is confusing, because we're overriding the node delete tab to delete a translation (so it doesn't delete the whole node). That explains why it's not getting routed back to the translation page of the node where the translation has been deleted. When you delete a translation on the translation tab, it properly removes the translation and sends the user back to the translation page.
What it looks like we need to do, is in the DeleteForm submit hook, check if we're deleting a translation, and if so, then set the redirect to the view node page of the default translation.
Comment #20
amateescu CreditAttribution: amateescu for Drupal Association commentedThe critical bug that this issue tries to address, as per the issue summary, is that the content entity delete forms are causing data loss by deleting more than they should, and their UI is quite broken (see the before screenshots from the IS).
While this area definitely needs quite a bit of UI/UX improvements, I do not think those should hold up a release-blocking critical bug. Can we please open another (major) issue where we can explore and discuss things like #13, #17 and #19? Pretty please? :)
Comment #21
jibran#5.1 is still a problem IMHO. This is a work around not a proper fix. Maybe we can ping @Berdir or @yched about it.
RE: #20 Let's not touch the ui here at all then because it seems to me that we need a proper discussion around that. I'd suggest let's not run into fixing it.
Comment #22
amateescu CreditAttribution: amateescu for Drupal Association commentedHave you read #7.1?
Thanks for the suggestion but if we don't touch the UI here, we will still have the same data loss bug at the UI level. If you look at the "Before - source node" screenshot from the IS, the delete button on the source entity says "Delete (this translation)", which is 100% false since pressing that button will delete the source entity and all its translations.
Like I said in #20 above, the current scope of this issue (and the reason why it's critical) is to provide the minimum amount of work required to bring this screen in a shippable state, not perfect but just enough to fix the data loss issue.
Comment #23
jibranYeah I have read #7.1 before that's the reason I suggested to ping @berdir or @yched but any ways if
TranslatableInterface
is your reason then why not add a new interface(ContentEntityTranslatableFormInterface
or something like that) toContentEntityConfirmFormBase
and update the if statement something like thisand move
to the above method.
How does this sound?
Comment #24
amateescu CreditAttribution: amateescu for Drupal Association commentedTbh, it doesn't make any sense to me. Since
ContentEntityInterface
extendsTranslatableInterface
, inContentEntityConfirmFormBase
andContentEntityDeleteForm
we always know that we work with a content entity, which is translatable per the methods inherited fromTranslatableInterface
.I'm super confused on to what exactly a new
ContentEntityTranslatableFormInterface
can bring to the table since we already know that content entities are translatable.Comment #25
plachAs pointed out by @amateescu, I don't think it makes sense to separate translation handling in a dedicated class just for forms, as it doesn't increase the overall coupling, which is already very tight.
I'd address the UX remarks here, though as the seem easy to fix, namely:
Quick code review, nice work, no biggies:
Can we store the untranslated object in a variable instead of retrieving it multiple times? It makes the code slightly more readable.
We should probably add an
elseif
check and bail out if we are on a custom entity form having a different operation from edit/default.I think it's fine to list the translations that would be deleted instead, as suggested above. I'd move the related code to the entity form, so it works even if CT is not enabled.
I'm not sure about this: won't it point to the entity itself, even if it has just been deleted, if a collection link template is not defined? Should we fix
::getCancelUrl()
to account for that and return<front>
in that case?We should have different log/messages in the two cases, I guess.
If what I suggested above makes sense this would go away.
Let's accomodate this too, since it's quite easy: the suggestion is replacing it with
"Delete @language translation"
if I'm not mistaken.Comment #26
yched CreditAttribution: yched commentedThe comment contradicts the actual code a bit, we still do something on delete forms (even if, when you look into the main class implementation, it happens to just be a dsm())
Also, entityFormDelete() phpdoc is a submit callback (and that's what its phpdoc says it is), so it feels weird to directly reuse that as part of a form alter ? It seems overrides in base classes could totally trust the phpdoc and do "submitty" stuff in there that would be ill-advised at alter time ?
Last, wouldn't it be a bit more direct if content_translation_form_alter() took care of "if that's delete form, do this, else do that", instead of deferring all cases to entityFormAllter() ?
Comment #27
yched CreditAttribution: yched commentedAlso, the same message (in the default implementation, never overriden : "The @entity-type %label has been deleted") will be displayed no matter what ? That sounds like it could give users a cold sweat, don't we need a dedicated message for the "just deleted a translation" case ?
Comment #28
disasm CreditAttribution: disasm at AppliedTrust commentedHere's a patch addressing most of the concerns. I'm not sure what needs done for the 2nd request in #25 I haven't moved anything yet (like the request in 3 to move logic to the entity form). And I haven't fixed the redirect to not go to the page. 4 and 6 still need addressed as well in that comment. Setting needs review to make sure the changes thus far don't break tests.
Comment #29
plachI was suggesting to just add a check that
$this->getOperation() == 'edit'
or$this->getOperation() == 'default'
or return immediately.Probably I didn't explain myself: I was suggesting to store in a variable the result of
$entity->getUntranslated()
.I think the suggestion was to list translations as a bullet list in the form page content, not as a message.
Concatenating translated strings is not a good practice: we should completely replace the value with
$this->t('Delete @language translation', ...)
.Comment #30
disasm CreditAttribution: disasm at AppliedTrust commentedWith the latest patch, I think the only thing remaining is getting rid of the drupal_set_message with the concatenated language strings and replacing with a bullet list in the form. Also, possibly moving the logic to entity form from ContentTranslationHandler mentioned in #25.
Comment #31
disasm CreditAttribution: disasm at AppliedTrust commentedSwitching list of languages being deleted to bulleted list.
Comment #32
Pere OrgaThank you for your work on this.
I like that wording better, but this is introducing inconsistencies with the following code:
I think it would be better to improve them all at the same time. We could open a follow up after closing this one. The UX still needs to be improved in many places but I agree with @amateescu that we don't need to postpone a critical issue for that.
Comment #33
YesCT CreditAttribution: YesCT commentedSaw a manual demo of it. Looks really great.
I think adding a phrase before the order list like:
This will delete the translations:
would be nice.
Comment #34
Pere OrgaThis is a bit confusing because is just displaying a list of languages, without an indication that these are translations about to be deleted.
Comment #35
disasm CreditAttribution: disasm at AppliedTrust commentedAdding markup above the list of items.
Comment #37
BalrajB CreditAttribution: BalrajB commentedLast patch "deleting_a_translation-2486177-35.patch", working as expected, however the text is confusing, it should say "Are you sure you want to delete the
<LANGUAGE>
content Test 1 page?" e.g. "Are you sure you want to delete the French content Test 1 page?" not https://www.evernote.com/shard/s183/sh/6216f7ba-7507-41f7-be33-221ecd051...Comment #38
Pere OrgaI confirm #37 happens when going to
/secondary-language/node/<nid>/delete
of a node translated to that language. It displays the form to delete a translation but the header "Are you sure you want to delete the content..." is not consistent with it.Comment #40
dawehnerJust some random thoughts.
Wait, shouldn't this use $entity_untranslated as otherwise a specific language would be used?
nitpick: we use || not or. Can we document why we stop here?
If we change this line, can we make it as protected?
Is that a functionality which would be helpful on entity itself? We do that more than just once place already in that patch.
Let's add public, even if the other ones don't do yet.
Given that we use the storage already, do you mind using
::loadByProperties
as well?Comment #41
disasm CreditAttribution: disasm at AppliedTrust commentedAddressing #40.
Comment #42
disasm CreditAttribution: disasm at AppliedTrust commentedAs for #37, fixing that text could be difficult. It's coming from Drupal\Core\Entity\EntityDeleteFormTrait method getQuestion(). Conditionally overriding that when a translation is being deleted vs. when a node is being deleted could provide to be rather difficult. I'm open for suggestions if anyone has any guidance.
Comment #44
disasm CreditAttribution: disasm at AppliedTrust commentedfixing syntax of loadByProperties() method (no entity_type param required).
Comment #46
dawehnerJust some small points.
I guess we should be able to use
isTranslation
there?We should add isTranslation() to TranslatableInterface and move this implementation to ContentEntityBase
Comment #47
disasm CreditAttribution: disasm at AppliedTrust commentedThis should pass tests again. Thanks @dawehner for the tip on using $entity->getEntityTypeId().
Comment #48
BerdirActually, I think you want to use getEntityType()->getLabel() here, that gives you the user-readable label (Content, User, Term, ..) and not the machine name (node, user, taxonomy_term, ...)
Comment #50
piyuesh23 CreditAttribution: piyuesh23 at QED42 commented@Berdir, that makes sense. Updated patch & using the human readable label now.
Comment #51
piyuesh23 CreditAttribution: piyuesh23 commentedComment #52
disasm CreditAttribution: disasm at AppliedTrust commentedThis one should pass tests again. Also moving some stuff around per @dawehner.
Comment #53
disasm CreditAttribution: disasm at AppliedTrust commented@piyuesh23 can you attach an interdiff showing your changes you made? Want to make sure I get them added to the work I've been doing. If you're using git, just a git show of your most recent commit outputted to interdiff.txt should suffice.
Comment #54
piyuesh23 CreditAttribution: piyuesh23 at QED42 commented@disasm, Adding interdiff here for the patch in #50.
Comment #58
disasm CreditAttribution: disasm at AppliedTrust commentedLast 2 test failures being fixed here. Overriding node delete form so it redirects to front page when deleting nodes.
Comment #59
disasm CreditAttribution: disasm at AppliedTrust commentedComment #60
dawehnerShould we TRUE|FALSE, sorry :(
Just a nitpick, the logging message is a little bit influent.
Comment #61
disasm CreditAttribution: disasm at AppliedTrust commentedaddressing #60.
Comment #62
mradcliffeThe latest patch does address the issues from comment #60.
The tests that are added seem to do what the issue summary suggests it should.
Should $this->t() be used in ContentEntityDeleteForm just as it is in NodeDeleteForm?
Comment #63
jibranThe patch looks much batter now some nits to fix and we are good to go.
Extra whitespace.
We can just use $entity->delete().
Let's create
$form_object = $form_state->getFormObject();
before if statement.Needs proper function docs now.
Comment #64
disasm CreditAttribution: disasm at AppliedTrust commentedAddresses #37 (switches title when deleting a translation.
Comment #65
disasm CreditAttribution: disasm at AppliedTrust commented@jibran which methods need docs in #4 (the included part doesn't make it clear).
Patch addresses everything else in #62 and #63.
Comment #66
jibrannm it's fine. Thanks for the fixes @disasm. I think this is ready. Let's wait for @plach to RTBC.
Comment #67
Pere Orgaif ($entity->isTranslation()) {
Would that be the same than doing:
if (!$entity->isDefaultTranslation()) {
?I say that because that function already exists, and I think is implemented better (uses the language and does not call any method):
Comment #68
Pere OrgaFrom PHP documentation:
i.e.
Comment #69
Pere OrgaIs not your code and is minor, but now that you are changing it, I would remove the useless isset(). Also, $status_translatable could be initialized to FALSE instead.
(Actually, is not that minor. If $definition->isTranslatable() returns a boolean (and it should), isset() will always return TRUE.)
Comment #70
yched CreditAttribution: yched commentedNo answer on #26 ?
Comment #71
amateescu CreditAttribution: amateescu for Drupal Association commented@yched, re #26: yes, I admit I cut a few corners in the initial patch :D
Let's get this issue back on track. This patch fixes #25 and #26 properly.
Comment #72
amateescu CreditAttribution: amateescu for Drupal Association commentedAdded some updated 'after' screenshots with the patch from #71 to the issue summary.
Comment #74
amateescu CreditAttribution: amateescu for Drupal Association commentedOops :/
Comment #75
disasm CreditAttribution: disasm at AppliedTrust commentedper #67 using isDefaultTranslation() instead of isTranslation. Removing the new method. Tested locally, and behavior hasn't changed. Also, only setting
<front>
on NodeDeleteForm when isDefaultTranslation().Comment #76
YesCT CreditAttribution: YesCT commentedI only had a quick look...
------
this is an unrelated change in a file not otherwise touched by this patch. please revert this part.
------
Also, the breadcrumbs are now not showing in the "after" screenshots. and the vertical spacing looks missing.
Please embed the after screenshots in the issue summary, near the before screenshots.
Comment #77
Pere OrgaI just created #2488156: Fix typos in @inheritdoc to address the issue in #76
Comment #78
disasm CreditAttribution: disasm at AppliedTrust commentedreverted #76. I think I accidentally introduced that one when I added the method isTranslation() we aren't using anymore.
Comment #79
disasm CreditAttribution: disasm at AppliedTrust commentedComment #80
disasm CreditAttribution: disasm at AppliedTrust commentedComment #81
disasm CreditAttribution: disasm at AppliedTrust commentedComment #82
plachManually tested this and it works great, just a couple of remaining remarks:
I'm confused: why need these UX improvements to be provided by CT, given that all the rest is implemented generically by the entity form? If translations were created programmatically without CT, we would be missing the UX benefits added here.
As I wrote above,
EntityDeleteFormTrait::getCancelUrl()
is broken when the entity type does not define acollection
link template, as it will try to redirect to the deleted entity canonical URL, which will always return a 404. We should return<front>
in that case instead and remove the special casing from the node delete form.Comment #83
yched CreditAttribution: yched commented@amateescu++ :-)
Comment #84
larowlanBlockContent also supports translatable entities. Should we be seeing changes in this patch for BlockContentDeleteForm too?
I note that the delete form there warns about removing placed instances.
Comment #85
amateescu CreditAttribution: amateescu for Drupal Association commented@plach, re #82: because that's how I started the patch and I'm persistent in my silliness :) Thanks for keeping a sharp eye.
Fixed both points.
Comment #86
amateescu CreditAttribution: amateescu for Drupal Association commented@larowlan, I just checked and
BlockContentDeleteForm
overrides only thebuildForm()
method, so it should be fine with all the improvements added to the base class.Comment #87
plachVery very close!
This should go into the if branch below.
Ubernitpick: what about
deleted_translations
?I think we can safely merge this test in the if above.
Comment #89
amateescu CreditAttribution: amateescu for Drupal Association commentedFixed all of #87 and updated the test.
Comment #90
plachAwesome!
Comment #91
disasm CreditAttribution: disasm at AppliedTrust commentedComment #92
disasm CreditAttribution: disasm at AppliedTrust commentedI looked over this and this doesn't look like it'll need a change record. Updating issue summary since reviews are done.
Comment #93
dawehnerThe patch is looking great for me!
Comment #94
webchickReally excellent work on this, everyone!
Tested this with a node with an English (source)/French translation (node titles: hello/bonjour), both with the delete button/tab on the two translations, as well as the admin/content page.
When attempting to delete the source translation (in my case, English), either from admin/content or from node/1/delete, you get this:
All is good.
If I hit the delete tab on the French translation, I get:
All is good again.
A couple of inconsistencies I found though:
1) If I hit the "Supprimer la traduction" button on the "bonjour" node form (as opposed to the "Supprimer" (Delete) tab, I get a slight variation, with no primary button styling:
That is confusing. Are there two delete forms for some reason?
2) When using Delete option within contextual links for "bonjour", it asks if I want to delete "hello" and then shows the "delete all translations" warning. Expected behaviour: Would only ask if I wanted to delete the French translation.
3) When attempting to delete "bonjour" from admin/content, the deletion form points to "hello" instead, and does not warn that all translations will be deleted, even though they will:
So I think there's still a bit more left to do here.
Comment #95
Gábor Hojtsy@webchick: looking at your screenshots I see "translation of the contenu" (note last word). I did not find that string in the patch and/or core, so not sure how that ended up there, just noting.
Comment #96
Pere OrgaReverted #75. These two functions do very different things.
Comment #97
amateescu CreditAttribution: amateescu for Drupal Association commented@webchick, thanks for the review!
#94.1: Yes, there are two delete forms. The other one that you saw is provided by the Content translation module and it's the one that content translators (as opposed to site editors) have access to. I tweaked it a bit to be in line with the main entity delete form.
#94.2 and 3: That's the bug being addressed in #2476563: Entity operations links tied to original entity language, ignore everything else, which you demoted from critical :P
@Gábor Hojtsy, "contenu" is the French translation for "content" :)
@Pere Orga, yes, I had the same impression that
isDefaultTranslation()
is something entirely different than what we needed here, and I was really confused when it was suggested in #67... Anyway, the interdiff looks good.Comment #99
amateescu CreditAttribution: amateescu for Drupal Association commentedFixed the tests.
Comment #100
Gábor Hojtsy@amateescu: right, what tripped me up is it was in the middle of an English sentence, but I see it comes from the entity type.
Comment #101
webchickRight, I realize we need translation-aware entity operations in order to delete "bonjour" and not "hello" but since I am deleting "hello," and "hello" has translations, why is it not warning me that I'm going to blow away my other translations like it would if I hit delete on the node form directly?
Comment #102
amateescu CreditAttribution: amateescu for Drupal Association commentedBecause the delete form provided by CT does not have all the improvements that went into the regular delete form.
@plach, should we just remove that one or update it?
Edit: oh wait, @webchick, I think you were testing a patch that used
isDefaultTranslation()
to check if you're dealing with a translation or not. That was wrong and corrected in a patch after your test, can you please try again with the latest patch?Comment #103
webchickNot being warned when you're about to delete translations you didn't realize you're going to delete I thought was the whole point of this issue? So, yes? :)
Comment #104
amateescu CreditAttribution: amateescu for Drupal Association commentedHeh, you're fast. See my edit from #102 :)
Comment #105
webchickAh, perfect. :) Will test a bit later today, thanks!
Comment #106
plachThis should be actually equivalent to
!CEB::isDefaultTranslation()
, not sure what difference you are referring to: the::language()
method returns a language object corresponding to the current active language code, which isLanguageInterface::LANGCODE_DEFAULT
for the default translation, so the actual default language code needs to be retrieved.::isDefaultTranslation()
allows to perform a lighter check but the logic behind is the same.I think this is a separate bug, I'm able to reproduce it even with the last patch: it seems contextual links' language is always the one of the available translation whose language has the heaviest weight, instead of matching the translation language.
Comment #107
plachActually the bug exists in HEAD too: #2488940: Contextual links are broken on multilingual sites.
Comment #108
Pere OrgaI was referring to !isDefaultTranslation() vs isTranslation(). I asked in #67 if they were equivalent, but clearly they are not.
Comment #109
amateescu CreditAttribution: amateescu for Drupal Association commented@plach, as far as I understand it, we need a way to compare source langcode to translation langcode, and
isDefaultTranslation()
compares default langcode (i.e.'x-default'
) to translation langcode.Comment #110
plachThe method is called
::isTranslation()
, the logic behind it aims to figure out whether we are (not) dealing with the default translation object, the default translation object has'x-default'
as active language, thus!::isDefaultTranslation()
gives us exactly the same result as::isTranslation()
.'x-default'
is just a shortcut to designate the entity default/original/source language that allows to change it without having to mess with internal keys and so on. If you have a look to theContentEntityBase::language()
method, you'll see that the active language is returned, unless we are dealing with the default translation, in which case'x-default'
is converted to the actual value before returning it.Comment #111
plachIn #2476563: Entity operations links tied to original entity language, ignore everything else we are planning to use it as a fallback for users not having edit permissions on the entity, so I guess
ContentTranslationDeleteForm
could just extendContentEntityDeleteForm
and override the submit handler to avoid deleting the whole entity. We could additionally introduce a validation check to block submission in case we are dealing with the default translation, in fact this could happen only by manually fiddling with the browser address bar.Comment #112
dawehnerAt least from my point of view, it seems pretty clear that its the exact opposite. In the beginning I would have started with the other way round for the method,
but at that point in time, its not worth to change the API, I think.
Comment #113
plachWe have an
::isDefaultRevision()
method :)Comment #114
dawehnerFair, but I just think it would have been easier the other way round.
Comment #115
codexmas CreditAttribution: codexmas at Acquia commentedTested patch with instructions provided and it works well. Clarity on wording is much improved.
Comment #116
pameeela CreditAttribution: pameeela commentedI have tested this too, and it works.
FWIW as someone new to this issue (and multi-lingual in general) I found it a bit confusing because you only get the "Delete this translation only" option if you are at the /language/node path (e.g. /cs/node/1/edit or cs/admin/content). So if you are at /admin/content and you click edit then delete, or use the drop down button from admin/content, you can only delete both. So it might be worth a follow up issue to clarify that, maybe just in the help text on the source node delete page, to say that you can delete single translations via the language-specific sub-path.
Comment #117
webchickWould love plach to take one more look at this.
Comment #118
pameeela CreditAttribution: pameeela commentedActually just testing a bit further, I believe there is a bug that is not related to this specific issue.
If you are at admin/content and you click edit on a translation, it should take you to [language]/node/nid/edit but right now if you click edit on the translation it takes you just to node/nid/edit. I have created #2489602: Edit/delete links for entity translations link to source node, not translation for this issue.
Comment #119
catchComment #120
amateescu CreditAttribution: amateescu for Drupal Association commented@plach, thanks for the explanation in #110, I didn't look at what
ContentEntityBase::language()
was doing internally.I think the agreement is to use
isDefaultTranslation()
and not add the newisTranslation()
method, so here is the patch from #89 + the interdiffs from #97 and #99 + removed some unused use statements.Comment #121
plachThanks @amateescu, I've some time here at the sprint and I'm addressing #111.
Comment #122
plachThis takes care of unifying the CT deletion form.
As a bonus, this unties redirect URLs and cancel URLs, whose coupling was creating some problems.
Comment #123
jibranNot needed anymore.
Comment #124
dawehnerLooks fine for me!
Comment #128
plachThis should fix failures and address #123.
Comment #129
Saphyel CreditAttribution: Saphyel as a volunteer commentedTested and works fine.
Comment #130
vijaycs85+1 to RTBC.
wow, this is nice. didn't know that we can do like this.
Comment #131
Adam Clarey CreditAttribution: Adam Clarey commentedI've tested patch from #128 and it works as expected. The form is now far more intuitive.
Comment #132
xjm@Adam Clarey and @Saphyel, thanks for testing! One note for next time is that it's always helpful to document the specific steps you used for testing and what the specific results were. See @webchick's work in #94 for a great example.
The summary, screenshots, integration test coverage, etc. are all great
I'm in the process of reviewing this and I must admit the sorta-crazy around
EntityDeleteFormTrait
is snarling my brain. I read over #1728804: Introduce (Content)EntityDeleteForm and children to handle entity deletions for some background on why things are the way they are, but I'm still unclear on why, for example,ContentEntityConfirmFormBase
is a thing (it seems only used for deletions), and why we don't just do away withEntityDeleteFormTrait
at this point (when we're overriding it so much) and just put the respective versions of the methods inContentEntityDeleteForm
andEntityDeleteForm
(which are the only usages). (For others' reference,ContentEntityDeleteForm
does not extendEntityDeleteForm
; andEntityDeleteForm
has only config-specific stuff, which also confused me quite a bit.) Is there a reason to keep the trait other than for BC? Because then we could do away with the trait overriding cleverness. (The rest of the weird is probably out of scope.) Setting NR for feedback on that because I feel like the sorta-confusing inheritance around this is a bit potentially fragile and maybe how this bug occurred in the first place.A couple other minor questions and notes I had:
Do we have test coverage for this?
The add link for all entity types is not necessarily
entity_type_id/add
, but this doesn't matter that much since this is just a test helper and it seems to be true at least for the types used in this test. And if that changes then the test would fail explicitly, so it's fine.Minor, but a comment as to why it's only for these operations could be worthwhile.
At this point is there any reason even to keep this as a separate subclass? Since all the other translation stuff is on the parent and the LanguageInterface parameter is optional.
Comment #133
plachWorking on this
Comment #134
plachOn a plane, I'll reply in detail tomorrow.
Comment #136
plachIn the process of fixing #132.1 (great catch), I found a few more glitches and fixed them: now users having edit permissions are no longer able to access the corresponding translation-specific routes. This will allow CT to provide translation-specific operations in #2476563: Entity operations links tied to original entity language, ignore everything else, without cluttering drop-buttons with redundant operations.
Aside from that, I agree that the entity deletion form class hierarchy could use a clean-up. Not sure this is the right issue.
The main point of having a separate translation deletion form is providing translators not having entity deletion access to still be able to delete translation. The extended class allows to explicitly set the form language instead of depending on the current one, which may be useful to avoid switching the current language. Another reason is that there may be entity types (such as users) that do not define a deletion form, in which case we still need to delete translations.
Comment #138
plachMmh, let's try this
Comment #140
xjmThanks @plach, #136 definitely helps clarify. I agree that fixing the entity deletion form hierarchy entirely would not make sense in this issue. So instead, let's file a followup to this issue to re-evaluate it? Then we could reference that followup in @todo in the patch, which would help address at least some of my concern. As followup work for this issue it could be prioritized during the beta (but we can discuss it more there).
Comment #141
plachJust added some debugging code, as I have no failures locally. I'll add the @todo in the next patch.
Comment #142
plachCreated #2491057: Streamline the entity deletion form class hierarchy to address @xjm's concerns.
Comment #143
plachBah
Comment #144
plachPosting the right patch usually helps...
Comment #146
xjmSo the
['absolute' => TRUE]
was what was causing the test failures? Just to make sure. :)Comment #147
plachNope, I was passing the stringified URL, instead of the URL object...
Comment #148
amateescu CreditAttribution: amateescu as a volunteer commentedReviewed the changes since #122 and also applied the patch and looked through the affected files locally, everything looks good to me, especially the extra test coverage.
Comment #150
webchickOk, pretty sure xjm's feedback has been addressed now, and this has been RTBC long enough now that anyone else who had concerns could've raised them. :)
I re-did my tests from #94 again and can find nothing further to complain about. Great work!! :D
Committed and pushed to 8.0.x. Thanks!
Comment #151
Gábor HojtsyYay, superb.
Comment #153
AnybodyFollow-up: #2485499: Allow source translations to be removed