Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dev/core#4409 Use translation for default language, if exists #26232

Merged
merged 1 commit into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion CRM/Core/BAO/Translation.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public static function hook_civicrm_apiWrappers(&$wrappers, $apiRequest): void {
}

$communicationLanguage = \Civi\Core\Locale::detect()->nominal;
if ($communicationLanguage === Civi::settings()->get('lcMessages')) {
if (!$communicationLanguage || !self::isTranslate($communicationLanguage)) {
return;
}

Expand Down Expand Up @@ -207,6 +207,34 @@ public static function hook_civicrm_apiWrappers(&$wrappers, $apiRequest): void {
}
}

/**
* Should the translation process be followed.
*
* It can be short-circuited if there we are in the site default language and
* it is not translated.
*
* @param string $communicationLanguage
*
* @return bool
*/
protected static function isTranslate(string $communicationLanguage): bool {
if ($communicationLanguage !== Civi::settings()->get('lcMessages')) {
return TRUE;
}
if (!isset(\Civi::$statics[__CLASS__]['translate_main'][$communicationLanguage])) {
// The code had an assumption that you would not translate the primary language.
// However, the UI is such that the features (approval flow) so it makes sense
// to translation the default site language as well. If we can see sites are
// doing this then let's treat the main locale like any other locale
\Civi::$statics[__CLASS__]['translate_main'] = (bool) CRM_Core_DAO::singleValueQuery(
'SELECT COUNT(*) FROM civicrm_translation WHERE language = %1 LIMIT 1', [
1 => [$communicationLanguage, 'String'],
]
);
}
return \Civi::$statics[__CLASS__]['translate_main'];
}

/**
* @param \Civi\Api4\Generic\AbstractAction $apiRequest
* @return array translated fields.
Expand Down
12 changes: 11 additions & 1 deletion tests/phpunit/CRM/Core/BAO/MessageTemplateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ public function getLocaleConfigurations(): array {
$allTemplates['fr_CA'] = ['subject' => 'Bonjour Canada', 'html' => 'Voila! Canada', 'text' => '{contribution.total_amount}'];
$allTemplates['es_PR'] = ['subject' => 'Buenos dias', 'html' => 'Listo', 'text' => '{contribution.total_amount}'];
$allTemplates['th_TH'] = ['subject' => 'สวัสดี', 'html' => 'ดังนั้น', 'text' => '{contribution.total_amount}'];
// en_US is the default language. We add it to ensure the translation is loaded rather than falling back to
// the message template. While it might seem you don't need a translation for the site default language
// all the draft & approval logic is attached to the translation, not the template.
$allTemplates['en_US'] = ['subject' => 'site default', 'html' => 'site default language', 'text' => '{contribution.total_amount}'];

$rendered = [];
// $rendered['*'] = ['subject' => 'Hello', 'html' => 'Look there!', 'text' => '$ 100.00'];
Expand All @@ -78,6 +82,7 @@ public function getLocaleConfigurations(): array {
$rendered['fr_CA'] = ['subject' => 'Bonjour Canada', 'html' => 'Voila! Canada', 'text' => '100,00 $ US'];
$rendered['es_PR'] = ['subject' => 'Buenos dias', 'html' => 'Listo', 'text' => '100.00 $US'];
$rendered['th_TH'] = ['subject' => 'สวัสดี', 'html' => 'ดังนั้น', 'text' => 'US$100.00'];
$rendered['en_US'] = ['subject' => 'site default', 'html' => 'site default language', 'text' => '$100.00'];

$result = [/* settings, templates, preferredLanguage, expectMessage */];

Expand All @@ -92,11 +97,16 @@ public function getLocaleConfigurations(): array {
$result['fr_CA falls back to fr_FR (ltd-tpls; no-partials)'] = [$noPartials, $this->getLocaleTemplates($allTemplates, ['*', 'fr_FR']), 'fr_CA', $rendered['fr_FR']];

$result['th_TH matches th_TH (all-tpls; yes-partials)'] = [$yesPartials, $allTemplates, 'th_TH', $rendered['th_TH']];
$result['th_TH falls back to system default (all-tpls; no-partials)'] = [$noPartials, $allTemplates, 'th_TH', $rendered['*']];
$result['th_TH falls back to site default translation (all-tpls; no-partials)'] = [$noPartials, $allTemplates, 'th_TH', $rendered['en_US']];
// Absent a translation for the site default language it should fall back to the message template.
$result['th_TH falls back to system default (all-tpls; no-partials)'] = [$noPartials, array_diff_key($allTemplates, ['en_US' => TRUE]), 'th_TH', $rendered['*']];
// ^^ The essence of the `partial_locales` setting -- whether partially-supported locales (th_TH) use mixed-mode or fallback to completely diff locale.
$result['th_TH falls back to system default (ltd-tpls; yes-partials)'] = [$yesPartials, $this->getLocaleTemplates($allTemplates, ['*']), 'th_TH', $rendered['*']];
$result['th_TH falls back to system default (ltd-tpls; no-partials)'] = [$noPartials, $this->getLocaleTemplates($allTemplates, ['*']), 'th_TH', $rendered['*']];

// Check that the en_US template is loaded, if exists.
$result['en_US matches en_US (all-tpls; yes-partials)'] = [$yesPartials, $allTemplates, 'en_US', $rendered['en_US']];

return $result;
}

Expand Down