self::synchronizeLegacyParameters($params);
$params = array_merge($modelDefaults, $viewDefaults, $envelopeDefaults, $params);
-
+ $language = $params['language'] ?? (!empty($params['contactId']) ? Civi\Api4\Contact::get(FALSE)->addWhere('id', '=', $params['contactId'])->addSelect('preferred_language')->execute()->first()['preferred_language'] : NULL);
CRM_Utils_Hook::alterMailParams($params, 'messageTemplate');
- $mailContent = self::loadTemplate((string) $params['workflow'], $params['isTest'], $params['messageTemplateID'] ?? NULL, $params['groupName'] ?? '', $params['messageTemplate'], $params['subject'] ?? NULL);
+ [$mailContent, $translatedLanguage] = self::loadTemplate((string) $params['workflow'], $params['isTest'], $params['messageTemplateID'] ?? NULL, $params['groupName'] ?? '', $params['messageTemplate'], $params['subject'] ?? NULL, $language);
+ global $moneyFormatLocale;
+ $originalValue = $moneyFormatLocale;
+ if ($translatedLanguage) {
+ // If the template has been translated then set the moneyFormatLocale to match the translation.
+ // Note that in future if we do the same for dates we are likely to want to set it to match
+ // the preferred_language rather than the translation language - a long discussion is on the
+ // property in AbstractAction
+ $moneyFormatLocale = $translatedLanguage;
+ }
self::synchronizeLegacyParameters($params);
$rendered = CRM_Core_TokenSmarty::render(CRM_Utils_Array::subset($mailContent, ['text', 'html', 'subject']), $params['tokenContext'], $params['tplParams']);
}
$nullSet = ['subject' => NULL, 'text' => NULL, 'html' => NULL];
$mailContent = array_merge($nullSet, $mailContent, $rendered);
+ $moneyFormatLocale = $originalValue;
return [$mailContent, $params];
}
* If omitted, the record will be loaded from workflowName/messageTemplateID.
* @param string|null $subjectOverride
* This option is the older, wonkier version of $messageTemplate['msg_subject']...
+ * @param string|null $language
*
* @return array
* @throws \API_Exception
* @throws \CRM_Core_Exception
*/
- protected static function loadTemplate(string $workflowName, bool $isTest, int $messageTemplateID = NULL, $groupName = NULL, ?array $messageTemplateOverride = NULL, ?string $subjectOverride = NULL): array {
+ protected static function loadTemplate(string $workflowName, bool $isTest, int $messageTemplateID = NULL, $groupName = NULL, ?array $messageTemplateOverride = NULL, ?string $subjectOverride = NULL, ?string $language = NULL): array {
$base = ['msg_subject' => NULL, 'msg_text' => NULL, 'msg_html' => NULL, 'pdf_format_id' => NULL];
if (!$workflowName && !$messageTemplateID) {
throw new CRM_Core_Exception(ts("Message template's option value or ID missing."));
}
$apiCall = MessageTemplate::get(FALSE)
+ ->setLanguage($language)
->addSelect('msg_subject', 'msg_text', 'msg_html', 'pdf_format_id', 'id')
->addWhere('is_default', '=', 1);
else {
$apiCall->addWhere('workflow_name', '=', $workflowName);
}
- $messageTemplate = array_merge($base, $apiCall->execute()->first() ?: [], $messageTemplateOverride ?: []);
+ $result = $apiCall->execute();
+ $messageTemplate = array_merge($base, $result->first() ?: [], $messageTemplateOverride ?: []);
if (empty($messageTemplate['id']) && empty($messageTemplateOverride)) {
if ($messageTemplateID) {
throw new CRM_Core_Exception(ts('No such message template: id=%1.', [1 => $messageTemplateID]));
$this->assertStringContainsString('<p>Hello testRenderTemplate Abba Baab!</p>', $rendered['html']);
}
+ /**
+ * Test that translated strings are rendered for templates where they exist.
+ *
+ * @throws \API_Exception|\CRM_Core_Exception
+ */
+ public function testRenderTranslatedTemplate(): void {
+ $this->individualCreate(['preferred_language' => 'fr_FR']);
+ $contributionID = $this->contributionCreate(['contact_id' => $this->ids['Contact']['individual_0']]);
+ $messageTemplateID = MessageTemplate::get()
+ ->addWhere('is_default', '=', 1)
+ ->addWhere('workflow_name', '=', 'contribution_online_receipt')
+ ->addSelect('id')
+ ->execute()->first()['id'];
+
+ Translation::save()->setRecords([
+ ['entity_field' => 'msg_subject', 'string' => 'Bonjour'],
+ ['entity_field' => 'msg_html', 'string' => 'Voila!'],
+ ['entity_field' => 'msg_text', 'string' => '{contribution.total_amount}'],
+ ])->setDefaults([
+ 'entity_table' => 'civicrm_msg_template',
+ 'entity_id' => $messageTemplateID,
+ 'status_id:name' => 'active',
+ 'language' => 'fr_FR',
+ ])->execute();
+
+ $messageTemplateFrench = MessageTemplate::get()
+ ->addWhere('is_default', '=', 1)
+ ->addWhere('workflow_name', '=', 'contribution_online_receipt')
+ ->addSelect('id', 'msg_subject', 'msg_html')
+ ->setLanguage('fr_FR')
+ ->execute()->first();
+
+ $this->assertEquals('Bonjour', $messageTemplateFrench['msg_subject']);
+ $this->assertEquals('Voila!', $messageTemplateFrench['msg_html']);
+
+ $rendered = CRM_Core_BAO_MessageTemplate::renderTemplate([
+ 'workflow' => 'contribution_online_receipt',
+ 'tokenContext' => [
+ 'contactId' => $this->ids['Contact']['individual_0'],
+ 'contributionId' => $contributionID,
+ ],
+ ]);
+ $this->assertEquals('Bonjour', $rendered['subject']);
+ $this->assertEquals('Voila!', $rendered['html']);
+ $this->assertEquals('100,00 $US', $rendered['text']);
+
+ // French Canadian should ALSO pick up French if there
+ //is no specific French Canadian.
+ $rendered = CRM_Core_BAO_MessageTemplate::renderTemplate([
+ 'workflow' => 'contribution_online_receipt',
+ 'tokenContext' => [
+ 'contactId' => $this->ids['Contact']['individual_0'],
+ 'contributionId' => $contributionID,
+ ],
+ 'language' => 'fr_CA',
+ ]);
+ $this->assertEquals('Bonjour', $rendered['subject']);
+ $this->assertEquals('Voila!', $rendered['html']);
+ // Money is formatted per fr_FR locale as that is the found-template-locale.
+ $this->assertEquals('100,00 $US', $rendered['text']);
+
+ Translation::save()->setRecords([
+ ['entity_field' => 'msg_subject', 'string' => 'Bonjour Canada'],
+ ['entity_field' => 'msg_html', 'string' => 'Voila! Canada'],
+ ['entity_field' => 'msg_text', 'string' => '{contribution.total_amount}'],
+ ])->setDefaults([
+ 'entity_table' => 'civicrm_msg_template',
+ 'entity_id' => $messageTemplateID,
+ 'status_id:name' => 'active',
+ 'language' => 'fr_CA',
+ ])->execute();
+
+ // But, prefer French Canadian where both exist.
+ $rendered = CRM_Core_BAO_MessageTemplate::renderTemplate([
+ 'workflow' => 'contribution_online_receipt',
+ 'tokenContext' => [
+ 'contactId' => $this->ids['Contact']['individual_0'],
+ 'contributionId' => $contributionID,
+ ],
+ 'language' => 'fr_CA',
+ ]);
+ $this->assertEquals('Bonjour Canada', $rendered['subject']);
+ $this->assertEquals('Voila! Canada', $rendered['html']);
+ // Note that as there was a native-Canada format the money-formatting is
+ // also subtly different.
+ $this->assertEquals('100,00 $ US', $rendered['text']);
+ }
+
/**
* @throws \API_Exception
* @throws \CRM_Core_Exception