Chris@0: languageManager) { Chris@0: $languages = $this->languageManager->getLanguages(); Chris@0: $config = $this->config->get('language.negotiation')->get('url'); Chris@0: Chris@0: switch ($config['source']) { Chris@0: case LanguageNegotiationUrl::CONFIG_PATH_PREFIX: Chris@0: $request_path = urldecode(trim($request->getPathInfo(), '/')); Chris@0: $path_args = explode('/', $request_path); Chris@0: $prefix = array_shift($path_args); Chris@0: Chris@0: // Search prefix within added languages. Chris@0: $negotiated_language = FALSE; Chris@0: foreach ($languages as $language) { Chris@0: if (isset($config['prefixes'][$language->getId()]) && $config['prefixes'][$language->getId()] == $prefix) { Chris@0: $negotiated_language = $language; Chris@0: break; Chris@0: } Chris@0: } Chris@0: Chris@0: if ($negotiated_language) { Chris@0: $langcode = $negotiated_language->getId(); Chris@0: } Chris@0: break; Chris@0: Chris@0: case LanguageNegotiationUrl::CONFIG_DOMAIN: Chris@0: // Get only the host, not the port. Chris@0: $http_host = $request->getHost(); Chris@0: foreach ($languages as $language) { Chris@0: // Skip the check if the language doesn't have a domain. Chris@0: if (!empty($config['domains'][$language->getId()])) { Chris@0: // Ensure that there is exactly one protocol in the URL when Chris@0: // checking the hostname. Chris@0: $host = 'http://' . str_replace(['http://', 'https://'], '', $config['domains'][$language->getId()]); Chris@0: $host = parse_url($host, PHP_URL_HOST); Chris@0: if ($http_host == $host) { Chris@0: $langcode = $language->getId(); Chris@0: break; Chris@0: } Chris@0: } Chris@0: } Chris@0: break; Chris@0: } Chris@0: } Chris@0: Chris@0: return $langcode; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function processInbound($path, Request $request) { Chris@0: $config = $this->config->get('language.negotiation')->get('url'); Chris@0: Chris@0: if ($config['source'] == LanguageNegotiationUrl::CONFIG_PATH_PREFIX) { Chris@0: $parts = explode('/', trim($path, '/')); Chris@0: $prefix = array_shift($parts); Chris@0: Chris@0: // Search prefix within added languages. Chris@0: foreach ($this->languageManager->getLanguages() as $language) { Chris@0: if (isset($config['prefixes'][$language->getId()]) && $config['prefixes'][$language->getId()] == $prefix) { Chris@0: // Rebuild $path with the language removed. Chris@0: $path = '/' . implode('/', $parts); Chris@0: break; Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: return $path; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) { Chris@0: $url_scheme = 'http'; Chris@0: $port = 80; Chris@0: if ($request) { Chris@0: $url_scheme = $request->getScheme(); Chris@0: $port = $request->getPort(); Chris@0: } Chris@0: $languages = array_flip(array_keys($this->languageManager->getLanguages())); Chris@0: // Language can be passed as an option, or we go for current URL language. Chris@0: if (!isset($options['language'])) { Chris@0: $language_url = $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_URL); Chris@0: $options['language'] = $language_url; Chris@0: } Chris@0: // We allow only added languages here. Chris@0: elseif (!is_object($options['language']) || !isset($languages[$options['language']->getId()])) { Chris@0: return $path; Chris@0: } Chris@0: $config = $this->config->get('language.negotiation')->get('url'); Chris@0: if ($config['source'] == LanguageNegotiationUrl::CONFIG_PATH_PREFIX) { Chris@0: if (is_object($options['language']) && !empty($config['prefixes'][$options['language']->getId()])) { Chris@0: $options['prefix'] = $config['prefixes'][$options['language']->getId()] . '/'; Chris@0: if ($bubbleable_metadata) { Chris@0: $bubbleable_metadata->addCacheContexts(['languages:' . LanguageInterface::TYPE_URL]); Chris@0: } Chris@0: } Chris@0: } Chris@0: elseif ($config['source'] == LanguageNegotiationUrl::CONFIG_DOMAIN) { Chris@0: if (is_object($options['language']) && !empty($config['domains'][$options['language']->getId()])) { Chris@0: Chris@0: // Save the original base URL. If it contains a port, we need to Chris@0: // retain it below. Chris@0: if (!empty($options['base_url'])) { Chris@0: // The colon in the URL scheme messes up the port checking below. Chris@0: $normalized_base_url = str_replace(['https://', 'http://'], '', $options['base_url']); Chris@0: } Chris@0: Chris@0: // Ask for an absolute URL with our modified base URL. Chris@0: $options['absolute'] = TRUE; Chris@0: $options['base_url'] = $url_scheme . '://' . $config['domains'][$options['language']->getId()]; Chris@0: Chris@0: // In case either the original base URL or the HTTP host contains a Chris@0: // port, retain it. Chris@0: if (isset($normalized_base_url) && strpos($normalized_base_url, ':') !== FALSE) { Chris@0: list(, $port) = explode(':', $normalized_base_url); Chris@0: $options['base_url'] .= ':' . $port; Chris@0: } Chris@0: elseif (($url_scheme == 'http' && $port != 80) || ($url_scheme == 'https' && $port != 443)) { Chris@0: $options['base_url'] .= ':' . $port; Chris@0: } Chris@0: Chris@0: if (isset($options['https'])) { Chris@0: if ($options['https'] === TRUE) { Chris@0: $options['base_url'] = str_replace('http://', 'https://', $options['base_url']); Chris@0: } Chris@0: elseif ($options['https'] === FALSE) { Chris@0: $options['base_url'] = str_replace('https://', 'http://', $options['base_url']); Chris@0: } Chris@0: } Chris@0: Chris@0: // Add Drupal's subfolder from the base_path if there is one. Chris@0: $options['base_url'] .= rtrim(base_path(), '/'); Chris@0: if ($bubbleable_metadata) { Chris@0: $bubbleable_metadata->addCacheContexts(['languages:' . LanguageInterface::TYPE_URL, 'url.site']); Chris@0: } Chris@0: } Chris@0: } Chris@0: return $path; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getLanguageSwitchLinks(Request $request, $type, Url $url) { Chris@0: $links = []; Chris@0: $query = $request->query->all(); Chris@0: Chris@0: foreach ($this->languageManager->getNativeLanguages() as $language) { Chris@0: $links[$language->getId()] = [ Chris@0: // We need to clone the $url object to avoid using the same one for all Chris@0: // links. When the links are rendered, options are set on the $url Chris@0: // object, so if we use the same one, they would be set for all links. Chris@0: 'url' => clone $url, Chris@0: 'title' => $language->getName(), Chris@0: 'language' => $language, Chris@0: 'attributes' => ['class' => ['language-link']], Chris@0: 'query' => $query, Chris@0: ]; Chris@0: } Chris@0: Chris@0: return $links; Chris@0: } Chris@0: Chris@0: }