diff --git a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
index 5497efb..9af998b 100644
--- a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
+++ b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
@@ -285,7 +285,13 @@ protected function mapFromStorageRecords(array $records, $load_revision = FALSE)
         // Skip the item delta and item value levels but let the field assign
         // the value as suiting. This avoids unnecessary array hierarchies and
         // saves memory here.
-        $entities[$id][$name][Language::LANGCODE_DEFAULT] = $value;
+        if ($field = strstr($name, '__', TRUE)) {
+          $property_name = substr($name, strpos($name, '__') + 2);
+          $entities[$id][$field][Language::LANGCODE_DEFAULT][$property_name] = $value;
+        }
+        else {
+          $entities[$id][$name][Language::LANGCODE_DEFAULT] = $value;
+        }
       }
       // If we have no multilingual values we can instantiate entity objecs
       // right now, otherwise we need to collect all the field values first.
@@ -353,6 +359,14 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) {
           if (isset($data_fields[$name])) {
             $entities[$id][$name][$langcode] = $values[$name];
           }
+          else {
+            foreach ($data_fields as $data_field) {
+              if (($field = strstr($data_field, '__', TRUE)) && $field === $name) {
+                $property_name = substr($data_field, strpos($data_field, '__') + 2);
+                $entities[$id][$name][$langcode][$property_name] = $values[$data_field];
+              }
+            }
+          }
         }
       }
 
@@ -744,17 +758,37 @@ protected function savePropertyData(EntityInterface $entity, $table_key = 'data_
    */
   protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'base_table') {
     $record = new \stdClass();
+    $values = array();
     $definitions = $entity->getPropertyDefinitions();
     $schema = drupal_get_schema($this->entityInfo[$table_key]);
     $is_new = $entity->isNew();
 
+    $multi_column_fields = array();
     foreach (drupal_schema_fields_sql($this->entityInfo[$table_key]) as $name) {
-      $info = $schema['fields'][$name];
-      $value = isset($definitions[$name]) && isset($entity->$name->value) ? $entity->$name->value : NULL;
+      // Check for fields which store data in multiple columns and process them
+      // separately.
+      if ($field = strstr($name, '__', TRUE)) {
+        $multi_column_fields[$field] = TRUE;
+        continue;
+      }
+      $values[$name] = isset($definitions[$name]) && isset($entity->$name->value) ? $entity->$name->value : NULL;
+    }
+
+    foreach (array_keys($multi_column_fields) as $field_name) {
+      $field_items = $entity->get($field_name);
+      $field_value = $field_items->getValue();
+      foreach ($field_items->getFieldDefinition()->getFieldPropertyNames() as $property_name) {
+        if (isset($schema['fields'][$field_name . '__' . $property_name])) {
+          $values[$field_name . '__' . $property_name] = isset($field_value[0][$property_name]) ? $field_value[0][$property_name] : NULL;
+        }
+      }
+    }
+
+    foreach ($values as $field_name => $value) {
       // If we are creating a new entity, we must not populate the record with
       // NULL values otherwise defaults would not be applied.
       if (isset($value) || !$is_new) {
-        $record->$name = drupal_schema_get_field_value($info, $value);
+        $record->$field_name = drupal_schema_get_field_value($schema['fields'][$field_name], $value);
       }
     }
 
diff --git a/core/lib/Drupal/Core/Field/FieldDefinition.php b/core/lib/Drupal/Core/Field/FieldDefinition.php
index 8e57f7c..eecb75b 100644
--- a/core/lib/Drupal/Core/Field/FieldDefinition.php
+++ b/core/lib/Drupal/Core/Field/FieldDefinition.php
@@ -107,7 +107,7 @@ public function getFieldSetting($setting_name) {
    * {@inheritdoc}
    */
   public function getFieldPropertyNames() {
-    return array_keys(\Drupal::typedData()->create($this->definition['type'])->getPropertyDefinitions());
+    return array_keys(\Drupal::typedData()->create($this->definition)->getPropertyDefinitions());
   }
 
   /**
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php
index a638245..879c02b 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php
@@ -22,7 +22,7 @@ class EntityReferenceItemTest extends FieldUnitTestBase {
    *
    * @var array
    */
-  public static $modules = array('entity_reference', 'taxonomy', 'options');
+  public static $modules = array('entity_reference', 'taxonomy', 'options', 'text', 'filter');
 
   /**
    * The taxonomy vocabulary to test with.
diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php
index 8e7bbb4..caa03e1 100644
--- a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php
+++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php
@@ -387,7 +387,7 @@ function createForum($type, $parent = 0) {
     );
 
     // Verify forum.
-    $term = db_query("SELECT * FROM {taxonomy_term_data} t WHERE t.vid = :vid AND t.name = :name AND t.description = :desc", array(':vid' => \Drupal::config('forum.settings')->get('vocabulary'), ':name' => $name, ':desc' => $description))->fetchAssoc();
+    $term = db_query("SELECT * FROM {taxonomy_term_data} t WHERE t.vid = :vid AND t.name = :name AND t.description__value = :desc", array(':vid' => \Drupal::config('forum.settings')->get('vocabulary'), ':name' => $name, ':desc' => $description))->fetchAssoc();
     $this->assertTrue(!empty($term), 'The ' . $type . ' exists in the database');
 
     // Verify forum hierarchy.
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php
index a091d1a..320bec0 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php
@@ -230,13 +230,7 @@ public static function baseFieldDefinitions($entity_type) {
     $properties['description'] = array(
       'label' => t('Description'),
       'description' => t('A description of the term'),
-      'type' => 'string_field',
-    );
-    // @todo Combine with description.
-    $properties['format'] = array(
-      'label' => t('Description format'),
-      'description' => t('The filter format ID of the description.'),
-      'type' => 'string_field',
+      'type' => 'field_item:text_long',
     );
     $properties['weight'] = array(
       'label' => t('Weight'),
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
index e7fb41e..bbed7fd 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
@@ -74,7 +74,7 @@ public function form(array $form, array &$form_state) {
       '#type' => 'text_format',
       '#title' => $this->t('Description'),
       '#default_value' => $term->description->value,
-      '#format' => $term->format->value,
+      '#format' => $term->description->format,
       '#weight' => 0,
     );
     $language_configuration = $this->moduleHandler->moduleExists('language') ? language_get_default_configuration('taxonomy_term', $vocabulary->id()) : FALSE;
@@ -178,7 +178,7 @@ public function buildEntity(array $form, array &$form_state) {
     // \Drupal\Core\Entity\Entity::save() method.
     $description = $form_state['values']['description'];
     $term->description->value = $description['value'];
-    $term->format->value = $description['format'];
+    $term->description->format = $description['format'];
 
     // Assign parents with proper delta values starting from 0.
     $term->parent = array_keys($form_state['values']['parent']);
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermViewBuilder.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermViewBuilder.php
index b33dbfd..2497dd6 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermViewBuilder.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermViewBuilder.php
@@ -27,7 +27,7 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang
       $display = $displays[$entity->bundle()];
       if (!empty($entity->description->value) && $display->getComponent('description')) {
         $entity->content['description'] = array(
-          '#markup' => check_markup($entity->description->value, $entity->format->value, '', TRUE),
+          '#markup' => check_markup($entity->description->value, $entity->description->format, '', TRUE),
           '#prefix' => '<div class="taxonomy-term-description">',
           '#suffix' => '</div>',
         );
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTestBase.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTestBase.php
index 4ae4823..9fd5a34 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTestBase.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTestBase.php
@@ -55,9 +55,11 @@ function createTerm($vocabulary) {
     $format = array_pop($filter_formats);
     $term = entity_create('taxonomy_term', array(
       'name' => $this->randomName(),
-      'description' => $this->randomName(),
-      // Use the first available text format.
-      'format' => $format->format,
+      'description' => array(
+        'value' => $this->randomName(),
+        // Use the first available text format.
+        'format' => $format->format,
+      ),
       'vid' => $vocabulary->id(),
       'langcode' => Language::LANGCODE_NOT_SPECIFIED,
     ));
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
index dcae350..4a850be 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php
@@ -346,7 +346,7 @@ function testTermInterface() {
     // Did this page request display a 'term-listing-heading'?
     $this->assertPattern('|class="taxonomy-term-description"|', 'Term page displayed the term description element.');
     // Check that it does NOT show a description when description is blank.
-    $term->description = '';
+    $term->description->value = NULL;
     $term->save();
     $this->drupalGet('taxonomy/term/' . $term->id());
     $this->assertNoPattern('|class="taxonomy-term-description"|', 'Term page did not display the term description when description was blank.');
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php
index be4ed53..c32e5c4 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php
@@ -88,7 +88,7 @@ function testTaxonomyTokenReplacement() {
     $tests = array();
     $tests['[term:tid]'] = $term1->id();
     $tests['[term:name]'] = check_plain($term1->name->value);
-    $tests['[term:description]'] = check_markup($term1->description->value, $term1->format->value);
+    $tests['[term:description]'] = check_markup($term1->description->value, $term1->description->format);
     $tests['[term:url]'] = url('taxonomy/term/' . $term1->id(), array('absolute' => TRUE));
     $tests['[term:node-count]'] = 0;
     $tests['[term:parent:name]'] = '[term:parent:name]';
@@ -103,7 +103,7 @@ function testTaxonomyTokenReplacement() {
     $tests = array();
     $tests['[term:tid]'] = $term2->id();
     $tests['[term:name]'] = check_plain($term2->name->value);
-    $tests['[term:description]'] = check_markup($term2->description->value, $term2->format->value);
+    $tests['[term:description]'] = check_markup($term2->description->value, $term2->description->format);
     $tests['[term:url]'] = url('taxonomy/term/' . $term2->id(), array('absolute' => TRUE));
     $tests['[term:node-count]'] = 1;
     $tests['[term:parent:name]'] = check_plain($term1->name->value);
diff --git a/core/modules/taxonomy/taxonomy.info.yml b/core/modules/taxonomy/taxonomy.info.yml
index 88de323..2fe12f0 100644
--- a/core/modules/taxonomy/taxonomy.info.yml
+++ b/core/modules/taxonomy/taxonomy.info.yml
@@ -6,4 +6,5 @@ version: VERSION
 core: 8.x
 dependencies:
   - options
+  - text
 configure: taxonomy.vocabulary_list
diff --git a/core/modules/taxonomy/taxonomy.install b/core/modules/taxonomy/taxonomy.install
index 086c030..f7abc20 100644
--- a/core/modules/taxonomy/taxonomy.install
+++ b/core/modules/taxonomy/taxonomy.install
@@ -48,13 +48,13 @@ function taxonomy_schema() {
         'default' => '',
         'description' => 'The term name.',
       ),
-      'description' => array(
+      'description__value' => array(
         'type' => 'text',
         'not null' => FALSE,
         'size' => 'big',
         'description' => 'A description of the term.',
       ),
-      'format' => array(
+      'description__format' => array(
         'type' => 'varchar',
         'length' => 255,
         'not null' => FALSE,
@@ -428,3 +428,24 @@ function taxonomy_update_8009() {
     }
   }
 }
+
+/**
+ * Rename the 'description' and 'format' columns for taxonomy terms.
+ */
+function taxonomy_update_8010() {
+  $description = array(
+    'type' => 'text',
+    'not null' => FALSE,
+    'size' => 'big',
+    'description' => 'A description of the term.',
+  );
+  db_change_field('taxonomy_term_data', 'description', 'description__value', $description);
+
+  $format = array(
+    'type' => 'varchar',
+    'length' => 255,
+    'not null' => FALSE,
+    'description' => 'The filter format ID of the description.',
+  );
+  db_change_field('taxonomy_term_data', 'format', 'description__format', $format);
+}
diff --git a/core/modules/taxonomy/taxonomy.pages.inc b/core/modules/taxonomy/taxonomy.pages.inc
index 96f84aa..310d696 100644
--- a/core/modules/taxonomy/taxonomy.pages.inc
+++ b/core/modules/taxonomy/taxonomy.pages.inc
@@ -76,7 +76,7 @@ function taxonomy_term_feed(Term $term) {
   $channel['title'] = \Drupal::config('system.site')->get('name') . ' - ' . $term->label();
   // Only display the description if we have a single term, to avoid clutter and confusion.
   // HTML will be removed from feed description.
-  $channel['description'] = check_markup($term->description->value, $term->format->value, '', TRUE);
+  $channel['description'] = check_markup($term->description->value, $term->description->format, '', TRUE);
   $nids = taxonomy_select_nodes($term->id(), FALSE, \Drupal::config('system.rss')->get('items.limit'));
 
   return node_feed($nids, $channel);
diff --git a/core/modules/taxonomy/taxonomy.tokens.inc b/core/modules/taxonomy/taxonomy.tokens.inc
index ad0a1d4..b0286c6 100644
--- a/core/modules/taxonomy/taxonomy.tokens.inc
+++ b/core/modules/taxonomy/taxonomy.tokens.inc
@@ -108,7 +108,7 @@ function taxonomy_tokens($type, $tokens, array $data = array(), array $options =
           break;
 
         case 'description':
-          $replacements[$original] = $sanitize ? check_markup($term->description->value, $term->format->value, '', TRUE) : $term->description->value;
+          $replacements[$original] = $sanitize ? check_markup($term->description->value, $term->description->format, '', TRUE) : $term->description->value;
           break;
 
         case 'url':
diff --git a/core/modules/taxonomy/taxonomy.views.inc b/core/modules/taxonomy/taxonomy.views.inc
index 3404b3a..6e06490 100644
--- a/core/modules/taxonomy/taxonomy.views.inc
+++ b/core/modules/taxonomy/taxonomy.views.inc
@@ -128,12 +128,12 @@ function taxonomy_views_data() {
   );
 
   // Term description
-  $data['taxonomy_term_data']['description'] = array(
+  $data['taxonomy_term_data']['description__value'] = array(
     'title' => t('Term description'),
     'help' => t('The description associated with a taxonomy term.'),
     'field' => array(
       'id' => 'markup',
-      'format' => array('field' => 'format'),
+      'format' => array('field' => 'description__format'),
       'click sortable' => FALSE,
     ),
     'filter' => array(
diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php
index 4486157..e126f5d 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/RowEntityTest.php
@@ -21,7 +21,7 @@ class RowEntityTest extends ViewUnitTestBase {
    *
    * @var array
    */
-  public static $modules = array('taxonomy', 'field', 'entity', 'system');
+  public static $modules = array('taxonomy', 'text', 'field', 'entity', 'system');
 
   /**
    * Views used by this test.
