The recipient type configuration allows sending email notifications to adhoc recipients via the "Email Field" option. This works fine for content with a single language, but when content has one or more language translation(s), the email field value from the original language will always be used.
For example, a page is created with English as the base language and then translated to French. Both are published. The French version is then edited and saved as Draft. The notification email is set to french@domain.com. When the page is re-published, french@domain.com should receive an email but they will not. Instead the email field value from English version will be used and the wrong person will be notified or no notification will be notified if the email field value is blank in the English version.
The problem stems from the fact that loadRevision($revision_id) in EntityStorageInterface seems to load the original language version of the node regardless of the language affected by the specified revision id. The relevant code for the workbench email module is in workbench_email.module.php:
function _workbench_email_content_moderation_event_shim(ContentModerationState $entity) {
if (!\Drupal::moduleHandler()->moduleExists('content_moderation') || class_exists('\Drupal\content_moderation\Event\ContentModerationStateChangedEvent')) {
// https://www.drupal.org/project/drupal/issues/2873287 will add this class
// to core.
return;
}
$entityStorage = \Drupal::entityTypeManager()->getStorage($entity->content_entity_type_id->value);
$moderationStateStorage = \Drupal::entityTypeManager()->getStorage($entity->getEntityTypeId());
$moderated_entity = $entityStorage->loadRevision($entity->content_entity_revision_id->value);
The fix I am proposing is to use getTranslation() to set the moderated entity to the correct (current) language for the revision. One option is to do this in the EmailField.php prepareRecipients() function, but by making the change in the workbench_email.module.php _workbench_email_content_moderation_event_shim() function, the moderated entity will be set to the correct language at the start of the process.
Steps to reproduce:
1. Clean drupal 8.6.3
2. Modules: Content Moderation, Workflows, Workbench Email, Language, Content Translation
3. Install second language (example: French)
4. Allow content to be translated (all fields for basic page content type) /admin/config/regional/content-language
5. Edit content type Basic Page and add new email field.
6. Add new Workbench Email Template /admin/structure/workbench-moderation/workbench-email-template
For the "Enabled recipient types" select "Email Field" and then check the Email field created in the basic page content type.
7. Edit Editorial workflow /admin/config/workflow/workflows
For the "Create New Draft" and "Published" transitions, enable the email template created in prior step. Also, for "This Workflow Applies To" select Basic Page content type.
8. Create new basic page and set email address to english@domain.com. Publish page and confirm attempted email to english@domain.com (use Recent Log Messages report).
9. Translate same page to French and set email address to french@domain.com. Publish page and email will be sent to english@domain.com, not french@domain.com.
| Comment | File | Size | Author |
|---|---|---|---|
| #16 | 3017273-16.patch | 8.18 KB | mrshowerman |
| #10 | 3017273-test-only.patch | 3.21 KB | larowlan |
| #7 | 3017273-7.patch | 951 bytes | dgilbert |
| #3 | 3017273-3.patch | 841 bytes | dgilbert |
Comments
Comment #2
dgilbert commentedComment #3
dgilbert commentedComment #4
dgilbert commentedComment #5
dgilbert commentedComment #6
larowlanThanks, looks great
Can we add to the kernel test here
Comment #7
dgilbert commentedModified patch to check if translation exists for the moderated entity. This is necessary when deleting a translated entity; otherwise the delete will fail because the translation language has already been removed from the entity.
Comment #8
larowlanThanks, we still need a test here - can you add to the kernel test?
Comment #9
dgilbert commentedI've never created a kernel test before. I'll have to look into the process when I have time, unless someone can provide guidance?
Comment #10
larowlanhere's a test only patch demonstrating the language issues
Comment #11
jibranQuestion is, should langcode come from content or recipient's user account?
I think for emails it should come from user profile and for token replacement it should come from content.
Bumping to major as per the duplicate issue.
Comment #12
kazuko.murata commentedI have fixed the issues below which was closed because of duplicates, based on #7 patch.
#3017022: Event subscriber should pass the entity lang code into the queue
#3025113: Send emails in the language of the recipient and not in the current UI language
In my patch the mail language is set from current UI language, and the token language is set from updated content.
Comment #13
mrshowerman#12 works nicely for us.
Here's a re-roll for 2.x.
Comment #14
tom konda#13 is not applies for 3.x.
I reroll a patch for 3.x.
Comment #15
larowlanThere was a test in #10 but it looks like we lost that?
There's also a BC break here, so we either need to work out a way to do it in a BC compatible fashion, or we need to make this a V4 only change. Comments below are a possible BC layer approach.
I think we can keep the argument but move to named arguments in the factory create method, and then if the argument is set for the entity repository emit a deprecation error.
Would require bumping min php to 8.0 but I think we're there already for 3.x branch.
if we add some error checking here for if revision ID is not set and just load up the default revision based off the UUID instead, and emit a deprecation error, we're keeping BC
And same here, if there's no language, we can emit a deprecation error
Let's keep the arguments in the same order, and make langcode and revision optional, emitting a deprecation error if they're omitted.
Comment #16
mrshowermanRe-roll. Leaving in NW as per #15.