diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 8d37a63..297a292 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -584,7 +584,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/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/Plugin/views/field/Field.php b/core/modules/views/src/Plugin/views/field/Field.php
index 73e03a4..9fb7d74 100644
--- a/core/modules/views/src/Plugin/views/field/Field.php
+++ b/core/modules/views/src/Plugin/views/field/Field.php
@@ -30,7 +30,7 @@
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
- * A field that displays fieldapi fields.
+ * A field that displays entity field data.
  *
  * @ingroup views_field_handlers
  *
@@ -114,6 +114,35 @@ class Field extends FieldPluginBase implements CacheablePluginInterface, MultiIt
   protected $fieldTypePluginManager;
 
   /**
+   * Static cache for ::getRenderableFieldNames().
+   *
+   * @var string[]
+   */
+  protected $renderableFieldNames;
+
+  /**
+   * Static cache for ::getRenderField().
+   *
+   * @var \Drupal\views\Plugin\views\field\Field
+   */
+  protected $renderField;
+
+
+  /**
+   * A list of indexes of rows whose fields have already been rendered.
+   *
+   * @var int[]
+   */
+  protected $processedRows = [];
+
+  /**
+   * Stores the output of all rendered fields.
+   *
+   * @var array
+   */
+  protected $fieldOutput = [];
+
+  /**
    * Constructs a \Drupal\field\Plugin\views\field\Field object.
    *
    * @param array $configuration
@@ -211,13 +240,13 @@ public function getEntityTypeId() {
   protected function getEntityManager() {
     return $this->entityManager;
   }
-
   /**
    * {@inheritdoc}
    */
   protected function getLanguageManager() {
     return $this->languageManager;
   }
+
   /**
    * {@inheritdoc}
    */
@@ -698,6 +727,225 @@ public function renderItems($items) {
       return $this->renderer->render($build);
     }
   }
+  /**
+   * {@inheritdoc}
+   */
+  public function preRender(&$values) {
+    parent::preRender($values);
+
+    $this->renderEntityFields($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 renderEntityFields(array $values) {
+    $render_field = $this->getRenderField();
+    $entities = [];
+    $translations = [];
+    $bundle_field_names = [];
+
+    foreach ($values as $row) {
+      // Skip this row if has already been processed.
+      if (!empty($render_field->processedRows[$row->index])) {
+        continue;
+      }
+      $render_field->processedRows[$row->index] = TRUE;
+
+      // Collect a list of entity types to process from the view relationships.
+      // We store a field name for each relationship toi make it easier
+      // retrieving the related entity from the row.
+      if (!isset($entity_type_ids)) {
+        $row_entities = array_intersect_key([$render_field->field => $row->_entity] + $row->_relationship_entities, $this->view->field);
+        $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 = $this->view->field[$rel_field_name]->getEntity($row);
+        $entity_type_id = $entity->getEntityTypeId();
+        $bundle = $entity->bundle();
+        $key = $row->index . ':' . $entity->id();
+
+        // 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();
+        $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;
+            }
+            // @todo Initialize field item attributes. This is required to call
+            //   prepare view as the RDF module assumes the "_attributes"
+            //   property to exist. Remove this in
+            //   https://www.drupal.org/node/2450477.
+            foreach ($entity->get($field_name) as $item) {
+              $item->_attributes = [];
+            }
+          }
+        }
+
+        // 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($render_field->fieldOutput[$entity_type_id])) {
+          $render_field->fieldOutput[$entity_type_id] = [];
+        }
+        foreach ($entity_type_entities as $bundle => $bundle_entities) {
+          $render_field->fieldOutput[$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) {
+        // We use self here, so theoretically you could inherit this class for a
+        // particular field.
+        if ($field instanceof static) {
+          $entity_type_id = $field->getFieldDefinition()->getTargetEntityTypeId();
+          $this->renderableFieldNames[$entity_type_id][$view_field_name] = $field->definition['field_name'];
+          if (!isset($this->renderField) && $field->options['relationship'] == 'none') {
+            $this->renderField = $field;
+          }
+        }
+      }
+      // Fall back to the current field if could not find any better one.
+      if (!isset($this->renderField)) {
+        $this->renderField = $this;
+      }
+    }
+    return $this->renderableFieldNames;
+  }
+
+  /**
+   * Returns the field plugin which takes over the rendering of all of them.
+   *
+   * @return \Drupal\views\Plugin\views\field\Field
+   *   The render field.
+   */
+  public function getRenderField() {
+    if (!isset($this->renderField)) {
+      $this->getRenderableFieldNames();
+    }
+    return $this->renderField;
+  }
+
+  /**
+   * 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 on 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;
+  }
+
+  /**
+   * Returns the rendered field output.
+   *
+   * @return array
+   */
+  public function getFieldOutput() {
+    return $this->getRenderField()->fieldOutput;
+  }
 
   /**
    * Gets an array of items for the field.
@@ -709,41 +957,43 @@ 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();
+    $entity = $this->getEntity($values);
+    $output = $this->getFieldOutput();
+    $entity_type_id = $entity->getEntityTypeId();
+    $key = $values->index . ':' . $entity->id();
+    $field_name = $this->definition['field_name'];
+
+    // Make sure entity fields are actually rendered for the current row.
+    if (!isset($output[$entity_type_id][$key])) {
+      $this->renderEntityFields([$values]);
+      $output = $this->getFieldOutput();
     }
 
-    $display = array(
-      'type' => $this->options['type'],
-      'settings' => $this->options['settings'],
-      'label' => 'hidden',
-    );
-    $render_array = $entity->get($this->definition['field_name'])->view($display);
+    if (!$entity || !isset($output[$entity_type_id][$key][$field_name])) {
+      return [];
+    }
 
-    $items = array();
+    $build = $output[$entity_type_id][$key][$field_name];
     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;
@@ -759,15 +1009,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);
+  protected 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
@@ -901,29 +1151,22 @@ protected function addSelfTokens(&$tokens, $item) {
    * @param \Drupal\views\ResultRow $row
    *   The result row the field value being processed belongs to.
    *
-   * @return string
-   *   The field language code.
+   * @return \Drupal\Core\Entity\FieldableEntityInterface
+   *   The entity translation object for the passed row.
    */
-  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;
-    }
+  protected function getEntityTranslation(EntityInterface $entity, ResultRow $row) {
+    // 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.
+    return $this->entityManager->getTranslationFromContext($entity, $langcode);
   }
 
   /**
