diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index 10f546dfd52e56c5b592c2f6eb8efb31767752e5..b007b5543885e095e8902cb0a225c9e62dacecca 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -9,6 +9,7 @@ use Drupal\content_translation\BundleTranslationSettingsInterface; use Drupal\content_translation\ContentTranslationManager; use Drupal\Core\Access\AccessResult; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\ContentEntityFormInterface; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityInterface; @@ -656,6 +657,7 @@ function content_translation_preprocess_language_content_settings_table(&$variab * Implements hook_page_attachments(). */ function content_translation_page_attachments(&$page) { + $cache = CacheableMetadata::createFromRenderArray($page); $route_match = \Drupal::routeMatch(); // If the current route has no parameters, return. @@ -673,6 +675,13 @@ function content_translation_page_attachments(&$page) { if ($entity instanceof ContentEntityInterface && $entity->hasLinkTemplate('canonical')) { // Current route represents a content entity. Build hreflang links. foreach ($entity->getTranslationLanguages() as $language) { + // Skip any translation that cannot be viewed. + $translation = $entity->getTranslation($language->getId()); + $access = $translation->access('view', NULL, TRUE); + $cache->addCacheableDependency($access); + if (!$access->isAllowed()) { + continue; + } $url = $entity->toUrl('canonical') ->setOption('language', $language) ->setAbsolute() @@ -688,6 +697,8 @@ function content_translation_page_attachments(&$page) { } } // Since entity was found, no need to iterate further. - return; + break; } + // Apply updated caching information. + $cache->applyTo($page); } diff --git a/core/modules/node/tests/src/Functional/NodeTranslationUITest.php b/core/modules/node/tests/src/Functional/NodeTranslationUITest.php index 5be412c332fed7138e5fb5226fb9574cfa1f8e83..d2decc4eadb5062c15795d5fefa8e0439a1292f1 100644 --- a/core/modules/node/tests/src/Functional/NodeTranslationUITest.php +++ b/core/modules/node/tests/src/Functional/NodeTranslationUITest.php @@ -371,7 +371,7 @@ public function testTranslationRendering() { $this->doTestTranslations('node/' . $node->id(), $values); // Test that the node page has the correct alternate hreflang links. - $this->doTestAlternateHreflangLinks($node->toUrl()); + $this->doTestAlternateHreflangLinks($node); } /** @@ -393,24 +393,35 @@ protected function doTestTranslations($path, array $values) { /** * Tests that the given path provides the correct alternate hreflang links. * - * @param \Drupal\Core\Url $url - * The path to be tested. + * @param \Drupal\node\Entity\Node $node + * The node to be tested. */ - protected function doTestAlternateHreflangLinks(Url $url) { + protected function doTestAlternateHreflangLinks(Node $node) { + $url = $node->toUrl(); $languages = $this->container->get('language_manager')->getLanguages(); $url->setAbsolute(); $urls = []; + $translations = []; foreach ($this->langcodes as $langcode) { $language_url = clone $url; $urls[$langcode] = $language_url->setOption('language', $languages[$langcode]); + $translations[$langcode] = $node->getTranslation($langcode); } foreach ($this->langcodes as $langcode) { - $this->drupalGet($urls[$langcode]); - foreach ($urls as $alternate_langcode => $language_url) { - // Retrieve desired link elements from the HTML head. - $links = $this->xpath('head/link[@rel = "alternate" and @href = :href and @hreflang = :hreflang]', - [':href' => $language_url->toString(), ':hreflang' => $alternate_langcode]); - $this->assert(isset($links[0]), new FormattableMarkup('The %langcode node translation has the correct alternate hreflang link for %alternate_langcode: %link.', ['%langcode' => $langcode, '%alternate_langcode' => $alternate_langcode, '%link' => $url->toString()])); + // Skip unpublished translations. + if ($translations[$langcode]->isPublished()) { + $this->drupalGet($urls[$langcode]); + foreach ($urls as $alternate_langcode => $language_url) { + // Retrieve desired link elements from the HTML head. + $links = $this->xpath('head/link[@rel = "alternate" and @href = :href and @hreflang = :hreflang]', + [':href' => $language_url->toString(), ':hreflang' => $alternate_langcode]); + if ($translations[$alternate_langcode]->isPublished()) { + $this->assert(isset($links[0]), new FormattableMarkup('The %langcode node translation has the correct alternate hreflang link for %alternate_langcode: %link.', ['%langcode' => $langcode, '%alternate_langcode' => $alternate_langcode, '%link' => $url->toString()])); + } + else { + $this->assertFalse(isset($links[0]), new FormattableMarkup('The %langcode node translation has an hreflang link for unpublished %alternate_langcode translation: %link.', ['%langcode' => $langcode, '%alternate_langcode' => $alternate_langcode, '%link' => $url->toString()])); + } + } } } }