Repository: symfony/ux
Pull request #2279 (2024-10-17 06:45:29)

[Autocomplete] Translate "Add ..." text with remote data setup
| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Issues        | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License       | MIT

In https://github.com/symfony/ux/pull/2108 the "Add..." translation has been added. But this only worked for non remote data setups. This PR makes it work for remote data setup too.

Also add translation for Dutch. 


jonasdekeukelaere: Changelog updated
smnandre: Do you know why the tests are failing ?
jonasdekeukelaere: No idea, looks like it is the same like in https://github.com/symfony/ux/pull/2108#issuecomment-2325673608

Patch:
diff --git a/src/Autocomplete/CHANGELOG.md b/src/Autocomplete/CHANGELOG.md
index b869da8e..1237b13d 100644
--- a/src/Autocomplete/CHANGELOG.md
+++ b/src/Autocomplete/CHANGELOG.md
@@ -1,5 +1,10 @@
 # CHANGELOG
 
+## 2.21.0
+
+-   Translate the `option_create` option from TomSelect with remote data setup #2279
+-   Add one missing Dutch translation #2279
+
 ## 2.20.0
 
 -   Translate the `option_create` option from TomSelect #2108
diff --git a/src/Autocomplete/assets/dist/controller.js b/src/Autocomplete/assets/dist/controller.js
index c6e9660b..7d9d148d 100644
--- a/src/Autocomplete/assets/dist/controller.js
+++ b/src/Autocomplete/assets/dist/controller.js
@@ -318,7 +318,7 @@ _default_1_instances = new WeakSet(), _default_1_getCommonConfig = function _def
                 return `<div class="no-results">${this.noResultsFoundTextValue}</div>`;
             },
             option_create: (data, escapeData) => {
-                return `<div class="create">${this.createOptionTextValue} <strong>${escapeData(data.input)}</strong>&hellip;</div>`;
+                return `<div class="create">${this.createOptionTextValue.replace('%placeholder%', `<strong>${escapeData(data.input)}</strong>`)}</div>`;
             },
         },
         preload: this.preload,
diff --git a/src/Autocomplete/assets/src/controller.ts b/src/Autocomplete/assets/src/controller.ts
index af7f096a..62fe734e 100644
--- a/src/Autocomplete/assets/src/controller.ts
+++ b/src/Autocomplete/assets/src/controller.ts
@@ -253,7 +253,7 @@ export default class extends Controller {
                     return `<div class="no-results">${this.noResultsFoundTextValue}</div>`;
                 },
                 option_create: (data: TomOption, escapeData: typeof escape_html): string => {
-                    return `<div class="create">${this.createOptionTextValue} <strong>${escapeData(data.input)}</strong>&hellip;</div>`;
+                    return `<div class="create">${this.createOptionTextValue.replace('%placeholder%', `<strong>${escapeData(data.input)}</strong>`)}</div>`;
                 },
             },
             preload: this.preload,
diff --git a/src/Autocomplete/translations/AutocompleteBundle.de.php b/src/Autocomplete/translations/AutocompleteBundle.de.php
index 107fbae1..fb5729ba 100644
--- a/src/Autocomplete/translations/AutocompleteBundle.de.php
+++ b/src/Autocomplete/translations/AutocompleteBundle.de.php
@@ -13,5 +13,5 @@ return [
     'Loading more results...' => 'Lade weitere Ergebnisse...',
     'No results found' => 'Keine Übereinstimmungen gefunden',
     'No more results' => 'Keine weiteren Ergebnisse',
-    'Add %placeholder%...' => '%placeholder% hinzufügen...',
+    // 'Add %placeholder%...' => 'Add %placeholder%...',
 ];
diff --git a/src/Autocomplete/translations/AutocompleteBundle.nl.php b/src/Autocomplete/translations/AutocompleteBundle.nl.php
index d9a2a90c..106be824 100644
--- a/src/Autocomplete/translations/AutocompleteBundle.nl.php
+++ b/src/Autocomplete/translations/AutocompleteBundle.nl.php
@@ -13,5 +13,5 @@ return [
     'Loading more results...' => 'Meer resultaten aan het laden...',
     'No results found' => 'Geen resultaten gevonden…',
     'No more results' => 'Niet meer resultaten gevonden…',
-    // 'Add %placeholder%...' => 'Add %placeholder%...',
+    'Add %placeholder%...' => 'Voeg %placeholder% toe...',
 ];
diff --git a/src/Icons/src/Command/LockIconsCommand.php b/src/Icons/src/Command/LockIconsCommand.php
index e452a7d7..c58a258f 100644
--- a/src/Icons/src/Command/LockIconsCommand.php
+++ b/src/Icons/src/Command/LockIconsCommand.php
@@ -72,21 +72,10 @@ final class LockIconsCommand extends Command
 
             [$prefix, $name] = $parts;
 
-            if (!$this->iconify->hasIconSet($prefix)) {
-                // not an icon set? example: "og:twitter"
-                if ($io->isVeryVerbose()) {
-                    $io->writeln(\sprintf(' <fg=bright-yellow;options=bold>✗</> IconSet Not Found: <fg=bright-white;bg=black>%s:%s</>.', $prefix, $name));
-                }
-                continue;
-            }
-
             try {
                 $svg = $this->iconify->fetchSvg($prefix, $name);
             } catch (IconNotFoundException) {
                 // icon not found on iconify
-                if ($io->isVerbose()) {
-                    $io->writeln(\sprintf(' <fg=bright-red;options=bold>✗</> Icon Not Found: <fg=bright-white;bg=black>%s:%s</>.', $prefix, $name));
-                }
                 continue;
             }
 
@@ -95,7 +84,7 @@ final class LockIconsCommand extends Command
             $license = $this->iconify->metadataFor($prefix)['license'];
             ++$count;
 
-            $io->writeln(\sprintf(
+            $io->text(\sprintf(
                 " <fg=bright-green;options=bold>✓</> Imported <fg=bright-white;bg=black>%s:</><fg=bright-magenta;bg=black;options>%s</> (License: <href=%s>%s</>). Render with: <comment>{{ ux_icon('%s') }}</comment>",
                 $prefix,
                 $name,
diff --git a/src/Icons/src/Iconify.php b/src/Icons/src/Iconify.php
index c948e24d..d9d3fa15 100644
--- a/src/Icons/src/Iconify.php
+++ b/src/Icons/src/Iconify.php
@@ -55,10 +55,6 @@ final class Iconify
 
         $response = $this->http->request('GET', \sprintf('/%s.json?icons=%s', $prefix, $name));
 
-        if (200 !== $response->getStatusCode()) {
-            throw new IconNotFoundException(\sprintf('The icon "%s:%s" does not exist on iconify.design.', $prefix, $name));
-        }
-
         try {
             $data = $response->toArray();
         } catch (JsonException) {
@@ -91,22 +87,16 @@ final class Iconify
             throw new IconNotFoundException(\sprintf('The icon "%s:%s" does not exist on iconify.design.', $prefix, $name));
         }
 
-        $response = $this->http->request('GET', \sprintf('/%s/%s.svg', $prefix, $name));
+        $content = $this->http
+            ->request('GET', \sprintf('/%s/%s.svg', $prefix, $name))
+            ->getContent()
+        ;
 
-        if (200 !== $response->getStatusCode()) {
+        if (!str_starts_with($content, '<svg')) {
             throw new IconNotFoundException(\sprintf('The icon "%s:%s" does not exist on iconify.design.', $prefix, $name));
         }
 
-        if (!str_starts_with($svg = $response->getContent(), '<svg')) {
-            throw new IconNotFoundException(\sprintf('The icon "%s:%s" does not exist on iconify.design.', $prefix, $name));
-        }
-
-        return $svg;
-    }
-
-    public function hasIconSet(string $prefix): bool
-    {
-        return isset($this->sets()[$prefix]);
+        return $content;
     }
 
     public function getIconSets(): array


Test patch:
diff --git a/src/Icons/tests/Unit/IconifyTest.php b/src/Icons/tests/Unit/IconifyTest.php
index a3aa50bf..f61abf3a 100644
--- a/src/Icons/tests/Unit/IconifyTest.php
+++ b/src/Icons/tests/Unit/IconifyTest.php
@@ -144,25 +144,6 @@ class IconifyTest extends TestCase
         $iconify->fetchIcon('bi', 'heart');
     }
 
-    public function testFetchIconThrowsWhenStatusCodeNot200(): void
-    {
-        $iconify = new Iconify(
-            cache: new NullAdapter(),
-            endpoint: 'https://example.com',
-            http: new MockHttpClient([
-                new JsonMockResponse([
-                    'bi' => [],
-                ]),
-                new JsonMockResponse([], ['http_code' => 404]),
-            ]),
-        );
-
-        $this->expectException(IconNotFoundException::class);
-        $this->expectExceptionMessage('The icon "bi:heart" does not exist on iconify.design.');
-
-        $iconify->fetchIcon('bi', 'heart');
-    }
-
     public function testGetMetadata(): void
     {
         $responseFile = __DIR__.'/../Fixtures/Iconify/collections.json';
@@ -189,21 +170,6 @@ class IconifyTest extends TestCase
         $this->stringContains('-.224l.235-.468ZM6.013 2.06c-.649-.1', $svg);
     }
 
-    public function testFetchSvgThrowIconNotFoundExceptionWhenStatusCodeNot200(): void
-    {
-        $client = new MockHttpClient([
-            new MockResponse(file_get_contents(__DIR__.'/../Fixtures/Iconify/collections.json'), [
-                'response_headers' => ['content-type' => 'application/json'],
-            ]),
-            new MockResponse('', ['http_code' => 404]),
-        ]);
-        $iconify = new Iconify(new NullAdapter(), 'https://localhost', $client);
-
-        $this->expectException(IconNotFoundException::class);
-
-        $iconify->fetchSvg('fa6-regular', 'bar');
-    }
-
     private function createHttpClient(mixed $data, int $code = 200): MockHttpClient
     {
         $mockResponse = new JsonMockResponse($data, ['http_code' => $code]);