diff --git a/core/modules/language/js/language.switcher.js b/core/modules/language/js/language.switcher.js
new file mode 100644
index 0000000..a7ed73a
--- /dev/null
+++ b/core/modules/language/js/language.switcher.js
@@ -0,0 +1,24 @@
+/**
+ * @file
+ * Attaches behaviors for the Language switch block.
+ */
+
+(function ($, Drupal, drupalSettings, _, Backbone, JSON, storage) {
+
+  "use strict";
+
+  Drupal.behaviors.language_switcher = {
+    attach: function (context) {
+      var $context = $(context);
+
+      // Set the destination parameter on each of the contextual links.
+      var destination = 'destination=' + Drupal.encodePath(drupalSettings.path.currentPath);
+      $context.find('.language-switcher a').each(function () {
+        var url = this.getAttribute('href');
+        var glue = (url.indexOf('?') === -1) ? '?' : '&';
+        this.setAttribute('href', url + glue + destination);
+      });
+    }
+  }
+
+})(jQuery, Drupal, drupalSettings, _, Backbone, window.JSON, window.sessionStorage);
diff --git a/core/modules/language/language.routing.yml b/core/modules/language/language.routing.yml
index 4d78d6d..a9c0c16 100644
--- a/core/modules/language/language.routing.yml
+++ b/core/modules/language/language.routing.yml
@@ -85,3 +85,10 @@ language.content_settings_page:
     _form: 'Drupal\language\Form\ContentLanguageSettingsForm'
   requirements:
     _permission: 'administer languages'
+
+language.redirect:
+  path: '/language-redirect'
+  defaults:
+    _controller: '\Drupal\language\Controller\LanguageRedirectController::redirect'
+  requirements:
+    _access: 'TRUE'
diff --git a/core/modules/language/src/Controller/LanguageRedirectController.php b/core/modules/language/src/Controller/LanguageRedirectController.php
new file mode 100644
index 0000000..f961cb6
--- /dev/null
+++ b/core/modules/language/src/Controller/LanguageRedirectController.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\LanguageRedirectController
+ */
+
+namespace Drupal\language\Controller;
+
+use Symfony\Component\DependencyInjection\ContainerAwareTrait;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Defines a controller to redirect users to the given page in that language.
+ */
+class LanguageRedirectController {
+
+  public function redirect(Request $request) {
+    $destination = $request->query->get('destination');
+    if (!isset($destination)) {
+      $destination = "";
+    }
+    return new RedirectResponse($destination, 301);
+  }
+
+
+}
diff --git a/core/modules/language/src/Plugin/Block/LanguageBlock.php b/core/modules/language/src/Plugin/Block/LanguageBlock.php
index a3aba84..dc7dc63 100644
--- a/core/modules/language/src/Plugin/Block/LanguageBlock.php
+++ b/core/modules/language/src/Plugin/Block/LanguageBlock.php
@@ -8,6 +8,7 @@
 namespace Drupal\language\Plugin\Block;
 
 use Drupal\Core\Block\BlockBase;
+use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Language\LanguageManagerInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
@@ -33,6 +34,13 @@ class LanguageBlock extends BlockBase implements ContainerFactoryPluginInterface
   protected $languageManager;
 
   /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $currentUser;
+
+  /**
    * Constructs an LanguageBlock object.
    *
    * @param array $configuration
@@ -43,10 +51,13 @@ class LanguageBlock extends BlockBase implements ContainerFactoryPluginInterface
    *   The plugin implementation definition.
    * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
    *   The language manager.
+   * @param \Drupal\Core\Session\AccountInterface $current_user
+   *   The current user.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, LanguageManagerInterface $language_manager) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, LanguageManagerInterface $language_manager, AccountInterface $current_user) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
     $this->languageManager = $language_manager;
+    $this->currentUser = $current_user;
   }
 
 
@@ -58,7 +69,8 @@ public static function create(ContainerInterface $container, array $configuratio
       $configuration,
       $plugin_id,
       $plugin_definition,
-      $container->get('language_manager')
+      $container->get('language_manager'),
+      $container->get('current_user')
     );
   }
 
@@ -75,17 +87,28 @@ protected function blockAccess(AccountInterface $account) {
    */
   public function build() {
     $build = array();
-    $path = drupal_is_front_page() ? '<front>' : current_path();
+    if ($this->currentUser->isAnonymous()) {
+      $path = drupal_is_front_page() ? '<front>' : current_path();
+    }
+    else {
+      $path = NULL;
+      $build['#attached'] = array(
+        'js' => array(
+          drupal_get_path('module', 'language') . DIRECTORY_SEPARATOR . 'js' . DIRECTORY_SEPARATOR . 'language.switcher.js',
+        ),
+      );
+    }
     $type = $this->getDerivativeId();
     $links = $this->languageManager->getLanguageSwitchLinks($type, $path);
 
     if (isset($links->links)) {
-      $build = array(
+      $build += array(
         '#theme' => 'links__language_block',
         '#links' => $links->links,
         '#attributes' => array(
           'class' => array(
             "language-switcher-{$links->method_id}",
+            "language-switcher"
           ),
         ),
         '#set_active_class' => TRUE,
@@ -94,4 +117,40 @@ public function build() {
     return $build;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultConfiguration() {
+    // @todo Ensure whenever language settings change, that appropriate cache
+    //   tags are invalidated, that allows us to cache this block forever.
+    return array('cache' => array('max_age' => \Drupal\Core\Cache\Cache::PERMANENT));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getRequiredCacheContexts() {
+    // The 'Language switcher' block must be cached per role: for anonymous
+    // users and non-anonymous users. For anonymous users, we render the final
+    // HTML, because we assume that page caching is enabled for anonymous users.
+    // For non-anymous users, we render language links that point to a generic
+    // language redirection route, with attached JavaScript that sets the
+    // 'destination' query string on those URLs. That way, we can cache one
+    // entry for all
+    // @todo Create this new is_anonymous cache context.
+    return array('cache_context.user.is_anonymous');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isCacheable() {
+    if ($this->currentUser->isAnonymous()) {
+      return FALSE;
+    }
+    else {
+      return parent::isCacheable();
+    }
+  }
+
 }
diff --git a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationSession.php b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationSession.php
index dc5617d..da5e926 100644
--- a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationSession.php
+++ b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationSession.php
@@ -143,6 +143,11 @@ function getLanguageSwitchLinks(Request $request, $type, $path) {
       else {
         $links[$langcode]['attributes']['class'][] = 'session-active';
       }
+
+      // No path given, add it later by JS.
+      if (!isset($path)) {
+        $links[$language->id]['route_name'] = 'language.redirect';
+      }
     }
 
     return $links;
diff --git a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php
index be9f915..6879395 100644
--- a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php
+++ b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php
@@ -197,6 +197,11 @@ function getLanguageSwitchLinks(Request $request, $type, $path) {
         'language' => $language,
         'attributes' => array('class' => array('language-link')),
       );
+
+      // No path given, add it later by JS.
+      if (!isset($path)) {
+        $links[$language->id]['route_name'] = 'language.redirect';
+      }
     }
 
     return $links;
