uc_order_mail() looks at its $message argument to determine the language for the mail, which is calculated by uc_store_mail_recipient_language($recipient) in uc_order_mail_invoice_form_submit(). This language is correctly used to translate the e-mail subject.
The body of the e-mail, the invoice itself, is not translated correctly though, but is sent in the current language (i.e. the language the site was in at the time the mail is sent).

To fix this, uc_order_load_invoice(), when called from uc_order_mail(), should also get the $langcode and translate the invoice template accordingly.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

stewart.adam’s picture

I've been trying to correct this on my site, I think things have changed a little though because of the new invoice templating system introduced in 6.x-2.4. However, the bug still exists and the core issue is the same. $settings['message'] is set prior to determining the user's language preference, so the message body gets sent in the same language as the site language at the time of generation.

The attached patch should fix the issue by first generating the message bodies from the template in the required languages and then sending the appropriately translated message body to the corresponding user based on language preference.

Some notes about how the patch works or what the patch changes:

  • We avoid wasting time by regenerating the same message body multiple times if two recipients prefer English and a third prefers Spanish for example.
  • Allows multiple administrators to receive the same admin notification but in their preferred language
  • Adds a new argument, $langcode, to the uc_order_theme() that is passed directly into the templates similar to variables like $thank_you_message.
  • For the template translation to work properly, an update is required to any overridden templates so that $langcode gets passed as the third argument to t(). For example:
    t('Welcome !username', array('!username' => ));
    # becomes
    t('Welcome !username', array('!username' => ), $langcode);
    
    # and
    
    t('Some string');
    # becomes
    t('Some string', array(), $langcode);
    # array() is used to indicate that there are no text replacements.
    

    The attached patch makes this change for the invoice templates included with Ubercart.

longwave’s picture

I wonder if we can temporarily switch the global site language before rendering the email template, to avoid having to add $langcode to every single t() call in there.

longwave’s picture

Status: Active » Needs review

Also, is it worth adding that extra code to avoid re-rendering the template multiple times, as most sites will only be sending one or two mails here?

Status: Needs review » Needs work

The last submitted patch, invoice_recipient_language-622388-1.patch, failed testing.

stewart.adam’s picture

Status: Needs work » Needs review
stewart.adam’s picture

[Re-queued the patch for testing because I have no clue why it did not apply successfully, I ran the same command it lists in the log and it applies cleanly]

I believe it would be possible to switch the global language, but that seemed a bit too hacky to me so I went the alternate route. If this is preferred though, I will redo the patch using this method. As for the extra code to avoid re-generatation, it is only a simple associative array that does all the work and it's well commented so I don't think it adds too much complexity and it has the possibility of improving performance.

Status: Needs review » Needs work

The last submitted patch, invoice_recipient_language-622388-1.patch, failed testing.

TR’s picture

Version: 6.x-2.0 » 6.x-2.x-dev

@firewing1: It's failing because of a bug with the testbot - hopefully that will be fixed soon. Until then, it would help if you install the simplest module on your own site and make sure the tests run clean with your patch.

micheleannj’s picture

subscribing... unless this has been solved elsewhere in the past 2 years?

TR’s picture

@micheleannj: A fix was proposed only last month. If you would like to see this resolved, you can test the fix and report whether it works for you. Issues don't magically resolve themselves - they need community participation. That means you are one of the people responsible for solving, or not solving, this problem.

PieterDC’s picture

I was thinking the same as @longwave in comment #2, so I created a quite different / smaller patch.

Ideally: drupal_mail() would let other modules, such as reglang, define which language to use for a mail, by invoking a hook before calling hook_mail() ... I guess

TR’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
longwave’s picture

Status: Needs work » Needs review
FileSize
1.3 KB

Fixed patch format. Test reports would be appreciated.

TR’s picture

Bumping - can someone test this?

fotisp’s picture

i can confirm that patch works fine for me for sending inovices from /admin/store/orders/xxxx/invoice/mail

thx :)

longwave’s picture

Version: 6.x-2.x-dev » 7.x-3.x-dev
Status: Needs review » Patch (to be ported)

Thanks for testing! Committed to 6.x-2.x, now needs porting to 7.x-3.x.

fotisp’s picture

Issue summary: View changes

Hello longwave,
I tested the patch to a uc3 installation and it works fine but it throws errors as $langcode is deleted and uc_order_mail in uc3 refers to it multiple times.
Deleting it from the lines seams to solved the problem but i'm not sure if this will cause other issues.
Could you please advice?
if it's ok i can provide a patch for uc3.
thanks!

TR’s picture

@fotisp: The patch for D6 works by temporarily storing the global $language variable, modifying it to the desired language for the e-mail, then restoring it when finished. The $langcode argument to t() was removed in the patch because we don't want two competing translation methods to conflict with each other.

In D7, the arguments to t() were changed to take an array with a key of 'langcode' instead of just a variable. See https://www.drupal.org/update/modules/6/7 for the changes between D6 and D7 - you can search for langcode to see what the changes were. Regardless, in D7, the third argument to t() should be removed for the same reason. (And the second argument too, since it's optional and not used and thus not needed unless there is a third argument.)

The other relevant change was with the token API. I think that the D7 patch should probably leave out the langcode argument to token_replace() just like it did for t().

Thanks for working on this. You can post your D7 patch here then set the issue status to "Needs review" to get the testbot and hopefully some humans look at it.