diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
index a031ac8..ca6ed7a 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 ef46168..3fe34f1 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 071f584..b4e07b2 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
@@ -135,6 +143,7 @@
   public function __construct(array $values, $entity_type, $bundle = FALSE, $translations = array()) {
     $this->entityTypeId = $entity_type;
     $this->entityKeys['bundle'] = $bundle ? $bundle : $this->entityTypeId;
+    $this->langcodeKey = $this->getEntityType()->getKey('langcode');
 
     foreach ($values as $key => $value) {
       // If the key matches an existing property set the value to the property
@@ -190,6 +199,12 @@ protected function typedDataManager() {
   protected function getLanguages() {
     if (empty($this->languages)) {
       $this->languages = $this->languageManager()->getLanguages(LanguageInterface::STATE_ALL);
+      // 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));
+      }
     }
     return $this->languages;
   }
@@ -485,24 +500,31 @@ 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;
       }
     }
+
     // 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);
     }
   }
 
@@ -521,14 +543,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
@@ -538,6 +552,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);
+    }
   }
 
   /**
@@ -656,7 +680,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 a867053..c76dc40 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 7d7eded..df404d8 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -434,7 +434,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 d4daa67..7a43b75 100644
--- a/core/lib/Drupal/Core/Entity/EntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/EntityStorageBase.php
@@ -58,6 +58,13 @@
   protected $uuidKey;
 
   /**
+   * The name of the entity langcode property.
+   *
+   * @var string
+   */
+  protected $langcodeKey;
+
+  /**
    * The UUID service.
    *
    * @var \Drupal\Component\Uuid\UuidInterface
@@ -82,6 +89,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 faf8856..c5d90ca 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 ec61644..e2ba2a9 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 3507502..365020c 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/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
index ffd84d4..e001e3d 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
@@ -262,8 +262,10 @@ protected function ensureFieldTable($index_prefix, &$field, $type, $langcode, $b
   protected function addJoin($type, $table, $join_condition, $langcode) {
     $arguments = array();
     if ($langcode) {
+      $entity_type_id = $this->sqlQuery->getMetaData('entity_type');
+      $langcode_key = $this->entityManager->getDefinition($entity_type_id)->getKey('langcode');
       $placeholder = ':langcode' . $this->sqlQuery->nextPlaceholder();
-      $join_condition .= ' AND %alias.langcode = ' . $placeholder;
+      $join_condition .= ' AND %alias.' . $langcode_key . ' = ' . $placeholder;
       $arguments[$placeholder] = $langcode;
     }
     return $this->sqlQuery->addJoin($type, $table, NULL, $join_condition, $arguments);
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 40a695e..e531d09 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;
 
 
@@ -1145,8 +1145,8 @@ protected function mapToDataStorageRecord(EntityInterface $entity, $table_name =
       $table_name = $this->dataTable;
     }
     $record = $this->mapToStorageRecord($entity, $table_name);
-    $record->langcode = $entity->language()->getId();
-    $record->default_langcode = intval($record->langcode == $entity->getUntranslated()->language()->getId());
+    $record->{$this->langcodeKey} = $entity->language()->getId();
+    $record->default_langcode = intval($record->{$this->langcodeKey} == $entity->getUntranslated()->language()->getId());
     return $record;
   }
 
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
index d3087b7..c0356c8 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
@@ -877,11 +877,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(
@@ -919,7 +923,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(
@@ -1397,7 +1401,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 d1ae4f6..ea3128f 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/Entity/EntityApiTest.php b/core/modules/system/src/Tests/Entity/EntityApiTest.php
index f30e94d..8e5b5ce 100644
--- a/core/modules/system/src/Tests/Entity/EntityApiTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityApiTest.php
@@ -17,11 +17,15 @@
  */
 class EntityApiTest extends EntityUnitTestBase {
 
+  /**
+   * @inheritdoc
+   */
   protected function setUp() {
     parent::setUp();
 
     $this->installEntitySchema('entity_test_rev');
     $this->installEntitySchema('entity_test_mul');
+    $this->installEntitySchema('entity_test_mul_langcode_key');
     $this->installEntitySchema('entity_test_mulrev');
   }
 
diff --git a/core/modules/system/src/Tests/Entity/EntityFieldDefaultValueTest.php b/core/modules/system/src/Tests/Entity/EntityFieldDefaultValueTest.php
index d315cb9..ecc5578 100644
--- a/core/modules/system/src/Tests/Entity/EntityFieldDefaultValueTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityFieldDefaultValueTest.php
@@ -44,13 +44,15 @@ public function testDefaultValues() {
   /**
    * Executes a test set for a defined entity type.
    *
-   * @param string $entity_type
+   * @param string $entity_type_id
    *   The entity type to run the tests with.
    */
-  protected function assertDefaultValues($entity_type) {
-    $entity = entity_create($entity_type);
-    $this->assertEqual($entity->langcode->value, 'en', String::format('%entity_type: Default language', array('%entity_type' => $entity_type)));
-    $this->assertTrue(Uuid::isValid($entity->uuid->value), String::format('%entity_type: Default UUID', array('%entity_type' => $entity_type)));
+  protected function assertDefaultValues($entity_type_id) {
+    $entity = entity_create($entity_type_id);
+    $definition = $this->entityManager->getDefinition($entity_type_id);
+    $langcode_key = $definition->getKey('langcode');
+    $this->assertEqual($entity->{$langcode_key}->value, 'en', String::format('%entity_type: Default language', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue(Uuid::isValid($entity->uuid->value), String::format('%entity_type: Default UUID', array('%entity_type' => $entity_type_id)));
     $this->assertEqual($entity->name->getValue(), array(0 => array('value' => NULL)), 'Field has one empty value by default.');
   }
 
diff --git a/core/modules/system/src/Tests/Entity/EntityFieldTest.php b/core/modules/system/src/Tests/Entity/EntityFieldTest.php
index 45709b9..5bd4a51 100644
--- a/core/modules/system/src/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityFieldTest.php
@@ -52,6 +52,7 @@ protected function setUp() {
 
     $this->installEntitySchema('entity_test_rev');
     $this->installEntitySchema('entity_test_mul');
+    $this->installEntitySchema('entity_test_mul_langcode_key');
     $this->installEntitySchema('entity_test_mulrev');
 
     // Create the test field.
@@ -96,108 +97,108 @@ public function testReadWrite() {
   /**
    * Executes the read write test set for a defined entity type.
    *
-   * @param string $entity_type
+   * @param string $entity_type_id
    *   The entity type to run the tests with.
    */
-  protected function doTestReadWrite($entity_type) {
-    $entity = $this->createTestEntity($entity_type);
+  protected function doTestReadWrite($entity_type_id) {
+    $entity = $this->createTestEntity($entity_type_id);
 
     $langcode = 'en';
 
     // Access the name field.
-    $this->assertTrue($entity->name instanceof FieldItemListInterface, format_string('%entity_type: Field implements interface', array('%entity_type' => $entity_type)));
-    $this->assertTrue($entity->name[0] instanceof FieldItemInterface, format_string('%entity_type: Field item implements interface', array('%entity_type' => $entity_type)));
+    $this->assertTrue($entity->name instanceof FieldItemListInterface, format_string('%entity_type: Field implements interface', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue($entity->name[0] instanceof FieldItemInterface, format_string('%entity_type: Field item implements interface', array('%entity_type' => $entity_type_id)));
 
-    $this->assertEqual($this->entity_name, $entity->name->value, format_string('%entity_type: Name value can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_name, $entity->name[0]->value, format_string('%entity_type: Name value can be read through list access.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($entity->name->getValue(), array(0 => array('value' => $this->entity_name)), format_string('%entity_type: Plain field value returned.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($this->entity_name, $entity->name->value, format_string('%entity_type: Name value can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($this->entity_name, $entity->name[0]->value, format_string('%entity_type: Name value can be read through list access.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($entity->name->getValue(), array(0 => array('value' => $this->entity_name)), format_string('%entity_type: Plain field value returned.', array('%entity_type' => $entity_type_id)));
 
     // Change the name.
     $new_name = $this->randomMachineName();
     $entity->name->value = $new_name;
-    $this->assertEqual($new_name, $entity->name->value, format_string('%entity_type: Name can be updated and read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($entity->name->getValue(), array(0 => array('value' => $new_name)), format_string('%entity_type: Plain field value reflects the update.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($new_name, $entity->name->value, format_string('%entity_type: Name can be updated and read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($entity->name->getValue(), array(0 => array('value' => $new_name)), format_string('%entity_type: Plain field value reflects the update.', array('%entity_type' => $entity_type_id)));
 
     $new_name = $this->randomMachineName();
     $entity->name[0]->value = $new_name;
-    $this->assertEqual($new_name, $entity->name->value, format_string('%entity_type: Name can be updated and read through list access.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($new_name, $entity->name->value, format_string('%entity_type: Name can be updated and read through list access.', array('%entity_type' => $entity_type_id)));
 
     // Access the user field.
-    $this->assertTrue($entity->user_id instanceof FieldItemListInterface, format_string('%entity_type: Field implements interface', array('%entity_type' => $entity_type)));
-    $this->assertTrue($entity->user_id[0] instanceof FieldItemInterface, format_string('%entity_type: Field item implements interface', array('%entity_type' => $entity_type)));
+    $this->assertTrue($entity->user_id instanceof FieldItemListInterface, format_string('%entity_type: Field implements interface', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue($entity->user_id[0] instanceof FieldItemInterface, format_string('%entity_type: Field item implements interface', array('%entity_type' => $entity_type_id)));
 
-    $this->assertEqual($this->entity_user->id(), $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_user->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($this->entity_user->id(), $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($this->entity_user->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type_id)));
 
     // Change the assigned user by entity.
     $new_user1 = $this->createUser();
     $entity->user_id->entity = $new_user1;
-    $this->assertEqual($new_user1->id(), $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($new_user1->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: Updated username value can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($new_user1->id(), $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($new_user1->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: Updated username value can be read.', array('%entity_type' => $entity_type_id)));
 
     // Change the assigned user by id.
     $new_user2 = $this->createUser();
     $entity->user_id->target_id = $new_user2->id();
-    $this->assertEqual($new_user2->id(), $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($new_user2->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: Updated username value can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($new_user2->id(), $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($new_user2->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: Updated username value can be read.', array('%entity_type' => $entity_type_id)));
 
     // Try unsetting a field.
     $entity->name->value = NULL;
     $entity->user_id->target_id = NULL;
-    $this->assertNull($entity->name->value, format_string('%entity_type: Name field is not set.', array('%entity_type' => $entity_type)));
-    $this->assertNull($entity->user_id->target_id, format_string('%entity_type: User ID field is not set.', array('%entity_type' => $entity_type)));
-    $this->assertNull($entity->user_id->entity, format_string('%entity_type: User entity field is not set.', array('%entity_type' => $entity_type)));
+    $this->assertNull($entity->name->value, format_string('%entity_type: Name field is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertNull($entity->user_id->target_id, format_string('%entity_type: User ID field is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertNull($entity->user_id->entity, format_string('%entity_type: User entity field is not set.', array('%entity_type' => $entity_type_id)));
 
     // Test setting the values via the typed data API works as well.
     // Change the assigned user by entity.
     $entity->user_id->first()->get('entity')->setValue($new_user2);
-    $this->assertEqual($new_user2->id(), $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($new_user2->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($new_user2->id(), $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($new_user2->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type_id)));
 
-     // Change the assigned user by id.
+    // Change the assigned user by id.
     $entity->user_id->first()->get('target_id')->setValue($new_user2->id());
-    $this->assertEqual($new_user2->id(), $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($new_user2->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($new_user2->id(), $entity->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($new_user2->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type_id)));
 
     // Try unsetting a field.
     $entity->name->first()->get('value')->setValue(NULL);
     $entity->user_id->first()->get('target_id')->setValue(NULL);
-    $this->assertNull($entity->name->value, format_string('%entity_type: Name field is not set.', array('%entity_type' => $entity_type)));
-    $this->assertNull($entity->user_id->target_id, format_string('%entity_type: User ID field is not set.', array('%entity_type' => $entity_type)));
-    $this->assertNull($entity->user_id->entity, format_string('%entity_type: User entity field is not set.', array('%entity_type' => $entity_type)));
+    $this->assertNull($entity->name->value, format_string('%entity_type: Name field is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertNull($entity->user_id->target_id, format_string('%entity_type: User ID field is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertNull($entity->user_id->entity, format_string('%entity_type: User entity field is not set.', array('%entity_type' => $entity_type_id)));
 
     // Create a fresh entity so target_id does not get its property object
     // instantiated, then verify setting a new value via typed data API works.
-    $entity2 = entity_create($entity_type, array(
+    $entity2 = entity_create($entity_type_id, array(
       'user_id' => array('target_id' => $new_user1->id()),
     ));
     // Access the property object, and set a value.
     $entity2->user_id->first()->get('target_id')->setValue($new_user2->id());
-    $this->assertEqual($new_user2->id(), $entity2->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($new_user2->name->value, $entity2->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($new_user2->id(), $entity2->user_id->target_id, format_string('%entity_type: Updated user id can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($new_user2->name->value, $entity2->user_id->entity->name->value, format_string('%entity_type: Updated user name value can be read.', array('%entity_type' => $entity_type_id)));
 
     // Test using isset(), empty() and unset().
     $entity->name->value = 'test unset';
     unset($entity->name->value);
-    $this->assertFalse(isset($entity->name->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type)));
-    $this->assertFalse(isset($entity->name[0]->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type)));
-    $this->assertTrue(empty($entity->name->value), format_string('%entity_type: Name is empty.', array('%entity_type' => $entity_type)));
-    $this->assertTrue(empty($entity->name[0]->value), format_string('%entity_type: Name is empty.', array('%entity_type' => $entity_type)));
+    $this->assertFalse(isset($entity->name->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertFalse(isset($entity->name[0]->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue(empty($entity->name->value), format_string('%entity_type: Name is empty.', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue(empty($entity->name[0]->value), format_string('%entity_type: Name is empty.', array('%entity_type' => $entity_type_id)));
 
     $entity->name->value = 'a value';
-    $this->assertTrue(isset($entity->name->value), format_string('%entity_type: Name is set.', array('%entity_type' => $entity_type)));
-    $this->assertTrue(isset($entity->name[0]->value), format_string('%entity_type: Name is set.', array('%entity_type' => $entity_type)));
-    $this->assertFalse(empty($entity->name->value), format_string('%entity_type: Name is not empty.', array('%entity_type' => $entity_type)));
-    $this->assertFalse(empty($entity->name[0]->value), format_string('%entity_type: Name is not empty.', array('%entity_type' => $entity_type)));
-    $this->assertTrue(isset($entity->name[0]), format_string('%entity_type: Name string item is set.', array('%entity_type' => $entity_type)));
-    $this->assertFalse(isset($entity->name[1]), format_string('%entity_type: Second name string item is not set as it does not exist', array('%entity_type' => $entity_type)));
-    $this->assertTrue(isset($entity->name), format_string('%entity_type: Name field is set.', array('%entity_type' => $entity_type)));
-    $this->assertFalse(isset($entity->nameInvalid), format_string('%entity_type: Not existing field is not set.', array('%entity_type' => $entity_type)));
+    $this->assertTrue(isset($entity->name->value), format_string('%entity_type: Name is set.', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue(isset($entity->name[0]->value), format_string('%entity_type: Name is set.', array('%entity_type' => $entity_type_id)));
+    $this->assertFalse(empty($entity->name->value), format_string('%entity_type: Name is not empty.', array('%entity_type' => $entity_type_id)));
+    $this->assertFalse(empty($entity->name[0]->value), format_string('%entity_type: Name is not empty.', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue(isset($entity->name[0]), format_string('%entity_type: Name string item is set.', array('%entity_type' => $entity_type_id)));
+    $this->assertFalse(isset($entity->name[1]), format_string('%entity_type: Second name string item is not set as it does not exist', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue(isset($entity->name), format_string('%entity_type: Name field is set.', array('%entity_type' => $entity_type_id)));
+    $this->assertFalse(isset($entity->nameInvalid), format_string('%entity_type: Not existing field is not set.', array('%entity_type' => $entity_type_id)));
 
     unset($entity->name[0]);
-    $this->assertFalse(isset($entity->name[0]), format_string('%entity_type: Name field item is not set.', array('%entity_type' => $entity_type)));
-    $this->assertFalse(isset($entity->name[0]->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type)));
-    $this->assertFalse(isset($entity->name->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type)));
+    $this->assertFalse(isset($entity->name[0]), format_string('%entity_type: Name field item is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertFalse(isset($entity->name[0]->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertFalse(isset($entity->name->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type_id)));
 
     $entity->name = array();
     $this->assertTrue(isset($entity->name), 'Name field is set.');
@@ -212,33 +213,35 @@ protected function doTestReadWrite($entity_type) {
     $this->assertFalse(isset($entity->name->value), 'Name value is not set.');
 
     $entity->name->value = 'a value';
-    $this->assertTrue(isset($entity->name->value), format_string('%entity_type: Name is set.', array('%entity_type' => $entity_type)));
+    $this->assertTrue(isset($entity->name->value), format_string('%entity_type: Name is set.', array('%entity_type' => $entity_type_id)));
     unset($entity->name);
-    $this->assertFalse(isset($entity->name), format_string('%entity_type: Name field is not set.', array('%entity_type' => $entity_type)));
-    $this->assertFalse(isset($entity->name[0]), format_string('%entity_type: Name field item is not set.', array('%entity_type' => $entity_type)));
-    $this->assertFalse(isset($entity->name[0]->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type)));
-    $this->assertFalse(isset($entity->name->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type)));
+    $this->assertFalse(isset($entity->name), format_string('%entity_type: Name field is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertFalse(isset($entity->name[0]), format_string('%entity_type: Name field item is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertFalse(isset($entity->name[0]->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type_id)));
+    $this->assertFalse(isset($entity->name->value), format_string('%entity_type: Name is not set.', array('%entity_type' => $entity_type_id)));
 
     // Access the language field.
-    $this->assertEqual($langcode, $entity->langcode->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(\Drupal::languageManager()->getLanguage($langcode), $entity->langcode->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
+    $entity_type = $this->entityManager->getDefinition($entity_type_id);
+    $langcode_key = $entity_type->getKey('langcode');
+    $this->assertEqual($langcode, $entity->{$langcode_key}->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual(\Drupal::languageManager()->getLanguage($langcode), $entity->{$langcode_key}->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type_id)));
 
     // Change the language by code.
-    $entity->langcode->value = \Drupal::languageManager()->getDefaultLanguage()->getId();
-    $this->assertEqual(\Drupal::languageManager()->getDefaultLanguage()->getId(), $entity->langcode->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(\Drupal::languageManager()->getDefaultLanguage(), $entity->langcode->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
+    $entity->{$langcode_key}->value = \Drupal::languageManager()->getDefaultLanguage()->getId();
+    $this->assertEqual(\Drupal::languageManager()->getDefaultLanguage()->getId(), $entity->{$langcode_key}->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual(\Drupal::languageManager()->getDefaultLanguage(), $entity->{$langcode_key}->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type_id)));
 
     // Revert language by code then try setting it by language object.
-    $entity->langcode->value = $langcode;
-    $entity->langcode->language = \Drupal::languageManager()->getDefaultLanguage();
-    $this->assertEqual(\Drupal::languageManager()->getDefaultLanguage()->getId(), $entity->langcode->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(\Drupal::languageManager()->getDefaultLanguage(), $entity->langcode->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
+    $entity->{$langcode_key}->value = $langcode;
+    $entity->{$langcode_key}->language = \Drupal::languageManager()->getDefaultLanguage();
+    $this->assertEqual(\Drupal::languageManager()->getDefaultLanguage()->getId(), $entity->{$langcode_key}->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual(\Drupal::languageManager()->getDefaultLanguage(), $entity->{$langcode_key}->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type_id)));
 
     // Access the text field and test updating.
-    $this->assertEqual($entity->field_test_text->value, $this->entity_field_text, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($entity->field_test_text->value, $this->entity_field_text, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type_id)));
     $new_text = $this->randomMachineName();
     $entity->field_test_text->value = $new_text;
-    $this->assertEqual($entity->field_test_text->value, $new_text, format_string('%entity_type: Updated text field can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($entity->field_test_text->value, $new_text, format_string('%entity_type: Updated text field can be read.', array('%entity_type' => $entity_type_id)));
 
     // Test creating the entity by passing in plain values.
     $this->entity_name = $this->randomMachineName();
@@ -248,96 +251,96 @@ protected function doTestReadWrite($entity_type) {
     $this->entity_field_text = $this->randomMachineName();
     $text_item[0]['value'] = $this->entity_field_text;
 
-    $entity = entity_create($entity_type, array(
+    $entity = entity_create($entity_type_id, array(
       'name' => $name_item,
       'user_id' => $user_item,
       'field_test_text' => $text_item,
     ));
-    $this->assertEqual($this->entity_name, $entity->name->value, format_string('%entity_type: Name value can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_user->id(), $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_user->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_field_text, $entity->field_test_text->value, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($this->entity_name, $entity->name->value, format_string('%entity_type: Name value can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($this->entity_user->id(), $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($this->entity_user->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($this->entity_field_text, $entity->field_test_text->value, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type_id)));
 
     // Test copying field values.
-    $entity2 = $this->createTestEntity($entity_type);
+    $entity2 = $this->createTestEntity($entity_type_id);
     $entity2->name = $entity->name;
     $entity2->user_id = $entity->user_id;
     $entity2->field_test_text = $entity->field_test_text;
 
-    $this->assertTrue($entity->name !== $entity2->name, format_string('%entity_type: Copying properties results in a different field object.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($entity->name->value, $entity2->name->value, format_string('%entity_type: Name field copied.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($entity->user_id->target_id, $entity2->user_id->target_id, format_string('%entity_type: User id field copied.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($entity->field_test_text->value, $entity2->field_test_text->value, format_string('%entity_type: Text field copied.', array('%entity_type' => $entity_type)));
+    $this->assertTrue($entity->name !== $entity2->name, format_string('%entity_type: Copying properties results in a different field object.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($entity->name->value, $entity2->name->value, format_string('%entity_type: Name field copied.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($entity->user_id->target_id, $entity2->user_id->target_id, format_string('%entity_type: User id field copied.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($entity->field_test_text->value, $entity2->field_test_text->value, format_string('%entity_type: Text field copied.', array('%entity_type' => $entity_type_id)));
 
     // Tests adding a value to a field item list.
     $entity->name[] = 'Another name';
-    $this->assertEqual($entity->name[1]->value, 'Another name', format_string('%entity_type: List item added via [].', array('%entity_type' => $entity_type)));
+    $this->assertEqual($entity->name[1]->value, 'Another name', format_string('%entity_type: List item added via [].', array('%entity_type' => $entity_type_id)));
     $entity->name[2]->value = 'Third name';
-    $this->assertEqual($entity->name[2]->value, 'Third name', format_string('%entity_type: List item added by a accessing not yet created item.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($entity->name[2]->value, 'Third name', format_string('%entity_type: List item added by a accessing not yet created item.', array('%entity_type' => $entity_type_id)));
 
     // Test removing and empty-ing list items.
-    $this->assertEqual(count($entity->name), 3, format_string('%entity_type: List has 3 items.', array('%entity_type' => $entity_type)));
+    $this->assertEqual(count($entity->name), 3, format_string('%entity_type: List has 3 items.', array('%entity_type' => $entity_type_id)));
     unset($entity->name[1]);
-    $this->assertEqual(count($entity->name), 2, format_string('%entity_type: Second list item has been removed.', array('%entity_type' => $entity_type)));
+    $this->assertEqual(count($entity->name), 2, format_string('%entity_type: Second list item has been removed.', array('%entity_type' => $entity_type_id)));
     $entity->name[2] = NULL;
-    $this->assertEqual(count($entity->name), 2, format_string('%entity_type: Assigning NULL does not reduce array count.', array('%entity_type' => $entity_type)));
-    $this->assertTrue($entity->name[2]->isEmpty(), format_string('%entity_type: Assigning NULL empties the item.', array('%entity_type' => $entity_type)));
+    $this->assertEqual(count($entity->name), 2, format_string('%entity_type: Assigning NULL does not reduce array count.', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue($entity->name[2]->isEmpty(), format_string('%entity_type: Assigning NULL empties the item.', array('%entity_type' => $entity_type_id)));
 
     // Test using isEmpty().
     unset($entity->name[2]);
-    $this->assertFalse($entity->name[0]->isEmpty(), format_string('%entity_type: Name item is not empty.', array('%entity_type' => $entity_type)));
+    $this->assertFalse($entity->name[0]->isEmpty(), format_string('%entity_type: Name item is not empty.', array('%entity_type' => $entity_type_id)));
     $entity->name->value = NULL;
-    $this->assertTrue($entity->name[0]->isEmpty(), format_string('%entity_type: Name item is empty.', array('%entity_type' => $entity_type)));
-    $this->assertTrue($entity->name->isEmpty(), format_string('%entity_type: Name field is empty.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(count($entity->name), 1, format_string('%entity_type: Empty item is considered when counting.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(count(iterator_to_array($entity->name->getIterator())), count($entity->name), format_string('%entity_type: Count matches iterator count.', array('%entity_type' => $entity_type)));
-    $this->assertTrue($entity->name->getValue() === array(0 => array('value' => NULL)), format_string('%entity_type: Name field value contains a NULL value.', array('%entity_type' => $entity_type)));
+    $this->assertTrue($entity->name[0]->isEmpty(), format_string('%entity_type: Name item is empty.', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue($entity->name->isEmpty(), format_string('%entity_type: Name field is empty.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual(count($entity->name), 1, format_string('%entity_type: Empty item is considered when counting.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual(count(iterator_to_array($entity->name->getIterator())), count($entity->name), format_string('%entity_type: Count matches iterator count.', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue($entity->name->getValue() === array(0 => array('value' => NULL)), format_string('%entity_type: Name field value contains a NULL value.', array('%entity_type' => $entity_type_id)));
 
     // Test using filterEmptyItems().
     $entity->name = array(NULL, 'foo');
-    $this->assertEqual(count($entity->name), 2, format_string('%entity_type: List has 2 items.', array('%entity_type' => $entity_type)));
+    $this->assertEqual(count($entity->name), 2, format_string('%entity_type: List has 2 items.', array('%entity_type' => $entity_type_id)));
     $entity->name->filterEmptyItems();
-    $this->assertEqual(count($entity->name), 1, format_string('%entity_type: The empty item was removed.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($entity->name[0]->value, 'foo', format_string('%entity_type: The items were renumbered.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($entity->name[0]->getName(), 0, format_string('%entity_type: The deltas were updated in the items.', array('%entity_type' => $entity_type)));
+    $this->assertEqual(count($entity->name), 1, format_string('%entity_type: The empty item was removed.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($entity->name[0]->value, 'foo', format_string('%entity_type: The items were renumbered.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($entity->name[0]->getName(), 0, format_string('%entity_type: The deltas were updated in the items.', array('%entity_type' => $entity_type_id)));
 
     // Test removing all list items by assigning an empty array.
     $entity->name = array();
-    $this->assertIdentical(count($entity->name), 0, format_string('%entity_type: Name field contains no items.', array('%entity_type' => $entity_type)));
-    $this->assertIdentical($entity->name->getValue(), array(), format_string('%entity_type: Name field value is an empty array.', array('%entity_type' => $entity_type)));
+    $this->assertIdentical(count($entity->name), 0, format_string('%entity_type: Name field contains no items.', array('%entity_type' => $entity_type_id)));
+    $this->assertIdentical($entity->name->getValue(), array(), format_string('%entity_type: Name field value is an empty array.', array('%entity_type' => $entity_type_id)));
 
     $entity->name->value = 'foo';
-    $this->assertEqual($entity->name->value, 'foo', format_string('%entity_type: Name field set.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($entity->name->value, 'foo', format_string('%entity_type: Name field set.', array('%entity_type' => $entity_type_id)));
     // Test removing all list items by setting it to NULL.
     $entity->name = NULL;
-    $this->assertIdentical(count($entity->name), 0, format_string('%entity_type: Name field contains no items.', array('%entity_type' => $entity_type)));
-    $this->assertNull($entity->name->getValue(), format_string('%entity_type: Name field value is an empty array.', array('%entity_type' => $entity_type)));
+    $this->assertIdentical(count($entity->name), 0, format_string('%entity_type: Name field contains no items.', array('%entity_type' => $entity_type_id)));
+    $this->assertNull($entity->name->getValue(), format_string('%entity_type: Name field value is an empty array.', array('%entity_type' => $entity_type_id)));
 
     // Test get and set field values.
     $entity->name = 'foo';
-    $this->assertEqual($entity->name[0]->toArray(), array('value' => 'foo'), format_string('%entity_type: Field value has been retrieved via toArray()', array('%entity_type' => $entity_type)));
+    $this->assertEqual($entity->name[0]->toArray(), array('value' => 'foo'), format_string('%entity_type: Field value has been retrieved via toArray()', array('%entity_type' => $entity_type_id)));
 
     $values = $entity->toArray();
-    $this->assertEqual($values['name'], array(0 => array('value' => 'foo')), format_string('%entity_type: Field value has been retrieved via toArray() from an entity.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($values['name'], array(0 => array('value' => 'foo')), format_string('%entity_type: Field value has been retrieved via toArray() from an entity.', array('%entity_type' => $entity_type_id)));
 
     // Make sure the user id can be set to zero.
     $user_item[0]['target_id'] = 0;
-    $entity = entity_create($entity_type, array(
+    $entity = entity_create($entity_type_id, array(
       'name' => $name_item,
       'user_id' => $user_item,
       'field_test_text' => $text_item,
     ));
-    $this->assertNotNull($entity->user_id->target_id, format_string('%entity_type: User id is not NULL', array('%entity_type' => $entity_type)));
-    $this->assertIdentical($entity->user_id->target_id, 0, format_string('%entity_type: User id has been set to 0', array('%entity_type' => $entity_type)));
+    $this->assertNotNull($entity->user_id->target_id, format_string('%entity_type: User id is not NULL', array('%entity_type' => $entity_type_id)));
+    $this->assertIdentical($entity->user_id->target_id, 0, format_string('%entity_type: User id has been set to 0', array('%entity_type' => $entity_type_id)));
 
     // Test setting the ID with the value only.
-    $entity = entity_create($entity_type, array(
+    $entity = entity_create($entity_type_id, array(
       'name' => $name_item,
       'user_id' => 0,
       'field_test_text' => $text_item,
     ));
-    $this->assertNotNull($entity->user_id->target_id, format_string('%entity_type: User id is not NULL', array('%entity_type' => $entity_type)));
-    $this->assertIdentical($entity->user_id->target_id, 0, format_string('%entity_type: User id has been set to 0', array('%entity_type' => $entity_type)));
+    $this->assertNotNull($entity->user_id->target_id, format_string('%entity_type: User id is not NULL', array('%entity_type' => $entity_type_id)));
+    $this->assertIdentical($entity->user_id->target_id, 0, format_string('%entity_type: User id has been set to 0', array('%entity_type' => $entity_type_id)));
   }
 
   /**
@@ -353,25 +356,28 @@ public function testSave() {
   /**
    * Executes the save tests for the given entity type.
    *
-   * @param string $entity_type
+   * @param string $entity_type_id
    *   The entity type to run the tests with.
    */
-  protected function doTestSave($entity_type) {
-    $entity = $this->createTestEntity($entity_type);
+  protected function doTestSave($entity_type_id) {
+    $entity_type = $this->entityManager->getDefinition($entity_type_id);
+    $langcode_key = $entity_type->getKey('langcode');
+    $entity = $this->createTestEntity($entity_type_id);
+
     $entity->save();
-    $this->assertTrue((bool) $entity->id(), format_string('%entity_type: Entity has received an id.', array('%entity_type' => $entity_type)));
+    $this->assertTrue((bool) $entity->id(), format_string('%entity_type: Entity has received an id.', array('%entity_type' => $entity_type_id)));
 
-    $entity = entity_load($entity_type, $entity->id());
-    $this->assertTrue((bool) $entity->id(), format_string('%entity_type: Entity loaded.', array('%entity_type' => $entity_type)));
+    $entity = entity_load($entity_type_id, $entity->id());
+    $this->assertTrue((bool) $entity->id(), format_string('%entity_type: Entity loaded.', array('%entity_type' => $entity_type_id)));
 
     // Access the name field.
-    $this->assertEqual(1, $entity->id->value, format_string('%entity_type: ID value can be read.', array('%entity_type' => $entity_type)));
-    $this->assertTrue(is_string($entity->uuid->value), format_string('%entity_type: UUID value can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual('en', $entity->langcode->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(\Drupal::languageManager()->getLanguage('en'), $entity->langcode->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_user->id(), $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_user->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($this->entity_field_text, $entity->field_test_text->value, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type)));
+    $this->assertEqual(1, $entity->id->value, format_string('%entity_type: ID value can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertTrue(is_string($entity->uuid->value), format_string('%entity_type: UUID value can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual('en', $entity->{$langcode_key}->value, format_string('%entity_type: Language code can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual(\Drupal::languageManager()->getLanguage('en'), $entity->{$langcode_key}->language, format_string('%entity_type: Language object can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($this->entity_user->id(), $entity->user_id->target_id, format_string('%entity_type: User id can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($this->entity_user->getUsername(), $entity->user_id->entity->name->value, format_string('%entity_type: User name can be read.', array('%entity_type' => $entity_type_id)));
+    $this->assertEqual($this->entity_field_text, $entity->field_test_text->value, format_string('%entity_type: Text field can be read.', array('%entity_type' => $entity_type_id)));
   }
 
   /**
@@ -387,16 +393,16 @@ public function testIntrospection() {
   /**
    * Executes the introspection tests for the given entity type.
    *
-   * @param string $entity_type
+   * @param string $entity_type_id
    *   The entity type to run the tests with.
    */
-  protected function doTestIntrospection($entity_type) {
+  protected function doTestIntrospection($entity_type_id) {
     // Test getting metadata upfront. The entity types used for this test have
     // a default bundle that is the same as the entity type.
-    $definitions = \Drupal::entityManager()->getFieldDefinitions($entity_type, $entity_type);
-    $this->assertEqual($definitions['name']->getType(), 'string', $entity_type .': Name field found.');
-    $this->assertEqual($definitions['user_id']->getType(), 'entity_reference', $entity_type .': User field found.');
-    $this->assertEqual($definitions['field_test_text']->getType(), 'text', $entity_type .': Test-text-field field found.');
+    $definitions = \Drupal::entityManager()->getFieldDefinitions($entity_type_id, $entity_type_id);
+    $this->assertEqual($definitions['name']->getType(), 'string', $entity_type_id .': Name field found.');
+    $this->assertEqual($definitions['user_id']->getType(), 'entity_reference', $entity_type_id .': User field found.');
+    $this->assertEqual($definitions['field_test_text']->getType(), 'text', $entity_type_id .': Test-text-field field found.');
 
     // Test deriving further metadata.
     $this->assertTrue($definitions['name'] instanceof FieldDefinitionInterface);
@@ -408,8 +414,10 @@ protected function doTestIntrospection($entity_type) {
     $this->assertEqual($value_definition->getDataType(), 'string');
 
     // Test deriving metadata from references.
-    $entity_definition = \Drupal\Core\Entity\TypedData\EntityDataDefinition::create($entity_type);
-    $reference_definition = $entity_definition->getPropertyDefinition('langcode')
+    $entity_definition = \Drupal\Core\Entity\TypedData\EntityDataDefinition::create($entity_type_id);
+    $entity_type = $this->entityManager->getDefinition($entity_type_id);
+    $langcode_key = $entity_type->getKey('langcode');
+    $reference_definition = $entity_definition->getPropertyDefinition($langcode_key)
       ->getPropertyDefinition('language')
       ->getTargetDefinition();
     $this->assertEqual($reference_definition->getDataType(), 'language');
@@ -428,24 +436,24 @@ protected function doTestIntrospection($entity_type) {
 
     // Test introspecting an entity object.
     // @todo: Add bundles and test bundles as well.
-    $entity = entity_create($entity_type);
+    $entity = entity_create($entity_type_id);
 
     $definitions = $entity->getFieldDefinitions();
-    $this->assertEqual($definitions['name']->getType(), 'string', $entity_type .': Name field found.');
-    $this->assertEqual($definitions['user_id']->getType(), 'entity_reference', $entity_type .': User field found.');
-    $this->assertEqual($definitions['field_test_text']->getType(), 'text', $entity_type .': Test-text-field field found.');
+    $this->assertEqual($definitions['name']->getType(), 'string', $entity_type_id .': Name field found.');
+    $this->assertEqual($definitions['user_id']->getType(), 'entity_reference', $entity_type_id .': User field found.');
+    $this->assertEqual($definitions['field_test_text']->getType(), 'text', $entity_type_id .': Test-text-field field found.');
 
     $name_properties = $entity->name->getFieldDefinition()->getPropertyDefinitions();
-    $this->assertEqual($name_properties['value']->getDataType(), 'string', $entity_type .': String value property of the name found.');
+    $this->assertEqual($name_properties['value']->getDataType(), 'string', $entity_type_id .': String value property of the name found.');
 
     $userref_properties = $entity->user_id->getFieldDefinition()->getPropertyDefinitions();
-    $this->assertEqual($userref_properties['target_id']->getDataType(), 'integer', $entity_type .': Entity id property of the user found.');
-    $this->assertEqual($userref_properties['entity']->getDataType(), 'entity_reference', $entity_type .': Entity reference property of the user found.');
+    $this->assertEqual($userref_properties['target_id']->getDataType(), 'integer', $entity_type_id .': Entity id property of the user found.');
+    $this->assertEqual($userref_properties['entity']->getDataType(), 'entity_reference', $entity_type_id .': Entity reference property of the user found.');
 
     $textfield_properties = $entity->field_test_text->getFieldDefinition()->getFieldStorageDefinition()->getPropertyDefinitions();
-    $this->assertEqual($textfield_properties['value']->getDataType(), 'string', $entity_type .': String value property of the test-text field found.');
-    $this->assertEqual($textfield_properties['format']->getDataType(), 'filter_format', $entity_type .': String format field of the test-text field found.');
-    $this->assertEqual($textfield_properties['processed']->getDataType(), 'string', $entity_type .': String processed property of the test-text field found.');
+    $this->assertEqual($textfield_properties['value']->getDataType(), 'string', $entity_type_id .': String value property of the test-text field found.');
+    $this->assertEqual($textfield_properties['format']->getDataType(), 'filter_format', $entity_type_id .': String format field of the test-text field found.');
+    $this->assertEqual($textfield_properties['processed']->getDataType(), 'string', $entity_type_id .': String processed property of the test-text field found.');
 
     // Make sure provided contextual information is right.
     $entity_adapter = $entity->getTypedData();
@@ -519,9 +527,10 @@ protected function doTestIterator($entity_type) {
    */
   public function testDataStructureInterfaces() {
     // All entity variations have to have the same results.
-    foreach (entity_test_entity_types() as $entity_type) {
-      $this->doTestDataStructureInterfaces($entity_type);
-    }
+//    foreach (entity_test_entity_types() as $entity_type) {
+//      $this->doTestDataStructureInterfaces($entity_type);
+//    }
+    $this->doTestDataStructureInterfaces('entity_test_mul_langcode_key');
   }
 
   /**
@@ -551,7 +560,9 @@ protected function doTestDataStructureInterfaces($entity_type) {
       // Field format.
       NULL,
     );
-    $this->assertEqual($strings, $target_strings, format_string('%entity_type: All contained strings found.', array('%entity_type' => $entity_type)));
+    asort($strings);
+    asort($target_strings);
+    $this->assertEqual(array_values($strings), array_values($target_strings), format_string('%entity_type: All contained strings found.', array('%entity_type' => $entity_type)));
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Entity/EntityLanguageTestBase.php b/core/modules/system/src/Tests/Entity/EntityLanguageTestBase.php
index 6aa3c91..363975b 100644
--- a/core/modules/system/src/Tests/Entity/EntityLanguageTestBase.php
+++ b/core/modules/system/src/Tests/Entity/EntityLanguageTestBase.php
@@ -53,6 +53,7 @@ protected function setUp() {
 
     $this->installEntitySchema('entity_test_rev');
     $this->installEntitySchema('entity_test_mul');
+    $this->installEntitySchema('entity_test_mul_langcode_key');
     $this->installEntitySchema('entity_test_mulrev');
 
     $this->installConfig(array('language'));
diff --git a/core/modules/system/src/Tests/Entity/EntityTranslationTest.php b/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
index c896f6f..2545e04 100644
--- a/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
@@ -35,6 +35,7 @@ public function testEntityLanguageMethods() {
    *   The entity type to run the tests with.
    */
   protected function _testEntityLanguageMethods($entity_type) {
+    $langcode_key = $this->entityManager->getDefinition($entity_type)->getKey('langcode');
     $entity = entity_create($entity_type, array(
       'name' => 'test',
       'user_id' => $this->container->get('current_user')->id(),
@@ -43,7 +44,7 @@ protected function _testEntityLanguageMethods($entity_type) {
     $entity = entity_create($entity_type, array(
       'name' => 'test',
       'user_id' => \Drupal::currentUser()->id(),
-      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
+      $langcode_key => LanguageInterface::LANGCODE_NOT_SPECIFIED,
     ));
     $this->assertEqual($entity->language()->getId(), LanguageInterface::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Entity language not specified.', array('%entity_type' => $entity_type)));
     $this->assertFalse($entity->getTranslationLanguages(FALSE), format_string('%entity_type: No translations are available', array('%entity_type' => $entity_type)));
@@ -71,7 +72,7 @@ protected function _testEntityLanguageMethods($entity_type) {
     // Now, make the entity language-specific by assigning a language and test
     // translating it.
     $default_langcode = $this->langcodes[0];
-    $entity->langcode->value = $default_langcode;
+    $entity->{$langcode_key}->value = $default_langcode;
     $entity->{$this->field_name} = array();
     $this->assertEqual($entity->language(), \Drupal::languageManager()->getLanguage($this->langcodes[0]), format_string('%entity_type: Entity language retrieved.', array('%entity_type' => $entity_type)));
     $this->assertFalse($entity->getTranslationLanguages(FALSE), format_string('%entity_type: No translations are available', array('%entity_type' => $entity_type)));
@@ -144,13 +145,14 @@ public function testMultilingualProperties() {
    *   The entity type to run the tests with.
    */
   protected function _testMultilingualProperties($entity_type) {
+    $langcode_key = $this->entityManager->getDefinition($entity_type)->getKey('langcode');
     $name = $this->randomMachineName();
     $uid = mt_rand(0, 127);
     $langcode = $this->langcodes[0];
 
     // Create a language neutral entity and check that properties are stored
     // as language neutral.
-    $entity = entity_create($entity_type, array('name' => $name, 'user_id' => $uid, 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED));
+    $entity = entity_create($entity_type, array('name' => $name, 'user_id' => $uid, $langcode_key => LanguageInterface::LANGCODE_NOT_SPECIFIED));
     $entity->save();
     $entity = entity_load($entity_type, $entity->id());
     $default_langcode = $entity->language()->getId();
@@ -170,7 +172,7 @@ protected function _testMultilingualProperties($entity_type) {
 
     // Create a language-aware entity and check that properties are stored
     // as language-aware.
-    $entity = entity_create($entity_type, array('name' => $name, 'user_id' => $uid, 'langcode' => $langcode));
+    $entity = entity_create($entity_type, array('name' => $name, 'user_id' => $uid, $langcode_key => $langcode));
     $entity->save();
     $entity = entity_load($entity_type, $entity->id());
     $default_langcode = $entity->language()->getId();
@@ -235,7 +237,7 @@ protected function _testMultilingualProperties($entity_type) {
     entity_create($entity_type, array(
       'user_id' => $properties[$langcode]['user_id'],
       'name' => 'some name',
-      'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
+      $langcode_key => LanguageInterface::LANGCODE_NOT_SPECIFIED,
     ))->save();
 
     $entities = entity_load_multiple($entity_type);
@@ -248,12 +250,12 @@ protected function _testMultilingualProperties($entity_type) {
     // explicit parameter.
     $entities = entity_load_multiple_by_properties($entity_type, array('name' => $properties[$langcode]['name'][0], 'default_langcode' => 0));
     $this->assertEqual(count($entities), 1, format_string('%entity_type: One entity correctly loaded by name translation.', array('%entity_type' => $entity_type)));
-    $entities = entity_load_multiple_by_properties($entity_type, array('langcode' => $default_langcode, 'name' => $name));
+    $entities = entity_load_multiple_by_properties($entity_type, array($langcode_key => $default_langcode, 'name' => $name));
     $this->assertEqual(count($entities), 1, format_string('%entity_type: One entity correctly loaded by name and language.', array('%entity_type' => $entity_type)));
 
-    $entities = entity_load_multiple_by_properties($entity_type, array('langcode' => $langcode, 'name' => $properties[$langcode]['name'][0]));
+    $entities = entity_load_multiple_by_properties($entity_type, array($langcode_key => $langcode, 'name' => $properties[$langcode]['name'][0]));
     $this->assertEqual(count($entities), 0, format_string('%entity_type: No entity loaded by name translation specifying the translation language.', array('%entity_type' => $entity_type)));
-    $entities = entity_load_multiple_by_properties($entity_type, array('langcode' => $langcode, 'name' => $properties[$langcode]['name'][0], 'default_langcode' => 0));
+    $entities = entity_load_multiple_by_properties($entity_type, array($langcode_key => $langcode, 'name' => $properties[$langcode]['name'][0], 'default_langcode' => 0));
     $this->assertEqual(count($entities), 1, format_string('%entity_type: One entity loaded by name translation and language specifying to look for translations.', array('%entity_type' => $entity_type)));
     $entities = entity_load_multiple_by_properties($entity_type, array('user_id' => $properties[$langcode]['user_id'][0], 'default_langcode' => NULL));
     $this->assertEqual(count($entities), 2, format_string('%entity_type: Two entities loaded by uid without caring about property translatability.', array('%entity_type' => $entity_type)));
@@ -283,7 +285,7 @@ protected function _testMultilingualProperties($entity_type) {
       ->condition('name', $properties[$langcode]['name'], '=', $langcode)
       ->condition("$this->field_name.value", $field_value, '=', $langcode);
     $result = $query
-      ->condition('langcode', $default_langcode)
+      ->condition($langcode_key, $default_langcode)
       ->condition($default_langcode_group)
       ->condition($langcode_group)
       ->execute();
@@ -296,9 +298,10 @@ protected function _testMultilingualProperties($entity_type) {
   function testEntityTranslationAPI() {
     $default_langcode = $this->langcodes[0];
     $langcode = $this->langcodes[1];
+    $langcode_key = 'langcode';
     $entity = $this->entityManager
       ->getStorage('entity_test_mul')
-      ->create(array('name' => $this->randomMachineName(), 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED));
+      ->create(array('name' => $this->randomMachineName(), $langcode_key => LanguageInterface::LANGCODE_NOT_SPECIFIED));
 
     $entity->save();
     $hooks = $this->getHooksInfo();
@@ -308,7 +311,7 @@ function testEntityTranslationAPI() {
     // retrieve a translation referring to it.
     $translation = $entity->getTranslation($langcode);
     $this->assertEqual($entity, $translation, 'The translation object corresponding to a non-default language is the entity object itself when the entity is language-neutral.');
-    $entity->langcode->value = $default_langcode;
+    $entity->{$langcode_key}->value = $default_langcode;
     $translation = $entity->getTranslation($default_langcode);
     $this->assertEqual($entity, $translation, 'The translation object corresponding to the default language (explicit) is the entity object itself.');
     $translation = $entity->getTranslation(LanguageInterface::LANGCODE_DEFAULT);
@@ -575,6 +578,7 @@ function testFieldDefinitions() {
    */
   public function testLanguageChange() {
     $entity_type = 'entity_test_mul';
+    $langcode_key = 'langcode';
     $controller = $this->entityManager->getStorage($entity_type);
     $langcode = $this->langcodes[0];
 
@@ -593,7 +597,7 @@ public function testLanguageChange() {
     // Check that field languages keep matching entity language even after
     // changing it.
     $langcode = $this->langcodes[1];
-    $entity->langcode->value = $langcode;
+    $entity->{$langcode_key}->value = $langcode;
     foreach (array($this->field_name, $this->untranslatable_field_name) as $field_name) {
       $this->assertEqual($entity->get($field_name)->getLangcode(), $langcode, 'Field language works as expected after changing entity language.');
     }
@@ -602,7 +606,7 @@ public function testLanguageChange() {
     // field values and untranslatable ones.
     $langcode = $this->langcodes[0];
     $entity->addTranslation($this->langcodes[2], array($this->field_name => $this->randomMachineName()));
-    $entity->langcode->value = $langcode;
+    $entity->{$langcode_key}->value = $langcode;
     foreach (array($this->field_name, $this->untranslatable_field_name) as $field_name) {
       $this->assertEqual($entity->get($field_name)->getLangcode(), $langcode, 'Field language works as expected after translating the entity and changing language.');
     }
@@ -611,7 +615,7 @@ public function testLanguageChange() {
     // language causes an exception to be thrown.
     $message = 'An exception is thrown when setting the default language to an existing translation language';
     try {
-      $entity->langcode->value = $this->langcodes[2];
+      $entity->{$langcode_key}->value = $this->langcodes[2];
       $this->fail($message);
     }
     catch (\InvalidArgumentException $e) {
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/entity_test.install b/core/modules/system/tests/modules/entity_test/entity_test.install
index 4d2e0f3..1a6d9a2 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.install
+++ b/core/modules/system/tests/modules/entity_test/entity_test.install
@@ -9,13 +9,7 @@
  * Implements hook_install().
  */
 function entity_test_install() {
-  $entity_types = array(
-    'entity_test',
-    'entity_test_rev',
-    'entity_test_mul',
-    'entity_test_mulrev',
-  );
-  foreach ($entity_types as $entity_type) {
+  foreach (entity_test_entity_types() as $entity_type) {
     // Auto-create fields for testing.
     entity_create('field_storage_config', array(
       'entity_type' => $entity_type,
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 08fa564..ff44c48 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -52,6 +52,7 @@ function entity_test_entity_types($filter = NULL) {
   }
   if ($filter != ENTITY_TEST_TYPES_REVISABLE) {
     $types[] = 'entity_test_mul';
+    $types[] = 'entity_test_mul_langcode_key';
   }
   if ($filter != ENTITY_TEST_TYPES_MULTILINGUAL) {
     $types[] = 'entity_test_rev';
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 9200270..d9800be 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
@@ -37,7 +37,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/EntityTestMulDefaultValue.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulLangcodeKey.php
similarity index 54%
copy from core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulDefaultValue.php
copy to core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulLangcodeKey.php
index 33369ac..9401d3e 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulDefaultValue.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulLangcodeKey.php
@@ -2,20 +2,19 @@
 
 /**
  * @file
- * Contains \Drupal\entity_test\Entity\EntityTestMulDefaultValue.
+ * Contains \Drupal\entity_test\Entity\EntityTestMul.
  */
 
 namespace Drupal\entity_test\Entity;
 
 use Drupal\Core\Entity\EntityTypeInterface;
-use Drupal\Core\Field\BaseFieldDefinition;
 
 /**
  * Defines the test entity class.
  *
  * @ContentEntityType(
- *   id = "entity_test_mul_default_value",
- *   label = @Translation("Test entity - data table"),
+ *   id = "entity_test_mul_langcode_key",
+ *   label = @Translation("Test entity - data table - langcode key"),
  *   handlers = {
  *     "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
  *     "access" = "Drupal\entity_test\EntityTestAccessControlHandler",
@@ -26,36 +25,33 @@
  *     "translation" = "Drupal\content_translation\ContentTranslationHandler",
  *     "views_data" = "Drupal\views\EntityViewsData"
  *   },
- *   base_table = "entity_test_mul",
- *   data_table = "entity_test_mul_property_data",
+ *   base_table = "entity_test_mul_langcode_key",
+ *   data_table = "entity_test_mul_langcode_key_field_data",
  *   translatable = TRUE,
  *   entity_keys = {
  *     "id" = "id",
  *     "uuid" = "uuid",
  *     "bundle" = "type",
- *     "label" = "name"
+ *     "label" = "name",
+ *     "langcode" = "custom_langcode_key",
  *   },
  *   links = {
- *     "canonical" = "entity.entity_test_mul.edit_form",
- *     "edit-form" = "entity.entity_test_mul.edit_form",
- *     "delete-form" = "entity.entity_test_mul.delete_form",
+ *     "canonical" = "entity.entity_test_mul_langcode_key.edit_form",
+ *     "edit-form" = "entity.entity_test_mul_langcode_key.edit_form",
+ *     "delete-form" = "entity.entity_test_mul_langcode_key.delete_form",
  *   },
- *   field_ui_base_route = "entity.entity_test_mul.admin_form",
+ *   field_ui_base_route = "entity.entity_test_mul_langcode_key.admin_form",
  * )
  */
-class EntityTestMulDefaultValue extends EntityTestMul {
+class EntityTestMulLangcodeKey extends EntityTest {
 
   /**
    * {@inheritdoc}
    */
   public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     $fields = parent::baseFieldDefinitions($entity_type);
-
-    $fields['description'] = BaseFieldDefinition::create('shape')
-      ->setLabel(t('Some custom description'))
-      ->setTranslatable(TRUE)
-      ->setDefaultValueCallback('entity_test_field_default_value');
-
+    $fields['custom_langcode_key'] = $fields['langcode'];
+    unset($fields['langcode']);
     return $fields;
   }
 
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 629ce9c..2ac5fec 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 9f361c7..cb30422 100644
--- a/core/modules/views/src/EntityViewsData.php
+++ b/core/modules/views/src/EntityViewsData.php
@@ -390,7 +390,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 e9c5a60..c1aac0f 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 ddfbd81..3f95ed9 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 a3a7013..82ef89b 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 cfa5cd9..2f0bd10 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();
