diff --git a/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php b/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php
index b5c2020cc44171b4952c6b4ebdd6961cfabf43c4..b9aa25ea2072ef81f90bde8ccae931a667d022d7 100644
--- a/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php
+++ b/typo3/sysext/core/Classes/Domain/Repository/PageRepository.php
@@ -365,8 +365,7 @@ class PageRepository implements LoggerAwareInterface
     /**
      * Master helper method to overlay a record to a language.
      *
-     * Be aware that for pages the languageId is taken, and for all other records the contentId.
-     * This might change through a feature switch in the future.
+     * Be aware that for pages the languageId is taken, and for all other records the contentId of the Aspect is used.
      *
      * @param string $table the name of the table, should be a TCA table with localization enabled
      * @param array $originalRow the current (full-fletched) record.
@@ -398,10 +397,57 @@ class PageRepository implements LoggerAwareInterface
         $localizedRecord = null;
         if ($languageAspect->doOverlays()) {
             $attempted = true;
-            if ($table === 'pages') {
-                $localizedRecord = $this->getPageOverlay($originalRow, $languageAspect);
+            // Mixed = if nothing is available in the selected language, try the fallbacks
+            // Fallbacks work as follows:
+            // 1. We have a default language record and then start doing overlays (= the basis for fallbacks)
+            // 2. Check if the actual requested language version is available in the DB (language=3 = canadian-french)
+            // 3. If not, we check the next language version in the chain (e.g. language=2 = french) and so forth until we find a record
+            if ($languageAspect->getOverlayType() === LanguageAspect::OVERLAYS_MIXED) {
+                $languageChain = $this->getLanguageFallbackChain($languageAspect);
+                $languageChain = array_reverse($languageChain);
+                if ($table === 'pages') {
+                    $result = $this->getPageOverlay(
+                        $originalRow,
+                        new LanguageAspect($languageAspect->getId(), $languageAspect->getId(), LanguageAspect::OVERLAYS_MIXED, $languageChain)
+                    );
+                    if (!empty($result)) {
+                        $localizedRecord = $result;
+                    }
+                } else {
+                    $languageChain = array_merge($languageChain, [$languageAspect->getContentId()]);
+                    // Loop through each (fallback) language and see if there is a record
+                    // However, we do not want to preserve the "originalRow", that's why we set the option to "OVERLAYS_ON"
+                    while (($languageId = array_pop($languageChain)) !== null) {
+                        $result = $this->getRecordOverlay(
+                            $table,
+                            $originalRow,
+                            new LanguageAspect($languageId, $languageId, LanguageAspect::OVERLAYS_ON)
+                        );
+                        // If an overlay is found, return it
+                        if (is_array($result)) {
+                            $localizedRecord = $result;
+                            break;
+                        }
+                    }
+                    if ($localizedRecord === null) {
+                        // If nothing was found, we set the localized record to the originalRow to simulate
+                        // that the default language is "kept" (we want fallback to default language).
+                        // Note: Most installations might have "type=fallback" set but do not set the default language
+                        // as fallback. In the future - once we want to get rid of the magic "default language",
+                        // this needs to behave different, and the "pageNotFound" special handling within fallbacks should be removed
+                        // and we need to check explicitly on in_array(0, $languageAspect->getFallbackChain())
+                        // However, getPageOverlay() a few lines above also returns the "default language page" as well.
+                        $localizedRecord = $originalRow;
+                    }
+                }
             } else {
-                $localizedRecord = $this->getRecordOverlay($table, $originalRow, $languageAspect);
+                // The option to hide records if they were not explicitly selected, was chosen (OVERLAYS_ON/WITH_FLOATING)
+                // in the language configuration. So, here no changes are done.
+                if ($table === 'pages') {
+                    $localizedRecord = $this->getPageOverlay($originalRow, $languageAspect);
+                } else {
+                    $localizedRecord = $this->getRecordOverlay($table, $originalRow, $languageAspect);
+                }
             }
         }
 
@@ -740,7 +786,7 @@ class PageRepository implements LoggerAwareInterface
                 }
             }
         }
-        return $row;
+        return is_array($row) ? $row : null;
     }
 
     /************************************************
diff --git a/typo3/sysext/core/Documentation/Changelog/12.2/Feature-88137-Multi-levelFallbackForContentInFrontendRendering.rst b/typo3/sysext/core/Documentation/Changelog/12.2/Feature-88137-Multi-levelFallbackForContentInFrontendRendering.rst
new file mode 100644
index 0000000000000000000000000000000000000000..d9018230c14f0242715466fab38c1f5281c7ed0e
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/12.2/Feature-88137-Multi-levelFallbackForContentInFrontendRendering.rst
@@ -0,0 +1,58 @@
+.. include:: /Includes.rst.txt
+
+.. _feature-88137-1673993076:
+
+========================================================================
+Feature: #88137 - Multi-level fallback for content in frontend rendering
+========================================================================
+
+See :issue:`88137`
+
+Description
+===========
+
+TYPO3's Site Handling was introduced in TYPO3 v9 and allows to define a
+"Fallback Type".
+
+A fallback type allows to define the behavior of how pages and the content
+should be fetched from the database when rendering a page in the frontend.
+
+The option "strict" only renders content which was explicitly translated or
+created in this defined language, and keeps the sorting behavior of the
+default language.
+
+The option "free" does not consider the default language or its sorting,
+and only directly fetches content of the given Language ID.
+
+The option "fallback" allows to define a fallback chain of other languages.
+When a certain page in the given language is not available or created, TYPO3
+first checks the fallback chain if a page is available in one of the languages
+of the fallback chain.
+
+A common scenario is this:
+* German (Austria) - Language = 2
+* German (Germany) - Language = 1
+* English (Default) - Language = 0
+
+TYPO3 now can deal with the language chain in fallback mode not only for pages,
+but also for any kind of content.
+
+
+Impact
+======
+
+When working in a scenario with "fallback" and multiple languages in the fallback
+chain, TYPO3 now checks for each content if the target language is available,
+and then checks for the same content if it is translated in the language of the
+fallback chain (example above in "German (Germany)"), before falling back to
+the default language - which was the behavior until now.
+
+The language chain processing works with fallback mode (a.k.a. "overlays in mixed mode"),
+both in TypoScript and Extbase code. Under the hood, the method
+:php:`PageRepository->getLanguageOverlay()` is responsible for the chaining.
+
+Current limitations:
+* Content fallback only works in fallbackType=fallback
+* Content fallback always stops at the default language (as this was the previous behavior)
+
+.. index:: Frontend, PHP-API, TypoScript, ext:core
diff --git a/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Storage/Typo3DbBackendTest.php b/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Storage/Typo3DbBackendTest.php
index 6f6780646e81c727a8e55112c293e7689e284d2d..26eee5252e8de41973818d0826f53aa8627e9142 100644
--- a/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Storage/Typo3DbBackendTest.php
+++ b/typo3/sysext/extbase/Tests/Functional/Persistence/Generic/Storage/Typo3DbBackendTest.php
@@ -21,6 +21,7 @@ use ExtbaseTeam\BlogExample\Domain\Model\Tag;
 use ExtbaseTeam\BlogExample\Domain\Repository\BlogRepository;
 use ExtbaseTeam\BlogExample\Domain\Repository\PostRepository;
 use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\LanguageAspect;
 use TYPO3\CMS\Core\Context\WorkspaceAspect;
 use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder;
 use TYPO3\CMS\Core\Http\ServerRequest;
@@ -71,6 +72,7 @@ class Typo3DbBackendTest extends FunctionalTestCase
         $blogRepository = $this->get(BlogRepository::class);
         $context = new Context([
             'workspace' => new WorkspaceAspect(1),
+            'language' => new LanguageAspect(0, 0),
         ]);
         GeneralUtility::setSingletonInstance(Context::class, $context);
         $querySettings = new Typo3QuerySettings($context, $this->get(ConfigurationManagerInterface::class));
diff --git a/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedSiteContentRenderingTest.php b/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedSiteContentRenderingTest.php
index feaa9066354b5f5462e714641015558e70598ab2..16fd8a0e789ddbf177efc981ea8bd8d356300d5a 100644
--- a/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedSiteContentRenderingTest.php
+++ b/typo3/sysext/frontend/Tests/Functional/Rendering/LocalizedSiteContentRenderingTest.php
@@ -87,7 +87,7 @@ use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\ResponseContent;
  *
  * LanguageAspect
  * -> doOverlays()
- *    whether the the overlay logic should be applied
+ *    whether the overlay logic should be applied
  * -> getLanguageId()
  *    the language that was originally requested
  * -> getContentId()
@@ -681,113 +681,110 @@ class LocalizedSiteContentRenderingTest extends AbstractDataHandlerActionTestCas
         self::assertEquals($statusCode, $response->getStatusCode());
     }
 
-    public function contentOnPartiallyTranslatedPageDataProvider(): array
+    public function contentOnPartiallyTranslatedPageDataProvider(): \Generator
     {
         //Expected behaviour:
         //Setting sys_language_mode to different values doesn't influence the result as the requested page is translated to Polish,
         //Page title is always [PL]Page, and both languageId/contentId are always 3
-        return [
-            [
-                'languageConfiguration' => [
-                    'fallbackType' => 'free',
-                ],
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+        yield 'free' => [
+            'languageConfiguration' => [
                 'fallbackType' => 'free',
-                'fallbackChain' => 'pageNotFound',
-                'overlayMode' => 'off',
             ],
-            [
-                'languageConfiguration' => [
-                    'fallbackType' => 'free',
-                    'fallbackChain' => ['EN'],
-                ],
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'fallbackType' => 'free',
+            'fallbackChain' => 'pageNotFound',
+            'overlayMode' => 'off',
+        ];
+        yield 'free with fallback' => [
+            'languageConfiguration' => [
                 'fallbackType' => 'free',
-                'fallbackChain' => '0,pageNotFound',
-                'overlayMode' => 'off',
+                'fallbackChain' => ['EN'],
             ],
-            [
-                'languageConfiguration' => [
-                    'fallbackType' => 'free',
-                    'fallbackChain' => ['DK', 'EN'],
-                ],
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'fallbackType' => 'free',
+            'fallbackChain' => '0,pageNotFound',
+            'overlayMode' => 'off',
+        ];
+        yield 'free with multiple fallbacks' => [
+            'languageConfiguration' => [
                 'fallbackType' => 'free',
-                'fallbackChain' => '1,0,pageNotFound',
-                'overlayMode' => 'off',
+                'fallbackChain' => ['DK', 'EN'],
             ],
-            // Expected behaviour:
-            // Not translated element #2 is shown because sys_language_overlay = 1 (with sys_language_overlay = hideNonTranslated, it would be hidden)
-            [
-                'languageConfiguration' => [
-                    'fallbackType' => 'fallback',
-                    'fallbackChain' => ['EN'],
-                ],
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+            'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'fallbackType' => 'free',
+            'fallbackChain' => '1,0,pageNotFound',
+            'overlayMode' => 'off',
+        ];
+        // Expected behaviour:
+        // Not translated element #2 is shown because sys_language_overlay = 1 (with sys_language_overlay = hideNonTranslated, it would be hidden)
+        yield 'fallback to EN' => [
+            'languageConfiguration' => [
                 'fallbackType' => 'fallback',
-                'fallbackChain' => '0,pageNotFound',
-                'overlayMode' => 'mixed',
+                'fallbackChain' => ['EN'],
             ],
-            // Expected behaviour:
-            // Element #3 is not translated in PL and it is translated in DK. It's not shown as content_fallback is not related to single CE level
-            // but on page level - and this page is translated to Polish, so no fallback is happening
-            [
-                'languageConfiguration' => [
-                    'fallbackType' => 'fallback',
-                    'fallbackChain' => ['DK', 'EN'],
-                ],
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+            'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+            'fallbackType' => 'fallback',
+            'fallbackChain' => '0,pageNotFound',
+            'overlayMode' => 'mixed',
+        ];
+        // Expected behaviour:
+        // Element #3 is not translated in PL, but it is translated in DK. The DK version is shown as it has a fallback chain defined.
+        yield 'fallback with multiple languages' => [
+            'languageConfiguration' => [
                 'fallbackType' => 'fallback',
-                'fallbackChain' => '1,0,pageNotFound',
-                'overlayMode' => 'mixed',
+                'fallbackChain' => ['DK', 'EN'],
             ],
-            [
-                'languageConfiguration' => [
-                    'fallbackType' => 'fallback',
-                    'fallbackChain' => [],
-                ],
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+            'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', '[Translate to Dansk:] Regular Element #3'],
+            'fallbackType' => 'fallback',
+            'fallbackChain' => '1,0,pageNotFound',
+            'overlayMode' => 'mixed',
+        ];
+        yield 'fallback but without languages' => [
+            'languageConfiguration' => [
                 'fallbackType' => 'fallback',
-                'fallbackChain' => 'pageNotFound',
-                'overlayMode' => 'mixed',
+                'fallbackChain' => [],
             ],
-            // Expected behaviour:
-            // Non translated default language elements are not shown, because of hideNonTranslated
-            [
-                'languageConfiguration' => [
-                    'fallbackType' => 'strict',
-                    'fallbackChain' => ['EN'],
-                ],
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', 'Regular Element #2', 'Regular Element #3'],
+            'fallbackType' => 'fallback',
+            'fallbackChain' => 'pageNotFound',
+            'overlayMode' => 'mixed',
+        ];
+        // Expected behaviour:
+        // Non translated default language elements are not shown, because of hideNonTranslated
+        yield 'strict with fallback to default' => [
+            'languageConfiguration' => [
                 'fallbackType' => 'strict',
-                'fallbackChain' => '0,pageNotFound',
-                'overlayMode' => 'includeFloating',
+                'fallbackChain' => ['EN'],
             ],
-            [
-                'languageConfiguration' => [
-                    'fallbackType' => 'strict',
-                    'fallbackChain' => ['DK', 'EN'],
-                ],
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'fallbackType' => 'strict',
+            'fallbackChain' => '0,pageNotFound',
+            'overlayMode' => 'includeFloating',
+        ];
+        yield 'strict with multiple fallbacks' => [
+            'languageConfiguration' => [
                 'fallbackType' => 'strict',
-                'fallbackChain' => '1,0,pageNotFound',
-                'overlayMode' => 'includeFloating',
+                'fallbackChain' => ['DK', 'EN'],
             ],
-            [
-                'languageConfiguration' => [
-                    'fallbackType' => 'strict',
-                    'fallbackChain' => [],
-                ],
-                'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'fallbackType' => 'strict',
+            'fallbackChain' => '1,0,pageNotFound',
+            'overlayMode' => 'includeFloating',
+        ];
+        yield 'strict without fallback' => [
+            'languageConfiguration' => [
                 'fallbackType' => 'strict',
-                'fallbackChain' => 'pageNotFound',
-                'overlayMode' => 'includeFloating',
+                'fallbackChain' => [],
             ],
+            'visibleRecordHeaders' => ['[Translate to Polski:] Regular Element #1', '[PL] Without default language'],
+            'fallbackType' => 'strict',
+            'fallbackChain' => 'pageNotFound',
+            'overlayMode' => 'includeFloating',
         ];
     }
 
     /**
-     * Page uid 89 is translated to to Polish, but not all CE are translated
+     * Page uid 89 is translated to Polish, but not all CE are translated
      *
      * @test
      * @dataProvider contentOnPartiallyTranslatedPageDataProvider