Repository: shopware/shopware
Pull request #7852: feat: add events to add custom translations in storefront
Author: login: Scarbous
Created: 2025-03-24T18:42:06Z | Merged: 2025-03-25T16:26:38Z

<!--
Thank you for contributing to Shopware! Please fill out this description template to help us to process your pull request.

Please make sure to fulfill our contribution guideline (https://developer.shopware.com/docs/resources/guidelines/code/contribution?category=shopware-platform-dev-en/contribution).

Do your changes need to be mentioned in the documentation?
Please create a second pull request at https://github.com/shopware/docs
-->

### 1. Why is this change necessary?
I want to overload translations.

### 2. What does this change do, exactly?
It implements two new Events wich can be used to manipulate the snippets before the returned.

### 3. Describe each step to reproduce the issue or behaviour.
There is no issue, only a missing function.

### 4. Please link to the relevant issues (if any).
-

### 5. Checklist

- [x] I have written tests and verified that they fail without my change
- [x] I have created a [changelog file](https://github.com/shopware/platform/blob/trunk/adr/2020-08-03-implement-new-changelog.md) with all necessary information about my changes
- [ ] I have written or adjusted the documentation according to my changes
- [x] This change has comments for package types, values, functions, and non-obvious lines of code
- [x] I have read the contribution requirements and fulfill them.



Diff:
diff --git a/changelog/_unreleased/2025-03-24-add-storefront-snippet-events.md b/changelog/_unreleased/2025-03-24-add-storefront-snippet-events.md
new file mode 100644
index 00000000000..15310647670
--- /dev/null
+++ b/changelog/_unreleased/2025-03-24-add-storefront-snippet-events.md
@@ -0,0 +1,8 @@
+---
+title: Add storefront snippet events
+author: Sascha Heilmeier
+author_email: sascha.heilmeier@netlogix.de
+author_github: @scarbous
+---
+# Core
+* Added events to `Shopware\Core\System\Snippet\SnippetService::getStorefrontSnippets` to manipulate the snippets before they are returned to the storefront
diff --git a/src/Core/Framework/DependencyInjection/services.xml b/src/Core/Framework/DependencyInjection/services.xml
index a3dd3c17efa..d62d4fd7a85 100644
--- a/src/Core/Framework/DependencyInjection/services.xml
+++ b/src/Core/Framework/DependencyInjection/services.xml
@@ -266,6 +266,7 @@ frame-ancestors 'none';
             <argument type="service" id="snippet_set.repository"/>
             <argument type="service" id="Shopware\Core\System\Snippet\Filter\SnippetFilterFactory"/>
             <argument type="service" id="service_container" />
+            <argument type="service" id="Shopware\Core\Framework\Extensions\ExtensionDispatcher"/>
             <argument type="service" id="Shopware\Storefront\Theme\DatabaseSalesChannelThemeLoader" on-invalid="null"/>
         </service>
 
diff --git a/src/Core/System/Snippet/Extension/StorefrontSnippetsExtension.php b/src/Core/System/Snippet/Extension/StorefrontSnippetsExtension.php
new file mode 100644
index 00000000000..2b2e1e5871f
--- /dev/null
+++ b/src/Core/System/Snippet/Extension/StorefrontSnippetsExtension.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Shopware\Core\System\Snippet\Extension;
+
+use Shopware\Core\Framework\Extensions\Extension;
+use Shopware\Core\Framework\Log\Package;
+use Symfony\Component\Translation\MessageCatalogueInterface;
+
+/**
+ * @extends Extension<array<string, string>>
+ */
+#[Package('discovery')]
+final class StorefrontSnippetsExtension extends Extension
+{
+    public const NAME = 'storefront.snippets';
+
+    /**
+     * @internal shopware owns the __constructor, but the properties are public API
+     *
+     * @param array<string, string> $snippets
+     * @param string[] $unusedThemes
+     */
+    public function __construct(
+        public array $snippets,
+        public readonly string $locale,
+        public readonly MessageCatalogueInterface $catalog,
+        public readonly string $snippetSetId,
+        public readonly ?string $fallbackLocale,
+        public readonly ?string $salesChannelId,
+        public readonly array $unusedThemes
+    ) {
+    }
+}
diff --git a/src/Core/System/Snippet/SnippetService.php b/src/Core/System/Snippet/SnippetService.php
index f05ef18ae75..7c813825ed1 100644
--- a/src/Core/System/Snippet/SnippetService.php
+++ b/src/Core/System/Snippet/SnippetService.php
@@ -9,9 +9,11 @@
 use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Bucket\TermsAggregation;
 use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Bucket\TermsResult;
 use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
+use Shopware\Core\Framework\Extensions\ExtensionDispatcher;
 use Shopware\Core\Framework\Log\Package;
 use Shopware\Core\Framework\Uuid\Uuid;
 use Shopware\Core\System\Snippet\Aggregate\SnippetSet\SnippetSetCollection;
+use Shopware\Core\System\Snippet\Extension\StorefrontSnippetsExtension;
 use Shopware\Core\System\Snippet\Files\AbstractSnippetFile;
 use Shopware\Core\System\Snippet\Files\SnippetFileCollection;
 use Shopware\Core\System\Snippet\Filter\SnippetFilterFactory;
@@ -47,6 +49,7 @@ public function __construct(
          * We need to get StorefrontPluginRegistry service from service_container lazily because it depends on kernel service.
          */
         private readonly ContainerInterface $container,
+        private readonly ExtensionDispatcher $extensionDispatcher,
         private readonly ?DatabaseSalesChannelThemeLoader $salesChannelThemeLoader = null
     ) {
     }
@@ -122,11 +125,32 @@ public function getStorefrontSnippets(MessageCatalogueInterface $catalog, string
             $locale === $fallbackLocale ? $fallbackSnippets : $this->getSnippetsByLocale($snippetCollection, $locale)
         );
 
-        // at least overwrite the snippets with the database customer overwrites
-        return array_replace_recursive(
-            $snippets,
-            $this->fetchSnippetsFromDatabase($snippetSetId, $unusedThemes)
-        );
+        return $this->extensionDispatcher
+            ->publish(
+                StorefrontSnippetsExtension::NAME,
+                new StorefrontSnippetsExtension(
+                    $snippets,
+                    $locale,
+                    $catalog,
+                    $snippetSetId,
+                    $fallbackLocale,
+                    $salesChannelId,
+                    $unusedThemes
+                ),
+                // overwrite the snippets with the database customer overwrites
+                fn (
+                    $snippets,
+                    $locale,
+                    $catalog,
+                    $snippetSetId,
+                    $fallbackLocale,
+                    $salesChannelId,
+                    $unusedThemes
+                ) => array_replace_recursive(
+                    $snippets,
+                    $this->fetchSnippetsFromDatabase($snippetSetId, $unusedThemes)
+                )
+            );
     }
 
     /**
diff --git a/tests/integration/Core/System/Snippet/SnippetServiceTest.php b/tests/integration/Core/System/Snippet/SnippetServiceTest.php
index b91bf21dfec..38a13301c10 100644
--- a/tests/integration/Core/System/Snippet/SnippetServiceTest.php
+++ b/tests/integration/Core/System/Snippet/SnippetServiceTest.php
@@ -1,4 +1,5 @@
-<?php declare(strict_types=1);
+<?php
+declare(strict_types=1);
 
 namespace Shopware\Tests\Integration\Core\System\Snippet;
 
@@ -7,10 +8,12 @@
 use PHPUnit\Framework\TestCase;
 use Shopware\Core\Defaults;
 use Shopware\Core\Framework\Context;
+use Shopware\Core\Framework\Extensions\ExtensionDispatcher;
 use Shopware\Core\Framework\Test\TestCaseBase\BasicTestDataBehaviour;
 use Shopware\Core\Framework\Test\TestCaseBase\DatabaseTransactionBehaviour;
 use Shopware\Core\Framework\Test\TestCaseBase\KernelTestBehaviour;
 use Shopware\Core\Framework\Uuid\Uuid;
+use Shopware\Core\System\Snippet\Extension\StorefrontSnippetsExtension;
 use Shopware\Core\System\Snippet\Files\AbstractSnippetFile;
 use Shopware\Core\System\Snippet\Files\SnippetFileCollection;
 use Shopware\Core\System\Snippet\Filter\SnippetFilterFactory;
@@ -37,6 +40,97 @@ protected function tearDown(): void
         MockSnippetFile::cleanup();
     }
 
+    public function testStorefrontSnippetsExtensionPre(): void
+    {
+        $locale = 'en-GB';
+
+        $service = $this->getSnippetService(
+            new MockSnippetFile(
+                $locale,
+                $locale,
+                (string) json_encode([
+                    'foo' => [
+                        'baz' => 'foo_baz_default0',
+                        'bas' => 'foo_bas_default1',
+                    ],
+                    'bar' => 'bar_default2',
+                ])
+            )
+        );
+
+        $snippetSetId = $this->getSnippetSetIdForLocale($locale);
+        static::assertNotNull($snippetSetId);
+
+        $snippetRepository = static::getContainer()->get('snippet.repository');
+        $snippetRepository->create([
+            [
+                'translationKey' => 'foo.bas',
+                'value' => 'foo_bas_override_db',
+                'author' => 'test',
+                'setId' => $snippetSetId,
+            ],
+        ], Context::createDefaultContext());
+
+        $listener = function (StorefrontSnippetsExtension $event): void {
+            $event->snippets['foo.baz'] = 'foo_baz_override0';
+            $event->snippets['foo.bas'] = 'foo_bas_override1';
+        };
+
+        $eventDispatcher = $this->getContainer()->get('event_dispatcher');
+
+        $eventDispatcher->addListener(ExtensionDispatcher::pre(StorefrontSnippetsExtension::NAME), $listener);
+
+        $snippets = $service->getStorefrontSnippets($this->getCatalog([], $locale), $snippetSetId);
+
+        static::assertEquals([
+            'foo.baz' => 'foo_baz_override0',
+            'foo.bas' => 'foo_bas_override_db',
+            'bar' => 'bar_default2',
+        ], $snippets);
+
+        $eventDispatcher->removeListener(ExtensionDispatcher::pre(StorefrontSnippetsExtension::NAME), $listener);
+
+        $snippetRepository->delete([
+            ['setId' => $snippetSetId],
+        ], Context::createDefaultContext());
+    }
+
+    public function testStorefrontSnippetsExtensionPost(): void
+    {
+        $locale = 'en-GB';
+        $service = $this->getSnippetService(
+            new MockSnippetFile(
+                $locale,
+                $locale,
+                (string) json_encode([
+                    'foo' => [
+                        'bar' => 'foo_baz_default0',
+                        'bas' => 'foo_bas_default1',
+                    ],
+                    'baz' => ['bar' => 'baz_bar_default2'],
+                ])
+            )
+        );
+        $snippetSetId = $this->getSnippetSetIdForLocale($locale);
+        static::assertNotNull($snippetSetId);
+        $listener = function (StorefrontSnippetsExtension $event): void {
+            $event->result['foo.bar'] = 'foo_bar_override';
+        };
+
+        $eventDispatcher = $this->getContainer()->get('event_dispatcher');
+        $eventDispatcher->addListener(ExtensionDispatcher::post(StorefrontSnippetsExtension::NAME), $listener);
+
+        $snippets = $service->getStorefrontSnippets($this->getCatalog([], $locale), $snippetSetId);
+
+        static::assertEquals([
+            'foo.bar' => 'foo_bar_override',
+            'foo.bas' => 'foo_bas_default1',
+            'baz.bar' => 'baz_bar_default2',
+        ], $snippets);
+
+        $eventDispatcher->removeListener(ExtensionDispatcher::post(StorefrontSnippetsExtension::NAME), $listener);
+    }
+
     public function testGetStorefrontSnippetsForNotExistingSnippetSet(): void
     {
         $snippetSetId = Uuid::randomHex();
@@ -982,7 +1076,7 @@ public function testTermFilterLargeSnippetMatches(): void
     }
 
     /**
-     * @param array<string> $messages
+     * @param array<array<string>> $messages
      */
     private function getCatalog(array $messages, string $local): MessageCatalogueInterface
     {
@@ -1025,7 +1119,10 @@ private function getSnippetService(AbstractSnippetFile ...$snippetFiles): Snippe
             static::getContainer()->get('snippet_set.repository'),
             static::getContainer()->get(SnippetFilterFactory::class),
             static::getContainer(),
-            static::getContainer()->has(DatabaseSalesChannelThemeLoader::class) ? static::getContainer()->get(DatabaseSalesChannelThemeLoader::class) : null
+            static::getContainer()->get(ExtensionDispatcher::class),
+            static::getContainer()->has(DatabaseSalesChannelThemeLoader::class) ? static::getContainer()->get(
+                DatabaseSalesChannelThemeLoader::class
+            ) : null
         );
     }
 
diff --git a/tests/unit/Core/System/Snippet/SnippetServiceTest.php b/tests/unit/Core/System/Snippet/SnippetServiceTest.php
index 7385b0e14a9..a55f581175e 100644
--- a/tests/unit/Core/System/Snippet/SnippetServiceTest.php
+++ b/tests/unit/Core/System/Snippet/SnippetServiceTest.php
@@ -8,6 +8,7 @@
 use PHPUnit\Framework\MockObject\MockObject;
 use PHPUnit\Framework\TestCase;
 use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
+use Shopware\Core\Framework\Extensions\ExtensionDispatcher;
 use Shopware\Core\Framework\Log\Package;
 use Shopware\Core\Framework\Uuid\Uuid;
 use Shopware\Core\System\Snippet\Files\SnippetFileCollection;
@@ -20,6 +21,7 @@
 use Shopware\Storefront\Theme\StorefrontPluginRegistry;
 use Shopware\Tests\Unit\Core\System\Snippet\Mock\MockSnippetFile;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\EventDispatcher\EventDispatcher;
 use Symfony\Component\Translation\MessageCatalogue;
 
 /**
@@ -109,6 +111,7 @@ public function testGetStorefrontSnippets(
             $this->createMock(EntityRepository::class),
             $this->createMock(SnippetFilterFactory::class),
             $container,
+            new ExtensionDispatcher(new EventDispatcher()),
             $cachedThemeLoader,
         );
 
@@ -134,7 +137,8 @@ public function testGetStorefrontSnippetsWithoutThemeRegistry(): void
             $this->createMock(EntityRepository::class),
             $this->createMock(EntityRepository::class),
             $this->createMock(SnippetFilterFactory::class),
-            $container
+            $container,
+            new ExtensionDispatcher(new EventDispatcher())
         );
 
         $snippets = $snippetService->getStorefrontSnippets($catalog, $snippetSetId, $locale);
@@ -157,6 +161,7 @@ public function testFindSnippetSetIdWithSalesChannelDomain(): void
             $this->createMock(EntityRepository::class),
             $this->createMock(SnippetFilterFactory::class),
             $this->createMock(ContainerInterface::class),
+            new ExtensionDispatcher(new EventDispatcher())
         );
 
         $snippetSetId = $snippetService->findSnippetSetId(Uuid::randomHex(), Uuid::randomHex(), 'en-GB');
@@ -180,6 +185,7 @@ public function testFindSnippetSetIdWithoutSalesChannelDomain(array $sets, strin
             $this->createMock(EntityRepository::class),
             $this->createMock(SnippetFilterFactory::class),
             $this->createMock(ContainerInterface::class),
+            new ExtensionDispatcher(new EventDispatcher())
         );
 
         $snippetSetId = $snippetService->findSnippetSetId(Uuid::randomHex(), Uuid::randomHex(), 'vi-VN');


Reviews:
user: login: MartinKrzykawski
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T09:00:51Z
user: login: marcelbrode
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T09:23:58Z
user: login: Scarbous
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T12:09:53Z
user: login: Scarbous
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T12:10:15Z
user: login: Scarbous
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T12:10:20Z
user: login: Scarbous
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T12:11:31Z
user: login: marcelbrode
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T13:05:39Z
user: login: MartinKrzykawski
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T14:56:11Z

Review comments:
diff_hunk: @@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+
+namespace Shopware\Core\System\Snippet\Event;
+
+use Symfony\Component\Translation\MessageCatalogueInterface;
+use Symfony\Contracts\EventDispatcher\Event;
+
+class AbstractStorefrontSnippetsEvent extends Event
path: src/Core/System/Snippet/Event/AbstractStorefrontSnippetsEvent.php
user: login: MartinKrzykawski
body: Please add the #[Package('discovery')] annotation to this class, as well as to the other created classes, to resolve the PHPStan issue.
created_at: 2025-03-25T08:36:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -122,11 +126,31 @@ public function getStorefrontSnippets(MessageCatalogueInterface $catalog, string
             $locale === $fallbackLocale ? $fallbackSnippets : $this->getSnippetsByLocale($snippetCollection, $locale)
         );
 
-        // at least overwrite the snippets with the database customer overwrites
-        return array_replace_recursive(
+        $event = $this->eventDispatcher->dispatch(new StorefrontSnippetsAfterCurrentLocaleEvent(
path: src/Core/System/Snippet/SnippetService.php
user: login: MartinKrzykawski
body: Instead of implementing multiple events that are triggered sequentially, consider using our extended event system for a more efficient approach: https://github.com/shopware/shopware/blob/trunk/adr/2024-06-18-extended-event-system.md
created_at: 2025-03-25T08:47:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -37,6 +40,98 @@ protected function tearDown(): void
         MockSnippetFile::cleanup();
     }
 
+    public function testStorefrontSnippetsAfterCurrentLocaleEvent(): void
+    {
+        $locale = 'en-GB';
+
+        $service = $this->getSnippetService(
+            new MockSnippetFile(
+                $locale,
+                $locale,
+                (string) json_encode([
+                    'foo' => [
+                        'baz' => 'foo_baz_default0',
+                        'bas' => 'foo_bas_default1',
+                    ],
+                    'bar' => 'bar_default2',
+                ])
+            )
+        );
+
+        $snippetSetId = $this->getSnippetSetIdForLocale($locale);
+        static::assertNotNull($snippetSetId);
+
+        $snippetRepository = static::getContainer()->get('snippet.repository');
+        $snippetRepository->create([
+            [
+                'translationKey' => 'foo.bas',
+                'value' => 'foo_bas_override_db',
+                'author' => 'test',
+                'setId' => $snippetSetId,
+            ],
+        ], Context::createDefaultContext());
+
+        $listener = function (StorefrontSnippetsAfterCurrentLocaleEvent $event): void {
+            $event->snippets['foo.baz'] = 'foo_baz_override0';
+            $event->snippets['foo.bas'] = 'foo_bas_override1';
+        };
+
+        /** @var EventDispatcherInterface $eventDispatcher */
path: tests/integration/Core/System/Snippet/SnippetServiceTest.php
user: login: MartinKrzykawski
body: You do not need to use inline annotations inside a PHPUnit test => https://github.com/shopware/shopware/blob/trunk/coding-guidelines/core/writing-code-for-static-analysis.md#12-ensuring-types-in-unit-tests

You can just assert if the variable is instance of EventDispatcherInterface. Please change it also for your other usages.
created_at: 2025-03-25T08:52:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -122,11 +126,31 @@ public function getStorefrontSnippets(MessageCatalogueInterface $catalog, string
             $locale === $fallbackLocale ? $fallbackSnippets : $this->getSnippetsByLocale($snippetCollection, $locale)
         );
 
-        // at least overwrite the snippets with the database customer overwrites
-        return array_replace_recursive(
+        $event = $this->eventDispatcher->dispatch(new StorefrontSnippetsAfterCurrentLocaleEvent(
             $snippets,
+            $locale,
+            $catalog,
+            $snippetSetId,
+            $fallbackLocale,
+            $salesChannelId
+        ));
+
+        // at least overwrite the snippets with the database customer overwrites
+        $snippets = array_replace_recursive(
+            $event->snippets,
             $this->fetchSnippetsFromDatabase($snippetSetId, $unusedThemes)
         );
+
+        $event = $this->eventDispatcher->dispatch(new StorefrontSnippetsAfterDatabaseOverwritesEvent(
path: src/Core/System/Snippet/SnippetService.php
user: login: marcelbrode
body: ```suggestion
        $event = $this->eventDispatcher->dispatch(new StorefrontSnippetsAfterDatabaseOverrideEvent(
```
It's just a small one, but this should be "Override" (non destructive) instead of "Overwrite" (destructive)
created_at: 2025-03-25T09:23:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,19 @@
+<?php declare(strict_types=1);
+
+namespace Shopware\Core\System\Snippet\Event;
+
+use Symfony\Component\Translation\MessageCatalogueInterface;
+use Symfony\Contracts\EventDispatcher\Event;
+
+class AbstractStorefrontSnippetsEvent extends Event
path: src/Core/System/Snippet/Event/AbstractStorefrontSnippetsEvent.php
user: login: Scarbous
body: done
created_at: 2025-03-25T12:09:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -122,11 +126,31 @@ public function getStorefrontSnippets(MessageCatalogueInterface $catalog, string
             $locale === $fallbackLocale ? $fallbackSnippets : $this->getSnippetsByLocale($snippetCollection, $locale)
         );
 
-        // at least overwrite the snippets with the database customer overwrites
-        return array_replace_recursive(
+        $event = $this->eventDispatcher->dispatch(new StorefrontSnippetsAfterCurrentLocaleEvent(
path: src/Core/System/Snippet/SnippetService.php
user: login: Scarbous
body: done
created_at: 2025-03-25T12:10:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -37,6 +40,98 @@ protected function tearDown(): void
         MockSnippetFile::cleanup();
     }
 
+    public function testStorefrontSnippetsAfterCurrentLocaleEvent(): void
+    {
+        $locale = 'en-GB';
+
+        $service = $this->getSnippetService(
+            new MockSnippetFile(
+                $locale,
+                $locale,
+                (string) json_encode([
+                    'foo' => [
+                        'baz' => 'foo_baz_default0',
+                        'bas' => 'foo_bas_default1',
+                    ],
+                    'bar' => 'bar_default2',
+                ])
+            )
+        );
+
+        $snippetSetId = $this->getSnippetSetIdForLocale($locale);
+        static::assertNotNull($snippetSetId);
+
+        $snippetRepository = static::getContainer()->get('snippet.repository');
+        $snippetRepository->create([
+            [
+                'translationKey' => 'foo.bas',
+                'value' => 'foo_bas_override_db',
+                'author' => 'test',
+                'setId' => $snippetSetId,
+            ],
+        ], Context::createDefaultContext());
+
+        $listener = function (StorefrontSnippetsAfterCurrentLocaleEvent $event): void {
+            $event->snippets['foo.baz'] = 'foo_baz_override0';
+            $event->snippets['foo.bas'] = 'foo_bas_override1';
+        };
+
+        /** @var EventDispatcherInterface $eventDispatcher */
path: tests/integration/Core/System/Snippet/SnippetServiceTest.php
user: login: Scarbous
body: done
created_at: 2025-03-25T12:10:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -122,11 +126,31 @@ public function getStorefrontSnippets(MessageCatalogueInterface $catalog, string
             $locale === $fallbackLocale ? $fallbackSnippets : $this->getSnippetsByLocale($snippetCollection, $locale)
         );
 
-        // at least overwrite the snippets with the database customer overwrites
-        return array_replace_recursive(
+        $event = $this->eventDispatcher->dispatch(new StorefrontSnippetsAfterCurrentLocaleEvent(
             $snippets,
+            $locale,
+            $catalog,
+            $snippetSetId,
+            $fallbackLocale,
+            $salesChannelId
+        ));
+
+        // at least overwrite the snippets with the database customer overwrites
+        $snippets = array_replace_recursive(
+            $event->snippets,
             $this->fetchSnippetsFromDatabase($snippetSetId, $unusedThemes)
         );
+
+        $event = $this->eventDispatcher->dispatch(new StorefrontSnippetsAfterDatabaseOverwritesEvent(
path: src/Core/System/Snippet/SnippetService.php
user: login: Scarbous
body: I switched from Event to Extension.
created_at: 2025-03-25T12:11:31Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-03-24T18:44:41Z
body: ## [Codecov](https://app.codecov.io/gh/shopware/shopware/pull/7852?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware) Report
Attention: Patch coverage is `96.15385%` with `1 line` in your changes missing coverage. Please review.
> Project coverage is 53.05%. Comparing base [(`4d4658c`)](https://app.codecov.io/gh/shopware/shopware/commit/4d4658c913fbc2ea5adf6987d80d2496def9a9ac?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware) to head [(`bb8dfb5`)](https://app.codecov.io/gh/shopware/shopware/commit/bb8dfb5e306d4536c1d6787d66b7c3e448ce0092?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware).
> Report is 15 commits behind head on trunk.

| [Files with missing lines](https://app.codecov.io/gh/shopware/shopware/pull/7852?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware) | Patch % | Lines |
|---|---|---|
| [.../Snippet/Extension/StorefrontSnippetsExtension.php](https://app.codecov.io/gh/shopware/shopware/pull/7852?src=pr&el=tree&filepath=src%2FCore%2FSystem%2FSnippet%2FExtension%2FStorefrontSnippetsExtension.php&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware#diff-c3JjL0NvcmUvU3lzdGVtL1NuaXBwZXQvRXh0ZW5zaW9uL1N0b3JlZnJvbnRTbmlwcGV0c0V4dGVuc2lvbi5waHA=) | 0.00% | [1 Missing :warning: ](https://app.codecov.io/gh/shopware/shopware/pull/7852?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##            trunk    #7852      +/-   ##
==========================================
+ Coverage   53.03%   53.05%   +0.01%     
==========================================
  Files        4698     4699       +1     
  Lines      158393   158452      +59     
  Branches     8703     8705       +2     
==========================================
+ Hits        84009    84070      +61     
+ Misses      71872    71868       -4     
- Partials     2512     2514       +2     
```

| [Flag](https://app.codecov.io/gh/shopware/shopware/pull/7852/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware) | Coverage Δ | |
|---|---|---|
| [jest-admin](https://app.codecov.io/gh/shopware/shopware/pull/7852/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware) | `60.45% <ø> (+<0.01%)` | :arrow_up: |
| [jest-storefront](https://app.codecov.io/gh/shopware/shopware/pull/7852/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware) | `69.85% <ø> (ø)` | |
| [phpunit-migration](https://app.codecov.io/gh/shopware/shopware/pull/7852/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware) | `41.72% <ø> (ø)` | |
| [phpunit-unit](https://app.codecov.io/gh/shopware/shopware/pull/7852/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware) | `45.42% <96.15%> (+0.03%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/shopware/shopware/pull/7852?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=shopware).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-03-25T12:09:44Z
body: <!--- Danger-PHP-Marker --><table>
  <thead>
    <tr>
      <th></th>
      <th>Warnings</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>:warning:</td>
      <td>Please be kind and add unit tests for your new code in these files: <br/><br/>src/Core/System/Snippet/Extension/StorefrontSnippetsExtension.php<br/><br/>If you are sure everything is fine with your changes, you can resolve this warning. <br /> You can run `composer make:coverage` to generate dummy unit tests for files that are not covered</td>
    </tr>
  </tbody>
</table>
author_association: NONE
user: login: MartinKrzykawski
created_at: 2025-03-25T14:58:26Z
body: Thanks for your contribution @Scarbous 🎉
author_association: CONTRIBUTOR