diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index f6122cf..4c9b184 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -254,6 +254,13 @@ public function isDefaultRevision($new_value = NULL) {
   /**
    * {@inheritdoc}
    */
+  public function isDefaultTranslation() {
+    return $this->activeLangcode == Language::LANGCODE_DEFAULT;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getRevisionId() {
     return $this->getEntityKey('revision');
   }
@@ -554,7 +561,7 @@ public function onChange($name) {
     }
 
     // Update the default internal language cache.
-    if ($name == $this->langcodeKey) {
+    if ($name == $this->langcodeKey && $this->isDefaultTranslation()) {
       $this->setDefaultLangcode();
       if (isset($this->translations[$this->defaultLangcode])) {
         $message = String::format('A translation already exists for the specified language (@langcode).', array('@langcode' => $this->defaultLangcode));
@@ -694,6 +701,8 @@ public function addTranslation($langcode, array $values = array()) {
         $values[$name] = $field->getValue();
       }
     }
+    $values[$this->langcodeKey] = $langcode;
+    $values[$this->getEntityType()->getKey('default_langcode')] = FALSE;
 
     $this->translations[$langcode]['status'] = static::TRANSLATION_CREATED;
     $translation = $this->getTranslation($langcode);
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 5ba64f2..a6fe80f 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -401,6 +401,7 @@ public function getBaseFieldDefinitions($entity_type_id) {
   protected function buildBaseFieldDefinitions($entity_type_id) {
     $entity_type = $this->getDefinition($entity_type_id);
     $class = $entity_type->getClass();
+    $keys = array_filter($entity_type->getKeys());
 
     // Fail with an exception for non-fieldable entity types.
     if (!$entity_type->isSubclassOf('\Drupal\Core\Entity\FieldableEntityInterface')) {
@@ -408,7 +409,18 @@ protected function buildBaseFieldDefinitions($entity_type_id) {
     }
 
     // Retrieve base field definitions and assign them the entity type provider.
+    /** @var FieldStorageDefinitionInterface[] $base_field_definitions */
     $base_field_definitions = $class::baseFieldDefinitions($entity_type);
+    $name = $keys['default_langcode'];
+    if ($entity_type->isTranslatable() && !isset($base_field_definitions[$name])) {
+      $base_field_definitions[$name] = BaseFieldDefinition::create('boolean')
+        ->setLabel($this->t('Default translation'))
+        ->setDescription($this->t('A flag indicating whether this is the default translation.'))
+        ->setTranslatable(TRUE)
+        ->setRevisionable(TRUE)
+        ->setDefaultValue(TRUE);
+    }
+
     $provider = $entity_type->getProvider();
     foreach ($base_field_definitions as $definition) {
       // @todo Remove this check once FieldDefinitionInterface exposes a proper
@@ -450,15 +462,21 @@ 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());
+    $fixed_keys = array('id', 'revision', 'uuid', 'bundle');
     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()) {
+      if (isset($base_field_definitions[$field_name]) && in_array($key, $fixed_keys) && $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)));
       }
-      if (isset($base_field_definitions[$field_name]) && in_array($key, array('id', 'revision', 'uuid', 'bundle', 'langcode')) && $base_field_definitions[$field_name]->isTranslatable()) {
+      if (isset($base_field_definitions[$field_name]) && in_array($key, $fixed_keys) && $base_field_definitions[$field_name]->isTranslatable()) {
         throw new \LogicException(String::format('The @field field cannot be translatable as it is used as @key entity key.', array('@field' => $base_field_definitions[$field_name]->getLabel(), '@key' => $key)));
       }
     }
+
+    // Make sure translatable entity types define the "langcode" field properly.
+    if ($entity_type->isTranslatable() && (!isset($keys['langcode']) || !isset($base_field_definitions[$keys['langcode']]) || !$base_field_definitions[$keys['langcode']]->isTranslatable())) {
+      throw new \LogicException(String::format('The @entity_type entity type cannot be translatable as it does not define a proper "langcode" field.', array('@entity_type' => $entity_type->getLabel())));
+    }
+
     return $base_field_definitions;
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php
index b23cd9d..54a10d8 100644
--- a/core/lib/Drupal/Core/Entity/EntityType.php
+++ b/core/lib/Drupal/Core/Entity/EntityType.php
@@ -238,6 +238,7 @@ public function __construct($definition) {
       'revision' => '',
       'bundle' => '',
       'langcode' => '',
+      'default_langcode' => 'default_langcode',
     );
     $this->handlers += array(
       'access' => 'Drupal\Core\Entity\EntityAccessControlHandler',
diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
index 0c09ec9..6e1ecf1 100644
--- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
+++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php
@@ -182,8 +182,8 @@ public function addField($field, $type, $langcode) {
 
         $table = $this->ensureEntityTable($index_prefix, $sql_column, $type, $langcode, $base_table, $entity_id_field, $entity_tables);
 
-        // If there is a field storage (some specifiers are not, like
-        // default_langcode), check for case sensitivity.
+        // If there is a field storage (some specifiers are not), check for case
+        // sensitivity.
         if ($field_storage) {
           $column = $field_storage->getMainPropertyName();
           $base_field_property_definitions = $field_storage->getPropertyDefinitions();
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 8a5a4a7..5968446 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -67,6 +67,13 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
   protected $langcodeKey = FALSE;
 
   /**
+   * The default language entity key.
+   *
+   * @var string
+   */
+  protected $defaultLangcodeKey = FALSE;
+
+  /**
    * The base table of the entity.
    *
    * @var string
@@ -200,7 +207,7 @@ protected function initTableLayout() {
     if ($translatable) {
       $this->dataTable = $this->entityType->getDataTable() ?: $this->entityTypeId . '_field_data';
       $this->langcodeKey = $this->entityType->getKey('langcode');
-      $this->defaultLangcodeKey = $this->entityType->getKey('default_langcode') ?: 'default_langcode';
+      $this->defaultLangcodeKey = $this->entityType->getKey('default_langcode');
     }
     if ($revisionable && $translatable) {
       $this->revisionDataTable = $this->entityType->getRevisionDataTable() ?: $this->entityTypeId . '_field_revision';
@@ -342,11 +349,7 @@ public function getTableMapping(array $storage_definitions = NULL) {
         // the data table.
         $table_mapping
           ->setFieldNames($this->baseTable, $key_fields)
-          ->setFieldNames($this->dataTable, array_values(array_diff($all_fields, array($this->uuidKey))))
-          // Add the denormalized 'default_langcode' field to the mapping. Its
-          // value is identical to the query expression
-          // "base_table.langcode = data_table.langcode"
-          ->setExtraColumns($this->dataTable, array('default_langcode'));
+          ->setFieldNames($this->dataTable, array_values(array_diff($all_fields, array($this->uuidKey))));
       }
       elseif ($revisionable && $translatable) {
         // The revisionable multilingual layout stores key field values in the
@@ -356,31 +359,20 @@ public function getTableMapping(array $storage_definitions = NULL) {
         // holds the data field values for all non-revisionable fields. The data
         // field values of revisionable fields are denormalized in the data
         // table, as well.
-        $table_mapping->setFieldNames($this->baseTable, array_values(array_diff($key_fields, array($this->langcodeKey))));
+        $table_mapping->setFieldNames($this->baseTable, array_values($key_fields));
 
         // Like in the multilingual, non-revisionable case the UUID is not
         // in the data table. Additionally, do not store revision metadata
         // fields in the data table.
         $data_fields = array_values(array_diff($all_fields, array($this->uuidKey), $revision_metadata_fields));
-        $table_mapping
-          ->setFieldNames($this->dataTable, $data_fields)
-          // Add the denormalized 'default_langcode' field to the mapping. Its
-          // value is identical to the query expression
-          // "base_langcode = data_table.langcode" where "base_langcode" is
-          // the language code of the default revision.
-          ->setExtraColumns($this->dataTable, array('default_langcode'));
+        $table_mapping->setFieldNames($this->dataTable, $data_fields);
 
         $revision_base_fields = array_merge(array($this->idKey, $this->revisionKey, $this->langcodeKey), $revision_metadata_fields);
         $table_mapping->setFieldNames($this->revisionTable, $revision_base_fields);
 
         $revision_data_key_fields = array($this->idKey, $this->revisionKey, $this->langcodeKey);
         $revision_data_fields = array_diff($revisionable_fields, $revision_metadata_fields, array($this->langcodeKey));
-        $table_mapping
-          ->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields))
-          // Add the denormalized 'default_langcode' field to the mapping. Its
-          // value is identical to the query expression
-          // "revision_table.langcode = data_table.langcode".
-          ->setExtraColumns($this->revisionDataTable, array('default_langcode'));
+        $table_mapping->setFieldNames($this->revisionDataTable, array_merge($revision_data_key_fields, $revision_data_fields));
       }
 
       // Add dedicated tables.
@@ -673,12 +665,14 @@ protected function attachPropertyData(array &$entities) {
 
       $table_mapping = $this->getTableMapping();
       if ($this->revisionDataTable) {
-        // Find revisioned fields that are not entity keys.
-        $fields = array_diff($table_mapping->getFieldNames($this->revisionDataTable), $table_mapping->getFieldNames($this->baseTable));
+        // Find revisioned fields that are not entity keys. Exclude the langcode
+        // key as the base table holds only the default language.
+        $base_fields = array_diff($table_mapping->getFieldNames($this->baseTable), array($this->langcodeKey));
+        $fields = array_diff($table_mapping->getFieldNames($this->revisionDataTable), $base_fields);
 
         // Find fields that are not revisioned or entity keys. Data fields have
         // the same value regardless of entity revision.
-        $data_fields = array_diff($table_mapping->getFieldNames($this->dataTable), $fields, $table_mapping->getFieldNames($this->baseTable));
+        $data_fields = array_diff($table_mapping->getFieldNames($this->dataTable), $fields, $base_fields);
         if ($data_fields) {
           $fields = array_merge($fields, $data_fields);
           $query->leftJoin($this->dataTable, 'data', "(revision.$this->idKey = data.$this->idKey)");
@@ -703,10 +697,9 @@ protected function attachPropertyData(array &$entities) {
 
         // Field values in default language are stored with
         // LanguageInterface::LANGCODE_DEFAULT as key.
-        $langcode = empty($values['default_langcode']) ? $values[$this->langcodeKey] : LanguageInterface::LANGCODE_DEFAULT;
+        $langcode = empty($values[$this->defaultLangcodeKey]) ? $values[$this->langcodeKey] : LanguageInterface::LANGCODE_DEFAULT;
         $translations[$id][$langcode] = TRUE;
 
-
         foreach ($fields as $field_name) {
           $columns = $table_mapping->getColumnNames($field_name);
           // Do not key single-column fields by property name.
@@ -776,13 +769,13 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value
       //   apply to the default language. See http://drupal.org/node/1866330.
       // Default to the original entity language if not explicitly specified
       // otherwise.
-      if (!array_key_exists('default_langcode', $values)) {
-        $values['default_langcode'] = 1;
+      if (!array_key_exists($this->defaultLangcodeKey, $values)) {
+        $values[$this->defaultLangcodeKey] = 1;
       }
       // If the 'default_langcode' flag is explicitly not set, we do not care
       // whether the queried values are in the original entity language or not.
-      elseif ($values['default_langcode'] === NULL) {
-        unset($values['default_langcode']);
+      elseif ($values[$this->defaultLangcodeKey] === NULL) {
+        unset($values[$this->defaultLangcodeKey]);
       }
     }
 
@@ -1156,8 +1149,6 @@ protected function mapToDataStorageRecord(EntityInterface $entity, $table_name =
       $table_name = $this->dataTable;
     }
     $record = $this->mapToStorageRecord($entity, $table_name);
-    $record->{$this->langcodeKey} = $entity->language()->getId();
-    $record->default_langcode = intval($record->{$this->langcodeKey} == $entity->getUntranslated()->language()->getId());
     return $record;
   }
 
@@ -1171,7 +1162,7 @@ protected function mapToDataStorageRecord(EntityInterface $entity, $table_name =
    *   The revision id.
    */
   protected function saveRevision(EntityInterface $entity) {
-    $record = $this->mapToStorageRecord($entity, $this->revisionTable);
+    $record = $this->mapToStorageRecord($entity->getUntranslated(), $this->revisionTable);
 
     $entity->preSaveRevision($this, $record);
 
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
index b987b90..4a399a3 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Database\Connection;
+use Drupal\Core\Database\DatabaseExceptionWrapper;
 use Drupal\Core\Entity\ContentEntityTypeInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\EntityStorageException;
@@ -163,7 +164,6 @@ public function requiresFieldStorageSchemaChanges(FieldStorageDefinitionInterfac
       $storage_definition->hasCustomStorage() != $original->hasCustomStorage() ||
       $storage_definition->getSchema() != $original->getSchema() ||
       $storage_definition->isRevisionable() != $original->isRevisionable() ||
-      $storage_definition->isTranslatable() != $original->isTranslatable() ||
       $table_mapping->allowsSharedTableStorage($storage_definition) != $table_mapping->allowsSharedTableStorage($original) ||
       $table_mapping->requiresDedicatedTableStorage($storage_definition) != $table_mapping->requiresDedicatedTableStorage($original)
     ) {
@@ -386,8 +386,17 @@ public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $
     // Only configurable fields currently support purging, so prevent deletion
     // of ones we can't purge if they have existing data.
     // @todo Add purging to all fields: https://www.drupal.org/node/2282119.
-    if (!($storage_definition instanceof FieldStorageConfigInterface) && $this->storage->countFieldData($storage_definition, TRUE)) {
-      throw new FieldStorageDefinitionUpdateForbiddenException('Unable to delete a field with data that can\'t be purged.');
+    try {
+      if (!($storage_definition instanceof FieldStorageConfigInterface) && $this->storage->countFieldData($storage_definition, TRUE)) {
+        throw new FieldStorageDefinitionUpdateForbiddenException('Unable to delete a field with data that can\'t be purged.');
+      }
+    }
+    catch (DatabaseExceptionWrapper $e) {
+      // This may happen when changing field storage schema, since we are not
+      // able to use a table mapping matching the passed storage definition.
+      // @todo Revisit this once we are able to instantiate the table mapping
+      //   properly. See https://www.drupal.org/node/2274017.
+      return;
     }
 
     // Retrieve a table mapping which contains the deleted field still.
@@ -506,13 +515,6 @@ protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $res
             $schema[$table_name] = array_merge_recursive($schema[$table_name], $this->getSharedTableFieldSchema($storage_definition, $table_name, $column_names));
           }
         }
-
-        // Add the schema for extra fields.
-        foreach ($table_mapping->getExtraColumns($table_name) as $column_name) {
-          if ($column_name == 'default_langcode') {
-            $this->addDefaultLangcodeSchema($schema[$table_name]);
-          }
-        }
       }
 
       // Process tables after having gathered field information.
@@ -727,25 +729,6 @@ protected function getFieldForeignKeys($field_name, array $field_schema, array $
   }
 
   /**
-   * Returns the schema for the 'default_langcode' metadata field.
-   *
-   * @param array $schema
-   *   The table schema to add the field schema to, passed by reference.
-   *
-   * @return array
-   *   A schema field array for the 'default_langcode' metadata field.
-   */
-  protected function addDefaultLangcodeSchema(&$schema) {
-    $schema['fields']['default_langcode'] =  array(
-      'description' => 'Boolean indicating whether field values are in the default entity language.',
-      'type' => 'int',
-      'size' => 'tiny',
-      'not null' => TRUE,
-      'default' => 1,
-    );
-  }
-
-  /**
    * Loads stored schema data for the given entity type definition.
    *
    * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
diff --git a/core/lib/Drupal/Core/TypedData/TranslatableInterface.php b/core/lib/Drupal/Core/TypedData/TranslatableInterface.php
index b3b832b..73b288d 100644
--- a/core/lib/Drupal/Core/TypedData/TranslatableInterface.php
+++ b/core/lib/Drupal/Core/TypedData/TranslatableInterface.php
@@ -13,7 +13,7 @@
 interface TranslatableInterface {
 
   /**
-   * Returns the default language.
+   * Returns the translation language.
    *
    * @return \Drupal\Core\Language\LanguageInterface
    *   The language object.
@@ -21,6 +21,14 @@
   public function language();
 
   /**
+   * Checks whether the translation is the default one.
+   *
+   * @return bool
+   *   TRUE if the translation is the default one, FALSE otherwise.
+   */
+  public function isDefaultTranslation();
+
+  /**
    * Returns the languages the data is translated to.
    *
    * @param bool $include_default
diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php
index 469c314..bab5cd8 100644
--- a/core/modules/block_content/src/Entity/BlockContent.php
+++ b/core/modules/block_content/src/Entity/BlockContent.php
@@ -167,6 +167,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     $fields['langcode'] = BaseFieldDefinition::create('language')
       ->setLabel(t('Language'))
       ->setDescription(t('The custom block language code.'))
+      ->setTranslatable(TRUE)
       ->setRevisionable(TRUE)
       ->setDisplayOptions('view', array(
         'type' => 'hidden',
diff --git a/core/modules/comment/src/Entity/Comment.php b/core/modules/comment/src/Entity/Comment.php
index 8b24aba..909abc3 100644
--- a/core/modules/comment/src/Entity/Comment.php
+++ b/core/modules/comment/src/Entity/Comment.php
@@ -224,6 +224,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     $fields['langcode'] = BaseFieldDefinition::create('language')
       ->setLabel(t('Language'))
       ->setDescription(t('The comment language code.'))
+      ->setTranslatable(TRUE)
       ->setDisplayOptions('view', array(
         'type' => 'hidden',
       ))
diff --git a/core/modules/content_translation/content_translation.admin.inc b/core/modules/content_translation/content_translation.admin.inc
index 341af53..fbb3a78 100644
--- a/core/modules/content_translation/content_translation.admin.inc
+++ b/core/modules/content_translation/content_translation.admin.inc
@@ -102,7 +102,7 @@ function _content_translation_form_language_content_settings_form_alter(array &$
         foreach ($fields as $field_name => $definition) {
           // Allow to configure only fields supporting multilingual storage.
           // We skip our own fields as they are always translatable.
-          if (!empty($storage_definitions[$field_name]) && $storage_definitions[$field_name]->isTranslatable() && $storage_definitions[$field_name]->getProvider() != 'content_translation') {
+          if (!empty($storage_definitions[$field_name]) && $storage_definitions[$field_name]->isTranslatable() && $storage_definitions[$field_name]->getProvider() != 'content_translation' && $field_name != $entity_type->getKey('langcode') && $field_name != $entity_type->getKey('default_langcode')) {
             $form['settings'][$entity_type_id][$bundle]['fields'][$field_name] = array(
               '#label' => $definition->getLabel(),
               '#type' => 'checkbox',
diff --git a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
index 78d7483..5570a2a 100644
--- a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
+++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
@@ -360,6 +360,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     $fields['langcode'] = BaseFieldDefinition::create('language')
       ->setLabel(t('Language'))
       ->setDescription(t('The menu link language code.'))
+      ->setTranslatable(TRUE)
       ->setDisplayOptions('view', array(
         'type' => 'hidden',
       ))
diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php
index f73155e..7535b15 100644
--- a/core/modules/node/src/Entity/Node.php
+++ b/core/modules/node/src/Entity/Node.php
@@ -353,6 +353,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     $fields['langcode'] = BaseFieldDefinition::create('language')
       ->setLabel(t('Language'))
       ->setDescription(t('The node language code.'))
+      ->setTranslatable(TRUE)
       ->setRevisionable(TRUE)
       ->setDisplayOptions('view', array(
         'type' => 'hidden',
diff --git a/core/modules/serialization/src/Tests/EntitySerializationTest.php b/core/modules/serialization/src/Tests/EntitySerializationTest.php
index a05bce6..04841a9 100644
--- a/core/modules/serialization/src/Tests/EntitySerializationTest.php
+++ b/core/modules/serialization/src/Tests/EntitySerializationTest.php
@@ -95,21 +95,24 @@ public function testNormalize() {
       'type' => array(
         array('value' => 'entity_test_mulrev'),
       ),
+      'created' => array(
+        array('value' => $this->entity->created->value),
+      ),
       'user_id' => array(
         array('target_id' => $this->values['user_id']),
       ),
       'revision_id' => array(
         array('value' => 1),
       ),
+      'default_langcode' => array(
+        array('value' => TRUE),
+      ),
       'field_test_text' => array(
         array(
           'value' => $this->values['field_test_text']['value'],
           'format' => $this->values['field_test_text']['format'],
         ),
       ),
-      'created' => array(
-        array('value' => $this->entity->created->value),
-      ),
     );
 
     $normalized = $this->serializer->normalize($this->entity);
@@ -175,10 +178,11 @@ public function testSerialize() {
       'langcode' => '<langcode><value>en</value></langcode>',
       'name' => '<name><value>' . $this->values['name'] . '</value></name>',
       'type' => '<type><value>entity_test_mulrev</value></type>',
+      'created' => '<created><value>' . $this->entity->created->value . '</value></created>',
       'user_id' => '<user_id><target_id>' . $this->values['user_id'] . '</target_id></user_id>',
       'revision_id' => '<revision_id><value>' . $this->entity->getRevisionId() . '</value></revision_id>',
+      'default_langcode' => '<default_langcode><value>1</value></default_langcode>',
       'field_test_text' => '<field_test_text><value>' . $this->values['field_test_text']['value'] . '</value><format>' . $this->values['field_test_text']['format'] . '</format></field_test_text>',
-      'created' => '<created><value>' . $this->entity->created->value . '</value></created>',
     );
     // Sort it in the same order as normalised.
     $expected = array_merge($normalized, $expected);
diff --git a/core/modules/shortcut/src/Entity/Shortcut.php b/core/modules/shortcut/src/Entity/Shortcut.php
index 9fd0332..a2179f9 100644
--- a/core/modules/shortcut/src/Entity/Shortcut.php
+++ b/core/modules/shortcut/src/Entity/Shortcut.php
@@ -163,6 +163,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     $fields['langcode'] = BaseFieldDefinition::create('language')
       ->setLabel(t('Language'))
       ->setDescription(t('The language code of the shortcut.'))
+      ->setTranslatable(TRUE)
       ->setDisplayOptions('view', array(
         'type' => 'hidden',
       ))
diff --git a/core/modules/system/src/Tests/Entity/EntityTranslationTest.php b/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
index 65bb740..c39b0bb 100644
--- a/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
@@ -588,9 +588,16 @@ function testFieldDefinitions() {
     $this->assertTrue(!isset($base_field_definitions['id']->translatable), 'Translatability for the <em>id</em> field is not defined.');
     $this->assertFalse($definitions['id']->isTranslatable(), 'Field translatability is disabled by default.');
 
-    // Check that entity ids and langcode fields cannot be translatable.
-    foreach (array('id', 'uuid', 'revision_id', 'type', 'langcode') as $name) {
-      $this->state->set('entity_test.field_definitions.translatable', array($name => TRUE));
+    // Check that entity id keys have the expect translatability.
+    $translatable_fields = array(
+      'id' => TRUE,
+      'uuid' => TRUE,
+      'revision_id' => TRUE,
+      'type' => TRUE,
+      'langcode' => FALSE,
+    );
+    foreach ($translatable_fields as $name => $translatable) {
+      $this->state->set('entity_test.field_definitions.translatable', array($name => $translatable));
       $this->entityManager->clearCachedFieldDefinitions();
       $message = format_string('Field %field cannot be translatable.', array('%field' => $name));
 
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 0549257..bec87c4 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
@@ -77,7 +77,8 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
 
     $fields['langcode'] = BaseFieldDefinition::create('language')
       ->setLabel(t('Language code'))
-      ->setDescription(t('The language code of the test entity.'));
+      ->setDescription(t('The language code of the test entity.'))
+      ->setTranslatable(TRUE);
 
     $fields['name'] = BaseFieldDefinition::create('string')
       ->setLabel(t('Name'))
diff --git a/core/modules/taxonomy/src/Entity/Term.php b/core/modules/taxonomy/src/Entity/Term.php
index 043c90d..7a1cc5f 100644
--- a/core/modules/taxonomy/src/Entity/Term.php
+++ b/core/modules/taxonomy/src/Entity/Term.php
@@ -121,6 +121,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     $fields['langcode'] = BaseFieldDefinition::create('language')
       ->setLabel(t('Language'))
       ->setDescription(t('The term language code.'))
+      ->setTranslatable(TRUE)
       ->setDisplayOptions('view', array(
         'type' => 'hidden',
       ))
diff --git a/core/modules/user/src/AccountForm.php b/core/modules/user/src/AccountForm.php
index 033731f..0d4e66d 100644
--- a/core/modules/user/src/AccountForm.php
+++ b/core/modules/user/src/AccountForm.php
@@ -344,7 +344,7 @@ public function alterPreferredLangcodeDescription(array $element) {
    *   The current state of the form.
    */
   public function syncUserLangcode($entity_type_id, UserInterface $user, array &$form, FormStateInterface &$form_state) {
-    $user->langcode = $user->preferred_langcode;
+    $user->getUntranslated()->langcode = $user->preferred_langcode;
   }
 
   /**
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index 76122bc..f770ee3 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -475,7 +475,8 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
 
     $fields['langcode'] = BaseFieldDefinition::create('language')
       ->setLabel(t('Language code'))
-      ->setDescription(t('The user language code.'));
+      ->setDescription(t('The user language code.'))
+      ->setTranslatable(TRUE);
 
     $fields['preferred_langcode'] = BaseFieldDefinition::create('language')
       ->setLabel(t('Preferred language code'))
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
index 8c159ec..179b8ad 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityManagerTest.php
@@ -37,6 +37,13 @@ class EntityManagerTest extends UnitTestCase {
   protected $entityManager;
 
   /**
+   * The entity type definition.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface
+   */
+  protected $entityType;
+
+  /**
    * The plugin discovery.
    *
    * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -146,17 +153,48 @@ protected function setUp() {
     $this->formBuilder = $this->getMock('Drupal\Core\Form\FormBuilderInterface');
     $this->controllerResolver = $this->getClassResolverStub();
 
-    $this->container = $this->getContainerWithCacheTagsInvalidator($this->cacheTagsInvalidator);
-
     $this->discovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
 
     $this->typedDataManager = $this->getMockBuilder('\Drupal\Core\TypedData\TypedDataManager')
       ->disableOriginalConstructor()
       ->getMock();
 
+    $map = [
+      ['field_item:boolean', TRUE, ['class' => 'Drupal\Core\Field\Plugin\Field\FieldType\BooleanItem']],
+    ];
+
+    $this->typedDataManager->expects($this->any())
+      ->method('getDefinition')
+      ->will($this->returnValueMap($map));
+
     $this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
 
     $this->installedDefinitions = $this->getMock('Drupal\Core\KeyValueStore\KeyValueStoreInterface');
+
+    $this->container = $this->getContainerWithCacheTagsInvalidator($this->cacheTagsInvalidator);
+    $this->container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+    \Drupal::setContainer($this->container);
+
+    $field_type_manager = $this->getMock('Drupal\Core\Field\FieldTypePluginManagerInterface');
+    $field_type_manager->expects($this->any())
+      ->method('getDefaultStorageSettings')
+      ->will($this->returnValue(array()));
+    $field_type_manager->expects($this->any())
+      ->method('getDefaultFieldSettings')
+      ->will($this->returnValue(array()));
+
+    $string_translation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface');
+
+    $map = [
+      ['cache_tags.invalidator', 1, $this->cacheTagsInvalidator],
+      ['plugin.manager.field.field_type', 1, $field_type_manager],
+      ['string_translation', 1, $string_translation],
+      ['typed_data_manager', 1, $this->typedDataManager],
+    ];
+
+    $this->container->expects($this->any())
+      ->method('get')
+      ->will($this->returnValueMap($map));
   }
 
   /**
@@ -668,6 +706,10 @@ public function testGetBaseFieldDefinitionsInvalidDefinition() {
     $langcode_definition = $this->setUpEntityWithFieldDefinition(FALSE, 'langcode', array('langcode' => 'langcode'));
     $langcode_definition->expects($this->once())
       ->method('isTranslatable')
+      ->will($this->returnValue(FALSE));
+
+    $this->entityType->expects($this->any())
+      ->method('isTranslatable')
       ->will($this->returnValue(TRUE));
 
     $this->entityManager->getBaseFieldDefinitions('test_entity_type');
@@ -725,19 +767,20 @@ public function testGetFieldDefinitionsProvider() {
    *   A field definition object.
    */
   protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $field_definition_id = 'id', $entity_keys = array()) {
-    $entity_type = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $this->entityType = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+
     $entity = $this->getMockBuilder('Drupal\Tests\Core\Entity\EntityManagerTestEntity')
       ->disableOriginalConstructor()
       ->getMockForAbstractClass();
     $entity_class = get_class($entity);
 
-    $entity_type->expects($this->any())
+    $this->entityType->expects($this->any())
       ->method('getClass')
       ->will($this->returnValue($entity_class));
-    $entity_type->expects($this->any())
+    $this->entityType->expects($this->any())
       ->method('getKeys')
-      ->will($this->returnValue($entity_keys));
-    $entity_type->expects($this->any())
+      ->will($this->returnValue($entity_keys + array('default_langcode' => 'default_langcode')));
+    $this->entityType->expects($this->any())
       ->method('isSubclassOf')
       ->with($this->equalTo('\Drupal\Core\Entity\FieldableEntityInterface'))
       ->will($this->returnValue(TRUE));
@@ -769,7 +812,7 @@ protected function setUpEntityWithFieldDefinition($custom_invoke_all = FALSE, $f
       ->with('storage')
       ->will($this->returnValue('\Drupal\Tests\Core\Entity\TestConfigEntityStorage'));
 
-    $this->setUpEntityManager(array('test_entity_type' => $entity_type, 'base_field_override' => $override_entity_type));
+    $this->setUpEntityManager(array('test_entity_type' => $this->entityType, 'base_field_override' => $override_entity_type));
 
     return $field_definition;
   }
@@ -1059,7 +1102,7 @@ public function testGetFieldMap() {
       ->will($this->returnValue($entity_class));
     $entity_type->expects($this->any())
       ->method('getKeys')
-      ->will($this->returnValue(array()));
+      ->will($this->returnValue(array('default_langcode' => 'default_langcode')));
     $entity_type->expects($this->any())
       ->method('id')
       ->will($this->returnValue('test_entity_type'));
@@ -1202,7 +1245,7 @@ public function testGetFieldMapByFieldType() {
       ->will($this->returnValue($entity_class));
     $entity_type->expects($this->any())
       ->method('getKeys')
-      ->will($this->returnValue(array()));
+      ->will($this->returnValue(array('default_langcode' => 'default_langcode')));
     $entity_type->expects($this->any())
       ->method('id')
       ->will($this->returnValue('test_entity_type'));
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
index c4ae0b6..6a61fa1 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php
@@ -38,7 +38,7 @@ protected function setUpEntityType($definition) {
    */
   public function testGetKeys($entity_keys, $expected) {
     $entity_type = $this->setUpEntityType(array('entity_keys' => $entity_keys));
-    $this->assertSame($expected, $entity_type->getKeys());
+    $this->assertSame($expected + ['default_langcode' => 'default_langcode'], $entity_type->getKeys());
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
index 9a786d5..237435f 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageSchemaTest.php
@@ -89,7 +89,6 @@ protected function setUp() {
    * @covers ::getFieldUniqueKeys
    * @covers ::getFieldForeignKeys
    * @covers ::getFieldSchemaData
-   * @covers ::addDefaultLangcodeSchema
    * @covers ::processBaseTable
    * @covers ::processIdentifierSchema
    */
@@ -321,13 +320,6 @@ public function testGetSchemaBase() {
             'type' => 'int',
             'not null' => FALSE,
           ),
-          'default_langcode' => array(
-            'description' => 'Boolean indicating whether field values are in the default entity language.',
-            'type' => 'int',
-            'size' => 'tiny',
-            'not null' => TRUE,
-            'default' => 1,
-          ),
         ),
         'primary key' => array('id'),
         'unique keys' => array(
diff --git a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
index ec24b1a..8d5b681 100644
--- a/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/Sql/SqlContentEntityStorageTest.php
@@ -643,7 +643,6 @@ public function testGetTableMappingTranslatable(array $entity_keys) {
     $expected = array();
     $actual = $mapping->getExtraColumns('entity_test');
     $this->assertEquals($expected, $actual);
-    $expected = array('default_langcode');
     $actual = $mapping->getExtraColumns('entity_test_field_data');
     $this->assertEquals($expected, $actual);
   }
@@ -704,7 +703,6 @@ public function testGetTableMappingTranslatableWithFields(array $entity_keys) {
     $expected = array();
     $actual = $mapping->getExtraColumns('entity_test');
     $this->assertEquals($expected, $actual);
-    $expected = array('default_langcode');
     $actual = $mapping->getExtraColumns('entity_test_field_data');
     $this->assertEquals($expected, $actual);
   }
@@ -761,13 +759,13 @@ public function testGetTableMappingRevisionableTranslatable(array $entity_keys)
     );
     $this->assertEquals($expected, $mapping->getTableNames());
 
-    // The language code is not stored on the base table, but on the revision
-    // table.
+    // The default language code is stored on the base table.
     $expected = array_values(array_filter(array(
       $entity_keys['id'],
       $entity_keys['revision'],
       $entity_keys['bundle'],
       $entity_keys['uuid'],
+      $entity_keys['langcode'],
     )));
     $actual = $mapping->getFieldNames('entity_test');
     $this->assertEquals($expected, $actual);
@@ -803,7 +801,6 @@ public function testGetTableMappingRevisionableTranslatable(array $entity_keys)
     $this->assertEquals($expected, $actual);
     $actual = $mapping->getExtraColumns('entity_test_revision');
     $this->assertEquals($expected, $actual);
-    $expected = array('default_langcode');
     $actual = $mapping->getExtraColumns('entity_test_field_data');
     $this->assertEquals($expected, $actual);
     $actual = $mapping->getExtraColumns('entity_test_field_revision');
@@ -891,13 +888,13 @@ public function testGetTableMappingRevisionableTranslatableWithFields(array $ent
       );
       $this->assertEquals($expected, $mapping->getTableNames());
 
-      // The language code is not stored on the base table, but on the revision
-      // table.
+      // The default language code is not stored on the base table.
       $expected = array_values(array_filter(array(
         $entity_keys['id'],
         $entity_keys['revision'],
         $entity_keys['bundle'],
         $entity_keys['uuid'],
+        $entity_keys['langcode'],
       )));
       $actual = $mapping->getFieldNames('entity_test');
       $this->assertEquals($expected, $actual);
@@ -933,7 +930,6 @@ public function testGetTableMappingRevisionableTranslatableWithFields(array $ent
       $this->assertEquals($expected, $actual);
       $actual = $mapping->getExtraColumns('entity_test_revision');
       $this->assertEquals($expected, $actual);
-      $expected = array('default_langcode');
       $actual = $mapping->getExtraColumns('entity_test_field_data');
       $this->assertEquals($expected, $actual);
       $actual = $mapping->getExtraColumns('entity_test_field_revision');
