From 94456d3e218cd4c5d431c3d61beeace7e9a978f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20B=C3=BCrk?= <stefan@buerk.tech>
Date: Sat, 10 Jun 2023 16:57:08 +0200
Subject: [PATCH] [BUGFIX] Resolve page with trailing slash requested without
 one
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

With #89091 pages with slugs containing trailing slash have
been enabled to be resolved when requested with trailing
slash in the request uri and have been a logical follow-up
of #86055.

In between an issue with language fallback chain have been
found, which allowed that a valid translated page could be
resolved with the default language slug even and reported
as #88715 and #96010. These issues have been solved with
https://review.typo3.org/c/Packages/TYPO3.CMS/+/75101 which
partly broke the original implemented behaviour for pages
with trailing slash slugs requested without a trailing slash.

This change now ensures pages are resolved containing a trailing
slash in their "slug" like "/my-page/subpage/" if requested without
the trailing slash like "https://domain.tld/my-page/subpage".

Additionally, tests are added to cover this case along with
other possible cases. This should detect future regressions.

The docblock return annotation for `PageRouter::matchRequest()` is
changed to the correct returned value, removing ignore pattern for
the phpstan baseline instead of increasing the counter.

Note: This change ensures that a page can be resolved in any
      constellation with trailing slash in record slug/not
      in record slug and requested with trailing slash/not
      requested slug. In both cases, already working and the
      now fixed variant are serving both potential duplicate
      content - if no correct cannonical url is provided.

Tackling the duplicate issue should be done in a dedicated
change for both cases.

Used command(s):

> Build/Scripts/runTests.sh -s phpstanGenerateBaseline

Resolves: #100990
Related: #96010
Related: #88715
Related: #89091
Related: #86055
Releases: main, 12.4, 11.5
Change-Id: I9f26c4500e2f812e8727b4b565570fcc579bf3e6
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/79679
Tested-by: core-ci <typo3@b13.com>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
---
 Build/phpstan/phpstan-baseline.neon           |    5 -
 .../core/Classes/Routing/PageRouter.php       |   23 +-
 .../SiteHandling/SlugSiteRequestTest.php      | 1423 ++++++++++++++++-
 3 files changed, 1356 insertions(+), 95 deletions(-)

diff --git a/Build/phpstan/phpstan-baseline.neon b/Build/phpstan/phpstan-baseline.neon
index 60af1e2f539a..f4fb5e158185 100644
--- a/Build/phpstan/phpstan-baseline.neon
+++ b/Build/phpstan/phpstan-baseline.neon
@@ -1060,11 +1060,6 @@ parameters:
 			count: 1
 			path: ../../typo3/sysext/core/Classes/Routing/PageRouter.php
 
-		-
-			message: "#^Method TYPO3\\\\CMS\\\\Core\\\\Routing\\\\PageRouter\\:\\:matchRequest\\(\\) should return TYPO3\\\\CMS\\\\Core\\\\Routing\\\\SiteRouteResult but returns TYPO3\\\\CMS\\\\Core\\\\Routing\\\\PageArguments\\.$#"
-			count: 3
-			path: ../../typo3/sysext/core/Classes/Routing/PageRouter.php
-
 		-
 			message: "#^Parameter \\#1 \\$callback of function array_map expects \\(callable\\(TYPO3\\\\CMS\\\\Core\\\\Routing\\\\Aspect\\\\AspectInterface\\)\\: mixed\\)\\|null, 'count' given\\.$#"
 			count: 1
diff --git a/typo3/sysext/core/Classes/Routing/PageRouter.php b/typo3/sysext/core/Classes/Routing/PageRouter.php
index 759c4eb40953..6e05a40d1693 100644
--- a/typo3/sysext/core/Classes/Routing/PageRouter.php
+++ b/typo3/sysext/core/Classes/Routing/PageRouter.php
@@ -92,7 +92,7 @@ class PageRouter implements RouterInterface
      * Finds a RouteResult based on the given request.
      *
      * @param RouteResultInterface|SiteRouteResult|null $previousResult
-     * @return SiteRouteResult
+     * @return RouteResultInterface|PageArguments
      * @throws RouteNotFoundException
      */
     public function matchRequest(ServerRequestInterface $request, RouteResultInterface $previousResult = null): RouteResultInterface
@@ -182,9 +182,9 @@ class PageRouter implements RouterInterface
                 return $this->buildPageArguments($matchedRoute, $result, $request->getQueryParams());
             }
         } catch (ResourceNotFoundException $e) {
-            // Second try, look for /my-page even though the request was called via /my-page/ and the slash
-            // was not part of the slug, but let's then check again
-            if (substr($prefixedUrlPath, -1) === '/') {
+            if (str_ends_with($prefixedUrlPath, '/')) {
+                // Second try, look for /my-page even though the request was called via /my-page/ and the slash
+                // was not part of the slug, but let's then check again
                 try {
                     $result = $matcher->match(rtrim($prefixedUrlPath, '/'));
                     /** @var Route $matchedRoute */
@@ -197,6 +197,21 @@ class PageRouter implements RouterInterface
                 } catch (ResourceNotFoundException $e) {
                     // Do nothing
                 }
+            } else {
+                // Second try, look for /my-page/ even though the request was called via /my-page and the slash
+                // was part of the slug, but let's then check again
+                try {
+                    $result = $matcher->match($prefixedUrlPath . '/');
+                    /** @var Route $matchedRoute */
+                    $matchedRoute = $fullCollection->get($result['_route']);
+                    // Only use route if page language variant matches current language, otherwise
+                    // handle it as route not found.
+                    if ($this->isRouteReallyValidForLanguage($matchedRoute, $language)) {
+                        return $this->buildPageArguments($matchedRoute, $result, $request->getQueryParams());
+                    }
+                } catch (ResourceNotFoundException $e) {
+                    // Do nothing
+                }
             }
         }
         throw new RouteNotFoundException('No route found for path "' . $urlPath . '"', 1538389998);
diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php
index db1c003e6de0..3770327c0b11 100644
--- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php
+++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php
@@ -546,7 +546,7 @@ final class SlugSiteRequestTest extends AbstractTestCase
     /**
      * @test
      */
-    public function pageIsRenderedWithTrailingSlash(): void
+    public function pageWithTrailingSlashSlugIsRenderedIfRequestedWithSlash(): void
     {
         $uri = 'https://website.us/features/frontend-editing/';
 
@@ -566,6 +566,75 @@ final class SlugSiteRequestTest extends AbstractTestCase
         self::assertSame('EN: Frontend Editing', $responseStructure->getScopePath('page/title'));
     }
 
+    /**
+     * @test
+     */
+    public function pageWithTrailingSlashSlugIsRenderedIfRequestedWithoutSlash(): void
+    {
+        $uri = 'https://website.us/features/frontend-editing';
+
+        $this->writeSiteConfiguration(
+            'website-local',
+            $this->buildSiteConfiguration(1000, 'https://website.local/'),
+            [
+                $this->buildDefaultLanguageConfiguration('EN', 'https://website.us/'),
+                $this->buildLanguageConfiguration('FR', 'https://website.fr/', ['EN']),
+                $this->buildLanguageConfiguration('FR-CA', 'https://website.ca/', ['FR', 'EN']),
+            ]
+        );
+
+        $response = $this->executeFrontendSubRequest(new InternalRequest($uri));
+        $responseStructure = ResponseContent::fromString((string)$response->getBody());
+        self::assertSame(200, $response->getStatusCode());
+        self::assertSame('EN: Frontend Editing', $responseStructure->getScopePath('page/title'));
+    }
+
+    /**
+     * @test
+     */
+    public function pageWithoutTrailingSlashSlugIsRenderedIfRequestedWithSlash(): void
+    {
+        $uri = 'https://website.us/features/';
+
+        $this->writeSiteConfiguration(
+            'website-local',
+            $this->buildSiteConfiguration(1000, 'https://website.local/'),
+            [
+                $this->buildDefaultLanguageConfiguration('EN', 'https://website.us/'),
+                $this->buildLanguageConfiguration('FR', 'https://website.fr/', ['EN']),
+                $this->buildLanguageConfiguration('FR-CA', 'https://website.ca/', ['FR', 'EN']),
+            ]
+        );
+
+        $response = $this->executeFrontendSubRequest(new InternalRequest($uri));
+        $responseStructure = ResponseContent::fromString((string)$response->getBody());
+        self::assertSame(200, $response->getStatusCode());
+        self::assertSame('EN: Features', $responseStructure->getScopePath('page/title'));
+    }
+
+    /**
+     * @test
+     */
+    public function pageWithoutTrailingSlashSlugIsRenderedIfRequestedWithoutSlash(): void
+    {
+        $uri = 'https://website.us/features';
+
+        $this->writeSiteConfiguration(
+            'website-local',
+            $this->buildSiteConfiguration(1000, 'https://website.local/'),
+            [
+                $this->buildDefaultLanguageConfiguration('EN', 'https://website.us/'),
+                $this->buildLanguageConfiguration('FR', 'https://website.fr/', ['EN']),
+                $this->buildLanguageConfiguration('FR-CA', 'https://website.ca/', ['FR', 'EN']),
+            ]
+        );
+
+        $response = $this->executeFrontendSubRequest(new InternalRequest($uri));
+        $responseStructure = ResponseContent::fromString((string)$response->getBody());
+        self::assertSame(200, $response->getStatusCode());
+        self::assertSame('EN: Features', $responseStructure->getScopePath('page/title'));
+    }
+
     public static function restrictedPageIsRenderedDataProvider(): array
     {
         $instructions = [
@@ -1263,7 +1332,11 @@ final class SlugSiteRequestTest extends AbstractTestCase
 
     public static function defaultLanguagePageNotResolvedForSiteLanguageBaseIfLanguagePageExistsDataProvider(): \Generator
     {
-        yield 'Default slug with default base resolves' => [
+        // ----------------------------------------------------------------
+        // #1 page slug without trailing slash, request with trailing slash
+        // ----------------------------------------------------------------
+
+        yield '#1 Default slug with default base resolves' => [
             'uri' => 'https://website.local/welcome/',
             'recordUpdates' => [],
             'fallbackIdentifiers' => [
@@ -1274,7 +1347,7 @@ final class SlugSiteRequestTest extends AbstractTestCase
             'expectedPageTitle' => 'EN: Welcome',
         ];
 
-        yield 'FR slug with FR base resolves' => [
+        yield '#1 FR slug with FR base resolves' => [
             'uri' => 'https://website.local/fr-fr/bienvenue/',
             'recordUpdates' => [],
             'fallbackIdentifiers' => [
@@ -1286,7 +1359,7 @@ final class SlugSiteRequestTest extends AbstractTestCase
         ];
 
         // Using default language slug with language base should be page not found if language page is active.
-        yield 'Default slug with default base do not resolve' => [
+        yield '#1 Default slug with default base do not resolve' => [
             'uri' => 'https://website.local/fr-fr/welcome/',
             'recordUpdates' => [],
             'fallbackIdentifiers' => [
@@ -1298,7 +1371,7 @@ final class SlugSiteRequestTest extends AbstractTestCase
         ];
 
         // Using default language slug with language base resolves for inactive / hidden language page
-        yield 'Default slug with default base but inactive language page resolves' => [
+        yield '#1 Default slug with default base but inactive language page resolves' => [
             'uri' => 'https://website.local/fr-fr/welcome/',
             'recordUpdates' => [
                 'pages' => [
@@ -1320,59 +1393,53 @@ final class SlugSiteRequestTest extends AbstractTestCase
             'expectedStatusCode' => 200,
             'expectedPageTitle' => 'EN: Welcome',
         ];
-    }
-
-    /**
-     * @link https://forge.typo3.org/issues/96010
-     * @test
-     * @dataProvider defaultLanguagePageNotResolvedForSiteLanguageBaseIfLanguagePageExistsDataProvider
-     */
-    public function defaultLanguagePageNotResolvedForSiteLanguageBaseIfLanguagePageExists(string $uri, array $recordUpdates, array $fallbackIdentifiers, string $fallbackType, int $expectedStatusCode, ?string $expectedPageTitle): void
-    {
-        $this->writeSiteConfiguration(
-            'website-local',
-            $this->buildSiteConfiguration(1000, 'https://website.local/'),
-            [
-                $this->buildDefaultLanguageConfiguration('EN', '/'),
-                $this->buildLanguageConfiguration('FR', 'https://website.local/fr-fr/', ['EN']),
-            ]
-        );
-        if ($recordUpdates !== []) {
-            foreach ($recordUpdates as $table => $records) {
-                foreach ($records as $record) {
-                    $this->getConnectionPool()->getConnectionForTable($table)
-                        ->update(
-                            $table,
-                            $record['data'] ?? [],
-                            $record['identifiers'] ?? [],
-                            $record['types'] ?? []
-                        );
-                }
-            }
-        }
-
-        $response = $this->executeFrontendSubRequest(new InternalRequest($uri));
-        $responseStructure = ResponseContent::fromString(
-            (string)$response->getBody()
-        );
 
-        self::assertSame(
-            $expectedStatusCode,
-            $response->getStatusCode()
-        );
-        if ($expectedPageTitle !== null) {
-            self::assertSame(
-                $expectedPageTitle,
-                $responseStructure->getScopePath('page/title')
-            );
-        }
-    }
+        // -------------------------------------------------------------
+        // #2 page slug with trailing slash, request with trailing slash
+        // -------------------------------------------------------------
 
-    public static function defaultLanguagePageNotResolvedForSiteLanguageBaseWithNonDefaultLanguageShorterUriIfLanguagePageExistsDataProvider(): \Generator
-    {
-        yield 'Default slug with default base resolves' => [
-            'uri' => 'https://website.local/en-en/welcome/',
-            'recordUpdates' => [],
+        yield '#2 Default slug with default base resolves' => [
+            'uri' => 'https://website.local/welcome/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
             'fallbackIdentifiers' => [
                 'EN',
             ],
@@ -1381,9 +1448,48 @@ final class SlugSiteRequestTest extends AbstractTestCase
             'expectedPageTitle' => 'EN: Welcome',
         ];
 
-        yield 'FR slug with FR base resolves' => [
-            'uri' => 'https://website.local/bienvenue/',
-            'recordUpdates' => [],
+        yield '#2 FR slug with FR base resolves' => [
+            'uri' => 'https://website.local/fr-fr/bienvenue/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
             'fallbackIdentifiers' => [
                 'EN',
             ],
@@ -1393,42 +1499,1187 @@ final class SlugSiteRequestTest extends AbstractTestCase
         ];
 
         // Using default language slug with language base should be page not found if language page is active.
-        yield 'Default slug with default base do not resolve' => [
-            'uri' => 'https://website.local/welcome/',
-            'recordUpdates' => [],
-            'fallbackIdentifiers' => [
-                'EN',
+        yield '#2 Default slug with default base do not resolve' => [
+            'uri' => 'https://website.local/fr-fr/welcome/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
             ],
-            'fallbackType' => 'strict',
-            'expectedStatusCode' => 404,
-            'expectedPageTitle' => null,
-        ];
-
-        // Using default language slug with language base should be page not found if language page is active.
-        yield 'Default slug with default base do not resolve strict without fallback' => [
-            'uri' => 'https://website.local/welcome/',
-            'recordUpdates' => [],
-            'fallbackIdentifiers' => [],
-            'fallbackType' => 'fallback',
-            'expectedStatusCode' => 404,
-            'expectedPageTitle' => null,
-        ];
-
-        // Using default language slug with language base should be page not found if language page is active.
-        yield 'Default slug with default base do not resolve fallback' => [
-            'uri' => 'https://website.local/welcome/',
-            'recordUpdates' => [],
             'fallbackIdentifiers' => [
                 'EN',
             ],
-            'fallbackType' => 'fallback',
+            'fallbackType' => 'strict',
             'expectedStatusCode' => 404,
             'expectedPageTitle' => null,
         ];
 
         // Using default language slug with language base resolves for inactive / hidden language page
-        yield 'Default slug with default base but inactive language page resolves' => [
-            'uri' => 'https://website.local/welcome/',
+        yield '#2 Default slug with default base but inactive language page resolves' => [
+            'uri' => 'https://website.local/fr-fr/welcome/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                            'hidden' => 1,
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        // ----------------------------------------------------------------
+        // #3 page slug with trailing slash, request without trailing slash
+        // ----------------------------------------------------------------
+
+        yield '#3 Default slug with default base resolves' => [
+            'uri' => 'https://website.local/welcome',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        yield '#3 FR slug with FR base resolves' => [
+            'uri' => 'https://website.local/fr-fr/bienvenue',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'FR: Welcome',
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#3 Default slug with default base do not resolve' => [
+            'uri' => 'https://website.local/fr-fr/welcome',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base resolves for inactive / hidden language page
+        yield '#3 Default slug with default base but inactive language page resolves' => [
+            'uri' => 'https://website.local/fr-fr/welcome',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                            'hidden' => 1,
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        // -------------------------------------------------------------------
+        // #4 page slug without trailing slash, request without trailing slash
+        // -------------------------------------------------------------------
+
+        yield '#4 Default slug with default base resolves' => [
+            'uri' => 'https://website.local/welcome',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        yield '#4 FR slug with FR base resolves' => [
+            'uri' => 'https://website.local/fr-fr/bienvenue',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'FR: Welcome',
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#4 Default slug with default base do not resolve' => [
+            'uri' => 'https://website.local/fr-fr/welcome',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base resolves for inactive / hidden language page
+        yield '#4 Default slug with default base but inactive language page resolves' => [
+            'uri' => 'https://website.local/fr-fr/welcome',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'hidden' => 1,
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+    }
+
+    /**
+     * @link https://forge.typo3.org/issues/96010
+     * @test
+     * @dataProvider defaultLanguagePageNotResolvedForSiteLanguageBaseIfLanguagePageExistsDataProvider
+     */
+    public function defaultLanguagePageNotResolvedForSiteLanguageBaseIfLanguagePageExists(string $uri, array $recordUpdates, array $fallbackIdentifiers, string $fallbackType, int $expectedStatusCode, ?string $expectedPageTitle): void
+    {
+        $this->writeSiteConfiguration(
+            'website-local',
+            $this->buildSiteConfiguration(1000, 'https://website.local/'),
+            [
+                $this->buildDefaultLanguageConfiguration('EN', '/'),
+                $this->buildLanguageConfiguration('FR', 'https://website.local/fr-fr/', ['EN']),
+            ]
+        );
+        if ($recordUpdates !== []) {
+            foreach ($recordUpdates as $table => $records) {
+                foreach ($records as $record) {
+                    $this->getConnectionPool()->getConnectionForTable($table)
+                        ->update(
+                            $table,
+                            $record['data'] ?? [],
+                            $record['identifiers'] ?? [],
+                            $record['types'] ?? []
+                        );
+                }
+            }
+        }
+
+        $response = $this->executeFrontendSubRequest(new InternalRequest($uri));
+        $responseStructure = ResponseContent::fromString(
+            (string)$response->getBody()
+        );
+
+        self::assertSame(
+            $expectedStatusCode,
+            $response->getStatusCode()
+        );
+        if ($expectedPageTitle !== null) {
+            self::assertSame(
+                $expectedPageTitle,
+                $responseStructure->getScopePath('page/title')
+            );
+        }
+    }
+
+    public static function defaultLanguagePageNotResolvedForSiteLanguageBaseWithNonDefaultLanguageShorterUriIfLanguagePageExistsDataProvider(): \Generator
+    {
+        // ----------------------------------------------------------------
+        // #1 page slug without trailing slash, request with trailing slash
+        // ----------------------------------------------------------------
+
+        yield '#1 Default slug with default base resolves' => [
+            'uri' => 'https://website.local/en-en/welcome/',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        yield '#1 FR slug with FR base resolves' => [
+            'uri' => 'https://website.local/bienvenue/',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'FR: Welcome',
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#1 Default slug with default base do not resolve' => [
+            'uri' => 'https://website.local/welcome/',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#1 Default slug with default base do not resolve strict without fallback' => [
+            'uri' => 'https://website.local/welcome/',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [],
+            'fallbackType' => 'fallback',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#1 Default slug with default base do not resolve fallback' => [
+            'uri' => 'https://website.local/welcome/',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'fallback',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base resolves for inactive / hidden language page
+        yield '#1 Default slug with default base but inactive language page resolves' => [
+            'uri' => 'https://website.local/welcome/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'hidden' => 1,
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        // -------------------------------------------------------------
+        // #2 page slug with trailing slash, request with trailing slash
+        // -------------------------------------------------------------
+
+        yield '#2 Default slug with default base resolves' => [
+            'uri' => 'https://website.local/en-en/welcome/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        yield '#2 FR slug with FR base resolves' => [
+            'uri' => 'https://website.local/bienvenue/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'FR: Welcome',
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#2 Default slug with default base do not resolve' => [
+            'uri' => 'https://website.local/welcome/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#2 Default slug with default base do not resolve strict without fallback' => [
+            'uri' => 'https://website.local/welcome/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [],
+            'fallbackType' => 'fallback',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#2 Default slug with default base do not resolve fallback' => [
+            'uri' => 'https://website.local/welcome/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'fallback',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base resolves for inactive / hidden language page
+        yield '#2 Default slug with default base but inactive language page resolves' => [
+            'uri' => 'https://website.local/welcome/',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                            'hidden' => 1,
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        // ----------------------------------------------------------------
+        // #3 page slug with trailing slash, request without trailing slash
+        // ----------------------------------------------------------------
+
+        yield '#3 Default slug with default base resolves' => [
+            'uri' => 'https://website.local/en-en/welcome',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        yield '#3 FR slug with FR base resolves' => [
+            'uri' => 'https://website.local/bienvenue',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'FR: Welcome',
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#3 Default slug with default base do not resolve' => [
+            'uri' => 'https://website.local/welcome',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#3 Default slug with default base do not resolve strict without fallback' => [
+            'uri' => 'https://website.local/welcome',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [],
+            'fallbackType' => 'fallback',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#3 Default slug with default base do not resolve fallback' => [
+            'uri' => 'https://website.local/welcome',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'fallback',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base resolves for inactive / hidden language page
+        yield '#3 Default slug with default base but inactive language page resolves' => [
+            'uri' => 'https://website.local/welcome',
+            'recordUpdates' => [
+                'pages' => [
+                    [
+                        'data' => [
+                            'slug' => '/welcome/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1100,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                            'hidden' => 1,
+                        ],
+                        'identifiers' => [
+                            'uid' => 1101,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1102,
+                        ],
+                        'types' => [],
+                    ],
+                    [
+                        'data' => [
+                            'slug' => '/简-bienvenue/',
+                        ],
+                        'identifiers' => [
+                            'uid' => 1103,
+                        ],
+                        'types' => [],
+                    ],
+                ],
+            ],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        // -------------------------------------------------------------------
+        // #4 page slug without trailing slash, request without trailing slash
+        // -------------------------------------------------------------------
+
+        yield '#4 Default slug with default base resolves' => [
+            'uri' => 'https://website.local/en-en/welcome',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'EN: Welcome',
+        ];
+
+        yield '#4 FR slug with FR base resolves' => [
+            'uri' => 'https://website.local/bienvenue',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 200,
+            'expectedPageTitle' => 'FR: Welcome',
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#4 Default slug with default base do not resolve' => [
+            'uri' => 'https://website.local/welcome',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'strict',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#4 Default slug with default base do not resolve strict without fallback' => [
+            'uri' => 'https://website.local/welcome',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [],
+            'fallbackType' => 'fallback',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base should be page not found if language page is active.
+        yield '#4 Default slug with default base do not resolve fallback' => [
+            'uri' => 'https://website.local/welcome',
+            'recordUpdates' => [],
+            'fallbackIdentifiers' => [
+                'EN',
+            ],
+            'fallbackType' => 'fallback',
+            'expectedStatusCode' => 404,
+            'expectedPageTitle' => null,
+        ];
+
+        // Using default language slug with language base resolves for inactive / hidden language page
+        yield '#4 Default slug with default base but inactive language page resolves' => [
+            'uri' => 'https://website.local/welcome',
             'recordUpdates' => [
                 'pages' => [
                     [
-- 
GitLab