diff --git a/lib/Drupal/Component/Utility/DiffArray.php b/lib/Drupal/Component/Utility/DiffArray.php
index 719049e..1b57b1d 100644
--- a/lib/Drupal/Component/Utility/DiffArray.php
+++ b/lib/Drupal/Component/Utility/DiffArray.php
@@ -47,4 +47,37 @@ class DiffArray {
     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.
+   *
+   * The comparison of items is always performed in the strict (===) mode.
+   *
+   * @param array $array1
+   *   The array to compare from.
+   * @param array $array2
+   *   The array to compare to.
+   *
+   * @return array
+   */
+  public static function diffOnce(array $array1, array $array2) {
+    foreach ($array2 as $item) {
+      // Always use strict mode because otherwise there could be fatal errors on
+      // object conversions.
+      $key = array_search($item, $array1, TRUE);
+      if ($key !== FALSE) {
+        unset($array1[$key]);
+      }
+    }
+    return $array1;
+  }
+
 }
diff --git a/modules/editor/editor.install b/modules/editor/editor.install
index a07bd80..cbbe80c 100644
--- a/modules/editor/editor.install
+++ b/modules/editor/editor.install
@@ -20,3 +20,86 @@ 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'])) {
+    $result = \Drupal::entityQuery('file')->execute();
+    if (empty($result)) {
+      return;
+    }
+    $sandbox['data']['file_ids'] = $result;
+
+    foreach (\Drupal::entityTypeManager()->getDefinitions() as $entity_type) {
+      if ($entity_type->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) {
+        $entity_type_id = $entity_type->id();
+        $query = \Drupal::entityQuery($entity_type_id);
+        if ($entity_type->isRevisionable()) {
+          $query->allRevisions();
+        }
+        $result = $query->execute();
+        if (!empty($result)) {
+          // We need result keys because they are either revision IDs (in case
+          // of revisionable entities) or entity IDs (in other case).
+          $sandbox['data']['entity_ids'][$entity_type_id] = array_keys($result);
+        }
+      }
+    }
+
+    $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']);
+    $ids = array_splice($sandbox['data']['entity_ids'][$entity_type_id], 0, $entity_load_limit);
+    $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
+    if ($entity_type->isRevisionable()) {
+      foreach ($ids as $revision_id) {
+        $entity = \Drupal::entityTypeManager()
+          ->getStorage($entity_type_id)
+          ->loadRevision($revision_id);
+        editor_entity_insert($entity);
+      }
+    }
+    else {
+      $entities = \Drupal::entityTypeManager()
+        ->getStorage($entity_type_id)
+        ->loadMultiple($ids);
+      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/modules/editor/editor.module b/modules/editor/editor.module
index d6fa16c..dbd95ff 100644
--- a/modules/editor/editor.module
+++ b/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;
@@ -383,13 +386,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);
     }
   }
@@ -470,24 +473,41 @@ 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 \Drupal\Core\Entity\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;
-      if ($field_item->getFieldDefinition()->getType() == 'text_with_summary') {
-        $text .= $field_item->summary;
-      }
+      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/modules/editor/src/Tests/Update/EditorUpdateTest.php b/modules/editor/src/Tests/Update/EditorUpdateTest.php
index e7f0f44..65cc6b7 100644
--- a/modules/editor/src/Tests/Update/EditorUpdateTest.php
+++ b/modules/editor/src/Tests/Update/EditorUpdateTest.php
@@ -2,6 +2,10 @@
 
 namespace Drupal\editor\Tests\Update;
 
+use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\file\Entity\File;
+use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\node\Entity\Node;
 use Drupal\system\Tests\Update\UpdatePathTestBase;
 
 /**
@@ -19,6 +23,7 @@ class EditorUpdateTest extends UpdatePathTestBase {
       __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
       // Simulate an un-synchronized environment.
       __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.editor-editor_update_8001.php',
+      __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.language-enabled.php',
     ];
   }
 
@@ -67,4 +72,77 @@ class EditorUpdateTest extends UpdatePathTestBase {
     $this->assertIdentical($format_full_html->get('status'), $editor_full_html->get('status'));
   }
 
+  /**
+   * Tests editor_update_8002().
+   *
+   * @see editor_update_8002()
+   */
+  public function testEditorUpdate8002() {
+
+    // Prepare second language.
+    ConfigurableLanguage::createFromLangcode('fr')->save();
+
+    // Make body field translatable.
+    FieldStorageConfig::loadByName('node', 'body')
+      ->setTranslatable(TRUE)
+      ->save();
+
+    // Prepare a test file.
+    $file_path = 'core/misc/druplicon.png';
+    $file = File::create();
+    $file->setFileUri($file_path);
+    $file->setFilename($this->container->get('file_system')->basename($file->getFileUri()));
+    $file->save();
+
+    $img_string = '<img src="' . $file_path . '" data-entity-type="file" data-entity-uuid="' . $file->uuid() . '" />';
+
+    // Initially reference file 2 times. Total file usages should be 2.
+    $node = Node::create([
+      'language' => 'en',
+      'type' => 'page',
+      'title' => 'test',
+      'body' => [
+        0 => [
+          'value' => str_repeat($img_string, 2),
+          'format' => 'full_html',
+        ],
+      ],
+      'uid' => 1,
+    ]);
+    $node->save();
+
+    // Add 2 more usages. Total file usages should be 4 now.
+    $node->get('body')->value = $node->get('body')->value . str_repeat($img_string, 2);
+    $node->save();
+
+    // Create a node translation having 5 file usages and force a new revision.
+    // Total file usages should be 15 now:
+    //  initial revision: en - 4, fr - does not exists,
+    //  new revision: en - 4, fr - 7.
+    $node->addTranslation('fr', [
+      'title' => 'test fr', 
+      'body' => [
+        0 => [
+          'value' => str_repeat($img_string, 7),
+          'format' => 'full_html',
+        ],
+      ],
+    ]);
+    $node->setNewRevision(TRUE);
+    $node->save();
+
+    // Now mess up file usages.
+    /** @var \Drupal\file\FileUsage\FileUsageInterface $file_usage */
+    $file_usage = $this->container->get('file.usage');
+    $file_usage->add($file, 'editor', 'node', $node->id(), 99999);
+
+    $usages = $file_usage->listUsage($file);
+    $this->assert($usages['editor']['node'][$node->id()] != 15, 'File usages are messed up.');
+
+    $this->runUpdates();
+
+    $usages = $file_usage->listUsage($file);
+    $this->assert($usages['editor']['node'][$node->id()] == 15, 'File usages are correct.');
+  }
+
 }
diff --git a/modules/editor/tests/src/Kernel/EditorFileUsageTest.php b/modules/editor/tests/src/Kernel/EditorFileUsageTest.php
index 9b7b487..1e72722 100644
--- a/modules/editor/tests/src/Kernel/EditorFileUsageTest.php
+++ b/modules/editor/tests/src/Kernel/EditorFileUsageTest.php
@@ -4,6 +4,7 @@ namespace Drupal\Tests\editor\Kernel;
 
 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 @@ class EditorFileUsageTest extends EntityKernelTestBase {
     ));
     $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 @@ class EditorFileUsageTest extends EntityKernelTestBase {
       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 @@ class EditorFileUsageTest extends EntityKernelTestBase {
       $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;
@@ -103,7 +119,8 @@ class EditorFileUsageTest extends EntityKernelTestBase {
 
     // Test editor_entity_insert(): increment.
     $this->createUser();
-    $node = $node = Node::create([
+    $node = Node::create([
+      'language' => 'en',
       'type' => 'page',
       'title' => 'test',
       'body' => $body,
@@ -199,11 +216,68 @@ class EditorFileUsageTest extends EntityKernelTestBase {
       $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.');
   }
 
 }
diff --git a/tests/Drupal/Tests/Core/Common/DiffArrayTest.php b/tests/Drupal/Tests/Core/Common/DiffArrayTest.php
index 4112eae..0d83349 100644
--- a/tests/Drupal/Tests/Core/Common/DiffArrayTest.php
+++ b/tests/Drupal/Tests/Core/Common/DiffArrayTest.php
@@ -13,23 +13,10 @@ use Drupal\Tests\UnitTestCase;
 class DiffArrayTest extends UnitTestCase {
 
   /**
-   * Array to use for testing.
-   *
-   * @var array
-   */
-  protected $array1;
-
-  /**
-   * Array to use for testing.
-   *
-   * @var array
+   * Tests DiffArray::diffAssocRecursive().
    */
-  protected $array2;
-
-  protected function setUp() {
-    parent::setUp();
-
-    $this->array1 = array(
+  public function testDiffAssocRecursive() {
+    $array1 = array(
       'same' => 'yes',
       'different' => 'no',
       'array_empty_diff' => array(),
@@ -40,7 +27,7 @@ class DiffArrayTest extends UnitTestCase {
       'string_compared_to_array' => 'value',
       'new' => 'new',
     );
-    $this->array2 = array(
+    $array2 = array(
       'same' => 'yes',
       'different' => 'yes',
       'array_empty_diff' => array(),
@@ -50,12 +37,7 @@ class DiffArrayTest extends UnitTestCase {
       'array_compared_to_string' => 'value',
       'string_compared_to_array' => array('value'),
     );
-  }
 
-  /**
-   * Tests DiffArray::diffAssocRecursive().
-   */
-  public function testDiffAssocRecursive() {
     $expected = array(
       'different' => 'no',
       'int_diff' => 1,
@@ -66,7 +48,55 @@ class DiffArrayTest extends UnitTestCase {
       'new' => 'new',
     );
 
-    $this->assertSame(DiffArray::diffAssocRecursive($this->array1, $this->array2), $expected);
+    $this->assertSame(DiffArray::diffAssocRecursive($array1, $array2), $expected);
+  }
+
+  /**
+   * Tests DiffArray::diffOnce().
+   */
+  public function testDiffOnce() {
+    $object1 = new \stdClass();
+    $object2 = new \stdClass();
+    $sets = [
+      [
+        'arrays' => [
+          [1, 1, 1, 1, 1],
+          [1, 1, 1],
+        ],
+        'expected' => [3 => 1, 4 => 1],
+      ],
+      [
+        'arrays' => [
+          [1, 1, 2, 2, 3, 3, 4],
+          ['4', 3, 2, 1],
+        ],
+        'expected' => [1 => 1, 3 => 2, 5 => 3, 6 => 4],
+      ],
+      [
+        'arrays' => [
+          [' ', '', 0, FALSE],
+          [0, 0, 0, 0, 'not used'],
+        ],
+        'expected' => [0 => ' ', 1 => '', 3 => FALSE],
+      ],
+      [
+        'arrays' => [
+          [$this, [], $object1, $object1, $object2],
+          [$object1, $object2, [], $this],
+        ],
+        'expected' => [3 => $object1],
+      ],
+      [
+        'arrays' => [
+          [['x' => ['y' => 'z']], [$object1]],
+          [1, 2, 3, '4', TRUE, [$object2], ['x' => ['y' => 'z']]],
+        ],
+        'expected' => [1 => [$object1]],
+      ],
+    ];
+    foreach ($sets as $set) {
+      $this->assertSame(DiffArray::diffOnce($set['arrays'][0], $set['arrays'][1]), $set['expected']);
+    }
   }
 
 }
