diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 8a5a4a7..c4c990f 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -610,18 +610,20 @@ protected function buildCacheId($id) {
    *
    * @param array $records
    *   Associative array of query results, keyed on the entity ID.
+   * @param bool $load_from_revision
+   *   Flag to indicate whether revisions should be loaded or not.
    *
    * @return array
    *   An array of entity objects implementing the EntityInterface.
    */
-  protected function mapFromStorageRecords(array $records) {
+  protected function mapFromStorageRecords(array $records, $load_from_revision = FALSE) {
     if (!$records) {
       return array();
     }
 
-    $entities = array();
+    $values = array();
     foreach ($records as $id => $record) {
-      $entities[$id] = array();
+      $values[$id] = array();
       // Skip the item delta and item value levels (if possible) but let the
       // field assign the value as suiting. This avoids unnecessary array
       // hierarchies and saves memory here.
@@ -630,26 +632,31 @@ protected function mapFromStorageRecords(array $records) {
         // that store several properties).
         if ($field_name = strstr($name, '__', TRUE)) {
           $property_name = substr($name, strpos($name, '__') + 2);
-          $entities[$id][$field_name][LanguageInterface::LANGCODE_DEFAULT][$property_name] = $value;
+          $values[$id][$field_name][LanguageInterface::LANGCODE_DEFAULT][$property_name] = $value;
         }
         else {
           // Handle columns named directly after the field (e.g if the field
           // type only stores one property).
-          $entities[$id][$name][LanguageInterface::LANGCODE_DEFAULT] = $value;
+          $values[$id][$name][LanguageInterface::LANGCODE_DEFAULT] = $value;
         }
       }
-      // If we have no multilingual values we can instantiate entity objects
-      // right now, otherwise we need to collect all the field values first.
-      if (!$this->dataTable) {
-        $bundle = $this->bundleKey ? $record->{$this->bundleKey} : FALSE;
-        // Turn the record into an entity class.
-        $entities[$id] = new $this->entityClass($entities[$id], $this->entityTypeId, $bundle);
-      }
     }
-    $this->attachPropertyData($entities);
+    $this->loadFromSharedTable($values);
 
     // Attach field values.
-    $this->loadFieldItems($entities);
+    $this->loadFromDedicatedTables($values, $load_from_revision);
+
+    $entities = array();
+    foreach ($values as $id => $entity_values) {
+      $bundle = $this->bundleKey ? $entity_values[$this->bundleKey][LanguageInterface::LANGCODE_DEFAULT] : FALSE;
+      // Turn the record into an entity class.
+      $translations = array();
+      if (isset($entity_values['_translations'])) {
+        $translations = array_keys($entity_values['_translations']);
+        unset($entity_values['_translations']);
+      }
+      $entities[$id] = new $this->entityClass($entity_values, $this->entityTypeId, $bundle, $translations);
+    }
 
     return $entities;
   }
@@ -657,10 +664,10 @@ protected function mapFromStorageRecords(array $records) {
   /**
    * Attaches property data in all languages for translatable properties.
    *
-   * @param array &$entities
+   * @param array &$values
    *   Associative array of entities, keyed on the entity ID.
    */
-  protected function attachPropertyData(array &$entities) {
+  protected function loadFromSharedTable(array &$values) {
     if ($this->dataTable) {
       // If a revision table is available, we need all the properties of the
       // latest revision. Otherwise we fall back to the data table.
@@ -668,7 +675,7 @@ protected function attachPropertyData(array &$entities) {
       $alias = $this->revisionDataTable ? 'revision' : 'data';
       $query = $this->database->select($table, $alias, array('fetch' => \PDO::FETCH_ASSOC))
         ->fields($alias)
-        ->condition($alias . '.' . $this->idKey, array_keys($entities), 'IN')
+        ->condition($alias . '.' . $this->idKey, array_keys($values), 'IN')
         ->orderBy($alias . '.' . $this->idKey);
 
       $table_mapping = $this->getTableMapping();
@@ -687,8 +694,8 @@ protected function attachPropertyData(array &$entities) {
 
         // Get the revision IDs.
         $revision_ids = array();
-        foreach ($entities as $values) {
-          $revision_ids[] = is_object($values) ? $values->getRevisionId() : $values[$this->revisionKey][LanguageInterface::LANGCODE_DEFAULT];
+        foreach ($values as $entity_values) {
+          $revision_ids[] = $entity_values[$this->revisionKey][LanguageInterface::LANGCODE_DEFAULT];
         }
         $query->condition('revision.' . $this->revisionKey, $revision_ids, 'IN');
       }
@@ -696,36 +703,30 @@ protected function attachPropertyData(array &$entities) {
         $fields = $table_mapping->getFieldNames($this->dataTable);
       }
 
-      $translations = array();
-      $data = $query->execute();
-      foreach ($data as $values) {
-        $id = $values[$this->idKey];
+      $result = $query->execute();
+      foreach ($result as $row) {
+        $id = $row[$this->idKey];
 
         // Field values in default language are stored with
         // LanguageInterface::LANGCODE_DEFAULT as key.
-        $langcode = empty($values['default_langcode']) ? $values[$this->langcodeKey] : LanguageInterface::LANGCODE_DEFAULT;
-        $translations[$id][$langcode] = TRUE;
+        $langcode = empty($row['default_langcode']) ? $row[$this->langcodeKey] : LanguageInterface::LANGCODE_DEFAULT;
 
+        // This is not nice.
+        $values[$id]['_translations'][$langcode] = TRUE;
 
         foreach ($fields as $field_name) {
           $columns = $table_mapping->getColumnNames($field_name);
           // Do not key single-column fields by property name.
           if (count($columns) == 1) {
-            $entities[$id][$field_name][$langcode] = $values[reset($columns)];
+            $values[$id][$field_name][$langcode] = $row[reset($columns)];
           }
           else {
             foreach ($columns as $property_name => $column_name) {
-              $entities[$id][$field_name][$langcode][$property_name] = $values[$column_name];
+              $values[$id][$field_name][$langcode][$property_name] = $row[$column_name];
             }
           }
         }
       }
-
-      foreach ($entities as $id => $values) {
-        $bundle = $this->bundleKey ? $values[$this->bundleKey][LanguageInterface::LANGCODE_DEFAULT] : FALSE;
-        // Turn the record into an entity class.
-        $entities[$id] = new $this->entityClass($values, $this->entityTypeId, $bundle, array_keys($translations[$id]));
-      }
     }
   }
 
@@ -739,7 +740,7 @@ public function loadRevision($revision_id) {
 
     if (!empty($records)) {
       // Convert the raw records to entity objects.
-      $entities = $this->mapFromStorageRecords($records);
+      $entities = $this->mapFromStorageRecords($records, TRUE);
       $this->postLoad($entities);
       $entity = reset($entities);
       if ($entity) {
@@ -1219,31 +1220,26 @@ protected function getQueryServiceName() {
    * Loads all fields for each entity object in a group of a single entity type.
    * The loaded field values are added directly to the entity objects.
    *
-   * @param \Drupal\Core\Entity\ContentEntityInterface[] $entities
+   * @param \Drupal\Core\Entity\ContentEntityInterface[] $values
    *   An array of entities keyed by entity ID.
+   * @param bool $load_from_revision
+   *   Flag to indicate whether revisions should be loaded or not.
    */
-  protected function loadFieldItems(array $entities) {
-    if (empty($entities)) {
+  protected function loadFromDedicatedTables(array &$values, $load_from_revision) {
+    if (empty($values)) {
       return;
     }
 
-    $age = static::FIELD_LOAD_CURRENT;
-    foreach ($entities as $entity) {
-      if (!$entity->isDefaultRevision()) {
-        $age = static::FIELD_LOAD_REVISION;
-        break;
-      }
-    }
-    $load_current = $age == static::FIELD_LOAD_CURRENT;
-
     // Collect entities ids, bundles and languages.
     $bundles = array();
     $ids = array();
     $default_langcodes = array();
-    foreach ($entities as $key => $entity) {
-      $bundles[$entity->bundle()] = TRUE;
-      $ids[] = $load_current ? $key : $entity->getRevisionId();
-      $default_langcodes[$key] = $entity->getUntranslated()->language()->getId();
+    foreach ($values as $key => $entity_values) {
+      $bundles[$this->bundleKey ? $entity_values[$this->bundleKey][LanguageInterface::LANGCODE_DEFAULT] : $this->entityTypeId] = TRUE;
+      $ids[] = !$load_from_revision ? $key : $entity_values[$this->revisionKey][LanguageInterface::LANGCODE_DEFAULT];
+      if ($this->langcodeKey && isset($entity_values[$this->langcodeKey][LanguageInterface::LANGCODE_DEFAULT])) {
+        $default_langcodes[$key] = $entity_values[$this->langcodeKey][LanguageInterface::LANGCODE_DEFAULT];
+      }
     }
 
     // Collect impacted fields.
@@ -1263,31 +1259,37 @@ protected function loadFieldItems(array $entities) {
     // Load field data.
     $langcodes = array_keys($this->languageManager->getLanguages(LanguageInterface::STATE_ALL));
     foreach ($storage_definitions as $field_name => $storage_definition) {
-      $table = $load_current ? $table_mapping->getDedicatedDataTableName($storage_definition) : $table_mapping->getDedicatedRevisionTableName($storage_definition);
+      $table = !$load_from_revision ? $table_mapping->getDedicatedDataTableName($storage_definition) : $table_mapping->getDedicatedRevisionTableName($storage_definition);
 
       // Ensure that only values having valid languages are retrieved. Since we
       // are loading values for multiple entities, we cannot limit the query to
       // the available translations.
       $results = $this->database->select($table, 't')
         ->fields('t')
-        ->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN')
+        ->condition(!$load_from_revision ? 'entity_id' : 'revision_id', $ids, 'IN')
         ->condition('deleted', 0)
         ->condition('langcode', $langcodes, 'IN')
         ->orderBy('delta')
         ->execute();
 
-      $delta_count = array();
       foreach ($results as $row) {
-        $bundle = $entities[$row->entity_id]->bundle();
+        $bundle = $row->bundle;
+
+        // Field values in default language are stored with
+        // LanguageInterface::LANGCODE_DEFAULT as key.
+        $langcode = LanguageInterface::LANGCODE_DEFAULT;
+        if ($this->langcodeKey && isset($default_langcodes[$row->entity_id]) && $row->langcode != $default_langcodes[$row->entity_id]) {
+          $langcode = $row->langcode;
+        }
+
+        if (!isset($values[$row->entity_id][$field_name][$langcode])) {
+          $values[$row->entity_id][$field_name][$langcode] = array();
+        }
 
         // Ensure that records for non-translatable fields having invalid
         // languages are skipped.
-        if ($row->langcode == $default_langcodes[$row->entity_id] || $definitions[$bundle][$field_name]->isTranslatable()) {
-          if (!isset($delta_count[$row->entity_id][$row->langcode])) {
-            $delta_count[$row->entity_id][$row->langcode] = 0;
-          }
-
-          if ($storage_definition->getCardinality() == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $storage_definition->getCardinality()) {
+        if ($row->langcode == LanguageInterface::LANGCODE_DEFAULT || $definitions[$bundle][$field_name]->isTranslatable()) {
+          if ($storage_definition->getCardinality() == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || count($values[$row->entity_id][$field_name][$langcode]) < $storage_definition->getCardinality()) {
             $item = array();
             // For each column declared by the field, populate the item from the
             // prefixed database column.
@@ -1298,8 +1300,7 @@ protected function loadFieldItems(array $entities) {
             }
 
             // Add the item to the field values for the entity.
-            $entities[$row->entity_id]->getTranslation($row->langcode)->{$field_name}->appendItem($item);
-            $delta_count[$row->entity_id][$row->langcode]++;
+            $values[$row->entity_id][$field_name][$langcode][] = $item;
           }
         }
       }
diff --git a/core/modules/field/src/Tests/BulkDeleteTest.php b/core/modules/field/src/Tests/BulkDeleteTest.php
index be306e5..fdffb7e 100644
--- a/core/modules/field/src/Tests/BulkDeleteTest.php
+++ b/core/modules/field/src/Tests/BulkDeleteTest.php
@@ -141,6 +141,11 @@ protected function setUp() {
     }
     $this->entities = entity_load_multiple($this->entity_type);
     foreach ($this->entities as $entity) {
+      // This test relies on the entities having stale field definitions
+      // so that the deleted field can be accessed on them. Access the field
+      // now, so that they are always loaded.
+      $entity->bf_1->value;
+
       // Also keep track of the entities per bundle.
       $this->entities_by_bundles[$entity->bundle()][$entity->id()] = $entity;
     }
