diff --git a/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php b/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php
index 697ae8a..ce96c49 100644
--- a/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php
+++ b/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php
@@ -44,7 +44,7 @@ public function __construct(ViewExecutable $view, LanguageManagerInterface $lang
   /**
    * {@inheritdoc}
    */
-  public function getLangcode(ResultRow $row) {
+  public function getLangcode(ResultRow $row, $relationship = 'none') {
     return $this->langcode;
   }
 
diff --git a/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php b/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php
index dbd3a72..55f5a5b 100644
--- a/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php
+++ b/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php
@@ -17,8 +17,10 @@ class DefaultLanguageRenderer extends EntityTranslationRendererBase {
   /**
    * {@inheritdoc}
    */
-  public function getLangcode(ResultRow $row) {
-    return $row->_entity->getUntranslated()->language()->getId();
+  public function getLangcode(ResultRow $row, $relationship = 'none') {
+    if ($entity = $this->getEntity($row, $relationship)) {
+      return $entity->getUntranslated()->language()->getId();
+    }
   }
 
 }
diff --git a/core/modules/views/src/Entity/Render/EntityFieldRenderer.php b/core/modules/views/src/Entity/Render/EntityFieldRenderer.php
index b00a572..3c2c84a 100644
--- a/core/modules/views/src/Entity/Render/EntityFieldRenderer.php
+++ b/core/modules/views/src/Entity/Render/EntityFieldRenderer.php
@@ -200,7 +200,8 @@ protected function buildFields(array $values) {
       $field = $this->view->field[current($field_ids)];
       foreach ($values as $result_row) {
         $entity = $field->getEntity($result_row);
-        $entities_by_bundles[$entity->bundle()][$result_row->index] = $this->getEntityTranslation($entity, $result_row);
+        $relationship = isset($field->options['relationship']) ? $field->options['relationship'] : 'none';
+        $entities_by_bundles[$entity->bundle()][$result_row->index] = $this->getEntityTranslation($entity, $result_row, $relationship);
       }
 
       // Determine unique sets of fields that can be processed by the same
diff --git a/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
index 7f9f44c..20f6815 100644
--- a/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
+++ b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
@@ -67,18 +67,20 @@ protected function getEntityTranslationRenderer() {
    *   The entity object the field value being processed is attached to.
    * @param \Drupal\views\ResultRow $row
    *   The result row the field value being processed belongs to.
+   * @param string $relationship
+   *   The relationship to be used, or 'none' by default.
    *
    * @return \Drupal\Core\Entity\FieldableEntityInterface
    *   The entity translation object for the specified row.
    */
-  public function getEntityTranslation(EntityInterface $entity, ResultRow $row) {
+  public function getEntityTranslation(EntityInterface $entity, ResultRow $row, $relationship = 'none') {
     // We assume the same language should be used for all entity fields
     // belonging to a single row, even if they are attached to different entity
     // types. Below we apply language fallback to ensure a valid value is always
     // picked.
     $translation = $entity;
     if ($entity instanceof TranslatableInterface && count($entity->getTranslationLanguages()) > 1) {
-      $langcode = $this->getEntityTranslationRenderer()->getLangcode($row);
+      $langcode = $this->getEntityTranslationRenderer()->getLangcode($row, $relationship);
       $translation = $this->getEntityManager()->getTranslationFromContext($entity, $langcode);
     }
     return $translation;
diff --git a/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php b/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php
index 4da6672..9a5cdf3 100644
--- a/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php
+++ b/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php
@@ -20,11 +20,13 @@
    *
    * @param \Drupal\views\ResultRow $row
    *   The result row.
+   * @param string $relationship
+   *   The relationship to be used, or 'none' by default.
    *
    * @return string
    *   A language code.
    */
-  abstract public function getLangcode(ResultRow $row);
+  abstract public function getLangcode(ResultRow $row, $relationship = 'none');
 
   /**
    * {@inheritdoc}
@@ -33,27 +35,62 @@ public function query(QueryPluginBase $query, $relationship = NULL) {
   }
 
   /**
-   * {@inheritdoc}
+   * Runs before each entity is rendered.
+   *
+   * @param \Drupal\views\ResultRow[] $result
+   *   The full array of results from the query.
+   * @param string $relationship
+   *   The relationship to be used, or 'none' by default.
    */
-  public function preRender(array $result) {
+  public function preRender(array $result, $relationship = 'none') {
     $view_builder = $this->view->rowPlugin->entityManager->getViewBuilder($this->entityType->id());
 
-    /** @var \Drupal\views\ResultRow $row */
     foreach ($result as $row) {
-      // @todo Take relationships into account.
-      //   See https://www.drupal.org/node/2457999.
-      $entity = $row->_entity;
-      $entity->view = $this->view;
-      $this->build[$entity->id()] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $this->getLangcode($row));
+      if ($entity = $this->getEntity($row, $relationship)) {
+        $entity->view = $this->view;
+        $this->build[$entity->id()] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $this->getLangcode($row, $relationship));
+      }
     }
   }
 
   /**
-   * {@inheritdoc}
+   * Renders entity data.
+   *
+   * @param \Drupal\views\ResultRow $row
+   *   A single row of the query result.
+   * @param string $relationship
+   *   The relationship to be used, or 'none' by default.
+   *
+   * @return array
+   *   A renderable array for the entity data contained in the result row.
    */
-  public function render(ResultRow $row) {
-    $entity_id = $row->_entity->id();
-    return $this->build[$entity_id];
+  public function render(ResultRow $row, $relationship = 'none') {
+    if ($entity = $this->getEntity($row, $relationship)) {
+      $entity_id = $entity->id();
+      return $this->build[$entity_id];
+    }
+  }
+
+  /**
+   * Gets the entity assosiated with a row.
+   *
+   * @param \Drupal\views\ResultRow $row
+   *   The result row.
+   * @param string $relationship
+   *   (optional) The relationship.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface|null
+   *   The entity might be optional, because the relationship entity might not
+   *   always exist.
+   */
+  protected function getEntity($row, $relationship = 'none') {
+    if ($relationship === 'none') {
+      return $row->_entity;
+    }
+    elseif (isset($row->_relationship_entities[$relationship])) {
+      return $row->_relationship_entities[$relationship];
+    }
+    return NULL;
   }
 
 }
diff --git a/core/modules/views/src/Entity/Render/RendererBase.php b/core/modules/views/src/Entity/Render/RendererBase.php
index deb1806..0a65d82 100644
--- a/core/modules/views/src/Entity/Render/RendererBase.php
+++ b/core/modules/views/src/Entity/Render/RendererBase.php
@@ -90,7 +90,7 @@ public function getCacheContexts() {
   /**
    * Runs before each entity is rendered.
    *
-   * @param $result
+   * @param \Drupal\views\ResultRow[] $result
    *   The full array of results from the query.
    */
   public function preRender(array $result) {
diff --git a/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
index c94243b..34d918d 100644
--- a/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
+++ b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
@@ -48,31 +48,34 @@ public function query(QueryPluginBase $query, $relationship = NULL) {
   /**
    * {@inheritdoc}
    */
-  public function preRender(array $result) {
+  public function preRender(array $result, $relationship = 'none') {
     $view_builder = $this->view->rowPlugin->entityManager->getViewBuilder($this->entityType->id());
 
     /** @var \Drupal\views\ResultRow $row */
     foreach ($result as $row) {
-      $entity = $row->_entity;
-      $entity->view = $this->view;
-      $langcode = $this->getLangcode($row);
-      $this->build[$entity->id()][$langcode] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $this->getLangcode($row));
+      if ($entity = $this->getEntity($row, $relationship)) {
+        $entity->view = $this->view;
+        $langcode = $this->getLangcode($row, $relationship);
+        $this->build[$entity->id()][$langcode] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $langcode);
+      }
     }
   }
 
   /**
    * {@inheritdoc}
    */
-  public function render(ResultRow $row) {
-    $entity_id = $row->_entity->id();
-    $langcode = $this->getLangcode($row);
-    return $this->build[$entity_id][$langcode];
+  public function render(ResultRow $row, $relationship = 'none') {
+    if ($entity = $this->getEntity($row, $relationship)) {
+      $entity_id = $entity->id();
+      $langcode = $this->getLangcode($row, $relationship);
+      return $this->build[$entity_id][$langcode];
+    }
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getLangcode(ResultRow $row) {
+  public function getLangcode(ResultRow $row, $relationship = 'none') {
     return isset($row->{$this->langcodeAlias}) ? $row->{$this->langcodeAlias} : $this->languageManager->getDefaultLanguage()->getId();
   }
 
diff --git a/core/modules/views/src/Plugin/views/row/EntityRow.php b/core/modules/views/src/Plugin/views/row/EntityRow.php
index e95e5fa..c0034d4 100644
--- a/core/modules/views/src/Plugin/views/row/EntityRow.php
+++ b/core/modules/views/src/Plugin/views/row/EntityRow.php
@@ -172,7 +172,13 @@ public function summaryTitle() {
    */
   public function query() {
     parent::query();
-    $this->getEntityTranslationRenderer()->query($this->view->getQuery());
+    if (isset($this->options['relationship'], $this->view->relationship[$this->options['relationship']])) {
+      $relationship = $this->view->relationship[$this->options['relationship']]->alias;
+    }
+    else {
+      $relationship = NULL;
+    }
+    $this->getEntityTranslationRenderer()->query($this->view->getQuery(), $relationship);
   }
 
   /**
@@ -181,7 +187,7 @@ public function query() {
   public function preRender($result) {
     parent::preRender($result);
     if ($result) {
-      $this->getEntityTranslationRenderer()->preRender($result);
+      $this->getEntityTranslationRenderer()->preRender($result, isset($this->options['relationship']) ? $this->options['relationship'] : 'none');
     }
   }
 
@@ -189,7 +195,7 @@ public function preRender($result) {
    * Overrides Drupal\views\Plugin\views\row\RowPluginBase::render().
    */
   public function render($row) {
-    return $this->getEntityTranslationRenderer()->render($row);
+    return $this->getEntityTranslationRenderer()->render($row, isset($this->options['relationship']) ? $this->options['relationship'] : 'none');
   }
 
   /**
diff --git a/core/modules/views/src/Plugin/views/row/RowPluginBase.php b/core/modules/views/src/Plugin/views/row/RowPluginBase.php
index 059a415..9c84f8e 100644
--- a/core/modules/views/src/Plugin/views/row/RowPluginBase.php
+++ b/core/modules/views/src/Plugin/views/row/RowPluginBase.php
@@ -96,7 +96,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
         $data = Views::viewsData()->get($relationship['table']);
         $base = $data[$relationship['field']]['relationship']['base'];
         if ($base == $this->base_table) {
-          $relationship_handler->init($executable, $relationship);
+          $relationship_handler->init($executable, $this->displayHandler, $relationship);
           $relationship_options[$relationship['id']] = $relationship_handler->adminLabel();
         }
       }
diff --git a/core/modules/views/src/Tests/Plugin/EntityRowTest.php b/core/modules/views/src/Tests/Plugin/EntityRowTest.php
new file mode 100644
index 0000000..46a6366
--- /dev/null
+++ b/core/modules/views/src/Tests/Plugin/EntityRowTest.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Tests\Plugin\EntityRowTest.
+ */
+
+namespace Drupal\views\Tests\Plugin;
+
+use Drupal\Core\Form\FormState;
+use Drupal\entity_test\Entity\EntityTest;
+use Drupal\user\Entity\User;
+use Drupal\views\Views;
+use Drupal\views\Tests\ViewUnitTestBase;
+
+/**
+ * Tests the generic entity row plugin.
+ *
+ * @group views
+ * @see \Drupal\views\Plugin\views\row\EntityRow
+ */
+class EntityRowTest extends ViewUnitTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['entity_test', 'field', 'system', 'user'];
+
+  /**
+   * Views used by this test.
+   *
+   * @var array
+   */
+  public static $testViews = array('test_entity_row');
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installEntitySchema('entity_test');
+    $this->installEntitySchema('user');
+  }
+
+  /**
+   * Tests the entity row handler.
+   */
+  public function testEntityRow() {
+    $user = User::create([
+      'name' => 'test user',
+    ]);
+    $user->save();
+
+    $entity_test = EntityTest::create([
+      'user_id' => $user->id(),
+      'name' => 'test entity test',
+    ]);
+    $entity_test->save();
+
+    // Ensure entities have different ids.
+    if ($entity_test->id() == $user->id()) {
+      $entity_test->delete();
+      $entity_test = EntityTest::create([
+        'user_id' => $user->id(),
+        'name' => 'test entity test',
+      ]);
+      $entity_test->save();
+    }
+
+    $view = Views::getView('test_entity_row');
+    $build = $view->preview();
+    $this->render($build);
+
+    $this->assertText('test entity test');
+    $this->assertNoText('Member for');
+
+    // Change the view to use a relationship to render the row.
+    $view = Views::getView('test_entity_row');
+    $display = &$view->storage->getDisplay('default');
+    $display['display_options']['row']['type'] = 'entity:user';
+    $display['display_options']['row']['options']['relationship'] = 'user_id';
+    $view->setDisplay('default');
+    $build = $view->preview();
+    $this->render($build);
+
+    $this->assertNoText('test entity test');
+    $this->assertText('Member for');
+
+    // Tests the available view mode options.
+    $form = array();
+    $form_state = new FormState();
+    $form_state->set('view', $view->storage);
+    $view->rowPlugin->buildOptionsForm($form, $form_state);
+
+    $this->assertTrue(isset($form['view_mode']['#options']['default']), 'Ensure that the default view mode is available');
+  }
+
+}
diff --git a/core/modules/views/src/Tests/Plugin/RowEntityTest.php b/core/modules/views/src/Tests/Plugin/RowEntityTest.php
deleted file mode 100644
index 7de0305..0000000
--- a/core/modules/views/src/Tests/Plugin/RowEntityTest.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\views\Tests\Plugin\RowEntityTest.
- */
-
-namespace Drupal\views\Tests\Plugin;
-
-use Drupal\Core\Form\FormState;
-use Drupal\views\Views;
-use Drupal\views\Tests\ViewUnitTestBase;
-
-/**
- * Tests the generic entity row plugin.
- *
- * @group views
- * @see \Drupal\views\Plugin\views\row\EntityRow
- */
-class RowEntityTest extends ViewUnitTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = ['taxonomy', 'text', 'filter', 'field', 'system', 'node', 'user'];
-
-  /**
-   * Views used by this test.
-   *
-   * @var array
-   */
-  public static $testViews = array('test_entity_row');
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->installEntitySchema('taxonomy_term');
-    $this->installConfig(array('taxonomy'));
-    \Drupal::service('router.builder')->rebuild();
-  }
-
-  /**
-   * Tests the entity row handler.
-   */
-  public function testEntityRow() {
-    $vocab = entity_create('taxonomy_vocabulary', array('name' => $this->randomMachineName(), 'vid' => strtolower($this->randomMachineName())));
-    $vocab->save();
-    $term = entity_create('taxonomy_term', array('name' => $this->randomMachineName(), 'vid' => $vocab->id() ));
-    $term->save();
-
-    $view = Views::getView('test_entity_row');
-    $build = $view->preview();
-    $this->render($build);
-
-    $this->assertText($term->getName(), 'The rendered entity appears as row in the view.');
-
-    // Tests the available view mode options.
-    $form = array();
-    $form_state = new FormState();
-    $form_state->set('view', $view->storage);
-    $view->rowPlugin->buildOptionsForm($form, $form_state);
-
-    $this->assertTrue(isset($form['view_mode']['#options']['default']), 'Ensure that the default view mode is available');
-  }
-
-}
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_row.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_row.yml
index ad9f748..c786e20 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_row.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_entity_row.yml
@@ -6,8 +6,8 @@ label: ''
 module: views
 description: ''
 tag: ''
-base_table: taxonomy_term_field_data
-base_field: nid
+base_table: entity_test
+base_field: id
 core: '8'
 display:
   default:
@@ -21,10 +21,17 @@ display:
           offset: 0
         type: none
       row:
-        type: 'entity:taxonomy_term'
+        type: 'entity:entity_test'
         options:
           relationship: none
           view_mode: full
+      relationships:
+        user_id:
+          table: entity_test
+          field: user_id
+          id: user_id
+          relationship: none
+          plugin_id: standard
     display_plugin: default
     display_title: Master
     id: default
