Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d4f467c

Browse files
committed
[Translation] Crowdin Bridge: use the project language mapping
1 parent d676858 commit d4f467c

File tree

2 files changed

+126
-85
lines changed

2 files changed

+126
-85
lines changed

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

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,13 @@ public function __toString(): string
5656
public function write(TranslatorBagInterface $translatorBag): void
5757
{
5858
$fileList = $this->getFileList();
59+
$languageMapping = $this->getLanguageMapping();
5960

6061
$responses = [];
6162

6263
foreach ($translatorBag->getCatalogues() as $catalogue) {
64+
$locale = $catalogue->getLocale();
65+
6366
foreach ($catalogue->getDomains() as $domain) {
6467
if (0 === \count($catalogue->all($domain))) {
6568
continue;
@@ -86,7 +89,7 @@ public function write(TranslatorBagInterface $translatorBag): void
8689
continue;
8790
}
8891

89-
$responses[] = $this->uploadTranslations($fileId, $domain, $content, $catalogue->getLocale());
92+
$responses[] = $this->uploadTranslations($fileId, $domain, $content, $languageMapping[$locale] ?? $locale);
9093
}
9194
}
9295
}
@@ -105,12 +108,11 @@ public function write(TranslatorBagInterface $translatorBag): void
105108
public function read(array $domains, array $locales): TranslatorBag
106109
{
107110
$fileList = $this->getFileList();
111+
$languageMapping = $this->getLanguageMapping();
108112

109113
$translatorBag = new TranslatorBag();
110114
$responses = [];
111115

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

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

121123
foreach ($locales as $locale) {
122124
if ($locale !== $this->defaultLocale) {
123-
$response = $this->exportProjectTranslations($localeLanguageMap[$locale], $fileId);
125+
$response = $this->exportProjectTranslations($languageMapping[$locale] ?? $locale, $fileId);
124126
} else {
125127
$response = $this->downloadSourceFile($fileId);
126128
}
@@ -406,37 +408,29 @@ private function getFileList(): array
406408
return $result;
407409
}
408410

409-
private function mapLocalesToLanguageId(array $locales): array
411+
private function getLanguageMapping(): array
410412
{
411413
/**
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)
414+
* @see https://developer.crowdin.com/api/v2/#operation/api.projects.get (Crowdin API)
415+
* @see https://developer.crowdin.com/enterprise/api/v2/#operation/api.projects.get (Crowdin Enterprise API)
416416
*/
417-
$response = $this->client->request('GET', '../../languages?limit=500');
417+
$response = $this->client->request('GET', '');
418418

419419
if (200 !== $response->getStatusCode()) {
420-
throw new ProviderException('Unable to list set languages.', $response);
420+
throw new ProviderException('Unable to get project info.', $response);
421421
}
422422

423-
$localeLanguageMap = [];
424-
foreach ($response->toArray()['data'] as $language) {
425-
foreach (['locale', 'osxLocale', 'id'] as $key) {
426-
if (\in_array($language['data'][$key], $locales, true)) {
427-
$localeLanguageMap[$language['data'][$key]] = $language['data']['id'];
428-
}
429-
}
423+
$projectInfo = $response->toArray()['data'];
424+
if (empty($projectInfo['languageMapping'])) {
425+
return [];
430426
}
431427

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);
428+
$mapping = [];
429+
foreach ($projectInfo['languageMapping'] as $key => $value) {
430+
$locale = $value['locale'];
431+
$mapping[$locale] = $key;
438432
}
439433

440-
return $localeLanguageMap;
434+
return $mapping;
441435
}
442436
}

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

Lines changed: 107 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ public function testCompleteWriteProcessAddFiles()
111111

112112
return new JsonMockResponse(['data' => []]);
113113
},
114+
'getProject' => function (string $method, string $url): ResponseInterface {
115+
$this->assertSame('GET', $method);
116+
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/', $url);
117+
118+
return new JsonMockResponse(['data' => ['languageMapping' => []]]);
119+
},
114120
'addStorage' => function (string $method, string $url, array $options = []) use ($expectedMessagesFileContent): ResponseInterface {
115121
$this->assertSame('POST', $method);
116122
$this->assertSame('https://api.crowdin.com/api/v2/storages', $url);
@@ -189,6 +195,12 @@ public function testWriteAddFileServerError()
189195

190196
return new JsonMockResponse(['data' => []]);
191197
},
198+
'getProject' => function (string $method, string $url): ResponseInterface {
199+
$this->assertSame('GET', $method);
200+
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/', $url);
201+
202+
return new JsonMockResponse(['data' => ['languageMapping' => []]]);
203+
},
192204
'addStorage' => function (string $method, string $url, array $options = []) use ($expectedMessagesFileContent): ResponseInterface {
193205
$this->assertSame('POST', $method);
194206
$this->assertSame('https://api.crowdin.com/api/v2/storages', $url);
@@ -261,6 +273,12 @@ public function testWriteUpdateFileServerError()
261273
],
262274
]));
263275
},
276+
'getProject' => function (string $method, string $url): ResponseInterface {
277+
$this->assertSame('GET', $method);
278+
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/', $url);
279+
280+
return new JsonMockResponse(['data' => ['languageMapping' => []]]);
281+
},
264282
'addStorage' => function (string $method, string $url, array $options = []) use ($expectedMessagesFileContent): ResponseInterface {
265283
$this->assertSame('POST', $method);
266284
$this->assertSame('https://api.crowdin.com/api/v2/storages', $url);
@@ -350,6 +368,12 @@ public function testWriteUploadTranslationsServerError()
350368
],
351369
]);
352370
},
371+
'getProject' => function (string $method, string $url): ResponseInterface {
372+
$this->assertSame('GET', $method);
373+
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/', $url);
374+
375+
return new JsonMockResponse(['data' => ['languageMapping' => []]]);
376+
},
353377
'addStorage' => function (string $method, string $url, array $options = []) use ($expectedMessagesFileContent): ResponseInterface {
354378
$this->assertSame('POST', $method);
355379
$this->assertSame('https://api.crowdin.com/api/v2/storages', $url);
@@ -443,6 +467,12 @@ public function testCompleteWriteProcessUpdateFiles()
443467
],
444468
]);
445469
},
470+
'getProject' => function (string $method, string $url): ResponseInterface {
471+
$this->assertSame('GET', $method);
472+
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/', $url);
473+
474+
return new JsonMockResponse(['data' => ['languageMapping' => []]]);
475+
},
446476
'addStorage' => function (string $method, string $url, array $options = []) use ($expectedMessagesFileContent): ResponseInterface {
447477
$this->assertSame('POST', $method);
448478
$this->assertSame('https://api.crowdin.com/api/v2/storages', $url);
@@ -513,6 +543,20 @@ public function testCompleteWriteProcessAddFileAndUploadTranslations(TranslatorB
513543
],
514544
]);
515545
},
546+
'getProject' => function (string $method, string $url): ResponseInterface {
547+
$this->assertSame('GET', $method);
548+
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/', $url);
549+
550+
return new JsonMockResponse([
551+
'data' => [
552+
'languageMapping' => [
553+
'pt-PT' => [
554+
'locale' => 'pt',
555+
],
556+
],
557+
],
558+
]);
559+
},
516560
'addStorage' => function (string $method, string $url, array $options = []) use ($expectedMessagesFileContent): ResponseInterface {
517561
$this->assertSame('POST', $method);
518562
$this->assertSame('https://api.crowdin.com/api/v2/storages', $url);
@@ -543,6 +587,22 @@ public function testCompleteWriteProcessAddFileAndUploadTranslations(TranslatorB
543587
$this->assertSame(sprintf('https://api.crowdin.com/api/v2/projects/1/translations/%s', $expectedLocale), $url);
544588
$this->assertSame('{"storageId":19,"fileId":12}', $options['body']);
545589

590+
return new MockResponse();
591+
},
592+
'addStorage3' => function (string $method, string $url, array $options = []) use ($expectedMessagesTranslationsContent): ResponseInterface {
593+
$this->assertSame('POST', $method);
594+
$this->assertSame('https://api.crowdin.com/api/v2/storages', $url);
595+
$this->assertSame('Content-Type: application/octet-stream', $options['normalized_headers']['content-type'][0]);
596+
$this->assertSame('Crowdin-API-FileName: messages.xlf', $options['normalized_headers']['crowdin-api-filename'][0]);
597+
$this->assertStringMatchesFormat($expectedMessagesTranslationsContent, $options['body']);
598+
599+
return new JsonMockResponse(['data' => ['id' => 19]], ['http_code' => 201]);
600+
},
601+
'uploadTranslations2' => function (string $method, string $url, array $options = []) use ($expectedLocale): ResponseInterface {
602+
$this->assertSame('POST', $method);
603+
$this->assertSame(sprintf('https://api.crowdin.com/api/v2/projects/1/translations/%s', $expectedLocale), $url);
604+
$this->assertSame('{"storageId":19,"fileId":12}', $options['body']);
605+
546606
return new MockResponse();
547607
},
548608
];
@@ -583,6 +643,33 @@ public static function getResponsesForProcessAddFileAndUploadTranslations(): \Ge
583643
</file>
584644
</xliff>
585645

646+
XLIFF
647+
];
648+
649+
$translatorBagPt = new TranslatorBag();
650+
$translatorBagPt->addCatalogue($arrayLoader->load([
651+
'a' => 'trans_en_a',
652+
], 'en'));
653+
$translatorBagPt->addCatalogue($arrayLoader->load([
654+
'a' => 'trans_pt_a',
655+
], 'pt'));
656+
657+
yield [$translatorBagPt, 'pt-PT', <<<'XLIFF'
658+
<?xml version="1.0" encoding="utf-8"?>
659+
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
660+
<file source-language="en" target-language="pt" datatype="plaintext" original="file.ext">
661+
<header>
662+
<tool tool-id="symfony" tool-name="Symfony"/>
663+
</header>
664+
<body>
665+
<trans-unit id="%s" resname="a">
666+
<source>a</source>
667+
<target>trans_pt_a</target>
668+
</trans-unit>
669+
</body>
670+
</file>
671+
</xliff>
672+
586673
XLIFF
587674
];
588675

@@ -633,25 +720,15 @@ public function testReadForOneLocaleAndOneDomain(string $locale, string $domain,
633720
],
634721
]);
635722
},
636-
'listLanguages' => function (string $method, string $url, array $options = []): ResponseInterface {
723+
'getProject' => function (string $method, string $url): ResponseInterface {
637724
$this->assertSame('GET', $method);
638-
$this->assertSame('https://api.crowdin.com/api/v2/languages?limit=500', $url);
639-
$this->assertSame('Authorization: Bearer API_TOKEN', $options['normalized_headers']['authorization'][0]);
725+
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/', $url);
640726

641727
return new JsonMockResponse([
642728
'data' => [
643-
[
644-
'data' => [
645-
'id' => 'en-GB',
646-
'osxLocale' => 'en_GB',
647-
'locale' => 'en-GB',
648-
],
649-
],
650-
[
651-
'data' => [
652-
'id' => 'fr',
653-
'osxLocale' => 'fr_FR',
654-
'locale' => 'fr-FR',
729+
'languageMapping' => [
730+
'pt-PT' => [
731+
'locale' => 'pt',
655732
],
656733
],
657734
],
@@ -771,25 +848,15 @@ public function testReadForDefaultLocaleAndOneDomain(string $locale, string $dom
771848
],
772849
]);
773850
},
774-
'listLanguages' => function (string $method, string $url, array $options = []): ResponseInterface {
851+
'getProject' => function (string $method, string $url): ResponseInterface {
775852
$this->assertSame('GET', $method);
776-
$this->assertSame('https://api.crowdin.com/api/v2/languages?limit=500', $url);
777-
$this->assertSame('Authorization: Bearer API_TOKEN', $options['normalized_headers']['authorization'][0]);
853+
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/', $url);
778854

779855
return new JsonMockResponse([
780856
'data' => [
781-
[
782-
'data' => [
783-
'id' => 'en',
784-
'osxLocale' => 'en_GB',
785-
'locale' => 'en-GB',
786-
],
787-
],
788-
[
789-
'data' => [
790-
'id' => 'fr',
791-
'osxLocale' => 'fr_FR',
792-
'locale' => 'fr-FR',
857+
'languageMapping' => [
858+
'pt-PT' => [
859+
'locale' => 'pt',
793860
],
794861
],
795862
],
@@ -875,25 +942,15 @@ public function testReadServerException()
875942
],
876943
]);
877944
},
878-
'listLanguages' => function (string $method, string $url, array $options = []): ResponseInterface {
945+
'getProject' => function (string $method, string $url): ResponseInterface {
879946
$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]);
947+
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/', $url);
882948

883949
return new JsonMockResponse([
884950
'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',
951+
'languageMapping' => [
952+
'pt-PT' => [
953+
'locale' => 'pt',
897954
],
898955
],
899956
],
@@ -934,25 +991,15 @@ public function testReadDownloadServerException()
934991
],
935992
]);
936993
},
937-
'listLanguages' => function (string $method, string $url, array $options = []): ResponseInterface {
994+
'getProject' => function (string $method, string $url): ResponseInterface {
938995
$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]);
996+
$this->assertSame('https://api.crowdin.com/api/v2/projects/1/', $url);
941997

942998
return new JsonMockResponse([
943999
'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',
1000+
'languageMapping' => [
1001+
'pt-PT' => [
1002+
'locale' => 'pt',
9561003
],
9571004
],
9581005
],

0 commit comments

Comments
 (0)