Skip to content

Commit 38ce6c3

Browse files
Peter Culkanicolas-grekas
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

Lines changed: 37 additions & 1 deletion
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

Lines changed: 97 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy