diff --git a/core/lib/Drupal/Component/Utility/DiffArray.php b/core/lib/Drupal/Component/Utility/DiffArray.php
index 719049e..b03be19 100644
--- a/core/lib/Drupal/Component/Utility/DiffArray.php
+++ b/core/lib/Drupal/Component/Utility/DiffArray.php
@@ -47,4 +47,35 @@ public static function diffAssocRecursive(array $array1, array $array2) {
     return $difference;
   }
 
+  /**
+   * Computes the difference of arrays.
+   *
+   * The main difference from the array_diff() is that this method does not
+   * remove duplicates. For example:
+   * @code
+   *   array_diff([1, 1, 1], [1]); // []
+   *   \Drupal\Component\Utility\DiffArray::diffOnce([1, 1, 1], [1]); // [1, 1]
+   * @endcode
+   *
+   * Keys are maintained from the $array1.
+   *
+   * @param array $array1
+   *   The array to compare from.
+   * @param array $array2
+   *   The array to compare to.
+   * @param bool $strict
+   *   The comparison mode.
+   *
+   * @return array
+   */
+  public static function diffOnce(array $array1, array $array2, $strict = FALSE) {
+    foreach ($array2 as $array) {
+      $pos = array_search($array, $array1, $strict);
+      if ($pos !== FALSE) {
+        unset($array1[$pos]);
+      }
+    }
+    return $array1;
+  }
+
 }
diff --git a/core/modules/editor/editor.install b/core/modules/editor/editor.install
index a07bd80..314bea4 100644
--- a/core/modules/editor/editor.install
+++ b/core/modules/editor/editor.install
@@ -20,3 +20,68 @@ function editor_update_8001() {
     }
   }
 }
+
+/**
+ * Recalculates file usages.
+ */
+function editor_update_8002(&$sandbox) {
+  $entity_load_limit = 50;
+
+  if (!\Drupal::moduleHandler()->moduleExists('file')) {
+    return;
+  }
+
+  if (!isset($sandbox['current'])) {
+    $file_ids = \Drupal::entityQuery('file')->execute();
+    if (empty($file_ids)) {
+      return;
+    }
+    $sandbox['data']['file_ids'] = $file_ids;
+
+    foreach (\Drupal::entityTypeManager()->getDefinitions() as $entity_type) {
+      if ($entity_type->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) {
+        $entity_type_id = $entity_type->id();
+        $entity_ids = \Drupal::entityQuery($entity_type_id)->execute();
+        if (!empty($entity_ids)) {
+          $sandbox['data']['entity_ids'][$entity_type_id] = $entity_ids;
+        }
+      }
+    }
+
+    $sandbox['current'] = 0;
+    $sandbox['max'] = count($sandbox['data']['file_ids']) + array_sum(array_map('count', $sandbox['data']['entity_ids']));
+  }
+  
+  if (!empty($sandbox['data']['file_ids'])) {
+
+    // Step 1: delete existing file usages.
+    /** @var \Drupal\file\FileUsage\FileUsageInterface $file_usage */
+    $file_usage = \Drupal::service('file.usage');
+    $files = \Drupal::entityTypeManager()
+      ->getStorage('file')
+      ->loadMultiple(array_splice($sandbox['data']['file_ids'], 0, $entity_load_limit));
+    foreach ($files as $file) {
+      $usages = $file_usage->listUsage($file);
+      if (!empty($usages['editor'])) {
+        $file_usage->delete($file, 'editor', NULL, NULL, 0);
+      }
+    }
+  }
+  else {
+
+    // Step 2: recalculate file usages.
+    reset($sandbox['data']['entity_ids']);
+    $entity_type_id = key($sandbox['data']['entity_ids']);
+    $entities = \Drupal::entityTypeManager()
+      ->getStorage($entity_type_id)
+      ->loadMultiple(array_splice($sandbox['data']['entity_ids'][$entity_type_id], 0, $entity_load_limit));
+    foreach ($entities as $entity) {
+      editor_entity_insert($entity);
+    }
+    $sandbox['data']['entity_ids'] = array_filter($sandbox['data']['entity_ids']);
+  }
+
+  $current_amount = count($sandbox['data']['file_ids']) + array_sum(array_map('count', $sandbox['data']['entity_ids']));
+  $sandbox['current'] = $sandbox['max'] - $current_amount;
+  $sandbox['#finished'] = empty($current_amount) ? 1 : ($sandbox['current'] / $sandbox['max']);
+}
diff --git a/core/modules/editor/editor.module b/core/modules/editor/editor.module
index 7c822ed..3bdf2cb 100644
--- a/core/modules/editor/editor.module
+++ b/core/modules/editor/editor.module
@@ -5,7 +5,10 @@
  * Adds bindings for client-side "text editors" to text formats.
  */
 
+use Drupal\Component\Utility\DiffArray;
 use Drupal\Component\Utility\Html;
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\TypedData\TranslatableInterface;
 use Drupal\editor\Entity\Editor;
 use Drupal\Core\Entity\FieldableEntityInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
@@ -369,13 +372,13 @@ function editor_entity_update(EntityInterface $entity) {
 
     // Detect file usages that should be incremented.
     foreach ($uuids_by_field as $field => $uuids) {
-      $added_files = array_diff($uuids_by_field[$field], $original_uuids_by_field[$field]);
+      $added_files = DiffArray::diffOnce($uuids_by_field[$field], $original_uuids_by_field[$field]);
       _editor_record_file_usage($added_files, $entity);
     }
 
     // Detect file usages that should be decremented.
     foreach ($original_uuids_by_field as $field => $uuids) {
-      $removed_files = array_diff($original_uuids_by_field[$field], $uuids_by_field[$field]);
+      $removed_files = DiffArray::diffOnce($original_uuids_by_field[$field], $uuids_by_field[$field]);
       _editor_delete_file_usage($removed_files, $entity, 1);
     }
   }
@@ -456,21 +459,38 @@ function _editor_delete_file_usage(array $uuids, EntityInterface $entity, $count
 /**
  * Finds all files referenced (data-entity-uuid) by formatted text fields.
  *
- * @param EntityInterface $entity
+ * @param FieldableEntityInterface $entity
  *   An entity whose fields to analyze.
  *
  * @return array
  *   An array of file entity UUIDs.
  */
-function _editor_get_file_uuids_by_field(EntityInterface $entity) {
+function _editor_get_file_uuids_by_field(FieldableEntityInterface $entity) {
   $uuids = array();
 
+  $field_definitions = $entity->getFieldDefinitions();
   $formatted_text_fields = _editor_get_formatted_text_fields($entity);
   foreach ($formatted_text_fields as $formatted_text_field) {
+
+    // In case of a translatable field, iterate over all its translations.
+    if ($field_definitions[$formatted_text_field]->isTranslatable() && $entity instanceof TranslatableInterface) {
+      $langcodes = array_keys($entity->getTranslationLanguages());
+    }
+    else {
+      $langcodes = [LanguageInterface::LANGCODE_NOT_APPLICABLE];
+    }
+
     $text = '';
-    $field_items = $entity->get($formatted_text_field);
-    foreach ($field_items as $field_item) {
-      $text .= $field_item->value;
+    foreach ($langcodes as $langcode) {
+      if ($langcode == LanguageInterface::LANGCODE_NOT_APPLICABLE) {
+        $field_items = $entity->get($formatted_text_field);
+      }
+      else {
+        $field_items = $entity->getTranslation($langcode)->get($formatted_text_field);
+      }
+      foreach ($field_items as $field_item) {
+        $text .= $field_item->value;
+      }
     }
     $uuids[$formatted_text_field] = _editor_parse_file_uuids($text);
   }
diff --git a/core/modules/editor/tests/src/Kernel/EditorFileUsageTest.php b/core/modules/editor/tests/src/Kernel/EditorFileUsageTest.php
index a8379d1..f0e9ca5 100644
--- a/core/modules/editor/tests/src/Kernel/EditorFileUsageTest.php
+++ b/core/modules/editor/tests/src/Kernel/EditorFileUsageTest.php
@@ -4,6 +4,7 @@
 
 use Drupal\editor\Entity\Editor;
 use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
+use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\node\Entity\Node;
 use Drupal\node\Entity\NodeType;
 use Drupal\file\Entity\File;
@@ -23,7 +24,14 @@ class EditorFileUsageTest extends EntityKernelTestBase {
    *
    * @var array
    */
-  public static $modules = array('editor', 'editor_test', 'node', 'file');
+  public static $modules = array('editor', 'editor_test', 'node', 'file', 'language');
+
+  /**
+   * Languages to enable.
+   *
+   * @var array
+   */
+  protected $langcodes = array('fr', 'en');
 
   protected function setUp() {
     parent::setUp();
@@ -41,8 +49,14 @@ protected function setUp() {
     ));
     $filtered_html_format->save();
 
+    // Add languages.
+    foreach ($this->langcodes as $langcode) {
+      ConfigurableLanguage::createFromLangcode($langcode)->save();
+    }
+
     // Set cardinality for body field.
     FieldStorageConfig::loadByName('node', 'body')
+      ->setTranslatable(TRUE)
       ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
       ->save();
 
@@ -69,6 +83,9 @@ public function testEditorEntityHooks() {
       2 => 'core/misc/help.png',
     );
 
+    /** @var \Drupal\file\FileUsage\FileUsageInterface $file_usage */
+    $file_usage = $this->container->get('file.usage');
+
     $image_entities = array();
     foreach ($image_paths as $key => $image_path) {
       $image = File::create();
@@ -76,7 +93,6 @@ public function testEditorEntityHooks() {
       $image->setFilename(drupal_basename($image->getFileUri()));
       $image->save();
 
-      $file_usage = $this->container->get('file.usage');
       $this->assertIdentical(array(), $file_usage->listUsage($image), 'The image ' . $image_paths[$key] . ' has zero usages.');
 
       $image_entities[] = $image;
@@ -104,6 +120,7 @@ public function testEditorEntityHooks() {
     // Test editor_entity_insert(): increment.
     $this->createUser();
     $node = $node = Node::create([
+      'language' => 'en',
       'type' => 'page',
       'title' => 'test',
       'body' => $body,
@@ -177,11 +194,68 @@ public function testEditorEntityHooks() {
       $this->assertIdentical(array('editor' => array('node' => array(1 => '2'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
     }
 
+    // Test editor_entity_translation_insert(): increment, by adding a new
+    // translation.
+    $translation = $node->addTranslation('fr', ['title' => 'test fr', 'body' => $original_values]);
+    $translation->save();
+    foreach ($image_entities as $key => $image_entity) {
+      $this->assertIdentical(array('editor' => array('node' => array(1 => '3'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 3 usages.');
+    }
+
+    // Test editor_entity_translation_delete(): decrement, by deleting a
+    // translation.
+    $node->removeTranslation('fr');
+    $node->save();
+    foreach ($image_entities as $key => $image_entity) {
+      $this->assertIdentical(array('editor' => array('node' => array(1 => '2'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
+    }
+
     // Test editor_entity_delete().
     $node->delete();
     foreach ($image_entities as $key => $image_entity) {
       $this->assertIdentical(array(), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has zero usages again.');
     }
+
+    // Prepare a new node having only one file entity referenced in the body
+    // field.
+    $image_entity_1 = $image_entities[0];
+    $body_value = '<img src="awesome-llama-0.jpg" data-entity-type="file" data-entity-uuid="' . $image_entity_1->uuid() . '" />';
+    $node = Node::create([
+      'language' => 'en',
+      'type' => 'page',
+      'title' => 'test',
+      'body' => [
+        0 => [
+          'value' => $body_value,
+          'format' => 'filtered_html',
+        ]
+      ],
+      'uid' => 1,
+    ]);
+    $node->save();
+    $nid = $node->id();
+    $this->assertIdentical(array('editor' => array('node' => array($nid => '1'))), $file_usage->listUsage($image_entity_1), 'The image ' . $image_entity_1->getFileUri() . ' has 1 usage.');
+
+    // Add a translation.
+    $translation = $node->addTranslation('fr', [
+      'title' => 'test fr',
+      'body' => $node->get('body')->getValue(),
+    ]);
+    $node->save();
+    $this->assertIdentical(array('editor' => array('node' => array($nid => '2'))), $file_usage->listUsage($image_entity_1), 'The image ' . $image_entity_1->getFileUri() . ' has 2 usages.');
+
+    // Replace image in the French translation.
+    $image_entity_2 = $image_entities[1];
+    $translation->get('body')->value = '<img src="awesome-llama-1.jpg" data-entity-type="file" data-entity-uuid="' . $image_entity_2->uuid() . '" />';;
+    $node->save();
+    $this->assertIdentical(array('editor' => array('node' => array($nid => '1'))), $file_usage->listUsage($image_entity_1), 'The image ' . $image_entity_1->getFileUri() . ' has 1 usage.');
+    $this->assertIdentical(array('editor' => array('node' => array($nid => '1'))), $file_usage->listUsage($image_entity_2), 'The image ' . $image_entity_2->getFileUri() . ' has 1 usage.');
+
+    // Re-save translation with no image and check if usage changed
+    $translation->get('body')->value = '';
+    $node->save();
+    $this->assertIdentical(array('editor' => array('node' => array($nid => '1'))), $file_usage->listUsage($image_entity_1), 'The image ' . $image_entity_1->getFileUri() . ' has 1 usage.');
+    $this->assertIdentical(array(), $file_usage->listUsage($image_entity_2), 'The image ' . $image_entity_2->getFileUri() . ' has zero usages.');
   }
 
 }
