diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
index 53be393..e662c27 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
@@ -189,7 +189,7 @@ protected function doLoadMultiple(array $ids = NULL) {
    */
   protected function doCreate(array $values) {
     // Set default language to site default if not provided.
-    $values += array('langcode' => $this->languageManager->getDefaultLanguage()->getId());
+    $values += array($this->langcodeKey => $this->languageManager->getDefaultLanguage()->getId());
     $entity = new $this->entityClass($values, $this->entityTypeId);
 
     return $entity;
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php
index 9948c74..e929d7d 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php
@@ -67,6 +67,7 @@ public function __construct($definition) {
     parent::__construct($definition);
     // Always add a default 'uuid' key.
     $this->entity_keys['uuid'] = 'uuid';
+    $this->entity_keys['langcode'] = 'langcode';
     $this->handlers += array(
       'storage' => 'Drupal\Core\Config\Entity\ConfigEntityStorage',
     );
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 826193b..0d4150f 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Entity\Plugin\DataType\EntityReference;
+use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
@@ -74,6 +75,13 @@
   protected $languages;
 
   /**
+   * The language entity key.
+   *
+   * @var string
+   */
+  protected $langcodeKey;
+
+  /**
    * Language code identifying the entity active language.
    *
    * This is the language field accessors will use to determine which field
@@ -136,6 +144,7 @@ public function __construct(array $values, $entity_type, $bundle = FALSE, $trans
     $this->entityTypeId = $entity_type;
     $this->entityKeys['bundle'] = $bundle ? $bundle : $this->entityTypeId;
     $this->languages = $this->languageManager()->getLanguages(LanguageInterface::STATE_ALL);
+    $this->langcodeKey = $this->getEntityType()->getKey('langcode');
 
     foreach ($values as $key => $value) {
       // If the key matches an existing property set the value to the property
@@ -375,8 +384,8 @@ protected function getTranslatedField($name, $langcode) {
    * {@inheritdoc}
    */
   public function set($name, $value, $notify = TRUE) {
-    // If default language or an entity key changes we need to react to that.
-    $notify = $name == 'langcode' || in_array($name, $this->getEntityType()->getKeys());
+    // If an entity key changes we need to react to that.
+    $notify = in_array($name, $this->getEntityType()->getKeys());
     $this->get($name)->setValue($value, $notify);
   }
 
@@ -474,24 +483,38 @@ public function language() {
    */
   protected function setDefaultLangcode() {
     // Get the language code if the property exists.
-    if ($this->hasField('langcode') && ($item = $this->get('langcode')) && isset($item->language)) {
+    // Try to read the value directly from the list of entity keys which got
+    // initialized in __construct(). This avoids creating a field item object.
+    if (isset($this->entityKeys['langcode'])) {
+      $this->defaultLangcode = $this->entityKeys['langcode'];
+    }
+    elseif ($this->hasField($this->langcodeKey) && ($item = $this->get($this->langcodeKey)) && isset($item->language)) {
       $this->defaultLangcode = $item->language->getId();
+      $this->entityKeys['langcode'] = $this->defaultLangcode;
     }
 
     if (empty($this->defaultLangcode)) {
       // Make sure we return a proper language object, if the entity has a
       // langcode field, default to the site's default language.
-      if ($this->hasField('langcode')) {
+      if ($this->hasField($this->langcodeKey)) {
         $this->defaultLangcode = $this->languageManager()->getDefaultLanguage()->getId();
       }
       else {
         $this->defaultLangcode = LanguageInterface::LANGCODE_NOT_SPECIFIED;
       }
     }
+
+    // If the entity references a language that is not or no longer available,
+    // we return a mock language object to avoid disrupting the consuming
+    // code.
+    if (!isset($this->languages[$this->defaultLangcode])) {
+      $this->languages[$this->defaultLangcode] = new Language(array('id' => $this->defaultLangcode));
+    }
+
     // This needs to be initialized manually as it is skipped when instantiating
     // the language field object to avoid infinite recursion.
-    if (!empty($this->fields['langcode'])) {
-      $this->fields['langcode'][LanguageInterface::LANGCODE_DEFAULT]->setLangcode($this->defaultLangcode);
+    if (!empty($this->fields[$this->langcodeKey])) {
+      $this->fields[$this->langcodeKey][LanguageInterface::LANGCODE_DEFAULT]->setLangcode($this->defaultLangcode);
     }
   }
 
@@ -510,14 +533,6 @@ protected function updateFieldLangcodes($langcode) {
    * {@inheritdoc}
    */
   public function onChange($name) {
-    if ($name == 'langcode') {
-      $this->setDefaultLangcode();
-      if (isset($this->translations[$this->defaultLangcode])) {
-        $message = String::format('A translation already exists for the specified language (@langcode).', array('@langcode' => $this->defaultLangcode));
-        throw new \InvalidArgumentException($message);
-      }
-      $this->updateFieldLangcodes($this->defaultLangcode);
-    }
     // Check if the changed name is the value of an entity key and if the value
     // of that is currently cached, if so, reset it. Exclude the bundle from
     // that check, as it ready only and must not change, unsetting it could
@@ -527,6 +542,16 @@ public function onChange($name) {
         unset($this->entityKeys[$key]);
       }
     }
+
+    // Update the default internal language cache.
+    if ($name == $this->langcodeKey) {
+      $this->setDefaultLangcode();
+      if (isset($this->translations[$this->defaultLangcode])) {
+        $message = String::format('A translation already exists for the specified language (@langcode).', array('@langcode' => $this->defaultLangcode));
+        throw new \InvalidArgumentException($message);
+      }
+      $this->updateFieldLangcodes($this->defaultLangcode);
+    }
   }
 
   /**
@@ -643,7 +668,11 @@ public function addTranslation($langcode, array $values = array()) {
     // Instantiate a new empty entity so default values will be populated in the
     // specified language.
     $entity_type = $this->getEntityType();
-    $default_values = array($entity_type->getKey('bundle') => $this->bundle(), 'langcode' => $langcode);
+
+    $default_values = array(
+      $entity_type->getKey('bundle') => $this->bundle(),
+      $this->langcodeKey => $langcode,
+    );
     $entity = $this->entityManager()
       ->getStorage($this->getEntityTypeId())
       ->create($default_values);
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityForm.php b/core/lib/Drupal/Core/Entity/ContentEntityForm.php
index 9f96efa..d4d2e06 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityForm.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityForm.php
@@ -143,8 +143,9 @@ public function setFormDisplay(EntityFormDisplayInterface $form_display, FormSta
    */
   protected function updateFormLangcode(FormStateInterface $form_state) {
     // Update the form language as it might have changed.
-    if ($form_state->hasValue('langcode') && $this->isDefaultFormLangcode($form_state)) {
-      $form_state->set('langcode', $form_state->getValue('langcode'));
+    $langcode_key = $this->entity->getEntityType()->getKey('langcode');
+    if ($form_state->hasValue($langcode_key) && $this->isDefaultFormLangcode($form_state)) {
+      $form_state->set('langcode', $form_state->getValue($langcode_key));
     }
   }
 
diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index e582f0e..c4c64e9 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -309,7 +309,8 @@ public function access($operation, AccountInterface $account = NULL, $return_as_
    * {@inheritdoc}
    */
   public function language() {
-    $language = $this->languageManager()->getLanguage($this->langcode);
+    $langcode = $this->{$this->getEntityType()->getKey('langcode')};
+    $language = $this->languageManager()->getLanguage($langcode);
     if (!$language) {
       // Make sure we return a proper language object.
       $langcode = $this->langcode ?: LanguageInterface::LANGCODE_NOT_SPECIFIED;
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 128d21d..a985a57 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -427,7 +427,7 @@ protected function buildBaseFieldDefinitions($entity_type_id) {
 
     // Ensure defined entity keys are there and have proper revisionable and
     // translatable values.
-    $keys = array_filter($entity_type->getKeys() + array('langcode' => 'langcode'));
+    $keys = array_filter($entity_type->getKeys());
     foreach ($keys as $key => $field_name) {
       if (isset($base_field_definitions[$field_name]) && in_array($key, array('id', 'revision', 'uuid', 'bundle')) && $base_field_definitions[$field_name]->isRevisionable()) {
         throw new \LogicException(String::format('The @field field cannot be revisionable as it is used as @key entity key.', array('@field' => $base_field_definitions[$field_name]->getLabel(), '@key' => $key)));
diff --git a/core/lib/Drupal/Core/Entity/EntityStorageBase.php b/core/lib/Drupal/Core/Entity/EntityStorageBase.php
index 4a40a9e..c2f9671 100644
--- a/core/lib/Drupal/Core/Entity/EntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityStorageBase.php
@@ -53,6 +53,13 @@
   protected $uuidKey;
 
   /**
+   * The name of the entity langcode property.
+   *
+   * @var string
+   */
+  protected $langcodeKey;
+
+  /**
    * The UUID service.
    *
    * @var \Drupal\Component\Uuid\UuidInterface
@@ -77,6 +84,7 @@ public function __construct(EntityTypeInterface $entity_type) {
     $this->entityType = $entity_type;
     $this->idKey = $this->entityType->getKey('id');
     $this->uuidKey = $this->entityType->getKey('uuid');
+    $this->langcodeKey = $this->entityType->getKey('langcode');
     $this->entityClass = $this->entityType->getClass();
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php
index 5ea863d..406e929 100644
--- a/core/lib/Drupal/Core/Entity/EntityType.php
+++ b/core/lib/Drupal/Core/Entity/EntityType.php
@@ -236,7 +236,8 @@ public function __construct($definition) {
     // Ensure defaults.
     $this->entity_keys += array(
       'revision' => '',
-      'bundle' => ''
+      'bundle' => '',
+      'langcode' => '',
     );
     $this->handlers += array(
       'access' => 'Drupal\Core\Entity\EntityAccessControlHandler',
diff --git a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
index f8237a5..b62a675 100644
--- a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php
@@ -105,12 +105,15 @@ public function getOriginalClass();
    *     entry can be omitted if this entity type exposes a single bundle (such
    *     that all entities have the same collection of fields). The name of this
    *     single bundle will be the same as the entity type.
-   *   - label: The name of the property that contains the entity label. For
-   *     example, if the entity's label is located in $entity->subject, then
-   *     'subject' should be specified here. If complex logic is required to
-   *     build the label, a 'label_callback' should be defined instead (see the
-   *     $label_callback block above for details).
-   *   - uuid (optional): The name of the property that contains the universally
+   *   - label: (optional) The name of the property that contains the entity
+   *     label. For example, if the entity's label is located in
+   *     $entity->subject, then 'subject' should be specified here. If complex
+   *     logic is required to build the label, a 'label_callback' should be
+   *     defined instead (see the $label_callback block above for details).
+   *   - langcode: (optional) The name of the property that contains the
+   *     language code. For instance, if the entity's language is located in
+   *     $entity->langcode, then 'langcode' should be specified here.
+   *   - uuid: (optional) The name of the property that contains the universally
    *     unique identifier of the entity, which is used to distinctly identify
    *     an entity across different systems.
    */
diff --git a/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php b/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php
index 59ca4d8..5c25492 100644
--- a/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/KeyValueStore/KeyValueEntityStorage.php
@@ -94,7 +94,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
    */
   public function doCreate(array $values = array()) {
     // Set default language to site default if not provided.
-    $values += array('langcode' => $this->languageManager->getDefaultLanguage()->getId());
+    $values += array($this->getEntityType()->getKey('langcode') => $this->languageManager->getDefaultLanguage()->getId());
     $entity = new $this->entityClass($values, $this->entityTypeId);
 
     // @todo This is handled by ContentEntityStorageBase, which assumes
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index b8db248..b811ee5 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -186,7 +186,7 @@ protected function initTableLayout() {
     $translatable = $this->entityType->isTranslatable();
     if ($translatable) {
       $this->dataTable = $this->entityType->getDataTable() ?: $this->entityTypeId . '_field_data';
-      $this->langcodeKey = $this->entityType->getKey('langcode') ?: 'langcode';
+      $this->langcodeKey = $this->entityType->getKey('langcode');
       $this->defaultLangcodeKey = $this->entityType->getKey('default_langcode') ?: 'default_langcode';
     }
     if ($revisionable && $translatable) {
@@ -682,7 +682,7 @@ protected function attachPropertyData(array &$entities) {
 
         // Field values in default language are stored with
         // LanguageInterface::LANGCODE_DEFAULT as key.
-        $langcode = empty($values['default_langcode']) ? $values['langcode'] : LanguageInterface::LANGCODE_DEFAULT;
+        $langcode = empty($values['default_langcode']) ? $values[$this->langcodeKey] : LanguageInterface::LANGCODE_DEFAULT;
         $translations[$id][$langcode] = TRUE;
 
 
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
index dac6584..6366255 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
@@ -885,11 +885,15 @@ protected function initializeDataTable(ContentEntityTypeInterface $entity_type)
     $entity_type_id = $entity_type->id();
     $id_key = $entity_type->getKey('id');
 
+    if (!$entity_type->getKey('langcode')) {
+      throw new \Exception(String::format('Missing langcode entity key for entity type "@entity_type_id"', array('@entity_type_id' => $entity_type->getKey('langcode'))));
+    }
+
     $schema = array(
       'description' => "The data table for $entity_type_id entities.",
       // @todo Use the language entity key when https://drupal.org/node/2143729
       //   is in.
-      'primary key' => array($id_key, 'langcode'),
+      'primary key' => array($id_key, $entity_type->getKey('langcode')),
       'indexes' => array(),
       'foreign keys' => array(
         $entity_type_id => array(
@@ -927,7 +931,7 @@ protected function initializeRevisionDataTable(ContentEntityTypeInterface $entit
       'description' => "The revision data table for $entity_type_id entities.",
       // @todo Use the language entity key when https://drupal.org/node/2143729
       //   is in.
-      'primary key' => array($revision_key, 'langcode'),
+      'primary key' => array($revision_key, $entity_type->getKey('langcode')),
       'indexes' => array(),
       'foreign keys' => array(
         $entity_type_id => array(
@@ -1405,7 +1409,7 @@ protected function getSharedTableFieldSchema(FieldStorageDefinitionInterface $st
       $schema['fields'][$schema_field_name] = $column_schema;
       $schema['fields'][$schema_field_name]['description'] = $field_description;
       // Only entity keys are required.
-      $keys = $this->entityType->getKeys() + array('langcode' => 'langcode');
+      $keys = $this->entityType->getKeys();
       // The label is an entity key, but label fields are not necessarily
       // required.
       // Because entity ID and revision ID are both serial fields in the base
diff --git a/core/modules/aggregator/src/Entity/Feed.php b/core/modules/aggregator/src/Entity/Feed.php
index 6532f36..f6efd2d 100644
--- a/core/modules/aggregator/src/Entity/Feed.php
+++ b/core/modules/aggregator/src/Entity/Feed.php
@@ -43,6 +43,7 @@
  *   entity_keys = {
  *     "id" = "fid",
  *     "label" = "title",
+ *     "langcode" = "langcode",
  *     "uuid" = "uuid",
  *   }
  * )
diff --git a/core/modules/aggregator/src/Entity/Item.php b/core/modules/aggregator/src/Entity/Item.php
index 066b7ff..21a0dca 100644
--- a/core/modules/aggregator/src/Entity/Item.php
+++ b/core/modules/aggregator/src/Entity/Item.php
@@ -35,6 +35,7 @@
  *   entity_keys = {
  *     "id" = "iid",
  *     "label" = "title",
+ *     "langcode" = "langcode",
  *   }
  * )
  */
diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php
index e2320bd..63dcbb9 100644
--- a/core/modules/block_content/src/Entity/BlockContent.php
+++ b/core/modules/block_content/src/Entity/BlockContent.php
@@ -49,6 +49,7 @@
  *     "revision" = "revision_id",
  *     "bundle" = "type",
  *     "label" = "info",
+ *     "langcode" = "langcode",
  *     "uuid" = "uuid"
  *   },
  *   bundle_entity_type = "block_content_type",
diff --git a/core/modules/comment/src/Entity/Comment.php b/core/modules/comment/src/Entity/Comment.php
index 57c7287..1fc4607 100644
--- a/core/modules/comment/src/Entity/Comment.php
+++ b/core/modules/comment/src/Entity/Comment.php
@@ -43,6 +43,7 @@
  *     "id" = "cid",
  *     "bundle" = "comment_type",
  *     "label" = "subject",
+ *     "langcode" = "langcode",
  *     "uuid" = "uuid"
  *   },
  *   links = {
diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php
index b1b6e9b..63760e2 100644
--- a/core/modules/content_translation/src/ContentTranslationHandler.php
+++ b/core/modules/content_translation/src/ContentTranslationHandler.php
@@ -147,19 +147,20 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En
     // Disable languages for existing translations, so it is not possible to
     // switch this node to some language which is already in the translation
     // set.
-    $language_widget = isset($form['langcode']) && $form['langcode']['#type'] == 'language_select';
+    $langcode_key = $this->entityType->getKey('langcode');
+    $language_widget = isset($form[$langcode_key]) && $form[$langcode_key]['#type'] == 'language_select';
     if ($language_widget && $has_translations) {
-      $form['langcode']['#options'] = array();
+      $form[$langcode_key]['#options'] = array();
       foreach (language_list(LanguageInterface::STATE_CONFIGURABLE) as $language) {
         if (empty($translations[$language->getId()]) || $language->getId() == $entity_langcode) {
-          $form['langcode']['#options'][$language->getId()] = $language->getName();
+          $form[$langcode_key]['#options'][$language->getId()] = $language->getName();
         }
       }
     }
 
     if ($is_translation) {
       if ($language_widget) {
-        $form['langcode']['#access'] = FALSE;
+        $form[$langcode_key]['#access'] = FALSE;
       }
 
       // Replace the delete button with the delete translation one.
@@ -272,7 +273,7 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En
       );
 
       if ($language_widget) {
-        $form['langcode']['#multilingual'] = TRUE;
+        $form[$langcode_key]['#multilingual'] = TRUE;
       }
 
       $form['#process'][] = array($this, 'entityFormSharedElements');
diff --git a/core/modules/file/src/Entity/File.php b/core/modules/file/src/Entity/File.php
index b21a182..de50c92 100644
--- a/core/modules/file/src/Entity/File.php
+++ b/core/modules/file/src/Entity/File.php
@@ -32,6 +32,7 @@
  *   entity_keys = {
  *     "id" = "fid",
  *     "label" = "filename",
+ *     "langcode" = "langcode",
  *     "uuid" = "uuid"
  *   }
  * )
@@ -39,17 +40,6 @@
 class File extends ContentEntityBase implements FileInterface {
 
   /**
-   * The plain data values of the contained properties.
-   *
-   * Define default values.
-   *
-   * @var array
-   */
-  protected $values = array(
-    'langcode' => array(LanguageInterface::LANGCODE_DEFAULT => array(0 => array('value' => LanguageInterface::LANGCODE_NOT_SPECIFIED))),
-  );
-
-  /**
    * {@inheritdoc}
    */
   public function getFilename() {
diff --git a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
index 8ae74de..34a122a 100644
--- a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
+++ b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
@@ -133,16 +133,17 @@ public function denormalize($data, $class, $format = NULL, array $context = arra
 
     // Create the entity.
     $typed_data_ids = $this->getTypedDataIds($data['_links']['type']);
+    $entity_type = $this->entityManager->getDefinition($typed_data_ids['entity_type']);
+    $langcode_key = $entity_type->getKey('langcode');
     $values = array();
+
     // Figure out the language to use.
-    if (isset($data['langcode'])) {
-      $values['langcode'] = $data['langcode'][0]['value'];
+    if (isset($data[$langcode_key])) {
+      $values[$langcode_key] = $data[$langcode_key][0]['value'];
       // Remove the langcode so it does not get iterated over below.
-      unset($data['langcode']);
+      unset($data[$langcode_key]);
     }
 
-    $entity_type = $this->entityManager->getDefinition($typed_data_ids['entity_type']);
-
     if ($entity_type->hasKey('bundle')) {
       $bundle_key = $entity_type->getKey('bundle');
       $values[$bundle_key] = $typed_data_ids['bundle'];
diff --git a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
index 9b44af0..4a7b96a 100644
--- a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
+++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
@@ -35,6 +35,7 @@
  *   entity_keys = {
  *     "id" = "id",
  *     "label" = "title",
+ *     "langcode" = "langcode",
  *     "uuid" = "uuid",
  *     "bundle" = "bundle"
  *   },
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index 4b7671f..2399430 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -47,6 +47,7 @@
  *     "revision" = "vid",
  *     "bundle" = "type",
  *     "label" = "title",
+ *     "langcode" = "langcode",
  *     "uuid" = "uuid"
  *   },
  *   bundle_entity_type = "node_type",
diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
index c58ff1a..7f4e7f7 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -134,13 +134,14 @@ public function patch(EntityInterface $original_entity, EntityInterface $entity
     }
 
     // Overwrite the received properties.
+    $langcode_key = $entity->getEntityType()->getKey('langcode');
     foreach ($entity as $field_name => $field) {
       if (isset($entity->{$field_name})) {
         // It is not possible to set the language to NULL as it is automatically
         // re-initialized. As it must not be empty, skip it if it is.
         // @todo: Use the langcode entity key when available. See
         //   https://drupal.org/node/2143729.
-        if ($field_name == 'langcode' && $field->isEmpty()) {
+        if ($field_name == $langcode_key && $field->isEmpty()) {
           continue;
         }
         if ($field->isEmpty() && !$original_entity->get($field_name)->access('delete')) {
diff --git a/core/modules/shortcut/src/Entity/Shortcut.php b/core/modules/shortcut/src/Entity/Shortcut.php
index 770406a..1956b6c 100644
--- a/core/modules/shortcut/src/Entity/Shortcut.php
+++ b/core/modules/shortcut/src/Entity/Shortcut.php
@@ -39,7 +39,8 @@
  *     "id" = "id",
  *     "uuid" = "uuid",
  *     "bundle" = "shortcut_set",
- *     "label" = "title"
+ *     "label" = "title",
+ *     "langcode" = "langcode",
  *   },
  *   links = {
  *     "canonical" = "entity.shortcut.canonical",
diff --git a/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php b/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php
index 5707234..8d9305c 100644
--- a/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php
+++ b/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php
@@ -53,9 +53,11 @@ public function testInstaller() {
     $this->assertResponse(200);
 
     $account = User::load(0);
-    $this->assertEqual($account->language()->getId(), 'de', 'Anonymous user is German.');
+    $this->assertEqual($account->language()->getId(), 'en', 'Anonymous user is English.');
     $account = User::load(1);
-    $this->assertEqual($account->language()->getId(), 'de', 'Administrator user is German.');
+    $this->assertEqual($account->language()->getId(), 'en', 'Administrator user is English.');
+    $account = $this->drupalCreateUser();
+    $this->assertEqual($account->language()->getId(), 'de', 'New user is German.');
 
     // Ensure that we can enable basic_auth on a non-english site.
     $this->drupalPostForm('admin/modules', array('modules[Web services][basic_auth][enable]' => TRUE), t('Save configuration'));
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php
index c583c46..ededaf8 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php
@@ -38,7 +38,8 @@
  *     "id" = "id",
  *     "uuid" = "uuid",
  *     "bundle" = "type",
- *     "label" = "name"
+ *     "label" = "name",
+ *     "langcode" = "langcode",
  *   },
  *   links = {
  *     "canonical" = "entity.entity_test.canonical",
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestDefaultValue.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestDefaultValue.php
index 1c1797f..28905da 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestDefaultValue.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestDefaultValue.php
@@ -20,7 +20,8 @@
  *   entity_keys = {
  *     "id" = "id",
  *     "uuid" = "uuid",
- *     "bundle" = "type"
+ *     "bundle" = "type",
+ *     "langcode" = "langcode"
  *   }
  * )
  */
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMul.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMul.php
index 402936f..cabb610 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMul.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMul.php
@@ -34,7 +34,8 @@
  *     "id" = "id",
  *     "uuid" = "uuid",
  *     "bundle" = "type",
- *     "label" = "name"
+ *     "label" = "name",
+ *     "langcode" = "langcode",
  *   },
  *   links = {
  *     "canonical" = "entity.entity_test_mul.edit_form",
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulDefaultValue.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulDefaultValue.php
index 33369ac..fa3a60e 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulDefaultValue.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulDefaultValue.php
@@ -33,7 +33,8 @@
  *     "id" = "id",
  *     "uuid" = "uuid",
  *     "bundle" = "type",
- *     "label" = "name"
+ *     "label" = "name",
+ *     "langcode" = "langcode"
  *   },
  *   links = {
  *     "canonical" = "entity.entity_test_mul.edit_form",
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRev.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRev.php
index b5fc86f..3d4de93 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRev.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRev.php
@@ -35,7 +35,8 @@
  *     "id" = "id",
  *     "uuid" = "uuid",
  *     "revision" = "revision_id",
- *     "bundle" = "type"
+ *     "bundle" = "type",
+ *     "langcode" = "langcode",
  *   },
  *   links = {
  *     "canonical" = "entity.entity_test_mulrev.edit_form",
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php
index 3b40ed9..f5bee90 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php
@@ -34,6 +34,7 @@
  *     "revision" = "revision_id",
  *     "bundle" = "type",
  *     "label" = "name",
+ *     "langcode" = "langcode",
  *   },
  *   links = {
  *     "canonical" = "entity.entity_test_rev.edit_form",
diff --git a/core/modules/taxonomy/src/Entity/Term.php b/core/modules/taxonomy/src/Entity/Term.php
index caebc53..d406a48 100644
--- a/core/modules/taxonomy/src/Entity/Term.php
+++ b/core/modules/taxonomy/src/Entity/Term.php
@@ -40,6 +40,7 @@
  *     "id" = "tid",
  *     "bundle" = "vid",
  *     "label" = "name",
+ *     "langcode" = "langcode",
  *     "uuid" = "uuid"
  *   },
  *   bundle_entity_type = "taxonomy_vocabulary",
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index c003db2..cc65e3a 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -44,6 +44,7 @@
  *   translatable = TRUE,
  *   entity_keys = {
  *     "id" = "uid",
+ *     "langcode" = "langcode",
  *     "uuid" = "uuid"
  *   },
  *   links = {
diff --git a/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
index d03e5d5..9b0e0da 100644
--- a/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
+++ b/core/modules/views/src/Entity/Render/TranslationLanguageRenderer.php
@@ -34,11 +34,11 @@ public function query(QueryPluginBase $query) {
     // If the data table is defined, we use the translation language as render
     // language, otherwise we fall back to the default entity language, which is
     // stored in the revision table for revisionable entity types.
-    $entity_info = $this->view->rowPlugin->entityManager->getDefinition($this->entityType->id());
+    $langcode_key = $this->entityType->getKey('langcode');
     foreach (array('data_table', 'revision_table', 'base_table') as $key) {
-      if ($table = $entity_info->get($key)) {
+      if ($table = $this->entityType->get($key)) {
         $table_alias = $query->ensureTable($table);
-        $this->langcodeAlias = $query->addField($table_alias, 'langcode');
+        $this->langcodeAlias = $query->addField($table_alias, $langcode_key);
         break;
       }
     }
diff --git a/core/modules/views/src/EntityViewsData.php b/core/modules/views/src/EntityViewsData.php
index 4bb38fe..b33c491 100644
--- a/core/modules/views/src/EntityViewsData.php
+++ b/core/modules/views/src/EntityViewsData.php
@@ -386,7 +386,7 @@ protected function mapSingleFieldViewsData($table, $field_name, $field_type, $co
    */
   protected function processViewsDataForLanguage($table, FieldDefinitionInterface $field_definition, array &$views_field, $field_column_name) {
     // Apply special titles for the langcode field.
-    if ($field_definition->getName() == 'langcode') {
+    if ($field_definition->getName() == $this->entityType->getKey('langcode')) {
       if ($table == $this->entityType->getDataTable() || $table == $this->entityType->getRevisionDataTable()) {
         $views_field['title'] = $this->t('Translation language');
       }
diff --git a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
index 476a199..8754054 100644
--- a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
+++ b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
@@ -87,7 +87,7 @@ protected function setUp() {
       'base_table' => 'entity_test',
       'id' => 'entity_test',
       'label' => 'Entity test',
-      'entity_keys' => ['id' => 'id'],
+      'entity_keys' => ['id' => 'id', 'langcode' => 'langcode'],
       'provider' => 'entity_test',
     ]);
 
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
index fb14691..c52fd57 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
@@ -111,6 +111,7 @@ protected function setUp() {
       ->will($this->returnValueMap(array(
         array('id', 'id'),
         array('uuid', 'uuid'),
+        array('langcode', 'langcode'),
       )));
     $this->entityType->expects($this->any())
       ->method('id')
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
index 933b7ed..a130905 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -658,7 +658,7 @@ public function testGetFieldStorageDefinitionsWithCaching() {
    * @expectedException \LogicException
    */
   public function testGetBaseFieldDefinitionsInvalidDefinition() {
-    $langcode_definition = $this->setUpEntityWithFieldDefinition(FALSE, 'langcode');
+    $langcode_definition = $this->setUpEntityWithFieldDefinition(FALSE, 'langcode', array('langcode' => 'langcode'));
     $langcode_definition->expects($this->once())
       ->method('isTranslatable')
       ->will($this->returnValue(TRUE));
@@ -710,11 +710,14 @@ public function testGetFieldDefinitionsProvider() {
    *   ModuleHandlerInterface::invokeAll() implementation. Defaults to FALSE.
    * @param string $field_definition_id
    *   (optional) The ID to use for the field definition. Defaults to 'id'.
+   * @param array $entity_keys
+   *   (optional) An array of entity keys for the mocked entity type. Defaults
+   *   to an empty array.
    *
    * @return \Drupal\Core\Field\BaseFieldDefinition|\PHPUnit_Framework_MockObject_MockObject
    *   A field definition object.
    */
-  protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $field_definition_id = 'id') {
+  protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $field_definition_id = 'id', $entity_keys = array()) {
     $entity_type = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
     $entity = $this->getMockBuilder('Drupal\Tests\Core\Entity\EntityManagerTestEntity')
       ->disableOriginalConstructor()
@@ -726,7 +729,7 @@ protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $f
       ->will($this->returnValue($entity_class));
     $entity_type->expects($this->any())
       ->method('getKeys')
-      ->will($this->returnValue(array()));
+      ->will($this->returnValue($entity_keys));
     $entity_type->expects($this->any())
       ->method('isSubclassOf')
       ->with($this->equalTo('\Drupal\Core\Entity\FieldableEntityInterface'))
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
index 4ff2f23..c6d70ce 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
@@ -69,9 +69,9 @@ public function testHasKey($entity_keys, $expected) {
    */
   public function providerTestGetKeys() {
     return array(
-      array(array(), array('revision' => '', 'bundle' => '')),
-      array(array('id' => 'id'), array('id' => 'id', 'revision' => '', 'bundle' => '')),
-      array(array('bundle' => 'bundle'), array('bundle' => 'bundle', 'revision' => '')),
+      array(array(), array('revision' => '', 'bundle' => '', 'langcode' => '')),
+      array(array('id' => 'id'), array('id' => 'id', 'revision' => '', 'bundle' => '', 'langcode' => '')),
+      array(array('bundle' => 'bundle'), array('bundle' => 'bundle', 'revision' => '', 'langcode' => '')),
     );
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
index 6535732..a531489 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
@@ -233,6 +233,11 @@ public function testAccess() {
    * @covers ::language
    */
   public function testLanguage() {
+    $this->entityType->expects($this->any())
+      ->method('getKey')
+      ->will($this->returnValueMap(array(
+        array('langcode', 'langcode'),
+      )));
     $this->assertSame('en', $this->entity->language()->getId());
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
index ee10e54..300151a 100644
--- a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php
@@ -96,6 +96,7 @@ protected function setUpKeyValueEntityStorage($uuid_key = 'uuid') {
       ->will($this->returnValueMap(array(
         array('id', 'id'),
         array('uuid', $uuid_key),
+        array('langcode', 'langcode'),
       )));
     $this->entityType->expects($this->atLeastOnce())
       ->method('id')
diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
index 3a28de0..a1f3723 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
@@ -499,6 +499,7 @@ public function testGetSchemaTranslatable() {
       'id' => 'entity_test',
       'entity_keys' => array(
         'id' => 'id',
+        'langcode' => 'langcode',
       ),
     ));
 
@@ -592,6 +593,7 @@ public function testGetSchemaRevisionableTranslatable() {
       'entity_keys' => array(
         'id' => 'id',
         'revision' => 'revision_id',
+        'langcode' => 'langcode',
       ),
     ));
 
diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
index 3589a63..0ff4939 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
@@ -607,6 +607,7 @@ public function testGetTableMappingTranslatable(array $entity_keys) {
         array('id', $entity_keys['id']),
         array('uuid', $entity_keys['uuid']),
         array('bundle', $entity_keys['bundle']),
+        array('langcode', $entity_keys['langcode']),
       )));
 
     $this->setUpEntityStorage();
@@ -667,6 +668,7 @@ public function testGetTableMappingTranslatableWithFields(array $entity_keys) {
         array('id', $entity_keys['id']),
         array('uuid', $entity_keys['uuid']),
         array('bundle', $entity_keys['bundle']),
+        array('langcode', $entity_keys['langcode']),
       )));
 
     $this->setUpEntityStorage();
@@ -733,6 +735,7 @@ public function testGetTableMappingRevisionableTranslatable(array $entity_keys)
         array('uuid', $entity_keys['uuid']),
         array('bundle', $entity_keys['bundle']),
         array('revision', $entity_keys['revision']),
+        array('langcode', $entity_keys['langcode']),
       )));
 
     $this->setUpEntityStorage();
@@ -854,6 +857,7 @@ public function testGetTableMappingRevisionableTranslatableWithFields(array $ent
           array('uuid', $entity_keys['uuid']),
           array('bundle', $entity_keys['bundle']),
           array('revision', $entity_keys['revision']),
+          array('langcode', $entity_keys['langcode']),
         )));
 
       $this->setUpEntityStorage();
