diff --git a/core/modules/locale/tests/modules/locale_test/lib/Drupal/locale_test/LocaleTestBundle.php b/core/modules/locale/tests/modules/locale_test/lib/Drupal/locale_test/LocaleTestBundle.php
new file mode 100644
index 0000000..c9baa25
--- /dev/null
+++ b/core/modules/locale/tests/modules/locale_test/lib/Drupal/locale_test/LocaleTestBundle.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\locale_test\LocaleTestBundle.
+ *
+ * This is a workaround to make sure the 'Last-Modified' HTTP header is not
+ * overridden by FinishResponseSubscriber. 'Last-Modified' is set when a remote
+ * translation file is served via a menu callback. So a new event subscriber is
+ * registered here to save the value and set it back.
+ */
+
+namespace Drupal\locale_test;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * Locale Test dependency injection container.
+ */
+class LocaleTestBundle extends Bundle {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function build(ContainerBuilder $container) {
+    // Register our response subscriber to handle finished responses.
+    $container->register('locale_test_finish_response_subscriber', 'Drupal\locale_test\LocaleTestFinishResponseSubscriber')
+      ->addTag('event_subscriber');
+  }
+
+}
diff --git a/core/modules/locale/tests/modules/locale_test/lib/Drupal/locale_test/LocaleTestFinishResponseSubscriber.php b/core/modules/locale/tests/modules/locale_test/lib/Drupal/locale_test/LocaleTestFinishResponseSubscriber.php
new file mode 100644
index 0000000..74b6cb6
--- /dev/null
+++ b/core/modules/locale/tests/modules/locale_test/lib/Drupal/locale_test/LocaleTestFinishResponseSubscriber.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains of \Drupal\locale_test\LocaleTestFinishResponseSubscriber.
+ *
+ * This is a workaround to make sure the 'Last-Modified' HTTP header is not
+ * overridden by FinishResponseSubscriber. 'Last-Modified' is set when a remote
+ * translation file is served via a menu callback. So this is a new event
+ * subscriber which saves the value and sets it back.
+ *
+ * This uses the saveLastModified() method which has a very high priority, so it
+ * can save the defined header really early in a class property. Then later on
+ * the setLastModified() method can set the header again using the value from
+ * this property, which has a very low priority, so it can manipulate the header
+ * after FinishResponseSubscriber has done its changes.
+ */
+
+namespace Drupal\locale_test;
+
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+
+/**
+ * Response subscriber to handle finished responses.
+ */
+class LocaleTestFinishResponseSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The 'Last-Modified' HTTP header.
+   *
+   * @var string
+   */
+  public $lastModified;
+
+  /**
+   * Registers the methods in this class that should be listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  public static function getSubscribedEvents() {
+    $events[KernelEvents::RESPONSE][] = array('saveLastModified', 100);
+    $events[KernelEvents::RESPONSE][] = array('setLastModified', -100);
+    return $events;
+  }
+
+  /**
+   * Saves the 'Last-Modified' HTTP header in a class property.
+   *
+   * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
+   *   The event where a translation file was served.
+   */
+  public function saveLastModified(FilterResponseEvent $event) {
+    $this->lastModified = $event->getResponse()->headers->get('Last-Modified');
+  }
+
+  /**
+   * Sets the 'Last-Modified' HTTP header to the response.
+   *
+   * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
+   *   The event where a translation file was served.
+   */
+  public function setLastModified(FilterResponseEvent $event) {
+    if (!empty($this->lastModified)) {
+      $event->getResponse()->headers->set('Last-Modified', $this->lastModified);
+    }
+  }
+
+}
diff --git a/core/modules/locale/tests/modules/locale_test/locale_test.info.yml b/core/modules/locale/tests/modules/locale_test/locale_test.info.yml
index ca4211d..7668ce0 100644
--- a/core/modules/locale/tests/modules/locale_test/locale_test.info.yml
+++ b/core/modules/locale/tests/modules/locale_test/locale_test.info.yml
@@ -7,3 +7,5 @@ core: 8.x
 hidden: true
 'interface translation project': locale_test
 'interface translation server pattern': core/modules/locale/test/test.%language.po
+dependencies:
+  - locale
diff --git a/core/modules/locale/tests/modules/locale_test/locale_test.module b/core/modules/locale/tests/modules/locale_test/locale_test.module
index 166983a..3dd16bd 100644
--- a/core/modules/locale/tests/modules/locale_test/locale_test.module
+++ b/core/modules/locale/tests/modules/locale_test/locale_test.module
@@ -6,6 +6,9 @@
  */
 use Drupal\Core\StreamWrapper\PublicStream;
 
+define('LOCALE_TEST_TIMESTAMP_NEW', REQUEST_TIME - 100);
+define('LOCALE_TEST_TIMESTAMP_OLD', REQUEST_TIME - 300);
+
 /**
  * Implements hook_system_info_alter().
  *
@@ -15,7 +18,7 @@
 function locale_test_system_info_alter(&$info, $file, $type) {
   // Only modify the system info if required.
   // By default the locale_test modules are hidden and have a project specified.
-  // To test the module detection proces by locale_project_list() the
+  // To test the module detection process by locale_project_list() the
   // test modules should mimic a custom module. I.e. be non-hidden.
   if (\Drupal::state()->get('locale.test_system_info_alter')) {
     if ($file->name == 'locale_test' || $file->name == 'locale_test_translate') {
@@ -26,6 +29,55 @@ function locale_test_system_info_alter(&$info, $file, $type) {
 }
 
 /**
+ * Copies a translation file to the translations folder.
+ *
+ * Mock modules use this method to copy their po files to the translations
+ * folder. They can also specify a timestamp which will be set for the copied
+ * file in order to be able to test different scenarios with these translation
+ * files.
+ *
+ * @param string $module
+ *   Name of the module providing the translation file that will be copied by
+ *   this method. Will be used for constructing the path for this translation
+ *   file.
+ * @param string $translation_file
+ *   Name of the translation file that will be copied.
+ * @param int $timestamp
+ *   (optional) Timestamp will be set as the creation date for the copy of
+ *   the translation file. By default the timestamp is the current time.
+ */
+function locale_test_copy_translation_file($module, $translation_file, $timestamp = NULL) {
+  $translation_file_path = drupal_get_path('module', $module) . '/' . $translation_file;
+  $translation_directory = variable_get('locale_translate_file_directory', conf_path() . '/files/translations');
+  $destination = $translation_directory . '/' . $translation_file;
+  file_unmanaged_copy($translation_file_path, $destination, FILE_EXISTS_REPLACE);
+
+  if (!empty($timestamp)) {
+    // Set the timestamp of the newly copied file.
+    touch($destination, $timestamp);
+  }
+}
+
+/**
+ * Serves a translation file as a result of a page callback.
+ *
+ * @param string $module
+ *   Name of the module providing the translation file that will be served.
+ * @param string $translation_file
+ *   Name of the translation file that will be served.
+ * @param int $timestamp
+ *   Timestamp of date that will be set in the 'Last-Modified' HTTP header.
+ */
+function locale_test_serve_translation_file($module, $translation_file, $timestamp) {
+  $translation_file_path = drupal_get_path('module', $module) . '/' . $translation_file;
+  $headers = array(
+    'Content-Type' => 'text/x-po; charset=utf-8',
+    'Last-Modified' => gmdate(DATE_RFC1123, $timestamp),
+  );
+  return file_transfer(drupal_realpath($translation_file_path), $headers);
+}
+
+/**
  * Implements hook_locale_translation_projects_alter().
  *
  * The translation status process by default checks the status of the installed
diff --git a/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one-8.x-1.1.de.po b/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one-8.x-1.1.de.po
new file mode 100644
index 0000000..adf6f55
--- /dev/null
+++ b/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one-8.x-1.1.de.po
@@ -0,0 +1,16 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: Drupal 8\\n"
+"MIME-Version: 1.0\\n"
+"Content-Type: text/plain; charset=UTF-8\\n"
+"Content-Transfer-Encoding: 8bit\\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
+
+msgid "January"
+msgstr "Januar_1"
+
+msgid "February"
+msgstr "Februar_1"
+
+msgid "March"
+msgstr "Marz_1"
diff --git a/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one.info.yml b/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one.info.yml
new file mode 100644
index 0000000..8490e1a
--- /dev/null
+++ b/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one.info.yml
@@ -0,0 +1,10 @@
+name: 'Locale test'
+description: 'Support module for locale module testing.'
+package: Testing
+version: '1.2'
+core: 8.x
+hidden: true
+'interface translation project': locale_test
+'interface translation server pattern': core/modules/locale/test/test.%language.po
+dependencies:
+  - locale
diff --git a/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one.install b/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one.install
new file mode 100644
index 0000000..15e18fa
--- /dev/null
+++ b/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one.install
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @file
+ * Sets up local po file.
+ */
+
+/**
+ * Implements hook_install().
+ *
+ * Copies the translation file provided by the module to the standard
+ * translations folder and sets timestamp of the new copy.
+ */
+function locale_test_contrib_one_install() {
+  locale_test_copy_translation_file(LOCALE_TEST_CONTRIB_ONE_MODULE_NAME, LOCALE_TEST_CONTRIB_ONE_PO_FILE, LOCALE_TEST_CONTRIB_ONE_PO_TIMESTAMP_LOCAL);
+}
diff --git a/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one.module b/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one.module
new file mode 100644
index 0000000..359921d
--- /dev/null
+++ b/core/modules/locale/tests/modules/locale_test_contrib_one/locale_test_contrib_one.module
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Mocks a custom module with local and remote po files.
+ *
+ * The purpose of this module is to mimic a contributed module with local and
+ * remote translation sources. It's used by Locale modules' tests, e.g. for
+ * testing automatic interface translation updates.
+ *
+ * It can also be used for manual testing. Comment out the "hidden: true"
+ * property in the module's .info.yml file to get started.
+ * When you enable the module it places a translation file into the configured
+ * translation directory (locale_test_contrib_one-8.x-1.1.de.po). The remote
+ * translation source is available at
+ * `/locale-test-remote-translations/8.x/locale_test_contrib_one-8.x-1.1.de.po`.
+ */
+
+/**
+ * Constants to control how the module will provide translation sources. Locale
+ * test mockup modules are almost identical with each other, these constants
+ * mean the differences between them. They also give us an overview what
+ * scenarios can be tested using these mockup modules.
+ */
+define('LOCALE_TEST_CONTRIB_ONE_MODULE_NAME', 'locale_test_contrib_one');
+define('LOCALE_TEST_CONTRIB_ONE_PO_FILE', 'locale_test_contrib_one-8.x-1.1.de.po');
+define('LOCALE_TEST_CONTRIB_ONE_REMOTE_TRANSLATION_ENDPOINT', 'locale-test-remote-translations');
+define('LOCALE_TEST_CONTRIB_ONE_PO_TIMESTAMP_LOCAL', LOCALE_TEST_TIMESTAMP_OLD);
+define('LOCALE_TEST_CONTRIB_ONE_PO_TIMESTAMP_REMOTE', LOCALE_TEST_TIMESTAMP_NEW);
+
+/**
+ * Implements hook_locale_translation_projects_alter().
+ *
+ * The po file supplied with the module is used as mock remote translation file
+ * as well as a local po file. Because the interface translation server pattern
+ * contains the host name of this site it is defined here and not in the
+ * .info.yml file.
+ */
+function locale_test_contrib_one_locale_translation_projects_alter(&$projects) {
+  $url = url(NULL, array('absolute' => TRUE)) . LOCALE_TEST_CONTRIB_ONE_REMOTE_TRANSLATION_ENDPOINT;
+
+  // Set the server URL and pattern to where the remote po file for this module
+  // can be found.
+  if (isset($projects[LOCALE_TEST_CONTRIB_ONE_MODULE_NAME])) {
+    $projects[LOCALE_TEST_CONTRIB_ONE_MODULE_NAME]['info']['interface translation server pattern'] = $url . '/%core/%project/%project-%version.%language.po';
+  }
+}
+
+/**
+ * Implements hook_menu().
+ *
+ * Provides a callback for the remote translation file.
+ */
+function locale_test_contrib_one_menu() {
+  $items = array();
+  $items[LOCALE_TEST_CONTRIB_ONE_REMOTE_TRANSLATION_ENDPOINT . '/' . DRUPAL_CORE_COMPATIBILITY . '/' . LOCALE_TEST_CONTRIB_ONE_PO_FILE] = array(
+    'title' => 'Testing: !po_file',
+    'title arguments' => array('!po_file' => LOCALE_TEST_CONTRIB_ONE_PO_FILE),
+    'page callback' => 'locale_test_contrib_one_remote_translation',
+    'access callback' => TRUE,
+    'type' => MENU_NORMAL_ITEM,
+  );
+  return $items;
+}
+
+/**
+ * Page callback: Serves remote translation file.
+ *
+ * This is the same translation file as the one used for locale po file testing,
+ * but we serve its content through this callback.
+ */
+function locale_test_contrib_one_remote_translation() {
+  return locale_test_serve_translation_file(LOCALE_TEST_CONTRIB_ONE_MODULE_NAME, LOCALE_TEST_CONTRIB_ONE_PO_FILE, LOCALE_TEST_CONTRIB_ONE_PO_TIMESTAMP_REMOTE);
+}
