diff --git a/core/core.services.yml b/core/core.services.yml
index 021ac1a..ceabcfb 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -5,6 +5,15 @@ parameters:
     default: keyvalue.database
   factory.keyvalue.expirable:
     default: keyvalue.expirable.database
+  # All the 'language.*' parameters must be overridden by the module providing
+  # the default language manager. They are necessary for allowing services to be
+  # language-aware in an efficient manner.
+  # @see \Drupal\language\LanguageServiceProvider::alter()
+  # @see \Drupal\Core\DrupalKernel::compileContainer()
+  language.default_values: []
+  language.is_multilingual: false
+  language.supported_langcodes: []
+  language.langcode_mappings: {}
 services:
   cache_factory:
     class: Drupal\Core\Cache\CacheFactory
@@ -465,11 +474,6 @@ services:
     arguments: ['@settings']
     tags:
       - { name: http_middleware, priority: 300 }
-  http_middleware.page_cache:
-    class: Drupal\Core\StackMiddleware\PageCache
-    arguments: ['@cache.render', '@page_cache_request_policy', '@page_cache_response_policy', '@content_negotiation']
-    tags:
-      - { name: http_middleware, priority: 200 }
   http_middleware.kernel_pre_handle:
     class: Drupal\Core\StackMiddleware\KernelPreHandle
     arguments: ['@kernel']
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index bc36c15..da25e14 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -980,6 +980,24 @@ protected function compileContainer() {
     }
     $container->setParameter('container.namespaces', $namespaces);
 
+    // Register synthetic services.
+    $container->register('class_loader')->setSynthetic(TRUE);
+    $container->register('kernel', 'Symfony\Component\HttpKernel\KernelInterface')->setSynthetic(TRUE);
+    $container->register('service_container', 'Symfony\Component\DependencyInjection\ContainerInterface')->setSynthetic(TRUE);
+
+    // Register declarative application services first, then set the default
+    // language values container parameter, and then register the application
+    // services defined in service providers.
+    // This particular order allows:
+    // - the declarative application services to document all container;
+    //   parameters
+    // - the application service providers to override all container parameters;
+    // - while still performing the low-level initialization of the default
+    //   language values container parameter.
+    $yaml_loader = new YamlFileLoader($container);
+    foreach ($this->serviceYamls['app'] as $filename) {
+      $yaml_loader->load($filename);
+    }
     // Store the default language values on the container. This is so that the
     // default language can be configured using the configuration factory. This
     // avoids the circular dependencies that would created by
@@ -992,17 +1010,6 @@ protected function compileContainer() {
       }
     }
     $container->setParameter('language.default_values', $default_language_values);
-
-    // Register synthetic services.
-    $container->register('class_loader')->setSynthetic(TRUE);
-    $container->register('kernel', 'Symfony\Component\HttpKernel\KernelInterface')->setSynthetic(TRUE);
-    $container->register('service_container', 'Symfony\Component\DependencyInjection\ContainerInterface')->setSynthetic(TRUE);
-
-    // Register application services.
-    $yaml_loader = new YamlFileLoader($container);
-    foreach ($this->serviceYamls['app'] as $filename) {
-      $yaml_loader->load($filename);
-    }
     foreach ($this->serviceProviders['app'] as $provider) {
       if ($provider instanceof ServiceProviderInterface) {
         $provider->register($container);
diff --git a/core/lib/Drupal/Core/Form/FormCache.php b/core/lib/Drupal/Core/Form/FormCache.php
index ea38fd2..fa03bac 100644
--- a/core/lib/Drupal/Core/Form/FormCache.php
+++ b/core/lib/Drupal/Core/Form/FormCache.php
@@ -210,11 +210,6 @@ public function setCache($form_build_id, $form, FormStateInterface $form_state)
       $this->keyValueExpirableFactory->get('form')->setWithExpire($form_build_id, $form, $expire);
     }
 
-    // Cache form state.
-    if ($this->configFactory->get('system.performance')->get('cache.page.use_internal') && $this->isPageCacheable()) {
-      $form_state->addBuildInfo('immutable', TRUE);
-    }
-
     // Store the known list of safe strings for form re-use.
     // @todo Ensure we are not storing an excessively large string list in:
     //   https://www.drupal.org/node/2295823
@@ -225,14 +220,4 @@ public function setCache($form_build_id, $form, FormStateInterface $form_state)
     }
   }
 
-  /**
-   * Checks if the page is cacheable.
-   *
-   * @return bool
-   *   TRUE is the page is cacheable, FALSE if not.
-   */
-  protected function isPageCacheable() {
-    return ($this->requestPolicy->check($this->requestStack->getCurrentRequest()) === RequestPolicyInterface::ALLOW);
-  }
-
 }
diff --git a/core/modules/block/src/Tests/BlockTest.php b/core/modules/block/src/Tests/BlockTest.php
index 197a370..1ff3946 100644
--- a/core/modules/block/src/Tests/BlockTest.php
+++ b/core/modules/block/src/Tests/BlockTest.php
@@ -21,6 +21,11 @@
 class BlockTest extends BlockTestBase {
 
   /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['page_cache'];
+
+  /**
    * Tests block visibility.
    */
   function testBlockVisibility() {
@@ -308,7 +313,6 @@ public function testBlockCacheTags() {
 
     // Enable page caching.
     $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
     $config->set('cache.page.max_age', 300);
     $config->save();
 
diff --git a/core/modules/block/src/Tests/BlockTestBase.php b/core/modules/block/src/Tests/BlockTestBase.php
index 1f3cb74..307a435 100644
--- a/core/modules/block/src/Tests/BlockTestBase.php
+++ b/core/modules/block/src/Tests/BlockTestBase.php
@@ -19,7 +19,7 @@
    *
    * @var array
    */
-  public static $modules = array('block', 'filter', 'test_page_test', 'help', 'block_test');
+  protected static $modules = array('block', 'filter', 'test_page_test', 'help', 'block_test');
 
   /**
    * A list of theme regions to test.
diff --git a/core/modules/file/src/Tests/DownloadTest.php b/core/modules/file/src/Tests/DownloadTest.php
index 9de1b3a..4df65e5 100644
--- a/core/modules/file/src/Tests/DownloadTest.php
+++ b/core/modules/file/src/Tests/DownloadTest.php
@@ -56,8 +56,8 @@ public function testPrivateFileTransferWithoutPageCache() {
    */
   public function testPrivateFileTransferWithPageCache() {
     // Turn on page caching and rerun the test.
+    $this->container->get('module_installer')->install(['page_cache']);
     $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
     $config->set('cache.page.max_age', 300);
     $config->save();
 
diff --git a/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php b/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php
index abe8ffb..88cf620 100644
--- a/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php
+++ b/core/modules/image/src/Tests/ImageStylesPathAndUrlTest.php
@@ -247,8 +247,8 @@ function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_slash =
    */
   protected function enablePageCache() {
     // Turn on page caching and rerun the test.
+    $this->container->get('module_installer')->install(['page_cache']);
     $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
     $config->set('cache.page.max_age', 300);
     $config->save();
   }
diff --git a/core/modules/language/src/LanguageNegotiator.php b/core/modules/language/src/LanguageNegotiator.php
index bc924fb..2354d88 100644
--- a/core/modules/language/src/LanguageNegotiator.php
+++ b/core/modules/language/src/LanguageNegotiator.php
@@ -188,20 +188,7 @@ protected function negotiateLanguage($type, $method_id) {
     $method = $this->negotiatorManager->getDefinition($method_id);
 
     if (!isset($method['types']) || in_array($type, $method['types'])) {
-
-      // Check for a cache mode force from settings.php.
-      if ($this->settings->get('page_cache_without_database')) {
-        $cache_enabled = TRUE;
-      }
-      else {
-        $cache_enabled = $this->configFactory->get('system.performance')->get('cache.page.use_internal');
-      }
-
-      // If the language negotiation method has no cache preference or this is
-      // satisfied we can execute the callback.
-      if ($cache = !isset($method['cache']) || $this->currentUser->isAuthenticated() || $method['cache'] == $cache_enabled) {
-        $langcode = $this->getNegotiationMethodInstance($method_id)->getLangcode($this->requestStack->getCurrentRequest());
-      }
+      $langcode = $this->getNegotiationMethodInstance($method_id)->getLangcode($this->requestStack->getCurrentRequest());
     }
 
     $languages = $this->languageManager->getLanguages();
diff --git a/core/modules/language/src/LanguageServiceProvider.php b/core/modules/language/src/LanguageServiceProvider.php
index d7c4ddd..11c89a1 100644
--- a/core/modules/language/src/LanguageServiceProvider.php
+++ b/core/modules/language/src/LanguageServiceProvider.php
@@ -53,9 +53,18 @@ public function alter(ContainerBuilder $container) {
       ->addArgument(new Reference('module_handler'))
       ->addArgument(new Reference('language.config_factory_override'))
       ->addArgument(new Reference('request_stack'));
+
+    // Allow other services to be aware of:
+    // - the default language;
+    // - whether the site is multilingual;
+    // - the list of supported langcodes;
+    // - the hash of browser langcodes to standardized/Drupal langcodes.
     if ($default_language_values = $this->getDefaultLanguageValues()) {
       $container->setParameter('language.default_values', $default_language_values);
     }
+    $container->setParameter('language.is_multilingual', $this->isMultilingual());
+    $container->setParameter('language.supported_langcodes', $this->getLanguageCodes());
+    $container->setParameter('language.langcode_mappings', $this->getLangcodeMappings());
 
     // For monolingual sites, we explicitly set the default language for the
     // language config override service as there is no language negotiation.
@@ -67,12 +76,20 @@ public function alter(ContainerBuilder $container) {
   }
 
   /**
-   * Checks whether the site is multilingual.
+   * Returns a list of langcodes, of the languages set up on the site.
    *
-   * @return bool
-   *   TRUE if the site is multilingual, FALSE otherwise.
+   * Returns the equivalent of
+   * @code
+   * array_keys(LanguageManagerInterface::getLanguages())
+   * @endcode
+   * but without needing the container to be available.
+   *
+   * @return string[]
+   *   A list of language codes.
+   *
+   * @see \Drupal\Core\Language\LanguageManagerInterface::getLanguages
    */
-  protected function isMultilingual() {
+  protected function getLanguageCodes() {
     // Assign the prefix to a local variable so it can be used in an anonymous
     // function.
     $prefix = static::CONFIG_PREFIX;
@@ -83,7 +100,35 @@ protected function isMultilingual() {
     $config_ids = array_filter($config_storage->listAll($prefix), function($config_id) use ($prefix) {
       return $config_id != $prefix . LanguageInterface::LANGCODE_NOT_SPECIFIED && $config_id != $prefix . LanguageInterface::LANGCODE_NOT_APPLICABLE;
     });
-    return count($config_ids) > 1;
+    $languages = array_map(function ($config_id) use ($prefix) {
+      return str_replace($prefix, '', $config_id);
+    }, $config_ids);
+    return $languages;
+  }
+
+  /**
+   * Checks whether the site is multilingual.
+   *
+   * @return bool
+   *   TRUE if the site is multilingual, FALSE otherwise.
+   */
+  protected function isMultilingual() {
+    return count($this->getLanguageCodes()) > 1;
+  }
+
+  /**
+   * Returns the list of langcode mappings, if any.
+   *
+   * @return string[]
+   *   An array with browser langcodes as keys and standardized/Drupal langcodes
+   *   as values.
+   */
+  protected function getLangcodeMappings() {
+    // @todo Try to swap out for config.storage to take advantage of database
+    //   and caching. This might prove difficult as this is called before the
+    //   container has finished building.
+    $config_storage = BootstrapConfigStorageFactory::get();
+    return $config_storage->read('language.mappings') ?: [];
   }
 
   /**
diff --git a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationBrowser.php b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationBrowser.php
index e9fc38e..462646a 100644
--- a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationBrowser.php
+++ b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationBrowser.php
@@ -17,7 +17,6 @@
  * @Plugin(
  *   id = \Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationBrowser::METHOD_ID,
  *   weight = -2,
- *   cache = 0,
  *   name = @Translation("Browser"),
  *   description = @Translation("Language from the browser's language settings."),
  *   config_route_name = "language.negotiation_browser"
diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_system_performance.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_system_performance.yml
index 2b6f478..c27f3a9 100644
--- a/core/modules/migrate_drupal/config/install/migrate.migration.d6_system_performance.yml
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_system_performance.yml
@@ -14,7 +14,6 @@ process:
   'css/preprocess': preprocess_css
   'js/preprocess': preprocess_js
   'cache/page/max_age': cache_lifetime
-  'cache/page/use_internal': cache
   'response/gzip': page_compression
 destination:
   plugin: config
diff --git a/core/modules/migrate_drupal/src/Tests/d6/MigrateSystemPerformanceTest.php b/core/modules/migrate_drupal/src/Tests/d6/MigrateSystemPerformanceTest.php
index 28d9a8b..933ccb7 100644
--- a/core/modules/migrate_drupal/src/Tests/d6/MigrateSystemPerformanceTest.php
+++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateSystemPerformanceTest.php
@@ -40,8 +40,6 @@ public function testSystemPerformance() {
     $this->assertIdentical($config->get('css.preprocess'), FALSE);
     $this->assertIdentical($config->get('js.preprocess'), FALSE);
     $this->assertIdentical($config->get('cache.page.max_age'), 0);
-    $this->assertIdentical($config->get('cache.page.use_internal'), TRUE);
-    $this->assertIdentical($config->get('response.gzip'), TRUE);
   }
 
 }
diff --git a/core/modules/page_cache/page_cache.info.yml b/core/modules/page_cache/page_cache.info.yml
new file mode 100644
index 0000000..af72fab
--- /dev/null
+++ b/core/modules/page_cache/page_cache.info.yml
@@ -0,0 +1,6 @@
+name: Internal page cache
+type: module
+description: 'Caches pages for anonymous users. Works well for small to medium-sized websites.'
+package: Core
+version: VERSION
+core: 8.x
diff --git a/core/modules/page_cache/page_cache.module b/core/modules/page_cache/page_cache.module
new file mode 100644
index 0000000..2c7d01f
--- /dev/null
+++ b/core/modules/page_cache/page_cache.module
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Caches responses for anonymous users, request and response policies allowing.
+ */
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\PageCache\RequestPolicyInterface;
+use Drupal\Core\Routing\RouteMatchInterface;
+
+/**
+ * Implements hook_help().
+ */
+function page_cache_help($route_name, RouteMatchInterface $route_match) {
+  switch ($route_name) {
+    case 'help.page.page_cache':
+      $output = '<h3>' . t('About') . '</h3>';
+      $output .= '<p>' . t('The Internal page cache module caches pages for anonymous users in the database.') . '</p>';
+      $output .= '<h3>' . t('Uses') . '</h3>';
+      $output .= '<dl>';
+      $output .= '<dt>' . t('Speeding up your site') . '</dt>';
+      $output .= '<dd>';
+      $output .= '<p>' . t('Pages requested by anonymous users are stored in a compressed format; depending on your site configuration and the amount of your web traffic tied to anonymous visitors, the caching system may significantly increase the speed of your site.');
+      $output .= '<p>' . t('(For authenticated users, pages need to be assembled for each user individually, but anonymous users all get the exact same version of each page.)') . '</p>';
+      $output .= '</dd>';
+      $output .= '<dt>' . t('Configuring Internal page cache') . '</dt>';
+      $output .= '<dd>';
+      $output .= '<p>' . t('On the <a href="@cache-settings">Performance settings page</a>, you can configure how long browsers and proxies may cache pages, that setting is also respected by the Internal page cache module. There is no other configuration.', array('@cache-settings' => \Drupal::url('system.performance_settings')))  . '</p>';
+      $output .= '</dd>';
+      $output .= '</dl>';
+
+      return $output;
+  }
+}
+
+/**
+ * Implements hook_form_alter().
+ */
+function page_cache_form_alter(&$form, FormStateInterface $form_state, $form_id) {
+  // If the page that's being built is cacheable, set the 'immutable' flag, to
+  // ensure that when the form is used, a new form build ID is generated when
+  // appropriate, to prevent information disclosure.
+  $request_policy = \Drupal::service('page_cache_request_policy');
+  $request = \Drupal::requestStack()->getCurrentRequest();
+  $request_is_cacheable = $request_policy->check($request) === RequestPolicyInterface::ALLOW;
+  if ($request_is_cacheable) {
+    $form_state->addBuildInfo('immutable', TRUE);
+  }
+}
diff --git a/core/modules/page_cache/page_cache.services.yml b/core/modules/page_cache/page_cache.services.yml
new file mode 100644
index 0000000..d532167
--- /dev/null
+++ b/core/modules/page_cache/page_cache.services.yml
@@ -0,0 +1,6 @@
+services:
+  http_middleware.page_cache:
+    class: Drupal\page_cache\StackMiddleware\PageCache
+    arguments: ['@cache.render', '@page_cache_request_policy', '@page_cache_response_policy', '@content_negotiation', '%language.is_multilingual%', '%language.supported_langcodes%', '%language.langcode_mappings%', '%language.default_values%']
+    tags:
+      - { name: http_middleware, priority: 200 }
diff --git a/core/lib/Drupal/Core/StackMiddleware/PageCache.php b/core/modules/page_cache/src/StackMiddleware/PageCache.php
similarity index 84%
rename from core/lib/Drupal/Core/StackMiddleware/PageCache.php
rename to core/modules/page_cache/src/StackMiddleware/PageCache.php
index b381018..a821a39 100644
--- a/core/lib/Drupal/Core/StackMiddleware/PageCache.php
+++ b/core/modules/page_cache/src/StackMiddleware/PageCache.php
@@ -2,11 +2,12 @@
 
 /**
  * @file
- * Contains \Drupal\Core\StackMiddleware\PageCache.
+ * Contains \Drupal\page_cache\StackMiddleware\PageCache.
  */
 
-namespace Drupal\Core\StackMiddleware;
+namespace Drupal\page_cache\StackMiddleware;
 
+use Drupal\Component\Utility\UserAgent;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\ContentNegotiation;
@@ -60,7 +61,35 @@ class PageCache implements HttpKernelInterface {
   protected $contentNegotiation;
 
   /**
-   * Constructs a ReverseProxyMiddleware object.
+   * The language.is_multilingual container parameter.
+   *
+   * @var bool
+   */
+  protected $isMultilingual;
+
+  /**
+   * The language.supported_langcodes container parameter.
+   *
+   * @var string[]
+   */
+  protected $supportedLangcodes;
+
+  /**
+   * The language.langcode_mappings container parameter.
+   *
+   * @var \string[]
+   */
+  protected $langcodeMappings;
+
+  /**
+   * The language.default-values container parameter.
+   *
+   * @var array
+   */
+  protected $defaultLanguageValues;
+
+  /**
+   * Constructs a PageCache object.
    *
    * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
    *   The decorated kernel.
@@ -72,33 +101,33 @@ class PageCache implements HttpKernelInterface {
    *   A policy rule determining the cacheability of the response.
    * @param \Drupal\Core\ContentNegotiation $content_negotiation
    *   The content negotiation library.
+   * @param bool $is_multilingual
+   *   The language.is_multilingual container parameter.
+   * @param string[] $supported_langcodes
+   *   The language.supported_langcodes container parameter.
+   * @param string[] $langcode_mappings
+   *   The language.langcode_mappings container parameter.
+   * @param array $language_default_values
+   *   The language.default-values container parameter.
    */
-  public function __construct(HttpKernelInterface $http_kernel, CacheBackendInterface $cache, RequestPolicyInterface $request_policy, ResponsePolicyInterface $response_policy, ContentNegotiation $content_negotiation) {
+  public function __construct(HttpKernelInterface $http_kernel, CacheBackendInterface $cache, RequestPolicyInterface $request_policy, ResponsePolicyInterface $response_policy, ContentNegotiation $content_negotiation, $is_multilingual, array $supported_langcodes, array $langcode_mappings, array $language_default_values) {
     $this->httpKernel = $http_kernel;
     $this->cache = $cache;
     $this->requestPolicy = $request_policy;
     $this->responsePolicy = $response_policy;
     $this->contentNegotiation = $content_negotiation;
+    $this->isMultilingual = $is_multilingual;
+    $this->supportedLangcodes = $supported_langcodes;
+    $this->langcodeMappings = $langcode_mappings;
+    $this->defaultLanguageValues = $language_default_values;
   }
 
   /**
    * {@inheritdoc}
    */
   public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
-    if ($type !== static::MASTER_REQUEST) {
-      // Only allow page caching on master request.
-      $cache_enabled = FALSE;
-    }
-    elseif (Settings::get('page_cache_without_database')) {
-      // Check for a cache mode force from settings.php.
-      $cache_enabled = TRUE;
-    }
-    else {
-      $config = $this->config('system.performance');
-      $cache_enabled = $config->get('cache.page.use_internal');
-    }
-
-    if ($cache_enabled && $this->requestPolicy->check($request) === RequestPolicyInterface::ALLOW) {
+    // Only allow page caching on master request.
+    if ($type === static::MASTER_REQUEST && $this->requestPolicy->check($request) === RequestPolicyInterface::ALLOW) {
       $response = $this->lookup($request, $type, $catch);
     }
     else {
@@ -243,20 +272,6 @@ protected function fetch(Request $request, $type = self::MASTER_REQUEST, $catch
       return $response;
     }
 
-    // Check if the current page may be compressed.
-    if (extension_loaded('zlib') && !$response->headers->get('Content-Encoding') && $this->config('system.performance')->get('response.gzip')) {
-      $content = $response->getContent();
-      if ($content) {
-        $response->setContent(gzencode($content, 9, FORCE_GZIP));
-        $response->headers->set('Content-Encoding', 'gzip');
-      }
-
-      // When page compression is enabled, ensure that proxy caches will record
-      // and deliver different versions of a page depending on whether the
-      // client supports gzip or not.
-      $response->setVary('Accept-Encoding', FALSE);
-    }
-
     // Use the actual timestamp from an Expires header, if available.
     $date = $response->getExpires();
     $expire = ($date > (new \DateTime())) ? $date->getTimestamp() : Cache::PERMANENT;
@@ -334,19 +349,24 @@ protected function getCacheId(Request $request) {
       $request->getUri(),
       $this->contentNegotiation->getContentType($request),
     );
-    return implode(':', $cid_parts);
-  }
 
-  /**
-   * Wraps Drupal::config().
-   *
-   * Config factory is not injected into this class in order to prevent
-   * premature initialization of config storage (database).
-   *
-   * @see \Drupal::config()
-   */
-  protected function config($name) {
-    return \Drupal::config($name);
+    // If there is an Accept-Language header, make it part of the CID.
+    $http_accept_language = $request->server->get('HTTP_ACCEPT_LANGUAGE');
+    if ($http_accept_language) {
+      $default_langcode = $this->defaultLanguageValues['id'];
+      if ($this->isMultilingual) {
+        $langcode = UserAgent::getBestMatchingLangcode($http_accept_language, $this->supportedLangcodes, $this->langcodeMappings);
+        if ($langcode === FALSE) {
+          $langcode = $default_langcode;
+        }
+      }
+      else {
+        $langcode = $default_langcode;
+      }
+      $cid_parts[] = $langcode;
+    }
+
+    return implode(':', $cid_parts);
   }
 
 }
diff --git a/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php b/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php
similarity index 95%
rename from core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php
rename to core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php
index 7ce1b5b..996362c 100644
--- a/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php
+++ b/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Contains \Drupal\system\Tests\Cache\PageCacheTagsIntegrationTest.
+ * Contains \Drupal\page_cache\Tests\PageCacheTagsIntegrationTest.
  */
 
-namespace Drupal\system\Tests\Cache;
+namespace Drupal\page_cache\Tests;
 
 use Drupal\Core\Url;
 use Drupal\simpletest\WebTestBase;
@@ -15,7 +15,7 @@
  * Enables the page cache and tests its cache tags in various scenarios.
  *
  * @group Cache
- * @see \Drupal\system\Tests\Bootstrap\PageCacheTest
+ * @see \Drupal\page_cache\Tests\PageCacheTest
  * @see \Drupal\node\Tests\NodePageCacheTest
  * @see \Drupal\menu_ui\Tests\MenuTest::testMenuBlockPageCacheTags()
  */
@@ -23,6 +23,11 @@ class PageCacheTagsIntegrationTest extends WebTestBase {
 
   protected $profile = 'standard';
 
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['page_cache'];
+
   protected $dumpHeaders = TRUE;
 
   /**
@@ -32,7 +37,6 @@ protected function setUp() {
     parent::setUp();
 
     $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
     $config->set('cache.page.max_age', 300);
     $config->save();
   }
diff --git a/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php b/core/modules/page_cache/src/Tests/PageCacheTest.php
similarity index 69%
rename from core/modules/system/src/Tests/Bootstrap/PageCacheTest.php
rename to core/modules/page_cache/src/Tests/PageCacheTest.php
index c3538f2..229eef5 100644
--- a/core/modules/system/src/Tests/Bootstrap/PageCacheTest.php
+++ b/core/modules/page_cache/src/Tests/PageCacheTest.php
@@ -2,20 +2,23 @@
 
 /**
  * @file
- * Definition of Drupal\system\Tests\Bootstrap\PageCacheTest.
+ * Contains \Drupal\page_cache\Tests\PageCacheTest.
  */
 
-namespace Drupal\system\Tests\Bootstrap;
+namespace Drupal\page_cache\Tests;
 
 use Drupal\Component\Datetime\DateTimePlus;
+use Drupal\Component\Utility\String;
 use Drupal\Core\Routing\RequestContext;
+use Drupal\Core\Url;
+use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\simpletest\WebTestBase;
 use Drupal\Core\Cache\Cache;
 
 /**
  * Enables the page cache and tests it with various HTTP requests.
  *
- * @group Bootstrap
+ * @group page_cache
  */
 class PageCacheTest extends WebTestBase {
 
@@ -26,7 +29,7 @@ class PageCacheTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('test_page_test', 'system_test');
+  public static $modules = array('test_page_test', 'system_test', 'page_cache');
 
   protected function setUp() {
     parent::setUp();
@@ -35,6 +38,10 @@ protected function setUp() {
       ->set('name', 'Drupal')
       ->set('page.front', 'test-page')
       ->save();
+
+    $config = $this->config('system.performance');
+    $config->set('cache.page.max_age', 300);
+    $config->save();
   }
 
   /**
@@ -44,11 +51,6 @@ protected function setUp() {
    * persisted.
    */
   function testPageCacheTags() {
-    $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
-    $config->set('cache.page.max_age', 300);
-    $config->save();
-
     $path = 'system-test/cache_tags_page';
     $tags = array('system_test_cache_tags_page');
     $this->drupalGet($path);
@@ -77,11 +79,6 @@ function testPageCacheTags() {
    * Tests support for different cache items with different Accept headers.
    */
   function testAcceptHeaderRequests() {
-    $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
-    $config->set('cache.page.max_age', 300);
-    $config->save();
-
     $url_generator = \Drupal::urlGenerator();
     $url_generator->setContext(new RequestContext());
     $accept_header_cache_uri = $url_generator->getPathFromRoute('system_test.page_cache_accept_header');
@@ -101,14 +98,67 @@ function testAcceptHeaderRequests() {
   }
 
   /**
+   * Tests support for different cache items with different Accept-Language headers.
+   *
+   * Note: test coverage for all the possible Accept-Language cases lives at
+   * \Drupal\Tests\Component\Utility\UserAgentTest.
+   */
+  function testAcceptLanguageHeaderRequests() {
+    $url = Url::fromRoute('<front>');
+
+    $verify_page_cache = function($expected_cid_parts, $accepted_langcode = FALSE) use ($url) {
+      $headers = [];
+      if (is_string($accepted_langcode)) {
+        $headers[] = 'Accept-Language: ' . $accepted_langcode;
+      }
+      $this->drupalGet($url, [], $headers);
+      $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'HTML page was not yet cached.');
+      $this->drupalGet($url, [], $headers);
+      $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'HTML page was cached.');
+      $cid = implode(':', $expected_cid_parts);
+      $this->assertTrue(\Drupal::cache('render')->get($cid), String::format('Expected page cache item exists with CID %cid.', ['%cid' => $cid]));
+
+      \Drupal::cache('render')->deleteAll();
+    };
+
+    // Single-language site:
+    // - no Accept-Language header: not keyed by langcode.
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html']);
+    // - nonsensical Accept-Language header: keyed by default ('en').
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'en'], 'utterly wrong Accept-Language header value, but presence matters in this test');
+    // - any valid Accept-Language language: keyed by default ('en').
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'en'], 'en');
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'en'], 'nl');
+
+    // Multilingual site, single lang:
+    // - nonsensical Accept-Language header: keyed by default ('en').
+    $this->container->get('module_installer')->install(['language']);
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'en'], 'utterly wrong Accept-Language header value, but presence matters in this test');
+    // - 'en' Accept-Language header: keyed by default ('en').
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'en'], 'en');
+    // - 'nl' Accept-Language header: keyed by default ('en').
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'en'], 'nl');
+
+    // Multilingual site, multiple langs:
+    // - nonsensical Accept-Language header: keyed by default ('en').
+    ConfigurableLanguage::createFromLangcode('nl')->save();
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'en'], 'utterly wrong Accept-Language header value, but presence matters in this test');
+    // - 'en' Accept-Language header: is also best match.
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'en'], 'en');
+    // - 'nl' Accept-Language header: is also best match.
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'nl'], 'nl');
+    // - 'en-US' Accept-Language header: matched to 'en'.
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'en'], 'en-US');
+    // - 'nl-BE' Accept-Language header: matched to 'nl'.
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'nl'], 'nl-BE');
+    // - complex Accept-Language header: matched to 'nl'.
+    $verify_page_cache([$url->setAbsolute()->toString(), 'html', 'nl'], 'hu, nl-BE;q=0.66, en;q=0.33');
+  }
+
+  /**
    * Tests support of requests with If-Modified-Since and If-None-Match headers.
    */
   function testConditionalRequests() {
-    $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
-    $config->set('cache.page.max_age', 300);
-    $config->save();
-
     // Fill the cache.
     $this->drupalGet('');
     // Verify the page is not printed twice when the cache is cold.
@@ -149,16 +199,9 @@ function testConditionalRequests() {
    * Tests cache headers.
    */
   function testPageCache() {
-    $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
-    $config->set('cache.page.max_age', 300);
-    $config->set('response.gzip', 1);
-    $config->save();
-
     // Fill the cache.
     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Page was not cached.');
-    $this->assertEqual(strtolower($this->drupalGetHeader('Vary')), 'cookie,accept-encoding', 'Vary header was sent.');
     // Symfony's Response logic determines a specific order for the subvalues
     // of the Cache-Control header, even if they are explicitly passed in to
     // the response header bag in a different order.
@@ -169,7 +212,6 @@ function testPageCache() {
     // Check cache.
     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
     $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
-    $this->assertEqual(strtolower($this->drupalGetHeader('Vary')), 'cookie,accept-encoding', 'Vary: Cookie header was sent.');
     $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'max-age=300, public', 'Cache-Control header was sent.');
     $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.');
     $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', 'Custom header was sent.');
@@ -178,14 +220,12 @@ function testPageCache() {
     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Expires', 'value' => 'Fri, 19 Nov 2008 05:00:00 GMT')));
     $this->assertEqual($this->drupalGetHeader('Expires'), 'Fri, 19 Nov 2008 05:00:00 GMT', 'Default header was replaced.');
     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Vary', 'value' => 'User-Agent')));
-    $this->assertEqual(strtolower($this->drupalGetHeader('Vary')), 'user-agent,accept-encoding', 'Default header was replaced.');
 
     // Check that authenticated users bypass the cache.
     $user = $this->drupalCreateUser();
     $this->drupalLogin($user);
     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
     $this->assertFalse($this->drupalGetHeader('X-Drupal-Cache'), 'Caching was bypassed.');
-    $this->assertTrue(strpos(strtolower($this->drupalGetHeader('Vary')), 'cookie') === FALSE, 'Vary: Cookie header was not sent.');
     $this->assertEqual($this->drupalGetHeader('Cache-Control'), 'must-revalidate, no-cache, post-check=0, pre-check=0, private', 'Cache-Control header was sent.');
     $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.');
     $this->assertEqual($this->drupalGetHeader('Foo'), 'bar', 'Custom header was sent.');
@@ -195,11 +235,6 @@ function testPageCache() {
    * Tests the omit_vary_cookie setting.
    */
   public function testPageCacheWithoutVaryCookie() {
-    $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
-    $config->set('cache.page.max_age', 300);
-    $config->save();
-
     $settings['settings']['omit_vary_cookie'] = (object) array(
       'value' => TRUE,
       'required' => TRUE,
@@ -217,51 +252,4 @@ public function testPageCacheWithoutVaryCookie() {
     $this->assertTrue(strpos($this->drupalGetHeader('Vary'), 'Cookie') === FALSE, 'Vary: Cookie header was not sent.');
   }
 
-  /**
-   * Tests page compression.
-   *
-   * The test should pass even if zlib.output_compression is enabled in php.ini,
-   * .htaccess or similar, or if compression is done outside PHP, e.g. by the
-   * mod_deflate Apache module.
-   */
-  function testPageCompression() {
-    $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
-    $config->set('cache.page.max_age', 300);
-    $config->set('response.gzip', 1);
-    $config->save();
-
-    // Fill the cache and verify that output is compressed.
-    $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
-    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS', 'Page was not cached.');
-    $this->drupalSetContent(gzinflate(substr($this->drupalGetContent(), 10, -8)));
-    $this->assertRaw('</html>', 'Page was gzip compressed.');
-
-    // Verify that cached output is compressed.
-    $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
-    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
-    $this->assertEqual($this->drupalGetHeader('Content-Encoding'), 'gzip', 'A Content-Encoding header was sent.');
-    $this->drupalSetContent(gzinflate(substr($this->drupalGetContent(), 10, -8)));
-    $this->assertRaw('</html>', 'Page was gzip compressed.');
-
-    // Verify that a client without compression support gets an uncompressed page.
-    $this->drupalGet('');
-    $this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT', 'Page was cached.');
-    $this->assertFalse($this->drupalGetHeader('Content-Encoding'), 'A Content-Encoding header was not sent.');
-    $this->assertTitle(t('Test page | @site-name', array('@site-name' => $this->config('system.site')->get('name'))), 'Site title matches.');
-    $this->assertRaw('</html>', 'Page was not compressed.');
-
-    // Disable compression mode.
-    $config->set('response.gzip', 0);
-    $config->save();
-
-    // Verify if cached page is still available for a client with compression support.
-    $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
-    $this->drupalSetContent(gzinflate(substr($this->drupalGetContent(), 10, -8)));
-    $this->assertRaw('</html>', 'Page was delivered after compression mode is changed (compression support enabled).');
-
-    // Verify if cached page is still available for a client without compression support.
-    $this->drupalGet('');
-    $this->assertRaw('</html>', 'Page was delivered after compression mode is changed (compression support disabled).');
-  }
 }
diff --git a/core/modules/system/config/install/system.performance.yml b/core/modules/system/config/install/system.performance.yml
index 1e75b4b..11392bd 100644
--- a/core/modules/system/config/install/system.performance.yml
+++ b/core/modules/system/config/install/system.performance.yml
@@ -1,6 +1,5 @@
 cache:
   page:
-    use_internal: false
     max_age: 0
 css:
   preprocess: true
@@ -13,6 +12,4 @@ fast_404:
 js:
   preprocess: true
   gzip: true
-response:
-  gzip: false
 stale_file_threshold: 2592000
diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml
index a8d13fa..c0f1906 100644
--- a/core/modules/system/config/schema/system.schema.yml
+++ b/core/modules/system/config/schema/system.schema.yml
@@ -161,14 +161,11 @@ system.performance:
       mapping:
         page:
           type: mapping
-          label: 'Page cache'
+          label: 'Page caching'
           mapping:
-            use_internal:
-              type: boolean
-              label: 'Use internal page cache'
             max_age:
               type: integer
-              label: 'Max age of page cache'
+              label: 'Max age'
     css:
       type: mapping
       label: 'CSS performance settings'
diff --git a/core/modules/system/src/Form/PerformanceForm.php b/core/modules/system/src/Form/PerformanceForm.php
index 9049c78..c5eb48c 100644
--- a/core/modules/system/src/Form/PerformanceForm.php
+++ b/core/modules/system/src/Form/PerformanceForm.php
@@ -121,6 +121,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#type' => 'details',
       '#title' => t('Caching'),
       '#open' => TRUE,
+      '#description' => $this->t('Note: Drupal provides an internal page cache module that is recommended for small to medium-sized websites.'),
     );
     // Identical options to the ones for block caching.
     // @see \Drupal\Core\Block\BlockBase::buildConfigurationForm()
@@ -132,14 +133,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#title' => t('Page cache maximum age'),
       '#default_value' => $config->get('cache.page.max_age'),
       '#options' => $period,
-      '#description' => t('The maximum time a page can be cached. This is used as the value for max-age in Cache-Control headers.'),
-    );
-
-    $form['caching']['cache'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Use internal page cache'),
-      '#description' => t("If a reverse proxy cache isn't available, use Drupal's internal cache system to store cached pages."),
-      '#default_value' => $config->get('cache.page.use_internal'),
+      '#description' => t('The maximum time a page can be cached by browsers and proxies. This is used as the value for max-age in Cache-Control headers.'),
     );
 
     $directory = 'public://';
@@ -157,16 +151,6 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       '#description' => t('External resources can be optimized automatically, which can reduce both the size and number of requests made to your website.') . $disabled_message,
     );
 
-    $form['bandwidth_optimization']['page_compression'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Compress cached pages'),
-      '#default_value' => $config->get('response.gzip'),
-      '#states' => array(
-        'visible' => array(
-          'input[name="cache"]' => array('checked' => TRUE),
-        ),
-      ),
-    );
     $form['bandwidth_optimization']['preprocess_css'] = array(
       '#type' => 'checkbox',
       '#title' => t('Aggregate CSS files'),
@@ -195,9 +179,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     $this->renderCache->deleteAll();
 
     $this->config('system.performance')
-      ->set('cache.page.use_internal', $form_state->getValue('cache'))
       ->set('cache.page.max_age', $form_state->getValue('page_cache_maximum_age'))
-      ->set('response.gzip', $form_state->getValue('page_compression'))
       ->set('css.preprocess', $form_state->getValue('preprocess_css'))
       ->set('js.preprocess', $form_state->getValue('preprocess_js'))
       ->save();
diff --git a/core/modules/system/src/Tests/Ajax/AjaxFormPageCacheTest.php b/core/modules/system/src/Tests/Ajax/AjaxFormPageCacheTest.php
index 9da0935..3e36515 100644
--- a/core/modules/system/src/Tests/Ajax/AjaxFormPageCacheTest.php
+++ b/core/modules/system/src/Tests/Ajax/AjaxFormPageCacheTest.php
@@ -17,11 +17,15 @@ class AjaxFormPageCacheTest extends AjaxTestBase {
   /**
    * {@inheritdoc}
    */
+  public static $modules = ['page_cache'];
+
+  /**
+   * {@inheritdoc}
+   */
   public function setUp() {
     parent::setUp();
 
     $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
     $config->set('cache.page.max_age', 300);
     $config->save();
   }
diff --git a/core/modules/system/src/Tests/Cache/PageCacheTagsTestBase.php b/core/modules/system/src/Tests/Cache/PageCacheTagsTestBase.php
index 3e3b1bc..7909300 100644
--- a/core/modules/system/src/Tests/Cache/PageCacheTagsTestBase.php
+++ b/core/modules/system/src/Tests/Cache/PageCacheTagsTestBase.php
@@ -26,12 +26,16 @@
   /**
    * {@inheritdoc}
    */
+  protected static $modules = ['page_cache'];
+
+  /**
+   * {@inheritdoc}
+   */
   protected function setUp() {
     parent::setUp();
 
     // Enable page caching.
     $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
     $config->set('cache.page.max_age', 3600);
     $config->save();
   }
diff --git a/core/modules/system/src/Tests/Form/FormStoragePageCacheTest.php b/core/modules/system/src/Tests/Form/FormStoragePageCacheTest.php
index d04be90..bac12db 100644
--- a/core/modules/system/src/Tests/Form/FormStoragePageCacheTest.php
+++ b/core/modules/system/src/Tests/Form/FormStoragePageCacheTest.php
@@ -19,7 +19,7 @@ class FormStoragePageCacheTest extends WebTestBase {
   /**
    * @var array
    */
-  public static $modules = array('form_test');
+  public static $modules = array('form_test', 'page_cache');
 
   /**
    * {@inheritdoc}
@@ -28,7 +28,6 @@ protected function setUp() {
     parent::setUp();
 
     $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
     $config->set('cache.page.max_age', 300);
     $config->save();
   }
diff --git a/core/modules/system/src/Tests/Session/SessionTest.php b/core/modules/system/src/Tests/Session/SessionTest.php
index bbe23f6..d6cea95 100644
--- a/core/modules/system/src/Tests/Session/SessionTest.php
+++ b/core/modules/system/src/Tests/Session/SessionTest.php
@@ -144,8 +144,8 @@ function testEmptyAnonymousSession() {
     $this->assertSessionEmpty(TRUE);
 
     // The same behavior is expected when caching is enabled.
+    $this->container->get('module_installer')->install(['page_cache']);
     $config = $this->config('system.performance');
-    $config->set('cache.page.use_internal', 1);
     $config->set('cache.page.max_age', 300);
     $config->save();
     $this->drupalGet('');
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 007595e..369e4a2 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -84,7 +84,7 @@ function system_help($route_name, RouteMatchInterface $route_match) {
       $output .= '<dt>' . t('Managing themes') . '</dt>';
       $output .= '<dd>' . t('The System module allows users with the appropriate permissions to install and uninstall themes on the <a href="@themes">Appearance administration page</a>. Themes determine the design and presentation of your site. Drupal comes packaged with several core themes, and additional contributed themes are available at the <a href="@drupal-themes">Drupal.org theme page</a>.', array('@themes' => \Drupal::url('system.themes_page'), '@drupal-themes' => 'http://drupal.org/project/themes')) . '</dd>';
       $output .= '<dt>' . t('Managing caching') . '</dt>';
-      $output .= '<dd>' . t("The System module allows users with the appropriate permissions to manage caching on the <a href='@cache-settings'>Performance settings page</a>. Drupal has a robust caching system that allows the efficient re-use of previously-constructed web pages and web page components. Pages requested by anonymous users are stored in a compressed format; depending on your site configuration and the amount of your web traffic tied to anonymous visitors, the caching system may significantly increase the speed of your site.", array('@cache-settings' => \Drupal::url('system.performance_settings'))) . '</dd>';
+      $output .= '<dd>' . t("The System module allows users with the appropriate permissions to manage caching on the <a href='@cache-settings'>Performance settings page</a>. Drupal has a robust caching system that allows the efficient re-use of previously-constructed web page components.", array('@cache-settings' => \Drupal::url('system.performance_settings'))) . '</dd>';
       $output .= '<dt>' . t('Performing system maintenance') . '</dt>';
       $output .= '<dd>' . t('In order for the site and its modules to continue to operate well, a set of routine administrative operations must run on a regular basis. The System module manages this task by making use of a system cron job. You can verify the status of cron tasks by visiting the <a href="@status">Status report page</a>. For more information, see the online handbook entry for <a href="@handbook">configuring cron jobs</a>. You can set up cron job by visiting <a href="@cron">Cron configuration</a> page', array('@status' => \Drupal::url('system.status'), '@handbook' => 'http://drupal.org/cron', '@cron' => \Drupal::url('system.cron_settings'))) . '</dd>';
       $output .= '<dt>' . t('Configuring basic site settings') . '</dt>';
diff --git a/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php b/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php
index 138309e..c1f33fc 100644
--- a/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php
+++ b/core/tests/Drupal/Tests/Core/Form/FormCacheTest.php
@@ -488,8 +488,10 @@ public function testSetCacheBuildIdMismatch() {
 
   /**
    * @covers ::setCache
+   *
+   * @todo Move this test to page_cache module.
    */
-  public function testSetCacheImmutableForm() {
+  public function atestSetCacheImmutableForm() {
     $form_build_id = 'the_form_build_id';
     $form = [
       '#form_id' => 'the_form_id',
@@ -508,7 +510,7 @@ public function testSetCacheImmutableForm() {
       ->with($form_build_id, $form_state_data, $this->isType('int'));
 
     // Rebuild the FormCache with a config factory that will return a config
-    // object with the internal page cache enabled.
+    // object with the page_cache module enabled.
     $this->configFactory = $this->getConfigFactoryStub(['system.performance' => ['cache.page.use_internal' => TRUE]]);
     $root = dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));
     $this->formCache = $this->getMockBuilder('Drupal\Core\Form\FormCache')
