diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-90613-AddLanguageArgumentToPage-relatedLinkViewHelpersAndUriViewHelpersInFluid.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-90613-AddLanguageArgumentToPage-relatedLinkViewHelpersAndUriViewHelpersInFluid.rst new file mode 100644 index 0000000000000000000000000000000000000000..7217ef181a21f2de62a021ce45e128a6dff998c4 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-90613-AddLanguageArgumentToPage-relatedLinkViewHelpersAndUriViewHelpersInFluid.rst @@ -0,0 +1,64 @@ +.. include:: ../../Includes.txt + +=================================================================================================== +Feature: #90613 - Add language argument to page-related LinkViewHelpers and UriViewHelpers in Fluid +=================================================================================================== + +See :issue:`90613` + +Description +=========== + +A new argument "language" is added to the following Fluid ViewHelpers: + +* :html:`<f:link.typolink>` +* :html:`<f:link.page>` +* :html:`<f:uri.typolink>` +* :html:`<f:uri.page>` + +They are responsible for linking to a page, and are using TypoLink functionality +under-the-hood. + + +Examples +-------- + +A Link to page with ID 13 but with language 3 - no matter what language the +current page is: + + +.. code-block:: html + + <f:link.page pageUid="13" language="3">Go to french version of about us page</f:link.page> + + +Creating a language menu: + +.. code-block:: html + + <ul> + <li> + <f:link.typolink parameter="current" language="3">Current page in french</f:link.typolink> + </li> + <li> + <f:link.typolink parameter="current" language="4">Current page in german</f:link.typolink> + </li> + <li> + <f:link.typolink parameter="current" language="5">Current page in spanish</f:link.typolink> + </li> + </ul> + + +Impact +====== + +The new argument allows to force a language when linking to a specific page, +making it consistent with the TypoLink option added in site handling for TYPO3 v9: + +https://docs.typo3.org/m/typo3/reference-typoscript/master/en-us/Functions/Typolink.html#language + +This Fluid option should be used instead of adding a `L` parameter to +`additionalParameters` argument to make linking to a specific language possible. +In general, using of the magic GET variable `L` is discouraged. + +.. index:: Fluid, ext:fluid \ No newline at end of file diff --git a/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php b/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php index 237e09e58b19b9c0f2e86d4253ca37983972c7d5..f93ad07f919d488139d5b815d599ca82f609a5be 100644 --- a/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php +++ b/typo3/sysext/extbase/Classes/Mvc/Web/Routing/UriBuilder.php @@ -108,6 +108,11 @@ class UriBuilder */ protected $targetPageType = 0; + /** + * @var string + */ + protected $language; + /** * @var bool */ @@ -293,6 +298,22 @@ class UriBuilder return $this; } + /** + * Enforces a URI / link to a page to a specific language (or use "current") + * @param string|null $language + * @return UriBuilder + */ + public function setLanguage(?string $language): UriBuilder + { + $this->language = $language; + return $this; + } + + public function getLanguage(): ?string + { + return $this->language; + } + /** * If set, the current query parameters will be merged with $this->arguments. Defaults to FALSE. * @@ -526,6 +547,7 @@ class UriBuilder $this->arguments = []; $this->section = ''; $this->format = ''; + $this->language = null; $this->createAbsoluteUri = false; $this->addQueryString = false; $this->addQueryStringMethod = ''; @@ -761,6 +783,10 @@ class UriBuilder $typolinkConfiguration['addQueryString.']['method'] = $this->addQueryStringMethod; } } + if ($this->language !== null) { + $typolinkConfiguration['language'] = $this->language; + } + if ($this->noCache === true) { $typolinkConfiguration['no_cache'] = 1; } diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Link/PageViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Link/PageViewHelper.php index c2986446222c0527daf527d5b1e576887771c768..ca1746a585c319377460d9b606fd5d14dba635d5 100644 --- a/typo3/sysext/fluid/Classes/ViewHelpers/Link/PageViewHelper.php +++ b/typo3/sysext/fluid/Classes/ViewHelpers/Link/PageViewHelper.php @@ -83,6 +83,7 @@ class PageViewHelper extends AbstractTagBasedViewHelper $this->registerArgument('pageUid', 'int', 'Target page. See TypoLink destination'); $this->registerArgument('pageType', 'int', 'Type of the target page. See typolink.parameter'); $this->registerArgument('noCache', 'bool', 'Set this to disable caching for the target page. You should not need this.'); + $this->registerArgument('language', 'string', 'link to a specific language - defaults to the current language, use a language ID or "current" to enforce a specific language', false, null); // @deprecated $this->registerArgument('noCacheHash', 'bool', 'Deprecated: Set this to suppress the cHash query parameter created by TypoLink. You should not need this.', false); $this->registerArgument('section', 'string', 'The anchor to be added to the URI'); @@ -106,6 +107,7 @@ class PageViewHelper extends AbstractTagBasedViewHelper $pageType = isset($this->arguments['pageType']) ? (int)$this->arguments['pageType'] : 0; $noCache = isset($this->arguments['noCache']) ? (bool)$this->arguments['noCache'] : false; $section = isset($this->arguments['section']) ? (string)$this->arguments['section'] : ''; + $language = $this->arguments['language'] ?? null; $linkAccessRestrictedPages = isset($this->arguments['linkAccessRestrictedPages']) ? (bool)$this->arguments['linkAccessRestrictedPages'] : false; $additionalParams = isset($this->arguments['additionalParams']) ? (array)$this->arguments['additionalParams'] : []; $absolute = isset($this->arguments['absolute']) ? (bool)$this->arguments['absolute'] : false; @@ -118,6 +120,7 @@ class PageViewHelper extends AbstractTagBasedViewHelper ->setTargetPageType($pageType) ->setNoCache($noCache) ->setSection($section) + ->setLanguage($language) ->setLinkAccessRestrictedPages($linkAccessRestrictedPages) ->setArguments($additionalParams) ->setCreateAbsoluteUri($absolute) diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php index ba163ac5987368397991abc1a7e1a4a7949733cd..4458beabc2faa83c58e8bccb1236061fa7aca331 100644 --- a/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php +++ b/typo3/sysext/fluid/Classes/ViewHelpers/Link/TypolinkViewHelper.php @@ -93,6 +93,7 @@ class TypolinkViewHelper extends AbstractViewHelper $this->registerArgument('target', 'string', '', false, ''); $this->registerArgument('class', 'string', '', false, ''); $this->registerArgument('title', 'string', '', false, ''); + $this->registerArgument('language', 'string', 'link to a specific language - defaults to the current language, use a language ID or "current" to enforce a specific language', false, null); $this->registerArgument('additionalParams', 'string', '', false, ''); $this->registerArgument('additionalAttributes', 'array', '', false, []); // @deprecated useCacheHash @@ -155,6 +156,9 @@ class TypolinkViewHelper extends AbstractViewHelper 'ATagParams' => $aTagParams, 'forceAbsoluteUrl' => $absolute, ]; + if (isset($arguments['language']) && $arguments['language'] !== null) { + $instructions['language'] = $arguments['language']; + } if ($addQueryString) { $instructions['addQueryString'] = $addQueryString; $instructions['addQueryString.'] = [ diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Uri/PageViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Uri/PageViewHelper.php index 7ee6ddcc3821ce13c49fcc84ebe5825525d40471..f08c83894068638f9ed8937c866373bc37fa5dee 100644 --- a/typo3/sysext/fluid/Classes/ViewHelpers/Uri/PageViewHelper.php +++ b/typo3/sysext/fluid/Classes/ViewHelpers/Uri/PageViewHelper.php @@ -73,6 +73,7 @@ class PageViewHelper extends AbstractViewHelper $this->registerArgument('additionalParams', 'array', 'query parameters to be attached to the resulting URI', false, []); $this->registerArgument('pageType', 'int', 'type of the target page. See typolink.parameter', false, 0); $this->registerArgument('noCache', 'bool', 'set this to disable caching for the target page. You should not need this.', false, false); + $this->registerArgument('language', 'string', 'link to a specific language - defaults to the current language, use a language ID or "current" to enforce a specific language', false, null); // @deprecated $this->registerArgument('noCacheHash', 'bool', 'Deprecated: Set this to suppress the cHash query parameter created by TypoLink. You should not need this.', false, null); $this->registerArgument('section', 'string', 'the anchor to be added to the URI', false, ''); @@ -99,6 +100,7 @@ class PageViewHelper extends AbstractViewHelper trigger_error('Using the argument "noCacheHash" in <f:uri.page> ViewHelper has no effect anymore. Remove the argument in your fluid template, as it will result in a fatal error.', E_USER_DEPRECATED); } $section = $arguments['section']; + $language = $arguments['language'] ?? null; $linkAccessRestrictedPages = $arguments['linkAccessRestrictedPages']; $absolute = $arguments['absolute']; $addQueryString = $arguments['addQueryString']; @@ -112,6 +114,7 @@ class PageViewHelper extends AbstractViewHelper ->setTargetPageType($pageType) ->setNoCache($noCache) ->setSection($section) + ->setLanguage($language) ->setLinkAccessRestrictedPages($linkAccessRestrictedPages) ->setArguments($additionalParams) ->setCreateAbsoluteUri($absolute) diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php index 7787e4a5a6b02ce1e66f34ccc21b813c31d64cbe..05537a48777186d7f24a83f10e614bc21a31c04a 100644 --- a/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php +++ b/typo3/sysext/fluid/Classes/ViewHelpers/Uri/TypolinkViewHelper.php @@ -67,6 +67,7 @@ class TypolinkViewHelper extends AbstractViewHelper { $this->registerArgument('parameter', 'string', 'stdWrap.typolink style parameter string', true); $this->registerArgument('additionalParams', 'string', 'stdWrap.typolink additionalParams', false, ''); + $this->registerArgument('language', 'string', 'link to a specific language - defaults to the current language, use a language ID or "current" to enforce a specific language', false, null); // @deprecated useCacheHash $this->registerArgument('useCacheHash', 'bool', 'Deprecated: You should not need this.', false); $this->registerArgument('addQueryString', 'bool', '', false, false); @@ -111,6 +112,9 @@ class TypolinkViewHelper extends AbstractViewHelper 'parameter' => $typoLinkParameter, 'forceAbsoluteUrl' => $absolute, ]; + if (isset($arguments['language']) && $arguments['language'] !== null) { + $instructions['language'] = $arguments['language']; + } if ($addQueryString) { $instructions['addQueryString'] = $addQueryString; $instructions['addQueryString.'] = [ diff --git a/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Link/PageViewHelperTest.php b/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Link/PageViewHelperTest.php index 3169d657839b553712bab1d413fd1d4ff763c069..0128e1f183e99c97e97f1a0e3b9dc1463aaa0df7 100644 --- a/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Link/PageViewHelperTest.php +++ b/typo3/sysext/fluid/Tests/Unit/ViewHelpers/Link/PageViewHelperTest.php @@ -50,6 +50,7 @@ class PageViewHelperTest extends ViewHelperBaseTestcase $this->uriBuilder->expects(self::any())->method('setSection')->willReturn($this->uriBuilder); $this->uriBuilder->expects(self::any())->method('setFormat')->willReturn($this->uriBuilder); $this->uriBuilder->expects(self::any())->method('setCreateAbsoluteUri')->willReturn($this->uriBuilder); + $this->uriBuilder->expects(self::any())->method('setLanguage')->willReturn($this->uriBuilder); $this->uriBuilder->expects(self::any())->method('setAddQueryString')->willReturn($this->uriBuilder); $this->uriBuilder->expects(self::any())->method('setArgumentsToBeExcludedFromQueryString')->willReturn($this->uriBuilder); $this->uriBuilder->expects(self::any())->method('setLinkAccessRestrictedPages')->willReturn($this->uriBuilder);