diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 5447e90..82fbe7a 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -154,10 +154,10 @@ public function __construct(array $values, $entity_type, $bundle = FALSE, $trans
     // original language.
     $data = array('status' => static::TRANSLATION_EXISTING);
     $this->translations[Language::LANGCODE_DEFAULT] = $data;
+    $this->initializeDefaultLanguage();
     if ($translations) {
-      $default_langcode = $this->language()->id;
       foreach ($translations as $langcode) {
-        if ($langcode != $default_langcode && $langcode != Language::LANGCODE_DEFAULT) {
+        if ($langcode != $this->language->id && $langcode != Language::LANGCODE_DEFAULT) {
           $this->translations[$langcode] = $data;
         }
       }
@@ -399,7 +399,8 @@ protected function getTranslatedField($property_name, $langcode) {
       }
       // Non-translatable fields are always stored with
       // Language::LANGCODE_DEFAULT as key.
-      if ($langcode != Language::LANGCODE_DEFAULT && empty($definition['translatable'])) {
+      $default = $langcode == Language::LANGCODE_DEFAULT;
+      if (!$default && empty($definition['translatable'])) {
         if (!isset($this->fields[$property_name][Language::LANGCODE_DEFAULT])) {
           $this->fields[$property_name][Language::LANGCODE_DEFAULT] = $this->getTranslatedField($property_name, Language::LANGCODE_DEFAULT);
         }
@@ -411,7 +412,14 @@ protected function getTranslatedField($property_name, $langcode) {
           $value = $this->values[$property_name][$langcode];
         }
         $field = \Drupal::typedData()->getPropertyInstance($this, $property_name, $value);
-        $field->setLangcode($langcode);
+        if (!$default) {
+          $field->setLangcode($langcode);
+        }
+        // If we are initializing the default language cache, the variable is
+        // not populated, thus we have no valid value to set.
+        elseif (isset($this->language)) {
+          $field->setLangcode($this->language->id);
+        }
         $this->fields[$property_name][$langcode] = $field;
       }
     }
@@ -537,17 +545,17 @@ public function language() {
       return $this->languages[$this->activeLangcode];
     }
     else {
-      return $this->language ?: $this->getDefaultLanguage();
+      return $this->language;
     }
   }
 
   /**
-   * Returns the entity original language.
+   * Initializes the entity original language local cache.
    *
    * @return \Drupal\Core\Language\Language
    *   A language object.
    */
-  protected function getDefaultLanguage() {
+  protected function initializeDefaultLanguage() {
     // Keep a local cache of the language object and clear it if the langcode
     // gets changed, see ContentEntityBase::onChange().
     if (!isset($this->language)) {
@@ -559,11 +567,32 @@ protected function getDefaultLanguage() {
         // Make sure we return a proper language object.
         $this->language = new Language(array('id' => Language::LANGCODE_NOT_SPECIFIED, 'locked' => TRUE));
       }
+      // 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'][Language::LANGCODE_DEFAULT]->setLangcode($this->language->id);
+      }
     }
     return $this->language;
   }
 
   /**
+   * Updates language for already instantiated fields.
+   *
+   * @return \Drupal\Core\Language\Language
+   *   A language object.
+   */
+  protected function updateFieldLangcodes($langcode) {
+    if (!empty($this->fields)) {
+      foreach ($this->fields as $name => $items) {
+        if (!empty($items[Language::LANGCODE_DEFAULT])) {
+          $items[Language::LANGCODE_DEFAULT]->setLangcode($langcode);
+        }
+      }
+    }
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function onChange($property_name) {
@@ -571,6 +600,8 @@ public function onChange($property_name) {
       // Avoid using unset as this unnecessarily triggers magic methods later
       // on.
       $this->language = NULL;
+      $this->initializeDefaultLanguage();
+      $this->updateFieldLangcodes($this->language->id);
     }
   }
 
@@ -582,11 +613,8 @@ public function onChange($property_name) {
   public function getTranslation($langcode) {
     // Ensure we always use the default language code when dealing with the
     // original entity language.
-    if ($langcode != Language::LANGCODE_DEFAULT) {
-      $default_language = $this->language ?: $this->getDefaultLanguage();
-      if ($langcode == $default_language->id) {
-        $langcode = Language::LANGCODE_DEFAULT;
-      }
+    if ($langcode != Language::LANGCODE_DEFAULT && $langcode == $this->language->id) {
+      $langcode = Language::LANGCODE_DEFAULT;
     }
 
     // Populate entity translation object cache so it will be available for all
@@ -613,7 +641,7 @@ public function getTranslation($langcode) {
           // If the entity or the requested language  is not a configured
           // language, we fall back to the entity itself, since in this case it
           // cannot have translations.
-          $translation = empty($this->getDefaultLanguage()->locked) && empty($languages[$langcode]->locked) ? $this->addTranslation($langcode) : $this;
+          $translation = empty($this->language->locked) && empty($languages[$langcode]->locked) ? $this->addTranslation($langcode) : $this;
         }
       }
     }
@@ -674,8 +702,7 @@ protected function initializeTranslation($langcode) {
    * {@inheritdoc}
    */
   public function hasTranslation($langcode) {
-    $default_language = $this->language ?: $this->getDefaultLanguage();
-    if ($langcode == $default_language->id) {
+    if ($langcode == $this->language->id) {
       $langcode = Language::LANGCODE_DEFAULT;
     }
     return !empty($this->translations[$langcode]['status']);
@@ -722,7 +749,7 @@ public function addTranslation($langcode, array $values = array()) {
    * {@inheritdoc}
    */
   public function removeTranslation($langcode) {
-    if (isset($this->translations[$langcode]) && $langcode != Language::LANGCODE_DEFAULT && $langcode != $this->getDefaultLanguage()->id) {
+    if (isset($this->translations[$langcode]) && $langcode != Language::LANGCODE_DEFAULT && $langcode != $this->language->id) {
       foreach ($this->getPropertyDefinitions() as $name => $definition) {
         if (!empty($definition['translatable'])) {
           unset($this->values[$name][$langcode]);
@@ -741,7 +768,7 @@ public function removeTranslation($langcode) {
    * {@inheritdoc}
    */
   public function initTranslation($langcode) {
-    if ($langcode != Language::LANGCODE_DEFAULT && $langcode != $this->getDefaultLanguage()->id) {
+    if ($langcode != Language::LANGCODE_DEFAULT && $langcode != $this->language->id) {
       $this->translations[$langcode]['status'] = static::TRANSLATION_EXISTING;
     }
   }
@@ -754,8 +781,7 @@ public function getTranslationLanguages($include_default = TRUE) {
     unset($translations[Language::LANGCODE_DEFAULT]);
 
     if ($include_default) {
-      $langcode = $this->getDefaultLanguage()->id;
-      $translations[$langcode] = TRUE;
+      $translations[$this->language->id] = TRUE;
     }
 
     // Now load language objects based upon translation langcodes.
@@ -915,10 +941,7 @@ public function __clone() {
       // original reference and re-creating its values.
       $this->clearTranslationCache();
       $translations = $this->translations;
-      unset($this->translations);
-      // This will trigger the magic setter as the translations array is
-      // undefined now.
-      $this->translations = $translations;
+      $this->translations = &$translations;
     }
   }
 
diff --git a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
index 5497efb..11666f3 100644
--- a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
+++ b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
@@ -325,7 +325,7 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) {
           // Get the revision IDs.
           $revision_ids = array();
           foreach ($entities as $values) {
-            $revision_ids[] = $values[$this->revisionKey];
+            $revision_ids[] = $values[$this->revisionKey][Language::LANGCODE_DEFAULT];
           }
           $query->condition($this->revisionKey, $revision_ids);
         }
@@ -849,41 +849,47 @@ protected function doLoadFieldItems($entities, $age) {
     }
 
     // Load field data.
-    $all_langcodes = array_keys(language_list());
+    $all_langcodes = array_keys(language_list(Language::STATE_ALL));
     foreach ($fields as $field_name => $field) {
       $table = $load_current ? static::_fieldTableName($field) : static::_fieldRevisionTableName($field);
 
-      // If the field is translatable ensure that only values having valid
-      // languages are retrieved. Since we are loading values for multiple
-      // entities, we cannot limit the query to the available translations.
-      $langcodes = $field->isFieldTranslatable() ? $all_langcodes : array(Language::LANGCODE_NOT_SPECIFIED);
+      // Ensure that only values having valid languages are retrieved. Since we
+      // are loading values for multiple entities, we cannot limit the query to
+      // the available translations.
       $results = $this->database->select($table, 't')
         ->fields('t')
         ->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN')
         ->condition('deleted', 0)
-        ->condition('langcode', $langcodes, 'IN')
+        ->condition('langcode', $all_langcodes, 'IN')
         ->orderBy('delta')
         ->execute();
 
+      $translatable = $field->isFieldTranslatable();
       $delta_count = array();
       foreach ($results as $row) {
-        if (!isset($delta_count[$row->entity_id][$row->langcode])) {
-          $delta_count[$row->entity_id][$row->langcode] = 0;
-        }
-
-        if ($field->getFieldCardinality() == FieldInterface::CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->getFieldCardinality()) {
-          $item = array();
-          // For each column declared by the field, populate the item from the
-          // prefixed database column.
-          foreach ($field->getColumns() as $column => $attributes) {
-            $column_name = static::_fieldColumnName($field, $column);
-            // Unserialize the value if specified in the column schema.
-            $item[$column] = (!empty($attributes['serialize'])) ? unserialize($row->$column_name) : $row->$column_name;
+        // Ensure that records for non-translatable fields having invalid
+        // languages are skipped.
+        // @todo Remove BC support for 'und' untranslatable fields as soon as
+        //   can write a migration for them.
+        if ($translatable || $row->langcode == Language::LANGCODE_NOT_SPECIFIED || $row->langcode == $entities[$row->entity_id]->getUntranslated()->language()->id) {
+          if (!isset($delta_count[$row->entity_id][$row->langcode])) {
+            $delta_count[$row->entity_id][$row->langcode] = 0;
           }
 
-          // Add the item to the field values for the entity.
-          $entities[$row->entity_id]->getTranslation($row->langcode)->{$field_name}[$delta_count[$row->entity_id][$row->langcode]] = $item;
-          $delta_count[$row->entity_id][$row->langcode]++;
+          if ($field->getFieldCardinality() == FieldInterface::CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->getFieldCardinality()) {
+            $item = array();
+            // For each column declared by the field, populate the item from the
+            // prefixed database column.
+            foreach ($field->getColumns() as $column => $attributes) {
+              $column_name = static::_fieldColumnName($field, $column);
+              // Unserialize the value if specified in the column schema.
+              $item[$column] = (!empty($attributes['serialize'])) ? unserialize($row->$column_name) : $row->$column_name;
+            }
+
+            // Add the item to the field values for the entity.
+            $entities[$row->entity_id]->getTranslation($row->langcode)->{$field_name}[$delta_count[$row->entity_id][$row->langcode]] = $item;
+            $delta_count[$row->entity_id][$row->langcode]++;
+          }
         }
       }
     }
@@ -897,6 +903,9 @@ protected function doSaveFieldItems(EntityInterface $entity, $update) {
     $id = $entity->id();
     $bundle = $entity->bundle();
     $entity_type = $entity->entityType();
+    $default_langcode = $entity->getUntranslated()->language()->id;
+    $translation_langcodes = array_keys($entity->getTranslationLanguages());
+
     if (!isset($vid)) {
       $vid = $id;
     }
@@ -930,7 +939,7 @@ protected function doSaveFieldItems(EntityInterface $entity, $update) {
       $query = $this->database->insert($table_name)->fields($columns);
       $revision_query = $this->database->insert($revision_name)->fields($columns);
 
-      $langcodes = $field->isFieldTranslatable() ? array_keys($entity->getTranslationLanguages()) : array(Language::LANGCODE_NOT_SPECIFIED);
+      $langcodes = $field->isFieldTranslatable() ? $translation_langcodes : array($default_langcode);
       foreach ($langcodes as $langcode) {
         $delta_count = 0;
         $items = $entity->getTranslation($langcode)->get($field_name);
diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php
index 00dcaba..da50ce1 100644
--- a/core/lib/Drupal/Core/Field/FieldItemList.php
+++ b/core/lib/Drupal/Core/Field/FieldItemList.php
@@ -39,7 +39,7 @@ class FieldItemList extends ItemList implements FieldItemListInterface {
    *
    * @var string
    */
-  protected $langcode = Language::LANGCODE_DEFAULT;
+  protected $langcode = Language::LANGCODE_NOT_SPECIFIED;
 
   /**
    * Overrides TypedData::__construct().
diff --git a/core/lib/Drupal/Core/Language/Language.php b/core/lib/Drupal/Core/Language/Language.php
index b5ea710..0174a99 100644
--- a/core/lib/Drupal/Core/Language/Language.php
+++ b/core/lib/Drupal/Core/Language/Language.php
@@ -59,11 +59,8 @@ class Language {
 
   /**
    * Language code referring to the default language of data, e.g. of an entity.
-   *
-   * @todo: Change value to differ from Language::LANGCODE_NOT_SPECIFIED once
-   * field API leverages the property API.
    */
-  const LANGCODE_DEFAULT = 'und';
+  const LANGCODE_DEFAULT = 'xx-default';
 
   /**
    * The language state when referring to configurable languages.
diff --git a/core/modules/content_translation/content_translation.admin.inc b/core/modules/content_translation/content_translation.admin.inc
index 6d02b9d..4c767f0 100644
--- a/core/modules/content_translation/content_translation.admin.inc
+++ b/core/modules/content_translation/content_translation.admin.inc
@@ -331,9 +331,6 @@ function content_translation_form_language_content_settings_submit(array $form,
  *     language_save_default_configuration().
  *   - fields: An associative array with field names as keys and a boolean as
  *     value, indicating field translatability.
- *
- * @todo Remove this migration entirely once the Field API is converted to the
- *   Entity Field API.
  */
 function _content_translation_update_field_translatability($settings) {
   $fields = array();
@@ -346,224 +343,15 @@ function _content_translation_update_field_translatability($settings) {
         foreach ($bundle_settings['fields'] as $field_name => $translatable) {
           // If a field is enabled for translation for at least one instance we
           // need to mark it as translatable.
-          if (FieldService::fieldInfo()->getField($entity_type, $field_name)) {
-            $fields[$entity_type][$field_name] = $translatable || !empty($fields[$entity_type][$field_name]);
+          $field = FieldService::fieldInfo()->getField($entity_type, $field_name);
+          if ($field && $field->isFieldTranslatable() !== $translatable) {
+            $field->translatable = $translatable;
+            $field->save();
           }
         }
       }
     }
   }
 
-  $operations = array();
-  foreach ($fields as $entity_type => $entity_type_fields) {
-    foreach ($entity_type_fields as $field_name => $translatable) {
-      $field = field_info_field($entity_type, $field_name);
-      if ($field->isFieldTranslatable() != $translatable) {
-        // If a field is untranslatable, it can have no data except under
-        // Language::LANGCODE_NOT_SPECIFIED. Thus we need a field to be translatable before
-        // we convert data to the entity language. Conversely we need to switch
-        // data back to Language::LANGCODE_NOT_SPECIFIED before making a field
-        // untranslatable lest we lose information.
-        $field_operations = array(
-          array('content_translation_translatable_switch', array($translatable, $entity_type, $field_name)),
-        );
-        if ($field->hasData()) {
-          $field_operations[] = array('content_translation_translatable_batch', array($translatable, $field_name));
-          $field_operations = $translatable ? $field_operations : array_reverse($field_operations);
-        }
-        $operations = array_merge($operations, $field_operations);
-      }
-    }
-  }
-
-  // As last operation store the submitted settings.
-  $operations[] = array('content_translation_save_settings', array($settings));
-
-  $batch = array(
-    'title' => t('Updating translatability for the selected fields'),
-    'operations' => $operations,
-    'finished' => 'content_translation_translatable_batch_done',
-    'file' => drupal_get_path('module', 'content_translation') . '/content_translation.admin.inc',
-  );
-  batch_set($batch);
-}
-
-/**
- * Toggles translatability of the given field.
- *
- * This is called from a batch operation, but should only run once per field.
- *
- * @param bool $translatable
- *   Indicator of whether the field should be made translatable (TRUE) or
- *   untranslatble (FALSE).
- * @param string $entity_type
- *   Field entity type.
- * @param string $field_name
- *   Field machine name.
- */
-function content_translation_translatable_switch($translatable, $entity_type, $field_name) {
-  $field = field_info_field($entity_type, $field_name);
-  if ($field->isFieldTranslatable() !== $translatable) {
-    $field->translatable = $translatable;
-    $field->save();
-  }
+  content_translation_save_settings($settings);
 }
-
-/**
- * Batch callback: Converts field data to or from Language::LANGCODE_NOT_SPECIFIED.
- *
- * @param bool $translatable
- *   Indicator of whether the field should be made translatable (TRUE) or
- *   untranslatble (FALSE).
- * @param string $field_name
- *   Field machine name.
- */
-function content_translation_translatable_batch($translatable, $field_name, &$context) {
-  // Determine the entity types to act on.
-  $entity_types = array();
-  foreach (field_info_instances() as $entity_type => $info) {
-    foreach ($info as $bundle => $instances) {
-      foreach ($instances as $instance_field_name => $instance) {
-        if ($instance_field_name == $field_name) {
-          $entity_types[] = $entity_type;
-          break 2;
-        }
-      }
-    }
-  }
-
-  if (empty($context['sandbox'])) {
-    $context['sandbox']['progress'] = 0;
-    $context['sandbox']['max'] = 0;
-
-    foreach ($entity_types as $entity_type) {
-      $field = field_info_field($entity_type, $field_name);
-      $columns = $field->getColumns();
-      $column = isset($columns['value']) ? 'value' : key($columns);
-      $query_field = "$field_name.$column";
-
-      // How many entities will need processing?
-      $query = \Drupal::entityQuery($entity_type);
-      $count = $query
-        ->exists($query_field)
-        ->count()
-        ->execute();
-
-      $context['sandbox']['max'] += $count;
-      $context['sandbox']['progress_entity_type'][$entity_type] = 0;
-      $context['sandbox']['max_entity_type'][$entity_type] = $count;
-    }
-
-    if ($context['sandbox']['max'] === 0) {
-      // Nothing to do.
-      $context['finished'] = 1;
-      return;
-    }
-  }
-
-  foreach ($entity_types as $entity_type) {
-    if ($context['sandbox']['max_entity_type'][$entity_type] === 0) {
-      continue;
-    }
-
-    $info = entity_get_info($entity_type);
-    $offset = $context['sandbox']['progress_entity_type'][$entity_type];
-    $query = \Drupal::entityQuery($entity_type);
-    $field = field_info_field($entity_type, $field_name);
-    $columns = $field->getColumns();
-    $column = isset($columns['value']) ? 'value' : key($columns);
-    $query_field = "$field_name.$column";
-    $result = $query
-      ->exists($query_field)
-      ->sort($info['entity_keys']['id'])
-      ->range($offset, 10)
-      ->execute();
-
-    foreach (entity_load_multiple($entity_type, $result) as $id => $entity) {
-      $context['sandbox']['max_entity_type'][$entity_type] -= count($result);
-      $context['sandbox']['progress_entity_type'][$entity_type]++;
-      $context['sandbox']['progress']++;
-      $langcode = $entity->language()->id;
-
-      // Skip process for language neutral entities.
-      if ($langcode == Language::LANGCODE_NOT_SPECIFIED) {
-        continue;
-      }
-
-      // We need a two-step approach while updating field translations: given
-      // that field-specific update functions might rely on the stored values to
-      // perform their processing first we need to store the new translations
-      // and only after we can remove the old ones. Otherwise we might have data
-      // loss, since the removal of the old translations might occur before the
-      // new ones are stored.
-      if ($translatable && isset($entity->{$field_name}[Language::LANGCODE_NOT_SPECIFIED])) {
-        // If the field is being switched to translatable and has data for
-        // Language::LANGCODE_NOT_SPECIFIED then we need to move the data to the right
-        // language.
-        $entity->{$field_name}[$langcode] = $entity->{$field_name}[Language::LANGCODE_NOT_SPECIFIED];
-        // Store the original value.
-        _content_translation_update_field($entity_type, $entity, $field_name);
-        $entity->{$field_name}[Language::LANGCODE_NOT_SPECIFIED] = array();
-        // Remove the language neutral value.
-        _content_translation_update_field($entity_type, $entity, $field_name);
-      }
-      elseif (!$translatable && isset($entity->{$field_name}[$langcode])) {
-        // The field has been marked untranslatable and has data in the entity
-        // language: we need to move it to Language::LANGCODE_NOT_SPECIFIED and drop the
-        // other translations.
-        $entity->{$field_name}[Language::LANGCODE_NOT_SPECIFIED] = $entity->{$field_name}[$langcode];
-        // Store the original value.
-        _content_translation_update_field($entity_type, $entity, $field_name);
-        // Remove translations.
-        foreach ($entity->{$field_name} as $langcode => $items) {
-          if ($langcode != Language::LANGCODE_NOT_SPECIFIED) {
-            $entity->{$field_name}[$langcode] = array();
-          }
-        }
-        _content_translation_update_field($entity_type, $entity, $field_name);
-      }
-      else {
-        // No need to save unchanged entities.
-        continue;
-      }
-    }
-  }
-
-  $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
-}
-
-/**
- * Stores the given field translations.
- */
-function _content_translation_update_field($entity_type, EntityInterface $entity, $field_name) {
-  $empty = 0;
-  $translations = $entity->getTranslationLanguages();
-
-  // Ensure that we are trying to store only valid data.
-  foreach (array_keys($translations) as $langcode) {
-    $items = $entity->getTranslation($langcode)->get($field_name);
-    $items->filterEmptyValues();
-    $empty += $items->isEmpty();
-  }
-
-  // Save the field value only if there is at least one item available,
-  // otherwise any stored empty field value would be deleted. If this happens
-  // the range queries would be messed up.
-  if ($empty < count($translations)) {
-    $entity->save();
-  }
-}
-
-/**
- * Batch finished callback: Checks the exit status of the batch operation.
- */
-function content_translation_translatable_batch_done($success, $results, $operations) {
-  if ($success) {
-    drupal_set_message(t("Successfully changed field translation setting."));
-  }
-  else {
-    // @todo: Do something about this case.
-    drupal_set_message(t("Something went wrong while processing data. Some nodes may appear to have lost fields."), 'error');
-  }
-}
-
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index 66bb500..0d9c3cb 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -86,10 +86,6 @@ function content_translation_entity_info_alter(array &$entity_info) {
       $info['translation']['content_translation'] = array();
     }
 
-    // Every fieldable entity type must have a translation controller class, no
-    // matter if it is enabled for translation or not. As a matter of fact we
-    // might need it to correctly switch field translatability when a field is
-    // shared accross different entities.
     $info['controllers'] += array('translation' => 'Drupal\content_translation\ContentTranslationController');
 
     // If no menu base path is provided we default to the usual
@@ -217,12 +213,6 @@ function content_translation_menu() {
     }
   }
 
-  $items['admin/config/regional/content_translation/translatable/%/%'] = array(
-    'title' => 'Confirm change in translatability.',
-    'description' => 'Confirm page for changing field translatability.',
-    'route_name' => 'content_translation.translatable',
-  );
-
   return $items;
 }
 
@@ -811,36 +801,12 @@ function content_translation_field_extra_fields() {
  * Implements hook_form_FORM_ID_alter() for 'field_ui_field_edit_form'.
  */
 function content_translation_form_field_ui_field_edit_form_alter(array &$form, array &$form_state, $form_id) {
-  $field = $form['#field'];
-  $field_name = $field->getFieldName();
-  $translatable = $field->isFieldTranslatable();
-  $entity_type = $field->entity_type;
-  $label = t('Field translation');
-
-  if ($field->hasData()) {
-    $form['field']['translatable'] = array(
-      '#type' => 'item',
-      '#title' => $label,
-      '#attributes' => array('class' => 'translatable'),
-      'link' => array(
-        '#type' => 'link',
-        '#prefix' => t('This field has data in existing content.') . ' ',
-        '#title' => !$translatable ? t('Enable translation') : t('Disable translation'),
-        '#href' => "admin/config/regional/content_translation/translatable/$entity_type/$field_name",
-        '#options' => array('query' => drupal_get_destination()),
-        '#access' => user_access('administer content translation'),
-      ),
-    );
-  }
-  else {
-    $form['field']['translatable'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Users may translate this field.'),
-      '#default_value' => $translatable,
-    );
-  }
-
-  $form['field']['translatable']['#weight'] = 20;
+  $form['field']['translatable'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Users may translate this field.'),
+    '#default_value' => $form['#field']->isFieldTranslatable(),
+    '#weight' => 20,
+  );
 }
 
 /**
diff --git a/core/modules/content_translation/content_translation.routing.yml b/core/modules/content_translation/content_translation.routing.yml
deleted file mode 100644
index 51db4a3..0000000
--- a/core/modules/content_translation/content_translation.routing.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-content_translation.translatable:
-  path: '/admin/config/regional/content_translation/translatable/{entity_type}/{field_name}'
-  defaults:
-    _form: 'Drupal\content_translation\Form\TranslatableForm'
-  requirements:
-    _permission: 'administer content translation'
diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Form/TranslatableForm.php b/core/modules/content_translation/lib/Drupal/content_translation/Form/TranslatableForm.php
deleted file mode 100644
index 363cb1c..0000000
--- a/core/modules/content_translation/lib/Drupal/content_translation/Form/TranslatableForm.php
+++ /dev/null
@@ -1,156 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\content_translation\Form\TranslatableForm.
- */
-
-namespace Drupal\content_translation\Form;
-
-use Drupal\Core\Form\ConfirmFormBase;
-use Drupal\field\Entity\Field;
-use Drupal\field\Field as FieldInfo;
-
-/**
- * Provides a confirm form for changing translatable status on translation
- * fields.
- */
-class TranslatableForm extends ConfirmFormBase {
-
-  /**
-   * The field info we are changing translatable status on.
-   *
-   * @var \Drupal\field\Entity\Field
-   */
-  protected $field;
-
-  /**
-   * The field name we are changing translatable
-   * status on.
-   *
-   * @var string.
-   */
-  protected $fieldName;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getFormId() {
-    return 'content_translation_translatable_form';
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getQuestion() {
-    if ($this->field->isFieldTranslatable()) {
-      $question = t('Are you sure you want to disable translation for the %name field?', array('%name' => $this->fieldName));
-    }
-    else {
-      $question = t('Are you sure you want to enable translation for the %name field?', array('%name' => $this->fieldName));
-    }
-    return $question;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDescription() {
-    $description = t('By submitting this form these changes will apply to the %name field everywhere it is used.',
-      array('%name' => $this->fieldName)
-    );
-    $description .= $this->field->isFieldTranslatable() ? "<br>" . t("<strong>All the existing translations of this field will be deleted.</strong><br>This action cannot be undone.") : '';
-    return $description;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getCancelRoute() {
-    return array(
-      'route_name' => '<front>',
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   * @param string $entity_type
-   *   The entity type.
-   * @param string $field_name
-   *   The field name.
-   */
-  public function buildForm(array $form, array &$form_state, $entity_type = NULL, $field_name = NULL) {
-    $this->fieldName = $field_name;
-    $this->fieldInfo = FieldInfo::fieldInfo()->getField($entity_type, $field_name);
-
-    return parent::buildForm($form, $form_state);
-  }
-
-  /**
-   * Form submission handler.
-   *
-   * This submit handler maintains consistency between the translatability of an
-   * entity and the language under which the field data is stored. When a field
-   * is marked as translatable, all the data in
-   * $entity->{field_name}[Language::LANGCODE_NOT_SPECIFIED] is moved to
-   * $entity->{field_name}[$entity_language]. When a field is marked as
-   * untranslatable the opposite process occurs. Note that marking a field as
-   * untranslatable will cause all of its translations to be permanently
-   * removed, with the exception of the one corresponding to the entity
-   * language.
-   *
-   * @param array $form
-   *   An associative array containing the structure of the form.
-   * @param array $form_state
-   *   An associative array containing the current state of the form.
-   */
-  public function submitForm(array &$form, array &$form_state) {
-    // This is the current state that we want to reverse.
-    $translatable = $form_state['values']['translatable'];
-    if ($this->field->translatable !== $translatable) {
-      // Field translatability has changed since form creation, abort.
-      $t_args = array('%field_name');
-      $msg = $translatable ?
-        t('The field %field_name is already translatable. No change was performed.', $t_args):
-        t('The field %field_name is already untranslatable. No change was performed.', $t_args);
-      drupal_set_message($msg, 'warning');
-      return;
-    }
-
-    // If a field is untranslatable, it can have no data except under
-    // Language::LANGCODE_NOT_SPECIFIED. Thus we need a field to be translatable
-    // before we convert data to the entity language. Conversely we need to
-    // switch data back to Language::LANGCODE_NOT_SPECIFIED before making a
-    // field untranslatable lest we lose information.
-    $operations = array(
-      array(
-        'content_translation_translatable_batch', array(
-          !$translatable,
-          $this->fieldName,
-        ),
-      ),
-      array(
-        'content_translation_translatable_switch', array(
-          !$translatable,
-          $this->field['entity_type'],
-          $this->fieldName,
-        ),
-      ),
-    );
-    $operations = $translatable ? $operations : array_reverse($operations);
-
-    $t_args = array('%field' => $this->fieldName);
-    $title = !$translatable ? t('Enabling translation for the %field field', $t_args) : t('Disabling translation for the %field field', $t_args);
-
-    $batch = array(
-      'title' => $title,
-      'operations' => $operations,
-      'finished' => 'content_translation_translatable_batch_done',
-      'file' => drupal_get_path('module', 'content_translation') . '/content_translation.admin.inc',
-    );
-
-    batch_set($batch);
-
-  }
-
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
index bc0e195..eabcdeb 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
@@ -7,10 +7,13 @@
 
 namespace Drupal\system\Tests\Entity;
 
+use Drupal\Component\Utility\MapArray;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\FieldableDatabaseStorageController;
 use Drupal\Core\Language\Language;
 use Drupal\Core\TypedData\TranslatableInterface;
 use Drupal\entity_test\Entity\EntityTestMulRev;
-use Drupal\Component\Utility\MapArray;
+use Drupal\field\Field as FieldService;
 
 /**
  * Tests entity translation.
@@ -19,6 +22,20 @@ class EntityTranslationTest extends EntityUnitTestBase {
 
   protected $langcodes;
 
+  /**
+   * The test field name.
+   *
+   * @var string
+   */
+  protected $field_name;
+
+  /**
+   * The untranslatable test field name.
+   *
+   * @var string
+   */
+  protected $untranslatable_field_name;
+
   public static $modules = array('language', 'entity_test');
 
   public static function getInfo() {
@@ -54,7 +71,10 @@ function setUp() {
     // Create a translatable test field.
     $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
 
-    // Create instance in all entity variations.
+    // Create an untranslatable test field.
+    $this->untranslatable_field_name = drupal_strtolower($this->randomName() . '_field_name');
+
+    // Create field instances in all entity variations.
     foreach (entity_test_entity_types() as $entity_type) {
       entity_create('field_entity', array(
         'name' => $this->field_name,
@@ -69,6 +89,19 @@ function setUp() {
         'bundle' => $entity_type,
       ))->save();
       $this->instance[$entity_type] = field_read_instance($entity_type, $this->field_name, $entity_type);
+
+      entity_create('field_entity', array(
+        'name' => $this->untranslatable_field_name,
+        'entity_type' => $entity_type,
+        'type' => 'text',
+        'cardinality' => 4,
+        'translatable' => FALSE,
+      ))->save();
+      entity_create('field_instance', array(
+        'field_name' => $this->untranslatable_field_name,
+        'entity_type' => $entity_type,
+        'bundle' => $entity_type,
+      ))->save();
     }
 
     // Create the default languages.
@@ -120,7 +153,7 @@ protected function _testEntityLanguageMethods($entity_type) {
     // Get the value.
     $field = $entity->getTranslation(Language::LANGCODE_DEFAULT)->get($this->field_name);
     $this->assertEqual($field->value, 'default value', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($field->getLangcode(), Language::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
 
     // Set the value in a certain language. As the entity is not
     // language-specific it should use the default language and so ignore the
@@ -133,11 +166,12 @@ protected function _testEntityLanguageMethods($entity_type) {
     // language-specific entity.
     $field = $entity->getTranslation($this->langcodes[1])->get($this->field_name);
     $this->assertEqual($field->value, 'default value2', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($field->getLangcode(), Language::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
 
     // Now, make the entity language-specific by assigning a language and test
     // translating it.
-    $entity->langcode->value = $this->langcodes[0];
+    $default_langcode = $this->langcodes[0];
+    $entity->langcode->value = $default_langcode;
     $entity->{$this->field_name} = array();
     $this->assertEqual($entity->language(), language_load($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)));
@@ -147,7 +181,7 @@ protected function _testEntityLanguageMethods($entity_type) {
     // Get the value.
     $field = $entity->get($this->field_name);
     $this->assertEqual($field->value, 'default value', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($field->getLangcode(), $default_langcode, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
 
     // Set a translation.
     $entity->getTranslation($this->langcodes[1])->set($this->field_name, array(0 => array('value' => 'translation 1')));
@@ -158,7 +192,7 @@ protected function _testEntityLanguageMethods($entity_type) {
     // Make sure the untranslated value stays.
     $field = $entity->get($this->field_name);
     $this->assertEqual($field->value, 'default value', 'Untranslated value stays.');
-    $this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, 'Untranslated value has the expected langcode.');
+    $this->assertEqual($field->getLangcode(), $default_langcode, 'Untranslated value has the expected langcode.');
 
     $translations[$this->langcodes[1]] = language_load($this->langcodes[1]);
     $this->assertEqual($entity->getTranslationLanguages(FALSE), $translations, 'Translations retrieved.');
@@ -190,7 +224,7 @@ protected function _testEntityLanguageMethods($entity_type) {
     // Get the value.
     $field = $entity->get($field_name);
     $this->assertEqual($field->value, 'default value2', format_string('%entity_type: Untranslated value set into a translation in non-strict mode.', array('%entity_type' => $entity_type)));
-    $this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($field->getLangcode(), $default_langcode, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
   }
 
   /**
@@ -219,20 +253,19 @@ protected function _testMultilingualProperties($entity_type) {
     $entity = entity_create($entity_type, array('name' => $name, 'user_id' => $uid));
     $entity->save();
     $entity = entity_load($entity_type, $entity->id());
-    $this->assertEqual($entity->language()->id, Language::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Entity created as language neutral.', array('%entity_type' => $entity_type)));
+    $default_langcode = $entity->language()->id;
+    $this->assertEqual($default_langcode, Language::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Entity created as language neutral.', array('%entity_type' => $entity_type)));
     $field = $entity->getTranslation(Language::LANGCODE_DEFAULT)->get('name');
     $this->assertEqual($name, $field->value, format_string('%entity_type: The entity name has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(Language::LANGCODE_DEFAULT, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
     $this->assertEqual($uid, $entity->getTranslation(Language::LANGCODE_DEFAULT)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
-    // As fields, translatable properties should ignore the given langcode and
-    // use neutral language if the entity is not translatable.
     $field = $entity->getTranslation($langcode)->get('name');
     $this->assertEqual($name, $field->value, format_string('%entity_type: The entity name defaults to neutral language.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(Language::LANGCODE_DEFAULT, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
     $this->assertEqual($uid, $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to neutral language.', array('%entity_type' => $entity_type)));
     $field = $entity->get('name');
     $this->assertEqual($name, $field->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(Language::LANGCODE_DEFAULT, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
     $this->assertEqual($uid, $entity->get('user_id')->target_id, format_string('%entity_type: The entity author can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
 
     // Create a language-aware entity and check that properties are stored
@@ -240,20 +273,21 @@ protected function _testMultilingualProperties($entity_type) {
     $entity = entity_create($entity_type, array('name' => $name, 'user_id' => $uid, 'langcode' => $langcode));
     $entity->save();
     $entity = entity_load($entity_type, $entity->id());
-    $this->assertEqual($entity->language()->id, $langcode, format_string('%entity_type: Entity created as language specific.', array('%entity_type' => $entity_type)));
+    $default_langcode = $entity->language()->id;
+    $this->assertEqual($default_langcode, $langcode, format_string('%entity_type: Entity created as language specific.', array('%entity_type' => $entity_type)));
     $field = $entity->getTranslation($langcode)->get('name');
     $this->assertEqual($name, $field->value, format_string('%entity_type: The entity name has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
     $this->assertEqual($uid, $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
     // Translatable properties on a translatable entity should use default
     // language if Language::LANGCODE_NOT_SPECIFIED is passed.
     $field = $entity->getTranslation(Language::LANGCODE_NOT_SPECIFIED)->get('name');
     $this->assertEqual($name, $field->value, format_string('%entity_type: The entity name defaults to the default language.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
     $this->assertEqual($uid, $entity->getTranslation(Language::LANGCODE_NOT_SPECIFIED)->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to the default language.', array('%entity_type' => $entity_type)));
     $field = $entity->get('name');
     $this->assertEqual($name, $field->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
-    $this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
     $this->assertEqual($uid, $entity->get('user_id')->target_id, format_string('%entity_type: The entity author can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
 
     // Create property translations.
@@ -285,8 +319,7 @@ protected function _testMultilingualProperties($entity_type) {
       );
       $field = $entity->getTranslation($langcode)->get('name');
       $this->assertEqual($properties[$langcode]['name'][0], $field->value, format_string('%entity_type: The entity name has been correctly stored for language %langcode.', $args));
-      // Fields for the default entity langcode are seen as language neutral.
-      $field_langcode = ($langcode == $entity->language()->id) ? Language::LANGCODE_NOT_SPECIFIED : $langcode;
+      $field_langcode = ($langcode == $entity->language()->id) ? $default_langcode : $langcode;
       $this->assertEqual($field_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expected langcode  %langcode.', $args));
       $this->assertEqual($properties[$langcode]['user_id'][0], $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored for language %langcode.', $args));
     }
@@ -482,6 +515,9 @@ function testEntityTranslationAPI() {
     $cloned = clone $entity;
     $translation = $cloned->getTranslation($langcode);
     $this->assertNotIdentical($entity, $translation->getUntranslated(), 'A cloned entity object has no reference to the original one.');
+    $entity->removeTranslation($langcode);
+    $this->assertFalse($entity->hasTranslation($langcode));
+    $this->assertTrue($cloned->hasTranslation($langcode));
 
     // Check that per-language defaults are properly populated.
     $entity = $this->reloadEntity($entity);
@@ -596,4 +632,152 @@ function testFieldDefinitions() {
     }
   }
 
+  /**
+   * Tests that changing entity language does not break field language.
+   */
+  public function testLanguageChange() {
+    $entity_type = 'entity_test_mul';
+    $controller = $this->entityManager->getStorageController($entity_type);
+    $langcode = $this->langcodes[0];
+
+    // check that field languages match entity language regardless of field
+    // translatability.
+    $values = array(
+      'langcode' => $langcode,
+      $this->field_name => $this->randomName(),
+      $this->untranslatable_field_name => $this->randomName(),
+    );
+    $entity = $controller->create($values);
+    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.');
+    }
+
+    // Check that field languages keep matching entity language even after
+    // changing it.
+    $langcode = $this->langcodes[1];
+    $entity->langcode->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.');
+    }
+
+    // Check that entity translation does not affect the language of original
+    // field values and untranslatable ones.
+    $langcode = $this->langcodes[0];
+    $entity->addTranslation($this->langcodes[2], array($this->field_name => $this->randomName()));
+    $entity->langcode->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.');
+    }
+  }
+
+  /**
+   * Tests field SQL storage.
+   */
+  public function testFieldSqlStorage() {
+    $entity_type = 'entity_test_mul';
+
+    $controller = $this->entityManager->getStorageController($entity_type);
+    $values = array(
+      $this->field_name => $this->randomName(),
+      $this->untranslatable_field_name => $this->randomName(),
+    );
+    $entity = $controller->create($values);
+    $entity->save();
+
+    // Tests that when changing language field language codes are still correct.
+    $langcode = $this->langcodes[0];
+    $entity->langcode->value = $langcode;
+    $entity->save();
+    $this->assertFieldStorageLangcode($entity, 'Field language successfully changed from language neutral.');
+    $langcode = $this->langcodes[1];
+    $entity->langcode->value = $langcode;
+    $entity->save();
+    $this->assertFieldStorageLangcode($entity, 'Field language successfully changed.');
+    $langcode = Language::LANGCODE_NOT_SPECIFIED;
+    $entity->langcode->value = $langcode;
+    $entity->save();
+    $this->assertFieldStorageLangcode($entity, 'Field language successfully changed to language neutral.');
+
+    // Test that after switching field translatability things keep working as
+    // before.
+    $this->toggleFieldTranslatability($entity_type);
+    $entity = $this->reloadEntity($entity);
+    foreach (array($this->field_name, $this->untranslatable_field_name) as $field_name) {
+      $this->assertEqual($entity->get($field_name)->value, $values[$field_name], 'Field language works as expected after switching translatability.');
+    }
+
+    // Test that after disabling field translatability translated values are not
+    // loaded.
+    $this->toggleFieldTranslatability($entity_type);
+    $entity = $this->reloadEntity($entity);
+    $entity->langcode->value = $this->langcodes[0];
+    $translation = $entity->addTranslation($this->langcodes[1]);
+    $translated_value = $this->randomName();
+    $translation->get($this->field_name)->value = $translated_value;
+    $translation->save();
+    $this->toggleFieldTranslatability($entity_type);
+    $entity = $this->reloadEntity($entity);
+    $this->assertEqual($entity->getTranslation($this->langcodes[1])->get($this->field_name)->value, $values[$this->field_name], 'Existing field translations are not loaded for untranslatable fields.');
+  }
+
+  /**
+   * Checks whether field languages are correctly stored for the given entity.
+   *
+   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
+   *   The entity fields are attached to.
+   * @param string $message
+   *   (optional) A message to display with the assertion.
+   */
+  protected function assertFieldStorageLangcode(ContentEntityInterface $entity, $message = '') {
+    $status = TRUE;
+    $entity_type = $entity->entityType();
+    $id = $entity->id();
+    $langcode = $entity->getUntranslated()->language()->id;
+    $fields = array($this->field_name, $this->untranslatable_field_name);
+
+    foreach ($fields as $field_name) {
+      $field = FieldService::fieldInfo()->getField($entity_type, $field_name);
+      $tables = array(
+        FieldableDatabaseStorageController::_fieldTableName($field),
+        FieldableDatabaseStorageController::_fieldRevisionTableName($field),
+      );
+
+      foreach ($tables as $table) {
+        $record = \Drupal::database()
+          ->select($table, 'f')
+          ->fields('f')
+          ->condition('f.entity_id', $id)
+          ->condition('f.revision_id', $id)
+          ->execute()
+          ->fetchObject();
+
+        if ($record->langcode != $langcode) {
+          $status = FALSE;
+          break;
+        }
+      }
+    }
+
+    return $this->assertTrue($status, $message);
+  }
+
+  /**
+   * Toggles field translatability.
+   *
+   * @param string $entity_type
+   *   The type of the entity fields are attached to.
+   */
+  protected function toggleFieldTranslatability($entity_type) {
+    $fields = array($this->field_name, $this->untranslatable_field_name);
+    foreach ($fields as $field_name) {
+      $field = FieldService::fieldInfo()->getField($entity_type, $field_name);
+      $translatable = !$field->isFieldTranslatable();
+      $field->set('translatable', $translatable);
+      $field->save();
+      FieldService::fieldInfo()->flush();
+      $field = FieldService::fieldInfo()->getField($entity_type, $field_name);
+      $this->assertEqual($field->isFieldTranslatable(), $translatable, 'Field translatability changed.');
+    }
+    \Drupal::cache('field')->deleteAll();
+  }
 }
diff --git a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
index 0b47055..49d9f78 100644
--- a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
@@ -128,7 +128,7 @@ function testProcessedCache() {
     $entity = entity_load($entity_type, $entity->id());
     $cache = cache('field')->get("field:$entity_type:" . $entity->id());
     $this->assertEqual($cache->data, array(
-      Language::LANGCODE_DEFAULT => array(
+      Language::LANGCODE_NOT_SPECIFIED => array(
         'summary_field' => array(
           0 => array(
             'value' => $value,
@@ -144,7 +144,7 @@ function testProcessedCache() {
     // Inject fake processed values into the cache to make sure that these are
     // used as-is and not re-calculated when the entity is loaded.
     $data = array(
-      Language::LANGCODE_DEFAULT => array(
+      Language::LANGCODE_NOT_SPECIFIED => array(
         'summary_field' => array(
           0 => array(
             'value' => $value,
