diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php
index 8d15cf4bc970b85f3bc4f429180f46cca9d99ac2..3e18d28b1ae8a63a3892fd8d36c2574955a117d3 100644
--- a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php
+++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php
@@ -148,7 +148,7 @@ public function import(Row $row, array $old_destination_id_values = []) {
     }
 
     $ids = $this->save($entity, $old_destination_id_values);
-    if (!empty($this->configuration['translations'])) {
+    if ($this->isTranslationDestination()) {
       $ids[] = $entity->language()->getId();
     }
     return $ids;
@@ -181,12 +181,15 @@ public function isTranslationDestination() {
    * {@inheritdoc}
    */
   public function getIds() {
+    $ids = [];
+
     $id_key = $this->getKey('id');
     $ids[$id_key] = $this->getDefinitionFromEntity($id_key);
 
     if ($this->isTranslationDestination()) {
-      if (!$langcode_key = $this->getKey('langcode')) {
-        throw new MigrateException('This entity type does not support translation.');
+      $langcode_key = $this->getKey('langcode');
+      if (!$langcode_key) {
+        throw new MigrateException(sprintf('The "%s" entity type does not support translations.', $this->storage->getEntityTypeId()));
       }
       $ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key);
     }
@@ -202,8 +205,8 @@ public function getIds() {
    * @param \Drupal\migrate\Row $row
    *   The row object to update from.
    *
-   * @return \Drupal\Core\Entity\EntityInterface|null
-   *   An updated entity, or NULL if it's the same as the one passed in.
+   * @return \Drupal\Core\Entity\EntityInterface
+   *   An updated entity from row values.
    */
   protected function updateEntity(EntityInterface $entity, Row $row) {
     $empty_destinations = $row->getEmptyDestinationProperties();
diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php
index 52d0f4fe1576ce557921b62020884d541b568abe..ff3f0071c7264d92bcd171480c2caaa10db7e984 100644
--- a/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php
+++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php
@@ -160,7 +160,9 @@ protected function getEntity(Row $row, array $old_destination_id_values) {
       $entity->enforceIsNew(FALSE);
       $entity->setNewRevision(TRUE);
     }
-    $this->updateEntity($entity, $row);
+    // We need to update the entity, so that the destination row IDs are
+    // correct.
+    $entity = $this->updateEntity($entity, $row);
     $entity->isDefaultRevision(FALSE);
     return $entity;
   }
@@ -177,10 +179,23 @@ protected function save(ContentEntityInterface $entity, array $old_destination_i
    * {@inheritdoc}
    */
   public function getIds() {
-    if ($key = $this->getKey('revision')) {
-      return [$key => $this->getDefinitionFromEntity($key)];
+    $ids = [];
+
+    $revision_key = $this->getKey('revision');
+    if (!$revision_key) {
+      throw new MigrateException(sprintf('The "%s" entity type does not support revisions.', $this->storage->getEntityTypeId()));
     }
-    throw new MigrateException('This entity type does not support revisions.');
+    $ids[$revision_key] = $this->getDefinitionFromEntity($revision_key);
+
+    if ($this->isTranslationDestination()) {
+      $langcode_key = $this->getKey('langcode');
+      if (!$langcode_key) {
+        throw new MigrateException(sprintf('The "%s" entity type does not support translations.', $this->storage->getEntityTypeId()));
+      }
+      $ids[$langcode_key] = $this->getDefinitionFromEntity($langcode_key);
+    }
+
+    return $ids;
   }
 
   /**
diff --git a/core/modules/migrate/tests/src/Kernel/Plugin/EntityRevisionTest.php b/core/modules/migrate/tests/src/Kernel/Plugin/EntityRevisionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..d15446fbad90974c1184aa7a72f814c29764716d
--- /dev/null
+++ b/core/modules/migrate/tests/src/Kernel/Plugin/EntityRevisionTest.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace Drupal\Tests\migrate\Kernel\Plugin;
+
+use Drupal\language\Entity\ConfigurableLanguage;
+use Drupal\node\Entity\Node;
+use Drupal\Tests\migrate\Kernel\MigrateTestBase;
+use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
+
+/**
+ * Tests the EntityRevision destination plugin.
+ *
+ * @group migrate
+ */
+class EntityRevisionTest extends MigrateTestBase {
+
+  use ContentTypeCreationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'content_translation',
+    'field',
+    'filter',
+    'language',
+    'node',
+    'system',
+    'text',
+    'user',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->installConfig('node');
+    $this->installSchema('node', ['node_access']);
+    $this->installEntitySchema('node');
+    $this->installEntitySchema('user');
+  }
+
+  /**
+   * Tests that EntityRevision correctly handles revision translations.
+   */
+  public function testRevisionTranslation() {
+    ConfigurableLanguage::createFromLangcode('fr')->save();
+
+    /** @var \Drupal\node\NodeInterface $node */
+    $node = Node::create([
+      'type' => $this->createContentType()->id(),
+      'title' => 'Default 1',
+    ]);
+    $node->addTranslation('fr', [
+      'title' => 'French 1',
+    ]);
+    $node->save();
+    $node->setNewRevision();
+    $node->setTitle('Default 2');
+    $node->getTranslation('fr')->setTitle('French 2');
+    $node->save();
+
+    $migration = [
+      'source' => [
+        'plugin' => 'embedded_data',
+        'data_rows' => [
+          [
+            'nid' => $node->id(),
+            'vid' => $node->getRevisionId(),
+            'langcode' => 'fr',
+            'title' => 'Titre nouveau, tabarnak!',
+          ],
+        ],
+        'ids' => [
+          'nid' => [
+            'type' => 'integer',
+          ],
+          'vid' => [
+            'type' => 'integer',
+          ],
+          'langcode' => [
+            'type' => 'string',
+          ],
+        ],
+      ],
+      'process' => [
+        'nid' => 'nid',
+        'vid' => 'vid',
+        'langcode' => 'langcode',
+        'title' => 'title',
+      ],
+      'destination' => [
+        'plugin' => 'entity_revision:node',
+        'translations' => TRUE,
+      ],
+    ];
+
+    /** @var \Drupal\migrate\Plugin\MigrationInterface $migration */
+    $migration = $this->container
+      ->get('plugin.manager.migration')
+      ->createStubMigration($migration);
+
+    $this->executeMigration($migration);
+
+    // The entity_revision destination uses the revision ID and langcode as its
+    // keys (the langcode is only used if the destination is configured for
+    // translation), so we should be able to look up the source IDs by revision
+    // ID and langcode.
+    $source_ids = $migration->getIdMap()->lookupSourceID([
+      'vid' => $node->getRevisionId(),
+      'langcode' => 'fr',
+    ]);
+    $this->assertNotEmpty($source_ids);
+    $this->assertSame($node->id(), $source_ids['nid']);
+    $this->assertSame($node->getRevisionId(), $source_ids['vid']);
+    $this->assertSame('fr', $source_ids['langcode']);
+
+    // Confirm the french revision was used in the migration, instead of the
+    // default revision.
+    /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
+    $entity_type_manager = \Drupal::entityTypeManager();
+    $revision = $entity_type_manager->getStorage('node')->loadRevision(1);
+    $this->assertSame('Default 1', $revision->label());
+    $this->assertSame('French 1', $revision->getTranslation('fr')->label());
+    $revision = $entity_type_manager->getStorage('node')->loadRevision(2);
+    $this->assertSame('Default 2', $revision->label());
+    $this->assertSame('Titre nouveau, tabarnak!', $revision->getTranslation('fr')->label());
+  }
+
+}
diff --git a/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php b/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php
index 9f435235608ed40d6e218e8b182ca6151e0bda0c..d0fd987dc32f5b573a52bc7d7ed7b9eec8d92fad 100644
--- a/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php
+++ b/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php
@@ -60,6 +60,7 @@ protected function setUp() {
     $this->entityType = $this->prophesize(EntityTypeInterface::class);
     $this->entityType->getPluralLabel()->willReturn('wonkiness');
     $this->storage->getEntityType()->willReturn($this->entityType->reveal());
+    $this->storage->getEntityTypeId()->willReturn('foo');
 
     $this->entityManager = $this->prophesize(EntityManagerInterface::class);
   }
@@ -129,7 +130,7 @@ public function testUntranslatable() {
       $this->entityManager->reveal(),
       $this->prophesize(FieldTypePluginManagerInterface::class)->reveal()
     );
-    $this->setExpectedException(MigrateException::class, 'This entity type does not support translation');
+    $this->setExpectedException(MigrateException::class, 'The "foo" entity type does not support translations.');
     $destination->getIds();
   }
 
diff --git a/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityRevisionTest.php b/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityRevisionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3fb4b7dbda14bf4b40363224a20ef7a9915d26e3
--- /dev/null
+++ b/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityRevisionTest.php
@@ -0,0 +1,162 @@
+<?php
+
+namespace Drupal\Tests\migrate\Unit\Plugin\migrate\destination;
+
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Field\BaseFieldDefinition;
+use Drupal\Core\Field\FieldTypePluginManagerInterface;
+use Drupal\migrate\MigrateException;
+use Drupal\migrate\Plugin\MigrationInterface;
+use Drupal\migrate\Plugin\migrate\destination\EntityRevision;
+use Drupal\migrate\Row;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests entity revision destination functionality.
+ *
+ * @coversDefaultClass \Drupal\migrate\Plugin\migrate\destination\EntityRevision
+ * @group migrate
+ */
+class EntityRevisionTest extends UnitTestCase {
+
+  /**
+   * The migration.
+   *
+   * @var \Drupal\migrate\Plugin\MigrationInterface
+   */
+  protected $migration;
+
+  /**
+   * The entity storage.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface
+   */
+  protected $storage;
+
+  /**
+   * The entity type.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface
+   */
+  protected $entityType;
+
+  /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->migration = $this->prophesize(MigrationInterface::class);
+    $this->storage = $this->prophesize(EntityStorageInterface::class);
+
+    $this->entityType = $this->prophesize(EntityTypeInterface::class);
+    $this->entityType->getSingularLabel()->willReturn('foo');
+    $this->entityType->getPluralLabel()->willReturn('bar');
+    $this->storage->getEntityType()->willReturn($this->entityType->reveal());
+    $this->storage->getEntityTypeId()->willReturn('foo');
+
+    $this->entityManager = $this->prophesize(EntityManagerInterface::class);
+  }
+
+  /**
+   * Tests that revision destination fails for unrevisionable entities.
+   */
+  public function testUnrevisionable() {
+    $this->entityType->getKey('id')->willReturn('id');
+    $this->entityType->getKey('revision')->willReturn('');
+    $this->entityManager->getBaseFieldDefinitions('foo')
+      ->willReturn([
+        'id' => BaseFieldDefinitionTest::create('integer'),
+      ]);
+
+    $destination = new EntityRevisionTestDestination(
+      [],
+      '',
+      [],
+      $this->migration->reveal(),
+      $this->storage->reveal(),
+      [],
+      $this->entityManager->reveal(),
+      $this->prophesize(FieldTypePluginManagerInterface::class)->reveal()
+    );
+    $this->setExpectedException(MigrateException::class, 'The "foo" entity type does not support revisions.');
+    $destination->getIds();
+  }
+
+  /**
+   * Tests that translation destination fails for untranslatable entities.
+   */
+  public function testUntranslatable() {
+    $this->entityType->getKey('id')->willReturn('id');
+    $this->entityType->getKey('revision')->willReturn('vid');
+    $this->entityType->getKey('langcode')->willReturn('');
+    $this->entityManager->getBaseFieldDefinitions('foo')
+      ->willReturn([
+        'id' => BaseFieldDefinitionTest::create('integer'),
+        'vid' => BaseFieldDefinitionTest::create('integer'),
+      ]);
+
+    $destination = new EntityRevisionTestDestination(
+      ['translations' => TRUE],
+      '',
+      [],
+      $this->migration->reveal(),
+      $this->storage->reveal(),
+      [],
+      $this->entityManager->reveal(),
+      $this->prophesize(FieldTypePluginManagerInterface::class)->reveal()
+    );
+    $this->setExpectedException(MigrateException::class, 'The "foo" entity type does not support translations.');
+    $destination->getIds();
+  }
+
+}
+
+/**
+ * Stub class for testing EntityRevision methods.
+ */
+class EntityRevisionTestDestination extends EntityRevision {
+
+  private $entity = NULL;
+
+  public function setEntity($entity) {
+    $this->entity = $entity;
+  }
+
+  protected function getEntity(Row $row, array $old_destination_id_values) {
+    return $this->entity;
+  }
+
+  public static function getEntityTypeId($plugin_id) {
+    return 'foo';
+  }
+
+}
+
+/**
+ * Stub class for BaseFieldDefinition.
+ */
+class BaseFieldDefinitionTest extends BaseFieldDefinition {
+
+  public static function create($type) {
+    return new static([]);
+  }
+
+  public function getSettings() {
+    return [];
+  }
+
+  public function getType() {
+    return 'integer';
+  }
+
+}
diff --git a/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php b/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php
index 8a6fe9a43dbc99157d3156be5e1fcb55b5c782ec..5a63f06e450f785f18bdf1403b06c2492069f4ac 100644
--- a/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php
+++ b/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php
@@ -230,6 +230,8 @@ public function save(ContentEntityInterface $entity, array $old_destination_id_v
    * workings of its implementation which would trickle into mock assertions. An
    * empty implementation avoids this.
    */
-  protected function updateEntity(EntityInterface $entity, Row $row) {}
+  protected function updateEntity(EntityInterface $entity, Row $row) {
+    return $entity;
+  }
 
 }
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php b/core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php
index 6be7801b6e2fd2148ae6a7a89e527bf5536fda0e..db44c6345058076a553c9cde0935f81d4b0a49ec 100644
--- a/core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php
+++ b/core/modules/migrate_drupal/tests/src/Kernel/d6/EntityContentBaseTest.php
@@ -115,7 +115,7 @@ public function testUntranslatable() {
     // Match the expected message. Can't use default argument types, because
     // we need to convert to string from TranslatableMarkup.
     $argument = Argument::that(function ($msg) {
-      return strpos((string) $msg, "This entity type does not support translation") !== FALSE;
+      return strpos((string) $msg, htmlentities('The "no_language_entity_test" entity type does not support translations.')) !== FALSE;
     });
     $message->display($argument, Argument::any())
       ->shouldBeCalled();