diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php
index 6a2fb98..f9ab09f 100644
--- a/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php
+++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php
@@ -7,11 +7,13 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Field\FieldTypePluginManagerInterface;
+use Drupal\Core\TypedData\TranslatableInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
 use Drupal\migrate\Plugin\MigrationInterface;
 use Drupal\migrate\MigrateException;
 use Drupal\migrate\Plugin\MigrateIdMapInterface;
 use Drupal\migrate\Row;
+
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -122,6 +124,19 @@ public function getIds() {
    *   The row object to update from.
    */
   protected function updateEntity(EntityInterface $entity, Row $row) {
+    if ($entity instanceof TranslatableInterface) {
+      $property = $this->storage->getEntityType()->getKey('langcode');
+
+      if ($row->hasDestinationProperty($property)) {
+        $language = $row->getDestinationProperty($property);
+
+        if (!$entity->hasTranslation($language)) {
+          $entity->addTranslation($language);
+        }
+        $entity = $entity->getTranslation($language);
+      }
+    }
+
     // If the migration has specified a list of properties to be overwritten,
     // clone the row with an empty set of destination values, and re-add only
     // the specified properties.
diff --git a/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php
index 62469e7..fbc39eb 100644
--- a/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php
+++ b/core/modules/migrate/src/Plugin/migrate/destination/EntityRevision.php
@@ -41,6 +41,10 @@ protected function getEntity(Row $row, array $old_destination_id_values) {
       $row->getDestinationProperty($this->getKey('revision'));
     if (!empty($revision_id) && ($entity = $this->storage->loadRevision($revision_id))) {
       $entity->setNewRevision(FALSE);
+
+      // Check if we're the default.
+      $default = $this->storage->load($entity->id());
+      $entity->isDefaultRevision($default->getRevisionId() === $revision_id);
     }
     else {
       $entity_id = $row->getDestinationProperty($this->getKey('id'));
@@ -54,9 +58,10 @@ protected function getEntity(Row $row, array $old_destination_id_values) {
 
       $entity->enforceIsNew(FALSE);
       $entity->setNewRevision(TRUE);
+      $entity->isDefaultRevision(FALSE);
     }
+
     $this->updateEntity($entity, $row);
-    $entity->isDefaultRevision(FALSE);
     return $entity;
   }
 
@@ -65,7 +70,13 @@ protected function getEntity(Row $row, array $old_destination_id_values) {
    */
   protected function save(ContentEntityInterface $entity, array $old_destination_id_values = array()) {
     $entity->save();
-    return array($entity->getRevisionId());
+    $ids = array($entity->getRevisionId());
+
+    if (isset($this->configuration['translated']) && $this->configuration['translated']) {
+      $ids[] = $entity->language()->getId();
+    }
+
+    return $ids;
   }
 
   /**
@@ -74,9 +85,21 @@ protected function save(ContentEntityInterface $entity, array $old_destination_i
   public function getIds() {
     if ($key = $this->getKey('revision')) {
       $ids[$key]['type'] = 'integer';
-      return $ids;
     }
-    throw new MigrateException('This entity type does not support revisions.');
+    else {
+      throw new MigrateException('This entity type does not support revisions.');
+    }
+
+    if (isset($this->configuration['translated']) && $this->configuration['translated']) {
+      if ($key = $this->getKey('langcode')) {
+        $ids[$key]['type'] = 'string';
+      }
+      else {
+        throw new MigrateException('This entity type does not support translation.');
+      }
+    }
+
+    return $ids;
   }
 
 }
diff --git a/core/modules/migrate/src/Tests/MigrateFilterExecutable.php b/core/modules/migrate/src/Tests/MigrateFilterExecutable.php
new file mode 100644
index 0000000..422904e
--- /dev/null
+++ b/core/modules/migrate/src/Tests/MigrateFilterExecutable.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\Tests\MigrateFilterExecutable.
+ */
+
+namespace Drupal\migrate\Tests;
+
+use Drupal\migrate\Entity\MigrationInterface;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate\MigrateMessageInterface;
+use Drupal\migrate\MigrateSkipRowException;
+use Drupal\migrate\Row;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+/**
+ * A MigrateExecutable that allows filtering the imported rows.
+ */
+class MigrateFilterExecutable extends MigrateExecutable {
+  /**
+   * Predicate for source rows to migrate.
+   *
+   * @var callback $filter
+   */
+  protected $filter;
+
+  /**
+   * {@inheritdoc}
+   *
+   * @param callback $filter
+   *   Predicate for source rows to migrate.
+   */
+  public function __construct(MigrationInterface $migration, MigrateMessageInterface $message, EventDispatcherInterface $event_dispatcher = NULL, $filter = NULL) {
+    parent::__construct($migration, $message, $event_dispatcher);
+    $this->filter = $filter;
+  }
+
+  public function processRow(Row $row, array $process = NULL, $value = NULL) {
+    if (!call_user_func($this->filter, $this->migration, $row)) {
+      throw new MigrateSkipRowException("Row filtered", FALSE);
+    }
+    parent::processRow($row, $process, $value);
+  }
+
+}
diff --git a/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php b/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php
index f1e288e..2759ad7 100644
--- a/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php
+++ b/core/modules/migrate/tests/src/Unit/destination/EntityRevisionTest.php
@@ -50,6 +50,22 @@ protected function setUp() {
     $this->storage = $this->prophesize('\Drupal\Core\Entity\EntityStorageInterface');
     $this->entityManager = $this->prophesize('\Drupal\Core\Entity\EntityManagerInterface');
     $this->fieldTypeManager = $this->prophesize('\Drupal\Core\Field\FieldTypePluginManagerInterface');
+
+    // Add a mock for getting keys.
+    $entity_type = $this->prophesize('\Drupal\Core\Entity\EntityTypeInterface');
+    $entity_type->getKey('id')->willReturn('nid');
+    $entity_type->getKey('revision')->willReturn('vid');
+    $this->storage->getEntityType()->willReturn($entity_type->reveal());
+
+    // Add the default revision of the entity.
+    // Claim to be revision 12 of node 5.
+    $default = $this->prophesize('\Drupal\Core\Entity\EntityInterface')
+      ->willImplement('\Drupal\Core\Entity\RevisionableInterface');
+    $default->getRevisionId()
+      ->willReturn(12);
+    $default->id()->willReturn(5);
+    $this->storage->load(5)
+      ->willReturn($default->reveal());
   }
 
   /**
@@ -62,6 +78,14 @@ public function testGetEntityDestinationValues() {
     // Return a dummy because we don't care what gets called.
     $entity = $this->prophesize('\Drupal\Core\Entity\EntityInterface')
       ->willImplement('\Drupal\Core\Entity\RevisionableInterface');
+
+    // Make sure we check whether or not we're the default.
+    $entity->id()->willReturn(5);
+    $this->storage->load(5)->shouldBeCalled();
+    $entity->isDefaultRevision(TRUE)->shouldBeCalled();
+
+    $entity->setNewRevision(FALSE)->shouldBeCalled();
+
     // Assert that the first ID from the destination values is used to load the
     // entity.
     $this->storage->loadRevision(12)
@@ -81,19 +105,19 @@ public function testGetEntityUpdateRevision() {
     $entity = $this->prophesize('\Drupal\Core\Entity\EntityInterface')
       ->willImplement('\Drupal\Core\Entity\RevisionableInterface');
 
-    $entity_type = $this->prophesize('\Drupal\Core\Entity\EntityTypeInterface');
-    $entity_type->getKey('id')->willReturn('nid');
-    $entity_type->getKey('revision')->willReturn('vid');
-    $this->storage->getEntityType()->willReturn($entity_type->reveal());
-
     // Assert we load the correct revision.
     $this->storage->loadRevision(2)
       ->shouldBeCalled()
       ->willReturn($entity->reveal());
-    // Make sure its set as an update and not the default revision.
-    $entity->setNewRevision(FALSE)->shouldBeCalled();
+
+    // Make sure we check whether or not we're the default.
+    $entity->id()->willReturn(5);
+    $this->storage->load(5)->shouldBeCalled();
     $entity->isDefaultRevision(FALSE)->shouldBeCalled();
 
+    // Make sure its set as an update.
+    $entity->setNewRevision(FALSE)->shouldBeCalled();
+
     $row = new Row(['nid' => 1, 'vid' => 2], ['nid' => 1, 'vid' => 2]);
     $row->setDestinationProperty('vid', 2);
     $this->assertEquals($entity->reveal(), $destination->getEntity($row, []));
@@ -109,11 +133,6 @@ public function testGetEntityNewRevision() {
     $entity = $this->prophesize('\Drupal\Core\Entity\EntityInterface')
       ->willImplement('\Drupal\Core\Entity\RevisionableInterface');
 
-    $entity_type = $this->prophesize('\Drupal\Core\Entity\EntityTypeInterface');
-    $entity_type->getKey('id')->willReturn('nid');
-    $entity_type->getKey('revision')->willReturn('vid');
-    $this->storage->getEntityType()->willReturn($entity_type->reveal());
-
     // Enforce is new should be disabled.
     $entity->enforceIsNew(FALSE)->shouldBeCalled();
     // And toggle this as new revision but not the default revision.
@@ -138,11 +157,6 @@ public function testGetEntityNewRevision() {
   public function testGetEntityLoadFailure() {
     $destination = $this->getEntityRevisionDestination([]);
 
-    $entity_type = $this->prophesize('\Drupal\Core\Entity\EntityTypeInterface');
-    $entity_type->getKey('id')->willReturn('nid');
-    $entity_type->getKey('revision')->willReturn('vid');
-    $this->storage->getEntityType()->willReturn($entity_type->reveal());
-
     // Return a failed load and make sure we don't fail and we return FALSE.
     $this->storage->load(1)
       ->shouldBeCalled()
diff --git a/core/modules/migrate_drupal/tests/fixtures/drupal6.php b/core/modules/migrate_drupal/tests/fixtures/drupal6.php
index 1ca67a5..9a55470 100644
--- a/core/modules/migrate_drupal/tests/fixtures/drupal6.php
+++ b/core/modules/migrate_drupal/tests/fixtures/drupal6.php
@@ -34727,7 +34727,7 @@
   'access_callback' => 'user_access',
   'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
   'page_callback' => 'drupal_get_form',
-  'page_arguments' => 'a:2:{i:0;s:14:"node_type_form";i:1;O:8:"stdClass":14:{s:4:"type";s:7:"company";s:4:"name";s:7:"Company";s:6:"module";s:4:"node";s:11:"description";s:17:"Company node type";s:4:"help";s:0:"";s:9:"has_title";s:1:"1";s:11:"title_label";s:4:"Name";s:8:"has_body";s:1:"1";s:10:"body_label";s:11:"Description";s:14:"min_word_count";s:2:"20";s:6:"custom";s:1:"0";s:8:"modified";s:1:"0";s:6:"locked";s:1:"0";s:9:"orig_type";s:7:"company";}}',
+  'page_arguments' => 'a:2:{i:0;s:14:"node_type_form";i:1;O:8:"stdClass":14:{s:4:"type";s:7:"company";s:4:"name";s:7:"Company";s:6:"module";s:4:"node";s:11:"description";s:17:"Company node type";s:4:"help";s:0:"";s:9:"has_title";s:1:"1";s:11:"title_label";s:4:"Name";s:8:"has_body";s:1:"1";s:10:"body_label";s:11:"Description";s:14:"min_word_count";s:1:"0";s:6:"custom";s:1:"0";s:8:"modified";s:1:"1";s:6:"locked";s:1:"0";s:9:"orig_type";s:7:"company";}}',
   'fit' => '15',
   'number_parts' => '4',
   'tab_parent' => '',
@@ -34749,7 +34749,7 @@
   'access_callback' => 'user_access',
   'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
   'page_callback' => 'drupal_get_form',
-  'page_arguments' => 'a:2:{i:0;s:24:"node_type_delete_confirm";i:1;O:8:"stdClass":14:{s:4:"type";s:7:"company";s:4:"name";s:7:"Company";s:6:"module";s:4:"node";s:11:"description";s:17:"Company node type";s:4:"help";s:0:"";s:9:"has_title";s:1:"1";s:11:"title_label";s:4:"Name";s:8:"has_body";s:1:"1";s:10:"body_label";s:11:"Description";s:14:"min_word_count";s:2:"20";s:6:"custom";s:1:"0";s:8:"modified";s:1:"0";s:6:"locked";s:1:"0";s:9:"orig_type";s:7:"company";}}',
+  'page_arguments' => 'a:2:{i:0;s:24:"node_type_delete_confirm";i:1;O:8:"stdClass":14:{s:4:"type";s:7:"company";s:4:"name";s:7:"Company";s:6:"module";s:4:"node";s:11:"description";s:17:"Company node type";s:4:"help";s:0:"";s:9:"has_title";s:1:"1";s:11:"title_label";s:4:"Name";s:8:"has_body";s:1:"1";s:10:"body_label";s:11:"Description";s:14:"min_word_count";s:1:"0";s:6:"custom";s:1:"0";s:8:"modified";s:1:"1";s:6:"locked";s:1:"0";s:9:"orig_type";s:7:"company";}}',
   'fit' => '31',
   'number_parts' => '5',
   'tab_parent' => '',
@@ -34859,7 +34859,7 @@
   'access_callback' => 'user_access',
   'access_arguments' => 'a:1:{i:0;s:24:"administer content types";}',
   'page_callback' => 'drupal_get_form',
-  'page_arguments' => 'a:2:{i:0;s:14:"node_type_form";i:1;O:8:"stdClass":14:{s:4:"type";s:7:"company";s:4:"name";s:7:"Company";s:6:"module";s:4:"node";s:11:"description";s:17:"Company node type";s:4:"help";s:0:"";s:9:"has_title";s:1:"1";s:11:"title_label";s:4:"Name";s:8:"has_body";s:1:"1";s:10:"body_label";s:11:"Description";s:14:"min_word_count";s:2:"20";s:6:"custom";s:1:"0";s:8:"modified";s:1:"0";s:6:"locked";s:1:"0";s:9:"orig_type";s:7:"company";}}',
+  'page_arguments' => 'a:2:{i:0;s:14:"node_type_form";i:1;O:8:"stdClass":14:{s:4:"type";s:7:"company";s:4:"name";s:7:"Company";s:6:"module";s:4:"node";s:11:"description";s:17:"Company node type";s:4:"help";s:0:"";s:9:"has_title";s:1:"1";s:11:"title_label";s:4:"Name";s:8:"has_body";s:1:"1";s:10:"body_label";s:11:"Description";s:14:"min_word_count";s:1:"0";s:6:"custom";s:1:"0";s:8:"modified";s:1:"1";s:6:"locked";s:1:"0";s:9:"orig_type";s:7:"company";}}',
   'fit' => '31',
   'number_parts' => '5',
   'tab_parent' => 'admin/content/node-type/company',
@@ -41338,18 +41338,35 @@
 ->values(array(
   'nid' => '9',
   'vid' => '12',
-  'type' => 'story',
-  'language' => '',
-  'title' => 'Once upon a time',
+  'type' => 'article',
+  'language' => 'en',
+  'title' => 'The Real McCoy',
   'uid' => '1',
   'status' => '1',
-  'created' => '1444671588',
-  'changed' => '1444671588',
+  'created' => '1444238800',
+  'changed' => '1444238808',
   'comment' => '2',
   'promote' => '1',
   'moderate' => '0',
   'sticky' => '0',
-  'tnid' => '0',
+  'tnid' => '9',
+  'translate' => '0',
+))
+->values(array(
+  'nid' => '10',
+  'vid' => '13',
+  'type' => 'article',
+  'language' => 'fr',
+  'title' => 'Le Vrai McCoy',
+  'uid' => '1',
+  'status' => '1',
+  'created' => '1444239050',
+  'changed' => '1444239050',
+  'comment' => '2',
+  'promote' => '1',
+  'moderate' => '0',
+  'sticky' => '0',
+  'tnid' => '9',
   'translate' => '0',
 ))
 ->execute();
@@ -41497,7 +41514,14 @@
 ))
 ->values(array(
   'nid' => '9',
-  'last_comment_timestamp' => '1444671588',
+  'last_comment_timestamp' => '1444238800',
+  'last_comment_name' => NULL,
+  'last_comment_uid' => '1',
+  'comment_count' => '0',
+))
+->values(array(
+  'nid' => '10',
+  'last_comment_timestamp' => '1444239050',
   'last_comment_name' => NULL,
   'last_comment_uid' => '1',
   'comment_count' => '0',
@@ -41738,11 +41762,22 @@
   'nid' => '9',
   'vid' => '12',
   'uid' => '1',
-  'title' => 'Once upon a time',
-  'body' => 'Come on kid, go to sleep.',
-  'teaser' => 'Come on kid, go to sleep.',
+  'title' => 'The Real McCoy',
+  'body' => "In the original, Queen's English.",
+  'teaser' => "In the original, Queen's English.",
+  'log' => '',
+  'timestamp' => '1444238808',
+  'format' => '1',
+))
+->values(array(
+  'nid' => '10',
+  'vid' => '13',
+  'uid' => '1',
+  'title' => 'Le Vrai McCoy',
+  'body' => 'Ooh là là!',
+  'teaser' => 'Ooh là là!',
   'log' => '',
-  'timestamp' => '1444671588',
+  'timestamp' => '1444239050',
   'format' => '1',
 ))
 ->execute();
@@ -41879,9 +41914,9 @@
   'title_label' => 'Name',
   'has_body' => '1',
   'body_label' => 'Description',
-  'min_word_count' => '20',
+  'min_word_count' => '0',
   'custom' => '0',
-  'modified' => '0',
+  'modified' => '1',
   'locked' => '0',
   'orig_type' => 'company',
 ))
@@ -44828,12 +44863,16 @@
   'value' => 's:1:"2";',
 ))
 ->values(array(
+  'name' => 'comment_company',
+  'value' => 's:1:"2";',
+))
+->values(array(
   'name' => 'comment_controls_article',
   'value' => 'i:3;',
 ))
 ->values(array(
   'name' => 'comment_controls_company',
-  'value' => 'i:3;',
+  'value' => 's:1:"3";',
 ))
 ->values(array(
   'name' => 'comment_controls_employee',
@@ -44873,7 +44912,7 @@
 ))
 ->values(array(
   'name' => 'comment_default_mode_company',
-  'value' => 'i:4;',
+  'value' => 's:1:"4";',
 ))
 ->values(array(
   'name' => 'comment_default_mode_employee',
@@ -44913,7 +44952,7 @@
 ))
 ->values(array(
   'name' => 'comment_default_order_company',
-  'value' => 'i:1;',
+  'value' => 's:1:"1";',
 ))
 ->values(array(
   'name' => 'comment_default_order_employee',
@@ -44953,7 +44992,7 @@
 ))
 ->values(array(
   'name' => 'comment_default_per_page_company',
-  'value' => 'i:50;',
+  'value' => 's:2:"50";',
 ))
 ->values(array(
   'name' => 'comment_default_per_page_employee',
@@ -44993,7 +45032,7 @@
 ))
 ->values(array(
   'name' => 'comment_form_location_company',
-  'value' => 'i:0;',
+  'value' => 's:1:"0";',
 ))
 ->values(array(
   'name' => 'comment_form_location_employee',
@@ -45037,7 +45076,7 @@
 ))
 ->values(array(
   'name' => 'comment_preview_company',
-  'value' => 'i:1;',
+  'value' => 's:1:"1";',
 ))
 ->values(array(
   'name' => 'comment_preview_employee',
@@ -45081,7 +45120,7 @@
 ))
 ->values(array(
   'name' => 'comment_subject_field_company',
-  'value' => 'i:1;',
+  'value' => 's:1:"1";',
 ))
 ->values(array(
   'name' => 'comment_subject_field_employee',
@@ -45444,6 +45483,10 @@
   'value' => 's:5:"never";',
 ))
 ->values(array(
+  'name' => 'event_nodeapi_company',
+  'value' => 's:5:"never";',
+))
+->values(array(
   'name' => 'event_nodeapi_event',
   'value' => 's:3:"all";',
 ))
@@ -45505,7 +45548,11 @@
 ))
 ->values(array(
   'name' => 'form_build_id_article',
-  'value' => 's:48:"form-mXZfFJxcCFGB80PPYtNOuwYbho6-xKTvrRLb3TAMkic";',
+  'value' => 's:48:"form-t2zKJflpBD4rpYoGQH33ckjjWAYdo5lF3Hl1O_YnWyE";',
+))
+->values(array(
+  'name' => 'form_build_id_company',
+  'value' => 's:48:"form-jFw2agRukPxjG5dG-N6joZLyoxXmCoxTzua0HUciqK0";',
 ))
 ->values(array(
   'name' => 'forum_block_num_0',
@@ -45600,6 +45647,10 @@
   'value' => 'a:1:{i:0;s:6:"status";}',
 ))
 ->values(array(
+  'name' => 'node_options_company',
+  'value' => 'a:2:{i:0;s:6:"status";i:1;s:7:"promote";}',
+))
+->values(array(
   'name' => 'node_options_forum',
   'value' => 'a:1:{i:0;s:6:"status";}',
 ))
@@ -45796,6 +45847,10 @@
   'value' => 'b:0;',
 ))
 ->values(array(
+  'name' => 'upload_company',
+  'value' => 's:1:"1";',
+))
+->values(array(
   'name' => 'upload_page',
   'value' => 'b:1;',
 ))
diff --git a/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6TestBase.php b/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6TestBase.php
index 761e718..359b75c 100644
--- a/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6TestBase.php
+++ b/core/modules/migrate_drupal/tests/src/Kernel/d6/MigrateDrupal6TestBase.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\migrate_drupal\Kernel\d6;
 
+use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
 
 /**
@@ -80,12 +81,26 @@ protected function migrateFields() {
   }
 
   /**
+   * Configure the languages necessary for translations.
+   */
+  protected function configureLanguages() {
+    ConfigurableLanguage::createFromLangcode('en')->save();
+    ConfigurableLanguage::createFromLangcode('fr')->save();
+  }
+
+  /**
    * Executes all content migrations.
    *
    * @param bool $include_revisions
    *   If TRUE, migrates node revisions.
    */
   protected function migrateContent($include_revisions = FALSE) {
+    // The revision migrations include translations, so we need to install
+    // the necessary languages.
+    if ($include_revisions) {
+      $this->configureLanguages();
+    }
+
     $this->migrateUsers(FALSE);
     $this->migrateFields();
 
diff --git a/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php b/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
index d073c18..32d7e1f 100644
--- a/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
+++ b/core/modules/migrate_drupal_ui/src/Tests/d6/MigrateUpgrade6Test.php
@@ -14,6 +14,13 @@
 class MigrateUpgrade6Test extends MigrateUpgradeTestBase {
 
   /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['language'];
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
@@ -39,8 +46,9 @@ protected function getEntityCounts() {
       'comment' => 3,
       'comment_type' => 2,
       'contact_form' => 5,
+      'configurable_language' => 5,
       'editor' => 2,
-      'field_config' => 62,
+      'field_config' => 63,
       'field_storage_config' => 43,
       'file' => 7,
       'filter_format' => 7,
@@ -56,7 +64,7 @@ protected function getEntityCounts() {
       'menu' => 8,
       'taxonomy_term' => 6,
       'taxonomy_vocabulary' => 6,
-      'tour' => 1,
+      'tour' => 4,
       'user' => 7,
       'user_role' => 6,
       'menu_link_content' => 4,
diff --git a/core/modules/node/migration_templates/d6_node_revision.yml b/core/modules/node/migration_templates/d6_node_revision.yml
index cd32ea0..4a51fbf 100644
--- a/core/modules/node/migration_templates/d6_node_revision.yml
+++ b/core/modules/node/migration_templates/d6_node_revision.yml
@@ -38,3 +38,4 @@ process:
 
 destination:
   plugin: entity_revision:node
+  translated: true
diff --git a/core/modules/node/src/Plugin/migrate/source/d6/Node.php b/core/modules/node/src/Plugin/migrate/source/d6/Node.php
index c70fd27..ea3ebc6 100644
--- a/core/modules/node/src/Plugin/migrate/source/d6/Node.php
+++ b/core/modules/node/src/Plugin/migrate/source/d6/Node.php
@@ -13,11 +13,10 @@
  * )
  */
 class Node extends DrupalSqlBase {
-
   /**
-   * The join options between the node and the node_revisions table.
+   * An expression for the translation set of a node.
    */
-  const JOIN = 'n.vid = nr.vid';
+  const NODE_TRANSLATION_SET = 'CASE n.tnid WHEN 0 THEN n.nid ELSE n.tnid END';
 
   /**
    * The default filter format.
@@ -37,12 +36,11 @@ class Node extends DrupalSqlBase {
    * {@inheritdoc}
    */
   public function query() {
+    $query = $this->translationQuery();
+
     // Select node in its last revision.
-    $query = $this->select('node_revisions', 'nr')
-      ->fields('n', array(
-        'nid',
+    $query->fields('n', array(
         'type',
-        'language',
         'status',
         'created',
         'changed',
@@ -50,11 +48,9 @@ public function query() {
         'promote',
         'moderate',
         'sticky',
-        'tnid',
         'translate',
       ))
       ->fields('nr', array(
-        'vid',
         'title',
         'body',
         'teaser',
@@ -64,10 +60,9 @@ public function query() {
       ));
     $query->addField('n', 'uid', 'node_uid');
     $query->addField('nr', 'uid', 'revision_uid');
-    $query->innerJoin('node', 'n', static::JOIN);
 
     if (isset($this->configuration['node_type'])) {
-      $query->condition('type', $this->configuration['node_type']);
+      $query->condition('n.type', $this->configuration['node_type']);
     }
 
     return $query;
@@ -87,6 +82,7 @@ protected function initializeIterator() {
   public function fields() {
     $fields = array(
       'nid' => $this->t('Node ID'),
+      'vid' => $this->t('Revision ID'),
       'type' => $this->t('Type'),
       'title' => $this->t('Title'),
       'body' => $this->t('Body'),
@@ -101,7 +97,6 @@ public function fields() {
       'sticky' => $this->t('Sticky at top of lists'),
       'revision' => $this->t('Create new revision'),
       'language' => $this->t('Language (fr, en, ...)'),
-      'tnid' => $this->t('The translation set id for this node'),
       'timestamp' => $this->t('The timestamp the latest revision of this node was created.'),
     );
     return $fields;
@@ -233,7 +228,7 @@ protected function getCckData(array $field, Row $node) {
         // the time being.
         ->isNotNull($field['field_name'] . '_' . $columns[0])
         ->condition('nid', $node->getSourceProperty('nid'))
-        ->condition('vid', $node->getSourceProperty('vid'))
+        ->condition('vid', $node->getSourceProperty('field_vid'))
         ->execute()
         ->fetchAllAssoc('delta');
     }
@@ -251,4 +246,44 @@ public function getIds() {
     return $ids;
   }
 
+  /**
+   * Build a query to get the maximum vid of each translation set.
+   *
+   * @return \Drupal\Core\Database\Query\SelectInterface
+   *   The generated query.
+   */
+  protected function maxVidQuery() {
+    $subquery = $this->select('node', 'n');
+    $subquery->addExpression(self::NODE_TRANSLATION_SET, 'translation_set');
+    $subquery->groupBy('translation_set');
+    $subquery->addExpression('MAX(vid)', 'vid');
+    return $subquery;
+  }
+
+  /**
+   * Build a query that yields the rows we want to migrate.
+   *
+   * It should have a node table 'n', and a node_revision table 'nr'.
+   *
+   * @return \Drupal\Core\Database\Query\SelectInterface
+   *   The generated query.
+   */
+  protected function translationQuery() {
+    $query = $this->select('node', 'n');
+    $query->fields('n', ['nid', 'language']);
+
+    // Only yield the default node for each translation set.
+    $query->where('n.tnid = 0 OR n.nid = n.tnid');
+
+    // Claim our vid is the maximum vid of our translation set.
+    $query->join($this->maxVidQuery(), 'max_vid', 'n.nid = max_vid.translation_set');
+    $query->fields('max_vid', ['vid']);
+
+    // Use the real vid for finding fields.
+    $query->join('node_revisions', 'nr', 'n.vid = nr.vid');
+    $query->addField('nr', 'vid', 'field_vid');
+
+    return $query;
+  }
+
 }
diff --git a/core/modules/node/src/Plugin/migrate/source/d6/NodeRevision.php b/core/modules/node/src/Plugin/migrate/source/d6/NodeRevision.php
index 41e7a18..7185682 100644
--- a/core/modules/node/src/Plugin/migrate/source/d6/NodeRevision.php
+++ b/core/modules/node/src/Plugin/migrate/source/d6/NodeRevision.php
@@ -12,9 +12,9 @@
 class NodeRevision extends Node {
 
   /**
-   * The join options between the node and the node_revisions_table.
+   * The join options between a node table and its translations.
    */
-  const JOIN = 'n.nid = nr.nid AND n.vid <> nr.vid';
+  const NODE_TRANSLATION_JOIN = '(n.tnid <> 0 AND n.tnid = nt.tnid) OR n.nid = nt.nid';
 
   /**
    * {@inheritdoc}
@@ -22,7 +22,6 @@ class NodeRevision extends Node {
   public function fields() {
     // Use all the node fields plus the vid that identifies the version.
     return parent::fields() + array(
-      'vid' => t('The primary identifier for this version.'),
       'log' => $this->t('Revision Log message'),
       'timestamp' => $this->t('Revision timestamp'),
     );
@@ -33,8 +32,87 @@ public function fields() {
    */
   public function getIds() {
     $ids['vid']['type'] = 'integer';
-    $ids['vid']['alias'] = 'nr';
+    $ids['vid']['alias'] = 'tvids';
+    $ids['language']['type'] = 'string';
+    $ids['language']['alias'] = 'tvids';
     return $ids;
   }
 
+  /**
+   * Build a query to turn each revision into multiple translation rows.
+   *
+   * For each D6 revision, generate a row for each translation that existed
+   * at that time.
+   *
+   * Eg: If we have:
+   *   | tnid | nid | vid | language |
+   *   |    1 |   1 |   1 |       en |
+   *   |    1 |   2 |   2 |       fr |
+   *   |    1 |   3 |   3 |       de |
+   *   |    1 |   1 |   4 |       en |
+   *
+   *
+   * Then we generate the following rows:
+   *   | vid | language | tvid |
+   *   |   1 |       en |    1 |
+   *   |   2 |       en |    1 |
+   *   |   2 |       fr |    2 |
+   *   |   3 |       en |    1 |
+   *   |   3 |       fr |    2 |
+   *   |   3 |       de |    3 |
+   *   |   4 |       en |    4 |
+   *   |   4 |       fr |    2 |
+   *   |   4 |       de |    3 |
+   *
+   * @return \Drupal\Core\Database\Query\SelectInterface
+   *   The generated query.
+   */
+  protected function translationRevisionsQuery() {
+    // Find the nodes that are translations of this node.
+    $query = $this->select('node_revisions', 'nr');
+    $query->join('node', 'n', 'n.nid = nr.nid');
+    $query->join('node', 'nt', self::NODE_TRANSLATION_JOIN);
+
+    // Find all translation revisions with lower vids than the current one.
+    $query->join('node_revisions', 'nrt',
+      'nrt.nid = nt.nid AND nr.vid >= nrt.vid');
+
+    // For each vid/language pair, we only want the top translation vid.
+    $query->groupBy('nr.vid');
+    $query->groupBy('nt.language');
+    $query->addField('nr', 'vid');
+    $query->addField('nt', 'language');
+    $query->addExpression('MAX(nrt.vid)', 'tvid');
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function translationQuery() {
+    // Multiply each revision according to translationRevisionsQuery.
+    $query = $this->select('node_revisions', 'nr');
+    $query->join($this->translationRevisionsQuery(), 'tvids',
+      'nr.vid = tvids.tvid');
+
+    // Get fields according to this row of node_revisions.
+    $query->addField('nr', 'vid', 'field_vid');
+    // Claim to be from a translation, see 'vid' in the table from
+    // translationRevisionsQuery.
+    $query->fields('tvids', ['vid', 'language']);
+
+    // Get the default node for this translation set.
+    $query->join('node', 'nt', 'nt.nid = nr.nid');
+    $query->join('node', 'n', self::NODE_TRANSLATION_JOIN);
+    $query->where('n.tnid = 0 OR n.tnid = n.nid');
+    $query->addField('n', 'nid');
+
+    // Add orders, for reproducible results.
+    $query->orderBy('vid');
+    $query->orderBy('language');
+
+    return $query;
+  }
+
 }
diff --git a/core/modules/node/src/Tests/Migrate/d6/MigrateNodeRevisionTest.php b/core/modules/node/src/Tests/Migrate/d6/MigrateNodeRevisionTest.php
deleted file mode 100644
index 05be99f..0000000
--- a/core/modules/node/src/Tests/Migrate/d6/MigrateNodeRevisionTest.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-namespace Drupal\node\Tests\Migrate\d6;
-use Drupal\Tests\node\Kernel\Migrate\d6\MigrateNodeTestBase;
-
-/**
- * Node content revisions migration.
- *
- * @group migrate_drupal_6
- */
-class MigrateNodeRevisionTest extends MigrateNodeTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-    $this->executeMigrations(['d6_node', 'd6_node_revision']);
-  }
-
-  /**
-   * Test node revisions migration from Drupal 6 to 8.
-   */
-  public function testNodeRevision() {
-    $node = \Drupal::entityManager()->getStorage('node')->loadRevision(2);
-    /** @var \Drupal\node\NodeInterface $node */
-    $this->assertIdentical('1', $node->id());
-    $this->assertIdentical('2', $node->getRevisionId());
-    $this->assertIdentical('und', $node->langcode->value);
-    $this->assertIdentical('Test title rev 2', $node->getTitle());
-    $this->assertIdentical('body test rev 2', $node->body->value);
-    $this->assertIdentical('teaser test rev 2', $node->body->summary);
-    $this->assertIdentical('2', $node->getRevisionUser()->id());
-    $this->assertIdentical('modified rev 2', $node->revision_log->value);
-    $this->assertIdentical('1390095702', $node->getRevisionCreationTime());
-
-    $node = \Drupal::entityManager()->getStorage('node')->loadRevision(5);
-    $this->assertIdentical('1', $node->id());
-    $this->assertIdentical('body test rev 3', $node->body->value);
-    $this->assertIdentical('1', $node->getRevisionUser()->id());
-    $this->assertIdentical('modified rev 3', $node->revision_log->value);
-    $this->assertIdentical('1390095703', $node->getRevisionCreationTime());
-  }
-
-}
diff --git a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeRevisionTest.php b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeRevisionTest.php
new file mode 100644
index 0000000..2a08cba
--- /dev/null
+++ b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeRevisionTest.php
@@ -0,0 +1,130 @@
+<?php
+
+namespace Drupal\Tests\node\Kernel\Migrate\d6;
+
+use Drupal\migrate\Plugin\MigrationInterface;
+use Drupal\migrate\Row;
+use Drupal\node\NodeInterface;
+
+/**
+ * Node content revisions migration.
+ *
+ * @group migrate_drupal_6
+ */
+class MigrateNodeRevisionTest extends MigrateNodeTestBase {
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['language'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+    $this->configureLanguages();
+  }
+
+  /**
+   * Test node revisions migration from Drupal 6 to 8.
+   */
+  public function testNodeRevision() {
+    $this->executeMigrations(['d6_node', 'd6_node_revision']);
+    $storage = \Drupal::entityManager()->getStorage('node');
+    $node = $storage->loadRevision(2);
+
+    /** @var \Drupal\node\NodeInterface $node */
+    $this->assertIdentical('1', $node->id());
+    $this->assertIdentical('2', $node->getRevisionId());
+    $this->assertIdentical('und', $node->langcode->value);
+    $this->assertIdentical('Test title rev 2', $node->getTitle());
+    $this->assertIdentical('body test rev 2', $node->body->value);
+    $this->assertIdentical('teaser test rev 2', $node->body->summary);
+    $this->assertIdentical('2', $node->getRevisionUser()->id());
+    $this->assertIdentical('modified rev 2', $node->revision_log->value);
+    $this->assertIdentical('1390095702', $node->getRevisionCreationTime());
+
+    $node = $storage->loadRevision(5);
+    $this->assertIdentical('1', $node->id());
+    $this->assertIdentical('body test rev 3', $node->body->value);
+    $this->assertIdentical('1', $node->getRevisionUser()->id());
+    $this->assertIdentical('modified rev 3', $node->revision_log->value);
+    $this->assertIdentical('1390095703', $node->getRevisionCreationTime());
+
+    // Revision 12 is the default revision of node 9.
+    $node = $storage->loadRevision(12);
+    $this->assertTrue($node instanceof NodeInterface);
+    $this->assertIdentical('9', $node->id());
+    // The French translation is only introduced in rev. 13.
+    $this->assertTrue($node->hasTranslation('en'));
+    $this->assertFalse($node->hasTranslation('fr'));
+    $this->assertIdentical('The Real McCoy', $node->getTitle());
+    $this->assertIdentical("In the original, Queen's English.", $node->body->value);
+
+    // Revision 13 was part of node 10, which is a translation of node 9.
+    $node = $storage->loadRevision(13);
+    $this->assertTrue($node instanceof NodeInterface);
+    $this->assertIdentical('9', $node->id());
+    $this->assertTrue($node->isDefaultRevision());
+    // English is the node's default language, in any revision.
+    $this->assertIdentical('en', $node->language()->getId());
+    // The English title and body did not change in this revision...
+    $this->assertIdentical('The Real McCoy', $node->getTitle());
+    $this->assertIdentical("In the original, Queen's English.", $node->body->value);
+    // ...but a French translation was introduced.
+    $this->assertTrue($node->hasTranslation('fr'));
+    $node = $node->getTranslation('fr');
+    $this->assertIdentical('Le Vrai McCoy', $node->getTitle());
+    $this->assertIdentical("Ooh là là!", $node->body->value);
+
+    // The node as a whole should have both languages.
+    $node = $storage->load(9);
+    $languages = array_keys($node->getTranslationLanguages());
+    sort($languages);
+    $this->assertIdentical(['en', 'fr'], $languages);
+
+    // Check that the translations are actually present.
+    $this->assertIdentical('The Real McCoy', $node->title->value);
+    $this->assertIdentical('Le Vrai McCoy', $node->getTranslation('fr')->title->value);
+  }
+
+  /**
+   * Test partial node revision migrations from Drupal 6 to 8.
+   */
+  public function testSomeNodeRevision() {
+    $storage = \Drupal::entityManager()->getStorage('node');
+
+    // Make sure we don't already have a revision.
+    $this->assertNull($storage->loadRevision(13), 'No revision before migrations');
+
+    $this->executeMigrations([
+      'd6_node',
+      'd6_node_revision'
+    ], function (MigrationInterface $migration, Row $row) {
+      // Only include nodes with nid 9.
+      if ($row->getSourceProperty('nid') != 9) {
+        return FALSE;
+      }
+      // Only include revision 13.
+      if (strstr($migration->id(), 'node_revision') !== FALSE) {
+        if ($row->getSourceProperty('vid') != 13) {
+          return FALSE;
+        }
+      }
+      return TRUE;
+    });
+
+    /** @var \Drupal\node\NodeInterface $node */
+    $node = $storage->loadRevision(13);
+    // Both languages should be present in this revision.
+    $this->assertTrue($node->hasTranslation('en'), 'English translation exists');
+    $this->assertIdentical('The Real McCoy', $node->getTranslation('en')
+      ->getTitle());
+    $this->assertTrue($node->hasTranslation('fr'), 'French translation exists');
+    $this->assertIdentical('Le Vrai McCoy', $node->getTranslation('fr')
+      ->getTitle());
+  }
+
+}
diff --git a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php
index 7f07d11..106976d 100644
--- a/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php
+++ b/core/modules/node/tests/src/Kernel/Migrate/d6/MigrateNodeTest.php
@@ -5,6 +5,7 @@
 use Drupal\Core\Database\Database;
 use Drupal\migrate\Plugin\MigrateIdMapInterface;
 use Drupal\node\Entity\Node;
+use Drupal\node\NodeInterface;
 use Drupal\Tests\file\Kernel\Migrate\d6\FileMigrationTestTrait;
 
 /**
@@ -79,6 +80,15 @@ public function testNode() {
     $this->assertIdentical('Drupal Groups', $node->field_test_link->title);
     $this->assertIdentical([], $node->field_test_link->options['attributes']);
 
+    // Test that translations are working.
+    $node = Node::load(9);
+    $this->assertTrue($node instanceof NodeInterface);
+    $this->assertIdentical('en', $node->langcode->value);
+    $this->assertIdentical('The Real McCoy', $node->title->value);
+
+    // Node 10 is a translation of node 9, and should not be imported separately.
+    $this->assertNull(Node::load(10));
+
     // Rerun migration with invalid link attributes and a different URL and
     // title. If only the attributes are changed the error does not occur.
     Database::getConnection('default', 'migrate')
diff --git a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeByNodeTypeTest.php b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeByNodeTypeTest.php
index 0c31810..38e42a1 100644
--- a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeByNodeTypeTest.php
+++ b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeByNodeTypeTest.php
@@ -40,7 +40,6 @@ class NodeByNodeTypeTest extends MigrateSqlSourceTestCase {
       'promote' => 1,
       'moderate' => 0,
       'sticky' => 0,
-      'tnid' => 0,
       'translate' => 0,
       // Node revision fields.
       'body' => 'body for node 1',
@@ -64,7 +63,6 @@ class NodeByNodeTypeTest extends MigrateSqlSourceTestCase {
       'promote' => 1,
       'moderate' => 0,
       'sticky' => 0,
-      'tnid' => 0,
       'translate' => 0,
       // Node revision fields.
       'body' => 'body for node 2',
@@ -101,7 +99,6 @@ protected function setUp() {
       'promote' => 1,
       'moderate' => 0,
       'sticky' => 0,
-      'tnid' => 0,
       'translate' => 0,
       // Node revision fields.
       'body' => 'body for node 5',
@@ -113,6 +110,8 @@ protected function setUp() {
     // Add another row with an article node and make sure it is not migrated.
 
     foreach ($database_contents as $k => $row) {
+      $row['tnid'] = 0;
+
       foreach (array('nid', 'vid', 'title', 'uid', 'body', 'teaser', 'format', 'timestamp', 'log') as $field) {
         $this->databaseContents['node_revisions'][$k][$field] = $row[$field];
         switch ($field) {
diff --git a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionByNodeTypeTest.php b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionByNodeTypeTest.php
index 8c78be7..86e467b 100644
--- a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionByNodeTypeTest.php
+++ b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionByNodeTypeTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\node\Unit\Plugin\migrate\source\d6;
 
+use Drupal\node\Plugin\migrate\source\d6\NodeRevision;
 use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
 
 /**
@@ -11,26 +12,14 @@
  */
 class NodeRevisionByNodeTypeTest extends MigrateSqlSourceTestCase {
 
-  const PLUGIN_CLASS = 'Drupal\node\Plugin\migrate\source\d6\NodeRevision';
+  const PLUGIN_CLASS = NodeRevision::class;
 
-  // The fake Migration configuration entity.
   protected $migrationConfiguration = [
     'id' => 'test',
-    // The fake configuration for the source.
     'source' => [
       'plugin' => 'd6_node_revision',
       'node_type' => 'page',
     ],
-    'sourceIds' => [
-      'vid' => [
-        'alias' => 'v',
-      ],
-    ],
-    'destinationIds' => [
-      'vid' => [
-        // This is where the field schema would go.
-      ],
-    ],
   ];
 
   protected $databaseContents = [
@@ -118,10 +107,6 @@ class NodeRevisionByNodeTypeTest extends MigrateSqlSourceTestCase {
     ],
   ];
 
-  // There are three revisions of nid 1; vid 4 is the current one. The
-  // NodeRevision plugin should capture every revision EXCEPT that one.
-  // nid 2 will be ignored because $this->migrationConfiguration specifies
-  // a particular node type.
   protected $expectedResults = [
     [
       'nid' => 1,
@@ -134,7 +119,6 @@ class NodeRevisionByNodeTypeTest extends MigrateSqlSourceTestCase {
       'promote' => 1,
       'moderate' => 0,
       'sticky' => 0,
-      'tnid' => 0,
       'translate' => 0,
       'vid' => 1,
       'node_uid' => 1,
@@ -156,7 +140,6 @@ class NodeRevisionByNodeTypeTest extends MigrateSqlSourceTestCase {
       'promote' => 1,
       'moderate' => 0,
       'sticky' => 0,
-      'tnid' => 0,
       'translate' => 0,
       'vid' => 3,
       'node_uid' => 1,
@@ -167,6 +150,28 @@ class NodeRevisionByNodeTypeTest extends MigrateSqlSourceTestCase {
       'log' => 'log for revision 3 (node 1)',
       'format' => 1,
     ],
+    [
+      'nid' => 1,
+      'type' => 'page',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279051598,
+      'changed' => 1279051598,
+      'comment' => 2,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'translate' => 0,
+      'vid' => 4,
+      'node_uid' => 1,
+      'revision_uid' => 1,
+      'title' => 'title for revision 4 (node 1)',
+      'body' => 'body for revision 4 (node 1)',
+      'teaser' => 'teaser for revision 4 (node 1)',
+      'log' => 'log for revision 4 (node 1)',
+      'format' => 1,
+      'timestamp' => 1279051598,
+    ],
   ];
 
 }
diff --git a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionTest.php b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionTest.php
index b1c23f8..3cd0c7e 100644
--- a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionTest.php
+++ b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeRevisionTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\node\Unit\Plugin\migrate\source\d6;
 
+use Drupal\node\Plugin\migrate\source\d6\NodeRevision;
 use Drupal\Tests\migrate\Unit\MigrateSqlSourceTestCase;
 
 /**
@@ -11,25 +12,13 @@
  */
 class NodeRevisionTest extends MigrateSqlSourceTestCase {
 
-  const PLUGIN_CLASS = 'Drupal\node\Plugin\migrate\source\d6\NodeRevision';
+  const PLUGIN_CLASS = NodeRevision::class;
 
-  // The fake Migration configuration entity.
   protected $migrationConfiguration = [
     'id' => 'test',
-    // The fake configuration for the source.
     'source' => [
       'plugin' => 'd6_node_revision',
     ],
-    'sourceIds' => [
-      'vid' => [
-        'alias' => 'v',
-      ],
-    ],
-    'destinationIds' => [
-      'vid' => [
-        // This is where the field schema would go.
-      ],
-    ],
   ];
 
   protected $databaseContents = [
@@ -68,6 +57,42 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase {
         'uid' => 1,
         'title' => 'title for revision 2 (node 2)',
       ],
+      // A translation set.
+      [
+        'nid' => 3,
+        'type' => 'article',
+        'language' => 'en',
+        'status' => 1,
+        'created' => 1279309100,
+        'changed' => 1279309300,
+        'comment' => 0,
+        'promote' => 1,
+        'moderate' => 0,
+        'sticky' => 0,
+        'tnid' => 3,
+        'translate' => 0,
+        'vid' => 2,
+        'uid' => 1,
+        'title' => 'title for revision 7 (node 3)',
+      ],
+      [
+        'nid' => 4,
+        'type' => 'article',
+        'language' => 'fr',
+        'status' => 1,
+        'created' => 1279309200,
+        'changed' => 1279309200,
+        'comment' => 0,
+        'promote' => 1,
+        'moderate' => 0,
+        'sticky' => 0,
+        'tnid' => 3,
+        'translate' => 0,
+        'vid' => 2,
+        'uid' => 1,
+        'title' => 'title for revision 6 (node 4)',
+      ],
+
     ],
     'node_revisions' => [
       [
@@ -114,13 +139,46 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase {
         'format' => 1,
         'timestamp' => 1279308993,
       ],
+      // Translations.
+      [
+        'nid' => 3,
+        'vid' => 5,
+        'uid' => 1,
+        'title' => 'title for revision 5 (node 3)',
+        'body' => 'body for revision 5 (node 3)',
+        'teaser' => 'teaser for revision 5 (node 3)',
+        'log' => 'log for revision 5 (node 3)',
+        'format' => 1,
+        'timestamp' => 1279309100,
+      ],
+      [
+        'nid' => 3,
+        'vid' => 7,
+        'uid' => 1,
+        'title' => 'title for revision 7 (node 3)',
+        'body' => 'body for revision 7 (node 3)',
+        'teaser' => 'teaser for revision 7 (node 3)',
+        'log' => 'log for revision 7 (node 3)',
+        'format' => 1,
+        'timestamp' => 1279309300,
+      ],
+      [
+        'nid' => 4,
+        'vid' => 6,
+        'uid' => 1,
+        'title' => 'title for revision 6 (node 4)',
+        'body' => 'body for revision 6 (node 4)',
+        'teaser' => 'teaser for revision 6 (node 4)',
+        'log' => 'log for revision 6 (node 4)',
+        'format' => 1,
+        'timestamp' => 1279309200,
+      ],
     ],
   ];
 
-  // There are three revisions of nid 1, but the NodeRevision source ignores
-  // the current revision. So only two revisions will be returned here. nid 2
-  // is ignored because it only has one revision (the current one).
-  protected $expectedResults = [
+  // There are three revisions of nid 1, and one for node 2. Results are sorted
+  // by vid.
+    protected $expectedResults = [
     [
       // Node fields.
       'nid' => 1,
@@ -133,7 +191,6 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase {
       'promote' => 1,
       'moderate' => 0,
       'sticky' => 0,
-      'tnid' => 0,
       'translate' => 0,
       // Node revision fields.
       'vid' => 1,
@@ -144,6 +201,30 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase {
       'teaser' => 'teaser for revision 1 (node 1)',
       'log' => 'log for revision 1 (node 1)',
       'format' => 1,
+      'field_vid' => 1,
+    ],
+    [
+      'nid' => 2,
+      'type' => 'article',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279290908,
+      'changed' => 1279308993,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'translate' => 0,
+      'vid' => 2,
+      'node_uid' => 1,
+      'revision_uid' => 1,
+      'title' => 'title for revision 2 (node 2)',
+      'body' => 'body for revision 2 (node 2)',
+      'teaser' => 'teaser for revision 2 (node 2)',
+      'log' => 'log for revision 2 (node 2)',
+      'format' => 1,
+      'timestamp' => 1279308993,
+      'field_vid' => 2,
     ],
     [
       // Node fields.
@@ -157,7 +238,6 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase {
       'promote' => 1,
       'moderate' => 0,
       'sticky' => 0,
-      'tnid' => 0,
       'translate' => 0,
       // Node revision fields.
       'vid' => 3,
@@ -168,6 +248,146 @@ class NodeRevisionTest extends MigrateSqlSourceTestCase {
       'teaser' => 'teaser for revision 3 (node 1)',
       'log' => 'log for revision 3 (node 1)',
       'format' => 1,
+      'field_vid' => 3,
+    ],
+    [
+      'nid' => 1,
+      'type' => 'page',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279051598,
+      'changed' => 1279051598,
+      'comment' => 2,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'translate' => 0,
+      'vid' => 4,
+      'node_uid' => 1,
+      'revision_uid' => 1,
+      'title' => 'title for revision 4 (node 1)',
+      'body' => 'body for revision 4 (node 1)',
+      'teaser' => 'teaser for revision 4 (node 1)',
+      'log' => 'log for revision 4 (node 1)',
+      'format' => 1,
+      'timestamp' => 1279051598,
+      'field_vid' => 4,
+    ],
+    // Translations add extra revisions.
+    [
+      'nid' => 3,
+      'type' => 'article',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279309100,
+      'changed' => 1279309300,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'translate' => 0,
+      'vid' => 5,
+      'node_uid' => 1,
+      'revision_uid' => 1,
+      'title' => 'title for revision 5 (node 3)',
+      'body' => 'body for revision 5 (node 3)',
+      'teaser' => 'teaser for revision 5 (node 3)',
+      'log' => 'log for revision 5 (node 3)',
+      'format' => 1,
+      'timestamp' => 1279309100,
+      'field_vid' => 5,
+    ],
+    [
+      'nid' => 3,
+      'type' => 'article',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279309100,
+      'changed' => 1279309300,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'translate' => 0,
+      'vid' => 6,
+      'node_uid' => 1,
+      'revision_uid' => 1,
+      'title' => 'title for revision 5 (node 3)',
+      'body' => 'body for revision 5 (node 3)',
+      'teaser' => 'teaser for revision 5 (node 3)',
+      'log' => 'log for revision 5 (node 3)',
+      'format' => 1,
+      'timestamp' => 1279309100,
+      'field_vid' => 5,
+    ],
+    [
+      'nid' => 3,
+      'type' => 'article',
+      'language' => 'fr',
+      'status' => 1,
+      'created' => 1279309100,
+      'changed' => 1279309300,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'translate' => 0,
+      'vid' => 6,
+      'node_uid' => 1,
+      'revision_uid' => 1,
+      'title' => 'title for revision 6 (node 4)',
+      'body' => 'body for revision 6 (node 4)',
+      'teaser' => 'teaser for revision 6 (node 4)',
+      'log' => 'log for revision 6 (node 4)',
+      'format' => 1,
+      'timestamp' => 1279309200,
+      'field_vid' => 6,
+    ],
+    [
+      'nid' => 3,
+      'type' => 'article',
+      'language' => 'en',
+      'status' => 1,
+      'created' => 1279309100,
+      'changed' => 1279309300,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'translate' => 0,
+      'vid' => 7,
+      'node_uid' => 1,
+      'revision_uid' => 1,
+      'title' => 'title for revision 7 (node 3)',
+      'body' => 'body for revision 7 (node 3)',
+      'teaser' => 'teaser for revision 7 (node 3)',
+      'log' => 'log for revision 7 (node 3)',
+      'format' => 1,
+      'timestamp' => 1279309300,
+      'field_vid' => 7,
+    ],
+    [
+      'nid' => 3,
+      'type' => 'article',
+      'language' => 'fr',
+      'status' => 1,
+      'created' => 1279309100,
+      'changed' => 1279309300,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'translate' => 0,
+      'vid' => 7,
+      'node_uid' => 1,
+      'revision_uid' => 1,
+      'title' => 'title for revision 6 (node 4)',
+      'body' => 'body for revision 6 (node 4)',
+      'teaser' => 'teaser for revision 6 (node 4)',
+      'log' => 'log for revision 6 (node 4)',
+      'format' => 1,
+      'timestamp' => 1279309200,
+      'field_vid' => 6,
     ],
   ];
 
diff --git a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeTest.php b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeTest.php
index 79f2bac..45b20f8 100644
--- a/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeTest.php
+++ b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeTest.php
@@ -36,7 +36,6 @@ class NodeTest extends MigrateSqlSourceTestCase {
       'promote' => 1,
       'moderate' => 0,
       'sticky' => 0,
-      'tnid' => 0,
       'translate' => 0,
       // Node revision fields.
       'body' => 'body for node 1',
@@ -60,7 +59,6 @@ class NodeTest extends MigrateSqlSourceTestCase {
       'promote' => 1,
       'moderate' => 0,
       'sticky' => 0,
-      'tnid' => 0,
       'translate' => 0,
       // Node revision fields.
       'body' => 'body for node 2',
@@ -83,7 +81,6 @@ class NodeTest extends MigrateSqlSourceTestCase {
       'promote' => 1,
       'moderate' => 0,
       'sticky' => 0,
-      'tnid' => 0,
       'translate' => 0,
       // Node revision fields.
       'body' => 'body for node 5',
@@ -95,6 +92,28 @@ class NodeTest extends MigrateSqlSourceTestCase {
         array('value' => '3.14159'),
       ),
     ),
+    array(
+      'nid' => 6,
+      'vid' => 7,
+      'type' => 'story',
+      'language' => 'en',
+      'title' => 'node title 6',
+      'uid' => 1,
+      'status' => 1,
+      'created' => 1279290909,
+      'changed' => 1279308994,
+      'comment' => 0,
+      'promote' => 1,
+      'moderate' => 0,
+      'sticky' => 0,
+      'translate' => 0,
+      // Node revision fields.
+      'body' => 'body for node 6',
+      'teaser' => 'body for node 6',
+      'log' => '',
+      'timestamp' => 1279308994,
+      'format' => 1,
+    ),
   );
 
   /**
@@ -145,22 +164,114 @@ protected function setUp() {
         'status' => TRUE,
       ),
     );
-    foreach ($this->expectedResults as $k => $row) {
+    $this->databaseContents['node'] = [
+      [
+        'nid' => 1,
+        'vid' => 1,
+        'type' => 'page',
+        'language' => 'en',
+        'title' => 'node title 1',
+        'uid' => 1,
+        'status' => 1,
+        'created' => 1279051598,
+        'changed' => 1279051598,
+        'comment' => 2,
+        'promote' => 1,
+        'moderate' => 0,
+        'sticky' => 0,
+        'translate' => 0,
+        'tnid' => 0,
+      ],
+      [
+        'nid' => 2,
+        'vid' => 2,
+        'type' => 'page',
+        'language' => 'en',
+        'title' => 'node title 2',
+        'uid' => 1,
+        'status' => 1,
+        'created' => 1279290908,
+        'changed' => 1279308993,
+        'comment' => 0,
+        'promote' => 1,
+        'moderate' => 0,
+        'sticky' => 0,
+        'translate' => 0,
+        'tnid' => 0,
+      ],
+      [
+        'nid' => 5,
+        'vid' => 5,
+        'type' => 'story',
+        'language' => 'en',
+        'title' => 'node title 5',
+        'uid' => 1,
+        'status' => 1,
+        'created' => 1279290908,
+        'changed' => 1279308993,
+        'comment' => 0,
+        'promote' => 1,
+        'moderate' => 0,
+        'sticky' => 0,
+        'translate' => 0,
+        'tnid' => 0,
+      ],
+      [
+        'nid' => 6,
+        'vid' => 6,
+        'type' => 'story',
+        'language' => 'en',
+        'title' => 'node title 6',
+        'uid' => 1,
+        'status' => 1,
+        'created' => 1279290909,
+        'changed' => 1279308994,
+        'comment' => 0,
+        'promote' => 1,
+        'moderate' => 0,
+        'sticky' => 0,
+        'translate' => 0,
+        'tnid' => 6,
+      ],
+      [
+        'nid' => 7,
+        'vid' => 7,
+        'type' => 'story',
+        'language' => 'fr',
+        'title' => 'node title 7',
+        'uid' => 1,
+        'status' => 1,
+        'created' => 1279290910,
+        'changed' => 1279308995,
+        'comment' => 0,
+        'promote' => 1,
+        'moderate' => 0,
+        'sticky' => 0,
+        'translate' => 0,
+        'tnid' => 6,
+      ],
+    ];
+
+    foreach ($this->databaseContents['node'] as $k => $row) {
+      // Find the equivalent row from expected results.
+      $result_row = NULL;
+      foreach ($this->expectedResults as $result) {
+        if (in_array($result['nid'], [$row['nid'], $row['tnid']])) {
+          $result_row = $result;
+          break;
+        }
+      }
+
+      // Populate node_revisions.
       foreach (array('nid', 'vid', 'title', 'uid', 'body', 'teaser', 'format', 'timestamp', 'log') as $field) {
-        $this->databaseContents['node_revisions'][$k][$field] = $row[$field];
-        switch ($field) {
-          case 'nid': case 'vid':
-            break;
-          case 'uid':
-            $this->databaseContents['node_revisions'][$k]['uid']++;
-            break;
-          default:
-            unset($row[$field]);
-            break;
+        $value = isset($row[$field]) ? $row[$field] : $result_row[$field];
+        $this->databaseContents['node_revisions'][$k][$field] = $value;
+        if ($field == 'uid') {
+          $this->databaseContents['node_revisions'][$k]['uid']++;
         }
       }
-      $this->databaseContents['node'][$k] = $row;
     }
+
     array_walk($this->expectedResults, function (&$row) {
       $row['node_uid'] = $row['uid'];
       $row['revision_uid'] = $row['uid'] + 1;
diff --git a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeRevisionTest.php b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeRevisionTest.php
index ff2b514..2747677 100644
--- a/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeRevisionTest.php
+++ b/core/modules/taxonomy/tests/src/Kernel/Migrate/d6/MigrateTermNodeRevisionTest.php
@@ -14,7 +14,7 @@ class MigrateTermNodeRevisionTest extends MigrateDrupal6TestBase {
   /**
    * {@inheritdoc}
    */
-  public static $modules = ['taxonomy'];
+  public static $modules = ['taxonomy', 'language'];
 
   /**
    * {@inheritdoc}
