It would help DX (developer usability) to change token_replace() to support passing in langcodes in $message, rather than having to provide a full object. Unless we allow the simpler parameter we will continue to have modules do something like $message['language'] = (object) array('language' => $language); which is just wrong. Let's standardize on functions like t() and accept a 'langcode' option instead.

Issue highly inspired by #1305378: Tokens should use $options['langcode'] and not need a language object

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Gábor Hojtsy’s picture

Gábor Hojtsy’s picture

Should also include a line of documentation, looks like hook_mail() does not document the language option in $message in any way in fact.

PrabhuG’s picture

Assigned: Unassigned » PrabhuG

working on.

PrabhuG’s picture

FileSize
18.81 KB

intial patch

Gábor Hojtsy’s picture

Status: Active » Needs review
Gábor Hojtsy’s picture

Status: Needs review » Needs work

Thanks for the patch, let's clean it up!

+++ b/core/includes/mail.incundefined
@@ -26,11 +26,11 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
- * used to generate the page ($language global variable) or the site default
- * language. See language_default(). The former is good if sending e-mail to
+ * used to generate the page or the site default
+ * language. See language_from_default(). The former is good if sending e-mail to

@@ -47,13 +47,13 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
- *       drupal_mail('example', 'notice', $account->mail, user_preferred_language($account), $params);
+ *       drupal_mail('example', 'notice', $account->mail, language_from_default(), $params);
  *     }

langauge_default() should be good still AFAIS, don't see why did you change these.

+++ b/core/includes/mail.incundefined
@@ -63,7 +63,6 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
- *         $langcode = $message['language']->langcode;
  *         $message['subject'] = t('Notification from !site', $variables, array('langcode' => $langcode));
  *         $message['body'][] = t("Dear !username\n\nThere is new content available on the site.", $variables, array('langcode' => $langcode));

$langcode is used just down there a little bit later.

+++ b/core/modules/contact/contact.pages.incundefined
@@ -169,16 +169,16 @@ function contact_site_form_submit($form, &$form_state) {
-  drupal_mail('contact', 'page_mail', $to, language_default(), $values, $from);
+  drupal_mail('contact', 'page_mail', $to, language_from_default(), $values, $from);

language_default()->langcode should be it.

+++ b/core/modules/contact/contact.pages.incundefined
@@ -169,16 +169,16 @@ function contact_site_form_submit($form, &$form_state) {
-    drupal_mail('contact', 'page_copy', $from, $language_interface, $values, $from);
+    drupal_mail('contact', 'page_copy', $from, $langcode_interface, $values, $from);
...
-    drupal_mail('contact', 'page_autoreply', $from, $language_interface, $values, $to);
+    drupal_mail('contact', 'page_autoreply', $from, $langcode_interface, $values, $to);

There is no $langcode_interface, should be $language_interface->langcode

+++ b/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.phpundefined
@@ -52,7 +52,7 @@ class MailTest extends WebTestBase implements MailInterface {
-    $message = drupal_mail('simpletest', 'mail_test', 'testing@example.com', $language_interface);
+    $message = drupal_mail('simpletest', 'mail_test', 'testing@example.com', $language_interface->lancode);

@@ -64,13 +64,13 @@ class MailTest extends WebTestBase implements MailInterface {
-    $message = drupal_mail('simpletest', 'cancel_test', 'cancel@example.com', $language);
+    $message = drupal_mail('simpletest', 'cancel_test', 'cancel@example.com', $language_interface->lancode);

Typo lancode => langcode.

+++ b/core/modules/system/system.moduleundefined
@@ -3554,14 +3554,14 @@ function system_send_email_action($entity, $context) {
-    $language = language_default();
+    $langcode = language_from_default();

+++ b/core/modules/update/update.fetch.incundefined
@@ -366,15 +366,15 @@ function _update_cron_notify() {
-      $default_language = language_default();
+      $default_langcode = language_from_default();

Use language_default()->langcode.

+++ b/core/modules/update/update.moduleundefined
@@ -602,7 +600,8 @@ function _update_message_text($msg_type, $msg_reason, $report_link = FALSE, $lan
+  $language = NULL;
+  if(!empty($langcode)) $language = language_load(langcode);

Hm, as per Drupal code style, this should be:

if (!empty($langcode) {
$language = language_load($langcode);
}

That is, add space after if, wrap code in {}. Then I'm not sure if this is the right code, but not seeing the surroundings yet.

+++ b/core/modules/user/user.moduleundefined
@@ -2145,7 +2145,6 @@ function user_mail($key, &$message, $params) {
  * Used by user_mail() and the settings forms to retrieve strings.
  */
 function _user_mail_text($key, $language = NULL, $variables = array(), $replace = TRUE) {

@@ -2297,7 +2296,7 @@ Your account on [site:name] has been canceled.
-    return token_replace($text, $variables, array('language' => $language, 'callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE));
+    return token_replace($text, $variables, array('langcode' => $langcode, 'callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE));

You also changed the argument here to $langcode in the invocation; should change in the function too.

Also, this token_replace will only apply once the token patch is committed from http://drupal.org/node/1305378

+++ b/core/modules/user/user.moduleundefined
@@ -2963,16 +2962,16 @@ function theme_user_signature($variables) {
-    return $default ? $default : language_default();
+    return language_from_default();

Should be language_default()->langcode;

+++ b/core/modules/user/user.moduleundefined
@@ -2999,21 +2998,21 @@ function user_preferred_language($account, $default = NULL) {
- * @param $language
+ * @param $langcode
  *   Optional language to use for the notification, overriding account language.

Say Optional language code.

+++ b/core/modules/user/user.moduleundefined
@@ -3021,7 +3020,7 @@ function _user_mail_notify($op, $account, $language = NULL) {
-      drupal_mail('user', 'register_pending_approval_admin', $site_mail, language_default(), $params);
+      drupal_mail('user', 'register_pending_approval_admin', $site_mail, language_from_default(), $params);

language_default()->langcode

PrabhuG’s picture

FileSize
19.37 KB

The patch is cleaned up.

PrabhuG’s picture

Status: Needs work » Needs review
Gábor Hojtsy’s picture

Status: Needs review » Needs work
+++ b/core/includes/mail.incundefined
@@ -26,10 +26,10 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
- * used to generate the page ($language global variable) or the site default
+ * used to generate the page or the site default
  * language. See language_default(). The former is good if sending e-mail to

Let's fix line wrapping here :)

+++ b/core/includes/mail.incundefined
@@ -47,14 +47,14 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
+ *     $langcode = $message['langcode'];
+ *     user_mail_tokens($variables, $data,array('langcode' => $langcode));

Why are you not passing on just $options (leave it as-is)? It should already have a langcode properly as needed, right?

+++ b/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.phpundefined
@@ -52,7 +52,7 @@ class MailTest extends WebTestBase implements MailInterface {
-    $message = drupal_mail('simpletest', 'mail_test', 'testing@example.com', $language_interface);
+    $message = drupal_mail('simpletest', 'mail_test', 'testing@example.com', $language_interface->langcode);
 

@@ -64,13 +64,13 @@ class MailTest extends WebTestBase implements MailInterface {
-    $message = drupal_mail('simpletest', 'cancel_test', 'cancel@example.com', $language);
+    $message = drupal_mail('simpletest', 'cancel_test', 'cancel@example.com', $language_interface->lancode);

lancode typos still here.

+++ b/core/modules/update/update.moduleundefined
@@ -602,7 +600,11 @@ function _update_message_text($msg_type, $msg_reason, $report_link = FALSE, $lan
+  if(!empty($langcode)) {
+    $language = language_load(langcode);
+  }else{
+    $language = NULL;
+  }

I'm afraid you did not take the whitespace suggestions into account :) if should have a space right after, else should have a newline before and a space after.

+++ b/core/modules/user/user.moduleundefined
@@ -2144,8 +2144,7 @@ function user_mail($key, &$message, $params) {
-function _user_mail_text($key, $language = NULL, $variables = array(), $replace = TRUE) {
-  $langcode = isset($language) ? $language->langcode : NULL;
+function _user_mail_text($key, $langcode = NULL, $variables = array(), $replace = TRUE) {

No phpdoc to update above the function?

+++ b/core/modules/user/user.moduleundefined
@@ -2297,6 +2296,12 @@ Your account on [site:name] has been canceled.
+    if(!empty($langcode)) {
+      $language = language_load($langcode);
+    }
+    else {
+      $language = NULL;

@@ -2999,21 +3004,23 @@ function user_preferred_language($account, $default = NULL) {
+    if(empty($langcode)) {
+      $langcode = user_preferred_langcode($account);
+    }

if should have a space after.

PrabhuG’s picture

Status: Needs work » Needs review
FileSize
21.03 KB

patch updated. I hope now all test will pass :)

Gábor Hojtsy’s picture

Status: Needs review » Needs work
+++ b/core/includes/mail.incundefined
@@ -26,13 +26,13 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
+ * used to generate the page or the site default language. See ¶
+ * language_default(). The former is good if sending e-mail to the person ¶
+ * filling the form, the later is good if you send e-mail to an address ¶

Line ends should not have whitespace.

+++ b/core/includes/mail.incundefined
@@ -47,14 +47,14 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
+ *     user_mail_tokens($variables, $data,$options);

@@ -63,9 +63,8 @@ define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER
+ *         $message['subject'] = t('Notification from !site', $variables,$options);
+ *         $message['body'][] = t("Dear !username\n\nThere is new content available on the site.", $variables, $options);

Please, do use whitespace after commas. Please.

Like the third one :)

+++ b/core/modules/user/user.moduleundefined
@@ -2133,19 +2133,31 @@ function user_build_content($account, $view_mode = 'full', $langcode = NULL) {
+ * @param $langcode
+ *   (optional) A language code of mail string.

Language code to use to generate the e-mail text.

+++ b/core/modules/user/user.moduleundefined
@@ -2133,19 +2133,31 @@ function user_build_content($account, $view_mode = 'full', $langcode = NULL) {
+ * @param $variables
+ *   (optional) A callback function that will be used to post-
+ *   process the array of token replacements after they are generated.
+ *   For example, a module using tokens in a text-only email might ¶
+ *   provide a callback to strip HTML entities from token values ¶
+ *   before they are inserted into the final text. ¶

Variables is certainly not a callback function, its an array :)

+++ b/core/modules/user/user.moduleundefined
@@ -2133,19 +2133,31 @@ function user_build_content($account, $view_mode = 'full', $langcode = NULL) {
+ * @param $replace
+ *   (optional) TRUE (default) Do not sanitize the token replacement.
+ *

This also sounds like is not the right documentation here.

+++ b/core/modules/user/user.moduleundefined
@@ -2297,6 +2309,12 @@ Your account on [site:name] has been canceled.
+    if(!empty($langcode)) {
+      $language = language_load($langcode);

Space after if, please, pretty please.

+++ b/core/modules/user/user.moduleundefined
@@ -2999,21 +3017,23 @@ function user_preferred_language($account, $default = NULL) {
- * @param $language
- *   Optional language to use for the notification, overriding account language.
+ * @param $langcode
+ *   Optional language code to use for the notification, overriding account language.

The new text now rans over 80 chars, just wrap to 80 chars, so the last word goes on a new line. Then "Optional" at the start can also be made "(optional)" like in other comments.

PrabhuG’s picture

FileSize
20.92 KB

comments updated testing.

PrabhuG’s picture

Status: Needs work » Needs review
FileSize
21.03 KB

comment updated in function description.

PrabhuG’s picture

comment updated in function description.

PrabhuG’s picture

FileSize
21.03 KB

comment updated in function description as (optional)

PrabhuG’s picture

Status: Needs review » Needs work
Issue tags: +DX (Developer Experience), +D8MI, +sprint, +language-base

The last submitted patch, 1305378-hook_mail-14.patch, failed testing.

Gábor Hojtsy’s picture

Patch does not apply anymore due to other patches landing. Needs a reroll.

Gábor Hojtsy’s picture

@PrabhuG: can you help reroll this patch?

PrabhuG’s picture

I'll be working on this weekend :)

savithac’s picture

Status: Needs work » Needs review
FileSize
20.95 KB

Status: Needs review » Needs work

The last submitted patch, 1305378-hook_mail-21.patch, failed testing.

Gábor Hojtsy’s picture

Issue tags: +langcode

Tagging for langcode conversions.

Gábor Hojtsy’s picture

Why did this cause all these new failures? We need someone to closely follow core changes, with updates far in between, core changes way too much and this will never apply when a committer comes around. :/

webflo’s picture

Status: Needs work » Needs review
FileSize
22.31 KB

Rerolled the patch from comment nr. 13.

webflo’s picture

Fixed the broken test in UserTokenReplaceTest.

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Thanks for the reroll, looks good to me!

webchick’s picture

Status: Reviewed & tested by the community » Needs work

This all looks good, but no longer applies due to #1757566: Convert user account e-mail templates to configuration system. Could we get a quick re-roll?

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
22.87 KB

Rerolled.

webchick’s picture

Title: Convert hook_mail() and hook_mail_alter() to langcode » Change notice: Convert hook_mail() and hook_mail_alter() to langcode
Priority: Normal » Critical
Status: Needs review » Active

Great. Testbot back to green.

Committed and pushed to 8.x. Thanks!

This will need a change notice.

webchick’s picture

Issue tags: +Needs change record

I knew I forgot one of the 30 things we need to do when that happens. :P~

Gábor Hojtsy’s picture

Title: Change notice: Convert hook_mail() and hook_mail_alter() to langcode » Convert hook_mail() and hook_mail_alter() to langcode
Priority: Critical » Normal
Status: Active » Fixed
Issue tags: -sprint
Gábor Hojtsy’s picture

Unfortunately this conversion was not 100% complete, looks like. @webchick noticed a bug with this, while building the Drupal 8 Spark disto. update_mail() is not yet converrted. Opened #1785966: Missing $language in update_mail() for that, let's fix that quickly :)

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

swentel’s picture

xjm’s picture

Issue tags: -Needs change record

Untagging. Please remove the "Needs change notification" tag when the change notice task is complete.