diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageAwareTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageAwareTest.php
new file mode 100644
index 0000000..df55d77
--- /dev/null
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageAwareTest.php
@@ -0,0 +1,299 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\node\Tests\NodeAccessLanguageTest.
+ */
+
+namespace Drupal\node\Tests;
+
+use Drupal\Core\Language\Language;
+
+/**
+ * Test case to verify node_access functionality for multiple languages.
+ */
+class NodeAccessLanguageAwareTest extends NodeTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('language', 'node_access_test_language');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Node access language aware',
+      'description' => 'Test node_access and db_select with node_access tag functionality with multiple languages with node_access_test_language which is language aware.',
+      'group' => 'Node',
+    );
+  }
+
+  /**
+   * Asserts node_access correctly grants or denies access.
+   */
+  function assertNodeAccess($ops, $node, $account, $langcode = NULL) {
+    foreach ($ops as $op => $result) {
+      $msg = t("node_access returns @result with operation '@op', language code @langcode.", array('@result' => $result ? 'true' : 'false', '@op' => $op, '@langcode' => !empty($langcode) ? "'$langcode'" : 'empty'));
+      $this->assertEqual($result, node_access($op, $node, $account, $langcode), $msg);
+    }
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    node_access_rebuild();
+
+    // Clear permissions for authenticated users.
+    db_delete('role_permission')
+      ->condition('rid', DRUPAL_AUTHENTICATED_RID)
+      ->execute();
+
+    // Add Hungarian and Catalan.
+    $language = new Language(array(
+      'langcode' => 'hu',
+    ));
+    language_save($language);
+    $language = new Language(array(
+      'langcode' => 'ca',
+    ));
+    language_save($language);
+  }
+
+  /**
+   * Runs tests for node_access function with multiple languages.
+   */
+  function testNodeAccessLanguageAware() {
+    $web_user = $this->drupalCreateUser(array('access content'));
+
+    $expected_node_access = array('view' => TRUE, 'update' => FALSE, 'delete' => FALSE);
+    $expected_node_access_no_access = array('view' => FALSE, 'update' => FALSE, 'delete' => FALSE);
+
+
+    // Creating a Node with default langcode Hungarian and translation Catalan.
+    // Hungarian language is public, Catalan is public.
+    $node = $this->drupalCreateNode(array(
+      'body' => array('hu' => array(array())),
+      'langcode' => 'hu',
+      'field_private' => array(
+        'hu' => array(0 => array('value' => 0)),
+        'ca' => array(0 => array('value' => 0)),
+      )
+    ));
+    $this->assertTrue($node->langcode == 'hu', t('Node created as Hungarian.'));
+
+    // Tests that access to default language (Hungarian) is granted.
+    $this->assertNodeAccess($expected_node_access, $node, $web_user);
+
+    // Tests that access to hungarian language is granted.
+    $this->assertNodeAccess($expected_node_access, $node, $web_user, 'hu');
+
+    // Tests that access to catalan language is granted.
+    $this->assertNodeAccess($expected_node_access, $node, $web_user, 'ca');
+
+    // Tests that access to english language is granted.
+    $this->assertNodeAccess($expected_node_access_no_access, $node, $web_user, 'en');
+
+    // Creating a Node with default langcode Hungarian and translation Catalan.
+    // Hungarian language is private, Catalan is public.
+    $node = $this->drupalCreateNode(array(
+      'body' => array('hu' => array(array())),
+      'langcode' => 'hu',
+      'field_private' => array(
+        'hu' => array(0 => array('value' => 1)),
+        'ca' => array(0 => array('value' => 0)),
+      )
+    ));
+    $this->assertTrue($node->langcode == 'hu', t('Node created as Hungarian.'));
+
+    // Tests that access to default language (Hungarian) is not granted.
+    $this->assertNodeAccess($expected_node_access_no_access, $node, $web_user);
+
+    // Tests that access to hungarian language is granted.
+    $this->assertNodeAccess($expected_node_access_no_access, $node, $web_user, 'hu');
+
+    // Tests that access to catalan language is granted.
+    $this->assertNodeAccess($expected_node_access, $node, $web_user, 'ca');
+
+    // Tests that access to english language is granted.
+    $this->assertNodeAccess($expected_node_access_no_access, $node, $web_user, 'en');
+
+    // Creating a Node with default langcode Hungarian and translation Catalan.
+    // Hungarian language is public, Catalan is private.
+    $node = $this->drupalCreateNode(array(
+      'body' => array('hu' => array(array())),
+      'langcode' => 'hu',
+      'field_private' => array(
+        'hu' => array(0 => array('value' => 0)),
+        'ca' => array(0 => array('value' => 1)),
+      )
+    ));
+    $this->assertTrue($node->langcode == 'hu', t('Node created as Hungarian.'));
+
+    // Tests that access to default language (Hungarian) is granted.
+    $this->assertNodeAccess($expected_node_access, $node, $web_user);
+
+    // Tests that access to hungarian language is granted.
+    $this->assertNodeAccess($expected_node_access, $node, $web_user, 'hu');
+
+    // Tests that access to catalan language is not granted.
+    $this->assertNodeAccess($expected_node_access_no_access, $node, $web_user, 'ca');
+
+    // Tests that access to english language is granted.
+    $this->assertNodeAccess($expected_node_access_no_access, $node, $web_user, 'en');
+
+    // Creating a Node with default langcode Hungarian and translation Catalan.
+    // Hungarian language is private, Catalan is private.
+    $node = $this->drupalCreateNode(array(
+      'body' => array('hu' => array(array())),
+      'langcode' => 'hu',
+      'field_private' => array(
+        'hu' => array(0 => array('value' => 1)),
+        'ca' => array(0 => array('value' => 1)),
+      )
+    ));
+    $this->assertTrue($node->langcode == 'hu', t('Node created as Hungarian.'));
+
+    // Tests that access to default language (Hungarian) is not granted.
+    $this->assertNodeAccess($expected_node_access_no_access, $node, $web_user);
+
+    // Tests that access to hungarian language is not granted.
+    $this->assertNodeAccess($expected_node_access_no_access, $node, $web_user, 'hu');
+
+    // Tests that access to catalan language is not granted.
+    $this->assertNodeAccess($expected_node_access_no_access, $node, $web_user, 'ca');
+
+    // Tests that access to english language is granted.
+    $this->assertNodeAccess($expected_node_access_no_access, $node, $web_user, 'en');
+  }
+
+  /**
+   * Runs tests for db_select with node_access tag and langcode.
+   */
+  function testNodeAccessLanguageAwareQueryTag() {
+    $web_user = $this->drupalCreateUser(array('access content'));
+
+    // Creating a Node with default langcode Hungarian and translation Catalan.
+    // Hungarian language is public, Catalan is public.
+    $node_both_public = $this->drupalCreateNode(array(
+      'body' => array('hu' => array(array())),
+      'langcode' => 'hu',
+      'field_private' => array(
+        'hu' => array(0 => array('value' => 0)),
+        'ca' => array(0 => array('value' => 0)),
+      )
+    ));
+
+    // Creating a Node with default langcode Hungarian and translation Catalan.
+    // Hungarian language is private, Catalan is public.
+    $node_only_hu_public = $this->drupalCreateNode(array(
+      'body' => array('hu' => array(array())),
+      'langcode' => 'hu',
+      'field_private' => array(
+        'hu' => array(0 => array('value' => 0)),
+        'ca' => array(0 => array('value' => 1)),
+      )
+    ));
+
+    // Creating a Node with default langcode Hungarian and translation Catalan.
+    // Hungarian language is public, Catalan is private.
+    $node_only_ca_public = $this->drupalCreateNode(array(
+      'body' => array('hu' => array(array())),
+      'langcode' => 'hu',
+      'field_private' => array(
+        'hu' => array(0 => array('value' => 1)),
+        'ca' => array(0 => array('value' => 0)),
+      )
+    ));
+
+    // Creating a Node with default langcode Hungarian and translation Catalan.
+    // Hungarian language is private, Catalan is private.
+    $node_no_public = $this->drupalCreateNode(array(
+      'body' => array('hu' => array(array())),
+      'langcode' => 'hu',
+      'field_private' => array(
+        'hu' => array(0 => array('value' => 1)),
+        'ca' => array(0 => array('value' => 1)),
+      )
+    ));
+
+    // Query the nodes table as readonly user with Node Access Tag and no
+    // specific langcode.
+    $select = db_select('node', 'n')
+    ->fields('n', array('nid'))
+    ->addMetaData('account', $web_user)
+    ->addTag('node_access');
+    $nids = $select->execute()->fetchAllAssoc('nid');
+
+    // Because no langcode is given it will use the fallback language
+    // (which is hungarian).
+    $this->assertEqual(count($nids), 2, 'db_select returns 2 nodes');
+    $this->assertTrue(array_key_exists($node_both_public->nid, $nids), 'Returned node ID is full public node.');
+    $this->assertTrue(array_key_exists($node_only_hu_public->nid, $nids), 'Returned node ID is Hungarian public only node.');
+
+    // Query the nodes table as readonly user with Node Access Tag and
+    // Hungarian langcode
+    $select = db_select('node', 'n')
+    ->fields('n', array('nid'))
+    ->addMetaData('account', $web_user)
+    ->addMetaData('langcode', 'hu')
+    ->addTag('node_access');
+    $nids = $select->execute()->fetchAllAssoc('nid');
+
+    // Same nodes as witouth langcode should be returned.
+    $this->assertEqual(count($nids), 2, 'db_select returns 2 nodes');
+    $this->assertTrue(array_key_exists($node_both_public->nid, $nids), 'Returned node ID is both public node.');
+    $this->assertTrue(array_key_exists($node_only_hu_public->nid, $nids), 'Returned node ID is Hungarian public only node.');
+
+    // Query the nodes table as readonly user with Node Access Tag and
+    // Catalan langcode
+    $select = db_select('node', 'n')
+    ->fields('n', array('nid'))
+    ->addMetaData('account', $web_user)
+    ->addMetaData('langcode', 'ca')
+    ->addTag('node_access');
+    $nids = $select->execute()->fetchAllAssoc('nid');
+
+    // Only the Catalan and the Full Public node should be returned.
+    $this->assertEqual(count($nids), 2, 'db_select returns 2 nodes');
+    $this->assertTrue(array_key_exists($node_both_public->nid, $nids), 'Returned node ID is both public node.');
+    $this->assertTrue(array_key_exists($node_only_ca_public->nid, $nids), 'Returned node ID is Catalan public only node.');
+
+
+    // Query the nodes table as readonly User with Node Access Tag and
+    // langcode de.
+    $select = db_select('node', 'n')
+    ->fields('n', array('nid'))
+    ->addMetaData('account', $web_user)
+    ->addMetaData('langcode', 'de')
+    ->addTag('node_access');
+    $nids = $select->execute()->fetchAllAssoc('nid');
+
+    // Because all created nodes are not in German, no Nodes are returned.
+    $this->assertTrue(empty($nids), 'db_select returns empty result');
+
+
+    // Query the nodes table as User 1 (full access) with Node Access Tag and no
+    // specific langcode.
+    $select = db_select('node', 'n')
+    ->fields('n', array('nid'))
+    ->addTag('node_access');
+    $nids = $select->execute()->fetchAllAssoc('nid');
+
+    // Both nodes are returned.
+    $this->assertEqual(count($nids), 4, 'db_select returns all nodes');
+
+    // Query the nodes table as User 1 (full access) with Node Access Tag and
+    // langcode de.
+    $select = db_select('node', 'n')
+    ->fields('n', array('nid'))
+    ->addMetaData('langcode', 'de')
+    ->addTag('node_access');
+    $nids = $select->execute()->fetchAllAssoc('nid');
+
+    // Both nodes are returned because node access tag is not invoked when
+    // the user is user 1.
+    $this->assertEqual(count($nids), 4, 'db_select returns all nodes');
+  }
+
+}
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageTest.php
index 73bf3af..3f6d331 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageTest.php
@@ -9,8 +9,6 @@
 
 use Drupal\Core\Language\Language;
 
-use Drupal\Core\Language\Language;
-
 /**
  * Test case to verify node_access functionality for multiple languages.
  */
@@ -26,7 +24,7 @@ class NodeAccessLanguageTest extends NodeTestBase {
   public static function getInfo() {
     return array(
       'name' => 'Node access language',
-      'description' => 'Test node_access and db_select with node_access tag functionality with multiple languages.',
+      'description' => 'Test node_access and db_select with node_access tag functionality with multiple languages with node_access_test_module which is not language aware.',
       'group' => 'Node',
     );
   }
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index e87988e..ae5ad9b 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -202,7 +202,7 @@ function node_schema() {
         'size' => 'tiny',
       ),
     ),
-    'primary key' => array('nid', 'gid', 'realm'),
+    'primary key' => array('nid', 'gid', 'langcode', 'realm'),
     'foreign keys' => array(
       'affected_node' => array(
         'table' => 'node',
@@ -765,6 +765,9 @@ function node_update_8011() {
     'default' => 1,
   );
   db_add_field('node_access', 'fallback', $fallback_field);
+
+  db_drop_primary_key('node_access');
+  db_add_primary_key('node_access', array('nid', 'gid', 'langcode', 'realm'));
 }
 
 
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 5e6a673..992b807 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -2763,8 +2763,24 @@ function node_access($op, $node, $account = NULL, $langcode = NULL) {
   // If no language code was provided, default to the node's langcode or
   // to an empty langcode if a node type was requested. The latter is purely
   // for caching purposes.
-  if (empty($langcode)) {
-    $langcode = (is_object($node) && isset($node->nid)) ? $node->langcode : '';
+  if (empty($langcode) && (is_object($node) && isset($node->nid))) {
+    if (module_exists('language')) {
+      // Load language from content negotiation.
+      $content_negotiation_langcode = language(LANGUAGE_TYPE_CONTENT)->langcode;
+      // Load languages the node exists in.
+      $node_translations = $node->getTranslationLanguages();
+      // If the node does not exist in the language from content negotiation
+      // return the default language of the node.
+      if (isset($node_translations[$content_negotiation_langcode])) {
+        $langcode = $content_negotiation_langcode;
+      } else {
+        $langcode = $node->langcode;
+      }
+    } else {
+      $langcode = $node->langcode;
+    }
+  } else if (empty($langcode)){
+    $langcode = '';
   }
 
   // If we've already checked access for this node, user and op, return from
diff --git a/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.info b/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.info
new file mode 100644
index 0000000..d5a9c7c
--- /dev/null
+++ b/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.info
@@ -0,0 +1,7 @@
+name = "Node module access tests language"
+description = "Support module for language aware node permission testing."
+package = Testing
+version = VERSION
+core = 8.x
+dependencies[] = options
+hidden = TRUE
diff --git a/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module b/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module
new file mode 100644
index 0000000..eaa76e4
--- /dev/null
+++ b/core/modules/node/tests/modules/node_access_test_language/node_access_test_language.module
@@ -0,0 +1,109 @@
+<?php
+
+/**
+ * @file
+ * Dummy module implementing language aware node access related hooks to
+ * test API interaction with the Node module. This module restricts
+ * view permission to those with a special 'node test view' permission.
+ */
+
+use Drupal\node\Plugin\Core\Entity\Node;
+
+/**
+ * Implements hook_node_grants().
+ */
+function node_access_test_language_node_grants($account, $op) {
+  $grants = array();
+  // First grant a grant to the author for own content.
+  $grants['node_access_test_language_author'] = array($account->uid);
+  if ($op == 'view' && user_access('node access language test view', $account)) {
+    $grants['node_access_language_test'] = array(7888, 7889);
+  }
+
+  $no_access_uid = state()->get('node_access_language_test.no_access_uid') ?: 0;
+  if ($op == 'view' && $account->uid == $no_access_uid) {
+    $grants['node_access_language_all'] = array(0);
+  }
+  return $grants;
+}
+
+/**
+ * Implements hook_node_access_records().
+ */
+function node_access_test_language_node_access_records(Node $node) {
+  $grants = array();
+
+  // Create grants for each translation of the node.
+  foreach ($node->getTranslationLanguages() as $langcode => $language) {
+    if ($node->field_private[$langcode][0]['value']) {
+      $grants[] = array(
+        'realm' => 'node_access_language_test',
+        'gid' => 7888,
+        'grant_view' => 1,
+        'grant_update' => 0,
+        'grant_delete' => 0,
+        'priority' => 0,
+        'langcode' => $langcode,
+      );
+      $grants[] = array(
+        'realm' => 'node_access_language_test',
+        'gid' => 7889,
+        'grant_view' => 1,
+        'grant_update' => 0,
+        'grant_delete' => 0,
+        'priority' => 0,
+        'langcode' => $langcode,
+      );
+      // For the author realm, the GID is equivalent to a UID, which
+      // means there are many many groups of just 1 user.
+      $grants[] = array(
+        'realm' => 'node_access_test_language_author',
+        'gid' => $node->uid,
+        'grant_view' => 1,
+        'grant_update' => 1,
+        'grant_delete' => 1,
+        'priority' => 0,
+        'langcode' => $langcode,
+      );
+    } else {
+      $grants[] = array('realm' => 'all', 'gid' => 0, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0, 'langcode' => $langcode);
+    }
+  }
+  return $grants;
+}
+
+/**
+ * Implements hook_permission().
+ *
+ * Sets up permissions for this module.
+ */
+function node_access_test_language_permission() {
+  return array('node access language test view' => array('title' => 'View content'));
+}
+
+function node_access_test_language_enable(){
+  $field_private = array(
+    'field_name' => 'field_private',
+    'type' => 'list_boolean',
+    'cardinality' => 1,
+    'translatable'  => 1,
+    'settings' => array(
+      'allowed_values' => array(0 => 'Not private', 1 => 'Private'),
+    ),
+  );
+  $field_private = field_create_field($field_private);
+
+  $instance = array(
+    'field_name' => $field_private['field_name'],
+    'entity_type' => 'node',
+    'bundle' => 'page',
+    'widget' => array(
+      'type' => 'options_buttons',
+    ),
+  );
+  $instance = field_create_instance($instance);
+}
+
+function node_access_test_language_disable(){
+  field_delete_instance(field_read_instance('node', 'field_private', 'page'));
+}
