diff --git a/core/core.services.yml b/core/core.services.yml
index 5e2c9e3781..e141b4624c 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -797,7 +797,7 @@ services:
     arguments: ['@current_route_match']
   router.route_provider:
     class: Drupal\Core\Routing\RouteProvider
-    arguments: ['@database', '@state', '@path.current', '@cache.data', '@path_processor_manager', '@cache_tags.invalidator']
+    arguments: ['@database', '@state', '@path.current', '@cache.data', '@path_processor_manager', '@cache_tags.invalidator', 'router', '@language_manager']
     tags:
       - { name: event_subscriber }
       - { name: backend_overridable }
diff --git a/core/lib/Drupal/Core/Routing/RouteProvider.php b/core/lib/Drupal/Core/Routing/RouteProvider.php
index 6c20b1e474..a7873d4c0f 100644
--- a/core/lib/Drupal/Core/Routing/RouteProvider.php
+++ b/core/lib/Drupal/Core/Routing/RouteProvider.php
@@ -6,6 +6,8 @@
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Language\LanguageManagerInterface;
 use Drupal\Core\Path\CurrentPathStack;
 use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
 use Drupal\Core\State\StateInterface;
@@ -85,6 +87,13 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
    */
   protected $pathProcessor;
 
+  /**
+   * The language manager.
+   *
+   * @var \Drupal\Core\Language\LanguageManagerInterface
+   */
+  protected $languageManager;
+
   /**
    * Cache ID prefix used to load routes.
    */
@@ -107,8 +116,10 @@ class RouteProvider implements PreloadableRouteProviderInterface, PagedRouteProv
    *   The cache tag invalidator.
    * @param string $table
    *   (Optional) The table in the database to use for matching. Defaults to 'router'
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   *   (Optional) The language manager.
    */
-  public function __construct(Connection $connection, StateInterface $state, CurrentPathStack $current_path, CacheBackendInterface $cache_backend, InboundPathProcessorInterface $path_processor, CacheTagsInvalidatorInterface $cache_tag_invalidator, $table = 'router') {
+  public function __construct(Connection $connection, StateInterface $state, CurrentPathStack $current_path, CacheBackendInterface $cache_backend, InboundPathProcessorInterface $path_processor, CacheTagsInvalidatorInterface $cache_tag_invalidator, $table = 'router', LanguageManagerInterface $language_manager = NULL) {
     $this->connection = $connection;
     $this->state = $state;
     $this->currentPath = $current_path;
@@ -116,6 +127,7 @@ public function __construct(Connection $connection, StateInterface $state, Curre
     $this->cacheTagInvalidator = $cache_tag_invalidator;
     $this->pathProcessor = $path_processor;
     $this->tableName = $table;
+    $this->languageManager = $language_manager ?: \Drupal::languageManager();
   }
 
   /**
@@ -147,7 +159,8 @@ public function __construct(Connection $connection, StateInterface $state, Curre
   public function getRouteCollectionForRequest(Request $request) {
     // Cache both the system path as well as route parameters and matching
     // routes.
-    $cid = 'route:' . $request->getPathInfo() . ':' . $request->getQueryString();
+    $langcode = $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_URL)->getId();
+    $cid = 'route:' . $langcode . ':' . $request->getPathInfo() . ':' . $request->getQueryString();
     if ($cached = $this->cache->get($cid)) {
       $this->currentPath->setPath($cached->data['path'], $request);
       $request->query->replace($cached->data['query']);
diff --git a/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php b/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php
index 1303082c15..4bec5cafc1 100644
--- a/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php
+++ b/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php
@@ -410,6 +410,12 @@ public function testLanguageSessionSwitchLinks() {
     ];
     $this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings'));
 
+    // Also switch the language_url type to session, to test alias handling and
+    // route caching.
+    $this->config('language.types')
+      ->set('negotiation.language_url.enabled', ['language-session' => 0])
+      ->save();
+
     // Enable the language switching block.
     $this->drupalPlaceBlock('language_block:' . LanguageInterface::TYPE_INTERFACE, [
       'id' => 'test_language_block',
@@ -434,7 +440,7 @@ public function testLanguageSessionSwitchLinks() {
     // Click on the French link.
     $this->clickLink(t('French'));
     // There should be a query parameter to set the session language.
-    $this->assertUrl('user/2', ['query' => ['language' => 'fr']]);
+    $this->assertContains('user/2?language=fr', $this->getSession()->getCurrentUrl());
     // Click on the 'Home' Link.
     $this->clickLink(t('Home'));
     // There should be no query parameter.
@@ -443,6 +449,27 @@ public function testLanguageSessionSwitchLinks() {
     $this->clickLink(t('French'));
     // There should be no query parameter.
     $this->assertUrl('user/2');
+
+    // Create an alias for user/2 just for en, make sure that this is a 404
+    // on the french page exist in english, no matter which language is
+    // checked first.
+    \Drupal::service('path.alias_storage')->save('/user/2', '/user-page', 'en');
+
+    $this->drupalGet('user-page');
+    $this->assertSession()->statusCodeEquals(404);
+
+    $this->clickLink('English');
+    $this->drupalGet('user-page');
+    $this->assertSession()->statusCodeEquals(200);
+
+    // Clear cache and repeata the check, this time with english first.
+    $this->resetAll();
+    $this->drupalGet('user-page');
+    $this->assertSession()->statusCodeEquals(200);
+
+    $this->clickLink('French');
+    $this->drupalGet('user-page');
+    $this->assertSession()->statusCodeEquals(404);
   }
 
   /**
diff --git a/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php b/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php
index 674214bf0c..b7381b8cff 100644
--- a/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php
@@ -558,7 +558,7 @@ public function testRouteCaching() {
     $request = Request::create($path, 'GET');
     $provider->getRouteCollectionForRequest($request);
 
-    $cache = $this->cache->get('route:/path/add/one:');
+    $cache = $this->cache->get('route:en:/path/add/one:');
     $this->assertEqual('/path/add/one', $cache->data['path']);
     $this->assertEqual([], $cache->data['query']);
     $this->assertEqual(3, count($cache->data['routes']));
@@ -568,7 +568,7 @@ public function testRouteCaching() {
     $request = Request::create($path, 'GET');
     $provider->getRouteCollectionForRequest($request);
 
-    $cache = $this->cache->get('route:/path/add/one:foo=bar');
+    $cache = $this->cache->get('route:en:/path/add/one:foo=bar');
     $this->assertEqual('/path/add/one', $cache->data['path']);
     $this->assertEqual(['foo' => 'bar'], $cache->data['query']);
     $this->assertEqual(3, count($cache->data['routes']));
@@ -578,7 +578,7 @@ public function testRouteCaching() {
     $request = Request::create($path, 'GET');
     $provider->getRouteCollectionForRequest($request);
 
-    $cache = $this->cache->get('route:/path/1/one:');
+    $cache = $this->cache->get('route:en:/path/1/one:');
     $this->assertEqual('/path/1/one', $cache->data['path']);
     $this->assertEqual([], $cache->data['query']);
     $this->assertEqual(2, count($cache->data['routes']));
@@ -595,7 +595,7 @@ public function testRouteCaching() {
     $request = Request::create($path, 'GET');
     $provider->getRouteCollectionForRequest($request);
 
-    $cache = $this->cache->get('route:/path/add-one:');
+    $cache = $this->cache->get('route:en:/path/add-one:');
     $this->assertEqual('/path/add/one', $cache->data['path']);
     $this->assertEqual([], $cache->data['query']);
     $this->assertEqual(3, count($cache->data['routes']));
