diff --git a/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php b/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php index a34ea386f8a50a4575a547d2c40592d599caed68..1f72cfe8fbcb5597d2ace2358a231926edb54522 100644 --- a/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php +++ b/typo3/sysext/frontend/Classes/Typolink/PageLinkBuilder.php @@ -163,9 +163,18 @@ class PageLinkBuilder extends AbstractTypolinkBuilder // Disable "?id=", for pages with no site configuration, this is added later-on anyway unset($queryParameters['id']); - // Override language property if not being set already - if (isset($queryParameters['L']) && !isset($conf['language'])) { - $conf['language'] = (int)$queryParameters['L']; + // Override language property if not being set already, supporting historically 'L' and + // modern '_language' arguments, giving '_language' the precedence. + if (isset($queryParameters['_language'])) { + if (!isset($conf['language'])) { + $conf['language'] = (int)$queryParameters['_language']; + } + unset($queryParameters['_language']); + } + if (isset($queryParameters['L'])) { + if (!isset($conf['language'])) { + $conf['language'] = (int)$queryParameters['L']; + } unset($queryParameters['L']); } diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/TypoLinkScenario.yaml b/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/TypoLinkScenario.yaml index 2a8118593127890c34f375fae06a8b7de37fdd61..1a44af4419b2db02755d085e29123643d601c1b2 100644 --- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/TypoLinkScenario.yaml +++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/Fixtures/TypoLinkScenario.yaml @@ -23,17 +23,29 @@ entitySettings: languageColumnNames: ['l18n_parent', 'l10n_source'] columnNames: {title: 'header', type: 'CType'} defaultValues: {hidden: 0, CType: 'text'} + language: + tableName: 'sys_language' + columnNames: {code: 'language_isocode'} entities: + language: + - self: {id: 1, title: 'French', code: 'fr'} + - self: {id: 2, title: 'Franco-Canadian', code: 'fr'} page: - self: {id: 1000, title: 'ACME Inc', type: *pageShortcut, shortcut: 'first', root: true, slug: '/'} children: - self: {id: 1100, title: 'EN: Welcome', slug: '/welcome', subtitle: 'hello-and-welcome'} + languageVariants: + - self: {id: 1101, title: 'FR: Bienvenue', language: 1, slug: '/bienvenue', subtitle: 'salut-et-bienvenue'} + - self: {id: 1102, title: 'FR-CA: Bienvenue', language: 2, slug: '/bienvenue', subtitle: 'salut-et-bienvenue'} entities: content: - self: {title: 'EN: Content Element #1'} - self: {title: 'EN: Content Element #2'} - self: {id: 1200, title: 'EN: Features', slug: '/features'} + languageVariants: + - self: {id: 1201, title: 'FR: Features', slug: '/features-fr', language: 1} + - self: {id: 1202, title: 'FR-CA: Features', slug: '/features-ca', language: 2} - self: {id: 1300, title: 'Go to TYPO3.org', type: *pageLink, slug: '/external', url: 'typo3.org' } - self: {id: 9911, title: '<good>', slug: '/test/good'} - self: {id: 9912, title: '<good a="a/" b="thing(1)">', slug: '/test/good-a-b-spaced'} diff --git a/typo3/sysext/frontend/Tests/Functional/SiteHandling/TypoLinkGeneratorTest.php b/typo3/sysext/frontend/Tests/Functional/SiteHandling/TypoLinkGeneratorTest.php index 47a0ef757671119f435ad31bbf9401f3a93ecc94..7e0129849286420e20acb8d3be6da8de3829b668 100644 --- a/typo3/sysext/frontend/Tests/Functional/SiteHandling/TypoLinkGeneratorTest.php +++ b/typo3/sysext/frontend/Tests/Functional/SiteHandling/TypoLinkGeneratorTest.php @@ -200,6 +200,58 @@ class TypoLinkGeneratorTest extends AbstractTestCase 'user@example.org target class title &other=other', '<a href="mailto:user@example.org" title="title" target="target" class="class">user@example.org</a>', ], + // check link with language parameters + [ + 't3://page?uid=1200&L=0', + '<a href="/features">EN: Features</a>', + ], + [ + 't3://page?uid=1200&_language=0', + '<a href="/features">EN: Features</a>', + ], + [ + 't3://page?uid=1200&L=1', + '<a href="https://acme.fr/features-fr">FR: Features</a>', + ], + [ + 't3://page?uid=1200&_language=1', + '<a href="https://acme.fr/features-fr">FR: Features</a>', + ], + [ + 't3://page?uid=1201&L=1', + '<a href="https://acme.fr/features-fr">FR: Features</a>', + ], + [ + 't3://page?uid=1201&_language=1', + '<a href="https://acme.fr/features-fr">FR: Features</a>', + ], + // localized page language overrule language arguments (new and old). + // This has also test coverage through SlugGeneratorTests. + [ + 't3://page?uid=1202&L=1', + '<a href="https://acme.ca/features-ca">FR-CA: Features</a>', + ], + [ + 't3://page?uid=1202&_language=1', + '<a href="https://acme.ca/features-ca">FR-CA: Features</a>', + ], + // check precedence order correctness if old and modern are provided + [ + 't3://page?uid=1200&L=2&_language=1', + '<a href="https://acme.fr/features-fr">FR: Features</a>', + ], + [ + 't3://page?uid=1200&_language=1&L=2', + '<a href="https://acme.fr/features-fr">FR: Features</a>', + ], + [ + 't3://page?uid=1200&L=1&_language=2', + '<a href="https://acme.ca/features-ca">FR-CA: Features</a>', + ], + [ + 't3://page?uid=1200&_language=2&L=1', + '<a href="https://acme.ca/features-ca">FR-CA: Features</a>', + ], ]; return $this->keysFromTemplate($instructions, '%1$s;'); }