Background information
I am developing a multilingual Drupal 8 commerce site where only authenticated users (customers) can place orders (anonymous users can't place orders). Customers can edit their preferred language using the default language field on their account. After an order is placed, another user with a special role (webmaster) has to prepare the order and physically fill a box with the contents of the order. When the webmaster is ready, he performs a transition on the order changing it's state. This transition triggers an e-mail that is sent to the customer, informing him that his order is ready for shipment. This e-mail is triggered through an event subscriber that reacts on the shipping transition of orders. The e-mail is formed by rendering a custom template.
Problem
A customer who's preferred language is Dutch, has placed an order. A webmaster is using the website in English and sets the order 'ready for shipment'. The customer gets an English e-mail while he should get a Dutch e-mail.
Code
The code that triggers the e-mail:
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$order = $event->getEntity();
$to = $order->getCustomer()->getEmail();
$langcode = $order->getCustomer()->getPreferredLangcode();
$subject = $this->t('Your order #@order_number is packed', ['@order_number' => $order->getOrderNumber()], ['langcode' => $langcode]);
$build = [
'#theme' => 'commerce_order_shipped_mail',
'#subject' => $subject,
'#order_number' => $order->getOrderNumber(),
'#order_date' => $this->dateFormatter->format($order->getCompletedTime(), 'default_date_only'),
'#order_url' => Url::fromRoute('entity.commerce_order.user_view', [
'user' => $order->getCustomer()->id(),
'commerce_order' => $order->id(),
], ['absolute' => TRUE]),
];
$mail = $this->mailManager->mail('order_shipped_mail', $to, $subject, $build, $langcode);
The mail function of the mail manger (wrapper):
$name = \Drupal::config('system.site')->get('name');
$email = \Drupal::config('system.site')->get('mail');
$from = '"' . $name . '" <' . $email . '>';
$params = [
'headers' => [
'Content-Type' => 'text/html; charset=UTF-8; format=flowed; delsp=yes',
'Content-Transfer-Encoding' => '8Bit',
'From' => $from,
],
'from' => $from,
'subject' => $subject,
'body' => $this->renderer->renderRoot($body),
];
$langcode = $langcode ?: $this->languageManager->getDefaultLanguage()->getId();
return $this->mailManager->mail('XXX_general', $key, $to, $langcode, $params);
The custom template:
<table>
<tbody>
<tr>
<td>
<h2>{{ 'Shipping confirmation'|t }}</h2>
<p>{{ 'Dear customer,'|t }}</p>
<p>
{% trans %}
Your order #{{ order_number }} of {{ order_date }} has been handed over to XXX.<br />
You will receive an email from XXX with the tracking information of your package.
{% endtrans %}
</p>
<p><a href="{{ order_url }}" target="{{ 'Order details'|t }}">{{ 'Order details'|t }}</a></p>
<p>The XXX team</p>
</td>
</tr>
</tbody>
As you can see a custom template is rendered that contains the body of the e-mail.
Actual question
How can I temporarily change the current language during a request so rendering happens in the correct language? I know I can give a langcode to a t-function but my rendered order URL would still be an English URL so this doesn't fix the problem. I have tried suggestions from here, and I thought the LanguageNegotiation Plugin would do the trick, but it doesn't.
Please excuse me if my question is malformed or if I provided to little information.