diff --git a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationContentEntity.php b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationContentEntity.php index b78dbb9e40..d8fa552267 100644 --- a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationContentEntity.php +++ b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationContentEntity.php @@ -4,6 +4,7 @@ use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Language\LanguageInterface; use Drupal\Core\PathProcessor\OutboundPathProcessorInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Render\BubbleableMetadata; @@ -110,9 +111,19 @@ public function processOutbound($path, &$options = [], Request $request = NULL, } if (isset($options['language']) || $langcode = $this->getLangcode($request)) { - // If the language option is set, unset it, so that the url language - // negotiator does not rewrite the url. - if (isset($options['language'])) { + // If the url comes from an interface language switcher, leave + // $options['language'] alone so that the interface language can be + // changed, and use the entity language in the query string. + if (isset($options['language_switch_link_type']) && $options['language_switch_link_type'] == LanguageInterface::TYPE_INTERFACE) { + // Language switch URLs refer to the current entity so using + // $request here is fine. + $content_entity_id = $this->getContentEntityTypeIdForCurrentRequest($request); + $langcode = $request->attributes->get($content_entity_id)->language()->getId(); + } + // Otherwise, unset $options['language'] in order to preserve the + // current prefix in the url, and only allow to change the content + // language. + elseif (isset($options['language'])) { $langcode = $options['language']->getId(); unset($options['language']); } diff --git a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php index 7436a3f3a0..5fc0bf20d6 100644 --- a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php +++ b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php @@ -198,11 +198,20 @@ public function getLanguageSwitchLinks(Request $request, $type, Url $url) { $query = $request->query->all(); foreach ($this->languageManager->getNativeLanguages() as $language) { + // We need to clone the $url object to avoid using the same one for all + // links. When the links are rendered, options are set on the $url + // object, so if we use the same one, they would be set for all links. + $url_copy = clone $url; + + // And we need to mark the links is some way, so that other language + // negotiators know that these URLs should not be changed. + $url_copy->setOption('language_switch_link_type', $type); + $links[$language->getId()] = [ // We need to clone the $url object to avoid using the same one for all // links. When the links are rendered, options are set on the $url // object, so if we use the same one, they would be set for all links. - 'url' => clone $url, + 'url' => $url_copy, 'title' => $language->getName(), 'language' => $language, 'attributes' => ['class' => ['language-link']],