$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, $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;
- }
+ $params['tokenContext']['locale'] = $translatedLanguage ?? $params['language'] ?? NULL;
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];
}
$apiCall = MessageTemplate::get(FALSE)
->setLanguage($language)
+ ->setTranslationMode('fuzzy')
->addSelect('msg_subject', 'msg_text', 'msg_html', 'pdf_format_id', 'id')
->addWhere('is_default', '=', 1);
$mailContent['subject'] = $subjectOverride;
}
- return [$mailContent, $apiCall->getTranslationLanguage()];
+ return [$mailContent, $messageTemplate['actual_language'] ?? NULL];
}
/**
public function _run(\Civi\Api4\Generic\Result $result) {
$this->validateValues();
- global $moneyFormatLocale;
- $separatorConfig = \CRM_Utils_Constant::value('IGNORE_SEPARATOR_CONFIG');
- $originalValue = $moneyFormatLocale;
-
- if ($this->getTranslationLanguage()) {
- // Passing in translation language forces money formatting, useful when the
- // template is previewed before being saved.
- $moneyFormatLocale = $this->getTranslationLanguage();
- putenv('IGNORE_SEPARATOR_CONFIG=' . 1);
- }
$r = \CRM_Core_BAO_MessageTemplate::renderTemplate([
'model' => $this->_model,
'messageTemplate' => $this->getMessageTemplate(),
'messageTemplateId' => $this->getMessageTemplateId(),
- 'language' => $this->getPreferredLanguage(),
+ 'language' => $this->getLanguage(),
]);
- $moneyFormatLocale = $originalValue;
- putenv('IGNORE_SEPARATOR_CONFIG=' . $separatorConfig);
$result[] = \CRM_Utils_Array::subset($r, ['subject', 'html', 'text']);
}
use Civi\Api4\Address;
use Civi\Api4\Contact;
use Civi\Api4\MessageTemplate;
+use Civi\Api4\Translation;
use Civi\Token\TokenProcessor;
/**
/**
* Test that translated strings are rendered for templates where they exist.
*
+ * This system has a relatively open localization policy where any translation can be used,
+ * even if the system doesn't allow it in the web UI. Ex: The sysadmin has configured 'fr_FR'
+ * strings. The user has requested 'fr_CA', and we'll fallback to 'fr_CA'.
+ *
* @throws \API_Exception|\CRM_Core_Exception
+ * @group locale
*/
- public function testRenderTranslatedTemplate(): void {
+ public function testRenderTranslatedTemplate_AllowPartialLocales(): void {
+ $cleanup = \CRM_Utils_AutoClean::swapSettings(['partial_locales' => TRUE, 'uiLanguages' => ['en_US']]);
+
$this->individualCreate(['preferred_language' => 'fr_FR']);
$contributionID = $this->contributionCreate(['contact_id' => $this->ids['Contact']['individual_0']]);
$messageTemplateID = MessageTemplate::get()
->addWhere('workflow_name', '=', 'contribution_online_receipt')
->addSelect('id', 'msg_subject', 'msg_html')
->setLanguage('fr_FR')
+ ->setTranslationMode('fuzzy')
->execute()->first();
$this->assertEquals('Bonjour', $messageTemplateFrench['msg_subject']);
$this->assertEquals('100,00 $ US', $rendered['text']);
}
+ /**
+ * Test that translated strings are rendered for templates where they exist.
+ *
+ * This system has a relatively closed localization policy where translations will only be
+ * used if the locale is fully supported by the app. Ex: Even though there are some strings
+ * for 'fr_FR', the language in "Admin=>Localizaton", so we don't use it.
+ *
+ * @throws \API_Exception|\CRM_Core_Exception
+ * @group locale
+ */
+ public function testRenderTranslatedTemplate_OnlyFullLocales(): void {
+ $cleanup = \CRM_Utils_AutoClean::swapSettings(['partial_locales' => FALSE, 'uiLanguages' => ['en_US']]);
+
+ $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')
+ ->setTranslationMode('fuzzy')
+ ->execute()->first();
+
+ $this->assertStringNotContainsString('Bonjour', $messageTemplateFrench['msg_subject']);
+ $this->assertStringNotContainsString('Voila!', $messageTemplateFrench['msg_html']);
+
+ $rendered = CRM_Core_BAO_MessageTemplate::renderTemplate([
+ 'workflow' => 'contribution_online_receipt',
+ 'tokenContext' => [
+ 'contactId' => $this->ids['Contact']['individual_0'],
+ 'contributionId' => $contributionID,
+ ],
+ ]);
+ $this->assertStringNotContainsString('Bonjour', $rendered['subject']);
+ $this->assertStringNotContainsString('Voila!', $rendered['html']);
+ $this->assertStringNotContainsString('100,00', $rendered['text']);
+ }
+
/**
* @throws \API_Exception
* @throws \CRM_Core_Exception