diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
index 9d6b8d6..6f46d18 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
@@ -335,6 +335,57 @@ protected function doPostSave(EntityInterface $entity, $update) {
   /**
    * {@inheritdoc}
    */
+  public function delete(array $entities) {
+    if (!$entities) {
+      // If no entities were passed, do nothing.
+      return;
+    }
+
+    if ($this->entityType->isRevisionable()) {
+      $ids = array_map(function(ContentEntityInterface $entity) {
+        return $entity->id();
+      }, $entities);
+      $query = $this->getQuery()->allRevisions();
+      $query->condition($this->entityType->getKey('id'), $ids, 'IN');
+
+      $revisions = $this->loadMultipleRevisions(array_keys($query->execute()));
+      foreach ($revisions as $revision_id => $revision) {
+        // The default revision will be deleted as part of the entity delete.
+        if (!$revision->isDefaultRevision()) {
+          $this->doDeleteRevision($revision);
+        }
+      }
+    }
+    return parent::delete($entities);
+  }
+
+  /**
+   * Loads multiple revisions.
+   *
+   * The default implementation loads revisions one by one. This is a low
+   * performance but reliable solution for all storages.
+   *
+   * @param array $revision_ids
+   *   An array of revision IDs to load.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface[]
+   *   The specified entity revisions or empty array if none found.
+   *
+   * @internal
+   *   https://www.drupal.org/node/1730874 This method is internal until we
+   *   decide to add it to \Drupal\Core\Entity\EntityStorageInterface.
+   */
+  public function loadMultipleRevisions(array $revision_ids) {
+    $revisions = [];
+    foreach ($revision_ids as $revision_id) {
+      $revisions[$revision_id] = $this->loadRevision($revision_id);
+    }
+    return $revisions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   protected function doDelete($entities) {
     /** @var \Drupal\Core\Entity\ContentEntityInterface[] $entities */
     foreach ($entities as $entity) {
@@ -357,14 +408,27 @@ protected function doDelete($entities) {
   public function deleteRevision($revision_id) {
     /** @var \Drupal\Core\Entity\ContentEntityInterface $revision */
     if ($revision = $this->loadRevision($revision_id)) {
-      // Prevent deletion if this is the default revision.
-      if ($revision->isDefaultRevision()) {
-        throw new EntityStorageException('Default revision can not be deleted');
-      }
-      $this->invokeFieldMethod('deleteRevision', $revision);
-      $this->doDeleteRevisionFieldItems($revision);
-      $this->invokeHook('revision_delete', $revision);
+      $this->doDeleteRevision($revision);
+    }
+  }
+
+  /**
+   * Deletes a revision.
+   *
+   * @param \Drupal\Core\Entity\ContentEntityInterface $revision
+   *   The revision to delete.
+   *
+   * @throws \Drupal\Core\Entity\EntityStorageException
+   *   Thrown if the revision is the default revision.
+   */
+  protected function doDeleteRevision(ContentEntityInterface $revision) {
+    // Prevent deletion if this is the default revision.
+    if ($revision->isDefaultRevision()) {
+      throw new EntityStorageException('Default revision can not be deleted');
     }
+    $this->invokeFieldMethod('deleteRevision', $revision);
+    $this->doDeleteRevisionFieldItems($revision);
+    $this->invokeHook('revision_delete', $revision);
   }
 
   /**
@@ -569,22 +633,24 @@ protected function populateAffectedRevisionTranslations(ContentEntityInterface $
   }
 
   /**
-   * Ensures integer entity IDs are valid.
+   * Ensures integer entity key values are valid.
    *
    * The identifier sanitization provided by this method has been introduced
    * as Drupal used to rely on the database to facilitate this, which worked
    * correctly with MySQL but led to errors with other DBMS such as PostgreSQL.
    *
    * @param array $ids
-   *   The entity IDs to verify.
+   *   The entity key values to verify.
+   * @param array $key
+   *   (optional) The entity key to sanitise values for. Defaults to 'id'.
    *
    * @return array
-   *   The sanitized list of entity IDs.
+   *   The sanitized list of entity key values.
    */
-  protected function cleanIds(array $ids) {
+  protected function cleanIds(array $ids, $key = 'id') {
     $definitions = $this->entityManager->getBaseFieldDefinitions($this->entityTypeId);
-    $id_definition = $definitions[$this->entityType->getKey('id')];
-    if ($id_definition->getType() == 'integer') {
+    $field_name = $this->entityType->getKey($key);
+    if ($field_name && $definitions[$field_name]->getType() == 'integer') {
       $ids = array_filter($ids, function ($id) {
         return is_numeric($id) && $id == (int) $id;
       });
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 6df1af0..ef937e1 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -438,17 +438,68 @@ protected function getFromStorage(array $ids = NULL) {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function loadMultipleRevisions(array $revision_ids) {
+    $revisions = $this->doLoadMutlipleRevisions($revision_ids);
+
+    if ($revisions) {
+      // The hooks are invoked keyed by entity ID so we have to do one by one.
+      foreach ($revisions as $revision) {
+        $data = [$revision->id() => $revision];
+        $this->invokeStorageLoadHook($data);
+        $this->postLoad($data);
+      }
+    }
+
+    return $revisions;
+  }
+
+  /**
+   * Gets multiple entity revisions from the storage.
+   *
+   * @param array $revision_ids
+   *   Return entities that match these IDs.
+   *
+   * @return \Drupal\Core\Entity\ContentEntityInterface[]
+   *   Array of entity revisions from the storage.
+   */
+  protected function doLoadMutlipleRevisions(array $revision_ids) {
+    $revisions = array();
+
+    // Sanitize IDs. Before feeding ID array into buildQuery, check whether
+    // it is empty as this would load all entities.
+    $revision_ids = $this->cleanIds($revision_ids, 'revision');
+
+    if (!empty($revision_ids)) {
+      // Build and execute the query.
+      $query_result = $this->buildQuery(NULL, FALSE, $revision_ids)->execute();
+      $records = $query_result->fetchAllAssoc($this->revisionKey);
+
+      // Map the loaded records into entity objects and according fields.
+      if ($records) {
+        $revisions = $this->mapFromStorageRecords($records, TRUE, 'revision_id');
+      }
+    }
+
+    return $revisions;
+  }
+
+  /**
    * Maps from storage records to entity objects, and attaches fields.
    *
    * @param array $records
-   *   Associative array of query results, keyed on the entity ID.
+   *   Associative array of query results, keyed on the entity ID or revision
+   *   ID.
    * @param bool $load_from_revision
    *   Flag to indicate whether revisions should be loaded or not.
+   * @param string $record_key
+   *   How $records is keyed. Either 'entity_id' or 'revision_id'.
    *
    * @return array
    *   An array of entity objects implementing the EntityInterface.
    */
-  protected function mapFromStorageRecords(array $records, $load_from_revision = FALSE) {
+  protected function mapFromStorageRecords(array $records, $load_from_revision = FALSE, $record_key = 'entity_id') {
     if (!$records) {
       return [];
     }
@@ -478,8 +529,8 @@ protected function mapFromStorageRecords(array $records, $load_from_revision = F
     $translations = array_fill_keys(array_keys($values), []);
 
     // Load values from shared and dedicated tables.
-    $this->loadFromSharedTables($values, $translations);
-    $this->loadFromDedicatedTables($values, $load_from_revision);
+    $this->loadFromSharedTables($values, $translations, $record_key);
+    $this->loadFromDedicatedTables($values, $load_from_revision, $record_key);
 
     $entities = [];
     foreach ($values as $id => $entity_values) {
@@ -495,11 +546,20 @@ protected function mapFromStorageRecords(array $records, $load_from_revision = F
    * Loads values for fields stored in the shared data tables.
    *
    * @param array &$values
-   *   Associative array of entities values, keyed on the entity ID.
+   *   Associative array of entities values, keyed on the entity ID or revision
+   *   ID.
    * @param array &$translations
    *   List of translations, keyed on the entity ID.
+   * @param string $record_key
+   *   How $values is keyed. Either 'entity_id' or 'revision_id'.
    */
-  protected function loadFromSharedTables(array &$values, array &$translations) {
+  protected function loadFromSharedTables(array &$values, array &$translations, $record_key = 'entity_id') {
+    if ($record_key === 'revision_id') {
+      $record_key = $this->revisionKey;
+    }
+    else {
+      $record_key = $this->idKey;
+    }
     if ($this->dataTable) {
       // If a revision table is available, we need all the properties of the
       // latest revision. Otherwise we fall back to the data table.
@@ -507,8 +567,8 @@ protected function loadFromSharedTables(array &$values, array &$translations) {
       $alias = $this->revisionDataTable ? 'revision' : 'data';
       $query = $this->database->select($table, $alias, ['fetch' => \PDO::FETCH_ASSOC])
         ->fields($alias)
-        ->condition($alias . '.' . $this->idKey, array_keys($values), 'IN')
-        ->orderBy($alias . '.' . $this->idKey);
+        ->condition($alias . '.' . $record_key, array_keys($values), 'IN')
+        ->orderBy($alias . '.' . $record_key);
 
       $table_mapping = $this->getTableMapping();
       if ($this->revisionDataTable) {
@@ -553,7 +613,7 @@ protected function loadFromSharedTables(array &$values, array &$translations) {
 
       $result = $query->execute();
       foreach ($result as $row) {
-        $id = $row[$this->idKey];
+        $id = $row[$record_key];
 
         // Field values in default language are stored with
         // LanguageInterface::LANGCODE_DEFAULT as key.
@@ -644,18 +704,20 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value
    *   An array of entity IDs, or NULL to load all entities.
    * @param $revision_id
    *   The ID of the revision to load, or FALSE if this query is asking for the
-   *   most current revision(s).
+   *   most current revision(s) and $revision_ids is not provided instead.
+   * @param array $revision_ids
+   *   Revision IDs to load.
    *
    * @return \Drupal\Core\Database\Query\Select
    *   A SelectQuery object for loading the entity.
    */
-  protected function buildQuery($ids, $revision_id = FALSE) {
+  protected function buildQuery($ids, $revision_id = FALSE, $revision_ids = []) {
     $query = $this->database->select($this->entityType->getBaseTable(), 'base');
 
     $query->addTag($this->entityTypeId . '_load_multiple');
 
-    if ($revision_id) {
-      $query->join($this->revisionTable, 'revision', "revision.{$this->idKey} = base.{$this->idKey} AND revision.{$this->revisionKey} = :revisionId", [':revisionId' => $revision_id]);
+    if ($revision_id || $revision_ids) {
+      $query->join($this->revisionTable, 'revision', "revision.{$this->idKey} = base.{$this->idKey}");
     }
     elseif ($this->revisionTable) {
       $query->join($this->revisionTable, 'revision', "revision.{$this->revisionKey} = base.{$this->revisionKey}");
@@ -692,6 +754,13 @@ protected function buildQuery($ids, $revision_id = FALSE) {
     if ($ids) {
       $query->condition("base.{$this->idKey}", $ids, 'IN');
     }
+    if ($revision_id) {
+      $query->condition("revision.{$this->revisionKey}", $revision_id);
+    }
+    if ($revision_ids) {
+      $query->condition("revision.{$this->revisionKey}", $revision_ids, 'IN');
+    }
+
 
     return $query;
   }
@@ -1081,8 +1150,10 @@ protected function getQueryServiceName() {
    * @param bool $load_from_revision
    *   (optional) Flag to indicate whether revisions should be loaded or not,
    *   defaults to FALSE.
+   * @param string $record_key
+   *   How $records is keyed. Either 'entity_id' or 'revision_id'.
    */
-  protected function loadFromDedicatedTables(array &$values, $load_from_revision) {
+  protected function loadFromDedicatedTables(array &$values, $load_from_revision, $record_key = 'entity_id') {
     if (empty($values)) {
       return;
     }
@@ -1132,21 +1203,24 @@ protected function loadFromDedicatedTables(array &$values, $load_from_revision)
       foreach ($results as $row) {
         $bundle = $row->bundle;
 
+        $value_key = $row->$record_key;
         // Field values in default language are stored with
         // LanguageInterface::LANGCODE_DEFAULT as key.
         $langcode = LanguageInterface::LANGCODE_DEFAULT;
-        if ($this->langcodeKey && isset($default_langcodes[$row->entity_id]) && $row->langcode != $default_langcodes[$row->entity_id]) {
+        if ($this->langcodeKey && isset($default_langcodes[$value_key]) && $row->langcode != $default_langcodes[$value_key]) {
           $langcode = $row->langcode;
         }
 
-        if (!isset($values[$row->entity_id][$field_name][$langcode])) {
-          $values[$row->entity_id][$field_name][$langcode] = [];
+        if (!isset($values[$value_key][$field_name][$langcode])) {
+          $values[$value_key][$field_name][$langcode] = [];
+       // if (!isset($values[$row->entity_id][$field_name][$langcode])) {
+       //LC   $values[$row->entity_id][$field_name][$langcode] = [];
         }
 
         // Ensure that records for non-translatable fields having invalid
         // languages are skipped.
         if ($langcode == LanguageInterface::LANGCODE_DEFAULT || $definitions[$bundle][$field_name]->isTranslatable()) {
-          if ($storage_definition->getCardinality() == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || count($values[$row->entity_id][$field_name][$langcode]) < $storage_definition->getCardinality()) {
+          if ($storage_definition->getCardinality() == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || count($values[$value_key][$field_name][$langcode]) < $storage_definition->getCardinality()) {
             $item = [];
             // For each column declared by the field, populate the item from the
             // prefixed database column.
@@ -1157,7 +1231,7 @@ protected function loadFromDedicatedTables(array &$values, $load_from_revision)
             }
 
             // Add the item to the field values for the entity.
-            $values[$row->entity_id][$field_name][$langcode][] = $item;
+            $values[$value_key][$field_name][$langcode][] = $item;
           }
         }
       }
diff --git a/core/modules/file/src/Tests/FileFieldRevisionTest.php b/core/modules/file/src/Tests/FileFieldRevisionTest.php
index 7de496f..63afdc7 100644
--- a/core/modules/file/src/Tests/FileFieldRevisionTest.php
+++ b/core/modules/file/src/Tests/FileFieldRevisionTest.php
@@ -139,4 +139,62 @@ public function testRevisions() {
     $this->assertFileEntryNotExists($node_file_r1, 'Original file entry is deleted after deleting the entire node with two revisions remaining.');
   }
 
+  /**
+   * Testing deletion of entity with multiple revisions.
+   *
+   * Every entity revision referencing different file.
+   */
+  public function testDeleteEntityWithMultipleRevisions() {
+    /** @var \Drupal\node\NodeStorageInterface $node_storage */
+    $node_storage = $this->container->get('entity_type.manager')->getStorage('node');
+    $type_name = 'article';
+    $field_name = strtolower($this->randomMachineName());
+
+    $this->createFileField($field_name, 'node', $type_name);
+
+    $test_file = $this->getTestFile('text');
+
+    // Create a new node with the uploaded file.
+    $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
+
+    // Check that the file exists on disk and in the database.
+    $node_storage->resetCache([$nid]);
+    $node = $node_storage->load($nid);
+    $node_file_r1 = File::load($node->{$field_name}->target_id);
+
+    // Upload another file to the same node in a new revision.
+    $this->replaceNodeFile($test_file, $field_name, $nid);
+    $node_storage->resetCache([$nid]);
+    $node = $node_storage->load($nid);
+    $node_file_r2 = File::load($node->{$field_name}->target_id);
+
+    // Check that files from both revisions exists as permanent managed files.
+    $this->assertFileExists($node_file_r1, 'New file saved to disk on node creation.');
+    $this->assertFileEntryExists($node_file_r1, 'File entry exists in database on node creation.');
+    $this->assertFileIsPermanent($node_file_r1, 'File is permanent.');
+
+    $this->assertFileExists($node_file_r2, 'Replacement file exists on disk after creating new revision.');
+    $this->assertFileEntryExists($node_file_r2, 'Replacement file entry exists in database after creating new revision.');
+    $this->assertFileIsPermanent($node_file_r2, 'Replacement file is permanent.');
+
+    // Delete entire Entity.
+    $node_storage->delete([$node]);
+
+    // Execute crons related to files.
+    $this->container->get('database')->update('file_managed')
+      ->fields([
+        'changed' => REQUEST_TIME - ($this->config('system.file')->get('temporary_maximum_age') + 1),
+      ])
+      ->condition('fid', [$node_file_r1->id(), $node_file_r2->id()], 'IN')
+      ->execute();
+    $this->container->get('cron')->run();
+
+    // Check data integrity, both files should be removed.
+    $this->assertFileNotExists($node_file_r1, 'File from non-active revision is deleted from disk.');
+    $this->assertFileEntryNotExists($node_file_r1, 'File from non-active revision is deleted from database.');
+
+    $this->assertFileNotExists($node_file_r2, 'File from active revision is deleted from disk.');
+    $this->assertFileEntryNotExists($node_file_r2, 'File from active revision is deleted from database.');
+  }
+
 }
diff --git a/core/modules/file/src/Tests/FileOnTranslatedEntityTest.php b/core/modules/file/src/Tests/FileOnTranslatedEntityTest.php
index 5f1e707..acab089 100644
--- a/core/modules/file/src/Tests/FileOnTranslatedEntityTest.php
+++ b/core/modules/file/src/Tests/FileOnTranslatedEntityTest.php
@@ -24,15 +24,18 @@ class FileOnTranslatedEntityTest extends FileFieldTestBase {
   protected $fieldName;
 
   /**
+   * @var \Drupal\node\Entity\NodeType
+   */
+  protected $contentType;
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
 
     // Create the "Basic page" node type.
-    // @todo Remove the disabling of new revision creation in
-    //   https://www.drupal.org/node/1239558.
-    $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page', 'new_revision' => FALSE]);
+    $this->contentType = $this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic page', 'new_revision' => FALSE]);
 
     // Create a file field on the "Basic page" node type.
     $this->fieldName = strtolower($this->randomMachineName());
@@ -73,9 +76,9 @@ protected function setUp() {
   }
 
   /**
-   * Tests synced file fields on translated nodes.
+   * Tests synced file fields on translated nodes without revisions.
    */
-  public function testSyncedFiles() {
+  public function testSyncedFilesWithoutRevisions() {
     // Verify that the file field on the "Basic page" node type is translatable.
     $definitions = \Drupal::entityManager()->getFieldDefinitions('node', 'page');
     $this->assertTrue($definitions[$this->fieldName]->isTranslatable(), 'Node file field is translatable.');
@@ -106,15 +109,85 @@ public function testSyncedFiles() {
 
     \Drupal::entityTypeManager()->getStorage('file')->resetCache();
 
-    /* @var $file \Drupal\file\FileInterface */
+    // Ensure the file status of the first file permanent.
+    $file = File::load($first_fid);
+    $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.');
+
+    // Ensure the file status of the second file is permanent.
+    $file = File::load($second_fid);
+    $this->assertTrue($file->isPermanent(), 'Second file still exists and is permanent.');
+
+    // Delete the french translation.
+    $this->drupalPostForm('fr/node/' . $default_language_node->id() . '/delete', array(), t('Delete French translation'));
+
+    \Drupal::entityTypeManager()->getStorage('file')->resetCache();
+
+    // Ensure the first is untouched.
+    $file = File::load($first_fid);
+    $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.');
+
+    // Because there are no revisions the second file is now not used.
+    $file = File::load($second_fid);
+    $this->assertTrue($file->isTemporary(), 'Second file still exists and is temporary.');
+
+    // Delete the content.
+    $this->drupalPostForm('node/' . $default_language_node->id() . '/delete', array(), t('Delete'));
+
+    \Drupal::entityTypeManager()->getStorage('file')->resetCache();
+
+    // Ensure the file status of the all files are now temporary.
+    $file = File::load($first_fid);
+    $this->assertTrue($file->isTemporary(), 'First file still exists and is temporary.');
+
+    $file = File::load($second_fid);
+    $this->assertTrue($file->isTemporary(), 'Second file still exists and is temporary.');
+  }
+
+  /**
+   * Tests synced file fields on translated nodes with revisions.
+   */
+  public function testSyncedFilesWithRevisions() {
+    // Enable new revisions for each content edit.
+    $this->contentType->setNewRevision(TRUE);
+    $this->contentType->save();
+
+    // Verify that the file field on the "Basic page" node type is translatable.
+    $definitions = \Drupal::entityManager()->getFieldDefinitions('node', 'page');
+    $this->assertTrue($definitions[$this->fieldName]->isTranslatable(), 'Node file field is translatable.');
+
+    // Create a default language node.
+    $default_language_node = $this->drupalCreateNode(array('type' => 'page', 'title' => 'Lost in translation'));
+
+    // Edit the node to upload a file.
+    $edit = array();
+    $name = 'files[' . $this->fieldName . '_0]';
+    $edit[$name] = drupal_realpath($this->drupalGetTestFiles('text')[0]->uri);
+    $this->drupalPostForm('node/' . $default_language_node->id() . '/edit', $edit, t('Save'));
+    $first_fid = $this->getLastFileId();
+
+    // Translate the node into French: remove the existing file.
+    $this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/fr', array(), t('Remove'));
+
+    // Upload a different file.
+    $edit = array();
+    $edit['title[0][value]'] = 'Bill Murray';
+    $name = 'files[' . $this->fieldName . '_0]';
+    $edit[$name] = drupal_realpath($this->drupalGetTestFiles('text')[1]->uri);
+    $this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
+    // This inspects the HTML after the post of the translation, the file
+    // should be displayed on the original node.
+    $this->assertRaw('file--mime-text-plain');
+    $second_fid = $this->getLastFileId();
+
+    \Drupal::entityTypeManager()->getStorage('file')->resetCache();
 
     // Ensure the file status of the first file permanent.
     $file = File::load($first_fid);
-    $this->assertTrue($file->isPermanent());
+    $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.');
 
     // Ensure the file status of the second file is permanent.
     $file = File::load($second_fid);
-    $this->assertTrue($file->isPermanent());
+    $this->assertTrue($file->isPermanent(), 'Second file still exists and is permanent.');
 
     // Translate the node into dutch: remove the existing file.
     $this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/nl', [], t('Remove'));
@@ -138,11 +211,59 @@ public function testSyncedFiles() {
 
     // Ensure the file status of the second file is permanent.
     $file = File::load($second_fid);
-    $this->assertTrue($file->isPermanent());
+    $this->assertTrue($file->isPermanent(), 'Second file still exists and is permanent.');
+
+    // Ensure the file status of the third file is permanent.
+    $file = File::load($third_fid);
+    $this->assertTrue($file->isPermanent(), 'Third file still exists and is permanent.');
+
+    // Delete the third translation. As the Dutch translation is the latest
+    // revision this will cause the Dutch file to be deleted.
+    $this->drupalPostForm('nl/node/' . $default_language_node->id() . '/delete', array(), t('Delete Dutch translation'));
+    \Drupal::entityTypeManager()->getStorage('file')->resetCache();
+
+    // Ensure the first file is untouched.
+    $file = File::load($first_fid);
+    $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.');
+    // This inspects the HTML after the post of the translation, the file
+    // should be displayed on the original node.
+    $this->assertRaw('file--mime-text-plain');
+
+    // Ensure the file status of the second file is permanent.
+    $file = File::load($second_fid);
+    $this->assertTrue($file->isPermanent(), 'Second file still exists and is permanent.');
+
+    // Ensure the file status of the third file is permanent.
+    $file = File::load($third_fid);
+    $this->assertTrue($file->isTemporary(), 'Third file still exists and is temporary.');
+
+    // Re-translate the node into dutch: remove the existing file.
+    $this->drupalPostForm('node/' . $default_language_node->id() . '/translations/add/en/nl', array(), t('Remove'));
+
+    // Upload a different file.
+    $edit = array();
+    $edit['title[0][value]'] = 'Scarlett Johansson';
+    $name = 'files[' . $this->fieldName . '_0]';
+    $edit[$name] = drupal_realpath($this->drupalGetTestFiles('text')[2]->uri);
+    $this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
+    $third_fid = $this->getLastFileId();
+
+    \Drupal::entityTypeManager()->getStorage('file')->resetCache();
+
+    // Ensure the first file is untouched.
+    $file = File::load($first_fid);
+    $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.');
+    // This inspects the HTML after the post of the translation, the file
+    // should be displayed on the original node.
+    $this->assertRaw('file--mime-text-plain');
+
+    // Ensure the file status of the second file is permanent.
+    $file = File::load($second_fid);
+    $this->assertTrue($file->isPermanent(), 'Second file still exists and is permanent.');
 
     // Ensure the file status of the third file is permanent.
     $file = File::load($third_fid);
-    $this->assertTrue($file->isPermanent());
+    $this->assertTrue($file->isPermanent(), 'Third file still exists and is permanent.');
 
     // Edit the second translation: remove the existing file.
     $this->drupalPostForm('fr/node/' . $default_language_node->id() . '/edit', [], t('Remove'));
@@ -157,32 +278,39 @@ public function testSyncedFiles() {
 
     \Drupal::entityTypeManager()->getStorage('file')->resetCache();
 
-    // Ensure the first and third files are untouched.
+    // Ensure all are untouched because they are being used by different
+    // revisions.
     $file = File::load($first_fid);
     $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.');
 
-    $file = File::load($third_fid);
-    $this->assertTrue($file->isPermanent());
+    $file = File::load($second_fid);
+    $this->assertTrue($file->isPermanent(), 'Second file still exists and is permanent.');
 
-    // Ensure the file status of the replaced second file is permanent.
     $file = File::load($replaced_second_fid);
-    $this->assertTrue($file->isPermanent());
+    $this->assertTrue($file->isPermanent(), 'Second replaced file still exists and is permanent.');
+
+    $file = File::load($third_fid);
+    $this->assertTrue($file->isPermanent(), 'Third file still exists and is permanent.');
 
     // Delete the third translation.
     $this->drupalPostForm('nl/node/' . $default_language_node->id() . '/delete', [], t('Delete Dutch translation'));
 
     \Drupal::entityTypeManager()->getStorage('file')->resetCache();
 
-    // Ensure the first and replaced second files are untouched.
+    // All files still being used by different revisions.
     $file = File::load($first_fid);
     $this->assertTrue($file->isPermanent(), 'First file still exists and is permanent.');
 
+    $file = File::load($second_fid);
+    $this->assertTrue($file->isPermanent(), 'Second file still exists and is permanent.');
+
     $file = File::load($replaced_second_fid);
-    $this->assertTrue($file->isPermanent());
+    $this->assertTrue($file->isPermanent(), 'Second replaced file still exists and is permanent.');
 
-    // Ensure the file status of the third file is now temporary.
+    // The dutch translation only doesn't exist in the latest revision but is
+    // still used by the previous revision.
     $file = File::load($third_fid);
-    $this->assertTrue($file->isTemporary());
+    $this->assertTrue($file->isPermanent(), 'Third file still exists and is permanent.');
 
     // Delete the all translations.
     $this->drupalPostForm('node/' . $default_language_node->id() . '/delete', [], t('Delete all translations'));
@@ -193,8 +321,14 @@ public function testSyncedFiles() {
     $file = File::load($first_fid);
     $this->assertTrue($file->isTemporary(), 'First file still exists and is temporary.');
 
+    $file = File::load($second_fid);
+    $this->assertTrue($file->isTemporary(), 'Second file still exists and is temporary.');
+
     $file = File::load($replaced_second_fid);
-    $this->assertTrue($file->isTemporary());
+    $this->assertTrue($file->isTemporary(), 'Second replaced file still exists and is temporary.');
+
+    $file = File::load($third_fid);
+    $this->assertTrue($file->isTemporary(), 'Third file still exists and is temporary.');
   }
 
 }
diff --git a/core/modules/system/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module b/core/modules/system/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module
index 0325dbd..6341ea4 100644
--- a/core/modules/system/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module
+++ b/core/modules/system/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\RevisionableInterface;
 
 /**
  * Implements hook_entity_create().
@@ -344,6 +345,25 @@ function entity_crud_hook_test_user_predelete() {
 }
 
 /**
+ * Implements hook_entity_revision_delete().
+ */
+function entity_crud_hook_test_entity_revision_delete(EntityInterface $entity) {
+  if ($entity instanceof RevisionableInterface) {
+    $GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $entity->getEntityTypeId() . ' for revision ID ' . $entity->getRevisionId());
+  }
+  else {
+    $GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called for type ' . $entity->getEntityTypeId());
+  }
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_revision_delete() for node entities.
+ */
+function entity_crud_hook_test_node_revision_delete(EntityInterface $entity) {
+  $GLOBALS['entity_crud_hook_test'][] = (__FUNCTION__ . ' called on revision ID ' . $entity->getRevisionId());
+}
+
+/**
  * Implements hook_entity_delete().
  */
 function entity_crud_hook_test_entity_delete(EntityInterface $entity) {
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php
index 9b279a5..6ae5455 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityCrudHookTest.php
@@ -345,6 +345,50 @@ public function testNodeHooks() {
       'entity_crud_hook_test_node_delete called',
       'entity_crud_hook_test_entity_delete called for type node',
     ]);
+    ));
+
+    $node = Node::create([
+      'uid' => $account->id(),
+      'type' => 'article',
+      'title' => 'Test node',
+      'status' => 0,
+      'promote' => 0,
+      'sticky' => 0,
+      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
+      'created' => REQUEST_TIME,
+      'changed' => REQUEST_TIME,
+    ]);
+    $node->save();
+    $first_revision_id = $node->getRevisionId();
+    // Create a new revision.
+    $node->setNewRevision(TRUE);
+    $node->setPublished(TRUE);
+    $node->save();
+    $second_revision_id = $node->getRevisionId();
+    // Create a forward revision.
+    $node->setNewRevision(TRUE);
+    $node->setPublished(FALSE);
+    $node->isDefaultRevision(FALSE);
+    $node->save();
+    $third_revision_id = $node->getRevisionId();
+
+    $GLOBALS['entity_crud_hook_test'] = array();
+    $node->delete();
+
+    $this->assertHookMessageOrder(array(
+      'entity_crud_hook_test_node_revision_delete called on revision ID ' . $first_revision_id,
+      'entity_crud_hook_test_entity_revision_delete called for type node for revision ID ' . $first_revision_id,
+      'entity_crud_hook_test_node_revision_delete called on revision ID ' . $third_revision_id,
+      'entity_crud_hook_test_entity_revision_delete called for type node for revision ID ' . $third_revision_id,
+      'entity_crud_hook_test_node_predelete called',
+      'entity_crud_hook_test_entity_predelete called for type node',
+      'entity_crud_hook_test_node_delete called',
+      'entity_crud_hook_test_entity_delete called for type node',
+    ));
+
+    // Ensure default revision is deleted normally.
+    $this->assertFalse(in_array('entity_crud_hook_test_node_revision_delete called on revision ID ' . $second_revision_id, $GLOBALS['entity_crud_hook_test'], TRUE), 'As the second revision is the default revision if won\'t have the revision delete hooks fired.');
+    $this->assertFalse(in_array('entity_crud_hook_test_entity_revision_delete called for type node for revision ID ' . $second_revision_id, $GLOBALS['entity_crud_hook_test'], TRUE), 'As the second revision is the default revision if won\'t have the revision delete hooks fired.');
   }
 
   /**
