When you are sending email to single user you have the option to select language selector and then to translate the message and subject of the mail based on that but when you are sending mail to users form a role you do not have that option.
I have managed to change it in core but needed a bit of touching :
1) modules/system.rules.inc -> add 'translatable' => TRUE, to subject and message field as expected this to be translatable
2) includes/rules.core.inc : class RulesPlugin has no option to get the tranlsated arguments by language, getArgument is protected so you can't just get the argument you need in the language you want so the only alternative was to add public function that i can call and will get me the arguments for the requested language:

   * Gets the right arguments for executing the element.
   * @throws RulesEvaluationException
   *   If case an argument cannot be retrieved an exception is thrown.
  protected function getExecutionArguments(RulesState $state) {
    $parameters = $this->pluginParameterInfo();
    // If there is language parameter, get its value first so it can be used
    // for getting other translatable values.
    $langcode = NULL;
    if (isset($parameters['language'])) {
      $lang_arg = $this->getArgument('language', $parameters['language'], $state);
      $langcode = $lang_arg instanceof EntityMetadataWrapper ? $lang_arg->value() : $lang_arg;
    // Now get all arguments.
    foreach ($parameters as $name => $info) {
      $args[$name] = $name == 'language' ? $lang_arg : $this->getArgument($name, $info, $state, $langcode);
    // Append the settings and the execution state. Faces will append $this.
    $args['settings'] = $this->settings;
    $args['state'] = $state;
    // Make the wrapped variables for the arguments available in the state.
    $state->currentArguments = $args;
    return rules_unwrap_data($args, $parameters);

now with that done all i had to do was to change
3) module/system.eval.inc : change the function rules_action_mail_to_users_of_role

 * Action: Send mail to all users of a specific role group(s).
function rules_action_mail_to_users_of_role($roles, $subject, $message, $from = NULL, $settings, RulesState $state, RulesPlugin $element) {
  $from = !empty($from) ? str_replace(array("\r", "\n"), '', $from) : NULL;

  // All authenticated users, which is everybody.
  if (in_array(DRUPAL_AUTHENTICATED_RID, $roles)) {
    $result = db_query('SELECT mail, language FROM {users} WHERE uid > 0');
  else {
    $rids = implode(',', $roles);
    // Avoid sending emails to members of two or more target role groups.
    $result = db_query('SELECT DISTINCT u.mail, u.language FROM {users} u INNER JOIN {users_roles} r ON u.uid = r.uid WHERE r.rid IN ('. $rids .')');

  // Now, actually send the mails.
  $params = array(
    'subject' => $subject,
    'message' => $message,
  // Set a unique key for this mail.
  $name = isset($element->root()->name) ? $element->root()->name : 'unnamed';
  $key = 'rules_action_mail_to_users_of_role_' . $name . '_' . $element->elementId();
  $languages = language_list();
  $cached = array();

  $message = array('result' => TRUE);
  foreach ($result as $row) {
    $language = isset($languages[$row->language]) ? $languages[$row->language] : language_default();
    // Allow translation of arguments!!!
    if (!empty($cached[$language->language])) {
      $params = $cached[$language->language];
    else {
      $result = $element->getExecutionArgumentsByLanguage($state, $language->language);
      $params = array(
        'subject' => $result['subject'],
        'message' => $result['message'],

    $message = drupal_mail('rules', $key, $row->mail, $language, $params, $from);
    if (!$message['result']) {
  if ($message['result']) {
    $role_names = array_intersect_key(user_roles(TRUE), array_flip($roles));
    watchdog('rules', 'Successfully sent email to the role(s) %roles.', array('%roles' => implode(', ', $role_names)));

with all this done the mails send to the user will be to his preferred language.
If anyone has faced such issue then with just a few lines of code it can be done.

There is one other possible way :
1) load a list of users by desired role
2) loop this list and for each user send mail
this looked a but strange for me and also the "Send mail to all users of a role" action seemed a lot more cleaner way for me so i did this changes.


fuzzy76’s picture