From 477c06c413fbb180165ffa5cdddb4b1d196cd56f Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Sun, 26 May 2013 13:18:10 -0700
Subject: [PATCH] =?UTF-8?q?Issue=20#1498674=20by=20plach,=20das-peter,=20S?=
 =?UTF-8?q?chnitzel,=20dawehner,=20YesCT,=20attiks,=20Berdir,=20G=C3=A1bor?=
 =?UTF-8?q?=20Hojtsy,=20Soul88,=20Carsten=20M=C3=BCller:=20Refactor=20node?=
 =?UTF-8?q?=20properties=20to=20multilingual.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 core/includes/database.inc                    |  20 +-
 core/includes/form.inc                        |  22 +-
 core/includes/menu.inc                        |   5 +-
 core/includes/schema.inc                      |  42 +-
 .../Core/Database/Driver/pgsql/Select.php     |   8 +-
 core/lib/Drupal/Core/Database/Schema.php      |   6 +-
 .../Core/Entity/DatabaseStorageController.php |   2 +-
 .../Entity/DatabaseStorageControllerNG.php    | 199 ++++--
 core/lib/Drupal/Core/Entity/EntityNG.php      |   3 +-
 .../lib/Drupal/action/Tests/BulkFormTest.php  |   9 +-
 .../config/views.view.test_bulk_form.yml      |   6 +-
 .../aggregator/Tests/AggregatorTestBase.php   |   2 +-
 .../CustomBlockStorageController.php          |  12 +-
 core/modules/book/book.module                 |  30 +-
 core/modules/book/book.services.yml           |   2 +-
 .../book/lib/Drupal/book/BookManager.php      |  35 +-
 .../book/Plugin/Block/BookNavigationBlock.php |   6 +-
 core/modules/comment/comment.admin.inc        |  13 +-
 core/modules/comment/comment.install          |   4 +-
 core/modules/comment/comment.module           |   5 +-
 core/modules/comment/comment.views.inc        |   4 +-
 .../comment/CommentStorageController.php      |   2 +-
 .../selection/CommentSelection.php            |   2 +-
 .../comment/Plugin/views/wizard/Comment.php   |   2 +-
 .../Tests/Views/DefaultViewRecentComments.php |   8 +
 .../comment/Tests/Views/FilterUserUIDTest.php |   4 +-
 .../Drupal/comment/Tests/Views/WizardTest.php |   2 +-
 .../views.view.test_comment_user_uid.yml      |   2 +-
 .../views.view.test_entity_reference.yml      |   6 +-
 .../Drupal/field/Tests/Views/ApiDataTest.php  |   8 +-
 core/modules/file/file.views.inc              |  18 +-
 core/modules/forum/forum.module               |  26 +-
 .../views/field/HistoryUserTimestamp.php      |   4 +-
 .../views/filter/HistoryUserTimestamp.php     |   2 +-
 .../Drupal/locale/Tests/LocaleContentTest.php |   4 +
 .../node/config/views.view.frontpage.yml      |   8 +-
 .../lib/Drupal/node/NodeFormController.php    |   2 +-
 .../lib/Drupal/node/NodeStorageController.php |  56 +-
 .../Drupal/node/Plugin/Core/Entity/Node.php   |   3 +-
 .../Plugin/views/argument/UidRevision.php     |   2 +-
 .../Drupal/node/Plugin/views/argument/Vid.php |   6 +-
 .../Drupal/node/Plugin/views/field/Link.php   |   7 +-
 .../node/Plugin/views/field/RevisionLink.php  |   6 +-
 .../Plugin/views/field/RevisionLinkDelete.php |   2 +-
 .../Plugin/views/field/RevisionLinkRevert.php |   2 +-
 .../node/Plugin/views/filter/UidRevision.php  |   2 +-
 .../Drupal/node/Plugin/views/wizard/Node.php  |   8 +-
 .../node/Plugin/views/wizard/NodeRevision.php |  10 +-
 .../Tests/Condition/NodeConditionTest.php     |   3 +-
 .../node/Tests/NodeAccessBaseTableTest.php    |   2 +-
 .../lib/Drupal/node/Tests/NodeAdminTest.php   |   4 +-
 .../node/Tests/NodeBlockFunctionalTest.php    |   4 +-
 .../Tests/NodeFieldMultilingualTestCase.php   |   1 +
 .../Tests/NodeRevisionPermissionsTest.php     |   4 +-
 .../node/Tests/NodeRevisionsAllTestCase.php   |   6 +-
 .../Drupal/node/Tests/NodeRevisionsTest.php   |   6 +-
 .../Drupal/node/Tests/Views/FieldTypeTest.php |   4 +-
 .../Tests/Views/FilterUidRevisionTest.php     |   2 +-
 .../Tests/Views/RevisionRelationships.php     |  16 +-
 core/modules/node/node.admin.inc              |  34 +-
 core/modules/node/node.install                | 607 +++++++++++++++---
 core/modules/node/node.module                 |  43 +-
 core/modules/node/node.pages.inc              |   6 +-
 core/modules/node/node.views.inc              |  82 +--
 .../test_views/views.view.test_field_type.yml |   2 +-
 ...ews.view.test_filter_node_uid_revision.yml |   2 +-
 .../views.view.test_node_revision_nid.yml     |  10 +-
 .../views.view.test_node_revision_vid.yml     |  10 +-
 .../test_views/views.view.test_node_view.yml  |   6 +-
 .../views.view.test_status_extra.yml          |   6 +-
 core/modules/search/search.api.php            |  11 +-
 core/modules/search/search.module             |   5 +-
 .../Tests/DrupalUnitTestBaseTest.php          |   2 +-
 .../lib/Drupal/simpletest/WebTestBase.php     |   5 -
 core/modules/statistics/statistics.module     |   5 +-
 ...views.view.test_statistics_integration.yml |   6 +-
 .../Tests/Entity/EntityBCDecoratorTest.php    |   2 +-
 .../Tests/Entity/EntityCrudHookTest.php       |   2 +-
 .../system/Tests/Entity/EntityFieldTest.php   |   2 +-
 core/modules/system/system.api.php            |   4 +-
 .../Plugin/views/field/TaxonomyIndexTid.php   |   4 +-
 .../Tests/Views/TrackerUserUidTest.php        |   2 +-
 .../views.view.test_tracker_user_uid.yml      |   2 +-
 core/modules/tracker/tracker.module           |  16 +-
 core/modules/tracker/tracker.pages.inc        |   6 +-
 core/modules/translation/translation.module   |  12 +-
 ...t_plugin_argument_default_current_user.yml |   2 +-
 .../views.view.test_user_relationship.yml     |   2 +-
 core/modules/user/user.api.php                |   6 +-
 core/modules/user/user.views.inc              |   4 +-
 .../views/config/views.view.archive.yml       |   8 +-
 .../views/config/views.view.backlinks.yml     |   4 +-
 .../config/views.view.comments_recent.yml     |   8 +-
 .../views/config/views.view.glossary.yml      |  10 +-
 .../views/config/views.view.taxonomy_term.yml |   6 +-
 .../views/config/views.view.tracker.yml       |  10 +-
 .../Tests/Handler/ArgumentStringTest.php      |   6 +-
 .../Drupal/views/Tests/QueryGroupByTest.php   |   4 +-
 .../Drupal/views/Tests/ViewExecutableTest.php |   2 +-
 .../lib/Drupal/views/Tests/ViewsDataTest.php  |   2 +-
 .../views/Tests/Wizard/ItemsPerPageTest.php   |   2 +-
 .../Drupal/views/Tests/Wizard/SortingTest.php |   4 +-
 .../views.view.test_aggregate_count.yml       |   2 +-
 ...iew.test_argument_default_current_user.yml |   4 +-
 ...views.view.test_argument_default_fixed.yml |   2 +-
 .../test_views/views.view.test_destroy.yml    |  12 +-
 .../test_views/views.view.test_display.yml    |   6 +-
 .../test_views/views.view.test_dropbutton.yml |   6 +-
 .../views.view.test_entity_type_filter.yml    |   4 +-
 .../views.view.test_exposed_admin_ui.yml      |   4 +-
 .../views.view.test_feed_display.yml          |   6 +-
 .../views.view.test_field_get_entity.yml      |   2 +-
 .../test_views/views.view.test_field_type.yml |   2 +-
 .../views.view.test_filter_date_between.yml   |   2 +-
 .../views.view.test_filter_group_override.yml |   4 +-
 .../views.view.test_filter_groups.yml         |   8 +-
 .../views.view.test_filter_in_operator_ui.yml |   2 +-
 .../test_views/views.view.test_glossary.yml   |   4 +-
 .../views.view.test_group_by_count.yml        |   2 +-
 .../views.view.test_group_by_in_filters.yml   |   2 +-
 .../views.view.test_handler_relationships.yml |   2 +-
 .../test_views/views.view.test_history.yml    |   8 +-
 .../views.view.test_redirect_view.yml         |   6 +-
 .../views.view.test_reset_button.yml          |   2 +-
 ...st_view_pager_full_zero_items_per_page.yml |   2 +-
 .../Drupal/views_ui/Tests/SettingsTest.php    |   2 +-
 126 files changed, 1165 insertions(+), 596 deletions(-)

diff --git a/core/includes/database.inc b/core/includes/database.inc
index 15ffcc3d5633..75f6a96e7612 100644
--- a/core/includes/database.inc
+++ b/core/includes/database.inc
@@ -34,20 +34,20 @@
  * results that need to be presented on multiple pages, and the Tablesort
  * Extender for generating appropriate queries for sortable tables.
  *
- * For example, one might wish to return a list of the most recent 10 nodes
+ * For example, one might wish to return a list of the most recent 10 rows
  * authored by a given user. Instead of directly issuing the SQL query
  * @code
- * SELECT n.nid, n.title, n.created FROM node n WHERE n.uid = $uid LIMIT 0, 10;
+ * SELECT e.id, e.title, e.created FROM example e WHERE e.uid = $uid LIMIT 0, 10;
  * @endcode
  * one would instead call the Drupal functions:
  * @code
- * $result = db_query_range('SELECT n.nid, n.title, n.created
- *   FROM {node} n WHERE n.uid = :uid', 0, 10, array(':uid' => $uid));
+ * $result = db_query_range('SELECT e.id, e.title, e.created
+ *   FROM {example} e WHERE e.uid = :uid', 0, 10, array(':uid' => $uid));
  * foreach ($result as $record) {
  *   // Perform operations on $record->title, etc. here.
  * }
  * @endcode
- * Curly braces are used around "node" to provide table prefixing via
+ * Curly braces are used around "example" to provide table prefixing via
  * DatabaseConnection::prefixTables(). The explicit use of a user ID is pulled
  * out into an argument passed to db_query() so that SQL injection attacks
  * from user input can be caught and nullified. The LIMIT syntax varies between
@@ -69,7 +69,7 @@
  *
  * Named placeholders begin with a colon followed by a unique string. Example:
  * @code
- * SELECT nid, title FROM {node} WHERE uid=:uid;
+ * SELECT id, title FROM {example} WHERE uid=:uid;
  * @endcode
  *
  * ":uid" is a placeholder that will be replaced with a literal value when
@@ -81,7 +81,7 @@
  *
  * Unnamed placeholders are simply a question mark. Example:
  * @code
- * SELECT nid, title FROM {node} WHERE uid=?;
+ * SELECT id, title FROM {example} WHERE uid=?;
  * @endcode
  *
  * In this case, the array of arguments must be an indexed array of values to
@@ -91,11 +91,11 @@
  * running a LIKE query the SQL wildcard character, %, should be part of the
  * value, not the query itself. Thus, the following is incorrect:
  * @code
- * SELECT nid, title FROM {node} WHERE title LIKE :title%;
+ * SELECT id, title FROM {example} WHERE title LIKE :title%;
  * @endcode
  * It should instead read:
  * @code
- * SELECT nid, title FROM {node} WHERE title LIKE :title;
+ * SELECT id, title FROM {example} WHERE title LIKE :title;
  * @endcode
  * and the value for :title should include a % as appropriate. Again, note the
  * lack of quotation marks around :title. Because the value is not inserted
@@ -109,7 +109,7 @@
  * object-oriented API for defining a query structurally. For example, rather
  * than:
  * @code
- * INSERT INTO node (nid, title, body) VALUES (1, 'my title', 'my body');
+ * INSERT INTO {example} (id, uid, path, name) VALUES (1, 2, 'home', 'Home path');
  * @endcode
  * one would instead write:
  * @code
diff --git a/core/includes/form.inc b/core/includes/form.inc
index f3d1d8673d6c..c8796723f9f8 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -4921,26 +4921,26 @@ function _form_set_attributes(&$element, $class = array()) {
  *   $context['message'] = check_plain($node->label());
  * }
  *
- * // More advanced example: multi-step operation - load all nodes, five by five
+ * // A more advanced example is a multi-step operation that loads all rows,
+ * // five by five.
  * function my_function_2(&$context) {
  *   if (empty($context['sandbox'])) {
  *     $context['sandbox']['progress'] = 0;
- *     $context['sandbox']['current_node'] = 0;
- *     $context['sandbox']['max'] = db_query('SELECT COUNT(DISTINCT nid) FROM {node}')->fetchField();
+ *     $context['sandbox']['current_id'] = 0;
+ *     $context['sandbox']['max'] = db_query('SELECT COUNT(DISTINCT id) FROM {example}')->fetchField();
  *   }
  *   $limit = 5;
- *   $result = db_select('node')
- *     ->fields('node', array('nid'))
- *     ->condition('nid', $context['sandbox']['current_node'], '>')
- *     ->orderBy('nid')
+ *   $result = db_select('example')
+ *     ->fields('example', array('id'))
+ *     ->condition('id', $context['sandbox']['current_id'], '>')
+ *     ->orderBy('id')
  *     ->range(0, $limit)
  *     ->execute();
  *   foreach ($result as $row) {
- *     $node = node_load($row->nid, TRUE);
- *     $context['results'][] = $node->nid . ' : ' . check_plain($node->label());
+ *     $context['results'][] = $row->id . ' : ' . check_plain($row->title);
  *     $context['sandbox']['progress']++;
- *     $context['sandbox']['current_node'] = $node->nid;
- *     $context['message'] = check_plain($node->label());
+ *     $context['sandbox']['current_id'] = $row->id;
+ *     $context['message'] = check_plain($row->title);
  *   }
  *   if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
  *     $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index b928a26cd5d7..5adcb1f705f3 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -1468,9 +1468,12 @@ function menu_tree_collect_node_links(&$tree, &$node_links) {
 function menu_tree_check_access(&$tree, $node_links = array()) {
   if ($node_links) {
     $nids = array_keys($node_links);
-    $select = db_select('node', 'n');
+    $select = db_select('node_field_data', 'n');
     $select->addField('n', 'nid');
+    // @todo This should be actually filtering on the desired node status field
+    //   language and just fall back to the default language.
     $select->condition('n.status', 1);
+
     $select->condition('n.nid', $nids, 'IN');
     $select->addTag('node_access');
     $nids = $select->execute()->fetchCol();
diff --git a/core/includes/schema.inc b/core/includes/schema.inc
index 6e5cda6d98f0..7b7aec90b6c0 100644
--- a/core/includes/schema.inc
+++ b/core/includes/schema.inc
@@ -433,20 +433,8 @@ function drupal_write_record($table, &$record, $primary_keys = array()) {
 
     // Type cast to proper datatype, except when the value is NULL and the
     // column allows this.
-    //
-    // MySQL PDO silently casts e.g. FALSE and '' to 0 when inserting the value
-    // into an integer column, but PostgreSQL PDO does not. Also type cast NULL
-    // when the column does not allow this.
     if (isset($object->$field) || !empty($info['not null'])) {
-      if ($info['type'] == 'int' || $info['type'] == 'serial') {
-        $fields[$field] = (int) $fields[$field];
-      }
-      elseif ($info['type'] == 'float') {
-        $fields[$field] = (float) $fields[$field];
-      }
-      else {
-        $fields[$field] = (string) $fields[$field];
-      }
+      $fields[$field] = drupal_schema_get_field_value($info, $fields[$field]);
     }
   }
 
@@ -521,6 +509,34 @@ function drupal_write_record($table, &$record, $primary_keys = array()) {
   return $return;
 }
 
+/**
+ * Typecasts values to proper datatypes.
+ *
+ * MySQL PDO silently casts, e.g. FALSE and '' to 0, when inserting the value
+ * into an integer column, but PostgreSQL PDO does not. Look up the schema
+ * information and use that to correctly typecast the value.
+ *
+ * @param array $info
+ *   An array describing the schema field info.
+ * @param mixed $value
+ *   The value to be converted.
+ *
+ * @return mixed
+ *   The converted value.
+ */
+function drupal_schema_get_field_value(array $info, $value) {
+  if ($info['type'] == 'int' || $info['type'] == 'serial') {
+    $value = (int) $value;
+  }
+  elseif ($info['type'] == 'float') {
+    $value = (float) $value;
+  }
+  else {
+    $value = (string) $value;
+  }
+  return $value;
+}
+
 /**
  * @} End of "addtogroup schemaapi".
  */
diff --git a/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
index c2a5a05eb76a..bf9f23a8a275 100644
--- a/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
+++ b/core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
@@ -32,16 +32,16 @@ public function orderRandom() {
    * yet selected.
    *
    * @code
-   *   $query = db_select('node', 'n');
-   *   $query->join('node_revision', 'nr', 'n.vid = nr.vid');
+   *   $query = db_select('example', 'e');
+   *   $query->join('example_revision', 'er', 'e.vid = er.vid');
    *   $query
    *     ->distinct()
-   *     ->fields('n')
+   *     ->fields('e')
    *     ->orderBy('timestamp');
    * @endcode
    *
    * In this query, it is not possible (without relying on the schema) to know
-   * whether timestamp belongs to node_revisions and needs to be added or
+   * whether timestamp belongs to example_revision and needs to be added or
    * belongs to node and is already selected. Queries like this will need to be
    * corrected in the original query by adding an explicit call to
    * SelectQuery::addField() or SelectQuery::fields().
diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php
index 7618a7c5b333..7b884f7719a7 100644
--- a/core/lib/Drupal/Core/Database/Schema.php
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -32,7 +32,7 @@
  * The following keys are defined:
  *   - 'description': A string in non-markup plain text describing this table
  *     and its purpose. References to other tables should be enclosed in
- *     curly-brackets. For example, the node_revisions table
+ *     curly-brackets. For example, the node_field_revision table
  *     description field might contain "Stores per-revision title and
  *     body data for each {node}."
  *   - 'fields': An associative array ('fieldname' => specification)
@@ -42,7 +42,7 @@
  *       and its purpose. References to other tables should be enclosed in
  *       curly-brackets. For example, the node table vid field
  *       description might contain "Always holds the largest (most
- *       recent) {node_revision}.vid value for this nid."
+ *       recent) {node_field_revision}.vid value for this nid."
  *     - 'type': The generic datatype: 'char', 'varchar', 'text', 'blob', 'int',
  *       'float', 'numeric', or 'serial'. Most types just map to the according
  *       database engine specific datatypes. Use 'serial' for auto incrementing
@@ -150,7 +150,7 @@
  *   ),
  *   'foreign keys' => array(
  *     'node_revision' => array(
- *       'table' => 'node_revision',
+ *       'table' => 'node_field_revision',
  *       'columns' => array('vid' => 'vid'),
  *      ),
  *     'node_author' => array(
diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
index 2c67c5aae5b5..c094bff0535e 100644
--- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
+++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php
@@ -289,7 +289,7 @@ public function loadRevision($revision_id) {
     // which attaches fields (if supported by the entity type) and calls the
     // entity type specific load callback, for example hook_node_load().
     if (!empty($queried_entities)) {
-      $this->attachLoad($queried_entities, TRUE);
+      $this->attachLoad($queried_entities, $revision_id);
     }
     return reset($queried_entities);
   }
diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
index 76ec89a356db..a5951477a62f 100644
--- a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
+++ b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
@@ -14,6 +14,7 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\DatabaseStorageController;
 use Drupal\Core\Entity\EntityStorageException;
+use Drupal\Core\TypedData\ComplexDataInterface;
 use Drupal\Component\Uuid\Uuid;
 use Drupal\Core\Database\Connection;
 
@@ -153,6 +154,55 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value
     parent::buildPropertyQuery($entity_query, $values);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function buildQuery($ids, $revision_id = FALSE) {
+    $query = $this->database->select($this->entityInfo['base_table'], 'base');
+    $is_revision_query = $this->revisionKey && ($revision_id || !$this->dataTable);
+
+    $query->addTag($this->entityType . '_load_multiple');
+
+    if ($revision_id) {
+      $query->join($this->revisionTable, 'revision', "revision.{$this->idKey} = base.{$this->idKey} AND revision.{$this->revisionKey} = :revisionId", array(':revisionId' => $revision_id));
+    }
+    elseif ($is_revision_query) {
+      $query->join($this->revisionTable, 'revision', "revision.{$this->revisionKey} = base.{$this->revisionKey}");
+    }
+
+    // Add fields from the {entity} table.
+    $entity_fields = drupal_schema_fields_sql($this->entityInfo['base_table']);
+
+    if ($is_revision_query) {
+      // Add all fields from the {entity_revision} table.
+      $entity_revision_fields = drupal_map_assoc(drupal_schema_fields_sql($this->entityInfo['revision_table']));
+      // The ID field is provided by entity, so remove it.
+      unset($entity_revision_fields[$this->idKey]);
+
+      // Remove all fields from the base table that are also fields by the same
+      // name in the revision table.
+      $entity_field_keys = array_flip($entity_fields);
+      foreach ($entity_revision_fields as $key => $name) {
+        if (isset($entity_field_keys[$name])) {
+          unset($entity_fields[$entity_field_keys[$name]]);
+        }
+      }
+      $query->fields('revision', $entity_revision_fields);
+
+      // Compare revision ID of the base and revision table, if equal then this
+      // is the default revision.
+      $query->addExpression('base.' . $this->revisionKey . ' = revision.' . $this->revisionKey, 'isDefaultRevision');
+    }
+
+    $query->fields('base', $entity_fields);
+
+    if ($ids) {
+      $query->condition("base.{$this->idKey}", $ids, 'IN');
+    }
+
+    return $query;
+  }
+
   /**
    * Overrides DatabaseStorageController::attachLoad().
    *
@@ -199,16 +249,20 @@ protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
   protected function mapFromStorageRecords(array $records, $load_revision = FALSE) {
     $entities = array();
     foreach ($records as $id => $record) {
-      $values = array();
+      $entities[$id] = array();
       foreach ($record as $name => $value) {
         // Skip the item delta and item value levels but let the field assign
         // the value as suiting. This avoids unnecessary array hierarchies and
         // saves memory here.
-        $values[$name][Language::LANGCODE_DEFAULT] = $value;
+        $entities[$id][$name][Language::LANGCODE_DEFAULT] = $value;
+      }
+      // If we have no multilingual values we can instantiate entity objecs
+      // 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->entityType, $bundle);
       }
-      $bundle = $this->bundleKey ? $record->{$this->bundleKey} : FALSE;
-      // Turn the record into an entity class.
-      $entities[$id] = new $this->entityClass($values, $this->entityType, $bundle);
     }
     $this->attachPropertyData($entities, $load_revision);
     return $entities;
@@ -219,50 +273,65 @@ protected function mapFromStorageRecords(array $records, $load_revision = FALSE)
    *
    * @param array &$entities
    *   Associative array of entities, keyed on the entity ID.
-   * @param boolean $load_revision
-   *   (optional) TRUE if the revision should be loaded, defaults to FALSE.
+   * @param int $revision_id
+   *   (optional) The revision to be loaded. Defaults to FALSE.
    */
-  protected function attachPropertyData(array &$entities, $load_revision = FALSE) {
+  protected function attachPropertyData(array &$entities, $revision_id = FALSE) {
     if ($this->dataTable) {
-      $query = $this->database->select($this->dataTable, 'data', array('fetch' => PDO::FETCH_ASSOC))
+      // If a revision table is available, we need all the properties of the
+      // latest revision. Otherwise we fall back to the data table.
+      $table = $this->revisionTable ?: $this->dataTable;
+      $query = $this->database->select($table, 'data', array('fetch' => PDO::FETCH_ASSOC))
         ->fields('data')
         ->condition($this->idKey, array_keys($entities))
         ->orderBy('data.' . $this->idKey);
-      if ($load_revision) {
-        // Get revision ID's.
-        $revision_ids = array();
-        foreach ($entities as $id => $entity) {
-          $revision_ids[] = $entity->get($this->revisionKey)->value;
+
+      if ($this->revisionTable) {
+        if ($revision_id) {
+          $query->condition($this->revisionKey, $revision_id);
+        }
+        else {
+          // Get the revision IDs.
+          $revision_ids = array();
+          foreach ($entities as $id => $values) {
+            $revision_ids[] = $values[$this->revisionKey];
+          }
+          $query->condition($this->revisionKey, $revision_ids);
         }
-        $query->condition($this->revisionKey, $revision_ids);
       }
-      $data = $query->execute();
 
-      // Fetch the field definitions to check which field is translatable.
+      $data = $query->execute();
       $field_definition = $this->getFieldDefinitions(array());
-      $data_fields = array_flip(drupal_schema_fields_sql($this->entityInfo['data_table']));
+      if ($this->revisionTable) {
+        $data_fields = array_flip(array_diff(drupal_schema_fields_sql($this->entityInfo['revision_table']), drupal_schema_fields_sql($this->entityInfo['base_table'])));
+      }
+      else {
+        $data_fields = array_flip(drupal_schema_fields_sql($this->entityInfo['data_table']));
+      }
 
       foreach ($data as $values) {
         $id = $values[$this->idKey];
+
         // Field values in default language are stored with
         // Language::LANGCODE_DEFAULT as key.
         $langcode = empty($values['default_langcode']) ? $values['langcode'] : Language::LANGCODE_DEFAULT;
-        $translation = $entities[$id]->getTranslation($langcode);
 
         foreach ($field_definition as $name => $definition) {
-          // Set translatable properties only.
-          if (isset($data_fields[$name]) && !empty($definition['translatable'])) {
-            // @todo Figure out how to determine which property has to be set.
-            // Currently it's guessing, and guessing is evil!
-            $property_definition = $translation->{$name}->getPropertyDefinitions();
-            $translation->{$name}->{key($property_definition)} = $values[$name];
-          }
-          // Avoid initializing configurable fields before loading them.
-          elseif (!empty($definition['configurable'])) {
-            unset($entities[$id]->fields[$name]);
+          // Set only translatable properties, unless we are dealing with a
+          // revisable entity, in which case we did not load the untranslatable
+          // data before.
+          $translatable = !empty($definition['translatable']);
+          if (isset($data_fields[$name]) && ($this->revisionTable || $translatable)) {
+            $entities[$id][$name][$langcode] = $values[$name];
           }
         }
       }
+
+      foreach ($entities as $id => $values) {
+        $bundle = $this->bundleKey ? $values[$this->bundleKey][Language::LANGCODE_DEFAULT] : FALSE;
+        // Turn the record into an entity class.
+        $entities[$id] = new $this->entityClass($values, $this->entityType, $bundle);
+      }
     }
   }
 
@@ -352,32 +421,53 @@ public function save(EntityInterface $entity) {
    *   The revision id.
    */
   protected function saveRevision(EntityInterface $entity) {
-    $record = $this->mapToRevisionStorageRecord($entity);
+    $return = $entity->id();
+    $default_langcode = $entity->language()->langcode;
 
-    // When saving a new revision, set any existing revision ID to NULL so as to
-    // ensure that a new revision will actually be created.
-    if ($entity->isNewRevision() && isset($record->{$this->revisionKey})) {
-      $record->{$this->revisionKey} = NULL;
+    if (!$entity->isNewRevision()) {
+      // Delete to handle removed values.
+      $this->database->delete($this->revisionTable)
+        ->condition($this->idKey, $entity->id())
+        ->condition($this->revisionKey, $entity->getRevisionId())
+        ->execute();
     }
 
-    $this->preSaveRevision($record, $entity);
+    $languages = $this->dataTable ? $entity->getTranslationLanguages(TRUE) : array($default_langcode => $entity->language());
+    foreach ($languages as $langcode => $language) {
+      $translation = $entity->getTranslation($langcode, FALSE);
+      $record = $this->mapToRevisionStorageRecord($translation);
+      $record->langcode = $langcode;
+      $record->default_langcode = $langcode == $default_langcode;
+
+      // When saving a new revision, set any existing revision ID to NULL so as
+      // to ensure that a new revision will actually be created.
+      if ($entity->isNewRevision() && isset($record->{$this->revisionKey})) {
+        $record->{$this->revisionKey} = NULL;
+      }
 
-    if ($entity->isNewRevision()) {
-      drupal_write_record($this->revisionTable, $record);
-      if ($entity->isDefaultRevision()) {
-        $this->database->update($this->entityInfo['base_table'])
-          ->fields(array($this->revisionKey => $record->{$this->revisionKey}))
-          ->condition($this->idKey, $record->{$this->idKey})
-          ->execute();
+      $this->preSaveRevision($record, $entity);
+
+      if ($entity->isNewRevision()) {
+        drupal_write_record($this->revisionTable, $record);
+        if ($entity->isDefaultRevision()) {
+          $this->database->update($this->entityInfo['base_table'])
+            ->fields(array($this->revisionKey => $record->{$this->revisionKey}))
+            ->condition($this->idKey, $record->{$this->idKey})
+            ->execute();
+        }
+        $entity->setNewRevision(FALSE);
       }
-      $entity->setNewRevision(FALSE);
-    }
-    else {
-      drupal_write_record($this->revisionTable, $record, $this->revisionKey);
+      else {
+        // @todo Use multiple insertions to improve performance.
+        drupal_write_record($this->revisionTable, $record);
+      }
+
+      // Make sure to update the new revision key for the entity.
+      $entity->{$this->revisionKey}->value = $record->{$this->revisionKey};
+      $return = $record->{$this->revisionKey};
     }
-    // Make sure to update the new revision key for the entity.
-    $entity->{$this->revisionKey}->value = $record->{$this->revisionKey};
-    return $record->{$this->revisionKey};
+
+    return $return;
   }
 
   /**
@@ -453,10 +543,11 @@ protected function mapToStorageRecord(EntityInterface $entity) {
    * @return \stdClass
    *   The record to store.
    */
-  protected function mapToRevisionStorageRecord(EntityInterface $entity) {
+  protected function mapToRevisionStorageRecord(ComplexDataInterface $entity) {
     $record = new \stdClass();
+    $definitions = $entity->getPropertyDefinitions();
     foreach (drupal_schema_fields_sql($this->entityInfo['revision_table']) as $name) {
-      if (isset($entity->$name->value)) {
+      if (isset($definitions[$name]) && isset($entity->$name->value)) {
         $record->$name = $entity->$name->value;
       }
     }
@@ -479,10 +570,14 @@ protected function mapToDataStorageRecord(EntityInterface $entity, $langcode) {
     // Don't use strict mode, this way there's no need to do checks here, as
     // non-translatable properties are replicated for each language.
     $translation = $entity->getTranslation($langcode, FALSE);
+    $definitions = $translation->getPropertyDefinitions();
+    $schema = drupal_get_schema($this->entityInfo['data_table']);
 
     $record = new \stdClass();
     foreach (drupal_schema_fields_sql($this->entityInfo['data_table']) as $name) {
-      $record->$name = $translation->$name->value;
+      $info = $schema['fields'][$name];
+      $value = isset($definitions[$name]) && isset($translation->$name->value) ? $translation->$name->value : NULL;
+      $record->$name = drupal_schema_get_field_value($info, $value);
     }
     $record->langcode = $langcode;
     $record->default_langcode = intval($default_langcode == $langcode);
diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php
index 6a93a596bfab..1f1d3c69e353 100644
--- a/core/lib/Drupal/Core/Entity/EntityNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityNG.php
@@ -328,6 +328,7 @@ public function getTranslation($langcode, $strict = TRUE) {
    */
   public function getTranslationLanguages($include_default = TRUE) {
     $translations = array();
+    $definitions = $this->getPropertyDefinitions();
     // Build an array with the translation langcodes set as keys. Empty
     // translations should not be included and must be skipped.
     foreach ($this->getProperties() as $name => $property) {
@@ -339,7 +340,7 @@ public function getTranslationLanguages($include_default = TRUE) {
           foreach ($this->values[$name] as $langcode => $values) {
             // If a value is there but the field object is empty, it has been
             // unset, so we need to skip the field also.
-            if ($values && !(isset($this->fields[$name][$langcode]) && $this->fields[$name][$langcode]->isEmpty())) {
+            if ($values && !empty($definitions[$name]['translatable']) && !(isset($this->fields[$name][$langcode]) && $this->fields[$name][$langcode]->isEmpty())) {
               $translations[$langcode] = TRUE;
             }
           }
diff --git a/core/modules/action/lib/Drupal/action/Tests/BulkFormTest.php b/core/modules/action/lib/Drupal/action/Tests/BulkFormTest.php
index 8a2cb912f3d5..8a86279cddc7 100644
--- a/core/modules/action/lib/Drupal/action/Tests/BulkFormTest.php
+++ b/core/modules/action/lib/Drupal/action/Tests/BulkFormTest.php
@@ -37,7 +37,14 @@ public static function getInfo() {
   public function testBulkForm() {
     $nodes = array();
     for ($i = 0; $i < 10; $i++) {
-      $nodes[] = $this->drupalCreateNode(array('sticky' => FALSE));
+      // Ensure nodes are sorted in the same order they are inserted in the
+      // array.
+      $timestamp = REQUEST_TIME - $i;
+      $nodes[] = $this->drupalCreateNode(array(
+        'sticky' => FALSE,
+        'created' => $timestamp,
+        'changed' => $timestamp,
+      ));
     }
 
     $this->drupalGet('test_bulk_form');
diff --git a/core/modules/action/tests/action_bulk_test/config/views.view.test_bulk_form.yml b/core/modules/action/tests/action_bulk_test/config/views.view.test_bulk_form.yml
index 06c67f2495de..4973c62a58b9 100644
--- a/core/modules/action/tests/action_bulk_test/config/views.view.test_bulk_form.yml
+++ b/core/modules/action/tests/action_bulk_test/config/views.view.test_bulk_form.yml
@@ -56,7 +56,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           label: ''
           alter:
@@ -124,7 +124,7 @@ display:
       filters:
         status:
           value: '1'
-          table: node
+          table: node_field_data
           field: status
           id: status
           expose:
@@ -134,7 +134,7 @@ display:
       sorts:
         created:
           id: created
-          table: node
+          table: node_field_data
           field: created
           order: DESC
           plugin_id: date
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
index 8f8dc0464632..04524532aebd 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
@@ -137,7 +137,7 @@ function getFeedEditObject($feed_url = NULL, array $values = array()) {
    */
   function getDefaultFeedItemCount() {
     // Our tests are based off of rss.xml, so let's find out how many elements should be related.
-    $feed_count = db_query_range('SELECT COUNT(*) FROM {node} n WHERE n.promote = 1 AND n.status = 1', 0, config('system.rss')->get('items.limit'))->fetchField();
+    $feed_count = db_query_range('SELECT COUNT(DISTINCT nid) FROM {node_field_data} n WHERE n.promote = 1 AND n.status = 1', 0, config('system.rss')->get('items.limit'))->fetchField();
     return $feed_count > 10 ? 10 : $feed_count;
   }
 
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php
index 87ff2d54b072..046b065b5bf6 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockStorageController.php
@@ -35,14 +35,12 @@ protected function preSaveRevision(\stdClass $record, EntityInterface $entity) {
         $record->log = '';
       }
     }
-    elseif (!isset($record->log) || $record->log === '') {
+    elseif (isset($entity->original) && (!isset($record->log) || $record->log === '')) {
       // If we are updating an existing custom_block without adding a new
-      // revision, we need to make sure $entity->log is unset whenever it is
-      // empty. As long as $entity->log is unset, drupal_write_record() will not
-      // attempt to update the existing database column when re-saving the
-      // revision; therefore, this code allows us to avoid clobbering an
-      // existing log entry with an empty one.
-      unset($record->log);
+      // revision, we need to make sure $entity->log is reset whenever it is
+      // empty. Therefore, this code allows us to avoid clobbering an existing
+      // log entry with an empty one.
+      $record->log = $entity->original->log->value;
     }
   }
 
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index 95247ad2e21e..8679d2f3a566 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -268,35 +268,7 @@ function book_admin_paths() {
  *   An array of all books.
  */
 function book_get_books() {
-  $all_books = &drupal_static(__FUNCTION__);
-
-  if (!isset($all_books)) {
-    $all_books = array();
-    $nids = db_query("SELECT DISTINCT(bid) FROM {book}")->fetchCol();
-
-    if ($nids) {
-      $query = db_select('book', 'b', array('fetch' => PDO::FETCH_ASSOC));
-      $query->join('node', 'n', 'b.nid = n.nid');
-      $query->join('menu_links', 'ml', 'b.mlid = ml.mlid');
-      $query->addField('n', 'type', 'type');
-      $query->addField('n', 'title', 'title');
-      $query->fields('b');
-      $query->fields('ml');
-      $query->condition('n.nid', $nids, 'IN');
-      $query->condition('n.status', 1);
-      $query->orderBy('ml.weight');
-      $query->orderBy('ml.link_title');
-      $query->addTag('node_access');
-      $result2 = $query->execute();
-      foreach ($result2 as $link) {
-        $link['href'] = $link['link_path'];
-        $link['options'] = unserialize($link['options']);
-        $all_books[$link['bid']] = $link;
-      }
-    }
-  }
-
-  return $all_books;
+  return Drupal::service('book.manager')->getAllBooks();
 }
 
 /**
diff --git a/core/modules/book/book.services.yml b/core/modules/book/book.services.yml
index 254c6ecc029b..9d8c1402ba03 100644
--- a/core/modules/book/book.services.yml
+++ b/core/modules/book/book.services.yml
@@ -1,4 +1,4 @@
 services:
   book.manager:
     class: Drupal\book\BookManager
-    arguments: ['@database']
+    arguments: ['@database', '@plugin.manager.entity']
diff --git a/core/modules/book/lib/Drupal/book/BookManager.php b/core/modules/book/lib/Drupal/book/BookManager.php
index cf2070bc8628..b037429ea191 100644
--- a/core/modules/book/lib/Drupal/book/BookManager.php
+++ b/core/modules/book/lib/Drupal/book/BookManager.php
@@ -6,8 +6,9 @@
 
 namespace Drupal\book;
 
-use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\Core\Database\Connection;
+use Drupal\Core\Entity\EntityManager;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Book Manager Service.
@@ -21,6 +22,13 @@ class BookManager {
    */
   protected $database;
 
+  /**
+   * Entity manager Service Object.
+   *
+   * @var \Drupal\Core\Entity\EntityManager
+   */
+  protected $entityManager;
+
   /**
    * Books Array.
    *
@@ -31,8 +39,9 @@ class BookManager {
   /**
    * Constructs a BookManager object.
    */
-  public function __construct(Connection $database) {
+  public function __construct(Connection $database, EntityManager $entityManager) {
     $this->database = $database;
+    $this->entityManager = $entityManager;
   }
 
   /**
@@ -57,24 +66,30 @@ public function getAllBooks() {
   protected function loadBooks() {
     $this->books = array();
     $nids = $this->database->query("SELECT DISTINCT(bid) FROM {book}")->fetchCol();
+
     if ($nids) {
       $query = $this->database->select('book', 'b', array('fetch' => \PDO::FETCH_ASSOC));
-      $query->join('node', 'n', 'b.nid = n.nid');
       $query->join('menu_links', 'ml', 'b.mlid = ml.mlid');
-      $query->addField('n', 'type', 'type');
-      $query->addField('n', 'title', 'title');
       $query->fields('b');
       $query->fields('ml');
-      $query->condition('n.nid', $nids, 'IN');
-      $query->condition('n.status', 1);
+      $query->condition('b.nid', $nids);
       $query->orderBy('ml.weight');
       $query->orderBy('ml.link_title');
       $query->addTag('node_access');
+      $query->addMetaData('base_table', 'book');
       $book_links = $query->execute();
+
+      $nodes = $this->entityManager->getStorageController('node')->load($nids);
+
       foreach ($book_links as $link) {
-        $link['href'] = $link['link_path'];
-        $link['options'] = unserialize($link['options']);
-        $this->books[$link['bid']] = $link;
+        $nid = $link['nid'];
+        if (isset($nodes[$nid]) && $nodes[$nid]->status) {
+          $link['href'] = $link['link_path'];
+          $link['options'] = unserialize($link['options']);
+          $link['title'] = $nodes[$nid]->label();
+          $link['type'] = $nodes[$nid]->bundle();
+          $this->books[$link['bid']] = $link;
+        }
       }
     }
   }
diff --git a/core/modules/book/lib/Drupal/book/Plugin/Block/BookNavigationBlock.php b/core/modules/book/lib/Drupal/book/Plugin/Block/BookNavigationBlock.php
index 4b9ccce4a3b3..7461aa7ed4f7 100644
--- a/core/modules/book/lib/Drupal/book/Plugin/Block/BookNavigationBlock.php
+++ b/core/modules/book/lib/Drupal/book/Plugin/Block/BookNavigationBlock.php
@@ -96,12 +96,12 @@ protected function blockBuild() {
     elseif ($current_bid) {
       // Only display this block when the user is browsing a book.
       $select = db_select('node', 'n')
-        ->fields('n', array('title'))
+        ->fields('n', array('nid'))
         ->condition('n.nid', $node->book['bid'])
         ->addTag('node_access');
-      $title = $select->execute()->fetchField();
+      $nid = $select->execute()->fetchField();
       // Only show the block if the user has view access for the top-level node.
-      if ($title) {
+      if ($nid) {
         $tree = menu_tree_all_data($node->book['menu_name'], $node->book);
         // There should only be one element at the top level.
         $data = array_shift($tree);
diff --git a/core/modules/comment/comment.admin.inc b/core/modules/comment/comment.admin.inc
index 488c2f9b3cb0..51158a9b9331 100644
--- a/core/modules/comment/comment.admin.inc
+++ b/core/modules/comment/comment.admin.inc
@@ -82,24 +82,27 @@ function comment_admin_overview($form, &$form_state, $arg) {
   $query = db_select('comment', 'c')
     ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
     ->extend('Drupal\Core\Database\Query\TableSortExtender');
-  $query->join('node', 'n', 'n.nid = c.nid');
-  $query->addField('n', 'title', 'node_title');
+  $query->join('node_field_data', 'n', 'n.nid = c.nid');
   $query->addTag('node_access');
   $result = $query
-    ->fields('c', array('cid', 'subject', 'name', 'changed'))
+    ->fields('c', array('cid', 'nid', 'subject', 'name', 'changed'))
     ->condition('c.status', $status)
     ->limit(50)
     ->orderByHeader($header)
     ->execute();
 
+  $nids = array();
   $cids = array();
 
   // We collect a sorted list of node_titles during the query to attach to the
   // comments later.
   foreach ($result as $row) {
+    $nids[] = $row->nid;
     $cids[] = $row->cid;
-    $node_titles[] = $row->node_title;
   }
+  // Ensure all nodes are statically cached so that we do not have to load them
+  // individually when getting their labels below.
+  node_load_multiple($nids);
   $comments = comment_load_multiple($cids);
 
   // Build a table listing the appropriate comments.
@@ -109,7 +112,7 @@ function comment_admin_overview($form, &$form_state, $arg) {
   foreach ($comments as $comment) {
     // Remove the first node title from the node_titles array and attach to
     // the comment.
-    $node_title = array_shift($node_titles);
+    $node_title = $comment->nid->entity->label();
     $options[$comment->id()] = array(
       'subject' => array(
         'data' => array(
diff --git a/core/modules/comment/comment.install b/core/modules/comment/comment.install
index b022efb3c933..964030482cc8 100644
--- a/core/modules/comment/comment.install
+++ b/core/modules/comment/comment.install
@@ -37,8 +37,8 @@ function comment_uninstall() {
  */
 function comment_enable() {
   // Insert records into the node_comment_statistics for nodes that are missing.
-  $query = db_select('node', 'n');
-  $query->leftJoin('node_comment_statistics', 'ncs', 'ncs.nid = n.nid');
+  $query = db_select('node_field_data', 'n');
+  $query->leftJoin('node_comment_statistics', 'ncs', 'ncs.nid = n.nid AND n.default_langcode = 1');
   $query->addField('n', 'created', 'last_comment_timestamp');
   $query->addField('n', 'uid', 'last_comment_uid');
   $query->addField('n', 'nid');
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index b2d0190914f9..9895b1f1cc44 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -452,13 +452,16 @@ function comment_permalink(Comment $comment) {
  */
 function comment_get_recent($number = 10) {
   $query = db_select('comment', 'c');
-  $query->innerJoin('node', 'n', 'n.nid = c.nid');
+  $query->innerJoin('node_field_data', 'n', 'n.nid = c.nid');
   $query->addTag('node_access');
   $query->addMetaData('base_table', 'comment');
   $comments = $query
     ->fields('c')
     ->condition('c.status', COMMENT_PUBLISHED)
     ->condition('n.status', NODE_PUBLISHED)
+    // @todo This should be actually filtering on the desired node status field
+    //   language and just fall back to the default language.
+    ->condition('n.default_langcode', 1)
     ->orderBy('c.created', 'DESC')
     // Additionally order by cid to ensure that comments with the same timestamp
     // are returned in the exact order posted.
diff --git a/core/modules/comment/comment.views.inc b/core/modules/comment/comment.views.inc
index ae0020ad7a10..6cc6c3196939 100644
--- a/core/modules/comment/comment.views.inc
+++ b/core/modules/comment/comment.views.inc
@@ -503,7 +503,7 @@ function comment_views_data_alter(&$data) {
     ),
   );
 
-  $data['node']['comment'] = array(
+  $data['node_field_data']['comment'] = array(
     'title' => t('Comment status'),
     'help' => t('Whether comments are enabled or disabled on the node.'),
     'field' => array(
@@ -517,7 +517,7 @@ function comment_views_data_alter(&$data) {
     ),
   );
 
-  $data['node']['uid_touch'] = array(
+  $data['node_field_data']['uid_touch'] = array(
     'title' => t('User posted or commented'),
     'help' => t('Display nodes only if a user posted the node or commented on the node.'),
     'argument' => array(
diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
index c005cb0aafeb..eef80c8dbe8a 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php
@@ -232,7 +232,7 @@ protected function updateNodeStatistics($nid) {
     }
     else {
       // Comments do not exist.
-      $node = db_query('SELECT uid, created FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchObject();
+      $node = db_query('SELECT uid, created FROM {node_field_data} WHERE nid = :nid LIMIT 1', array(':nid' => $nid))->fetchObject();
       db_update('node_comment_statistics')
         ->fields(array(
           'cid' => 0,
diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/entity_reference/selection/CommentSelection.php b/core/modules/comment/lib/Drupal/comment/Plugin/entity_reference/selection/CommentSelection.php
index 61dd1a3a2691..ae544e0cda83 100644
--- a/core/modules/comment/lib/Drupal/comment/Plugin/entity_reference/selection/CommentSelection.php
+++ b/core/modules/comment/lib/Drupal/comment/Plugin/entity_reference/selection/CommentSelection.php
@@ -51,7 +51,7 @@ public function entityQueryAlter(SelectInterface $query) {
     // The Comment module doesn't implement any proper comment access,
     // and as a consequence doesn't make sure that comments cannot be viewed
     // when the user doesn't have access to the node.
-    $node_alias = $query->innerJoin('node', 'n', '%alias.nid = ' . $base_table . '.nid');
+    $node_alias = $query->innerJoin('node_field_data', 'n', '%alias.nid = ' . $base_table . '.nid');
     // Pass the query to the node access control.
     $this->reAlterQuery($query, 'node_access', $node_alias);
 
diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/views/wizard/Comment.php b/core/modules/comment/lib/Drupal/comment/Plugin/views/wizard/Comment.php
index c45efbdb41fa..df62c6ab18c8 100644
--- a/core/modules/comment/lib/Drupal/comment/Plugin/views/wizard/Comment.php
+++ b/core/modules/comment/lib/Drupal/comment/Plugin/views/wizard/Comment.php
@@ -58,7 +58,7 @@ class Comment extends WizardPluginBase {
     ),
     'status_node' => array(
       'value' => TRUE,
-      'table' => 'node',
+      'table' => 'node_field_data',
       'field' => 'status',
       'relationship' => 'nid'
     )
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php b/core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php
index 46d031873559..37455c5e1ee5 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/DefaultViewRecentComments.php
@@ -84,11 +84,19 @@ public function setUp() {
       $comment->comment_body->value = 'Test body ' . $i;
       $comment->comment_body->format = 'full_html';
 
+      // Ensure comments are sorted in ascending order.
+      $time = REQUEST_TIME + ($this->masterDisplayResults - $i);
+      $comment->created->value = $time;
+      $comment->changed->value = $time;
+
       comment_save($comment);
     }
 
     // Store all the nodes just created to access their properties on the tests.
     $this->commentsCreated = entity_load_multiple('comment');
+
+    // Sort created comments in ascending order.
+    ksort($this->commentsCreated, SORT_NUMERIC);
   }
 
   /**
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/Views/FilterUserUIDTest.php b/core/modules/comment/lib/Drupal/comment/Tests/Views/FilterUserUIDTest.php
index e614c1e5ed5f..9c8c88049ae2 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/Views/FilterUserUIDTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/FilterUserUIDTest.php
@@ -36,11 +36,11 @@ function testCommentUserUIDTest() {
 
     $options = array(
       'id' => 'uid_touch',
-      'table' => 'node',
+      'table' => 'node_field_data',
       'field' => 'uid_touch',
       'value' => array($this->loggedInUser->uid),
     );
-    $view->addItem('default', 'filter', 'node', 'uid_touch', $options);
+    $view->addItem('default', 'filter', 'node_field_data', 'uid_touch', $options);
     $this->executeView($view, array($this->account->uid));
     $result_set = array(
       array(
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php b/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php
index 83ceaeeac007..44a20d4c0afd 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/Views/WizardTest.php
@@ -80,7 +80,7 @@ public function testCommentWizard() {
     $this->assertEqual($view->filter['status']->table, 'comment');
     $this->assertEqual($view->filter['status']->field, 'status');
     $this->assertTrue($view->filter['status']->value);
-    $this->assertEqual($view->filter['status_node']->table, 'node');
+    $this->assertEqual($view->filter['status_node']->table, 'node_field_data');
     $this->assertEqual($view->filter['status_node']->field, 'status');
     $this->assertTrue($view->filter['status_node']->value);
 
diff --git a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_user_uid.yml b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_user_uid.yml
index 86738f6a167f..813da9f23d0b 100644
--- a/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_user_uid.yml
+++ b/core/modules/comment/tests/modules/comment_test_views/test_views/views.view.test_comment_user_uid.yml
@@ -18,7 +18,7 @@ display:
             number_of_records: '0'
           summary_options:
             items_per_page: '25'
-          table: node
+          table: node_field_data
           plugin_id: argument_comment_user_uid
       cache:
         type: none
diff --git a/core/modules/entity_reference/tests/modules/entity_reference_test/config/views.view.test_entity_reference.yml b/core/modules/entity_reference/tests/modules/entity_reference_test/config/views.view.test_entity_reference.yml
index bd20cf4215ae..f9bd3e54187c 100644
--- a/core/modules/entity_reference/tests/modules/entity_reference_test/config/views.view.test_entity_reference.yml
+++ b/core/modules/entity_reference/tests/modules/entity_reference_test/config/views.view.test_entity_reference.yml
@@ -32,7 +32,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           label: ''
           alter:
@@ -50,7 +50,7 @@ display:
       filters:
         status:
           value: '1'
-          table: node
+          table: node_field_data
           field: status
           id: status
           expose:
@@ -59,7 +59,7 @@ display:
       sorts:
         created:
           id: created
-          table: node
+          table: node_field_data
           field: created
           order: DESC
   entity_reference_1:
diff --git a/core/modules/field/lib/Drupal/field/Tests/Views/ApiDataTest.php b/core/modules/field/lib/Drupal/field/Tests/Views/ApiDataTest.php
index 54404b64531d..f18742271ffa 100644
--- a/core/modules/field/lib/Drupal/field/Tests/Views/ApiDataTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/Views/ApiDataTest.php
@@ -93,7 +93,7 @@ function testViewsData() {
     $this->assertTrue(isset($data[$revision_table]));
     // The node field should join against node.
     $this->assertTrue(isset($data[$current_table]['table']['join']['node']));
-    $this->assertTrue(isset($data[$revision_table]['table']['join']['node_revision']));
+    $this->assertTrue(isset($data[$revision_table]['table']['join']['node_field_revision']));
 
     $expected_join = array(
       'left_field' => 'nid',
@@ -112,7 +112,7 @@ function testViewsData() {
         array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
       ),
     );
-    $this->assertEqual($expected_join, $data[$revision_table]['table']['join']['node_revision']);
+    $this->assertEqual($expected_join, $data[$revision_table]['table']['join']['node_field_revision']);
 
     // Check the table and the joins of the second field.
     // Attached to both node and user.
@@ -126,7 +126,7 @@ function testViewsData() {
     $this->assertTrue(isset($data[$revision_table_2]));
     // The second field should join against both node and users.
     $this->assertTrue(isset($data[$current_table_2]['table']['join']['node']));
-    $this->assertTrue(isset($data[$revision_table_2]['table']['join']['node_revision']));
+    $this->assertTrue(isset($data[$revision_table_2]['table']['join']['node_field_revision']));
     $this->assertTrue(isset($data[$current_table_2]['table']['join']['users']));
 
     $expected_join = array(
@@ -146,7 +146,7 @@ function testViewsData() {
         array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
       )
     );
-    $this->assertEqual($expected_join, $data[$revision_table_2]['table']['join']['node_revision']);
+    $this->assertEqual($expected_join, $data[$revision_table_2]['table']['join']['node_field_revision']);
     $expected_join = array(
       'left_field' => 'uid',
       'field' => 'entity_id',
diff --git a/core/modules/file/file.views.inc b/core/modules/file/file.views.inc
index 6b0fb59937fd..c9e271f11bc3 100644
--- a/core/modules/file/file.views.inc
+++ b/core/modules/file/file.views.inc
@@ -226,7 +226,7 @@ function file_views_data() {
     'title' => t('Content'),
     'help' => t('Content that is associated with this file, usually because this file is in a field on the content.'),
     // Only provide this field/relationship/etc. when the 'file_managed' base table is present.
-    'skip base' => array('node', 'node_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
+    'skip base' => array('node', 'node_field_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
     'real field' => 'id',
     'relationship' => array(
       'title' => t('Content'),
@@ -257,7 +257,7 @@ function file_views_data() {
     'title' => t('User'),
     'help' => t('A user that is associated with this file, usually because this file is in a field on the user.'),
     // Only provide this field/relationship/etc. when the 'file_managed' base table is present.
-    'skip base' => array('node', 'node_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
+    'skip base' => array('node', 'node_field_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
     'real field' => 'id',
     'relationship' => array(
       'title' => t('User'),
@@ -272,7 +272,7 @@ function file_views_data() {
     'title' => t('File'),
     'help' => t('A file that is associated with this user, usually because it is in a field on the user.'),
     // Only provide this field/relationship/etc. when the 'users' base table is present.
-    'skip base' => array('file_managed', 'node', 'node_revision', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
+    'skip base' => array('file_managed', 'node', 'node_field_revision', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
     'real field' => 'fid',
     'relationship' => array(
       'title' => t('File'),
@@ -288,7 +288,7 @@ function file_views_data() {
     'title' => t('Comment'),
     'help' => t('A comment that is associated with this file, usually because this file is in a field on the comment.'),
     // Only provide this field/relationship/etc. when the 'file_managed' base table is present.
-    'skip base' => array('node', 'node_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
+    'skip base' => array('node', 'node_field_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
     'real field' => 'id',
     'relationship' => array(
       'title' => t('Comment'),
@@ -303,7 +303,7 @@ function file_views_data() {
     'title' => t('File'),
     'help' => t('A file that is associated with this comment, usually because it is in a field on the comment.'),
     // Only provide this field/relationship/etc. when the 'comment' base table is present.
-    'skip base' => array('file_managed', 'node', 'node_revision', 'users', 'taxonomy_term_data', 'taxonomy_vocabulary'),
+    'skip base' => array('file_managed', 'node', 'node_field_revision', 'users', 'taxonomy_term_data', 'taxonomy_vocabulary'),
     'real field' => 'fid',
     'relationship' => array(
       'title' => t('File'),
@@ -319,7 +319,7 @@ function file_views_data() {
     'title' => t('Taxonomy Term'),
     'help' => t('A taxonomy term that is associated with this file, usually because this file is in a field on the taxonomy term.'),
     // Only provide this field/relationship/etc. when the 'file_managed' base table is present.
-    'skip base' => array('node', 'node_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
+    'skip base' => array('node', 'node_field_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
     'real field' => 'id',
     'relationship' => array(
       'title' => t('Taxonomy Term'),
@@ -334,7 +334,7 @@ function file_views_data() {
     'title' => t('File'),
     'help' => t('A file that is associated with this taxonomy term, usually because it is in a field on the taxonomy term.'),
     // Only provide this field/relationship/etc. when the 'taxonomy_term_data' base table is present.
-    'skip base' => array('file_managed', 'node', 'node_revision', 'users', 'comment', 'taxonomy_vocabulary'),
+    'skip base' => array('file_managed', 'node', 'node_field_revision', 'users', 'comment', 'taxonomy_vocabulary'),
     'real field' => 'fid',
     'relationship' => array(
       'title' => t('File'),
@@ -350,7 +350,7 @@ function file_views_data() {
     'title' => t('Taxonomy Vocabulary'),
     'help' => t('A taxonomy vocabulary that is associated with this file, usually because this file is in a field on the taxonomy vocabulary.'),
     // Only provide this field/relationship/etc. when the 'file_managed' base table is present.
-    'skip base' => array('node', 'node_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
+    'skip base' => array('node', 'node_field_revision', 'users', 'comment', 'taxonomy_term_data', 'taxonomy_vocabulary'),
     'real field' => 'id',
     'relationship' => array(
       'title' => t('Taxonomy Vocabulary'),
@@ -365,7 +365,7 @@ function file_views_data() {
     'title' => t('File'),
     'help' => t('A file that is associated with this taxonomy vocabulary, usually because it is in a field on the taxonomy vocabulary.'),
     // Only provide this field/relationship/etc. when the 'taxonomy_vocabulary' base table is present.
-    'skip base' => array('file_managed', 'node', 'node_revision', 'users', 'comment', 'taxonomy_term_data'),
+    'skip base' => array('file_managed', 'node', 'node_field_revision', 'users', 'comment', 'taxonomy_term_data'),
     'real field' => 'fid',
     'relationship' => array(
       'title' => t('File'),
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index 1a5e0091ecc6..42d73265e5c6 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -743,7 +743,7 @@ function forum_forum_load($tid = NULL) {
   $_forums = taxonomy_get_tree($vid, $tid, NULL, TRUE);
 
   if (count($_forums)) {
-    $query = db_select('node', 'n');
+    $query = db_select('node_field_data', 'n');
     $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid');
     $query->join('forum', 'f', 'n.vid = f.vid');
     $query->addExpression('COUNT(n.nid)', 'topic_count');
@@ -751,6 +751,9 @@ function forum_forum_load($tid = NULL) {
     $counts = $query
       ->fields('f', array('tid'))
       ->condition('n.status', 1)
+      // @todo This should be actually filtering on the desired node status
+      //   field language and just fall back to the default language.
+      ->condition('n.default_langcode', 1)
       ->groupBy('tid')
       ->addTag('node_access')
       ->execute()
@@ -774,7 +777,7 @@ function forum_forum_load($tid = NULL) {
     }
 
     // Query "Last Post" information for this forum.
-    $query = db_select('node', 'n');
+    $query = db_select('node_field_data', 'n');
     $query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $forum->id()));
     $query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid');
     $query->join('users', 'u', 'ncs.last_comment_uid = u.uid');
@@ -783,6 +786,9 @@ function forum_forum_load($tid = NULL) {
     $topic = $query
       ->fields('ncs', array('last_comment_timestamp', 'last_comment_uid'))
       ->condition('n.status', 1)
+      // @todo This should be actually filtering on the desired node status
+      //   field language and just fall back to the default language.
+      ->condition('n.default_langcode', 1)
       ->orderBy('last_comment_timestamp', 'DESC')
       ->range(0, 1)
       ->addTag('node_access')
@@ -821,12 +827,15 @@ function forum_forum_load($tid = NULL) {
  *   The number of new posts in the forum that have not been read by the user.
  */
 function _forum_topics_unread($term, $uid) {
-  $query = db_select('node', 'n');
+  $query = db_select('node_field_data', 'n');
   $query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $term));
   $query->leftJoin('history', 'h', 'n.nid = h.nid AND h.uid = :uid', array(':uid' => $uid));
   $query->addExpression('COUNT(n.nid)', 'count');
   return $query
     ->condition('status', 1)
+    // @todo This should be actually filtering on the desired node status field
+    //   language and just fall back to the default language.
+    ->condition('n.default_langcode', 1)
     ->condition('n.created', HISTORY_READ_LIMIT, '>')
     ->isNull('h.nid')
     ->addTag('node_access')
@@ -894,7 +903,7 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
   if ($nids) {
     $nodes = node_load_multiple($nids);
 
-    $query = db_select('node', 'n')
+    $query = db_select('node_field_data', 'n')
       ->extend('Drupal\Core\Database\Query\TableSortExtender');
     $query->fields('n', array('nid'));
 
@@ -914,7 +923,10 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
     $query
       ->orderBy('f.sticky', 'DESC')
       ->orderByHeader($forum_topic_list_header)
-      ->condition('n.nid', $nids);
+      ->condition('n.nid', $nids)
+      // @todo This should be actually filtering on the desired node language
+      //   and just fall back to the default language.
+      ->condition('n.default_langcode', 1);
 
     $result = array();
     foreach ($query->execute() as $row) {
@@ -1320,7 +1332,9 @@ function _forum_update_forum_index($nid) {
   }
   else {
     // Comments do not exist.
-    $node = db_query('SELECT uid, created FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchObject();
+    // @todo This should be actually filtering on the desired node language and
+    //   just fall back to the default language.
+    $node = db_query('SELECT uid, created FROM {node_field_data} WHERE nid = :nid AND default_langcode = 1', array(':nid' => $nid))->fetchObject();
     db_update('forum_index')
       ->fields( array(
         'comment_count' => 0,
diff --git a/core/modules/history/lib/Drupal/history/Plugin/views/field/HistoryUserTimestamp.php b/core/modules/history/lib/Drupal/history/Plugin/views/field/HistoryUserTimestamp.php
index ccbba18add51..950fcf7ad2c3 100644
--- a/core/modules/history/lib/Drupal/history/Plugin/views/field/HistoryUserTimestamp.php
+++ b/core/modules/history/lib/Drupal/history/Plugin/views/field/HistoryUserTimestamp.php
@@ -32,8 +32,8 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
 
     global $user;
     if ($user->uid) {
-      $this->additional_fields['created'] = array('table' => 'node', 'field' => 'created');
-      $this->additional_fields['changed'] = array('table' => 'node', 'field' => 'changed');
+      $this->additional_fields['created'] = array('table' => 'node_field_data', 'field' => 'created');
+      $this->additional_fields['changed'] = array('table' => 'node_field_data', 'field' => 'changed');
       if (module_exists('comment') && !empty($this->options['comments'])) {
         $this->additional_fields['last_comment'] = array('table' => 'node_comment_statistics', 'field' => 'last_comment_timestamp');
       }
diff --git a/core/modules/history/lib/Drupal/history/Plugin/views/filter/HistoryUserTimestamp.php b/core/modules/history/lib/Drupal/history/Plugin/views/filter/HistoryUserTimestamp.php
index 7847ccccdbb3..48f4b1079add 100644
--- a/core/modules/history/lib/Drupal/history/Plugin/views/filter/HistoryUserTimestamp.php
+++ b/core/modules/history/lib/Drupal/history/Plugin/views/filter/HistoryUserTimestamp.php
@@ -71,7 +71,7 @@ public function query() {
 
     $this->ensureMyTable();
     $field = "$this->tableAlias.$this->realField";
-    $node = $this->query->ensure_table('node', $this->relationship);
+    $node = $this->query->ensure_table('node_field_data', $this->relationship);
 
     $clause = '';
     $clause2 = '';
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
index d69d083d0c7f..bc6ae1a0d081 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleContentTest.php
@@ -47,6 +47,7 @@ function testMachineNameLTR() {
     $edit = array();
     $edit['predefined_langcode'] = 'ar';
     $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
+    drupal_static_reset('language_list');
 
     $edit = array(
       'site_default_language' => 'ar',
@@ -85,6 +86,7 @@ function testContentTypeLanguageConfiguration() {
       'direction' => '0',
     );
     $this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
+    drupal_static_reset('language_list');
 
     // Set the content type to use multilingual support.
     $this->drupalGet("admin/structure/types/manage/{$type2->type}");
@@ -156,6 +158,7 @@ function testContentTypeDirLang() {
     $edit = array();
     $edit['predefined_langcode'] = 'es';
     $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
+    drupal_static_reset('language_list');
 
     // Set the content type to use multilingual support.
     $this->drupalGet("admin/structure/types/manage/{$type->type}");
@@ -218,6 +221,7 @@ function testNodeAdminLanguageFilter() {
     // Enable multiple languages.
     $this->drupalPost('admin/config/regional/language/edit/en', array('locale_translate_english' => TRUE), t('Save language'));
     $this->drupalPost('admin/config/regional/language/add', array('predefined_langcode' => 'zh-hant'), t('Add language'));
+    drupal_static_reset('language_list');
 
     // Create two nodes: English and Chinese.
     $node_en = $this->drupalCreateNode(array('langcode' => 'en'));
diff --git a/core/modules/node/config/views.view.frontpage.yml b/core/modules/node/config/views.view.frontpage.yml
index 94747fe6a5da..b04facaba9c8 100644
--- a/core/modules/node/config/views.view.frontpage.yml
+++ b/core/modules/node/config/views.view.frontpage.yml
@@ -91,7 +91,7 @@ display:
           is_grouped: '0'
           operator: '='
           relationship: none
-          table: node
+          table: node_field_data
           value: '1'
           plugin_id: boolean
         status:
@@ -100,7 +100,7 @@ display:
           field: status
           group: '1'
           id: status
-          table: node
+          table: node_field_data
           value: '1'
           plugin_id: boolean
       pager:
@@ -150,13 +150,13 @@ display:
           id: sticky
           order: DESC
           relationship: none
-          table: node
+          table: node_field_data
           plugin_id: boolean
         created:
           field: created
           id: created
           order: DESC
-          table: node
+          table: node_field_data
           plugin_id: date
           relationship: none
           group_type: group
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index 82504a099558..4bc59fe20f02 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -319,7 +319,7 @@ protected function actions(array $form, array &$form_state) {
   public function validate(array $form, array &$form_state) {
     $node = $this->buildEntity($form, $form_state);
 
-    if (isset($node->nid) && (node_last_changed($node->nid) > $node->changed)) {
+    if (isset($node->nid) && (node_last_changed($node->nid, $this->getFormLangcode($form_state)) > $node->changed)) {
       form_set_error('changed', t('The content on this page has either been modified by another user, or you have already submitted modifications using this form. As a result, your changes cannot be saved.'));
     }
 
diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php
index c9e832e03b21..db3ba75a0154 100644
--- a/core/modules/node/lib/Drupal/node/NodeStorageController.php
+++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php
@@ -79,21 +79,6 @@ protected function attachLoad(&$queried_entities, $load_revision = FALSE) {
     }
   }
 
-  /**
-   * Overrides Drupal\Core\Entity\DatabaseStorageController::buildQuery().
-   */
-  protected function buildQuery($ids, $revision_id = FALSE) {
-    // Ensure that uid is taken from the {node} table,
-    // alias timestamp to revision_timestamp and add revision_uid.
-    $query = parent::buildQuery($ids, $revision_id);
-    $fields =& $query->getFields();
-    unset($fields['timestamp']);
-    $query->addField('revision', 'timestamp', 'revision_timestamp');
-    $fields['uid']['table'] = 'base';
-    $query->addField('revision', 'uid', 'revision_uid');
-    return $query;
-  }
-
   /**
    * Overrides Drupal\Core\Entity\DatabaseStorageController::invokeHook().
    */
@@ -128,6 +113,16 @@ protected function invokeHook($hook, EntityInterface $node) {
     module_invoke_all('entity_' . $hook, $node, $this->entityType);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function mapToDataStorageRecord(EntityInterface $entity, $langcode) {
+    // @todo Remove this once comment is a regular entity field.
+    $record = parent::mapToDataStorageRecord($entity, $langcode);
+    $record->comment = isset($record->comment) ? intval($record->comment) : 0;
+    return $record;
+  }
+
   /**
    * Overrides Drupal\Core\Entity\DatabaseStorageController::preSave().
    */
@@ -142,30 +137,23 @@ protected function preSave(EntityInterface $node) {
   protected function preSaveRevision(\stdClass $record, EntityInterface $entity) {
     if ($entity->isNewRevision()) {
       // When inserting either a new node or a new node revision, $node->log
-      // must be set because {node_revision}.log is a text column and therefore
-      // cannot have a default value. However, it might not be set at this
-      // point (for example, if the user submitting a node form does not have
-      // permission to create revisions), so we ensure that it is at least an
-      // empty string in that case.
-      // @todo: Make the {node_revision}.log column nullable so that we can
-      // remove this check.
+      // must be set because {node_field_revision}.log is a text column and
+      // therefore cannot have a default value. However, it might not be set at
+      // this point (for example, if the user submitting a node form does not
+      // have permission to create revisions), so we ensure that it is at least
+      // an empty string in that case.
+      // @todo Make the {node_field_revision}.log column nullable so that we
+      //   can remove this check.
       if (!isset($record->log)) {
         $record->log = '';
       }
     }
-    elseif (!isset($record->log) || $record->log === '') {
+    elseif (isset($entity->original) && (!isset($record->log) || $record->log === '')) {
       // If we are updating an existing node without adding a new revision, we
-      // need to make sure $node->log is unset whenever it is empty. As long as
-      // $node->log is unset, drupal_write_record() will not attempt to update
-      // the existing database column when re-saving the revision; therefore,
-      // this code allows us to avoid clobbering an existing log entry with an
-      // empty one.
-      unset($record->log);
-    }
-
-    if ($entity->isNewRevision()) {
-      $record->timestamp = REQUEST_TIME;
-      $record->uid = isset($entity->revision_uid->value) ? $entity->revision_uid->value : $GLOBALS['user']->uid;
+      // need to make sure $entity->log is reset whenever it is empty.
+      // Therefore, this code allows us to avoid clobbering an existing log
+      // entry with an empty one.
+      $record->log = $entity->original->log;
     }
   }
 
diff --git a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
index 7a9ffa9a0b56..fc4da346b76a 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php
@@ -30,7 +30,8 @@
  *     "translation" = "Drupal\node\NodeTranslationController"
  *   },
  *   base_table = "node",
- *   revision_table = "node_revision",
+ *   data_table = "node_field_data",
+ *   revision_table = "node_field_revision",
  *   uri_callback = "node_uri",
  *   fieldable = TRUE,
  *   translatable = TRUE,
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/argument/UidRevision.php b/core/modules/node/lib/Drupal/node/Plugin/views/argument/UidRevision.php
index d4320243ef81..a32ae6fb8507 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/argument/UidRevision.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument/UidRevision.php
@@ -21,7 +21,7 @@ class UidRevision extends Uid {
   public function query($group_by = FALSE) {
     $this->ensureMyTable();
     $placeholder = $this->placeholder();
-    $this->query->add_where_expression(0, "$this->tableAlias.uid = $placeholder OR ((SELECT COUNT(*) FROM {node_revision} nr WHERE nr.uid = $placeholder AND nr.nid = $this->tableAlias.nid) > 0)", array($placeholder => $this->argument));
+    $this->query->add_where_expression(0, "$this->tableAlias.revision_uid = $placeholder OR ((SELECT COUNT(DISTINCT vid) FROM {node_field_revision} nfr WHERE nfr.revision_uid = $placeholder AND nfr.nid = $this->tableAlias.nid) > 0)", array($placeholder => $this->argument));
   }
 
 }
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/argument/Vid.php b/core/modules/node/lib/Drupal/node/Plugin/views/argument/Vid.php
index 4e36279c725e..eb2565b0e119 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/argument/Vid.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/argument/Vid.php
@@ -25,9 +25,9 @@ class Vid extends Numeric {
   function title_query() {
     $titles = array();
 
-    $results = db_select('node_revision', 'nr')
-      ->fields('nr', array('vid', 'nid', 'title'))
-      ->condition('nr.vid', $this->value)
+    $results = db_select('node_field_revision', 'npr')
+      ->fields('npr', array('vid', 'nid', 'title'))
+      ->condition('npr.vid', $this->value)
       ->execute()
       ->fetchAllAssoc('vid', PDO::FETCH_ASSOC);
     $nids = array();
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/field/Link.php b/core/modules/node/lib/Drupal/node/Plugin/views/field/Link.php
index ace65a6d2acf..266bedf5fca8 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/field/Link.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/field/Link.php
@@ -38,7 +38,12 @@ public function buildOptionsForm(&$form, &$form_state) {
     $form['alter']['external'] = array('#access' => FALSE);
   }
 
-  public function query() {}
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $this->add_additional_fields();
+  }
 
   function render($values) {
     if ($entity = $this->get_entity($values)) {
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLink.php b/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLink.php
index 758af765e80c..1f4bba227986 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLink.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLink.php
@@ -27,7 +27,7 @@ class RevisionLink extends Link {
   public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
     parent::init($view, $display, $options);
 
-    $this->additional_fields['node_vid'] = array('table' => 'node_revision', 'field' => 'vid');
+    $this->additional_fields['node_vid'] = array('table' => 'node_field_revision', 'field' => 'vid');
   }
 
   public function access() {
@@ -42,7 +42,7 @@ function render_link($data, $values) {
 
     // Current revision uses the node view path.
     $path = 'node/' . $node->nid;
-    if ($node->vid != $vid) {
+    if (!$node->isDefaultRevision()) {
       $path .= "/revisions/$vid/view";
     }
 
@@ -67,7 +67,7 @@ function render_link($data, $values) {
    */
   function get_revision_entity($values, $op) {
     $vid = $this->get_value($values, 'node_vid');
-    $node = $this->get_value($values);
+    $node = $this->get_entity($values);
     // Unpublished nodes ignore access control.
     $node->status = 1;
     // Ensure user has access to perform the operation on this node.
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLinkDelete.php b/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLinkDelete.php
index 2d5aee70542e..2ffb49c47d77 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLinkDelete.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLinkDelete.php
@@ -30,7 +30,7 @@ function render_link($data, $values) {
     }
 
     // Current revision cannot be deleted.
-    if ($node->vid == $vid) {
+    if ($node->isDefaultRevision()) {
       return;
     }
 
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLinkRevert.php b/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLinkRevert.php
index 537857ee0efb..8f9671c4e8d4 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLinkRevert.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/field/RevisionLinkRevert.php
@@ -30,7 +30,7 @@ function render_link($data, $values) {
     }
 
     // Current revision cannot be reverted.
-    if ($node->vid == $vid) {
+    if ($node->isDefaultRevision()) {
       return;
     }
 
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/filter/UidRevision.php b/core/modules/node/lib/Drupal/node/Plugin/views/filter/UidRevision.php
index 9ed9fe38f748..0653583e0fff 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/filter/UidRevision.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/filter/UidRevision.php
@@ -27,7 +27,7 @@ public function query($group_by = FALSE) {
     $args = array_values($this->value);
 
     $this->query->add_where_expression($this->options['group'], "$this->tableAlias.uid IN($placeholder) OR
-      ((SELECT COUNT(*) FROM {node_revision} nr WHERE nr.uid IN($placeholder) AND nr.nid = $this->tableAlias.nid) > 0)", array($placeholder => $args),
+      ((SELECT COUNT(DISTINCT vid) FROM {node_field_revision} nfr WHERE nfr.revision_uid IN ($placeholder) AND nfr.nid = $this->tableAlias.nid) > 0)", array($placeholder => $args),
       $args);
   }
 
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php b/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php
index 644fbcf5dc2c..31092684c992 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php
@@ -31,7 +31,7 @@ class Node extends WizardPluginBase {
   /**
    * Set the created column.
    */
-  protected $createdColumn = 'created';
+  protected $createdColumn = 'node_field_data-created';
 
   /**
    * Set default values for the path field options.
@@ -54,7 +54,7 @@ class Node extends WizardPluginBase {
   protected $filters = array(
     'status' => array(
       'value' => TRUE,
-      'table' => 'node',
+      'table' => 'node_field_data',
       'field' => 'status'
     )
   );
@@ -67,7 +67,7 @@ class Node extends WizardPluginBase {
   public function getAvailableSorts() {
     // You can't execute functions in properties, so override the method
     return array(
-      'title:DESC' => t('Title')
+      'node_field_data-title:DESC' => t('Title')
     );
   }
 
@@ -146,7 +146,7 @@ protected function default_display_options() {
     // to a row style that uses fields.
     /* Field: Content: Title */
     $display_options['fields']['title']['id'] = 'title';
-    $display_options['fields']['title']['table'] = 'node';
+    $display_options['fields']['title']['table'] = 'node_field_data';
     $display_options['fields']['title']['field'] = 'title';
     $display_options['fields']['title']['label'] = '';
     $display_options['fields']['title']['alter']['alter_text'] = 0;
diff --git a/core/modules/node/lib/Drupal/node/Plugin/views/wizard/NodeRevision.php b/core/modules/node/lib/Drupal/node/Plugin/views/wizard/NodeRevision.php
index 0f416384aa0f..37bcb5be07b9 100644
--- a/core/modules/node/lib/Drupal/node/Plugin/views/wizard/NodeRevision.php
+++ b/core/modules/node/lib/Drupal/node/Plugin/views/wizard/NodeRevision.php
@@ -21,7 +21,7 @@
  * @Plugin(
  *   id = "node_revision",
  *   module = "node",
- *   base_table = "node_revision",
+ *   base_table = "node_field_revision",
  *   title = @Translation("Content revisions")
  * )
  */
@@ -37,7 +37,7 @@ class NodeRevision extends WizardPluginBase {
    */
   protected $pathField = array(
     'id' => 'vid',
-    'table' => 'node_revision',
+    'table' => 'node_field_revision',
     'field' => 'vid',
     'exclude' => TRUE,
     'alter' => array(
@@ -65,7 +65,7 @@ class NodeRevision extends WizardPluginBase {
   protected $filters = array(
     'status' => array(
       'value' => TRUE,
-      'table' => 'node_revision',
+      'table' => 'node_field_revision',
       'field' => 'status'
     )
   );
@@ -97,7 +97,7 @@ protected function default_display_options() {
 
     /* Field: Content revision: Created date */
     $display_options['fields']['timestamp']['id'] = 'timestamp';
-    $display_options['fields']['timestamp']['table'] = 'node_revision';
+    $display_options['fields']['timestamp']['table'] = 'node_field_revision';
     $display_options['fields']['timestamp']['field'] = 'timestamp';
     $display_options['fields']['timestamp']['alter']['alter_text'] = 0;
     $display_options['fields']['timestamp']['alter']['make_link'] = 0;
@@ -112,7 +112,7 @@ protected function default_display_options() {
 
     /* Field: Content revision: Title */
     $display_options['fields']['title']['id'] = 'title';
-    $display_options['fields']['title']['table'] = 'node_revision';
+    $display_options['fields']['title']['table'] = 'node_field_revision';
     $display_options['fields']['title']['field'] = 'title';
     $display_options['fields']['title']['label'] = '';
     $display_options['fields']['title']['alter']['alter_text'] = 0;
diff --git a/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php b/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php
index f6c818074999..c5856e570a4d 100644
--- a/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/Condition/NodeConditionTest.php
@@ -28,7 +28,8 @@ protected function setUp() {
     parent::setUp();
     $this->installSchema('node', 'node_type');
     $this->installSchema('node', 'node');
-    $this->installSchema('node', 'node_revision');
+    $this->installSchema('node', 'node_field_data');
+    $this->installSchema('node', 'node_field_revision');
   }
 
   /**
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessBaseTableTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessBaseTableTest.php
index 6b7d00deb239..20370161cbc1 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessBaseTableTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessBaseTableTest.php
@@ -85,7 +85,7 @@ function testNodeAccessBasic() {
         }
 
         $this->drupalPost('node/add/article', $edit, t('Save'));
-        $nid = db_query('SELECT nid FROM {node} WHERE title = :title', array(':title' => $edit['title']))->fetchField();
+        $nid = db_query('SELECT nid FROM {node_field_data} WHERE title = :title', array(':title' => $edit['title']))->fetchField();
         $private_status = db_query('SELECT private FROM {node_access_test} where nid = :nid', array(':nid' => $nid))->fetchField();
         $this->assertTrue($is_private == $private_status, 'The private status of the node was properly set in the node_access_test table.');
         if ($is_private) {
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php
index bcfbfcdedd45..e34f61b43818 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php
@@ -44,7 +44,7 @@ function testContentAdminSort() {
     }
 
     // Test that the default sort by node.changed DESC actually fires properly.
-    $nodes_query = db_select('node', 'n')
+    $nodes_query = db_select('node_field_data', 'n')
       ->fields('n', array('nid'))
       ->orderBy('changed', 'DESC')
       ->execute()
@@ -59,7 +59,7 @@ function testContentAdminSort() {
 
     // Compare the rendered HTML node list to a query for the nodes ordered by
     // title to account for possible database-dependent sort order.
-    $nodes_query = db_select('node', 'n')
+    $nodes_query = db_select('node_field_data', 'n')
       ->fields('n', array('nid'))
       ->orderBy('title')
       ->execute()
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
index 92e181c6ef51..ee1e5addb615 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeBlockFunctionalTest.php
@@ -74,13 +74,13 @@ public function testRecentNodeBlock() {
     $node3 = $this->drupalCreateNode($default_settings);
 
     // Change the changed time for node so that we can test ordering.
-    db_update('node')
+    db_update('node_field_data')
       ->fields(array(
         'changed' => $node1->changed + 100,
       ))
       ->condition('nid', $node2->nid)
       ->execute();
-    db_update('node')
+    db_update('node_field_data')
       ->fields(array(
         'changed' => $node1->changed + 200,
       ))
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
index 02064600c54e..18c879f6283c 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeFieldMultilingualTestCase.php
@@ -138,4 +138,5 @@ function testMultilingualDisplaySettings() {
     ));
     $this->assertEqual(current($body), $node->body['en'][0]['value'], 'Node body found.');
   }
+
 }
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionPermissionsTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionPermissionsTest.php
index dfdccdfbe14d..6898bc644f68 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionPermissionsTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionPermissionsTest.php
@@ -98,7 +98,7 @@ function testNodeRevisionAccessAnyType() {
 
     foreach ($permutations as $case) {
       // Skip this test if there are no revisions for the node.
-      if (!($revision->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid', array(':nid' => $revision->nid))->fetchField() == 1 || $case['op'] == 'update' || $case['op'] == 'delete'))) {
+      if (!($revision->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid', array(':nid' => $revision->nid))->fetchField() == 1 || $case['op'] == 'update' || $case['op'] == 'delete'))) {
         if (!empty($case['account']->is_admin) || user_access($this->map[$case['op']], $case['account'])) {
           $this->assertTrue(_node_revision_access($revision, $case['op'], $case['account']), "{$this->map[$case['op']]} granted.");
         }
@@ -144,7 +144,7 @@ function testNodeRevisionAccessPerType() {
     $permutations = $this->generatePermutations($parameters);
     foreach ($permutations as $case) {
       // Skip this test if there are no revisions for the node.
-      if (!($revision->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid', array(':nid' => $revision->nid))->fetchField() == 1 || $case['op'] == 'update' || $case['op'] == 'delete'))) {
+      if (!($revision->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid', array(':nid' => $revision->nid))->fetchField() == 1 || $case['op'] == 'update' || $case['op'] == 'delete'))) {
         if (!empty($case['account']->is_admin) || user_access($this->type_map[$case['op']], $case['account'])) {
           $this->assertTrue(_node_revision_access($revision, $case['op'], $case['account']), "{$this->type_map[$case['op']]} granted.");
         }
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsAllTestCase.php b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsAllTestCase.php
index 746915ec87db..67cf0b57fc10 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsAllTestCase.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsAllTestCase.php
@@ -134,17 +134,17 @@ function testRevisions() {
         '%title' => $nodes[1]->title,
       )),
       'Revision deleted.');
-    $this->assertTrue(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid and vid = :vid',
+    $this->assertTrue(db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid and vid = :vid',
       array(':nid' => $node->nid, ':vid' => $nodes[1]->vid))->fetchField() == 0,
       'Revision not found.');
 
     // Set the revision timestamp to an older date to make sure that the
     // confirmation message correctly displays the stored revision date.
     $old_revision_date = REQUEST_TIME - 86400;
-    db_update('node_revision')
+    db_update('node_field_revision')
       ->condition('vid', $nodes[2]->vid)
       ->fields(array(
-        'timestamp' => $old_revision_date,
+        'revision_timestamp' => $old_revision_date,
       ))
       ->execute();
     $this->drupalPost("node/$node->nid/revisions/{$nodes[2]->vid}/revert", array(), t('Revert'));
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php
index 27e49cd7879a..9415b6b19c97 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php
@@ -114,15 +114,15 @@ function testRevisions() {
     $this->assertRaw(t('Revision from %revision-date of @type %title has been deleted.',
                         array('%revision-date' => format_date($nodes[1]->revision_timestamp),
                               '@type' => 'Basic page', '%title' => $nodes[1]->label())), 'Revision deleted.');
-    $this->assertTrue(db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid and vid = :vid', array(':nid' => $node->nid, ':vid' => $nodes[1]->vid))->fetchField() == 0, 'Revision not found.');
+    $this->assertTrue(db_query('SELECT COUNT(vid) FROM {node_field_revision} WHERE nid = :nid and vid = :vid', array(':nid' => $node->nid, ':vid' => $nodes[1]->vid))->fetchField() == 0, 'Revision not found.');
 
     // Set the revision timestamp to an older date to make sure that the
     // confirmation message correctly displays the stored revision date.
     $old_revision_date = REQUEST_TIME - 86400;
-    db_update('node_revision')
+    db_update('node_field_revision')
       ->condition('vid', $nodes[2]->vid)
       ->fields(array(
-        'timestamp' => $old_revision_date,
+        'revision_timestamp' => $old_revision_date,
       ))
       ->execute();
     $this->drupalPost("node/$node->nid/revisions/{$nodes[2]->vid}/revert", array(), t('Revert'));
diff --git a/core/modules/node/lib/Drupal/node/Tests/Views/FieldTypeTest.php b/core/modules/node/lib/Drupal/node/Tests/Views/FieldTypeTest.php
index 3b92fb97d8c9..17bcea539273 100644
--- a/core/modules/node/lib/Drupal/node/Tests/Views/FieldTypeTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/Views/FieldTypeTest.php
@@ -31,11 +31,11 @@ public function testFieldType() {
     $node = $this->drupalCreateNode();
     $expected_result[] = array(
       'nid' => $node->id(),
-      'node_type' => $node->bundle(),
+      'node_field_data_type' => $node->bundle(),
     );
     $column_map = array(
       'nid' => 'nid',
-      'node_type' => 'node_type',
+      'node_field_data_type' => 'node_field_data_type',
     );
 
     $view = views_get_view('test_field_type');
diff --git a/core/modules/node/lib/Drupal/node/Tests/Views/FilterUidRevisionTest.php b/core/modules/node/lib/Drupal/node/Tests/Views/FilterUidRevisionTest.php
index c132c48a2695..375bd329ef1f 100644
--- a/core/modules/node/lib/Drupal/node/Tests/Views/FilterUidRevisionTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/Views/FilterUidRevisionTest.php
@@ -41,7 +41,7 @@ public function testFilter() {
     $expected_result[] = array('nid' => $node->id());
     // Create one node of which an additional revision author will be the
     // author.
-    $node = $this->drupalCreateNode(array('uid' => $no_author->id()));
+    $node = $this->drupalCreateNode(array('revision_uid' => $no_author->id()));
     $expected_result[] = array('nid' => $node->id());
     $revision = clone $node;
     // Force to add a new revision.
diff --git a/core/modules/node/lib/Drupal/node/Tests/Views/RevisionRelationships.php b/core/modules/node/lib/Drupal/node/Tests/Views/RevisionRelationships.php
index deea0c5521b1..9ffc781e8586 100644
--- a/core/modules/node/lib/Drupal/node/Tests/Views/RevisionRelationships.php
+++ b/core/modules/node/lib/Drupal/node/Tests/Views/RevisionRelationships.php
@@ -53,8 +53,8 @@ public function testNodeRevisionRelationship() {
     $node_revision->save();
     $column_map = array(
       'vid' => 'vid',
-      'node_revision_nid' => 'node_revision_nid',
-      'node_node_revision_nid' => 'node_node_revision_nid',
+      'node_field_revision_nid' => 'node_field_revision_nid',
+      'node_node_field_revision_nid' => 'node_node_field_revision_nid',
     );
 
     // Here should be two rows.
@@ -63,13 +63,13 @@ public function testNodeRevisionRelationship() {
     $resultset_nid = array(
       array(
         'vid' => '1',
-        'node_revision_nid' => '1',
-        'node_node_revision_nid' => '1',
+        'node_field_revision_nid' => '1',
+        'node_node_field_revision_nid' => '1',
       ),
       array(
         'vid' => '2',
-        'node_revision_nid' => '1',
-        'node_node_revision_nid' => '1',
+        'node_field_revision_nid' => '1',
+        'node_node_field_revision_nid' => '1',
       ),
     );
     $this->assertIdenticalResultset($view_nid, $resultset_nid, $column_map);
@@ -80,8 +80,8 @@ public function testNodeRevisionRelationship() {
     $resultset_vid = array(
       array(
         'vid' => '2',
-        'node_revision_nid' => '1',
-        'node_node_revision_nid' => '1',
+        'node_field_revision_nid' => '1',
+        'node_node_field_revision_nid' => '1',
       ),
     );
     $this->assertIdenticalResultset($view_vid, $resultset_vid, $column_map);
diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc
index 3b05a805e10a..69b6b0a07a9e 100644
--- a/core/modules/node/node.admin.inc
+++ b/core/modules/node/node.admin.inc
@@ -277,14 +277,17 @@ function node_filter_form_submit($form, &$form_state) {
  * @param array $updates
  *   Array of key/value pairs with node field names and the value to update that
  *   field to.
+ * @param string $langcode
+ *   (optional) The language updates should be applied to. If none is specified
+ *   all available languages are processed.
  */
-function node_mass_update($nodes, $updates) {
+function node_mass_update($nodes, $updates, $langcode = NULL) {
   // We use batch processing to prevent timeout when updating a large number
   // of nodes.
   if (count($nodes) > 10) {
     $batch = array(
       'operations' => array(
-        array('_node_mass_update_batch_process', array($nodes, $updates))
+        array('_node_mass_update_batch_process', array($nodes, $updates, $langcode))
       ),
       'finished' => '_node_mass_update_batch_finished',
       'title' => t('Processing'),
@@ -300,7 +303,7 @@ function node_mass_update($nodes, $updates) {
   }
   else {
     foreach ($nodes as $nid) {
-      _node_mass_update_helper($nid, $updates);
+      _node_mass_update_helper($nid, $updates, $langcode);
     }
     drupal_set_message(t('The update has been performed.'));
   }
@@ -313,18 +316,24 @@ function node_mass_update($nodes, $updates) {
  *   ID of node to update.
  * @param $updates
  *   Associative array of updates.
+ * @param string $langcode
+ *   (optional) The language updates should be applied to. If none is specified
+ *   all available languages are processed.
  *
  * @return object
  *   An updated node object.
  *
  * @see node_mass_update()
  */
-function _node_mass_update_helper($nid, $updates) {
+function _node_mass_update_helper($nid, $updates, $langcode = NULL) {
   $node = node_load($nid, TRUE);
+  $langcodes = isset($langcode) ? array($langcode) : array_keys($node->getTranslationLanguages());
   // For efficiency manually save the original node before applying any changes.
   $node->original = clone $node;
-  foreach ($updates as $name => $value) {
-    $node->$name = $value;
+  foreach ($langcodes as $langcode) {
+    foreach ($updates as $name => $value) {
+      $node->getTranslation($langcode, FALSE)->$name = $value;
+    }
   }
   $node->save();
   return $node;
@@ -488,7 +497,7 @@ function node_admin_nodes() {
   }
   $header['operations'] = array('data' => t('Operations'));
 
-  $query = db_select('node', 'n')
+  $query = db_select('node_field_data', 'n')
     ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
     ->extend('Drupal\Core\Database\Query\TableSortExtender');
   node_build_filter_query($query);
@@ -497,7 +506,7 @@ function node_admin_nodes() {
     // If the user is able to view their own unpublished nodes, allow them
     // to see these in addition to published nodes. Check that they actually
     // have some unpublished nodes to view before adding the condition.
-    if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT nid FROM {node} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => 0))->fetchCol()) {
+    if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT DISTINCT nid FROM {node_field_data} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => 0))->fetchCol()) {
       $query->condition(db_or()
         ->condition('n.status', 1)
         ->condition('n.nid', $own_unpublished, 'IN')
@@ -509,7 +518,8 @@ function node_admin_nodes() {
     }
   }
   $nids = $query
-    ->fields('n',array('nid'))
+    ->distinct()
+    ->fields('n', array('nid'))
     ->limit(50)
     ->orderByHeader($header)
     ->addTag('node_access')
@@ -569,7 +579,7 @@ function node_admin_nodes() {
         'query' => $destination,
       );
     }
-    if (module_invoke('translation_entity', 'enabled', 'node', $node->bundle())) {
+    if ($node->isTranslatable()) {
       $operations['translate'] = array(
         'title' => t('Translate'),
         'href' => 'node/' . $node->nid . '/translations',
@@ -656,14 +666,14 @@ function node_admin_nodes_submit($form, &$form_state) {
  */
 function node_multiple_delete_confirm($form, &$form_state, $nodes) {
   $form['nodes'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
+  $node_entities = node_load_multiple(array_keys($nodes));
   // array_filter returns only elements with TRUE values
   foreach ($nodes as $nid => $value) {
-    $title = db_query('SELECT title FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchField();
     $form['nodes'][$nid] = array(
       '#type' => 'hidden',
       '#value' => $nid,
       '#prefix' => '<li>',
-      '#suffix' => check_plain($title) . "</li>\n",
+      '#suffix' => check_plain($node_entities[$nid]->label()) . "</li>\n",
     );
   }
   $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index 67cd0c323614..a4cc1550d44c 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -29,7 +29,7 @@ function node_schema() {
       // Defaults to NULL in order to avoid a brief period of potential
       // deadlocks on the index.
       'vid' => array(
-        'description' => 'The current {node_revision}.vid version identifier.',
+        'description' => 'The current {node_field_revision}.vid version identifier.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => FALSE,
@@ -49,6 +49,76 @@ function node_schema() {
         'not null' => TRUE,
         'default' => '',
       ),
+      // @todo Remove the following columns when removing the legacy Content
+      //   Translation module. See http://drupal.org/node/1952062.
+      'tnid' => array(
+        'description' => 'The translation set ID for this node, which equals the node ID of the source post in each set.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'translate' => array(
+        'description' => 'A boolean indicating whether this translation page needs to be updated.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'indexes' => array(
+      'node_type' => array(array('type', 4)),
+      'tnid' => array('tnid'),
+      'translate' => array('translate'),
+    ),
+    'unique keys' => array(
+      'vid' => array('vid'),
+      'uuid' => array('uuid'),
+    ),
+    'foreign keys' => array(
+      'node_revision' => array(
+        'table' => 'node_field_revision',
+        'columns' => array('vid' => 'vid'),
+      ),
+    ),
+    'primary key' => array('nid'),
+  );
+
+  // Node field storage.
+  $schema['node_field_data'] = array(
+    'description' => 'Base table for node properties.',
+    'fields' => array(
+      'nid' => array(
+        'description' => 'The primary identifier for a node.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'vid' => array(
+        'description' => 'The current {node_field_revision}.vid version identifier.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'type' => array(
+        'description' => 'The {node_type}.type of this node.',
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'langcode' => array(
+        'description' => 'The {language}.langcode of these node property values.',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'default_langcode' => array(
+        'description' => 'Boolean indicating whether the property values are in the {language}.langcode of this node.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
       'title' => array(
         'description' => 'The title of this node, always treated as non-markup plain text.',
         'type' => 'varchar',
@@ -64,236 +134,256 @@ function node_schema() {
         'default' => 0,
       ),
       'status' => array(
-        'description' => 'Boolean indicating whether the node is published (visible to non-administrators).',
+        'description' => 'Boolean indicating whether the node translation is published (visible to non-administrators).',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 1,
       ),
       'created' => array(
-        'description' => 'The Unix timestamp when the node was created.',
+        'description' => 'The Unix timestamp when the node translation was created.',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
       ),
       'changed' => array(
-        'description' => 'The Unix timestamp when the node was most recently saved.',
+        'description' => 'The Unix timestamp when the node translation was most recently saved.',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
       ),
       'comment' => array(
-        'description' => 'Whether comments are allowed on this node: 0 = no, 1 = closed (read only), 2 = open (read/write).',
+        'description' => 'Whether comments are allowed on this node translation: 0 = no, 1 = closed (read only), 2 = open (read/write).',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
       ),
       'promote' => array(
-        'description' => 'Boolean indicating whether the node should be displayed on the front page.',
+        'description' => 'Boolean indicating whether the node translation should be displayed on the front page.',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
       ),
       'sticky' => array(
-        'description' => 'Boolean indicating whether the node should be displayed at the top of lists in which it appears.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'tnid' => array(
-        'description' => 'The translation set id for this node, which equals the node id of the source post in each set.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'translate' => array(
-        'description' => 'A boolean indicating whether this translation page needs to be updated.',
+        'description' => 'Boolean indicating whether the node translation should be displayed at the top of lists in which it appears.',
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
       ),
     ),
     'indexes' => array(
-      'node_changed'        => array('changed'),
-      'node_created'        => array('created'),
-      'node_frontpage'      => array('promote', 'status', 'sticky', 'created'),
-      'node_status_type'    => array('status', 'type', 'nid'),
-      'node_title_type'     => array('title', array('type', 4)),
-      'node_type'           => array(array('type', 4)),
-      'uid'                 => array('uid'),
-      'tnid'                => array('tnid'),
-      'translate'           => array('translate'),
-    ),
-    'unique keys' => array(
+      'node_changed' => array('changed'),
+      'node_created' => array('created'),
+      'node_default_langcode' => array('default_langcode'),
+      'node_langcode' => array('langcode'),
+      'node_frontpage' => array('promote', 'status', 'sticky', 'created'),
+      'node_status_type' => array('status', 'type', 'nid'),
+      'node_title_type' => array('title', array('type', 4)),
+      'node_type' => array(array('type', 4)),
+      'nid' => array('nid'),
       'vid' => array('vid'),
-      'uuid' => array('uuid'),
+      'uid' => array('uid'),
     ),
     'foreign keys' => array(
-      'node_revision' => array(
-        'table' => 'node_revision',
-        'columns' => array('vid' => 'vid'),
+      'node_base' => array(
+        'table' => 'node',
+        'columns' => array('nid' => 'nid'),
       ),
       'node_author' => array(
         'table' => 'users',
         'columns' => array('uid' => 'uid'),
       ),
     ),
-    'primary key' => array('nid'),
+    'primary key' => array('nid', 'vid', 'langcode'),
   );
 
-  $schema['node_access'] = array(
-    'description' => 'Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.',
+  $schema['node_field_revision'] = array(
+    'description' => 'Stores information about each saved version of a {node}.',
     'fields' => array(
       'nid' => array(
-        'description' => 'The {node}.nid this record affects.',
+        'description' => 'The {node} this version belongs to.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
-        'default' => 0,
+      ),
+      'vid' => array(
+        'description' => 'The primary identifier for this version.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
       ),
       'langcode' => array(
-        'description' => 'The {language}.langcode of this node.',
+        'description' => 'The {language}.langcode of this version.',
         'type' => 'varchar',
         'length' => 12,
         'not null' => TRUE,
         'default' => '',
       ),
-      'fallback' => array(
-        'description' => 'Boolean indicating whether this record should be used as a fallback if a language condition is not provided.',
+      'default_langcode' => array(
+        'description' => 'Boolean indicating whether the property values of this version are in the {language}.langcode of this node.',
         'type' => 'int',
-        'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 1,
       ),
-      'gid' => array(
-        'description' => "The grant ID a user must possess in the specified realm to gain this row's privileges on the node.",
+      'log' => array(
+        'description' => 'The log entry explaining the changes in this version.',
+        'type' => 'text',
+        'not null' => FALSE,
+        'size' => 'big',
+      ),
+      'revision_timestamp' => array(
+        'description' => 'The Unix timestamp when the version was created.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'revision_uid' => array(
+        'description' => 'The {users}.uid that created this version.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 0,
       ),
-      'realm' => array(
-        'description' => 'The realm in which the user must possess the grant ID. Each node access node can define one or more realms.',
+      'title' => array(
+        'description' => 'The title of this version, always treated as non-markup plain text.',
         'type' => 'varchar',
         'length' => 255,
         'not null' => TRUE,
         'default' => '',
       ),
-      'grant_view' => array(
-        'description' => 'Boolean indicating whether a user with the realm/grant pair can view this node.',
+      'uid' => array(
+        'description' => 'The {users}.uid that created this node.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 0,
-        'size' => 'tiny',
       ),
-      'grant_update' => array(
-        'description' => 'Boolean indicating whether a user with the realm/grant pair can edit this node.',
+      'status' => array(
+        'description' => 'Boolean indicating whether the node (at the time of this revision) is published (visible to non-administrators).',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
+      'created' => array(
+        'description' => 'The Unix timestamp when the node was created.',
         'type' => 'int',
-        'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 0,
-        'size' => 'tiny',
       ),
-      'grant_delete' => array(
-        'description' => 'Boolean indicating whether a user with the realm/grant pair can delete this node.',
+      'changed' => array(
+        'description' => 'The Unix timestamp when the version was most recently saved.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'comment' => array(
+        'description' => 'Whether comments are allowed on this node (at the time of this revision): 0 = no, 1 = closed (read only), 2 = open (read/write).',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'promote' => array(
+        'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed on the front page.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'sticky' => array(
+        'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears.',
         'type' => 'int',
-        'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 0,
-        'size' => 'tiny',
       ),
     ),
-    'primary key' => array('nid', 'gid', 'realm', 'langcode'),
+    'indexes' => array(
+      'nid' => array('nid'),
+      'uid' => array('uid'),
+      'revision_uid' => array('revision_uid'),
+      'vid' => array('vid'),
+      'node_default_langcode' => array('default_langcode'),
+      'node_langcode' => array('langcode'),
+    ),
     'foreign keys' => array(
-      'affected_node' => array(
+      'versioned_node' => array(
         'table' => 'node',
         'columns' => array('nid' => 'nid'),
       ),
-     ),
+      'version_author' => array(
+        'table' => 'users',
+        'columns' => array('uid' => 'uid'),
+      ),
+    ),
+    'primary key' => array('nid', 'vid', 'langcode'),
   );
 
-  $schema['node_revision'] = array(
-    'description' => 'Stores information about each saved version of a {node}.',
+  $schema['node_access'] = array(
+    'description' => 'Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.',
     'fields' => array(
       'nid' => array(
-        'description' => 'The {node} this version belongs to.',
+        'description' => 'The {node}.nid this record affects.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 0,
       ),
-      'vid' => array(
-        'description' => 'The primary identifier for this version.',
-        'type' => 'serial',
+      'langcode' => array(
+        'description' => 'The {language}.langcode of this node.',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'fallback' => array(
+        'description' => 'Boolean indicating whether this record should be used as a fallback if a language condition is not provided.',
+        'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
+        'default' => 1,
       ),
-      'uid' => array(
-        'description' => 'The {users}.uid that created this version.',
+      'gid' => array(
+        'description' => "The grant ID a user must possess in the specified realm to gain this row's privileges on the node.",
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 0,
       ),
-      'title' => array(
-        'description' => 'The title of this version.',
+      'realm' => array(
+        'description' => 'The realm in which the user must possess the grant ID. Each node access node can define one or more realms.',
         'type' => 'varchar',
         'length' => 255,
         'not null' => TRUE,
         'default' => '',
       ),
-      'log' => array(
-        'description' => 'The log entry explaining the changes in this version.',
-        'type' => 'text',
-        'not null' => TRUE,
-        'size' => 'big',
-      ),
-      'timestamp' => array(
-        'description' => 'A Unix timestamp indicating when this version was created.',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'status' => array(
-        'description' => 'Boolean indicating whether the node (at the time of this revision) is published (visible to non-administrators).',
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 1,
-      ),
-      'comment' => array(
-        'description' => 'Whether comments are allowed on this node (at the time of this revision): 0 = no, 1 = closed (read only), 2 = open (read/write).',
+      'grant_view' => array(
+        'description' => 'Boolean indicating whether a user with the realm/grant pair can view this node.',
         'type' => 'int',
+        'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 0,
+        'size' => 'tiny',
       ),
-      'promote' => array(
-        'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed on the front page.',
+      'grant_update' => array(
+        'description' => 'Boolean indicating whether a user with the realm/grant pair can edit this node.',
         'type' => 'int',
+        'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 0,
+        'size' => 'tiny',
       ),
-      'sticky' => array(
-        'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears.',
+      'grant_delete' => array(
+        'description' => 'Boolean indicating whether a user with the realm/grant pair can delete this node.',
         'type' => 'int',
+        'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 0,
+        'size' => 'tiny',
       ),
     ),
-    'indexes' => array(
-      'nid' => array('nid'),
-      'uid' => array('uid'),
-    ),
-    'primary key' => array('vid'),
+    'primary key' => array('nid', 'gid', 'realm', 'langcode'),
     'foreign keys' => array(
-      'versioned_node' => array(
+      'affected_node' => array(
         'table' => 'node',
         'columns' => array('nid' => 'nid'),
       ),
-      'version_author' => array(
-        'table' => 'users',
-        'columns' => array('uid' => 'uid'),
-      ),
     ),
   );
 
@@ -377,7 +467,7 @@ function node_schema() {
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
-        'size' => 'tiny'
+        'size' => 'tiny',
       ),
       'orig_type' => array(
         'description' => 'The original machine-readable name of this node type. This may be different from the current type name if the locked field is 0.',
@@ -753,6 +843,309 @@ function node_update_8015() {
   db_add_primary_key('node_access', array('nid', 'gid', 'realm', 'langcode'));
 }
 
+/**
+ * Upgrade node schema to the standard entity SQL schema: schema definition.
+ */
+function _node_update_8016_schema() {
+  $schema = array();
+
+  $schema['node_field_data'] = array(
+    'description' => 'Base table for node properties.',
+    'fields' => array(
+      'nid' => array(
+        'description' => 'The primary identifier for a node.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'vid' => array(
+        'description' => 'The current {node_field_revision}.vid version identifier.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'type' => array(
+        'description' => 'The {node_type}.type of this node.',
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'langcode' => array(
+        'description' => 'The {language}.langcode of these node property values.',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'default_langcode' => array(
+        'description' => 'Boolean indicating whether the property values are in the {language}.langcode of this node.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
+      'title' => array(
+        'description' => 'The title of this node, always treated as non-markup plain text.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'uid' => array(
+        'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'status' => array(
+        'description' => 'Boolean indicating whether the node translation is published (visible to non-administrators).',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
+      'created' => array(
+        'description' => 'The Unix timestamp when the node translation was created.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'changed' => array(
+        'description' => 'The Unix timestamp when the node translation was most recently saved.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'comment' => array(
+        'description' => 'Whether comments are allowed on this node translation: 0 = no, 1 = closed (read only), 2 = open (read/write).',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'promote' => array(
+        'description' => 'Boolean indicating whether the node translation should be displayed on the front page.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'sticky' => array(
+        'description' => 'Boolean indicating whether the node translation should be displayed at the top of lists in which it appears.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'indexes' => array(
+      'node_changed' => array('changed'),
+      'node_created' => array('created'),
+      'node_frontpage' => array('promote', 'status', 'sticky', 'created'),
+      'node_status_type' => array('status', 'type', 'nid'),
+      'node_title_type' => array('title', array('type', 4)),
+      'node_type' => array(array('type', 4)),
+      'nid' => array('nid'),
+      'vid' => array('vid'),
+      'uid' => array('uid'),
+    ),
+    'foreign keys' => array(
+      'node_base' => array(
+        'table' => 'node',
+        'columns' => array('nid' => 'nid'),
+      ),
+      'node_author' => array(
+        'table' => 'users',
+        'columns' => array('uid' => 'uid'),
+      ),
+    ),
+    'primary key' => array('nid', 'vid', 'langcode'),
+  );
+
+  $schema['node_field_revision'] = array(
+    'description' => 'Stores information about each saved version of a {node}.',
+    'fields' => array(
+      'nid' => array(
+        'description' => 'The {node} this version belongs to.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'vid' => array(
+        'description' => 'The primary identifier for this version.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'langcode' => array(
+        'description' => 'The {language}.langcode of this version.',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'default_langcode' => array(
+        'description' => 'Boolean indicating whether the property values of this version are in the {language}.langcode of this node.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
+      'log' => array(
+        'description' => 'The log entry explaining the changes in this version.',
+        'type' => 'text',
+        'not null' => FALSE,
+        'size' => 'big',
+      ),
+      'revision_timestamp' => array(
+        'description' => 'The Unix timestamp when the version was created.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'revision_uid' => array(
+        'description' => 'The {users}.uid that created this version.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'title' => array(
+        'description' => 'The title of this version, always treated as non-markup plain text.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'uid' => array(
+        'description' => 'The {users}.uid that created this node.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'status' => array(
+        'description' => 'Boolean indicating whether the node (at the time of this revision) is published (visible to non-administrators).',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
+      'created' => array(
+        'description' => 'The Unix timestamp when the node was created.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'changed' => array(
+        'description' => 'The Unix timestamp when the version was most recently saved.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'comment' => array(
+        'description' => 'Whether comments are allowed on this node (at the time of this revision): 0 = no, 1 = closed (read only), 2 = open (read/write).',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'promote' => array(
+        'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed on the front page.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'sticky' => array(
+        'description' => 'Boolean indicating whether the node (at the time of this revision) should be displayed at the top of lists in which it appears.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'indexes' => array(
+      'nid' => array('nid'),
+      'uid' => array('uid'),
+      'revision_uid' => array('revision_uid'),
+      'vid' => array('vid'),
+    ),
+    'foreign keys' => array(
+      'versioned_node' => array(
+        'table' => 'node',
+        'columns' => array('nid' => 'nid'),
+      ),
+      'version_author' => array(
+        'table' => 'users',
+        'columns' => array('uid' => 'uid'),
+      ),
+    ),
+    'primary key' => array('nid', 'vid', 'langcode'),
+  );
+
+  return $schema;
+}
+
+/**
+ * Upgrade node schema to the standard entity SQL schema: create new tables.
+ */
+function node_update_8016() {
+  foreach (_node_update_8016_schema() as $table => $table_schema) {
+    db_create_table($table, $table_schema);
+  }
+}
+
+/**
+ * Upgrade node schema to the standard entity SQL schema: migrate data.
+ */
+function node_update_8017(&$sandbox) {
+  if (!isset($sandbox['progress'])) {
+    // Initialize the batch status.
+    $sandbox['progress'] = 0;
+    $sandbox['max'] = db_query('SELECT COUNT(vid) FROM {node_revision}')->fetchField();
+  }
+
+  // Prepare the new records.
+  $queries = array();
+  $schema = _node_update_8016_schema();
+  $result = db_query_range('SELECT nr.*, nr.timestamp AS revision_timestamp, nr.uid as revision_uid, 1 AS default_langcode, n.langcode, n.vid = nr.vid AS default_revision, n.uid, n.changed, n.created, n.type FROM {node_revision} nr JOIN {node} n ON nr.nid = n.nid ORDER BY nr.nid ASC, nr.vid ASC', $sandbox['progress'], 50);
+
+  foreach ($result as $row) {
+    $sandbox['progress']++;
+    foreach ($schema as $table => $table_schema) {
+      // We need to store the data table record only when dealing with the
+      // default revision.
+      if ($row->default_revision || $table == 'node_field_revision') {
+        $fields = array_keys($table_schema['fields']);
+        $record = array();
+        foreach ($fields as $field) {
+          if (isset($row->{$field})) {
+            $record[$field] = $row->{$field};
+          }
+        }
+        if (!isset($queries[$table])) {
+          $queries[$table] = db_insert($table)->fields($fields);
+        }
+        $queries[$table]->values($record);
+      }
+    }
+  }
+
+  // Store the new records.
+  foreach ($queries as $query) {
+    $query->execute();
+  }
+
+  $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
+}
+
+/**
+ * Upgrade node schema to the standard entity SQL schema: delete old fields.
+ */
+function node_update_8018() {
+  $indexes = array('node_changed', 'node_created', 'node_frontpage', 'node_status_type', 'node_title_type', 'uid');
+  foreach ($indexes as $index) {
+    db_drop_index('node', $index);
+  }
+  $fields = array('title', 'uid', 'status', 'created', 'changed', 'comment', 'promote', 'sticky');
+  foreach ($fields as $field) {
+    db_drop_field('node', $field);
+  }
+}
+
 /**
  * @} End of "addtogroup updates-7.x-to-8.x"
  * The next series of updates should start at 9000.
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 6d7b1c969735..d41d96064f1c 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -975,6 +975,7 @@ function node_submit(EntityInterface $node) {
   // If a new revision is created, save the current user as revision author.
   if ($node->isNewRevision()) {
     $node->revision_uid = $user->uid;
+    $node->revision_timestamp = REQUEST_TIME;
   }
 
   $node->created = !empty($node->date) && $node->date instanceOf DrupalDateTime ? $node->date->getTimestamp() : REQUEST_TIME;
@@ -1327,7 +1328,7 @@ function node_search_execute($keys = NULL, $conditions = NULL) {
   $query = db_select('search_index', 'i', array('target' => 'slave'))
     ->extend('Drupal\search\SearchQuery')
     ->extend('Drupal\Core\Database\Query\PagerSelectExtender');
-  $query->join('node', 'n', 'n.nid = i.sid');
+  $query->join('node_field_data', 'n', 'n.nid = i.sid');
   $query
     ->condition('n.status', 1)
     ->addTag('node_access')
@@ -1428,7 +1429,8 @@ function node_user_cancel($edit, $account, $method) {
     case 'user_cancel_block_unpublish':
       // Unpublish nodes (current revisions).
       module_load_include('inc', 'node', 'node.admin');
-      $nodes = db_select('node', 'n')
+      $nodes = db_select('node_field_data', 'n')
+        ->distinct()
         ->fields('n', array('nid'))
         ->condition('uid', $account->uid)
         ->execute()
@@ -1439,14 +1441,15 @@ function node_user_cancel($edit, $account, $method) {
     case 'user_cancel_reassign':
       // Anonymize nodes (current revisions).
       module_load_include('inc', 'node', 'node.admin');
-      $nodes = db_select('node', 'n')
+      $nodes = db_select('node_field_data', 'n')
+        ->distinct()
         ->fields('n', array('nid'))
         ->condition('uid', $account->uid)
         ->execute()
         ->fetchCol();
       node_mass_update($nodes, array('uid' => 0));
       // Anonymize old revisions.
-      db_update('node_revision')
+      db_update('node_field_revision')
         ->fields(array('uid' => 0))
         ->condition('uid', $account->uid)
         ->execute();
@@ -1460,14 +1463,15 @@ function node_user_cancel($edit, $account, $method) {
 function node_user_predelete($account) {
   // Delete nodes (current revisions).
   // @todo Introduce node_mass_delete() or make node_mass_update() more flexible.
-  $nodes = db_select('node', 'n')
+  $nodes = db_select('node_field_data', 'n')
+    ->distinct()
     ->fields('n', array('nid'))
     ->condition('uid', $account->uid)
     ->execute()
     ->fetchCol();
   node_delete_multiple($nodes);
   // Delete old revisions.
-  $revisions = db_query('SELECT vid FROM {node_revision} WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol();
+  $revisions = db_query('SELECT DISTINCT vid FROM {node_field_revision} WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol();
   foreach ($revisions as $revision) {
     node_revision_delete($revision);
   }
@@ -1567,7 +1571,7 @@ function _node_revision_access(EntityInterface $node, $op = 'view', $account = N
     // different revisions so there is no need for a separate database check.
     // Also, if you try to revert to or delete the default revision, that's
     // not good.
-    if ($node->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField() == 1 || $op == 'update' || $op == 'delete')) {
+    if ($node->isDefaultRevision() && (db_query('SELECT COUNT(*) FROM {node_field_revision} WHERE nid = :nid AND default_langcode = 1', array(':nid' => $node->nid))->fetchField() == 1 || $op == 'update' || $op == 'delete')) {
       $access[$cid] = FALSE;
     }
     elseif (user_access('administer nodes', $account)) {
@@ -1813,12 +1817,17 @@ function node_page_title(EntityInterface $node) {
  *
  * @param $nid
  *   The ID of a node.
+ * @param string $langcode
+ *   (optional) The language the node has been last modified in. Defaults to the
+ *   node language.
  *
- * @return
+ * @return string
  *   A unix timestamp indicating the last time the node was changed.
  */
-function node_last_changed($nid) {
-  return db_query('SELECT changed FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetch()->changed;
+function node_last_changed($nid, $langcode = NULL) {
+  $language_clause = isset($langcode) ? 'langcode = :langcode' : 'default_langcode = 1';
+  $result = db_query('SELECT changed FROM {node_field_data} WHERE nid = :nid AND ' . $language_clause, array(':nid' => $nid, ':langcode' => $langcode))->fetch();
+  return is_object($result) ? $result->changed : FALSE;
 }
 
 /**
@@ -1832,7 +1841,7 @@ function node_last_changed($nid) {
  */
 function node_revision_list(EntityInterface $node) {
   $revisions = array();
-  $result = db_query('SELECT r.vid, r.title, r.log, r.uid, n.vid AS current_vid, r.timestamp, u.name FROM {node_revision} r LEFT JOIN {node} n ON n.vid = r.vid INNER JOIN {users} u ON u.uid = r.uid WHERE r.nid = :nid ORDER BY r.vid DESC', array(':nid' => $node->nid));
+  $result = db_query('SELECT nfr.vid, nfr.title, nfr.log, nfr.revision_uid AS uid, n.vid AS current_vid, nfr.revision_timestamp, u.name FROM {node_field_revision} nfr LEFT JOIN {node} n ON n.vid = nfr.vid INNER JOIN {users} u ON u.uid = nfr.revision_uid WHERE nfr.nid = :nid AND nfr.default_langcode = 1 ORDER BY nfr.vid DESC', array(':nid' => $node->nid));
   foreach ($result as $revision) {
     $revisions[$revision->vid] = $revision;
   }
@@ -1851,13 +1860,13 @@ function node_revision_list(EntityInterface $node) {
  *   visible to the current user.
  */
 function node_get_recent($number = 10) {
-  $query = db_select('node', 'n');
+  $query = db_select('node_field_data', 'n');
 
   if (!user_access('bypass node access')) {
     // If the user is able to view their own unpublished nodes, allow them
     // to see these in addition to published nodes. Check that they actually
     // have some unpublished nodes to view before adding the condition.
-    if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT nid FROM {node} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => NODE_NOT_PUBLISHED))->fetchCol()) {
+    if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT DISTINCT nid FROM {node_field_data} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => NODE_NOT_PUBLISHED))->fetchCol()) {
       $query->condition(db_or()
         ->condition('n.status', NODE_PUBLISHED)
         ->condition('n.nid', $own_unpublished, 'IN')
@@ -1869,6 +1878,7 @@ function node_get_recent($number = 10) {
     }
   }
   $nids = $query
+    ->distinct()
     ->fields('n', array('nid'))
     ->orderBy('n.changed', 'DESC')
     ->range(0, $number)
@@ -2044,8 +2054,9 @@ function node_feed($nids = FALSE, $channel = array()) {
   $rss_config = config('system.rss');
 
   if ($nids === FALSE) {
-    $nids = db_select('node', 'n')
-      ->fields('n', array('nid', 'created'))
+    $nids = db_select('node_field_data', 'n')
+      ->distinct()
+      ->fields('n', array('nid'))
       ->condition('n.promote', 1)
       ->condition('n.status', 1)
       ->orderBy('n.created', 'DESC')
@@ -2766,7 +2777,7 @@ function node_query_node_access_alter(AlterableInterface $query) {
       if (!($table_info instanceof SelectInterface)) {
         $table = $table_info['table'];
         // If the node table is in the query, it wins immediately.
-        if ($table == 'node') {
+        if ($table == 'node' || $table == 'node_field_data') {
           $base_table = $table;
           break;
         }
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index 863babd36579..9aa4982f736a 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -265,13 +265,13 @@ function node_revision_overview($node) {
     $row = array();
     $type = $node->type;
     if ($revision->current_vid > 0) {
-      $row[] = array('data' => t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'short'), "node/$node->nid"), '!username' => theme('username', array('account' => $revision))))
+      $row[] = array('data' => t('!date by !username', array('!date' => l(format_date($revision->revision_timestamp, 'short'), "node/$node->nid"), '!username' => theme('username', array('account' => $revision))))
                                . (($revision->log != '') ? '<p class="revision-log">' . filter_xss($revision->log) . '</p>' : ''),
                      'class' => array('revision-current'));
       $row[] = array('data' => drupal_placeholder(t('current revision')), 'class' => array('revision-current'));
     }
     else {
-      $row[] = t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'short'), "node/$node->nid/revisions/$revision->vid/view"), '!username' => theme('username', array('account' => $revision))))
+      $row[] = t('!date by !username', array('!date' => l(format_date($revision->revision_timestamp, 'short'), "node/$node->nid/revisions/$revision->vid/view"), '!username' => theme('username', array('account' => $revision))))
                . (($revision->log != '') ? '<p class="revision-log">' . filter_xss($revision->log) . '</p>' : '');
       if ($revert_permission) {
         $links['revert'] = array(
@@ -379,7 +379,7 @@ function node_revision_delete_confirm_submit($form, &$form_state) {
   watchdog('content', '@type: deleted %title revision %revision.', array('@type' => $node_revision->type, '%title' => $node_revision->label(), '%revision' => $node_revision->vid));
   drupal_set_message(t('Revision from %revision-date of @type %title has been deleted.', array('%revision-date' => format_date($node_revision->revision_timestamp), '@type' => node_get_type_label($node_revision), '%title' => $node_revision->label())));
   $form_state['redirect'] = 'node/' . $node_revision->nid;
-  if (db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid', array(':nid' => $node_revision->nid))->fetchField() > 1) {
+  if (db_query('SELECT COUNT(DISTINCT vid) FROM {node_field_revision} WHERE nid = :nid', array(':nid' => $node_revision->nid))->fetchField() > 1) {
     $form_state['redirect'] .= '/revisions';
   }
 }
diff --git a/core/modules/node/node.views.inc b/core/modules/node/node.views.inc
index 6f3320f636f0..dbea61b1eef9 100644
--- a/core/modules/node/node.views.inc
+++ b/core/modules/node/node.views.inc
@@ -32,6 +32,14 @@ function node_views_data() {
   $data['node']['table']['entity type'] = 'node';
   $data['node']['table']['wizard_id'] = 'node';
 
+  $data['node_field_data']['table']['group'] = t('Content');
+  $data['node_field_data']['table']['entity type'] = 'node';
+  $data['node_field_data']['table']['join']['node'] = array(
+    'type' => 'INNER',
+    'left_field' => 'nid',
+    'field' => 'nid',
+  );
+
   $data['node']['nid'] = array(
     'title' => t('Nid'),
     'help' => t('The node ID.'),
@@ -53,7 +61,7 @@ function node_views_data() {
   );
 
   // This definition has more items in it than it needs to as an example.
-  $data['node']['title'] = array(
+  $data['node_field_data']['title'] = array(
     'title' => t('Title'),
     'help' => t('The content title.'),
     'field' => array(
@@ -75,7 +83,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['created'] = array(
+  $data['node_field_data']['created'] = array(
     'title' => t('Post date'),
     'help' => t('The date the content was posted.'),
     'field' => array(
@@ -89,7 +97,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['changed'] = array(
+  $data['node_field_data']['changed'] = array(
     'title' => t('Updated date'),
     'help' => t('The date the content was last updated.'),
     'field' => array(
@@ -103,7 +111,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['type'] = array(
+  $data['node_field_data']['type'] = array(
     'title' => t('Type'),
     'help' => t('The content type (for example, "blog entry", "forum post", "story", etc).'),
     'field' => array(
@@ -120,7 +128,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['status'] = array(
+  $data['node_field_data']['status'] = array(
     'title' => t('Published status'),
     'help' => t('Whether or not the content is published.'),
     'field' => array(
@@ -141,7 +149,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['status_extra'] = array(
+  $data['node_field_data']['status_extra'] = array(
     'title' => t('Published status or admin user'),
     'help' => t('Filters out unpublished content if the current user cannot view it.'),
     'filter' => array(
@@ -151,7 +159,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['promote'] = array(
+  $data['node_field_data']['promote'] = array(
     'title' => t('Promoted to front page status'),
     'help' => t('Whether or not the content is promoted to the front page.'),
     'field' => array(
@@ -170,7 +178,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['sticky'] = array(
+  $data['node_field_data']['sticky'] = array(
     'title' => t('Sticky status'),
     'help' => t('Whether or not the content is sticky.'),
     'field' => array(
@@ -261,7 +269,7 @@ function node_views_data() {
 
   // Bogus fields for aliasing purposes.
 
-  $data['node']['created_fulldate'] = array(
+  $data['node_field_data']['created_fulldate'] = array(
     'title' => t('Created date'),
     'help' => t('Date in the form of CCYYMMDD.'),
     'argument' => array(
@@ -270,7 +278,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['date_year_month'] = array(
+  $data['node_field_data']['date_year_month'] = array(
     'title' => t('Created year + month'),
     'help' => t('Date in the form of YYYYMM.'),
     'argument' => array(
@@ -279,7 +287,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['created_year'] = array(
+  $data['node_field_data']['created_year'] = array(
     'title' => t('Created year'),
     'help' => t('Date in the form of YYYY.'),
     'argument' => array(
@@ -288,7 +296,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['created_month'] = array(
+  $data['node_field_data']['created_month'] = array(
     'title' => t('Created month'),
     'help' => t('Date in the form of MM (01 - 12).'),
     'argument' => array(
@@ -297,7 +305,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['created_day'] = array(
+  $data['node_field_data']['created_day'] = array(
     'title' => t('Created day'),
     'help' => t('Date in the form of DD (01 - 31).'),
     'argument' => array(
@@ -306,7 +314,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['created_week'] = array(
+  $data['node_field_data']['created_week'] = array(
     'title' => t('Created week'),
     'help' => t('Date in the form of WW (01 - 53).'),
     'argument' => array(
@@ -315,7 +323,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['changed_fulldate'] = array(
+  $data['node_field_data']['changed_fulldate'] = array(
     'title' => t('Updated date'),
     'help' => t('Date in the form of CCYYMMDD.'),
     'argument' => array(
@@ -324,7 +332,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['changed_year_month'] = array(
+  $data['node_field_data']['changed_year_month'] = array(
     'title' => t('Updated year + month'),
     'help' => t('Date in the form of YYYYMM.'),
     'argument' => array(
@@ -333,7 +341,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['changed_year'] = array(
+  $data['node_field_data']['changed_year'] = array(
     'title' => t('Updated year'),
     'help' => t('Date in the form of YYYY.'),
     'argument' => array(
@@ -342,7 +350,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['changed_month'] = array(
+  $data['node_field_data']['changed_month'] = array(
     'title' => t('Updated month'),
     'help' => t('Date in the form of MM (01 - 12).'),
     'argument' => array(
@@ -351,7 +359,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['changed_day'] = array(
+  $data['node_field_data']['changed_day'] = array(
     'title' => t('Updated day'),
     'help' => t('Date in the form of DD (01 - 31).'),
     'argument' => array(
@@ -360,7 +368,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['changed_week'] = array(
+  $data['node_field_data']['changed_week'] = array(
     'title' => t('Updated week'),
     'help' => t('Date in the form of WW (01 - 53).'),
     'argument' => array(
@@ -369,7 +377,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['uid'] = array(
+  $data['node_field_data']['uid'] = array(
     'title' => t('Author uid'),
     'help' => t('The user authoring the content. If you need more fields than the uid add the content: author relationship'),
     'relationship' => array(
@@ -399,7 +407,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node']['uid_revision'] = array(
+  $data['node_field_data']['uid_revision'] = array(
     'title' => t('User has a revision'),
     'help' => t('All nodes where a certain user has a revision'),
     'real field' => 'nid',
@@ -411,15 +419,15 @@ function node_views_data() {
     ),
   );
 
-  $data['node_revision']['table']['entity type'] = 'node';
+  $data['node_field_revision']['table']['entity type'] = 'node';
   // Define the base group of this table. Fields that don't have a group defined
   // will go into this field by default.
-  $data['node_revision']['table']['group']  = t('Content revision');
-  $data['node_revision']['table']['wizard_id'] = 'node_revision';
+  $data['node_field_revision']['table']['group']  = t('Content revision');
+  $data['node_field_revision']['table']['wizard_id'] = 'node_revision';
 
 
   // Advertise this table as a possible base table.
-  $data['node_revision']['table']['base'] = array(
+  $data['node_field_revision']['table']['base'] = array(
     'field' => 'vid',
     'title' => t('Content revision'),
     'help' => t('Content revision is a history of changes to content.'),
@@ -429,14 +437,14 @@ function node_views_data() {
   );
 
   // For other base tables, explain how we join.
-  $data['node_revision']['table']['join'] = array(
+  $data['node_field_revision']['table']['join'] = array(
     'node' => array(
       'left_field' => 'vid',
       'field' => 'vid',
     ),
   );
 
-  $data['node_revision']['uid'] = array(
+  $data['node_field_revision']['revision_uid'] = array(
     'title' => t('User'),
     'help' => t('Relate a content revision to the user who created the revision.'),
     'relationship' => array(
@@ -447,7 +455,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node_revision']['nid'] = array(
+  $data['node_field_revision']['nid'] = array(
     'title' => t('Nid'),
     'help' => t('The revision NID of the content revision.'),
     'field' => array(
@@ -472,7 +480,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node_revision']['vid'] = array(
+  $data['node_field_revision']['vid'] = array(
     'title' => t('Vid'),
     'help' => t('The revision ID of the content revision.'),
     'field' => array(
@@ -497,7 +505,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node_revision']['status'] = array(
+  $data['node_field_revision']['status'] = array(
     'title' => t('Published'),
     'help' => t('Whether or not the content is published.'),
     'field' => array(
@@ -518,7 +526,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node_revision']['title'] = array(
+  $data['node_field_revision']['title'] = array(
     'title' => t('Title'),
     'help' => t('The content title.'),
     'field' => array(
@@ -536,7 +544,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node_revision']['log'] = array(
+  $data['node_field_revision']['log'] = array(
     'title' => t('Log message'),
     'help' => t('The log message entered when the revision was created.'),
     'field' => array(
@@ -547,7 +555,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node_revision']['timestamp'] = array(
+  $data['node_field_revision']['changed'] = array(
     'title' => t('Updated date'),
     'help' => t('The date the node was last updated.'),
     'field' => array(
@@ -561,7 +569,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node_revision']['link_to_revision'] = array(
+  $data['node_field_revision']['link_to_revision'] = array(
     'field' => array(
       'title' => t('Link to revision'),
       'help' => t('Provide a simple link to the revision.'),
@@ -570,7 +578,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node_revision']['revert_revision'] = array(
+  $data['node_field_revision']['revert_revision'] = array(
     'field' => array(
       'title' => t('Link to revert revision'),
       'help' => t('Provide a simple link to revert to the revision.'),
@@ -579,7 +587,7 @@ function node_views_data() {
     ),
   );
 
-  $data['node_revision']['delete_revision'] = array(
+  $data['node_field_revision']['delete_revision'] = array(
     'field' => array(
       'title' => t('Link to delete revision'),
       'help' => t('Provide a simple link to delete the content revision.'),
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_type.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_type.yml
index f1620dbb34c5..317ed915ddfb 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_type.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_field_type.yml
@@ -9,7 +9,7 @@ display:
         type:
           field: type
           id: type
-          table: node
+          table: node_field_data
     display_plugin: default
     display_title: Master
     id: default
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_filter_node_uid_revision.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_filter_node_uid_revision.yml
index 404304b937ec..f309a1b3c9a3 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_filter_node_uid_revision.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_filter_node_uid_revision.yml
@@ -29,7 +29,7 @@ display:
           is_grouped: '0'
           operator: in
           relationship: none
-          table: node
+          table: node_field_data
           value:
             - '1'
           plugin_id: node_uid_revision
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_nid.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_nid.yml
index 58e7e648d67f..09c8eab75af4 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_nid.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_nid.yml
@@ -1,5 +1,5 @@
 id: test_node_revision_nid
-base_table: node_revision
+base_table: node_field_revision
 core: 8
 display:
   default:
@@ -7,19 +7,19 @@ display:
       relationships:
         nid:
           id: nid
-          table: node_revision
+          table: node_field_revision
           field: nid
           required: true
           plugin_id: standard
       fields:
         vid:
           id: vid
-          table: node_revision
+          table: node_field_revision
           field: vid
           plugin_id: standard
         nid_1:
           id: nid_1
-          table: node_revision
+          table: node_field_revision
           field: nid
           plugin_id: standard
         nid:
@@ -31,7 +31,7 @@ display:
       arguments:
         nid:
           id: nid
-          table: node_revision
+          table: node_field_revision
           field: nid
           plugin_id: node_nid
     display_plugin: default
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_vid.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_vid.yml
index fe29d14b3368..553bfd2c2410 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_vid.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_revision_vid.yml
@@ -1,5 +1,5 @@
 id: test_node_revision_vid
-base_table: node_revision
+base_table: node_field_revision
 core: 8
 display:
   default:
@@ -7,19 +7,19 @@ display:
       relationships:
         vid:
           id: vid
-          table: node_revision
+          table: node_field_revision
           field: vid
           required: true
           plugin_id: standard
       fields:
         vid:
           id: vid
-          table: node_revision
+          table: node_field_revision
           field: vid
           plugin_id: standard
         nid_1:
           id: nid_1
-          table: node_revision
+          table: node_field_revision
           field: nid
           plugin_id: standard
         nid:
@@ -31,7 +31,7 @@ display:
       arguments:
         nid:
           id: nid
-          table: node_revision
+          table: node_field_revision
           field: nid
           plugin_id: node_nid
     display_plugin: default
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_view.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_view.yml
index 4b82a313e4ba..e56c2d93a368 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_view.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_node_view.yml
@@ -121,7 +121,7 @@ display:
       filters:
         status:
           value: '1'
-          table: node
+          table: node_field_data
           field: status
           id: status
           expose:
@@ -130,7 +130,7 @@ display:
       sorts:
         created:
           id: created
-          table: node
+          table: node_field_data
           field: created
           order: DESC
           relationship: none
@@ -148,7 +148,7 @@ display:
       arguments:
         type:
           id: type
-          table: node
+          table: node_field_data
           field: type
           relationship: none
           group_type: group
diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_status_extra.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_status_extra.yml
index 92d5f89b3147..094f8d415a13 100644
--- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_status_extra.yml
+++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_status_extra.yml
@@ -28,7 +28,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           relationship: none
           group_type: group
@@ -79,7 +79,7 @@ display:
       filters:
         status_extra:
           id: status_extra
-          table: node
+          table: node_field_data
           field: status_extra
           relationship: none
           group_type: group
@@ -116,7 +116,7 @@ display:
       sorts:
         nid:
           id: nid
-          table: node
+          table: node_field_data
           field: nid
           order: ASC
           plugin_id: standard
diff --git a/core/modules/search/search.api.php b/core/modules/search/search.api.php
index 3f30a4a77d82..3b7a986b3c9a 100644
--- a/core/modules/search/search.api.php
+++ b/core/modules/search/search.api.php
@@ -88,8 +88,8 @@ function hook_search_reset() {
  * @ingroup search
  */
 function hook_search_status() {
-  $total = db_query('SELECT COUNT(*) FROM {node} WHERE status = 1')->fetchField();
-  $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField();
+  $total = db_query('SELECT COUNT(DISTINCT nid) FROM {node_field_data} WHERE status = 1')->fetchField();
+  $remaining = db_query("SELECT COUNT(DISTINCT nid) FROM {node_field_data} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField();
   return array('remaining' => $remaining, 'total' => $total);
 }
 
@@ -175,7 +175,7 @@ function hook_search_execute($keys = NULL, $conditions = NULL) {
   $query = db_select('search_index', 'i', array('target' => 'slave'))
     ->extend('Drupal\search\SearchQuery')
     ->extend('Drupal\Core\Database\Query\PagerSelectExtender');
-  $query->join('node', 'n', 'n.nid = i.sid');
+  $query->join('node_field_data', 'n', 'n.nid = i.sid');
   $query
     ->condition('n.status', 1)
     ->addTag('node_access')
@@ -197,6 +197,9 @@ function hook_search_execute($keys = NULL, $conditions = NULL) {
 
   // Load results.
   $find = $query
+    // Add the language code of the indexed item to the result of the query,
+    // since the node will be rendered using the respective language.
+    ->fields('i', array('langcode'))
     ->limit(10)
     ->execute();
   $results = array();
@@ -219,7 +222,7 @@ function hook_search_execute($keys = NULL, $conditions = NULL) {
       'type' => check_plain(node_get_type_label($node)),
       'title' => $node->label($item->langcode),
       'user' => theme('username', array('account' => $node)),
-      'date' => $node->get('changed', $item->langcode),
+      'date' => $node->changed,
       'node' => $node,
       'extra' => $extra,
       'score' => $item->calculated_score,
diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index efaf03187813..9de229b0d106 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -631,10 +631,9 @@ function search_index($sid, $module, $text, $langcode) {
             if (preg_match('!(?:node|book)/(?:view/)?([0-9]+)!i', $path, $match)) {
               $linknid = $match[1];
               if ($linknid > 0) {
-                $node = db_query('SELECT title, nid, vid FROM {node} WHERE nid = :nid', array(':nid' => $linknid), array('target' => 'slave'))->fetchObject();
                 $link = TRUE;
-                // Do not use $node->label(), $node comes from the database.
-                $linktitle = $node->title;
+                $node = node_load($linknid);
+                $linktitle = $node->label();
               }
             }
           }
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
index 242bcd6089a5..92f230665d9f 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/Tests/DrupalUnitTestBaseTest.php
@@ -110,7 +110,7 @@ function testEnableModulesInstallContainer() {
     // Install Node module.
     $this->enableModules(array('field_sql_storage', 'field', 'node'));
 
-    $this->installSchema('node', array('node_type', 'node'));
+    $this->installSchema('node', array('node_type', 'node', 'node_field_data'));
     // Perform an entity query against node.
     $query = \Drupal::entityQuery('node');
     // Disable node access checks, since User module is not enabled.
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 760aeed93ba9..a75ade4ee9a6 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -275,11 +275,6 @@ protected function drupalCreateNode(array $settings = array()) {
     }
     $node->save();
 
-    // Small hack to link revisions to our test user.
-    db_update('node_revision')
-      ->fields(array('uid' => $node->uid))
-      ->condition('vid', $node->vid)
-      ->execute();
     return $node;
   }
 
diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module
index 7b1528161c46..89986c53e9a0 100644
--- a/core/modules/statistics/statistics.module
+++ b/core/modules/statistics/statistics.module
@@ -119,7 +119,7 @@ function statistics_cron() {
  */
 function statistics_title_list($dbfield, $dbrows) {
   if (in_array($dbfield, array('totalcount', 'daycount', 'timestamp'))) {
-    $query = db_select('node', 'n');
+    $query = db_select('node_field_data', 'n');
     $query->addTag('node_access');
     $query->join('node_counter', 's', 'n.nid = s.nid');
     $query->join('users', 'u', 'n.uid = u.uid');
@@ -129,6 +129,9 @@ function statistics_title_list($dbfield, $dbrows) {
       ->fields('u', array('uid', 'name'))
       ->condition($dbfield, 0, '<>')
       ->condition('n.status', 1)
+      // @todo This should be actually filtering on the desired node status
+      //   field language and just fall back to the default language.
+      ->condition('n.default_langcode', 1)
       ->orderBy($dbfield, 'DESC')
       ->range(0, $dbrows)
       ->execute();
diff --git a/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml b/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml
index 1a00c2540981..663d49cb942e 100644
--- a/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml
+++ b/core/modules/statistics/tests/modules/statistics_test_views/test_views/views.view.test_statistics_integration.yml
@@ -30,7 +30,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           label: ''
           alter:
@@ -213,7 +213,7 @@ display:
       filters:
         status:
           value: '1'
-          table: node
+          table: node_field_data
           field: status
           id: status
           expose:
@@ -222,7 +222,7 @@ display:
       sorts:
         created:
           id: created
-          table: node
+          table: node_field_data
           field: created
           order: DESC
   page_1:
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityBCDecoratorTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityBCDecoratorTest.php
index 892fd182479f..74c37be91bae 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityBCDecoratorTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityBCDecoratorTest.php
@@ -32,7 +32,7 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
     $this->installSchema('user', array('users_roles', 'users_data', 'role_permission'));
-    $this->installSchema('node', array('node', 'node_revision', 'node_type', 'node_access'));
+    $this->installSchema('node', array('node', 'node_field_data', 'node_field_revision', 'node_type', 'node_access'));
     $this->installSchema('comment', array('comment', 'node_comment_statistics'));
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php
index 0b7b200ea0a7..da9db4678990 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityCrudHookTest.php
@@ -44,7 +44,7 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
     $this->installSchema('user', array('users_roles', 'users_data'));
-    $this->installSchema('node', array('node', 'node_revision', 'node_type', 'node_access'));
+    $this->installSchema('node', array('node', 'node_field_data', 'node_field_revision', 'node_type', 'node_access'));
     $this->installSchema('comment', array('comment', 'node_comment_statistics'));
   }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
index 3c76f5627d99..0b1f33726343 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
@@ -36,7 +36,7 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
     $this->installSchema('user', array('users_roles', 'users_data'));
-    $this->installSchema('node', array('node', 'node_revision', 'node_type', 'node_access'));
+    $this->installSchema('node', array('node', 'node_field_data', 'node_field_revision', 'node_type', 'node_access'));
     $this->installSchema('entity_test', array(
       'entity_test_mul',
       'entity_test_mul_property_data',
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index f0ad115bbc89..308cef1f445b 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -2398,7 +2398,7 @@ function hook_schema() {
         'not null' => TRUE,
       ),
       'vid' => array(
-        'description' => 'The current {node_revision}.vid version identifier.',
+        'description' => 'The current {node_field_revision}.vid version identifier.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
@@ -2429,7 +2429,7 @@ function hook_schema() {
     ),
     'foreign keys' => array(
       'node_revision' => array(
-        'table' => 'node_revision',
+        'table' => 'node_field_revision',
         'columns' => array('vid' => 'vid'),
       ),
       'node_author' => array(
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/views/field/TaxonomyIndexTid.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/views/field/TaxonomyIndexTid.php
index 44faa7f8742b..5d48bce68765 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/views/field/TaxonomyIndexTid.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/views/field/TaxonomyIndexTid.php
@@ -28,8 +28,8 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
     parent::init($view, $display, $options);
 
     // @todo: Wouldn't it be possible to use $this->base_table and no if here?
-    if ($view->storage->get('base_table') == 'node_revision') {
-      $this->additional_fields['nid'] = array('table' => 'node_revision', 'field' => 'nid');
+    if ($view->storage->get('base_table') == 'node_field_revision') {
+      $this->additional_fields['nid'] = array('table' => 'node_field_revision', 'field' => 'nid');
     }
     else {
       $this->additional_fields['nid'] = array('table' => 'node', 'field' => 'nid');
diff --git a/core/modules/tracker/lib/Drupal/tracker/Tests/Views/TrackerUserUidTest.php b/core/modules/tracker/lib/Drupal/tracker/Tests/Views/TrackerUserUidTest.php
index ca64eb375e35..804774d79173 100644
--- a/core/modules/tracker/lib/Drupal/tracker/Tests/Views/TrackerUserUidTest.php
+++ b/core/modules/tracker/lib/Drupal/tracker/Tests/Views/TrackerUserUidTest.php
@@ -33,7 +33,7 @@ public static function getInfo() {
   public function testUserUid() {
     $map = array(
       'nid' => 'nid',
-      'node_title' => 'title',
+      'node_field_data_title' => 'title',
     );
 
     $expected = array(
diff --git a/core/modules/tracker/tests/modules/tracker_test_views/test_views/views.view.test_tracker_user_uid.yml b/core/modules/tracker/tests/modules/tracker_test_views/test_views/views.view.test_tracker_user_uid.yml
index 9f6ee9b08863..a4840a4b4823 100644
--- a/core/modules/tracker/tests/modules/tracker_test_views/test_views/views.view.test_tracker_user_uid.yml
+++ b/core/modules/tracker/tests/modules/tracker_test_views/test_views/views.view.test_tracker_user_uid.yml
@@ -47,7 +47,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           relationship: none
           group_type: group
diff --git a/core/modules/tracker/tracker.module b/core/modules/tracker/tracker.module
index 125b5dac4242..34235b99ba14 100644
--- a/core/modules/tracker/tracker.module
+++ b/core/modules/tracker/tracker.module
@@ -84,7 +84,9 @@ function tracker_cron() {
   if ($max_nid > 0) {
     $batch_size = config('tracker.settings')->get('cron_index_limit');
     $last_nid = FALSE;
-    $result = db_query_range('SELECT nid, uid, status FROM {node} WHERE nid <= :max_nid ORDER BY nid DESC', 0, $batch_size, array(':max_nid' => $max_nid), array('target' => 'slave'));
+    // @todo This should be actually filtering on the desired language and just
+    //   fall back to the default language.
+    $result = db_query_range('SELECT nid, uid, status FROM {node_field_data} WHERE nid <= :max_nid AND default_langcode = 1 ORDER BY nid DESC', 0, $batch_size, array(':max_nid' => $max_nid), array('target' => 'slave'));
 
     $count = 0;
 
@@ -269,7 +271,9 @@ function tracker_comment_delete($comment) {
  *   The node updated timestamp or comment timestamp.
  */
 function _tracker_add($nid, $uid, $changed) {
-  $node = db_query('SELECT nid, status, uid, changed FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchObject();
+  // @todo This should be actually filtering on the desired language and just
+  //   fall back to the default language.
+  $node = db_query('SELECT nid, status, uid, changed FROM {node_field_data} WHERE nid = :nid AND default_langcode = 1 ORDER BY changed DESC, status DESC', array(':nid' => $nid))->fetchObject();
 
   // Adding a comment can only increase the changed timestamp, so our
   // calculation here is simple.
@@ -308,7 +312,9 @@ function _tracker_add($nid, $uid, $changed) {
  *  is the greatest.
  */
 function _tracker_calculate_changed($nid) {
-  $changed = db_query('SELECT changed FROM {node} WHERE nid = :nid', array(':nid' => $nid), array('target' => 'slave'))->fetchField();
+  // @todo This should be actually filtering on the desired language and just
+  //   fall back to the default language.
+  $changed = db_query('SELECT changed FROM {node_field_data} WHERE nid = :nid AND default_langcode = 1 ORDER BY changed DESC', array(':nid' => $nid), array('target' => 'slave'))->fetchField();
   $latest_comment = db_query_range('SELECT cid, changed FROM {comment} WHERE nid = :nid AND status = :status ORDER BY changed DESC', 0, 1, array(
     ':nid' => $nid,
     ':status' => COMMENT_PUBLISHED,
@@ -330,7 +336,9 @@ function _tracker_calculate_changed($nid) {
  *   The last changed timestamp of the node.
  */
 function _tracker_remove($nid, $uid = NULL, $changed = NULL) {
-  $node = db_query('SELECT nid, status, uid, changed FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchObject();
+  // @todo This should be actually filtering on the desired language and just
+  //   fall back to the default language.
+  $node = db_query('SELECT nid, status, uid, changed FROM {node_field_data} WHERE nid = :nid AND default_langcode = 1 ORDER BY changed DESC, status DESC', array(':nid' => $nid))->fetchObject();
 
   // The user only keeps his or her subscription if both of the following are true:
   //   (1) The node exists.
diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc
index a801ad702ca7..db99e54d6d2c 100644
--- a/core/modules/tracker/tracker.pages.inc
+++ b/core/modules/tracker/tracker.pages.inc
@@ -50,9 +50,11 @@ function tracker_page($account = NULL, $set_title = FALSE) {
   $rows = array();
   if (!empty($tracker_data)) {
     $nids = array_keys($tracker_data);
-    $nodes = entity_load_multiple('node', $nids);
+    $nodes = node_load_multiple($nids);
     // Now, get the data and put into the placeholder array.
-    $result = db_query('SELECT n.nid, l.comment_count FROM {node} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid INNER JOIN {users} u ON n.uid = u.uid WHERE n.nid IN (:nids)', array(':nids' => $nids), array('target' => 'slave'))->fetchAllKeyed();
+    // @todo This should be actually filtering on the desired language and just
+    //   fall back to the default language.
+    $result = db_query('SELECT n.nid, l.comment_count FROM {node_field_data} n INNER JOIN {node_comment_statistics} l ON n.nid = l.nid WHERE n.nid IN (:nids) AND n.default_langcode = 1 ORDER BY n.changed DESC', array(':nids' => $nids), array('target' => 'slave'))->fetchAllKeyed();
     foreach ($result as $nid => $comment_count) {
       $nodes[$nid]->last_activity = $tracker_data[$nid]->changed;
       $nodes[$nid]->comment_count = $comment_count;
diff --git a/core/modules/translation/translation.module b/core/modules/translation/translation.module
index fcb2adb763ae..9fa4ac2151d3 100644
--- a/core/modules/translation/translation.module
+++ b/core/modules/translation/translation.module
@@ -488,11 +488,13 @@ function translation_node_get_translations($tnid) {
 
     if (!isset($translations[$tnid])) {
       $translations[$tnid] = array();
-      $result = db_select('node', 'n')
-        ->fields('n', array('nid', 'type', 'uid', 'status', 'title', 'langcode'))
-        ->condition('n.tnid', $tnid)
-        ->addTag('node_access')
-        ->execute();
+      $query = db_select('node_field_data', 'n');
+      $query->innerJoin('node', 'nb', 'nb.nid = n.nid AND nb.langcode = n.langcode');
+      $query->fields('n', array('nid', 'uid', 'status', 'title', 'langcode'))
+        ->fields('nb', array('type'))
+        ->condition('nb.tnid', $tnid)
+        ->addTag('node_access');
+      $result = $query->execute();
 
       foreach ($result as $node) {
         $translations[$tnid][$node->langcode] = $node;
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_plugin_argument_default_current_user.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_plugin_argument_default_current_user.yml
index fce83434e2a4..8af545e5f7cc 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_plugin_argument_default_current_user.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_plugin_argument_default_current_user.yml
@@ -35,7 +35,7 @@ display:
           hide_empty: '0'
           id: title
           link_to_node: '0'
-          table: node
+          table: node_field_data
       pager:
         options:
           id: '0'
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_relationship.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_relationship.yml
index 0714c16f57bf..5a5f28388a1e 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_relationship.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_user_relationship.yml
@@ -53,7 +53,7 @@ display:
           id: title
           label: ''
           link_to_node: '1'
-          table: node
+          table: node_field_data
           plugin_id: node
         uid:
           alter:
diff --git a/core/modules/user/user.api.php b/core/modules/user/user.api.php
index 652c5b5772ad..5309f81436ad 100644
--- a/core/modules/user/user.api.php
+++ b/core/modules/user/user.api.php
@@ -119,7 +119,7 @@ function hook_user_cancel($edit, $account, $method) {
     case 'user_cancel_block_unpublish':
       // Unpublish nodes (current revisions).
       module_load_include('inc', 'node', 'node.admin');
-      $nodes = db_select('node', 'n')
+      $nodes = db_select('node_field_data', 'n')
         ->fields('n', array('nid'))
         ->condition('uid', $account->uid)
         ->execute()
@@ -130,14 +130,14 @@ function hook_user_cancel($edit, $account, $method) {
     case 'user_cancel_reassign':
       // Anonymize nodes (current revisions).
       module_load_include('inc', 'node', 'node.admin');
-      $nodes = db_select('node', 'n')
+      $nodes = db_select('node_field_data', 'n')
         ->fields('n', array('nid'))
         ->condition('uid', $account->uid)
         ->execute()
         ->fetchCol();
       node_mass_update($nodes, array('uid' => 0));
       // Anonymize old revisions.
-      db_update('node_revision')
+      db_update('node_field_revision')
         ->fields(array('uid' => 0))
         ->condition('uid', $account->uid)
         ->execute();
diff --git a/core/modules/user/user.views.inc b/core/modules/user/user.views.inc
index 8a27f8249d95..58f6a510b2e5 100644
--- a/core/modules/user/user.views.inc
+++ b/core/modules/user/user.views.inc
@@ -48,7 +48,7 @@ function user_views_data() {
       'title' => t('Content authored'),
       'help' => t('Relate content to the user who created it. This relationship will create one record for each content item created by the user.'),
       'id' => 'standard',
-      'base' => 'node',
+      'base' => 'node_field_data',
       'base field' => 'uid',
       'field' => 'uid',
       'label' => t('nodes'),
@@ -76,7 +76,7 @@ function user_views_data() {
       'argument field' => 'uid',
       'base' => 'node',
       'field' => 'nid',
-      'relationship' => 'node:uid'
+      'relationship' => 'node_field_data:uid'
     ),
   );
 
diff --git a/core/modules/views/config/views.view.archive.yml b/core/modules/views/config/views.view.archive.yml
index 3cba318ee9ed..abd29441cc61 100644
--- a/core/modules/views/config/views.view.archive.yml
+++ b/core/modules/views/config/views.view.archive.yml
@@ -56,7 +56,7 @@ display:
       sorts:
         created:
           id: created
-          table: node
+          table: node_field_data
           field: created
           order: DESC
           plugin_id: date
@@ -70,7 +70,7 @@ display:
       arguments:
         created_year_month:
           id: created_year_month
-          table: node
+          table: node_field_data
           field: created_year_month
           default_action: summary
           exception:
@@ -89,7 +89,7 @@ display:
       filters:
         status:
           id: status
-          table: node
+          table: node_field_data
           field: status
           value: '1'
           group: '0'
@@ -139,7 +139,7 @@ display:
       arguments:
         created_year_month:
           id: created_year_month
-          table: node
+          table: node_field_data
           field: created_year_month
           default_action: summary
           exception:
diff --git a/core/modules/views/config/views.view.backlinks.yml b/core/modules/views/config/views.view.backlinks.yml
index 311d5f5afb81..38c125bc2943 100644
--- a/core/modules/views/config/views.view.backlinks.yml
+++ b/core/modules/views/config/views.view.backlinks.yml
@@ -68,7 +68,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           label: ''
           link_to_node: '1'
@@ -133,7 +133,7 @@ display:
       filters:
         status:
           id: status
-          table: node
+          table: node_field_data
           field: status
           value: '1'
           group: '0'
diff --git a/core/modules/views/config/views.view.comments_recent.yml b/core/modules/views/config/views.view.comments_recent.yml
index c7ebba32892d..9a3ce2ba0fd7 100644
--- a/core/modules/views/config/views.view.comments_recent.yml
+++ b/core/modules/views/config/views.view.comments_recent.yml
@@ -156,8 +156,8 @@ display:
           custom_date_format: ''
           timezone: ''
       sorts:
-        timestamp:
-          id: timestamp
+        changed:
+          id: changed
           table: comment
           field: changed
           order: DESC
@@ -172,7 +172,7 @@ display:
       filters:
         status_extra:
           id: status_extra
-          table: node
+          table: node_field_data
           field: status_extra
           relationship: nid
           group: '0'
@@ -217,7 +217,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           relationship: nid
           label: 'Reply to'
diff --git a/core/modules/views/config/views.view.glossary.yml b/core/modules/views/config/views.view.glossary.yml
index 8237f1f98bdf..e73a4176488c 100644
--- a/core/modules/views/config/views.view.glossary.yml
+++ b/core/modules/views/config/views.view.glossary.yml
@@ -56,7 +56,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           link_to_node: '1'
           plugin_id: node
@@ -159,7 +159,7 @@ display:
           format_username: '1'
         changed:
           id: changed
-          table: node
+          table: node_field_data
           field: changed
           label: 'Last update'
           date_format: long
@@ -212,7 +212,7 @@ display:
       arguments:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           default_action: default
           exception:
@@ -246,7 +246,7 @@ display:
       relationships:
         uid:
           id: uid
-          table: node
+          table: node_field_data
           field: uid
           plugin_id: standard
           relationship: none
@@ -325,7 +325,7 @@ display:
       arguments:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           default_action: summary
           exception:
diff --git a/core/modules/views/config/views.view.taxonomy_term.yml b/core/modules/views/config/views.view.taxonomy_term.yml
index 850909b4bcaf..ebe804ce883f 100644
--- a/core/modules/views/config/views.view.taxonomy_term.yml
+++ b/core/modules/views/config/views.view.taxonomy_term.yml
@@ -55,7 +55,7 @@ display:
       sorts:
         sticky:
           id: sticky
-          table: node
+          table: node_field_data
           field: sticky
           order: DESC
           plugin_id: standard
@@ -67,7 +67,7 @@ display:
             label: ''
         created:
           id: created
-          table: node
+          table: node_field_data
           field: created
           order: DESC
           plugin_id: date
@@ -137,7 +137,7 @@ display:
       filters:
         status_extra:
           id: status_extra
-          table: node
+          table: node_field_data
           field: status_extra
           group: '0'
           expose:
diff --git a/core/modules/views/config/views.view.tracker.yml b/core/modules/views/config/views.view.tracker.yml
index 1e2450168180..fa81fff1922e 100644
--- a/core/modules/views/config/views.view.tracker.yml
+++ b/core/modules/views/config/views.view.tracker.yml
@@ -56,7 +56,7 @@ display:
       relationships:
         uid:
           id: uid
-          table: node
+          table: node_field_data
           field: uid
           plugin_id: standard
           relationship: none
@@ -66,7 +66,7 @@ display:
       fields:
         type:
           id: type
-          table: node
+          table: node_field_data
           field: type
           plugin_id: node_type
           relationship: none
@@ -117,7 +117,7 @@ display:
           machine_name: '0'
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           plugin_id: node
           relationship: none
@@ -455,7 +455,7 @@ display:
       arguments:
         uid_touch:
           id: uid_touch
-          table: node
+          table: node_field_data
           field: uid_touch
           exception:
             title_enable: '1'
@@ -482,7 +482,7 @@ display:
       filters:
         status:
           id: status
-          table: node
+          table: node_field_data
           field: status
           value: '1'
           group: '0'
diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/ArgumentStringTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/ArgumentStringTest.php
index b0098f3b6023..e1ed866217a7 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Handler/ArgumentStringTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Handler/ArgumentStringTest.php
@@ -47,13 +47,13 @@ function testGlossary() {
 
     $count_field = 'nid';
     foreach ($view->result as &$row) {
-      if (strpos($row->node_title, 'a') === 0) {
+      if (strpos($view->field['title']->get_value($row), 'a') === 0) {
         $this->assertEqual(1, $row->{$count_field});
       }
-      if (strpos($row->node_title, 'b') === 0) {
+      if (strpos($view->field['title']->get_value($row), 'b') === 0) {
         $this->assertEqual(2, $row->{$count_field});
       }
-      if (strpos($row->node_title, 'c') === 0) {
+      if (strpos($view->field['title']->get_value($row), 'c') === 0) {
         $this->assertEqual(3, $row->{$count_field});
       }
     }
diff --git a/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php b/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php
index 51a156cdb6c5..92bb8ce74920 100644
--- a/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/QueryGroupByTest.php
@@ -58,7 +58,7 @@ public function testAggregateCount() {
     $types = array();
     foreach ($view->result as $item) {
       // num_records is a alias for nid.
-      $types[$item->node_type] = $item->num_records;
+      $types[$item->node_field_data_type] = $item->num_records;
     }
 
     $this->assertEqual($types[$type1->type], 4);
@@ -101,7 +101,7 @@ function GroupByTestHelper($group_by, $values) {
     $this->assertEqual(count($view->result), 2, 'Make sure the count of items is right.');
     // Group by nodetype to identify the right count.
     foreach ($view->result as $item) {
-      $results[$item->node_type] = $item->nid;
+      $results[$item->node_field_data_type] = $item->nid;
     }
     $this->assertEqual($results[$type1->type], $values[0]);
     $this->assertEqual($results[$type2->type], $values[1]);
diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php
index 41e5c8bc20d5..57d4b04c610d 100644
--- a/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php
@@ -81,7 +81,7 @@ public static function getInfo() {
 
   protected function setUpFixtures() {
     $this->installSchema('user', array('users', 'role_permission'));
-    $this->installSchema('node', array('node_type', 'node'));
+    $this->installSchema('node', array('node_type', 'node', 'node_field_data'));
     $this->installSchema('comment', array('comment', 'node_comment_statistics'));
     parent::setUpFixtures();
 
diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewsDataTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewsDataTest.php
index 19245181d73a..84cebb1ae6eb 100644
--- a/core/modules/views/lib/Drupal/views/Tests/ViewsDataTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/ViewsDataTest.php
@@ -362,7 +362,7 @@ public function testFetchBaseTables() {
 
     // Test the number of tables returned and their order.
     $this->assertEqual(count($base_tables), 3, 'The correct amount of base tables were returned.');
-    $this->assertIdentical(array_keys($base_tables), array('node', 'node_revision', 'views_test_data'), 'The tables are sorted as expected.');
+    $this->assertIdentical(array_keys($base_tables), array('node', 'node_field_revision', 'views_test_data'), 'The tables are sorted as expected.');
 
     // Test the values returned for each base table.
     $defaults = array(
diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/ItemsPerPageTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/ItemsPerPageTest.php
index 13cf88530cd6..f51de221a904 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Wizard/ItemsPerPageTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/ItemsPerPageTest.php
@@ -45,7 +45,7 @@ function testItemsPerPage() {
     $view['description'] = $this->randomName(16);
     $view['show[wizard_key]'] = 'node';
     $view['show[type]'] = 'article';
-    $view['show[sort]'] = 'created:DESC';
+    $view['show[sort]'] = 'node_field_data-created:DESC';
     $view['page[create]'] = 1;
     $view['page[title]'] = $this->randomName(16);
     $view['page[path]'] = $this->randomName(16);
diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/SortingTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/SortingTest.php
index 9ca635d995ca..f7c9712c499d 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Wizard/SortingTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/SortingTest.php
@@ -35,7 +35,7 @@ function testSorting() {
     $view1['label'] = $this->randomName(16);
     $view1['id'] = strtolower($this->randomName(16));
     $view1['description'] = $this->randomName(16);
-    $view1['show[sort]'] = 'created:ASC';
+    $view1['show[sort]'] = 'node_field_data-created:ASC';
     $view1['page[create]'] = 1;
     $view1['page[title]'] = $this->randomName(16);
     $view1['page[path]'] = $this->randomName(16);
@@ -60,7 +60,7 @@ function testSorting() {
     $view2['label'] = $this->randomName(16);
     $view2['id'] = strtolower($this->randomName(16));
     $view2['description'] = $this->randomName(16);
-    $view2['show[sort]'] = 'created:DESC';
+    $view2['show[sort]'] = 'node_field_data-created:DESC';
     $view2['page[create]'] = 1;
     $view2['page[title]'] = $this->randomName(16);
     $view2['page[path]'] = $this->randomName(16);
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_aggregate_count.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_aggregate_count.yml
index 0526e68d4669..958165483349 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_aggregate_count.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_aggregate_count.yml
@@ -15,7 +15,7 @@ display:
           id: type
           summary:
             format: default_summary
-          table: node
+          table: node_field_data
           plugin_id: node_type
       cache:
         type: none
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_argument_default_current_user.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_argument_default_current_user.yml
index e01546952827..1b8dff500453 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_argument_default_current_user.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_argument_default_current_user.yml
@@ -12,7 +12,7 @@ display:
           default_action: default
           field: uid
           id: uid
-          table: node
+          table: node_field_data
           plugin_id: numeric
       cache:
         type: none
@@ -33,7 +33,7 @@ display:
           hide_empty: '0'
           id: title
           link_to_node: '0'
-          table: node
+          table: node_field_data
           plugin_id: node
       pager:
         options:
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_argument_default_fixed.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_argument_default_fixed.yml
index 333899e75f60..f8a2500a78b3 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_argument_default_fixed.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_argument_default_fixed.yml
@@ -36,7 +36,7 @@ display:
           hide_empty: '0'
           id: title
           link_to_node: '0'
-          table: node
+          table: node_field_data
           plugin_id: node
       pager:
         options:
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_destroy.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_destroy.yml
index 8342fc065265..772d5f10c781 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_destroy.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_destroy.yml
@@ -35,21 +35,21 @@ display:
           field: created_day
           id: created_day
           style_plugin: default_summary
-          table: node
+          table: node_field_data
           plugin_id: date_day
         created_fulldate:
           default_argument_type: fixed
           field: created_fulldate
           id: created_fulldate
           style_plugin: default_summary
-          table: node
+          table: node_field_data
           plugin_id: date_fulldate
         created_month:
           default_argument_type: fixed
           field: created_month
           id: created_month
           style_plugin: default_summary
-          table: node
+          table: node_field_data
           plugin_id: date_month
       cache:
         type: none
@@ -72,7 +72,7 @@ display:
         created:
           field: created
           id: created
-          table: node
+          table: node_field_data
           plugin_id: date
         nid:
           field: nid
@@ -93,12 +93,12 @@ display:
         status:
           field: status
           id: status
-          table: node
+          table: node_field_data
           plugin_id: boolean
         title:
           field: title
           id: title
-          table: node
+          table: node_field_data
           plugin_id: string
       footer:
         area:
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_display.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_display.yml
index 8f1b0b9e3b48..d5fff8a7ec30 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_display.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_display.yml
@@ -44,14 +44,14 @@ display:
         title:
           field: title
           id: title
-          table: node
+          table: node_field_data
           plugin_id: node
       filters:
         status:
           field: status
           group: '1'
           id: status
-          table: node
+          table: node_field_data
           value: '1'
           plugin_id: boolean
       pager:
@@ -70,7 +70,7 @@ display:
           field: created
           id: created
           order: DESC
-          table: node
+          table: node_field_data
           plugin_id: date
       style_plugin: default
       title: 'Test Display'
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_dropbutton.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_dropbutton.yml
index c0ec6403db82..536a3be7f998 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_dropbutton.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_dropbutton.yml
@@ -79,7 +79,7 @@ display:
           link_to_node: '0'
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           plugin_id: node
           label: ''
@@ -201,7 +201,7 @@ display:
       filters:
         status:
           value: '1'
-          table: node
+          table: node_field_data
           field: status
           id: status
           plugin_id: boolean
@@ -211,7 +211,7 @@ display:
       sorts:
         created:
           id: created
-          table: node
+          table: node_field_data
           field: created
           order: DESC
           plugin_id: date
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_entity_type_filter.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_entity_type_filter.yml
index 6860337ead35..81dc402db9ae 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_entity_type_filter.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_entity_type_filter.yml
@@ -17,7 +17,7 @@ display:
           relationship: none
         type:
           id: type
-          table: node
+          table: node_field_data
           field: type
           relationship: none
           group_type: group
@@ -69,7 +69,7 @@ display:
       filters:
         type:
           id: type
-          table: node
+          table: node_field_data
           field: type
           relationship: none
           value:
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_exposed_admin_ui.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_exposed_admin_ui.yml
index e4dde6f038ce..bab17148ca12 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_exposed_admin_ui.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_exposed_admin_ui.yml
@@ -21,7 +21,7 @@ display:
             use_operator: '1'
           field: type
           id: type
-          table: node
+          table: node_field_data
           plugin_id: node_type
         body_value:
           id: body_value
@@ -69,7 +69,7 @@ display:
         created:
           field: created
           id: created
-          table: node
+          table: node_field_data
           plugin_id: date
       style:
         type: default
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_feed_display.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_feed_display.yml
index eb81e3df51d4..a87bf86cb128 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_feed_display.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_feed_display.yml
@@ -28,7 +28,7 @@ display:
           id: title
           label: ''
           link_to_node: '1'
-          table: node
+          table: node_field_data
           plugin_id: node
       filters:
         status:
@@ -37,7 +37,7 @@ display:
           field: status
           group: '1'
           id: status
-          table: node
+          table: node_field_data
           value: '1'
           plugin_id: boolean
       pager:
@@ -57,7 +57,7 @@ display:
           field: created
           id: created
           order: DESC
-          table: node
+          table: node_field_data
           plugin_id: date
       style:
         type: default
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_field_get_entity.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_field_get_entity.yml
index 7fa0da62f5b5..0600e9581918 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_field_get_entity.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_field_get_entity.yml
@@ -52,7 +52,7 @@ display:
           label: author
           relationship: nid
           required: '0'
-          table: node
+          table: node_field_data
           plugin_id: standard
       sorts: {  }
       style:
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_field_type.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_field_type.yml
index 0663e76f16a5..d3b4a0a4e844 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_field_type.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_field_type.yml
@@ -9,7 +9,7 @@ display:
         type:
           field: type
           id: type
-          table: node
+          table: node_field_data
           plugin_id: node_type
     display_plugin: default
     display_title: Master
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_date_between.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_date_between.yml
index 6ec71b3ce250..313a0522dee4 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_date_between.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_date_between.yml
@@ -21,7 +21,7 @@ display:
         created:
           field: created
           id: created
-          table: node
+          table: node_field_data
           plugin_id: date
       pager:
         type: full
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_group_override.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_group_override.yml
index 2a154b10551b..cd290d9b9f09 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_group_override.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_group_override.yml
@@ -19,7 +19,7 @@ display:
           field: title
           id: title
           label: ''
-          table: node
+          table: node_field_data
           plugin_id: node
       filters:
         status:
@@ -28,7 +28,7 @@ display:
           field: status
           group: '1'
           id: status
-          table: node
+          table: node_field_data
           value: '1'
           plugin_id: boolean
       pager:
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_groups.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_groups.yml
index 0b76446ddd9d..edaf39c23a1a 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_groups.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_groups.yml
@@ -19,7 +19,7 @@ display:
           field: title
           id: title
           label: ''
-          table: node
+          table: node_field_data
           plugin_id: node
       filter_groups:
         groups:
@@ -48,7 +48,7 @@ display:
           field: status
           group: '1'
           id: status
-          table: node
+          table: node_field_data
           value: '1'
           plugin_id: boolean
       pager:
@@ -62,7 +62,7 @@ display:
           field: created
           id: created
           order: DESC
-          table: node
+          table: node_field_data
           plugin_id: date
       title: test_filter_groups
       style:
@@ -105,7 +105,7 @@ display:
           field: status
           group: '1'
           id: status
-          table: node
+          table: node_field_data
           value: '1'
           plugin_id: boolean
       path: test-filter-groups
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml
index d1a8c839405e..abe6884fee62 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_filter_in_operator_ui.yml
@@ -22,7 +22,7 @@ display:
           exposed: '1'
           field: type
           id: type
-          table: node
+          table: node_field_data
           plugin_id: string
       pager:
         type: full
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_glossary.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_glossary.yml
index 7054d2f1b326..f8783ce4d35f 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_glossary.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_glossary.yml
@@ -19,7 +19,7 @@ display:
             number_of_records: '0'
           summary_options:
             items_per_page: '25'
-          table: node
+          table: node_field_data
           plugin_id: string
       cache:
         type: none
@@ -30,7 +30,7 @@ display:
           field: title
           id: title
           label: ''
-          table: node
+          table: node_field_data
           plugin_id: node
       pager:
         type: full
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_group_by_count.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_group_by_count.yml
index e6e23c7717f7..c69fb2991b0f 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_group_by_count.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_group_by_count.yml
@@ -43,7 +43,7 @@ display:
           hide_empty: '0'
           id: type
           link_to_node: '0'
-          table: node
+          table: node_field_data
           plugin_id: node_type
       group_by: '1'
       pager:
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_group_by_in_filters.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_group_by_in_filters.yml
index 927c84997ab7..753dd4c83cd6 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_group_by_in_filters.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_group_by_in_filters.yml
@@ -26,7 +26,7 @@ display:
           hide_empty: '0'
           id: type
           link_to_node: '0'
-          table: node
+          table: node_field_data
           plugin_id: node_type
       filters:
         nid:
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_handler_relationships.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_handler_relationships.yml
index cd04aa5599d0..bf45d7d1daf9 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_handler_relationships.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_handler_relationships.yml
@@ -8,7 +8,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           plugin_id: node
       relationships:
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_history.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_history.yml
index edb9825dde06..aca6f52a15a0 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_history.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_history.yml
@@ -27,7 +27,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           plugin_id: node
           label: ''
@@ -97,7 +97,7 @@ display:
       filters:
         status:
           value: '1'
-          table: node
+          table: node_field_data
           field: status
           plugin_id: boolean
           id: status
@@ -107,7 +107,7 @@ display:
       sorts:
         created:
           id: created
-          table: node
+          table: node_field_data
           field: created
           plugin_id: date
           order: DESC
@@ -130,7 +130,7 @@ display:
       filters:
         status:
           id: status
-          table: node
+          table: node_field_data
           field: status
           plugin_id: boolean
           relationship: none
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_redirect_view.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_redirect_view.yml
index dbb4621b6b99..4afc2ed485ac 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_redirect_view.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_redirect_view.yml
@@ -34,7 +34,7 @@ display:
       fields:
         title:
           id: title
-          table: node
+          table: node_field_data
           field: title
           label: ''
           alter:
@@ -53,7 +53,7 @@ display:
       filters:
         status:
           value: '1'
-          table: node
+          table: node_field_data
           field: status
           id: status
           expose:
@@ -63,7 +63,7 @@ display:
       sorts:
         created:
           id: created
-          table: node
+          table: node_field_data
           field: created
           order: DESC
           plugin_id: date
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_reset_button.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_reset_button.yml
index d6564f489f52..cd293d2b83b1 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_reset_button.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_reset_button.yml
@@ -23,7 +23,7 @@ display:
           exposed: '1'
           field: type
           id: type
-          table: node
+          table: node_field_data
           plugin_id: node_type
       pager:
         type: full
diff --git a/core/modules/views/tests/views_test_config/test_views/views.view.test_view_pager_full_zero_items_per_page.yml b/core/modules/views/tests/views_test_config/test_views/views.view.test_view_pager_full_zero_items_per_page.yml
index 7b1efb3be03e..968c40efa53c 100644
--- a/core/modules/views/tests/views_test_config/test_views/views.view.test_view_pager_full_zero_items_per_page.yml
+++ b/core/modules/views/tests/views_test_config/test_views/views.view.test_view_pager_full_zero_items_per_page.yml
@@ -26,7 +26,7 @@ display:
           hide_empty: '0'
           id: title
           link_to_node: '0'
-          table: node
+          table: node_field_data
           plugin_id: node
       pager:
         options:
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Tests/SettingsTest.php b/core/modules/views_ui/lib/Drupal/views_ui/Tests/SettingsTest.php
index 1d499598e347..4b1810457ce3 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/Tests/SettingsTest.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Tests/SettingsTest.php
@@ -116,7 +116,7 @@ function testEditUI() {
     $xpath = $this->xpath('//div[@class="views-query-info"]//pre');
     $this->assertEqual(count($xpath), 1, 'The views sql is shown.');
     $this->assertFalse(strpos($xpath[0], 'db_condition_placeholder') !== FALSE, 'No placeholders are shown in the views sql.');
-    $this->assertTrue(strpos($xpath[0], "node.status = '1'") !== FALSE, 'The placeholders in the views sql is replace by the actual value.');
+    $this->assertTrue(strpos($xpath[0], "node_field_data.status = '1'") !== FALSE, 'The placeholders in the views sql is replace by the actual value.');
   }
 
 }
-- 
GitLab