diff --git a/core/modules/toolbar/js/views/ToolbarVisualView.js b/core/modules/toolbar/js/views/ToolbarVisualView.js
index 2b6071ee47b6d52564ef28048beb3782af34211e..62908e0e552d96d69c61dc2ae66ce55b193cec7a 100644
--- a/core/modules/toolbar/js/views/ToolbarVisualView.js
+++ b/core/modules/toolbar/js/views/ToolbarVisualView.js
@@ -248,7 +248,8 @@
       //   (3) The orientation of the tray is vertical.
       if (!this.model.get('areSubtreesLoaded') && $activeTab.data('drupal-subtrees') !== undefined && orientation === 'vertical') {
         var subtreesHash = drupalSettings.toolbar.subtreesHash;
-        var endpoint = Drupal.url('toolbar/subtrees/' + subtreesHash);
+        var langcode = drupalSettings.toolbar.langcode;
+        var endpoint = Drupal.url('toolbar/subtrees/' + subtreesHash + '/' + langcode);
         var cachedSubtreesHash = localStorage.getItem('Drupal.toolbar.subtreesHash');
         var cachedSubtrees = JSON.parse(localStorage.getItem('Drupal.toolbar.subtrees'));
         var isVertical = this.model.get('orientation') === 'vertical';
diff --git a/core/modules/toolbar/lib/Drupal/toolbar/Controller/ToolbarController.php b/core/modules/toolbar/lib/Drupal/toolbar/Controller/ToolbarController.php
index d5fc878caf7583e6ea931a57a483c475026ad1d2..11d17b4c59fbe76fbf5f09ee07f683d0dedf8afb 100644
--- a/core/modules/toolbar/lib/Drupal/toolbar/Controller/ToolbarController.php
+++ b/core/modules/toolbar/lib/Drupal/toolbar/Controller/ToolbarController.php
@@ -32,10 +32,19 @@ public function subtreesJsonp() {
 
   /**
    * Checks access for the subtree controller.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The current request.
+   * @param string $langcode
+   *   The langcode of the requested site, NULL if none given.
+   *
+   * @return string
+   *   Returns AccessInterface::ALLOW when access was granted, otherwise
+   *   AccessInterface::DENY.
    */
-  public function checkSubTreeAccess(Request $request) {
+  public function checkSubTreeAccess(Request $request, $langcode) {
     $hash = $request->get('hash');
-    return ($this->currentUser()->hasPermission('access toolbar') && ($hash == _toolbar_get_subtrees_hash())) ? AccessInterface::ALLOW : AccessInterface::DENY;
+    return ($this->currentUser()->hasPermission('access toolbar') && ($hash == _toolbar_get_subtrees_hash($langcode))) ? AccessInterface::ALLOW : AccessInterface::DENY;
   }
 
 }
diff --git a/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php b/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php
index 082a6a7e2facbafda62377be5e7da854d4784e5d..01f043e60ba0a6b1fbff11ba73c335285c1ebbbf 100644
--- a/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php
+++ b/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php
@@ -452,6 +452,55 @@ function testSubtreesJsonRequest() {
 
     $this->drupalGetJSON('toolbar/subtrees/' . $subtrees_hash);
     $this->assertResponse('200');
+
+    // Test that the subtrees hash changes with a different language code and
+    // that JSON is returned when a language code is specified.
+    // Create a new language with the langcode 'xx'.
+    $langcode = 'xx';
+    // The English name for the language. This will be translated.
+    $name = $this->randomName(16);
+    $edit = array(
+      'predefined_langcode' => 'custom',
+      'langcode' => $langcode,
+      'name' => $name,
+      'direction' => '0',
+    );
+    $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
+
+    // Get a page with the new language langcode in the URL.
+    $this->drupalGet('/xx/test-page');
+    // Request a new page to refresh the drupalSettings object.
+    $subtrees_hash = $this->getSubtreesHash();
+
+    $this->drupalGetJSON('toolbar/subtrees/' . $subtrees_hash . '/' . $langcode);
+    $this->assertResponse('200');
+  }
+
+  /**
+   *  Test that subtrees hashes vary by the language of the page.
+   */
+  function testLanguageSwitching() {
+    // Create a new language with the langcode 'xx'.
+    $langcode = 'xx';
+    // The English name for the language. This will be translated.
+    $name = $this->randomName(16);
+    $edit = array(
+      'predefined_langcode' => 'custom',
+      'langcode' => $langcode,
+      'name' => $name,
+      'direction' => '0',
+    );
+    $this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
+
+    // Get a page with the new language langcode in the URL.
+    $this->drupalGet('/xx/test-page');
+    // Assert different hash.
+    $new_subtree_hash = $this->getSubtreesHash();
+
+    // Assert that the old admin menu subtree hash and the new admin menu
+    // subtree hash are different.
+    $this->assertTrue($new_subtree_hash, 'A valid hash value for the admin menu subtrees was created.');
+    $this->assertNotEqual($this->hash, $new_subtree_hash, 'The user-specific subtree menu hash has been updated.');
   }
 
   /**
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index 6e3e4e3e44140a871e300785501bff91398e0bd1..0f58cb277aef11911cb7d40bc4dbb35e15367401 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -378,10 +378,12 @@ function toolbar_toolbar() {
   // toolbar_subtrees route. We provide the JavaScript requesting that JSONP
   // script here with the hash parameter that is needed for that route.
   // @see toolbar_subtrees_jsonp()
+  $langcode = \Drupal::languageManager()->getCurrentLanguage()->id;
   $menu['toolbar_administration']['#attached']['js'][] = array(
     'type' => 'setting',
     'data' => array('toolbar' => array(
-      'subtreesHash' => _toolbar_get_subtrees_hash(),
+      'subtreesHash' => _toolbar_get_subtrees_hash($langcode),
+      'langcode' => $langcode,
     )),
   );
 
@@ -503,12 +505,15 @@ function toolbar_get_rendered_subtrees() {
 /**
  * Returns the hash of the per-user rendered toolbar subtrees.
  *
+ * @param string $langcode
+ *   The langcode of the current request.
+ *
  * @return string
  *   The hash of the admin_menu subtrees.
  */
-function _toolbar_get_subtrees_hash() {
+function _toolbar_get_subtrees_hash($langcode) {
   $uid = \Drupal::currentUser()->id();
-  $cid = _toolbar_get_user_cid($uid);
+  $cid = _toolbar_get_user_cid($uid, $langcode);
   if ($cache = \Drupal::cache('toolbar')->get($cid)) {
     $hash = $cache->data;
   }
@@ -566,12 +571,14 @@ function toolbar_user_role_update(RoleInterface $role) {
  *
  * @param int $uid
  *   A user ID.
+ * @param string $langcode
+ *   The langcode of the current request.
  *
  * @return string
  *   A unique cache ID for the user.
  */
-function _toolbar_get_user_cid($uid) {
-  return 'toolbar_' . $uid . ':' . \Drupal::languageManager()->getCurrentLanguage()->id;
+function _toolbar_get_user_cid($uid, $langcode) {
+  return 'toolbar_' . $uid . ':' . $langcode;
 }
 
 /**
diff --git a/core/modules/toolbar/toolbar.routing.yml b/core/modules/toolbar/toolbar.routing.yml
index 6e2f2559bb31c2cb1222c8bfc0b197b61388d253..4cb014e53c56092f4144460a09061f0735ccedb1 100644
--- a/core/modules/toolbar/toolbar.routing.yml
+++ b/core/modules/toolbar/toolbar.routing.yml
@@ -1,6 +1,7 @@
 toolbar.subtrees:
-  path: '/toolbar/subtrees/{hash}'
+  path: '/toolbar/subtrees/{hash}/{langcode}'
   defaults:
     _controller: '\Drupal\toolbar\Controller\ToolbarController::subtreesJsonp'
+    langcode: null
   requirements:
     _custom_access: '\Drupal\toolbar\Controller\ToolbarController::checkSubTreeAccess'