diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index d315b27..acf3040 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -585,7 +585,7 @@ public function onChange($name) {
       case $this->defaultLangcodeKey:
         // @todo Use a standard method to make the default_langcode field
         //   read-only. See https://www.drupal.org/node/2443991.
-        if (isset($this->values[$this->defaultLangcodeKey])) {
+        if (isset($this->values[$this->defaultLangcodeKey]) && $this->get($this->defaultLangcodeKey)->value != $this->isDefaultTranslation()) {
           $this->get($this->defaultLangcodeKey)->setValue($this->isDefaultTranslation(), FALSE);
           $message = String::format('The default translation flag cannot be changed (@langcode).', array('@langcode' => $this->activeLangcode));
           throw new \LogicException($message);
diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
index 071de3e..99551fc 100644
--- a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
+++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
@@ -316,8 +316,7 @@ public function buildComponents(array &$build, array $entities, array $displays,
       $entities_by_bundle[$entity->bundle()][$id] = $entity;
     }
 
-    // Invoke hook_entity_prepare_view().
-    $this->moduleHandler()->invokeAll('entity_prepare_view', array($this->entityTypeId, $entities, $displays, $view_mode));
+    $this->prepareView($entities, $displays, $view_mode);
 
     // Let the displays build their render arrays.
     foreach ($entities_by_bundle as $bundle => $bundle_entities) {
@@ -329,6 +328,14 @@ public function buildComponents(array &$build, array $entities, array $displays,
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function prepareView($entities, $displays, $view_mode) {
+    // Invoke hook_entity_prepare_view().
+    $this->moduleHandler()->invokeAll('entity_prepare_view', array($this->entityTypeId, $entities, $displays, $view_mode));
+  }
+
+  /**
    * Specific per-entity building.
    *
    * @param array $build
diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilderInterface.php b/core/lib/Drupal/Core/Entity/EntityViewBuilderInterface.php
index c3e167a..2d5f48c 100644
--- a/core/lib/Drupal/Core/Entity/EntityViewBuilderInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityViewBuilderInterface.php
@@ -36,6 +36,19 @@
   public function buildComponents(array &$build, array $entities, array $displays, $view_mode, $langcode = NULL);
 
   /**
+   * Prepares the specified entities for rendering.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface[] $entities
+   *   The entities whose content is being built.
+   * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface[] $displays
+   *   The array of entity view displays holding the display options
+   *   configured for the entity components, keyed by bundle name.
+   * @param $view_mode
+   *   The view mode in which the entity is being viewed.
+   */
+  public function prepareView($entities, $displays, $view_mode);
+
+  /**
    * Returns the render array for the provided entity.
    *
    * @param \Drupal\Core\Entity\EntityInterface $entity
diff --git a/core/modules/field/src/Tests/Views/HandlerFieldFieldTest.php b/core/modules/field/src/Tests/Views/HandlerFieldFieldTest.php
index c017ded..92ea637 100644
--- a/core/modules/field/src/Tests/Views/HandlerFieldFieldTest.php
+++ b/core/modules/field/src/Tests/Views/HandlerFieldFieldTest.php
@@ -205,7 +205,7 @@ public function _testMultipleFieldRender() {
       foreach ($pure_items as $j => $item) {
         $items[] = $pure_items[$j]['value'];
       }
-      $this->assertEqual($rendered_field, implode(', ', $items), 'Make sure that the amount of items is limited.');
+      $this->assertEqual($rendered_field, implode(', ', $items), 'The amount of items is limited.');
     }
 
     // Test that an empty field is rendered without error.
@@ -227,7 +227,7 @@ public function _testMultipleFieldRender() {
       foreach ($pure_items as $j => $item) {
         $items[] = $pure_items[$j]['value'];
       }
-      $this->assertEqual($rendered_field, implode(', ', $items), 'Make sure that the amount of items is limited.');
+      $this->assertEqual($rendered_field, implode(', ', $items), 'The amount of items is limited and the offset is correct.');
     }
     $view->destroy();
 
@@ -248,7 +248,7 @@ public function _testMultipleFieldRender() {
       foreach ($pure_items as $j => $item) {
         $items[] = $pure_items[$j]['value'];
       }
-      $this->assertEqual($rendered_field, implode(', ', $items), 'Make sure that the amount of items is limited.');
+      $this->assertEqual($rendered_field, implode(', ', $items), 'The amount of items is limited and they are reversed.');
     }
     $view->destroy();
 
@@ -266,7 +266,7 @@ public function _testMultipleFieldRender() {
       $pure_items = $this->nodes[$i]->{$field_name}->getValue();
       $items[] = $pure_items[0]['value'];
       $items[] = $pure_items[4]['value'];
-      $this->assertEqual($rendered_field, implode(', ', $items), 'Make sure that the amount of items is limited.');
+      $this->assertEqual($rendered_field, implode(', ', $items), 'Items are limited to first and last.');
     }
     $view->destroy();
 
@@ -286,7 +286,7 @@ public function _testMultipleFieldRender() {
       foreach ($pure_items as $j => $item) {
         $items[] = $pure_items[$j]['value'];
       }
-      $this->assertEqual($rendered_field, implode(':', $items), 'Make sure that the amount of items is limited.');
+      $this->assertEqual($rendered_field, implode(':', $items), 'The amount of items is limited and the custom separator is correct.');
     }
     $view->destroy();
 
@@ -305,7 +305,7 @@ public function _testMultipleFieldRender() {
       foreach ($pure_items as $j => $item) {
         $items[] = $pure_items[$j]['value'];
       }
-      $this->assertEqual($rendered_field, implode('<h2>test</h2>', $items), 'Make sure that the amount of items is limited.');
+      $this->assertEqual($rendered_field, implode('<h2>test</h2>', $items), 'The custom separator is correctly escaped.');
     }
     $view->destroy();
   }
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index 50b6f36..b4bca6f 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -217,6 +217,11 @@ function rdf_entity_prepare_view($entity_type, array $entities, array $displays)
       $field_mapping = $mapping->getPreparedFieldMapping($name);
       if ($field_mapping) {
         foreach ($entity->get($name) as $item) {
+          // @todo Initialize field item attributes, if they are missing. Remove
+          //   this in https://www.drupal.org/node/2450477.
+          if (!isset($item->_attributes)) {
+            $item->_attributes = array();
+          }
           $item->_attributes += rdf_rdfa_attributes($field_mapping, $item->toArray());
         }
       }
diff --git a/core/modules/system/src/Tests/Entity/EntityTranslationTest.php b/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
index aab0d28..c7eee60 100644
--- a/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
@@ -383,10 +383,20 @@ protected function doTestEntityTranslationAPI($entity_type) {
 
     // Verify that changing the default translation flag causes an exception to
     // be thrown.
-    $message = 'The default translation flag cannot be changed.';
     foreach ($entity->getTranslationLanguages() as $t_langcode => $language) {
       $translation = $entity->getTranslation($t_langcode);
       $default = $translation->isDefaultTranslation();
+
+      $message = 'The default translation flag can be reassigned the same value.';
+      try {
+        $translation->{$default_langcode_key}->value = $default;
+        $this->pass($message);
+      }
+      catch (\LogicException $e) {
+        $this->fail($message);
+      }
+
+      $message = 'The default translation flag cannot be changed.';
       try {
         $translation->{$default_langcode_key}->value = !$default;
         $this->fail($message);
@@ -394,6 +404,7 @@ protected function doTestEntityTranslationAPI($entity_type) {
       catch (\LogicException $e) {
         $this->pass($message);
       }
+
       $this->assertEqual($translation->{$default_langcode_key}->value, $default);
     }
 
diff --git a/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php b/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php
index 8470efd..697ae8a 100644
--- a/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php
+++ b/core/modules/views/src/Entity/Render/ConfigurableLanguageRenderer.php
@@ -15,7 +15,7 @@
 /**
  * Renders entities in a configured language.
  */
-class ConfigurableLanguageRenderer extends RendererBase {
+class ConfigurableLanguageRenderer extends EntityTranslationRendererBase {
 
   /**
    * A specific language code for rendering if available.
diff --git a/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php b/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php
index bab75d8..dbd3a72 100644
--- a/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php
+++ b/core/modules/views/src/Entity/Render/DefaultLanguageRenderer.php
@@ -12,7 +12,7 @@
 /**
  * Renders entities in their default language.
  */
-class DefaultLanguageRenderer extends RendererBase {
+class DefaultLanguageRenderer extends EntityTranslationRendererBase {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/views/src/Entity/Render/EntityFieldRenderer.php b/core/modules/views/src/Entity/Render/EntityFieldRenderer.php
new file mode 100644
index 0000000..00b238d
--- /dev/null
+++ b/core/modules/views/src/Entity/Render/EntityFieldRenderer.php
@@ -0,0 +1,358 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Entity\Render\EntityFieldRenderer.
+ */
+
+namespace Drupal\views\Entity\Render;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\RevisionableInterface;
+use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\views\Plugin\views\field\Field;
+use Drupal\views\Plugin\views\query\QueryPluginBase;
+use Drupal\views\ResultRow;
+use Drupal\views\ViewExecutable;
+
+/**
+ * Defines a base class for entity translation renderers.
+ */
+class EntityFieldRenderer extends RendererBase {
+  use EntityTranslationRenderTrait;
+
+  /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
+   * Static cache for ::getRenderableFieldNames().
+   *
+   * @var string[][]
+   */
+  protected $renderableFieldNames;
+
+  /**
+   * A list of indexes of rows whose fields have already been rendered.
+   *
+   * @var int[]
+   */
+  protected $processedRows = [];
+
+  /**
+   * Constructs a renderer object.
+   *
+   * @param \Drupal\views\ViewExecutable $view
+   *   The entity row being rendered.
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   *   The language manager.
+   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+   *   The entity type.
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   */
+  public function __construct(ViewExecutable $view, LanguageManagerInterface $language_manager, EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager) {
+    parent::__construct($view, $language_manager, $entity_type);
+    $this->entityManager = $entity_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getEntityTypeId() {
+    return $this->entityType->id();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEntityManager() {
+    return $this->entityManager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+
+  protected function getLanguageManager() {
+    return $this->languageManager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getView() {
+    return $this->view;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query(QueryPluginBase $query) {
+    $this->getEntityTranslationRenderer()->query($query);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preRender(array $values) {
+    $this->buildFields($values);
+  }
+
+  /**
+   * Renders all fields of all rows using entity display objects.
+   *
+   * @param \Drupal\views\ResultRow[] $values
+   *   An array of all ResultRow objects returned from the query.
+   *
+   * @see \Drupal\Core\Entity\Entity\EntityViewDisplay
+   */
+  protected function buildFields(array $values) {
+    $entities = [];
+    $translations = [];
+    $bundle_field_names = [];
+
+    foreach ($values as $row) {
+      // Skip this row if it has already been processed.
+      if (!empty($this->processedRows[$row->index])) {
+        continue;
+      }
+      $this->processedRows[$row->index] = TRUE;
+
+      // Collect a list of entity types to process from the view relationships.
+      // We store a field name for each relationship to make it easier
+      // retrieving the related entity from the row.
+      if (!isset($entity_type_ids)) {
+        $row_entities = [$row->_entity] + array_intersect_key($row->_relationship_entities, $this->view->relationship);
+        $entity_type_ids = array_combine(
+          array_keys($row_entities),
+          array_map(function (EntityInterface $entity) { return $entity->getEntityTypeId(); }, $row_entities)
+        );
+      }
+
+      // Process all entities for each entity type.
+      foreach ($entity_type_ids as $rel_field_name => $entity_type_id) {
+        $entity = isset($row->_relationship_entities[$rel_field_name]) ? $row->_relationship_entities[$rel_field_name] : $row->_entity;
+        $entity_type_id = $entity->getEntityTypeId();
+        $bundle = $entity->bundle();
+        $key = $this->getEntityRowKey($row, $entity);
+
+        // Skip this entity if has already been processed.
+        if (isset($entities[$entity_type_id][$bundle][$key])) {
+          continue;
+        }
+
+        // We need to allow each field plugin to process the entity, but we
+        // clone it just once to improve performance.
+        $entity = $this->getEntityTranslation(clone $entity, $row);
+        $field_names = $this->getRenderableFieldNames();
+        // There might be relationships without fields. A typical example is to
+        // show a list of nodes, filtered by the current user.
+        $field_names += [$entity_type_id => []];
+        $processed = FALSE;
+
+        foreach ($field_names[$entity_type_id] as $view_field_name => $field_name) {
+          if ($entity->hasField($field_name)) {
+            /** @var \Drupal\views\Plugin\views\field\Field $field */
+            $field = $this->view->field[$view_field_name];
+            $processed_entity = $field->processEntity($row, $entity, FALSE);
+            if ($processed_entity) {
+              $entity = $processed_entity;
+              $processed = TRUE;
+            }
+          }
+        }
+
+        // Collect entities and bundle information if the entity was processed,
+        // otherwise we have no data to render.
+        if ($processed) {
+          $entities[$entity_type_id][$bundle][$key] = $entity;
+          $translations[$entity_type_id][$entity->language()->getId()][$entity->id()] = $entity;
+          if (!isset($bundle_field_names[$entity_type_id][$bundle])) {
+            $bundle_field_names[$entity_type_id][$bundle] = array_intersect($field_names[$entity_type_id], array_keys($entity->getFieldDefinitions()));
+          }
+        }
+      }
+    }
+
+    // We need to prepare field output just once.
+    if ($entities) {
+      foreach ($entities as $entity_type_id => $entity_type_entities) {
+        $displays = $this->getBundleDisplays($entity_type_id, $bundle_field_names[$entity_type_id]);
+
+        // Run prepare_view on all result entities. We need to prepare entities
+        // per language as the array needs to be keyed by entity id.
+        foreach ($translations[$entity_type_id] as $langcode => $entity_translations) {
+          $this->entityManager
+            ->getViewBuilder($entity_type_id)
+            ->prepareView($entity_translations, $displays, $this->getCustomViewMode($entity_type_id));
+        }
+
+        // Build render arrays for each bundle.
+        if (!isset($this->build[$entity_type_id])) {
+          $this->build[$entity_type_id] = [];
+        }
+        foreach ($entity_type_entities as $bundle => $bundle_entities) {
+          $this->build[$entity_type_id] += $displays[$bundle]->buildMultiple($bundle_entities);
+        }
+      }
+    }
+  }
+
+  /**
+   * Returns a list of names of entity fields to be rendered.
+   *
+   * @return string[][]
+   *   An associative array of entity field names keyed by the corresponding
+   *   Views field plugin names.
+   */
+  protected function getRenderableFieldNames() {
+    if (!isset($this->renderableFieldNames)) {
+      $this->renderableFieldNames = [];
+      foreach ($this->view->field as $view_field_name => $field) {
+        if ($field instanceof Field) {
+          $entity_type_id = $field->definition['entity_type'];
+          $this->renderableFieldNames[$entity_type_id][$view_field_name] = $field->definition['field_name'];
+        }
+      }
+    }
+    return $this->renderableFieldNames;
+  }
+
+  /**
+   * Return the code of the language the field should be displayed in.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   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.
+   *
+   * @return \Drupal\Core\Entity\FieldableEntityInterface
+   *   The entity translation object for the passed row.
+   */
+  protected function getEntityTranslation(EntityInterface $entity, ResultRow $row) {
+    // 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.
+    $langcode = $this->getEntityTranslationRenderer()->getLangcode($row);
+    return $this->entityManager->getTranslationFromContext($entity, $langcode);
+  }
+
+  /**
+   * Returns the custom view mode to be used for field rendering.
+   *
+   * @param string $entity_type_id
+   *   The type of the entities whose fields are being rendered.
+   *
+   * @return string
+   *   A custom view mode name.
+   */
+  protected function getCustomViewMode($entity_type_id) {
+    return 'views:' . $this->view->storage->id() . ':' . $this->view->current_display . ':' . $entity_type_id;
+  }
+
+  /**
+   * Returns the display objects to be used to render fields.
+   *
+   * @param string $entity_type_id
+   *   The id of the entity type being processed.
+   * @param string[][] $bundle_field_names
+   *   An associative array of arrays of field names keyed by bundle name. Each
+   *   nested array is keyed by a Views field plugin name.
+   *
+   * @return \Drupal\Core\Entity\Entity\EntityViewDisplay[]
+   *   An associative array of display objects keyed by bundle name.
+   */
+  protected function getBundleDisplays($entity_type_id, $bundle_field_names) {
+    /** @var \Drupal\Core\Entity\Entity\EntityViewDisplay[] $displays */
+    $displays = [];
+    $storage = $this->entityManager->getStorage('entity_view_display');
+    $view_mode = $this->getCustomViewMode($entity_type_id);
+
+    // Create one entity display object per bundle, so you can prepare entities
+    // in different bundles at the same time.
+    foreach ($bundle_field_names as $bundle => $field_names) {
+      $displays[$bundle] = $storage->create([
+        'targetEntityType' => $entity_type_id,
+        'bundle' => $bundle,
+        'viewMode' => $view_mode,
+      ]);
+
+      // Configure display options for the fields in the view.
+      foreach ($field_names as $view_field_name => $field_name) {
+        $field = $this->view->field[$view_field_name];
+        $options = [
+          'type' => $field->options['type'],
+          'settings' => $field->options['settings'],
+          'label' => 'hidden',
+        ];
+        $displays[$bundle]->setComponent($field_name, $options);
+      }
+    }
+
+    return $displays;
+  }
+
+  /**
+   * Renders entity field data.
+   *
+   * @param \Drupal\views\ResultRow $row
+   *   A single row of the query result.
+   * @param \Drupal\views\Plugin\views\field\Field $field
+   *   (optional) A field to be rendered.
+   *
+   * @return array
+   *   A renderable array for the entity data contained in the result row.
+   */
+  public function render(ResultRow $row, Field $field = NULL) {
+    $build = $this->build;
+
+    if (isset($field)) {
+      $entity = $field->getEntity($row);
+      if (!$entity) {
+        $build = [];
+      }
+      else {
+        $entity_type_id = $entity->getEntityTypeId();
+        $key = $this->getEntityRowKey($row, $entity);
+        $field_name = $field->definition['field_name'];
+
+        // Make sure entity fields are actually rendered for the current row.
+        if (!isset($build[$entity_type_id][$key])) {
+          $this->buildFields([$row]);
+          $build = $this->build;
+        }
+
+        $build = isset($build[$entity_type_id][$key][$field_name]) ? $build[$entity_type_id][$key][$field_name] : [];
+      }
+    }
+
+    return $build;
+  }
+
+  /**
+   * Returns a unique identifier for a row entity.
+   *
+   * @param \Drupal\views\ResultRow $row
+   *   A single row of the query result.
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The row entity.
+   *
+   * @return string
+   *   The entity row key.
+   */
+  protected function getEntityRowKey(ResultRow $row, EntityInterface $entity) {
+    $key = $row->index . ':' . $entity->id();
+    if ($entity instanceof RevisionableInterface) {
+      $key .= ':' . $entity->getRevisionId();
+    }
+    return $key;
+  }
+
+}
diff --git a/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
index 1be7364..f874c75 100644
--- a/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
+++ b/core/modules/views/src/Entity/Render/EntityTranslationRenderTrait.php
@@ -10,25 +10,25 @@
 use Drupal\views\Plugin\views\PluginBase;
 
 /**
- * Trait used to instantiate the view's entity language render.
+ * Trait used to instantiate the view's entity translation renderer.
  */
 trait EntityTranslationRenderTrait {
 
   /**
    * The renderer to be used to render the entity row.
    *
-   * @var \Drupal\views\Entity\Render\RendererBase
+   * @var \Drupal\views\Entity\Render\EntityTranslationRendererBase
    */
-  protected $entityLanguageRenderer;
+  protected $entityTranslationRenderer;
 
   /**
    * Returns the current renderer.
    *
-   * @return \Drupal\views\Entity\Render\RendererBase
+   * @return \Drupal\views\Entity\Render\EntityTranslationRendererBase
    *   The configured renderer.
    */
   protected function getEntityTranslationRenderer() {
-    if (!isset($this->entityLanguageRenderer)) {
+    if (!isset($this->entityTranslationRenderer)) {
       $view = $this->getView();
       $rendering_language = $view->display_handler->getOption('rendering_language');
       $langcode = NULL;
@@ -52,9 +52,9 @@ protected function getEntityTranslationRenderer() {
       }
       $class = '\Drupal\views\Entity\Render\\' . $renderer;
       $entity_type = $this->getEntityManager()->getDefinition($this->getEntityTypeId());
-      $this->entityLanguageRenderer = new $class($view, $this->getLanguageManager(), $entity_type, $langcode);
+      $this->entityTranslationRenderer = new $class($view, $this->getLanguageManager(), $entity_type, $langcode);
     }
-    return $this->entityLanguageRenderer;
+    return $this->entityTranslationRenderer;
   }
 
   /**
diff --git a/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php b/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php
new file mode 100644
index 0000000..bb9b8cc
--- /dev/null
+++ b/core/modules/views/src/Entity/Render/EntityTranslationRendererBase.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Entity\Render\EntityTranslationRendererBase.
+ */
+
+namespace Drupal\views\Entity\Render;
+
+use Drupal\views\Plugin\views\query\QueryPluginBase;
+use Drupal\views\ResultRow;
+
+/**
+ * Defines a base class for entity translation renderers.
+ */
+abstract class EntityTranslationRendererBase extends RendererBase {
+
+  /**
+   * Returns the language code associated to the given row.
+   *
+   * @param \Drupal\views\ResultRow $row
+   *   The result row.
+   *
+   * @return string
+   *   A language code.
+   */
+  abstract public function getLangcode(ResultRow $row);
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query(QueryPluginBase $query) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preRender(array $result) {
+    $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;
+      $this->build[$entity->id()] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $this->getLangcode($row));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function render(ResultRow $row) {
+    $entity_id = $row->_entity->id();
+    return $this->build[$entity_id];
+  }
+
+}
diff --git a/core/modules/views/src/Entity/Render/RendererBase.php b/core/modules/views/src/Entity/Render/RendererBase.php
index be8aea6..137fe1d 100644
--- a/core/modules/views/src/Entity/Render/RendererBase.php
+++ b/core/modules/views/src/Entity/Render/RendererBase.php
@@ -14,7 +14,7 @@
 use Drupal\views\ViewExecutable;
 
 /**
- * Defines a base class for entity row renderers.
+ * Defines a base class for entity renderers.
  */
 abstract class RendererBase {
 
@@ -63,54 +63,30 @@ public function __construct(ViewExecutable $view, LanguageManagerInterface $lang
   }
 
   /**
-   * Returns the language code associated to the given row.
-   *
-   * @param \Drupal\views\ResultRow $row
-   *   The result row.
-   *
-   * @return string
-   *   A language code.
-   */
-  abstract public function getLangcode(ResultRow $row);
-
-  /**
    * Alters the query if needed.
    *
    * @param \Drupal\views\Plugin\views\query\QueryPluginBase $query
    *   The query to alter.
    */
-  public function query(QueryPluginBase $query) {
-  }
+  abstract public function query(QueryPluginBase $query);
 
   /**
-   * Runs before each row is rendered.
+   * Runs before each entity is rendered.
    *
    * @param $result
    *   The full array of results from the query.
    */
-  public function preRender(array $result) {
-    $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;
-      $this->build[$entity->id()] = $view_builder->view($entity, $this->view->rowPlugin->options['view_mode'], $this->getLangcode($row));
-    }
-  }
+  abstract public function preRender(array $result);
 
   /**
-   * Renders a row object.
+   * Renders entity data.
    *
    * @param \Drupal\views\ResultRow $row
    *   A single row of the query result.
    *
    * @return array
-   *   The renderable array of a single row.
+   *   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];
-  }
+  abstract public function render(ResultRow $row);
 
 }
diff --git a/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
index 58c8ff0..093b249 100644
--- a/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
+++ b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
@@ -13,7 +13,7 @@
 /**
  * Renders entity translations in their active language.
  */
-class TranslationLanguageRenderer extends RendererBase {
+class TranslationLanguageRenderer extends EntityTranslationRendererBase {
 
   /**
    * Stores the field alias of the langcode column.
diff --git a/core/modules/views/src/Plugin/views/field/Field.php b/core/modules/views/src/Plugin/views/field/Field.php
index 46d3f5f..90b204d 100644
--- a/core/modules/views/src/Plugin/views/field/Field.php
+++ b/core/modules/views/src/Plugin/views/field/Field.php
@@ -16,13 +16,12 @@
 use Drupal\Core\Field\FormatterPluginManager;
 use Drupal\Core\Form\FormHelper;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Language\LanguageManagerInterface;
 use Drupal\Core\Render\Element;
 use Drupal\Core\Render\RendererInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\views\FieldAPIHandlerTrait;
-use Drupal\views\Entity\Render\EntityTranslationRenderTrait;
+use Drupal\views\Entity\Render\EntityFieldRenderer;
 use Drupal\views\Plugin\CacheablePluginInterface;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\ResultRow;
@@ -30,7 +29,7 @@
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
- * A field that displays fieldapi fields.
+ * A field that displays entity field data.
  *
  * @ingroup views_field_handlers
  *
@@ -39,8 +38,6 @@
  * @ViewsField("field")
  */
 class Field extends FieldPluginBase implements CacheablePluginInterface, MultiItemsFieldHandlerInterface {
-  use EntityTranslationRenderTrait;
-
   use FieldAPIHandlerTrait;
 
   /**
@@ -114,6 +111,13 @@ class Field extends FieldPluginBase implements CacheablePluginInterface, MultiIt
   protected $fieldTypePluginManager;
 
   /**
+   * Static cache for ::getEntityFieldRenderer().
+   *
+   * @var \Drupal\views\Entity\Render\EntityFieldRenderer
+   */
+  protected $entityFieldRenderer;
+
+  /**
    * Constructs a \Drupal\field\Plugin\views\field\Field object.
    *
    * @param array $configuration
@@ -201,13 +205,6 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
   /**
    * {@inheritdoc}
    */
-  public function getEntityTypeId() {
-    return $this->getEntityType();
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   protected function getEntityManager() {
     return $this->entityManager;
   }
@@ -215,19 +212,6 @@ protected function getEntityManager() {
   /**
    * {@inheritdoc}
    */
-  protected function getLanguageManager() {
-    return $this->languageManager;
-  }
-  /**
-   * {@inheritdoc}
-   */
-  protected function getView() {
-    return $this->view;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function access(AccountInterface $account) {
     $access_control_handler = $this->entityManager->getAccessControlHandler($this->getEntityType());
     return $access_control_handler->fieldAccess('view', $this->getFieldDefinition(), $account);
@@ -271,8 +255,8 @@ public function query($use_groupby = FALSE) {
       $this->addAdditionalFields($fields);
     }
 
-    // Let the configured entity translation renderer alter the query if needed.
-    $this->getEntityTranslationRenderer()->query($this->query);
+    // Let the entity field renderer alter the query if needed.
+    $this->getEntityFieldRenderer()->query($this->query);
   }
 
   /**
@@ -685,6 +669,7 @@ public function submitGroupByForm(&$form, FormStateInterface $form_state) {
    */
   public function renderItems($items) {
     if (!empty($items)) {
+      $items = $this->prepareItemsByDelta($items);
       if ($this->options['multi_type'] == 'separator' || !$this->options['group_rows']) {
         $separator = $this->options['multi_type'] == 'separator' ? SafeMarkup::checkAdminXss($this->options['separator']) : '';
         $build = [
@@ -706,6 +691,106 @@ public function renderItems($items) {
   }
 
   /**
+   * Adapts the $items according to the delta configuration.
+   *
+   * The method filters limits the shown deltas, reorders the items as well as
+   * takens into account an offset.
+   *
+   * @param array $all_values
+   *   The items for individual rendering.
+   *
+   * @return array
+   *   The manipulated items.
+   */
+  protected function prepareItemsByDelta(array $all_values) {
+    if ($this->options['delta_reversed']) {
+      $all_values = array_reverse($all_values);
+    }
+
+    // We are supposed to show only certain deltas.
+    if ($this->limit_values) {
+      $row = $this->view->result[$this->view->row_index];
+
+      // Offset is calculated differently when row grouping for a field is
+      // not enabled. Since there are multiple rows, the delta needs to be
+      // taken into account, so that different values are shown per row.
+      if (!$this->options['group_rows'] && isset($this->aliases['delta']) && isset($row->{$this->aliases['delta']})) {
+        $delta_limit = 1;
+        $offset = $row->{$this->aliases['delta']};
+      }
+      // Single fields don't have a delta available so choose 0.
+      elseif (!$this->options['group_rows'] && !$this->multiple) {
+        $delta_limit = 1;
+        $offset = 0;
+      }
+      else {
+        $delta_limit = $this->options['delta_limit'];
+        $offset = intval($this->options['delta_offset']);
+
+        // We should only get here in this case if there's an offset, and
+        // in that case we're limiting to all values after the offset.
+        if ($delta_limit === 0) {
+          $delta_limit = count($all_values) - $offset;
+        }
+      }
+
+      // Determine if only the first and last values should be shown
+      $delta_first_last = $this->options['delta_first_last'];
+
+      $new_values = array();
+      for ($i = 0; $i < $delta_limit; $i++) {
+        $new_delta = $offset + $i;
+
+        if (isset($all_values[$new_delta])) {
+          // If first-last option was selected, only use the first and last values
+          if (!$delta_first_last
+            // Use the first value.
+            || $new_delta == $offset
+            // Use the last value.
+            || $new_delta == ($delta_limit + $offset - 1)) {
+            $new_values[] = $all_values[$new_delta];
+          }
+        }
+      }
+      $all_values = $new_values;
+    }
+
+    return $all_values;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preRender(&$values) {
+    parent::preRender($values);
+    $this->getEntityFieldRenderer()->preRender($values);
+  }
+
+  /**
+   * Returns the entity field renderer.
+   *
+   * @return \Drupal\views\Entity\Render\EntityFieldRenderer
+   *   The entity field renderer.
+   */
+  protected function getEntityFieldRenderer() {
+    if (!isset($this->entityFieldRenderer)) {
+      foreach ($this->view->field as $field) {
+        if (isset($field->entityFieldRenderer)) {
+          $this->entityFieldRenderer = $field->entityFieldRenderer;
+          break;
+        }
+      }
+      if (!isset($this->entityFieldRenderer)) {
+        $base_table = $this->view->storage->get('base_table');
+        $views_data = $this->getViewsData()->get($base_table);
+        $entity_type = $this->entityManager->getDefinition($views_data['table']['entity type']);
+        $this->entityFieldRenderer = new EntityFieldRenderer($this->view, $this->languageManager, $entity_type, $this->entityManager);
+      }
+    }
+    return $this->entityFieldRenderer;
+  }
+
+  /**
    * Gets an array of items for the field.
    *
    * @param \Drupal\views\ResultRow $values
@@ -715,41 +800,31 @@ public function renderItems($items) {
    *   An array of items for the field.
    */
   public function getItems(ResultRow $values) {
-    $original_entity = $this->getEntity($values);
-    if (!$original_entity) {
-      return array();
-    }
-    $entity = $this->process_entity($values, $original_entity);
-    if (!$entity) {
-      return array();
-    }
+    $build = $this->getEntityFieldRenderer()->render($values, $this);
 
-    $display = array(
-      'type' => $this->options['type'],
-      'settings' => $this->options['settings'],
-      'label' => 'hidden',
-    );
-    $render_array = $entity->get($this->definition['field_name'])->view($display);
-
-    $items = array();
+    if (!$build) {
+      return [];
+    }
     if ($this->options['field_api_classes']) {
-      return array(array('rendered' => $this->renderer->render($render_array)));
+      return [['rendered' => $this->renderer->render($build)]];
     }
 
-    foreach (Element::children($render_array) as $count) {
-      $items[$count]['rendered'] = $render_array[$count];
-      // FieldItemListInterface::view() adds an #access property to the render
-      // array that determines whether or not the current user is allowed to
-      // view the field in the context of the current entity. We need to respect
-      // this parameter when we pull out the children of the field array for
+    // Render using the formatted data itself.
+    $items = [];
+    foreach (Element::children($build) as $delta) {
+      $items[$delta]['rendered'] = $build[$delta];
+      // EntityViewDisplay::build() adds an #access property to the render array
+      // that determines whether or not the current user is allowed to view the
+      // field in the context of the current entity. We need to respect this
+      // parameter when we pull out the children of the field array for
       // rendering.
-      if (isset($render_array['#access'])) {
-        $items[$count]['rendered']['#access'] = $render_array['#access'];
+      if (isset($build['#access'])) {
+        $items[$delta]['rendered']['#access'] = $build['#access'];
       }
       // Only add the raw field items (for use in tokens) if the current user
       // has access to view the field content.
-      if ((!isset($items[$count]['rendered']['#access']) || $items[$count]['rendered']['#access']) && !empty($render_array['#items'][$count])) {
-        $items[$count]['raw'] = $render_array['#items'][$count];
+      if ((!isset($items[$delta]['rendered']['#access']) || $items[$delta]['rendered']['#access']) && !empty($build['#items'][$delta])) {
+        $items[$delta]['raw'] = $build['#items'][$delta];
       }
     }
     return $items;
@@ -765,15 +840,15 @@ public function getItems(ResultRow $values) {
    *   The result row object containing the values.
    * @param \Drupal\Core\Entity\EntityInterface $entity
    *   The entity to be processed.
+   * @param bool $clone
+   *   (optional) Whether a clone of the specified entity should processed.
+   *   Defaults to TRUE.
    *
-   * @return
-   *   TRUE if the processing completed successfully, otherwise FALSE.
+   * @return bool|\Drupal\Core\Entity\FieldableEntityInterface
+   *   Returns the processed entity if successful, else returns FALSE.
    */
-  function process_entity(ResultRow $values, EntityInterface $entity) {
-    $processed_entity = clone $entity;
-
-    $langcode = $this->getFieldLangcode($processed_entity, $values);
-    $processed_entity = $processed_entity->getTranslation($langcode);
+  public function processEntity(ResultRow $values, EntityInterface $entity, $clone = TRUE) {
+    $processed_entity = $clone ? clone $entity : $entity;
 
     // If we are grouping, copy our group fields into the cloned entity.
     // It's possible this will cause some weirdness, but there's only
@@ -811,57 +886,6 @@ function process_entity(ResultRow $values, EntityInterface $entity) {
       return FALSE;
     }
 
-    // We are supposed to show only certain deltas.
-    if ($this->limit_values && !empty($processed_entity->{$this->definition['field_name']})) {
-      $all_values = !empty($processed_entity->{$this->definition['field_name']}) ? $processed_entity->{$this->definition['field_name']}->getValue() : array();
-      if ($this->options['delta_reversed']) {
-        $all_values = array_reverse($all_values);
-      }
-
-      // Offset is calculated differently when row grouping for a field is
-      // not enabled. Since there are multiple rows, the delta needs to be
-      // taken into account, so that different values are shown per row.
-      if (!$this->options['group_rows'] && isset($this->aliases['delta']) && isset($values->{$this->aliases['delta']})) {
-        $delta_limit = 1;
-        $offset = $values->{$this->aliases['delta']};
-      }
-      // Single fields don't have a delta available so choose 0.
-      elseif (!$this->options['group_rows'] && !$this->multiple) {
-        $delta_limit = 1;
-        $offset = 0;
-      }
-      else {
-        $delta_limit = $this->options['delta_limit'];
-        $offset = intval($this->options['delta_offset']);
-
-        // We should only get here in this case if there's an offset, and
-        // in that case we're limiting to all values after the offset.
-        if ($delta_limit === 0) {
-          $delta_limit = count($all_values) - $offset;
-        }
-      }
-
-      // Determine if only the first and last values should be shown
-      $delta_first_last = $this->options['delta_first_last'];
-
-      $new_values = array();
-      for ($i = 0; $i < $delta_limit; $i++) {
-        $new_delta = $offset + $i;
-
-        if (isset($all_values[$new_delta])) {
-          // If first-last option was selected, only use the first and last values
-          if (!$delta_first_last
-            // Use the first value.
-            || $new_delta == $offset
-            // Use the last value.
-            || $new_delta == ($delta_limit + $offset - 1)) {
-            $new_values[] = $all_values[$new_delta];
-          }
-        }
-      }
-      $processed_entity->{$this->definition['field_name']} = $new_values;
-    }
-
     return $processed_entity;
   }
 
@@ -900,39 +924,6 @@ protected function addSelfTokens(&$tokens, $item) {
   }
 
   /**
-   * Return the code of the language the field should be displayed in.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   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.
-   *
-   * @return string
-   *   The field language code.
-   */
-  protected function getFieldLangcode(EntityInterface $entity, ResultRow $row) {
-    if ($this->getFieldDefinition()->isTranslatable()) {
-      // Even if the current field is not attached to the main entity, we use it
-      // to determine the field language, as we assume the same language should
-      // be used for all values belonging to a single row, when possible. Below
-      // we apply language fallback to ensure a valid value is always picked.
-      $langcode = $this->getEntityTranslationRenderer()->getLangcode($row);
-
-      // Give the Entity Field API a chance to fallback to a different language
-      // (or LanguageInterface::LANGCODE_NOT_SPECIFIED), in case the field has
-      // no data for the selected language. FieldItemListInterface::view() does
-      // this as well, but since the returned language code is used before
-      // calling it, the fallback needs to happen explicitly.
-      $langcode = $this->entityManager->getTranslationFromContext($entity, $langcode)->language()->getId();
-
-      return $langcode;
-    }
-    else {
-      return LanguageInterface::LANGCODE_NOT_SPECIFIED;
-    }
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function calculateDependencies() {
@@ -983,11 +974,19 @@ protected function getTableMapping() {
    * {@inheritdoc}
    */
   public function getValue(ResultRow $values, $field = NULL) {
-    if ($field === NULL) {
-      return $this->getEntity($values)->{$this->definition['field_name']}->value;
+    /** @var \Drupal\Core\Field\FieldItemListInterface $field_item_list */
+    $field_item_list = $this->getEntity($values)->{$this->definition['field_name']};
+    $field_item_definition = $field_item_list->getFieldDefinition();
+
+    if ($field_item_definition->getFieldStorageDefinition()->getCardinality() == 1) {
+      return $field ? $field_item_list->$field : $field_item_list->value;
     }
 
-    return $this->getEntity($values)->{$this->definition['field_name']}->$field;
+    $values = [];
+    foreach ($field_item_list as $field_item) {
+      $values[] = $field ? $field_item->$field : $field_item->value;
+    }
+    return $values;
   }
 
 }
diff --git a/core/modules/views/src/Tests/Handler/FieldFieldTest.php b/core/modules/views/src/Tests/Handler/FieldFieldTest.php
index 4982cdd..2297871 100644
--- a/core/modules/views/src/Tests/Handler/FieldFieldTest.php
+++ b/core/modules/views/src/Tests/Handler/FieldFieldTest.php
@@ -7,10 +7,12 @@
 
 namespace Drupal\views\Tests\Handler;
 
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\entity_test\Entity\EntityTest;
 use Drupal\entity_test\Entity\EntityTestRev;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
+use Drupal\user\Entity\User;
 use Drupal\views\Plugin\views\field\Field;
 use Drupal\views\Tests\ViewUnitTestBase;
 use Drupal\views\Views;
@@ -31,7 +33,7 @@ class FieldFieldTest extends ViewUnitTestBase {
   /**
    * {@inheritdoc}
    */
-  public static $testViews = ['test_field_field_test', 'test_field_field_revision_test'];
+  public static $testViews = ['test_field_field_test', 'test_field_field_complex_test', 'test_field_field_revision_test', 'test_field_field_revision_complex_test'];
 
   /**
    * The stored test entities.
@@ -48,14 +50,45 @@ class FieldFieldTest extends ViewUnitTestBase {
   protected $entityRevision;
 
   /**
+   * Stores a couple of test users.
+   *
+   * @var \Drupal\user\UserInterface[]
+   */
+  protected $testUsers;
+
+  /**
+   * The admin user.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $adminUser;
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
 
     $this->installEntitySchema('entity_test');
+    $this->installEntitySchema('user');
     $this->installEntitySchema('entity_test_rev');
 
+    // Bypass any field access.
+    $this->adminUser = User::create([
+      'admin_role' => true,
+    ]);
+    $this->adminUser->save();
+    $this->container->get('current_user')->setAccount($this->adminUser);
+
+    $this->testUsers = [];
+    for ($i = 0; $i < 5; $i++) {
+      $this->testUsers[$i] = User::create([
+        'name' => 'test ' . $i,
+        'timezone' => User::getAllowedTimezones()[$i],
+      ]);
+      $this->testUsers[$i]->save();
+    }
+
     // Setup a field storage and field, but also change the views data for the
     // entity_test entity type.
     $field_storage = FieldStorageConfig::create([
@@ -72,11 +105,29 @@ protected function setUp() {
     ]);
     $field->save();
 
+    $field_storage_multiple = FieldStorageConfig::create([
+      'field_name' => 'field_test_multiple',
+      'type' => 'integer',
+      'entity_type' => 'entity_test',
+      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
+    ]);
+    $field_storage_multiple->save();
+
+    $field_multiple = FieldConfig::create([
+      'field_name' => 'field_test_multiple',
+      'entity_type' => 'entity_test',
+      'bundle' => 'entity_test',
+    ]);
+    $field_multiple->save();
+
     $random_number = (string) 30856;
+    $random_number_multiple = (string) 1370359990;
     for ($i = 0; $i < 5; $i++) {
       $this->entities[$i] = $entity = EntityTest::create([
         'bundle' => 'entity_test',
         'field_test' => $random_number[$i],
+        'field_test_multiple' => [$random_number_multiple[$i * 2], $random_number_multiple[$i * 2 + 1]],
+        'user_id' => $this->testUsers[$i]->id(),
       ]);
       $entity->save();
     }
@@ -97,30 +148,58 @@ protected function setUp() {
     ]);
     $field->save();
 
+    $field_storage_multiple = FieldStorageConfig::create([
+      'field_name' => 'field_test_multiple',
+      'type' => 'integer',
+      'entity_type' => 'entity_test_rev',
+      'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
+    ]);
+    $field_storage_multiple->save();
+
+    $field_multiple = FieldConfig::create([
+      'field_name' => 'field_test_multiple',
+      'entity_type' => 'entity_test_rev',
+      'bundle' => 'entity_test_rev',
+    ]);
+    $field_multiple->save();
+
     $this->entityRevision = [];
     $this->entityRevision[0] = $entity = EntityTestRev::create([
       'name' => 'base value',
       'field_test' => 1,
+      'field_test_multiple' => [1, 3, 7],
+      'user_id' =>  $this->testUsers[0]->id(),
     ]);
     $entity->save();
+    $original_entity = clone $entity;
 
-    $entity = clone $entity;
+    $entity = clone $original_entity;
     $entity->setNewRevision(TRUE);
     $entity->name->value = 'revision value1';
     $entity->field_test->value = 2;
+    $entity->field_test_multiple[0]->value = 0;
+    $entity->field_test_multiple[1]->value = 3;
+    $entity->field_test_multiple[2]->value = 5;
+    $entity->user_id->target_id = $this->testUsers[1]->id();
     $entity->save();
     $this->entityRevision[1] = $entity;
 
-    $entity = clone $entity;
+    $entity = clone $original_entity;
     $entity->setNewRevision(TRUE);
     $entity->name->value = 'revision value2';
     $entity->field_test->value = 3;
+    $entity->field_test_multiple[0]->value = 9;
+    $entity->field_test_multiple[1]->value = 9;
+    $entity->field_test_multiple[2]->value = 9;
+    $entity->user_id->target_id = $this->testUsers[2]->id();
     $entity->save();
     $this->entityRevision[2] = $entity;
 
-    $this->entityRevision[0] = $entity = EntityTestRev::create([
+    $this->entityRevision[3] = $entity = EntityTestRev::create([
       'name' => 'next entity value',
       'field_test' => 4,
+      'field_test_multiple' => [2, 9, 9],
+      'user_id' => $this->testUsers[3]->id(),
     ]);
     $entity->save();
 
@@ -186,6 +265,71 @@ public function testSimpleRender() {
   }
 
   /**
+   * Tests the result of a view with complex field configuration.
+   *
+   * A complex field configuration contains multiple times the same field, with
+   * different delta limit / offset.
+   */
+  public function testComplexExecute() {
+    $executable = Views::getView('test_field_field_complex_test');
+    $executable->execute();
+
+    $timezones = [];
+    foreach ($this->testUsers as $user) {
+      $timezones[] = $user->getTimeZone();
+    }
+
+    $this->assertTrue($executable->field['field_test_multiple'] instanceof Field);
+    $this->assertTrue($executable->field['field_test_multiple_1'] instanceof Field);
+    $this->assertTrue($executable->field['field_test_multiple_2'] instanceof Field);
+    $this->assertTrue($executable->field['timezone'] instanceof Field);
+
+    $this->assertIdenticalResultset($executable,
+      [
+        ['timezone' => $timezones[0], 'field_test_multiple' => [1, 3], 'field_test_multiple_1' => [1, 3], 'field_test_multiple_2' => [1, 3]],
+        ['timezone' => $timezones[1], 'field_test_multiple' => [7, 0], 'field_test_multiple_1' => [7, 0], 'field_test_multiple_2' => [7, 0]],
+        ['timezone' => $timezones[2], 'field_test_multiple' => [3, 5], 'field_test_multiple_1' => [3, 5], 'field_test_multiple_2' => [3, 5]],
+        ['timezone' => $timezones[3], 'field_test_multiple' => [9, 9], 'field_test_multiple_1' => [9, 9], 'field_test_multiple_2' => [9, 9]],
+        ['timezone' => $timezones[4], 'field_test_multiple' => [9, 0], 'field_test_multiple_1' => [9, 0], 'field_test_multiple_2' => [9, 0]],
+      ],
+      ['timezone' => 'timezone', 'field_test_multiple' => 'field_test_multiple', 'field_test_multiple_1' => 'field_test_multiple_1', 'field_test_multiple_2' => 'field_test_multiple_2']
+    );
+  }
+
+  /**
+   * Tests the output of a view with complex field configuration.
+   */
+  public function testComplexRender() {
+    $executable = Views::getView('test_field_field_complex_test');
+    $executable->render();
+
+    $this->assertEqual($this->testUsers[0]->getTimeZone(), $executable->getStyle()->getField(0, 'timezone'));
+    $this->assertEqual("1, 3", $executable->getStyle()->getField(0, 'field_test_multiple'));
+    $this->assertEqual("1", $executable->getStyle()->getField(0, 'field_test_multiple_1'));
+    $this->assertEqual("3", $executable->getStyle()->getField(0, 'field_test_multiple_2'));
+
+    $this->assertEqual($this->testUsers[1]->getTimeZone(), $executable->getStyle()->getField(1, 'timezone'));
+    $this->assertEqual("7, 0", $executable->getStyle()->getField(1, 'field_test_multiple'));
+    $this->assertEqual("7", $executable->getStyle()->getField(1, 'field_test_multiple_1'));
+    $this->assertEqual("0", $executable->getStyle()->getField(1, 'field_test_multiple_2'));
+
+    $this->assertEqual($this->testUsers[2]->getTimeZone(), $executable->getStyle()->getField(2, 'timezone'));
+    $this->assertEqual("3, 5", $executable->getStyle()->getField(2, 'field_test_multiple'));
+    $this->assertEqual("3", $executable->getStyle()->getField(2, 'field_test_multiple_1'));
+    $this->assertEqual("5", $executable->getStyle()->getField(2, 'field_test_multiple_2'));
+
+    $this->assertEqual($this->testUsers[3]->getTimeZone(), $executable->getStyle()->getField(3, 'timezone'));
+    $this->assertEqual("9, 9", $executable->getStyle()->getField(3, 'field_test_multiple'));
+    $this->assertEqual("9", $executable->getStyle()->getField(3, 'field_test_multiple_1'));
+    $this->assertEqual("9", $executable->getStyle()->getField(3, 'field_test_multiple_2'));
+
+    $this->assertEqual($this->testUsers[4]->getTimeZone(), $executable->getStyle()->getField(4, 'timezone'));
+    $this->assertEqual("9, 0", $executable->getStyle()->getField(4, 'field_test_multiple'));
+    $this->assertEqual("9", $executable->getStyle()->getField(4, 'field_test_multiple_1'));
+    $this->assertEqual("0", $executable->getStyle()->getField(4, 'field_test_multiple_2'));
+  }
+
+  /**
    * Tests the revision result.
    */
   public function testRevisionExecute() {
@@ -207,11 +351,11 @@ public function testRevisionExecute() {
   }
 
   /**
-   * Tests the output of a revision view with base fields and configurable fields.
+   * Tests the output of a revision view with base and configurable fields.
    */
   public function testRevisionRender() {
     $executable = Views::getView('test_field_field_revision_test');
-    $executable->execute();
+    $executable->render();
 
     $this->assertEqual(1, $executable->getStyle()->getField(0, 'id'));
     $this->assertEqual(1, $executable->getStyle()->getField(0, 'revision_id'));
@@ -232,7 +376,72 @@ public function testRevisionRender() {
     $this->assertEqual(4, $executable->getStyle()->getField(3, 'revision_id'));
     $this->assertEqual(4, $executable->getStyle()->getField(3, 'field_test'));
     $this->assertEqual('next entity value', $executable->getStyle()->getField(3, 'name'));
+  }
 
+  /**
+   * Tests the revision result.
+   */
+  public function testRevisionComplexExecute() {
+    $executable = Views::getView('test_field_field_revision_complex_test');
+    $executable->execute();
+
+    $timezones = [];
+    foreach ($this->testUsers as $user) {
+      $timezones[] = $user->getTimeZone();
+    }
+
+    $this->assertTrue($executable->field['id'] instanceof Field);
+    $this->assertTrue($executable->field['revision_id'] instanceof Field);
+    $this->assertTrue($executable->field['timezone'] instanceof Field);
+    $this->assertTrue($executable->field['field_test_multiple'] instanceof Field);
+    $this->assertTrue($executable->field['field_test_multiple_1'] instanceof Field);
+    $this->assertTrue($executable->field['field_test_multiple_2'] instanceof Field);
+
+    $this->assertIdenticalResultset($executable,
+      [
+        ['id' => 1, 'field_test' => 1, 'revision_id' => 1, 'uid' => $this->testUsers[0]->id(), 'timezone' => $timezones[0], 'field_test_multiple' => [1, 3, 7], 'field_test_multiple_1' => [1, 3, 7], 'field_test_multiple_2' => [1, 3, 7]],
+        ['id' => 1, 'field_test' => 2, 'revision_id' => 2, 'uid' => $this->testUsers[1]->id(), 'timezone' => $timezones[1], 'field_test_multiple' => [0, 3, 5], 'field_test_multiple_1' => [0, 3, 5], 'field_test_multiple_2' => [0, 3, 5]],
+        ['id' => 1, 'field_test' => 3, 'revision_id' => 3, 'uid' => $this->testUsers[2]->id(), 'timezone' => $timezones[2], 'field_test_multiple' => [9, 9, 9], 'field_test_multiple_1' => [9, 9, 9], 'field_test_multiple_2' => [9, 9, 9]],
+        ['id' => 2, 'field_test' => 4, 'revision_id' => 4, 'uid' => $this->testUsers[3]->id(), 'timezone' => $timezones[3], 'field_test_multiple' => [2, 9, 9], 'field_test_multiple_1' => [2, 9, 9], 'field_test_multiple_2' => [2, 9, 9]],
+      ],
+      ['entity_test_rev_revision_id' => 'id', 'revision_id' => 'revision_id', 'users_field_data_entity_test_rev_revision_uid' => 'uid', 'timezone' => 'timezone', 'field_test_multiple' => 'field_test_multiple', 'field_test_multiple_1' => 'field_test_multiple_1', 'field_test_multiple_2' => 'field_test_multiple_2']
+    );
+  }
+
+  /**
+   * Tests the output of a revision view with base fields and configurable fields.
+   */
+  public function testRevisionComplexRender() {
+    $executable = Views::getView('test_field_field_revision_complex_test');
+    $executable->render();
+
+    $this->assertEqual(1, $executable->getStyle()->getField(0, 'id'));
+    $this->assertEqual(1, $executable->getStyle()->getField(0, 'revision_id'));
+    $this->assertEqual($this->testUsers[0]->getTimeZone(), $executable->getStyle()->getField(0, 'timezone'));
+    $this->assertEqual('1, 3, 7', $executable->getStyle()->getField(0, 'field_test_multiple'));
+    $this->assertEqual('1', $executable->getStyle()->getField(0, 'field_test_multiple_1'));
+    $this->assertEqual('3, 7', $executable->getStyle()->getField(0, 'field_test_multiple_2'));
+
+    $this->assertEqual(1, $executable->getStyle()->getField(1, 'id'));
+    $this->assertEqual(2, $executable->getStyle()->getField(1, 'revision_id'));
+    $this->assertEqual($this->testUsers[1]->getTimeZone(), $executable->getStyle()->getField(1, 'timezone'));
+    $this->assertEqual('0, 3, 5', $executable->getStyle()->getField(1, 'field_test_multiple'));
+    $this->assertEqual('0', $executable->getStyle()->getField(1, 'field_test_multiple_1'));
+    $this->assertEqual('3, 5', $executable->getStyle()->getField(1, 'field_test_multiple_2'));
+
+    $this->assertEqual(1, $executable->getStyle()->getField(2, 'id'));
+    $this->assertEqual(3, $executable->getStyle()->getField(2, 'revision_id'));
+    $this->assertEqual($this->testUsers[2]->getTimeZone(), $executable->getStyle()->getField(2, 'timezone'));
+    $this->assertEqual('9, 9, 9', $executable->getStyle()->getField(2, 'field_test_multiple'));
+    $this->assertEqual('9', $executable->getStyle()->getField(2, 'field_test_multiple_1'));
+    $this->assertEqual('9, 9', $executable->getStyle()->getField(2, 'field_test_multiple_2'));
+
+    $this->assertEqual(2, $executable->getStyle()->getField(3, 'id'));
+    $this->assertEqual(4, $executable->getStyle()->getField(3, 'revision_id'));
+    $this->assertEqual($this->testUsers[3]->getTimeZone(), $executable->getStyle()->getField(3, 'timezone'));
+    $this->assertEqual('2, 9, 9', $executable->getStyle()->getField(3, 'field_test_multiple'));
+    $this->assertEqual('2', $executable->getStyle()->getField(3, 'field_test_multiple_1'));
+    $this->assertEqual('9, 9', $executable->getStyle()->getField(3, 'field_test_multiple_2'));
   }
 
 }
diff --git a/core/modules/views/src/Tests/Handler/FieldGroupRowsTest.php b/core/modules/views/src/Tests/Handler/FieldGroupRowsTest.php
index a5f18d2..7ec98b8 100644
--- a/core/modules/views/src/Tests/Handler/FieldGroupRowsTest.php
+++ b/core/modules/views/src/Tests/Handler/FieldGroupRowsTest.php
@@ -85,8 +85,11 @@ public function testGroupRows() {
 
     // Test ungrouped rows.
     $this->executeView($view);
+    $view->row_index = 0;
     $this->assertEqual($view->field[$this->fieldName]->advancedRender($view->result[0]), 'a');
+    $view->row_index = 1;
     $this->assertEqual($view->field[$this->fieldName]->advancedRender($view->result[1]), 'b');
+    $view->row_index = 2;
     $this->assertEqual($view->field[$this->fieldName]->advancedRender($view->result[2]), 'c');
   }
 
diff --git a/core/modules/views/src/Tests/ViewResultAssertionTrait.php b/core/modules/views/src/Tests/ViewResultAssertionTrait.php
index 222bf25..8ba6907 100644
--- a/core/modules/views/src/Tests/ViewResultAssertionTrait.php
+++ b/core/modules/views/src/Tests/ViewResultAssertionTrait.php
@@ -109,7 +109,18 @@ protected function assertIdenticalResultsetHelper($view, $expected_result, $colu
       $row = array();
       foreach ($column_map as $expected_column) {
         // The comparison will be done on the string representation of the value.
-        $row[$expected_column] = (string) (is_object($value) ? $value->$expected_column : $value[$expected_column]);
+        if (is_object($value)) {
+          $row[$expected_column] = (string) $value->$expected_column;
+        }
+        // This case is about fields with multiple values.
+        elseif (is_array($value[$expected_column])) {
+          foreach (array_keys($value[$expected_column]) as $delta) {
+            $row[$expected_column][$delta] = (string) $value[$expected_column][$delta];
+          }
+        }
+        else {
+          $row[$expected_column] = (string) $value[$expected_column];
+        }
       }
       $expected_result[$key] = $row;
     }
@@ -136,4 +147,3 @@ protected function assertIdenticalResultsetHelper($view, $expected_result, $colu
   }
 
 }
-
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_complex_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_complex_test.yml
new file mode 100644
index 0000000..58ee430
--- /dev/null
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_complex_test.yml
@@ -0,0 +1,79 @@
+langcode: und
+status: true
+dependencies: {  }
+id: test_field_field_complex_test
+module: views
+description: ''
+tag: ''
+base_table: entity_test
+base_field: id
+core: '8'
+display:
+  default:
+    display_options:
+      access:
+        type: none
+      cache:
+        type: none
+      fields:
+        id:
+          id: id
+          table: entity_test
+          field: id
+          plugin_id: field
+          entity_type: entity_test
+          entity_field: id
+        field_test_multiple:
+          id: field_test_multiple
+          table: entity_test__field_test_multiple
+          field: field_test_multiple
+          plugin_id: field
+          entity_type: entity_test
+          entity_field: field_test_multiple
+          delta_limit: 0
+          group_rows: true
+        field_test_multiple_1:
+          id: field_test_multiple_1
+          table: entity_test__field_test_multiple
+          field: field_test_multiple
+          plugin_id: field
+          entity_type: entity_test
+          entity_field: field_test_multiple
+          delta_limit: 1
+          group_rows: true
+        field_test_multiple_2:
+          id: field_test_multiple_2
+          table: entity_test__field_test_multiple
+          field: field_test_multiple
+          plugin_id: field
+          entity_type: entity_test
+          entity_field: field_test_multiple
+          delta_limit: 0
+          delta_offset: 1
+          group_rows: true
+        timezone:
+          id: timezone
+          table: users_field_data
+          field: timezone
+          plugin_id: field
+          relationship: user_id
+          alter: {}
+      relationships:
+        user_id:
+          table: entity_test
+          field: user_id
+          id: user_id
+          plugin_id: standard
+      sorts:
+        id:
+          id: id
+          table: entity_test
+          field: id
+          plugin_id: standard
+          order: asc
+      style:
+        type: html_list
+    display_plugin: default
+    display_title: Master
+    id: default
+    position: 0
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_complex_test.yml
similarity index 50%
copy from core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml
copy to core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_complex_test.yml
index 5a49a08..b0122a3 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_complex_test.yml
@@ -1,7 +1,7 @@
 langcode: und
 status: true
 dependencies: {  }
-id: test_field_field_revision_test
+id: test_field_field_revision_complex_test
 module: views
 description: ''
 tag: ''
@@ -30,20 +30,47 @@ display:
           plugin_id: field
           entity_type: entity_test_rev
           entity_field: revision_id
-        field_test:
-          id: field_test
-          table: entity_test__field_test
-          field: field_test
+        field_test_multiple:
+          id: field_test_multiple
+          table: entity_test_rev__field_test_multiple
+          field: field_test_multiple
           plugin_id: field
           entity_type: entity_test_rev
-          entity_field: field_test
-        name:
-          id: name
-          table: entity_test_rev_revision
-          field: name
+          entity_field: field_test_multiple
+          delta_limit: 0
+          group_rows: true
+        field_test_multiple_1:
+          id: field_test_multiple_1
+          table: entity_test_rev__field_test_multiple
+          field: field_test_multiple
+          plugin_id: field
+          entity_type: entity_test_rev
+          entity_field: field_test_multiple
+          delta_limit: 1
+          group_rows: true
+        field_test_multiple_2:
+          id: field_test_multiple_2
+          table: entity_test_rev__field_test_multiple
+          field: field_test_multiple
           plugin_id: field
           entity_type: entity_test_rev
-          entity_field: name
+          entity_field: field_test_multiple
+          delta_limit: 0
+          delta_offset: 1
+          group_rows: true
+        timezone:
+          id: timezone
+          table: users_field_data
+          field: timezone
+          plugin_id: field
+          relationship: user_id
+          alter: {}
+      relationships:
+        user_id:
+          table: entity_test_rev_revision
+          field: user_id
+          id: user_id
+          plugin_id: standard
       sorts:
         revision_id:
           id: revision_id
diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml
index 5a49a08..d85d4d1 100644
--- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml
+++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_revision_test.yml
@@ -32,7 +32,7 @@ display:
           entity_field: revision_id
         field_test:
           id: field_test
-          table: entity_test__field_test
+          table: entity_test_rev__field_test
           field: field_test
           plugin_id: field
           entity_type: entity_test_rev
diff --git a/core/modules/views/tests/src/Unit/Plugin/field/FieldTest.php b/core/modules/views/tests/src/Unit/Plugin/field/FieldTest.php
index 9ca73d4..54bd3a4 100644
--- a/core/modules/views/tests/src/Unit/Plugin/field/FieldTest.php
+++ b/core/modules/views/tests/src/Unit/Plugin/field/FieldTest.php
@@ -7,9 +7,11 @@
 
 namespace Drupal\Tests\views\Unit\Plugin\field;
 
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Tests\UnitTestCase;
 use Drupal\Tests\views\Unit\Plugin\HandlerTestTrait;
 use Drupal\views\Plugin\views\field\Field;
+use Drupal\views\ResultRow;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 
 /**
@@ -438,6 +440,7 @@ public function testQueryWithGroupByForBaseField() {
     ];
     $handler = new Field([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
     $handler->view = $this->executable;
+    $handler->view->field = [$handler];
 
     $this->setupLanguageRenderer($handler, $definition);
 
@@ -499,6 +502,7 @@ public function testQueryWithGroupByForConfigField() {
     ];
     $handler = new Field([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
     $handler->view = $this->executable;
+    $handler->view->field = [$handler];
 
     $this->setupLanguageRenderer($handler, $definition);
 
@@ -551,6 +555,85 @@ public function testQueryWithGroupByForConfigField() {
   }
 
   /**
+   * @covers ::prepareItemsByDelta
+   *
+   * @dataProvider providerTestPrepareItemsByDelta
+   */
+  public function testPrepareItemsByDelta(array $options, array $expected_values) {
+    $definition = [
+      'entity_type' => 'test_entity',
+      'field_name' => 'integer',
+    ];
+    $handler = new TestField([], 'field', $definition, $this->entityManager, $this->formatterPluginManager, $this->fieldTypePluginManager, $this->languageManager, $this->renderer);
+    $handler->view = $this->executable;
+    $handler->view->field = [$handler];
+
+    $this->setupLanguageRenderer($handler, $definition);
+
+    $field_storage = $this->getConfigFieldStorage();
+    $field_storage->expects($this->any())
+      ->method('getCardinality')
+      ->willReturn(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
+
+    $this->entityManager->expects($this->any())
+      ->method('getFieldStorageDefinitions')
+      ->with('test_entity')
+      ->willReturn([
+        'integer' => $field_storage,
+      ]);
+
+    $table_mapping = $this->getMock('Drupal\Core\Entity\Sql\TableMappingInterface');
+    $table_mapping
+      ->expects($this->any())
+      ->method('getFieldColumnName')
+      ->with($field_storage, 'value')
+      ->willReturn('integer_value');
+    $entity_storage = $this->getMock('Drupal\Core\Entity\Sql\SqlEntityStorageInterface');
+    $entity_storage->expects($this->any())
+      ->method('getTableMapping')
+      ->willReturn($table_mapping);
+    $this->entityManager->expects($this->any())
+      ->method('getStorage')
+      ->with('test_entity')
+      ->willReturn($entity_storage);
+
+    $options = [
+      'group_column' => 'value',
+      'group_columns' => [],
+      'table' => 'test_entity__integer',
+    ] + $options;
+    $handler->init($this->executable, $this->display, $options);
+
+    $this->executable->row_index = 0;
+    $this->executable->result = [0 => new ResultRow([])];
+
+    $items = [3, 1, 4, 1, 5, 9];
+    $this->assertEquals($expected_values, $handler->executePrepareItemsByDelta($items));
+  }
+
+  /**
+   * Provides test data for testPrepareItemsByDelta().
+   */
+  public function providerTestPrepareItemsByDelta() {
+    $data = [];
+
+    // Let's display all values.
+    $data[] = [[], [3, 1, 4, 1, 5, 9]];
+    // Test just reversed deltas.
+    $data[] = [['delta_reversed' => TRUE], [9, 5, 1, 4, 1, 3]];
+
+    // Test combinations of delta limit, offset and first_last.
+    $data[] = [['group_rows' => TRUE, 'delta_limit' => 3], [3, 1, 4]];
+    $data[] = [['group_rows' => TRUE, 'delta_limit' => 3, 'delta_offset' => 2], [4, 1, 5]];
+    $data[] = [['group_rows' => TRUE, 'delta_reversed' => TRUE, 'delta_limit' => 3, 'delta_offset' => 2], [1, 4, 1]];
+    $data[] = [['group_rows' => TRUE, 'delta_first_last' => TRUE], [3, 9]];
+    $data[] = [['group_rows' => TRUE, 'delta_limit' => 1, 'delta_first_last' => TRUE], [3]];
+    $data[] = [['group_rows' => TRUE, 'delta_offset' => 1, 'delta_first_last' => TRUE], [1, 9]];
+
+    return $data;
+  }
+
+  /**
    * Returns a mocked base field storage object.
    *
    * @return \Drupal\Core\Field\FieldStorageDefinitionInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -640,3 +723,11 @@ protected function setupLanguageRenderer(Field $handler, $definition) {
   }
 
 }
+
+class TestField extends Field {
+
+  public function executePrepareItemsByDelta(array $all_values) {
+    return $this->prepareItemsByDelta($all_values);
+  }
+
+}
