diff --git a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationSession.php b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationSession.php
index a1547c0..147b9da 100644
--- a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationSession.php
+++ b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationSession.php
@@ -116,6 +116,13 @@ public function processOutbound($path, &$options = array(), Request $request = N
         }
       }
     }
+
+    // To avoid page cache duplicates, remove the language query if the default
+    // language is set.
+    if ($this->currentUser->isAnonymous() && $cache && isset($options['query'][$this->queryParam]) && $options['query'][$this->queryParam] == $default) {
+      unset($options['query'][$this->queryParam]);
+    }
+
     return $path;
   }
 
@@ -138,12 +145,12 @@ public function getLanguageSwitchLinks(Request $request, $type, Url $url) {
         'attributes' => array('class' => array('language-link')),
         'query' => $query,
       );
-      if ($language_query != $langcode) {
-        $links[$langcode]['query'][$param] = $langcode;
-      }
-      else {
+      if ($langcode == $language_query) {
         $links[$langcode]['attributes']['class'][] = 'session-active';
       }
+      // Always set the language query parameter. It may be removed in
+      // LanguageNegotiationSession::processOutbound().
+      $links[$langcode]['query'][$param] = $langcode;
     }
 
     return $links;
