Skip to content

Commit

Permalink
[BUGFIX] Don't render hreflang tag for pages with canonical set
Browse files Browse the repository at this point in the history
When a canonical link is set in the page properties, this page
or translation should not get a hreflang link in frontend as this
might send conflicting signals to search engines.

Resolves: #89878
Releases: master, 10.4
Change-Id: I4a2fb81b474bf155ba0beca5dfa3948f36edf840
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67328
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Guido Schmechel <guido.schmechel@brandung.de>
Tested-by: Martin Kutschker <mkutschker-typo3@yahoo.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Guido Schmechel <guido.schmechel@brandung.de>
Reviewed-by: Martin Kutschker <mkutschker-typo3@yahoo.com>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
  • Loading branch information
haassie authored and georgringer committed Jan 20, 2021
1 parent dd3c52a commit 8dbb66e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 2 deletions.
39 changes: 37 additions & 2 deletions typo3/sysext/seo/Classes/HrefLang/HrefLangGenerator.php
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}
Expand Up @@ -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'}
Expand Up @@ -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' => ''],
];

Expand All @@ -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'),
]
);
Expand Down Expand Up @@ -160,6 +162,28 @@ public function checkHrefLangOutputDataProvider(): array
'<link rel="alternate" hreflang="" href="https://acme.com/nl/welkom"/>',
]
],
'English page with canonical' => [
'https://acme.com/contact',
[
'<link rel="alternate" hreflang="de-DE" href="https://acme.com/de/kontakt"/>',
'<link rel="alternate" hreflang="de-CH" href="https://acme.com/de-ch/kontakt"/>',
],
[
'<link rel="alternate" hreflang="en-US" href="https://acme.com/contact"/>',
'<link rel="alternate" hreflang="x-default" href="https://acme.com/contact"/>',
]
],
'Swiss german page with canonical' => [
'https://acme.com/de-ch/uber',
[
'<link rel="alternate" hreflang="en-US" href="https://acme.com/about"/>',
'<link rel="alternate" hreflang="x-default" href="https://acme.com/about"/>',
'<link rel="alternate" hreflang="de-DE" href="https://acme.com/de/uber"/>',
],
[
'<link rel="alternate" hreflang="de-CH" href="https://acme.com/de-ch/uber"/>',
]
],
];
}

Expand Down

0 comments on commit 8dbb66e

Please sign in to comment.