diff --git a/src/Symfony/Component/Translation/Bridge/Loco/LocoProvider.php b/src/Symfony/Component/Translation/Bridge/Loco/LocoProvider.php index ea4232c4ee75a..b5544070a5678 100644 --- a/src/Symfony/Component/Translation/Bridge/Loco/LocoProvider.php +++ b/src/Symfony/Component/Translation/Bridge/Loco/LocoProvider.php @@ -14,6 +14,7 @@ use Psr\Log\LoggerInterface; use Symfony\Component\Translation\Exception\ProviderException; use Symfony\Component\Translation\Loader\LoaderInterface; +use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Provider\ProviderInterface; use Symfony\Component\Translation\TranslatorBag; use Symfony\Component\Translation\TranslatorBagInterface; @@ -60,7 +61,7 @@ public function write(TranslatorBagInterface $translatorBag): void } foreach ($catalogue->all() as $domain => $messages) { - $createdIds = $this->createAssets(array_keys($messages)); + $createdIds = $this->createAssets(array_keys($messages), $domain); if ($createdIds) { $this->tagsAssets($createdIds, $domain); } @@ -117,7 +118,18 @@ public function read(array $domains, array $locales): TranslatorBag throw new ProviderException('Unable to read the Loco response: '.$responseContent, $response); } - $translatorBag->addCatalogue($this->loader->load($responseContent, $locale, $domain)); + $locoCatalogue = $this->loader->load($responseContent, $locale, $domain); + $catalogue = new MessageCatalogue($locale); + + foreach ($locoCatalogue->all($domain) as $key => $message) { + if (str_starts_with($key, $domain.'__')) { + $key = substr($key, \strlen($domain) + 2); + } + + $catalogue->set($key, $message, $domain); + } + + $translatorBag->addCatalogue($catalogue); } return $translatorBag; @@ -166,13 +178,14 @@ private function getAssetsIds(string $domain): array }, $response->toArray(false)); } - private function createAssets(array $keys): array + private function createAssets(array $keys, string $domain): array { $responses = $createdIds = []; foreach ($keys as $key) { $responses[$key] = $this->client->request('POST', 'assets', [ 'body' => [ + 'id' => $domain.'__'.$key, // must be globally unique, not only per domain 'text' => $key, 'type' => 'text', 'default' => 'untranslated', diff --git a/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php b/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php index 3d3dd8af985ca..09c779324310b 100644 --- a/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php +++ b/src/Symfony/Component/Translation/Bridge/Loco/Tests/LocoProviderTest.php @@ -63,6 +63,7 @@ public function testCompleteWriteProcess() $responses = [ 'createAsset1' => function (string $method, string $url, array $options = []) use ($expectedAuthHeader): ResponseInterface { $expectedBody = http_build_query([ + 'id' => 'messages__a', 'text' => 'a', 'type' => 'text', 'default' => 'untranslated', @@ -72,7 +73,7 @@ public function testCompleteWriteProcess() $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); $this->assertSame($expectedBody, $options['body']); - return new MockResponse('{"id": "1337"}', ['http_code' => 201]); + return new MockResponse('{"id": "messages__a"}', ['http_code' => 201]); }, 'getTags1' => function (string $method, string $url, array $options = []) use ($expectedAuthHeader): ResponseInterface { $this->assertSame('GET', $method); @@ -93,12 +94,13 @@ public function testCompleteWriteProcess() $this->assertSame('POST', $method); $this->assertSame('https://localise.biz/api/tags/messages.json', $url); $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); - $this->assertSame('1337', $options['body']); + $this->assertSame('messages__a', $options['body']); return new MockResponse(); }, 'createAsset2' => function (string $method, string $url, array $options = []) use ($expectedAuthHeader): ResponseInterface { $expectedBody = http_build_query([ + 'id' => 'validators__post.num_comments', 'text' => 'post.num_comments', 'type' => 'text', 'default' => 'untranslated', @@ -108,7 +110,7 @@ public function testCompleteWriteProcess() $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); $this->assertSame($expectedBody, $options['body']); - return new MockResponse('{"id": "1234"}', ['http_code' => 201]); + return new MockResponse('{"id": "validators__post.num_comments"}', ['http_code' => 201]); }, 'getTags2' => function (string $method, string $url, array $options = []) use ($expectedAuthHeader): ResponseInterface { $this->assertSame('GET', $method); @@ -129,7 +131,7 @@ public function testCompleteWriteProcess() $this->assertSame('POST', $method); $this->assertSame('https://localise.biz/api/tags/validators.json', $url); $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); - $this->assertSame('1234', $options['body']); + $this->assertSame('validators__post.num_comments', $options['body']); return new MockResponse(); }, @@ -146,11 +148,11 @@ public function testCompleteWriteProcess() $this->assertSame(['filter' => 'messages'], $options['query']); $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); - return new MockResponse('[{"id":"1337"}]'); + return new MockResponse('[{"id":"messages__a"}]'); }, 'translateAsset1' => function (string $method, string $url, array $options = []) use ($expectedAuthHeader): ResponseInterface { $this->assertSame('POST', $method); - $this->assertSame('https://localise.biz/api/translations/1337/en', $url); + $this->assertSame('https://localise.biz/api/translations/messages__a/en', $url); $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); $this->assertSame('trans_en_a', $options['body']); @@ -162,11 +164,11 @@ public function testCompleteWriteProcess() $this->assertSame(['filter' => 'validators'], $options['query']); $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); - return new MockResponse('[{"id":"1234"}]'); + return new MockResponse('[{"id":"validators__post.num_comments"}]'); }, 'translateAsset2' => function (string $method, string $url, array $options = []) use ($expectedAuthHeader): ResponseInterface { $this->assertSame('POST', $method); - $this->assertSame('https://localise.biz/api/translations/1234/en', $url); + $this->assertSame('https://localise.biz/api/translations/validators__post.num_comments/en', $url); $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); $this->assertSame('{count, plural, one {# comment} other {# comments}}', $options['body']); @@ -193,11 +195,11 @@ public function testCompleteWriteProcess() $this->assertSame(['filter' => 'messages'], $options['query']); $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); - return new MockResponse('[{"id":"1337"}]'); + return new MockResponse('[{"id":"messages__a"}]'); }, 'translateAsset3' => function (string $method, string $url, array $options = []) use ($expectedAuthHeader): ResponseInterface { $this->assertSame('POST', $method); - $this->assertSame('https://localise.biz/api/translations/1337/fr', $url); + $this->assertSame('https://localise.biz/api/translations/messages__a/fr', $url); $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); $this->assertSame('trans_fr_a', $options['body']); @@ -209,11 +211,11 @@ public function testCompleteWriteProcess() $this->assertSame(['filter' => 'validators'], $options['query']); $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); - return new MockResponse('[{"id":"1234"}]'); + return new MockResponse('[{"id":"validators__post.num_comments"}]'); }, 'translateAsset4' => function (string $method, string $url, array $options = []) use ($expectedAuthHeader): ResponseInterface { $this->assertSame('POST', $method); - $this->assertSame('https://localise.biz/api/translations/1234/fr', $url); + $this->assertSame('https://localise.biz/api/translations/validators__post.num_comments/fr', $url); $this->assertSame($expectedAuthHeader, $options['normalized_headers']['authorization'][0]); $this->assertSame('{count, plural, one {# commentaire} other {# commentaires}}', $options['body']); @@ -321,11 +323,11 @@ function (string $method, string $url, array $options = []): ResponseInterface { $this->assertSame('https://localise.biz/api/assets?filter=messages', $url); $this->assertSame(['filter' => 'messages'], $options['query']); - return new MockResponse('[{"id":"1337"}]'); + return new MockResponse('[{"id":"messages__a"}]'); }, function (string $method, string $url): MockResponse { $this->assertSame('DELETE', $method); - $this->assertSame('https://localise.biz/api/assets/1337.json', $url); + $this->assertSame('https://localise.biz/api/assets/messages__a.json', $url); return new MockResponse(); }, @@ -334,11 +336,11 @@ function (string $method, string $url, array $options = []): ResponseInterface { $this->assertSame('https://localise.biz/api/assets?filter=validators', $url); $this->assertSame(['filter' => 'validators'], $options['query']); - return new MockResponse('[{"id":"1234"}]'); + return new MockResponse('[{"id":"validators__post.num_comments"}]'); }, function (string $method, string $url): MockResponse { $this->assertSame('DELETE', $method); - $this->assertSame('https://localise.biz/api/assets/1234.json', $url); + $this->assertSame('https://localise.biz/api/assets/validators__post.num_comments.json', $url); return new MockResponse(); }, diff --git a/src/Symfony/Component/Translation/Bridge/Loco/composer.json b/src/Symfony/Component/Translation/Bridge/Loco/composer.json index 550a2f5b6de74..36d2eea52cb6d 100644 --- a/src/Symfony/Component/Translation/Bridge/Loco/composer.json +++ b/src/Symfony/Component/Translation/Bridge/Loco/composer.json @@ -19,6 +19,7 @@ "php": ">=7.2.5", "symfony/http-client": "^5.3", "symfony/config": "^5.3", + "symfony/polyfill-php80": "^1.23", "symfony/translation": "^5.3" }, "autoload": {