diff --git a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php index 09b3b0a3ae67b1a2ee3b89e194b7974f71441dc3..37e64b4acc16f838873f1307a113bf44f2c1a85e 100644 --- a/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php +++ b/typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php @@ -905,6 +905,7 @@ class TypoScriptFrontendController implements LoggerAwareInterface // about languages - whether we took the correct shortcut or // whether a translation of the page overwrites the shortcut // target and we need to follow the new target + $this->settingLanguage($request); $this->originalShortcutPage = $this->page; $this->page = $this->sys_page->resolveShortcutPage($this->page, true); $this->id = (int)$this->page['uid']; diff --git a/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php b/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php index d2c82fb3f2bdaebe7372abd044b1b3698250af3b..01a5b27ef27a7079263859cbfe9fa4930ecc6a6a 100644 --- a/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php +++ b/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php @@ -408,6 +408,14 @@ class PageLinkBuilder extends AbstractTypolinkBuilder if (empty($page) || !is_array($page)) { return []; } + + // If the page repository (= current page) does actually link to a different page + // It is needed to also resolve the page translation now, as it might have a different shortcut + // page + if (isset($configuration['language']) && $configuration['language'] !== 'current') { + $page = $pageRepository->getLanguageOverlay('pages', $page, new LanguageAspect($configuration['language'], $configuration['language'])); + } + $page = $this->resolveShortcutPage($page, $pageRepository, $disableGroupAccessCheck); $languageField = $GLOBALS['TCA']['pages']['ctrl']['languageField'] ?? null; diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml b/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml index bb23dd44db5933b1d0ee9ac751e984ea309591b4..3e392b91f552c791b14028115af3ee087e279ad1 100644 --- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml +++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/SlugScenario.yaml @@ -141,6 +141,8 @@ entities: - self: {id: 2021, title: 'FEGroups Restricted', visitorGroups: 30, slug: '/sysfolder-restricted'} - self: {id: 2022, title: 'FEGroups Restricted', hidden: 1, visitorGroups: 30, slug: '/sysfolder-restricted-hidden'} - self: {id: 2030, title: 'Cross Site Shortcut', slug: '/cross-site-shortcut', type: *pageShortcut, shortcut: 2100} + languageVariants: + - self: {id: 2031, title: 'Shortcut to Research - shows a different page', language: 1, type: *pageShortcut, shortcut: 1400, slug: '/other-cross-site-shortcut', l10n_state: '{"starttime":"parent","endtime":"parent","nav_hide":"parent","url":"parent","lastUpdated":"parent","newUntil":"parent","no_search":"parent","shortcut":"custom","shortcut_mode":"parent","content_from_pid":"parent","author":"parent","author_email":"parent","media":"parent","og_image":"parent","twitter_image":"parent"}' } - self: {id: 2000, title: 'ACME Blog', type: *pageShortcut, shortcut: 'first', root: true, slug: '/'} children: - self: {id: 2100, title: 'Authors', slug: '/authors'} diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php index 93b0891ee7844fdc5d5d74ecda30157af6a3f5fa..16418efd09cb4923d058e24928260b5bdced631d 100644 --- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php +++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugLinkGeneratorTest.php @@ -830,6 +830,20 @@ final class SlugLinkGeneratorTest extends AbstractTestCase ], ], ], + 'resolved shortcut in translation' => [ + 'https://acme.fr/', + 1100, + '2030', + [ + [ + 'title' => 'Shortcut to Research - shows a different page', + 'link' => '/acme-dans-votre-region', + 'active' => 0, + 'current' => 0, + ], + ], + ], + ]; } @@ -837,7 +851,7 @@ final class SlugLinkGeneratorTest extends AbstractTestCase * @test * @dataProvider hierarchicalMenuSetsActiveStateProperlyDataProvider */ - public function hierarchicalMenuSetsActiveStateProperly(string $hostPrefix, int $sourcePageId, string $menuPageIds, array $expectation): void + public function hierarchicalMenuSetsActiveStateProperly(string $hostPrefix, int $sourcePageId, string $menuPageIds, array $expectation, int $languageId = 0): void { $response = $this->executeFrontendSubRequest( (new InternalRequest($hostPrefix)) diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php index 3770327c0b11e188960b700fe68cb24733896c2b..5bb44f00741621666515314c48cf91c1a2cce334 100644 --- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php +++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/SlugSiteRequestTest.php @@ -1220,16 +1220,22 @@ final class SlugSiteRequestTest extends AbstractTestCase ); } - public static function crossSiteShortcutsAreRedirectedDataProvider(): array + public static function crossSiteShortcutsAreRedirectedDataProvider(): \Generator { - return [ - 'shortcut is redirected' => [ - 'https://website.local/cross-site-shortcut', - 307, - [ - 'X-Redirect-By' => ['TYPO3 Shortcut/Mountpoint'], - 'location' => ['https://blog.local/authors'], - ], + yield 'shortcut is redirected' => [ + 'https://website.local/cross-site-shortcut', + 307, + [ + 'X-Redirect-By' => ['TYPO3 Shortcut/Mountpoint'], + 'location' => ['https://blog.local/authors'], + ], + ]; + yield 'shortcut of translated page is redirected to a different page than the original page' => [ + 'https://website.local/fr/other-cross-site-shortcut', + 307, + [ + 'X-Redirect-By' => ['TYPO3 Shortcut/Mountpoint'], + 'location' => ['https://website.local/fr/acme-dans-votre-region'], ], ]; } @@ -1242,11 +1248,19 @@ final class SlugSiteRequestTest extends AbstractTestCase { $this->writeSiteConfiguration( 'website-local', - $this->buildSiteConfiguration(1000, 'https://website.local/') + $this->buildSiteConfiguration(1000, 'https://website.local/'), + [ + $this->buildDefaultLanguageConfiguration('EN', '/'), + $this->buildLanguageConfiguration('FR', '/fr/', ['EN']), + ] ); $this->writeSiteConfiguration( 'blog-local', - $this->buildSiteConfiguration(2000, 'https://blog.local/') + $this->buildSiteConfiguration(2000, 'https://blog.local/'), + [ + $this->buildDefaultLanguageConfiguration('EN', '/'), + $this->buildLanguageConfiguration('FR', '/fr/', ['EN']), + ] ); $this->setUpFrontendRootPage( 2000,