8000 bug #58983 [Translation] [Bridge][Lokalise] Fix empty keys array in P… · symfony/symfony@294a39f · GitHub
[go: up one dir, main page]

Skip to content

Commit 294a39f

Browse files
bug #58983 [Translation] [Bridge][Lokalise] Fix empty keys array in PUT, DELETE requests causing Lokalise API error (DominicLuidold)
This PR was squashed before being merged into the 5.4 branch. Discussion ---------- [Translation] [Bridge][Lokalise] Fix empty keys array in PUT, DELETE requests causing Lokalise API error | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | / | License | MIT This PR fixes two cases where an empty `keys` array is passed to a `PUT`/`DELETE` request, resulting in a Lokalise API error. The empty arrays are the result of a `Symfony\Component\Translation\TranslatorBag` containing one or more `Symfony\Component\Translation\MessageCatalogue` _without any_ messages getting passed into the `Symfony\Component\Translation\Bridge\Lokalise\LokaliseProvider` (which is expected behaviour, see [here](https://github.com/symfony/symfony/blob/7.3/src/Symfony/Component/Translation/Command/TranslationPushCommand.php#L153) and below). This is the case if either * `bin/console translation:push lokalise` * `bin/console translation:push lokalise --delete-missing` is called when both the local translations as well as the translations on Lokalise match 1:1 for a given translation domain. This will fix the following erros that might be observed while running the mentioned commands: <details> <summary>Before/after for <code>translation:push lokalise</code></summary> **Before:** ```console $ bin/console translation:push lokalise --domains=validators ERROR [app] Unable to get keys ids from Lokalise: "{"error":{"message":"`filter_filenames` parameter has invalid values","code":400}}". [OK] All local translations has been sent to "lokalise" (for "de, en, fr, it" locale(s), and "validators" domain(s)). ``` **After:** ```console $ bin/console translation:push lokalise --domains=validators [OK] All local translations has been sent to "lokalise" (for "de, en, fr, it" locale(s), and "validators" domain(s)). ``` </details> <details> <summary>Before/after for <code>translation:push lokalise --delete-missing</code></summary> **Before:** ```console $ bin/console translation:push lokalise --domains=validators --delete-missing In LokaliseProvider.php line 135: Unable to delete keys from Lokalise: "{"error":{"message":"`keys` parameter is not valid","code":400}}". translation:push [--force] [--delete-missing] [--domains [DOMAINS]] [--locales [LOCALES]] [--] [<provider>] ``` **After:** ```console $ bin/console translation:push lokalise --domains=validators --delete-missing [OK] Missing translations on "lokalise" has been deleted (for "de, en, fr, it" locale(s), and "validators" domain(s)). [OK] All local translations has been sent to "lokalise" (for "de, en, fr, it" locale(s), and "validators" domain(s)). ``` </details> Commits ------- 2e51808 [Translation] [Bridge][Lokalise] Fix empty keys array in PUT, DELETE requests causing Lokalise API error
2 parents 520e31b + 2e51808 commit 294a39f

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

src/Symfony/Component/Translation/Bridge/Lokalise/LokaliseProvider.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ public function delete(TranslatorBagInterface $translatorBag): void
129129
$keysIds += $this->getKeysIds($keysToDelete, $domain);
130130
}
131131

132+
if (!$keysIds) {
133+
return;
134+
}
135+
132136
$response = $this->client->request('DELETE', 'keys', [
133137
'json' => ['keys' => array_values($keysIds)],
134138
]);
@@ -261,6 +265,10 @@ private function updateTranslations(array $keysByDomain, TranslatorBagInterface
261265
}
262266
}
263267

268+
if (!$keysToUpdate) {
269+
return;
270+
}
271+
264272
$response = $this->client->request('PUT', 'keys', [
265273
'json' => ['keys' => $keysToUpdate],
266274
]);

src/Symfony/Component/Translation/Bridge/Lokalise/Tests/LokaliseProviderTest.php

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,56 @@ public function testCompleteWriteProcess()
249249
$this->assertTrue($updateProcessed, 'Translations update was not called.');
250250
}
251251

252+
public function testUpdateProcessWhenLocalTranslationsMatchLokaliseTranslations()
253+
{
254+
$getLanguagesResponse = function (string $method, string $url): ResponseInterface {
255+
$this->assertSame('GET', $method);
256+
$this->assertSame('https://api.lokalise.com/api2/projects/PROJECT_ID/languages', $url);
257+
258+
return new MockResponse(json_encode([
259+
'languages' => [
260+
['lang_iso' => 'en'],
261+
['lang_iso' => 'fr'],
262+
],
263+
]));
264+
};
265+
266+
$failOnPutRequest = function (string $method, string $url, array $options = []): void {
267+
$this->assertSame('PUT', $method);
268+
$this->assertSame('https://api.lokalise.com/api2/projects/PROJECT_ID/keys', $url);
269+
$this->assertSame(json_encode(['keys' => []]), $options['body']);
270+
271+
$this->fail('PUT request is invalid: an empty `keys` array was provided, resulting in a Lokalise API error');
272+
};
273+
274+
$mockHttpClient = (new MockHttpClient([
275+
$getLanguagesResponse,
276+
$failOnPutRequest,
277+
]))->withOptions([
278+
'base_uri' => 'https://api.lokalise.com/api2/projects/PROJECT_ID/',
279+
'headers' => ['X-Api-Token' => 'API_KEY'],
280+
]);
281+
282+
$provider = self::createProvider(
283+
$mockHttpClient,
284+
$this->getLoader(),
285+
$this->getLogger(),
286+
$this->getDefaultLocale(),
287+
'api.lokalise.com'
288+
);
289+
290+
// TranslatorBag with catalogues that do not store any message to mimic the behaviour of
291+
// Symfony\Component\Translation\Command\TranslationPushCommand when local translations and Lokalise
292+
// translations match without any changes in both translation sets
293+
$translatorBag = new TranslatorBag();
294+
$translatorBag->addCatalogue(new MessageCatalogue('en', []));
295+
$translatorBag->addCatalogue(new MessageCatalogue('fr', []));
296+
297+
$provider->write($translatorBag);
298+
299+
$this->assertSame(1, $mockHttpClient->getRequestsCount());
300+
}
301+
252302
public function testWriteGetLanguageServerError()
253303
{
254304
$getLanguagesResponse = function (string $method, string $url, array $options = []): ResponseInterface {
@@ -721,6 +771,38 @@ public function testDeleteProcess()
721771
$provider->delete($translatorBag);
722772
}
723773

774+
public function testDeleteProcessWhenLocalTranslationsMatchLokaliseTranslations()
775+
{
776+
$failOnDeleteRequest = function (string $method, string $url, array $options = []): void {
777+
$this->assertSame('DELETE', $method);
778+
$this->assertSame('https://api.lokalise.com/api2/projects/PROJECT_ID/keys', $url);
779+
$this->assertSame(json_encode(['keys' => []]), $options['body']);
780+
781+
$this->fail('DELETE request is invalid: an empty `keys` array was provided, resulting in a Lokalise API error');
782+
};
783+
784+
// TranslatorBag with catalogues that do not store any message to mimic the behaviour of
785+
// Symfony\Component\Translation\Command\TranslationPushCommand when local translations and Lokalise
786+
// translations match without any changes in both translation sets
787+
$translatorBag = new TranslatorBag();
788+
$translatorBag->addCatalogue(new MessageCatalogue('en', []));
789+
$translatorBag->addCatalogue(new MessageCatalogue('fr', []));
790+
791+
$mockHttpClient = new MockHttpClient([$failOnDeleteRequest], 'https://api.lokalise.com/api2/projects/PROJECT_ID/');
792+
793+
$provider = self::createProvider(
794+
$mockHttpClient,
795+
$this->getLoader(),
796+
$this->getLogger(),
797+
$this->getDefaultLocale(),
798+
'api.lokalise.com'
799+
);
800+
801+
$provider->delete($translatorBag);
802+
803+
$this->assertSame(0, $mockHttpClient->getRequestsCount());
804+
}
805+
724806
public static function getResponsesForOneLocaleAndOneDomain(): \Generator
725807
{
726808
$arrayLoader = new ArrayLoader();

0 commit comments

Comments
 (0)
0