diff --git a/Civi/Core/Locale.php b/Civi/Core/Locale.php index 709a37bcc04edf620fe5e6cb8d2071e6a79db555..467fb722fbbd476b50c09657ffac7bbfc8f1ac07 100644 --- a/Civi/Core/Locale.php +++ b/Civi/Core/Locale.php @@ -203,6 +203,14 @@ class Locale { $validDbLocales = \Civi::settings()->get('languageLimit'); $locale->db = static::pickFirstLocale(array_keys($validDbLocales), $fallbacks) ?: $systemDefault; } + + // Determine locale for UF APIs: This next bit is a little bit wrong. + // We should have something like `$validUfLanguages` and pick the closest match. + // Or perhaps each `CRM_Utils_System_{$UF}` should have a `negotiate()` helper. + // But it's a academic... D7/D8/BD are the only UF's which implement `setUFLocale`/`getUFLocale`, + // and they drop the country-code - which basically addresses the goal (falling back to a more generic locale). + $locale->uf = $locale->ts; + return $locale; } diff --git a/tests/phpunit/E2E/Api4/LocaleTest.php b/tests/phpunit/E2E/Api4/LocaleTest.php index 9fa21cd6bfa88d3ae30d52577d88a26d87f37a15..c8356fbc12c331ab337e57ff307f7114694f1f3f 100644 --- a/tests/phpunit/E2E/Api4/LocaleTest.php +++ b/tests/phpunit/E2E/Api4/LocaleTest.php @@ -2,22 +2,78 @@ namespace E2E\Api4; +use Civi\API\Event\RespondEvent; + /** * Class LocaleTest + * * @package E2E\Api4 * @group e2e */ class LocaleTest extends \CiviEndToEndTestCase { + public function getLanguageExamples(): array { + $results = []; + switch (CIVICRM_UF) { + case 'Drupal': + case 'Drupal8': + case 'Backdrop': + $results[] = ['de_DE', 'de_CH', 't', 'Yes', 'Ja']; + // That's weird -- you install Drupal's "de", and you do `setUFLocale('de_DE')`, and + // the result is... to report back as 'de_DE'. Weird. But the actual string is OK... + break; + + case 'WordPress': + $results[] = ['de_DE', 'de_DE', '__', 'Yes', 'Ja']; + break; + + case 'Joomla': + default: + $this->fail('Test not implemented for ' . CIVICRM_UF); + } + return $results; + } + /** - * Ensure that + * APIv4 allows you to request that operations be processed in a specific language. + * + * @param string $civiLocale + * The locale to specify in Civi. (eg Civi\Api4\Foo::bar()->setLanguage($civiLocale)) + * Ex: 'de_DE' + * @param string $expectUfLocale + * The corresponding locale in the UF. + * Ex: 'de' + * @param string|array $translator + * The user-framework's translation method. + * Ex: 't' (Drupal) or '__' (WordPress) + * @param string $inputString + * The string to translate. + * Ex: 'Yes', 'Login', 'Continue' + * @param string $expectString + * The string that should be returned. + * Ex: 'Ja', 'Anmeldung', 'Fortsetzen' + * + * @dataProvider getLanguageExamples */ - public function testSetLanguage() { + public function testSetLanguage($civiLocale, $expectUfLocale, $translator, $inputString, $expectString) { + $actualStrings = []; + $actualLocales = []; + \Civi::dispatcher()->addListener('civi.api.respond', function (RespondEvent $e) use (&$actualStrings, &$actualLocales, $translator, $inputString, $civiLocale) { + $isTranslatedRequest = ($e->getApiRequest()->getLanguage() === $civiLocale); + if ($isTranslatedRequest) { + $actualLocales[] = \CRM_Utils_System::getUFLocale(); + $actualStrings[] = call_user_func($translator, $inputString); + } + }, -100); $contacts = civicrm_api4('Contact', 'get', [ 'limit' => 25, - 'language' => 'en_US', + 'language' => $civiLocale, ]); - $this->assertTrue(count($contacts) > 0); + $this->assertTrue(count($contacts) > 0, 'The API call should return successfully.'); + $this->assertEquals(1, count($actualLocales), 'We should observed one UF locale.'); + $this->assertEquals(1, count($actualStrings), 'We should observed one UF translation.'); + $this->assertEquals($expectUfLocale . ':' . $expectString, $actualLocales[0] . ':' . $actualStrings[0], + "Expected UF to report locale as '$expectUfLocale:$expectString'."); } }