diff --git a/typo3/sysext/seo/Classes/HrefLang/HrefLangGenerator.php b/typo3/sysext/seo/Classes/HrefLang/HrefLangGenerator.php
index fa86d0308096..646615454d6f 100644
--- a/typo3/sysext/seo/Classes/HrefLang/HrefLangGenerator.php
+++ b/typo3/sysext/seo/Classes/HrefLang/HrefLangGenerator.php
@@ -17,8 +17,14 @@
namespace TYPO3\CMS\Seo\HrefLang;
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\LanguageAspectFactory;
+use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Core\Http\Uri;
+use TYPO3\CMS\Core\Site\Entity\SiteInterface;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
use TYPO3\CMS\Frontend\DataProcessing\LanguageMenuProcessor;
@@ -60,16 +66,25 @@ public function __invoke(ModifyHrefLangTagsEvent $event): void
$languages = $this->languageMenuProcessor->process($this->cObj, [], [], []);
/** @var SiteLanguage $siteLanguage */
$siteLanguage = $event->getRequest()->getAttribute('language');
+ $pageId = (int)$this->getTypoScriptFrontendController()->id;
+
foreach ($languages['languagemenu'] as $language) {
if ($language['available'] === 1 && !empty($language['link']) && $language['hreflang']) {
+ $page = $this->getTranslatedPageRecord($pageId, $language['languageId'], $event->getRequest());
+ if (!empty($page['canonical_link'])) {
+ // do not set hreflang when canonical is set
+ continue;
+ }
+
$href = $this->getAbsoluteUrl($language['link'], $siteLanguage);
$hrefLangs[$language['hreflang']] = $href;
}
}
if (count($hrefLangs) > 1) {
- $href = $this->getAbsoluteUrl($languages['languagemenu'][0]['link'], $siteLanguage);
- $hrefLangs['x-default'] = $href;
+ if (array_key_exists($languages['languagemenu'][0]['hreflang'], $hrefLangs)) {
+ $hrefLangs['x-default'] = $hrefLangs[$languages['languagemenu'][0]['hreflang']];
+ }
}
$event->setHrefLangs($hrefLangs);
@@ -101,4 +116,24 @@ protected function getTypoScriptFrontendController(): TypoScriptFrontendControll
{
return $GLOBALS['TSFE'];
}
+
+ protected function getTranslatedPageRecord(int $pageId, int $languageId, ServerRequestInterface $request): array
+ {
+ $site = $request->getAttribute('site');
+ if (!$site instanceof SiteInterface) {
+ return $this->getTypoScriptFrontendController()->page;
+ }
+
+ $targetSiteLanguage = $site->getLanguageById($languageId);
+ $languageAspect = LanguageAspectFactory::createFromSiteLanguage($targetSiteLanguage);
+
+ $context = clone GeneralUtility::makeInstance(Context::class);
+ $context->setAspect('language', $languageAspect);
+
+ $pageRepository = GeneralUtility::makeInstance(PageRepository::class, $context);
+ if ($languageId > 0) {
+ return $pageRepository->getPageOverlay($pageId, $languageId);
+ }
+ return $pageRepository->getPage($pageId);
+ }
}
diff --git a/typo3/sysext/seo/Tests/Functional/Fixtures/HrefLangScenario.yml b/typo3/sysext/seo/Tests/Functional/Fixtures/HrefLangScenario.yml
index cacb83488890..0496f3962384 100644
--- a/typo3/sysext/seo/Tests/Functional/Fixtures/HrefLangScenario.yml
+++ b/typo3/sysext/seo/Tests/Functional/Fixtures/HrefLangScenario.yml
@@ -44,3 +44,11 @@ entities:
languageVariants:
- self: {id: 1101, title: 'DE: Willkommen', language: 1, slug: '/willkommen'}
- self: {id: 1102, title: 'NL: Welkom', language: 3, slug: '/welkom'}
+ - self: {id: 1200, title: 'EN: Contact', slug: '/contact', canonical_link: 'https://www.typo3.org'}
+ languageVariants:
+ - self: {id: 1201, title: 'DE: Kontakt', language: 1, slug: '/kontakt'}
+ - self: {id: 1202, title: 'DE-CH: Kontakt', language: 2, slug: '/kontakt'}
+ - self: {id: 1300, title: 'EN: About', slug: '/about'}
+ languageVariants:
+ - self: {id: 1301, title: 'DE: Uber', language: 1, slug: '/uber'}
+ - self: {id: 1302, title: 'DE-CH: Uber', language: 2, slug: '/uber', canonical_link: 'https://acme.com/de/uber'}
diff --git a/typo3/sysext/seo/Tests/Functional/HrefLang/HrefLangGeneratorTest.php b/typo3/sysext/seo/Tests/Functional/HrefLang/HrefLangGeneratorTest.php
index 3f6188c0921f..8275dbe960d1 100644
--- a/typo3/sysext/seo/Tests/Functional/HrefLang/HrefLangGeneratorTest.php
+++ b/typo3/sysext/seo/Tests/Functional/HrefLang/HrefLangGeneratorTest.php
@@ -43,6 +43,7 @@ class HrefLangGeneratorTest extends FunctionalTestCase
protected const LANGUAGE_PRESETS = [
'EN' => ['id' => 0, 'title' => 'English', 'locale' => 'en_US.UTF8', 'iso' => 'en', 'hrefLang' => 'en-US', 'direction' => ''],
'DE' => ['id' => 1, 'title' => 'German', 'locale' => 'de_DE.UTF8', 'iso' => 'de', 'hrefLang' => 'de-DE', 'direction' => ''],
+ 'DE-CH' => ['id' => 2, 'title' => 'Swiss German', 'locale' => 'de_CH.UTF8', 'iso' => 'de', 'hrefLang' => 'de-CH', 'direction' => ''],
'NL' => ['id' => 3, 'title' => 'Dutch', 'locale' => 'nl_NL.UTF8', 'iso' => 'nl', 'hrefLang' => '', 'direction' => ''],
];
@@ -68,6 +69,7 @@ protected function setUp(): void
[
$this->buildDefaultLanguageConfiguration('EN', '/'),
$this->buildLanguageConfiguration('DE', '/de'),
+ $this->buildLanguageConfiguration('DE-CH', '/de-ch'),
$this->buildLanguageConfiguration('NL', '/nl'),
]
);
@@ -160,6 +162,28 @@ public function checkHrefLangOutputDataProvider(): array
'',
]
],
+ 'English page with canonical' => [
+ 'https://acme.com/contact',
+ [
+ '',
+ '',
+ ],
+ [
+ '',
+ '',
+ ]
+ ],
+ 'Swiss german page with canonical' => [
+ 'https://acme.com/de-ch/uber',
+ [
+ '',
+ '',
+ '',
+ ],
+ [
+ '',
+ ]
+ ],
];
}