3 namespace Drupal\language\Plugin\LanguageNegotiation;
5 use Drupal\Core\Language\LanguageInterface;
6 use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
7 use Drupal\Core\Render\BubbleableMetadata;
9 use Drupal\language\LanguageNegotiationMethodBase;
10 use Drupal\language\LanguageSwitcherInterface;
11 use Symfony\Component\HttpFoundation\Request;
14 * Identify language from a request/session parameter.
16 * @LanguageNegotiation(
17 * id = Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSession::METHOD_ID,
19 * name = @Translation("Session"),
20 * description = @Translation("Language from a request/session parameter."),
21 * config_route_name = "language.negotiation_session"
24 class LanguageNegotiationSession extends LanguageNegotiationMethodBase implements OutboundPathProcessorInterface, LanguageSwitcherInterface {
27 * Flag used to determine whether query rewriting is active.
31 protected $queryRewrite;
34 * The query parameter name to rewrite.
38 protected $queryParam;
41 * The query parameter value to be set.
45 protected $queryValue;
48 * The language negotiation method id.
50 const METHOD_ID = 'language-session';
55 public function getLangcode(Request $request = NULL) {
56 $config = $this->config->get('language.negotiation')->get('session');
57 $param = $config['parameter'];
58 $langcode = $request && $request->query->get($param) ? $request->query->get($param) : NULL;
59 if (!$langcode && isset($_SESSION[$param])) {
60 $langcode = $_SESSION[$param];
68 public function persist(LanguageInterface $language) {
69 // We need to update the session parameter with the request value only if we
70 // have an authenticated user.
71 $langcode = $language->getId();
72 if ($langcode && $this->languageManager) {
73 $languages = $this->languageManager->getLanguages();
74 if ($this->currentUser->isAuthenticated() && isset($languages[$langcode])) {
75 $config = $this->config->get('language.negotiation')->get('session');
76 $_SESSION[$config['parameter']] = $langcode;
84 public function processOutbound($path, &$options = [], Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
86 // The following values are not supposed to change during a single page
87 // request processing.
88 if (!isset($this->queryRewrite)) {
89 if ($this->currentUser->isAnonymous()) {
90 $languages = $this->languageManager->getLanguages();
91 $config = $this->config->get('language.negotiation')->get('session');
92 $this->queryParam = $config['parameter'];
93 $this->queryValue = $request->query->has($this->queryParam) ? $request->query->get($this->queryParam) : NULL;
94 $this->queryRewrite = isset($languages[$this->queryValue]);
97 $this->queryRewrite = FALSE;
101 // If the user is anonymous, the user language negotiation method is
102 // enabled, and the corresponding option has been set, we must preserve
103 // any explicit user language preference even with cookies disabled.
104 if ($this->queryRewrite) {
105 if (!isset($options['query'][$this->queryParam])) {
106 $options['query'][$this->queryParam] = $this->queryValue;
108 if ($bubbleable_metadata) {
109 // Cached URLs that have been processed by this outbound path
110 // processor must be:
112 // - invalidated when the language negotiation config changes, since
113 // another query parameter may be used to determine the language.
114 ->addCacheTags($this->config->get('language.negotiation')->getCacheTags())
115 // - varied by the configured query parameter.
116 ->addCacheContexts(['url.query_args:' . $this->queryParam]);
126 public function getLanguageSwitchLinks(Request $request, $type, Url $url) {
128 $config = $this->config->get('language.negotiation')->get('session');
129 $param = $config['parameter'];
130 $language_query = isset($_SESSION[$param]) ? $_SESSION[$param] : $this->languageManager->getCurrentLanguage($type)->getId();
132 parse_str($request->getQueryString(), $query);
134 foreach ($this->languageManager->getNativeLanguages() as $language) {
135 $langcode = $language->getId();
136 $links[$langcode] = [
137 // We need to clone the $url object to avoid using the same one for all
138 // links. When the links are rendered, options are set on the $url
139 // object, so if we use the same one, they would be set for all links.
141 'title' => $language->getName(),
142 'attributes' => ['class' => ['language-link']],
145 if ($language_query != $langcode) {
146 $links[$langcode]['query'][$param] = $langcode;
149 $links[$langcode]['attributes']['class'][] = 'session-active';