Skip to content

Commit 38ce6c3

Browse files
Peter Culkanicolas-grekas
Peter Culka
authored andcommitted
[Translation] Crowdin Bridge: Fix locale vs LanguageId
1 parent 2c4648e commit 38ce6c3

File tree

2 files changed

+134
-1
lines changed

2 files changed

+134
-1
lines changed

src/Symfony/Component/Translation/Bridge/Crowdin/CrowdinProvider.php

+37-1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ public function read(array $domains, array $locales): TranslatorBag
109109
$translatorBag = new TranslatorBag();
110110
$responses = [];
111111

112+
$localeLanguageMap = $this->mapLocalesToLanguageId($locales);
113+
112114
foreach ($domains as $domain) {
113115
$fileId = $this->getFileIdByDomain($fileList, $domain);
114116

@@ -118,7 +120,7 @@ public function read(array $domains, array $locales): TranslatorBag
118120

119121
foreach ($locales as $locale) {
120122
if ($locale !== $this->defaultLocale) {
121-
$response = $this->exportProjectTranslations($locale, $fileId);
123+
$response = $this->exportProjectTranslations($localeLanguageMap[$locale], $fileId);
122124
} else {
123125
$response = $this->downloadSourceFile($fileId);
124126
}
@@ -403,4 +405,38 @@ private function getFileList(): array
403405

404406
return $result;
405407
}
408+
409+
private function mapLocalesToLanguageId(array $locales): array
410+
{
411+
/**
412+
* We cannot query by locales, we need to fetch all and filter out the relevant ones.
413+
*
414+
* @see https://developer.crowdin.com/api/v2/#operation/api.languages.getMany (Crowdin API)
415+
* @see https://developer.crowdin.com/enterprise/api/v2/#operation/api.languages.getMany (Crowdin Enterprise API)
416+
*/
417+
$response = $this->client->request('GET', '../../languages?limit=500');
418+
419+
if (200 !== $response->getStatusCode()) {
420+
throw new ProviderException('Unable to list set languages.', $response);
421+
}
422+
423+
$localeLanguageMap = [];
424+
foreach ($response->toArray()['data'] as $language) {
425+
foreach (['locale', 'osxLocale', 'id'] as $key) {
426+
if (\in_array($language['data'][$key], $locales)) {
427+
$localeLanguageMap[$language['data'][$key]] = $language['data']['id'];
428+
}
429+
}
430+
}
431+
432+
if (\count($localeLanguageMap) !== \count($locales)) {
433+
$message = implode('", "', array_diff($locales, array_keys($localeLanguageMap)));
434+
$message = sprintf('Unable to find all requested locales: "%s" not found.', $message);
435+
$this->logger->error($message);
436+
437+
throw new ProviderException($message, $response);
438+
}
439+
440+
return $localeLanguageMap;
441+
}
406442
}

src/Symfony/Component/Translation/Bridge/Crowdin/Tests/CrowdinProviderTest.php

+97
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,30 @@ public function testReadForOneLocaleAndOneDomain(string $locale, string $domain,
632632
],
633633
]));
634634
},
635+
'listLanguages' => function (string $method, string $url, array $options = []): ResponseInterface {
636+
$this->assertSame('GET', $method);
637+
$this->assertSame('https://api.crowdin.com/api/v2/languages?limit=500', $url);
638+
$this->assertSame('Authorization: Bearer API_TOKEN', $options['normalized_headers']['authorization'][0]);
639+
640+
return new MockResponse(json_encode([
641+
'data' => [
642+
[
643+
'data' => [
644+
'id' => 'en-GB',
645+
'osxLocale' => 'en_GB',
646+
'locale' => 'en-GB',
647+
],
648+
],
649+
[
650+
'data' => [
651+
'id' => 'fr',
652+
'osxLocale' => 'fr_FR',
653+
'locale' => 'fr-FR',
654+
],
655+
],
656+
],
657+
]));
658+
},
635659
'exportProjectTranslations' => function (string $method, string $url, array $options = []) use ($expectedTargetLanguageId): ResponseInterface {
636660
$this->assertSame('POST', $method);
637661
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/translations/exports', $url);
@@ -746,12 +770,37 @@ public function testReadForDefaultLocaleAndOneDomain(string $locale, string $dom
746770
],
747771
]));
748772
},
773+
'listLanguages' => function (string $method, string $url, array $options = []): ResponseInterface {
774+
$this->assertSame('GET', $method);
775+
$this->assertSame('https://api.crowdin.com/api/v2/languages?limit=500', $url);
776+
$this->assertSame('Authorization: Bearer API_TOKEN', $options['normalized_headers']['authorization'][0]);
777+
778+
return new MockResponse(json_encode([
779+
'data' => [
780+
[
781+
'data' => [
782+
'id' => 'en',
783+
'osxLocale' => 'en_GB',
784+
'locale' => 'en-GB',
785+
],
786+
],
787+
[
788+
'data' => [
789+
'id' => 'fr',
790+
'osxLocale' => 'fr_FR',
791+
'locale' => 'fr-FR',
792+
],
793+
],
794+
],
795+
]));
796+
},
749797
'downloadSource' => function (string $method, string $url): ResponseInterface {
750798
$this->assertSame('GET', $method);
751799
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/files/12/download', $url);
752800

753801
return new MockResponse(json_encode(['data' => ['url' => 'https://file.url']]));
754802
},
803+
755804
'downloadFile' => function (string $method, string $url) use ($responseContent): ResponseInterface {
756805
$this->assertSame('GET', $method);
757806
$this->assertSame('https://file.url/', $url);
@@ -826,6 +875,30 @@ public function testReadServerException()
826875
],
827876
]));
828877
},
878+
'listLanguages' => function (string $method, string $url, array $options = []): ResponseInterface {
879+
$this->assertSame('GET', $method);
880+
$this->assertSame('https://api.crowdin.com/api/v2/languages?limit=500', $url);
881+
$this->assertSame('Authorization: Bearer API_TOKEN', $options['normalized_headers']['authorization'][0]);
882+
883+
return new MockResponse(json_encode([
884+
'data' => [
885+
[
886+
'data' => [
887+
'id' => 'en',
888+
'osxLocale' => 'en_GB',
889+
'locale' => 'en-GB',
890+
],
891+
],
892+
[
893+
'data' => [
894+
'id' => 'fr',
895+
'osxLocale' => 'fr_FR',
896+
'locale' => 'fr-FR',
897+
],
898+
],
899+
],
900+
]));
901+
},
829902
'exportProjectTranslations' => function (string $method, string $url, array $options = []): ResponseInterface {
830903
$this->assertSame('POST', $method);
831904
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/translations/exports', $url);
@@ -861,6 +934,30 @@ public function testReadDownloadServerException()
861934
],
862935
]));
863936
},
937+
'listLanguages' => function (string $method, string $url, array $options = []): ResponseInterface {
938+
$this->assertSame('GET', $method);
939+
$this->assertSame('https://api.crowdin.com/api/v2/languages?limit=500', $url);
940+
$this->assertSame('Authorization: Bearer API_TOKEN', $options['normalized_headers']['authorization'][0]);
941+
942+
return new MockResponse(json_encode([
943+
'data' => [
944+
[
945+
'data' => [
946+
'id' => 'en',
947+
'osxLocale' => 'en_GB',
948+
'locale' => 'en-GB',
949+
],
950+
],
951+
[
952+
'data' => [
953+
'id' => 'fr',
954+
'osxLocale' => 'fr_FR',
955+
'locale' => 'fr-FR',
956+
],
957+
],
958+
],
959+
]));
960+
},
864961
'exportProjectTranslations' => function (string $method, string $url, array $options = []): ResponseInterface {
865962
$this->assertSame('POST', $method);
866963
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/translations/exports', $url);

0 commit comments

Comments
 (0)