diff --git a/core/lib/Drupal/Core/Field/FieldItemBase.php b/core/lib/Drupal/Core/Field/FieldItemBase.php
index 33ec95c..39b9412 100644
--- a/core/lib/Drupal/Core/Field/FieldItemBase.php
+++ b/core/lib/Drupal/Core/Field/FieldItemBase.php
@@ -243,7 +243,7 @@ public function deleteRevision() { }
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     return array();
   }
 
diff --git a/core/lib/Drupal/Core/Field/FieldItemInterface.php b/core/lib/Drupal/Core/Field/FieldItemInterface.php
index d10790d..22da92d 100644
--- a/core/lib/Drupal/Core/Field/FieldItemInterface.php
+++ b/core/lib/Drupal/Core/Field/FieldItemInterface.php
@@ -250,7 +250,7 @@ public static function defaultInstanceSettings();
    * @return
    *   The form definition for the field settings.
    */
-  public function settingsForm(array $form, array &$form_state, $has_data);
+  public function settingsForm(array &$form, array &$form_state, $has_data);
 
   /**
    * Returns a form for the instance-level settings.
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php
index 30d33c5..10d03b3 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php
@@ -63,7 +63,7 @@ public static function schema(FieldStorageDefinitionInterface $field_definition)
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     $element = array();
     $settings = $this->getSettings();
 
diff --git a/core/modules/comment/comment.install b/core/modules/comment/comment.install
index 40fb1a0..e35bead 100644
--- a/core/modules/comment/comment.install
+++ b/core/modules/comment/comment.install
@@ -67,12 +67,18 @@ function comment_schema() {
         'length' => 255,
         'description' => 'The entity_type of the entity to which this comment is a reply.',
       ),
-      'field_id' => array(
+      'field_name' => array(
         'type' => 'varchar',
         'not null' => TRUE,
-        'default' => 'node.comment',
+        'default' => 'comment',
         'length' => 255,
-        'description' => 'The field_id of the field that was used to add this comment.',
+        'description' => 'The field_name of the field that was used to add this comment.',
+      ),
+      'comment_type' => array(
+        'type' => 'varchar',
+        'not null' => TRUE,
+        'length' => 32,
+        'description' => 'The comment_type of this comment.',
       ),
       'uid' => array(
         'type' => 'int',
@@ -151,8 +157,8 @@ function comment_schema() {
       'comment_status_pid' => array('pid', 'status'),
       'comment_num_new' => array(
         'entity_id',
-        array('entity_type', 32),
-        array('field_id', 32),
+        'entity_type',
+        'comment_type',
         'status',
         'created',
         'cid',
@@ -161,8 +167,8 @@ function comment_schema() {
       'comment_uid' => array('uid'),
       'comment_entity_langcode' => array(
         'entity_id',
-        array('entity_type', 32),
-        array('field_id', 32),
+        'entity_type',
+        'comment_type',
         'langcode',
       ),
       'comment_created' => array('created'),
@@ -196,12 +202,12 @@ function comment_schema() {
         'length' => 255,
         'description' => 'The entity_type of the entity to which this comment is a reply.',
       ),
-      'field_id' => array(
+      'field_name' => array(
         'type' => 'varchar',
         'not null' => TRUE,
-        'default' => 'node__comment',
+        'default' => 'comment',
         'length' => 255,
-        'description' => 'The field_id of the field that was used to add this comment.',
+        'description' => 'The field_name of the field that was used to add this comment.',
       ),
       'cid' => array(
         'type' => 'int',
@@ -236,7 +242,7 @@ function comment_schema() {
         'description' => 'The total number of comments on this entity.',
       ),
     ),
-    'primary key' => array('entity_id', array('entity_type', 32), array('field_id', 32)),
+    'primary key' => array('entity_id', 'entity_type', array('field_name', 32)),
     'indexes' => array(
       'last_comment_timestamp' => array('last_comment_timestamp'),
       'comment_count' => array('comment_count'),
diff --git a/core/modules/comment/comment.local_actions.yml b/core/modules/comment/comment.local_actions.yml
new file mode 100644
index 0000000..0f65c76
--- /dev/null
+++ b/core/modules/comment/comment.local_actions.yml
@@ -0,0 +1,5 @@
+comment_type_add:
+  route_name: comment.type_add
+  title: 'Add comment type'
+  appears_on:
+    - comment.type_list
diff --git a/core/modules/comment/comment.local_tasks.yml b/core/modules/comment/comment.local_tasks.yml
index 091321b..5a9a4f9 100644
--- a/core/modules/comment/comment.local_tasks.yml
+++ b/core/modules/comment/comment.local_tasks.yml
@@ -29,3 +29,9 @@ comment.admin_approval:
   class: Drupal\comment\Plugin\Menu\LocalTask\UnapprovedComments
   parent_id: comment.admin
   weight: 1
+
+# Default tab for comment type editing.
+comment.type_edit:
+  title: 'Edit'
+  route_name: comment.type_edit
+  base_route: comment.type_edit
diff --git a/core/modules/comment/comment.menu_links.yml b/core/modules/comment/comment.menu_links.yml
index 7d715fe..8b582de 100644
--- a/core/modules/comment/comment.menu_links.yml
+++ b/core/modules/comment/comment.menu_links.yml
@@ -3,8 +3,8 @@ comment.admin:
   route_name: comment.admin
   parent: system.admin
   description: 'List and edit site comments and the comment approval queue.'
-comment.bundle_list:
-  title: 'Comment forms'
-  route_name: comment.bundle_list
+comment.type_list:
+  title: 'Comment types'
+  route_name: comment.type_list
   parent: system.admin_structure
   description: 'Manage fields and displays settings for comment forms.'
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index faaf6b6..61d94bf 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -19,6 +19,7 @@
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Render\Element;
 use Drupal\Core\Url;
+use Drupal\field\Entity\FieldConfig;
 use Drupal\field\FieldInstanceConfigInterface;
 use Drupal\field\FieldConfigInterface;
 use Drupal\file\FileInterface;
@@ -100,26 +101,10 @@ function comment_help($route_name, Request $request) {
  */
 function comment_entity_bundle_info() {
   $bundles = array();
-  $ids = \Drupal::entityQuery('field_config')
-    ->condition('type', 'comment')
-    ->execute();
-  $config_factory = \Drupal::configFactory();
-  foreach ($ids as $id) {
-    // @todo: We can not rely on the field map here, so we need to manually look
-    //   for a matching field instance to use for the label. Remove this in
-    //   https://drupal.org/node/2228763.
-    list($entity_type_id, $field_name) = explode('.', $id);
-    $instance_ids = $config_factory->listAll('field.instance.' . $entity_type_id . '.');
-    // Look for an instance for this field.
-    foreach ($instance_ids as $instance_id) {
-      $instance_field_name = substr($instance_id, strrpos($instance_id, '.') + 1);
-      if ($instance_field_name == $field_name) {
-        $config = \Drupal::config($instance_id);
-        $bundles['comment'][$entity_type_id . '__' . $field_name] = array(
-          'label' => $config->get('label'),
-        );
-      }
-    }
+  foreach (entity_load_multiple('comment_type') as $comment_type) {
+    $bundles['comment'][$comment_type->id] = array(
+      'label' => $comment_type->label,
+    );
   }
   return $bundles;
 }
@@ -142,23 +127,21 @@ function comment_uri(CommentInterface $comment) {
  */
 function comment_entity_extra_field_info() {
   $return = array();
-  foreach (\Drupal::service('comment.manager')->getAllFields() as $entity_type => $fields) {
-    foreach ($fields as $field_name => $field_info) {
-      $return['comment'][$entity_type . '__' . $field_name] = array(
-        'form' => array(
-          'author' => array(
-            'label' => t('Author'),
-            'description' => t('Author textfield'),
-            'weight' => -2,
-          ),
-          'subject' => array(
-            'label' => t('Subject'),
-            'description' => t('Subject textfield'),
-            'weight' => -1,
-          ),
+  foreach (entity_load_multiple('comment_type') as $comment_type) {
+    $return['comment'][$comment_type->id] = array(
+      'form' => array(
+        'author' => array(
+          'label' => t('Author'),
+          'description' => t('Author textfield'),
+          'weight' => -2,
         ),
-      );
-    }
+        'subject' => array(
+          'label' => t('Subject'),
+          'description' => t('Subject textfield'),
+          'weight' => -1,
+        ),
+      ),
+    );
   }
 
   return $return;
@@ -206,15 +189,6 @@ function comment_count_unpublished() {
 }
 
 /**
- * Implements hook_ENTITY_TYPE_insert() for 'field_instance_config'.
- */
-function comment_field_instance_config_insert(FieldInstanceConfigInterface $instance) {
-  if ($instance->getType() == 'comment' && !$instance->isSyncing()) {
-    \Drupal::service('comment.manager')->addBodyField($instance->entity_type, $instance->getName());
-  }
-}
-
-/**
  * Implements hook_ENTITY_TYPE_create() for 'field_instance_config'.
  */
 function comment_field_instance_config_create(FieldInstanceConfigInterface $instance) {
@@ -247,24 +221,14 @@ function comment_field_instance_config_update(FieldInstanceConfigInterface $inst
 }
 
 /**
- * Implements hook_ENTITY_TYPE_delete() for 'field_config'.
- */
-function comment_field_config_delete(FieldConfigInterface $field) {
-  if ($field->getType() == 'comment') {
-    // Delete all fields and displays attached to the comment bundle.
-    entity_invoke_bundle_hook('delete', 'comment', $field->entity_type . '__' . $field->getName());
-  }
-}
-
-/**
  * Implements hook_ENTITY_TYPE_delete() for 'field_instance_config'.
  */
 function comment_field_instance_config_delete(FieldInstanceConfigInterface $instance) {
   if ($instance->getType() == 'comment') {
     // Delete all comments that used by the entity bundle.
-    $comments = db_query("SELECT cid FROM {comment} WHERE entity_type = :entity_type AND field_id = :field_id", array(
+    $comments = db_query("SELECT cid FROM {comment} WHERE entity_type = :entity_type AND field_name = :field_name", array(
       ':entity_type' => $instance->getEntityTypeId(),
-      ':field_id' => $instance->getEntityTypeId() . '__' . $instance->getName(),
+      ':field_name' => $instance->getName(),
     ))->fetchCol();
     entity_delete_multiple('comment', $comments);
   }
@@ -278,6 +242,10 @@ function comment_permission() {
     'administer comments' => array(
       'title' => t('Administer comments and comment settings'),
     ),
+    'administer comment types' => array(
+      'title' => t('Administer comment types and settings'),
+      'restrict access' => TRUE,
+    ),
     'access comments' => array(
       'title' => t('View comments'),
     ),
@@ -332,7 +300,7 @@ function comment_new_page_count($num_comments, $new_replies, EntityInterface $en
       ->fields('comment', array('thread'))
       ->condition('entity_id', $entity->id())
       ->condition('entity_type', $entity->getEntityTypeId())
-      ->condition('field_id', $entity->getEntityTypeId() . '__' . $field_name)
+      ->condition('field_name', $field_name)
       ->condition('status', CommentInterface::PUBLISHED)
       ->orderBy('created', 'DESC')
       ->orderBy('cid', 'DESC')
@@ -354,11 +322,11 @@ function comment_new_page_count($num_comments, $new_replies, EntityInterface $en
     // Find the number of the first comment of the first unread thread.
     $count = db_query('SELECT COUNT(*) FROM {comment} WHERE entity_id = :entity_id
                       AND entity_type = :entity_type
-                      AND field_id = :field_id
+                      AND field_name = :field_name
                       AND status = :status AND SUBSTRING(thread, 1, (LENGTH(thread) - 1)) < :thread', array(
       ':status' => CommentInterface::PUBLISHED,
       ':entity_id' => $entity->id(),
-      ':field_id' => $entity->getEntityTypeId() . '__' . $field_name,
+      ':field_name' => $field_name,
       ':entity_type' => $entity->getEntityTypeId(),
       ':thread' => $first_thread,
     ))->fetchField();
@@ -572,10 +540,13 @@ function comment_node_view_alter(array &$build, EntityInterface $node, EntityVie
  *   The renderable array for the comment addition form.
  */
 function comment_add(EntityInterface $entity, $field_name = 'comment', $pid = NULL) {
+  /** @var \Drupal\field\FieldConfigInterface $field */
+  $field = Fieldconfig::loadByName($entity->getEntityTypeId(), $field_name);
   $values = array(
     'entity_type' => $entity->getEntityTypeId(),
     'entity_id' => $entity->id(),
-    'field_id' => $entity->getEntityTypeId() . '__' . $field_name,
+    'field_name' => $field_name,
+    'comment_type' => $field->getSetting('bundle'),
     'pid' => $pid,
   );
   $comment = entity_create('comment', $values);
@@ -664,7 +635,7 @@ function comment_get_thread(EntityInterface $entity, $field_name, $mode, $commen
   $query
     ->condition('c.entity_id', $entity->id())
     ->condition('c.entity_type', $entity->getEntityTypeId())
-    ->condition('c.field_id', $entity->getEntityTypeId() . '__' . $field_name)
+    ->condition('c.field_name', $field_name)
     ->addTag('entity_access')
     ->addTag('comment_filter')
     ->addMetaData('base_table', 'comment')
@@ -677,7 +648,7 @@ function comment_get_thread(EntityInterface $entity, $field_name, $mode, $commen
   $count_query
     ->condition('c.entity_id', $entity->id())
     ->condition('c.entity_type', $entity->getEntityTypeId())
-    ->condition('c.field_id', $entity->getEntityTypeId() . '__' . $field_name)
+    ->condition('c.field_name', $field_name)
     ->addTag('entity_access')
     ->addTag('comment_filter')
     ->addMetaData('base_table', 'comment')
@@ -779,21 +750,6 @@ function comment_view_multiple($comments, $view_mode = 'full', $langcode = NULL)
 /**
  * Implements hook_form_FORM_ID_alter().
  */
-function comment_form_field_ui_field_instance_edit_form_alter(&$form, $form_state) {
-  if ($form['#field']->getType() == 'comment') {
-    // Collect translation settings.
-    if (\Drupal::moduleHandler()->moduleExists('content_translation')) {
-      array_unshift($form['#submit'], 'comment_translation_configuration_element_submit');
-    }
-
-    // Hide required checkbox.
-    $form['instance']['required']['#access'] = FALSE;
-  }
-}
-
-/**
- * Implements hook_form_FORM_ID_alter().
- */
 function comment_form_field_ui_field_overview_form_alter(&$form, $form_state) {
   $request = \Drupal::request();
   if ($form['#entity_type'] == 'comment' && $request->attributes->has('commented_entity_type')) {
@@ -834,28 +790,6 @@ function comment_form_field_ui_field_edit_form_alter(&$form, $form_state) {
 }
 
 /**
- * Form submission handler for field_ui_field_edit_form().
- *
- * This handles the comment translation settings added by
- * _comment_field_instance_settings_form_process().
- *
- * @see _comment_field_instance_settings_form_process()
- */
-function comment_translation_configuration_element_submit($form, &$form_state) {
-  // The comment translation settings form element is embedded into the instance
-  // settings form. Hence we need to provide to the regular submit handler a
-  // manipulated form state to make it process comment settings instead of the
-  // host entity.
-  $key = 'language_configuration';
-  $comment_form_state = array(
-    'content_translation' => array('key' => $key),
-    'language' => array($key => array('entity_type' => 'comment', 'bundle' => $form['#field']->name)),
-    'values' => array($key => array('content_translation' => $form_state['values']['content_translation'])),
-  );
-  content_translation_language_configuration_element_submit($form, $comment_form_state);
-}
-
-/**
  * Implements hook_entity_load().
  *
  * @see \Drupal\comment\Plugin\Field\FieldType\CommentItem::propertyDefinitions()
@@ -873,14 +807,11 @@ function comment_entity_load($entities, $entity_type) {
   // comment statistics properties, which are defined on each CommentItem field.
   $result = \Drupal::service('comment.statistics')->read($entities, $entity_type);
   foreach ($result as $record) {
-    $parts = explode('__', $record->field_id, 2);
-    list(, $field_name) = $parts;
-
     // Skip fields that entity does not have.
-    if (!$entities[$record->entity_id]->hasField($field_name)) {
+    if (!$entities[$record->entity_id]->hasField($record->field_name)) {
       continue;
     }
-    $comment_statistics = $entities[$record->entity_id]->get($field_name);
+    $comment_statistics = $entities[$record->entity_id]->get($record->field_name);
     $comment_statistics->cid = $record->cid;
     $comment_statistics->last_comment_timestamp = $record->last_comment_timestamp;
     $comment_statistics->last_comment_name = $record->last_comment_name;
@@ -1137,7 +1068,7 @@ function comment_num_new($entity_id, $entity_type, $field_name = NULL, $timestam
       ->condition('c.created', $timestamp, '>');
     if ($field_name) {
       // Limit to a particular field.
-      $query->condition('c.field_id', $entity_type . '__' . $field_name);
+      $query->condition('c.field_name', $field_name);
     }
 
     return $query->execute()
@@ -1169,7 +1100,7 @@ function comment_get_display_ordinal($cid, FieldDefinitionInterface $field_defin
   // Count how many comments (c1) are before $cid (c2) in display order. This is
   // the 0-based display ordinal.
   $query = db_select('comment', 'c1');
-  $query->innerJoin('comment', 'c2', 'c2.entity_id = c1.entity_id AND c2.entity_type = c1.entity_type AND c2.field_id = c1.field_id');
+  $query->innerJoin('comment', 'c2', 'c2.entity_id = c1.entity_id AND c2.entity_type = c1.entity_type AND c2.field_name = c1.field_name');
   $query->addExpression('COUNT(*)', 'count');
   $query->condition('c2.cid', $cid);
   if (!user_access('administer comments')) {
diff --git a/core/modules/comment/comment.routing.yml b/core/modules/comment/comment.routing.yml
index 1a6ac59..40367ae 100644
--- a/core/modules/comment/comment.routing.yml
+++ b/core/modules/comment/comment.routing.yml
@@ -66,24 +66,50 @@ comment.new_comments_node_links:
   requirements:
     _permission: 'access content'
 
-comment.bundle_list:
-  path: '/admin/structure/comments'
+comment.node_redirect:
+  path: '/comment/{node}/reply'
+  defaults:
+    _controller: 'Drupal\comment\Controller\CommentController::redirectNode'
+  requirements:
+    _entity_access: 'node.view'
+    _module_dependencies: 'node'
+
+comment.type_list:
+  path: '/admin/structure/comment'
   defaults:
-    _content: '\Drupal\comment\Controller\AdminController::overviewBundles'
+    _entity_list: 'comment_type'
     _title: 'Comment forms'
   requirements:
-    _permission: 'administer comments'
+    _permission: 'administer comment types'
+  options:
+    _admin_route: TRUE
+
+comment.type_delete:
+  path: '/admin/structure/comment/manage/{comment_type}/delete'
+  defaults:
+    _entity_form: 'comment_type.delete'
+    _title: 'Delete'
+  requirements:
+    _entity_access: 'comment_type.delete'
+  options:
+    _admin_route: TRUE
 
-# This route is only used by Field UI.
-comment.bundle:
-  path: '/admin/structure/comments/manage/{bundle}'
+comment.type_add:
+  path: '/admin/structure/comment/types/add'
+  defaults:
+    _entity_form: 'comment_type.add'
+    _title: 'Add'
   requirements:
-    _access: 'FALSE'
+    _permission: 'administer comment types'
+  options:
+    _admin_route: TRUE
 
-comment.node_redirect:
-  path: '/comment/{node}/reply'
+comment.type_edit:
+  path: '/admin/structure/comment/manage/{comment_type}'
   defaults:
-    _controller: 'Drupal\comment\Controller\CommentController::redirectNode'
+    _entity_form: 'comment_type.edit'
+    _title: 'Edit'
   requirements:
-    _entity_access: 'node.view'
-    _module_dependencies: 'node'
+    _entity_access: 'comment_type.update'
+  options:
+    _admin_route: TRUE
diff --git a/core/modules/comment/comment.services.yml b/core/modules/comment/comment.services.yml
index 13846b1..b0fc2ad 100644
--- a/core/modules/comment/comment.services.yml
+++ b/core/modules/comment/comment.services.yml
@@ -12,9 +12,3 @@ services:
   comment.statistics:
     class: Drupal\comment\CommentStatistics
     arguments: ['@database', '@current_user', '@entity.manager', '@state']
-
-  comment.route_enhancer:
-      class: Drupal\comment\Routing\CommentBundleEnhancer
-      arguments: ['@entity.manager']
-      tags:
-        - { name: route_enhancer}
diff --git a/core/modules/comment/comment.views.inc b/core/modules/comment/comment.views.inc
index 6429f28..8d9c39e 100644
--- a/core/modules/comment/comment.views.inc
+++ b/core/modules/comment/comment.views.inc
@@ -332,9 +332,26 @@ function comment_views_data() {
     ),
   );
 
-  $data['comment']['field_id'] = array(
-    'title' => t('Comment field id'),
-    'help' => t('The Field id from which the comment originated.'),
+  $data['comment']['field_name'] = array(
+    'title' => t('Comment field name'),
+    'help' => t('The Field name from which the comment originated.'),
+    'field' => array(
+      'id' => 'standard',
+    ),
+    'filter' => array(
+      'id' => 'string',
+    ),
+    'argument' => array(
+      'id' => 'string',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+  );
+
+  $data['comment']['comment_type'] = array(
+    'title' => t('Comment type'),
+    'help' => t('The comment type for this comment.'),
     'field' => array(
       'id' => 'standard',
     ),
@@ -567,9 +584,9 @@ function comment_views_data() {
       'id' => 'standard',
     ),
   );
-  $data['comment_entity_statistics']['field_id'] = array(
-    'title' => t('Comment field ID'),
-    'help' => t('The field ID from which the comment originated.'),
+  $data['comment_entity_statistics']['field_name'] = array(
+    'title' => t('Comment field name'),
+    'help' => t('The field name from which the comment originated.'),
     'field' => array(
       'id' => 'standard',
     ),
@@ -666,8 +683,8 @@ function comment_views_data_alter(&$data) {
                 'value' => $entity_type_id,
               ),
               array(
-                'field' => 'field_id',
-                'value' => $entity_type_id . '.' . $field_name,
+                'field' => 'field_name',
+                'value' => $field_name,
               ),
             ),
           ),
diff --git a/core/modules/comment/config/schema/comment.schema.yml b/core/modules/comment/config/schema/comment.schema.yml
index 3b322b2..f6810e5 100644
--- a/core/modules/comment/config/schema/comment.schema.yml
+++ b/core/modules/comment/config/schema/comment.schema.yml
@@ -43,6 +43,34 @@ action.configuration.comment_unpublish_action:
   type: action_configuration_default
   label: 'Unpublish comment configuration'
 
+comment.type.*:
+  type: mapping
+  label: 'Comment type settings'
+  mapping:
+    id:
+      type: string
+      label: 'Machine-readable name'
+    uuid:
+      type: string
+      label: 'UUID'
+    targetEntityTypeId:
+      type: string
+      label: 'Target Entity Type ID'
+    label:
+      type: label
+      label: 'Label'
+    description:
+      type: text
+      label: 'Description'
+    status:
+      type: boolean
+      label: 'Status'
+    langcode:
+      type: string
+      label: 'Default language'
+    dependencies:
+      type: config_dependencies
+      label: 'Dependencies'
 
 field.comment.settings:
   type: sequence
diff --git a/core/modules/comment/lib/Drupal/comment/CommentFieldNameItem.php b/core/modules/comment/lib/Drupal/comment/CommentFieldNameItem.php
deleted file mode 100644
index 94b8587..0000000
--- a/core/modules/comment/lib/Drupal/comment/CommentFieldNameItem.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\comment\CommentFieldNameItem.
- */
-
-namespace Drupal\comment;
-
-use Drupal\Core\Field\FieldStorageDefinitionInterface;
-use Drupal\Core\Field\Plugin\Field\FieldType\StringItem;
-use Drupal\Core\TypedData\DataDefinition;
-
-/**
- * The field item for the 'fieldname' field.
- */
-class CommentFieldNameItem extends StringItem {
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
-    $properties['value'] = DataDefinition::create('string')
-      ->setLabel(t('String value'))
-      ->setClass('\Drupal\comment\CommentFieldNameValue')
-      ->setComputed(TRUE);
-
-    return $properties;
-  }
-
-}
diff --git a/core/modules/comment/lib/Drupal/comment/CommentFieldNameValue.php b/core/modules/comment/lib/Drupal/comment/CommentFieldNameValue.php
deleted file mode 100644
index 0190b8d..0000000
--- a/core/modules/comment/lib/Drupal/comment/CommentFieldNameValue.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\comment\CommentFieldNameValue.
- */
-
-namespace Drupal\comment;
-
-use Drupal\Core\TypedData\TypedData;
-use Drupal\Core\TypedData\ReadOnlyException;
-use InvalidArgumentException;
-
-/**
- * A computed property for the string value of the field_name field.
- */
-class CommentFieldNameValue extends TypedData {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getValue() {
-    if (!isset($this->value)) {
-      if (!isset($this->parent)) {
-        throw new InvalidArgumentException('Computed properties require context for computation.');
-      }
-      $field = $this->parent->getParent();
-      $entity = $field->getParent();
-      // Field id is of the form {entity_type}__{field_name}. We set the
-      // optional limit param to explode() in case the user adds a field with __
-      // in the name.
-      $parts = explode('__', $entity->getFieldId(), 2);
-      if ($parts && count($parts) == 2) {
-        $this->value = end($parts);
-      }
-    }
-    return $this->value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setValue($value, $notify = TRUE) {
-    if (isset($value)) {
-      $this->field_name = $value;
-      // Also set the field id.
-      $field = $this->parent->getParent();
-      $entity = $field->getParent();
-      $entity->field_id = $entity->getCommentedEntityTypeId() . '__' . $value;
-    }
-  }
-
-}
diff --git a/core/modules/comment/lib/Drupal/comment/CommentForm.php b/core/modules/comment/lib/Drupal/comment/CommentForm.php
index 6fd7ff6..1f509c6 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentForm.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentForm.php
@@ -215,7 +215,7 @@ public function form(array $form, array &$form_state) {
 
     // Add internal comment properties.
     $original = $comment->getUntranslated();
-    foreach (array('cid', 'pid', 'entity_id', 'entity_type', 'field_id', 'uid', 'langcode') as $key) {
+    foreach (array('cid', 'pid', 'entity_id', 'entity_type', 'comment_type', 'field_name', 'uid', 'langcode') as $key) {
       $key_name = key($comment->$key->getFieldDefinition()->getPropertyDefinitions());
       $form[$key] = array('#type' => 'value', '#value' => $original->$key->{$key_name});
     }
diff --git a/core/modules/comment/lib/Drupal/comment/CommentInterface.php b/core/modules/comment/lib/Drupal/comment/CommentInterface.php
index 48af294..9af4c0e 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentInterface.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentInterface.php
@@ -67,24 +67,15 @@ public function getCommentedEntityId();
   public function getCommentedEntityTypeId();
 
   /**
-   * Returns the field ID of the comment field the comment is attached to.
-   *
-   * @return string
-   *   The field identifier of the field the comment is attached to.
-   */
-  public function getFieldId();
-
-  /**
    * Sets the field ID for which this comment is attached.
    *
-   * @param string $field_id
-   *   The field identifier, usually formatted: {entity_type}__{field_name},
-   *   for example, node__comment.
+   * @param string $field_name
+   *   The field name through which the comment was added.
    *
    * @return $this
    *   The class instance that this method is called on.
    */
-  public function setFieldId($field_id);
+  public function setFieldName($field_name);
 
   /**
    * Returns the name of the field the comment is attached to.
@@ -258,4 +249,12 @@ public function setThread($thread);
    */
   public function permalink();
 
+  /**
+   * Get the comment type id for this comment.
+   *
+   * @return string
+   *   The id of the comment type.
+   */
+  public function getTypeId();
+
 }
diff --git a/core/modules/comment/lib/Drupal/comment/CommentManager.php b/core/modules/comment/lib/Drupal/comment/CommentManager.php
index 7bd9f0f..0a976d9 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentManager.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentManager.php
@@ -16,6 +16,7 @@
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\field\Entity\FieldConfig;
 
 /**
  * Comment manager contains common functions to manage comment fields.
@@ -103,9 +104,27 @@ public function getAllFields() {
   /**
    * {@inheritdoc}
    */
-  public function addDefaultField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN) {
+  public function addDefaultField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN, $comment_type_id = 'comment') {
+    $comment_type_storage = $this->entityManager->getStorage('comment_type');
+    if ($comment_type = $comment_type_storage->load($comment_type_id)) {
+      if ($comment_type->getTargetEntityTypeId() !== $entity_type) {
+        throw new \InvalidArgumentException($this->t('The given comment type id %id can only be used with the %entity_type entity type', array(
+          '%id' => $comment_type_id,
+          '%entity_type' => $entity_type,
+        )));
+      }
+    }
+    else {
+      // Silently create the comment-type for the calling code.
+      $comment_type_storage->create(array(
+        'id' => $comment_type_id,
+        'label' => $comment_type_id,
+        'targetEntityTypeId' => $entity_type,
+        'description' => 'Default comment field',
+      ))->save();
+    }
     // Make sure the field doesn't already exist.
-    if (!$this->entityManager->getStorage('field_config')->load($entity_type . '.' . $field_name)) {
+    if (!FieldConfig::loadByName($entity_type, $field_name)) {
       // Add a default comment field for existing node comments.
       $field = $this->entityManager->getStorage('field_config')->create(array(
         'entity_type' => $entity_type,
@@ -113,14 +132,14 @@ public function addDefaultField($entity_type, $bundle, $field_name = 'comment',
         'type' => 'comment',
         'translatable' => '0',
         'settings' => array(
-          'description' => 'Default comment field',
+          'comment_type' => $comment_type_id,
         ),
       ));
       // Create the field.
       $field->save();
     }
     // Make sure the instance doesn't already exist.
-    if (!$this->entityManager->getStorage('field_instance_config')->load($entity_type . '.' . $bundle . '.' . $field_name)) {
+    if (!array_key_exists($field_name, $this->entityManager->getFieldDefinitions($entity_type, $bundle))) {
       $instance = $this->entityManager->getStorage('field_instance_config')->create(array(
         'label' => 'Comment settings',
         'description' => '',
@@ -174,15 +193,15 @@ public function addDefaultField($entity_type, $bundle, $field_name = 'comment',
       }
 
     }
-    $this->addBodyField($entity_type, $field_name);
+    $this->addBodyField($comment_type_id);
   }
 
   /**
    * {@inheritdoc}
    */
-  public function addBodyField($entity_type, $field_name) {
+  public function addBodyField($comment_type_id) {
     // Create the field if needed.
-    $field = $this->entityManager->getStorage('field_config')->load('comment.comment_body');
+    $field = FieldConfig::loadByName('comment', 'comment_body');
     if (!$field) {
       $field = $this->entityManager->getStorage('field_config')->create(array(
         'name' => 'comment_body',
@@ -191,49 +210,38 @@ public function addBodyField($entity_type, $field_name) {
       ));
       $field->save();
     }
-    // Create the instance if needed, field name defaults to 'comment'.
-    $comment_bundle = $entity_type . '__' . $field_name;
-    $field_instance = $this->entityManager
-      ->getStorage('field_instance_config')
-      ->load("comment.$comment_bundle.comment_body");
-    if (!$field_instance) {
+    $field_instances = $this->entityManager
+      ->getFieldDefinitions('comment', $comment_type_id);
+    if (empty($field_instances['comment_body'])) {
       // Attaches the body field by default.
       $field_instance = $this->entityManager->getStorage('field_instance_config')->create(array(
         'field_name' => 'comment_body',
         'label' => 'Comment',
         'entity_type' => 'comment',
-        'bundle' => $comment_bundle,
+        'bundle' => $comment_type_id,
         'settings' => array('text_processing' => 1),
         'required' => TRUE,
       ));
       $field_instance->save();
 
       // Assign widget settings for the 'default' form mode.
-      entity_get_form_display('comment', $comment_bundle, 'default')
+      entity_get_form_display('comment', $comment_type_id, 'default')
         ->setComponent('comment_body', array(
           'type' => 'text_textarea',
         ))
         ->save();
 
       // Assign display settings for the 'default' view mode.
-      entity_get_display('comment', $comment_bundle, 'default')
+      entity_get_display('comment', $comment_type_id, 'default')
         ->setComponent('comment_body', array(
           'label' => 'hidden',
           'type' => 'text_default',
           'weight' => 0,
         ))
         ->save();
-    }
-  }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getFieldUIPageTitle($commented_entity_type, $field_name) {
-    $field_info = $this->getFields($commented_entity_type);
-    $sample_bundle = reset($field_info[$field_name]['bundles']);
-    $sample_definition = $this->entityManager->getFieldDefinitions($commented_entity_type, $sample_bundle)[$field_name];
-    return String::checkPlain($sample_definition->getLabel());
+      $this->entityManager->clearCachedFieldDefinitions();
+    }
   }
 
   /**
diff --git a/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php b/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php
index f302e18..8797065 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentManagerInterface.php
@@ -48,36 +48,24 @@ public function getAllFields();
    * @param string $bundle
    *   The bundle to attach the default comment field instance to.
    * @param string $field_name
-   *   (optional) Field name to use for the comment field. Defaults to 'comment'.
+   *   (optional) Field name to use for the comment field. Defaults to
+   *     'comment'.
    * @param int $default_value
    *   (optional) Default value, one of CommentItemInterface::HIDDEN,
    *   CommentItemInterface::OPEN, CommentItemInterface::CLOSED. Defaults to
    *   CommentItemInterface::OPEN.
+   * @param string $comment_type_id
+   *   (optional) ID of comment type to use. Defaults to 'comment'.
    */
-  public function addDefaultField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN);
+  public function addDefaultField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN, $comment_type_id = 'comment');
 
   /**
    * Creates a comment_body field instance.
    *
-   * @param string $entity_type
-   *   The type of the entity to which the comment field attached.
-   * @param string $field_name
-   *   Name of the comment field to add comment_body field.
-   */
-  public function addBodyField($entity_type, $field_name);
-
-  /**
-   * Builds human readable page title for field_ui management screens.
-   *
-   * @param string $commented_entity_type
-   *   The entity type to which the comment field is attached.
-   * @param string $field_name
-   *   The comment field for which the overview is to be displayed.
-   *
-   * @return string
-   *   The human readable field name.
+   * @param string $comment_type
+   *   The comment bundle.
    */
-  public function getFieldUIPageTitle($commented_entity_type, $field_name);
+  public function addBodyField($comment_type);
 
   /**
    * Provides a message if posting comments is forbidden.
diff --git a/core/modules/comment/lib/Drupal/comment/CommentStatistics.php b/core/modules/comment/lib/Drupal/comment/CommentStatistics.php
index 9e3fbd1..fbbdff4 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentStatistics.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentStatistics.php
@@ -95,7 +95,7 @@ public function create(ContentEntityInterface $entity, $fields) {
       ->fields(array(
         'entity_id',
         'entity_type',
-        'field_id',
+        'field_name',
         'cid',
         'last_comment_timestamp',
         'last_comment_name',
@@ -126,7 +126,7 @@ public function create(ContentEntityInterface $entity, $fields) {
       $query->values(array(
         'entity_id' => $entity->id(),
         'entity_type' => $entity->getEntityTypeId(),
-        'field_id' => $entity->getEntityTypeId() . '__' . $field_name,
+        'field_name' => $field_name,
         'cid' => 0,
         'last_comment_timestamp' => $last_comment_timestamp,
         'last_comment_name' => NULL,
@@ -157,7 +157,7 @@ public function getRankingInfo() {
           'alias' => 'ces',
           // Default to comment field as this is the most common use case for
           // nodes.
-          'on' => "ces.entity_id = i.sid AND ces.entity_type = 'node' AND ces.field_id = 'node__comment'",
+          'on' => "ces.entity_id = i.sid AND ces.entity_type = 'node' AND ces.field_name = 'comment'",
         ),
         // Inverse law that maps the highest reply count on the site to 1 and 0
         // to 0. Note that the CAST here is necessary for PostgreSQL, because the
@@ -183,7 +183,7 @@ public function update(CommentInterface $comment) {
     $query->addExpression('COUNT(cid)');
     $count = $query->condition('c.entity_id', $comment->getCommentedEntityId())
       ->condition('c.entity_type', $comment->getCommentedEntityTypeId())
-      ->condition('c.field_id', $comment->getFieldId())
+      ->condition('c.field_name', $comment->getFieldName())
       ->condition('c.status', CommentInterface::PUBLISHED)
       ->execute()
       ->fetchField();
@@ -194,7 +194,7 @@ public function update(CommentInterface $comment) {
         ->fields('c', array('cid', 'name', 'changed', 'uid'))
         ->condition('c.entity_id', $comment->getCommentedEntityId())
         ->condition('c.entity_type', $comment->getCommentedEntityTypeId())
-        ->condition('c.field_id', $comment->getFieldId())
+        ->condition('c.field_name', $comment->getFieldName())
         ->condition('c.status', CommentInterface::PUBLISHED)
         ->orderBy('c.created', 'DESC')
         ->range(0, 1)
@@ -212,7 +212,7 @@ public function update(CommentInterface $comment) {
         ->keys(array(
           'entity_id' => $comment->getCommentedEntityId(),
           'entity_type' => $comment->getCommentedEntityTypeId(),
-          'field_id' => $comment->getFieldId(),
+          'field_name' => $comment->getFieldName(),
         ))
         ->execute();
     }
@@ -241,7 +241,7 @@ public function update(CommentInterface $comment) {
         ))
         ->condition('entity_id', $comment->getCommentedEntityId())
         ->condition('entity_type', $comment->getCommentedEntityTypeId())
-        ->condition('field_id', $comment->getFieldId())
+        ->condition('field_name', $comment->getFieldName())
         ->execute();
     }
   }
diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorage.php b/core/modules/comment/lib/Drupal/comment/CommentStorage.php
index 88a1bd4..7c90d45 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentStorage.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentStorage.php
@@ -95,7 +95,7 @@ public function updateEntityStatistics(CommentInterface $comment) {
   public function getMaxThread(EntityInterface $comment) {
     $query = $this->database->select('comment', 'c')
       ->condition('entity_id', $comment->getCommentedEntityId())
-      ->condition('field_id', $comment->getFieldId())
+      ->condition('field_name', $comment->getFieldName())
       ->condition('entity_type', $comment->getCommentedEntityTypeId());
     $query->addExpression('MAX(thread)', 'thread');
     return $query->execute()
@@ -108,7 +108,7 @@ public function getMaxThread(EntityInterface $comment) {
   public function getMaxThreadPerThread(EntityInterface $comment) {
     $query = $this->database->select('comment', 'c')
       ->condition('entity_id', $comment->getCommentedEntityId())
-      ->condition('field_id', $comment->getFieldId())
+      ->condition('field_name', $comment->getFieldName())
       ->condition('entity_type', $comment->getCommentedEntityTypeId())
       ->condition('thread', $comment->getParentComment()->getThread() . '.%', 'LIKE');
     $query->addExpression('MAX(thread)', 'thread');
diff --git a/core/modules/comment/lib/Drupal/comment/CommentTypeForm.php b/core/modules/comment/lib/Drupal/comment/CommentTypeForm.php
new file mode 100644
index 0000000..3650e45
--- /dev/null
+++ b/core/modules/comment/lib/Drupal/comment/CommentTypeForm.php
@@ -0,0 +1,143 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\comment\CommentTypeForm.
+ */
+
+namespace Drupal\comment;
+
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\Core\Entity\EntityForm;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Base form controller for category edit forms.
+ */
+class CommentTypeForm extends EntityForm implements ContainerInjectionInterface {
+
+  /**
+   * Entity manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity.manager')
+    );
+  }
+
+  /**
+   * Constructs a CommentTypeFormController
+   *
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager service.
+   */
+  function __construct(EntityManagerInterface $entity_manager) {
+    $this->entityManager = $entity_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function form(array $form, array &$form_state) {
+    $form = parent::form($form, $form_state);
+
+    $comment_type = $this->entity;
+
+    $form['label'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Label'),
+      '#maxlength' => 255,
+      '#default_value' => $comment_type->label(),
+      '#description' => t("Provide a label for this comment type to help identify it in the administration pages."),
+      '#required' => TRUE,
+    );
+    $form['id'] = array(
+      '#type' => 'machine_name',
+      '#default_value' => $comment_type->id(),
+      '#machine_name' => array(
+        'exists' => '\Drupal\comment\Entity\CommentType::load',
+      ),
+      '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
+      '#disabled' => !$comment_type->isNew(),
+    );
+
+    $form['description'] = array(
+      '#type' => 'textarea',
+      '#default_value' => $comment_type->description,
+      '#description' => t('Enter a description for this comment type.'),
+      '#title' => t('Description'),
+    );
+
+    $options = array();
+    foreach ($this->entityManager->getDefinitions() as $entity_type) {
+      if ($entity_type->isFieldable()) {
+        $options[$entity_type->id()] = $entity_type->getLabel();
+      }
+    }
+    $form['targetEntityTypeId'] = array(
+      '#type' => 'select',
+      '#default_value' => $comment_type->targetEntityTypeId,
+      '#description' => t('Select the target entity type for this comment type.'),
+      '#title' => t('Target entity type'),
+      '#options' => $options,
+    );
+
+    if ($this->moduleHandler->moduleExists('content_translation')) {
+      $form['language'] = array(
+        '#type' => 'details',
+        '#title' => t('Language settings'),
+        '#group' => 'additional_settings',
+      );
+
+      $language_configuration = language_get_default_configuration('comment', $comment_type->id());
+      $form['language']['language_configuration'] = array(
+        '#type' => 'language_configuration',
+        '#entity_information' => array(
+          'entity_type' => 'comment',
+          'bundle' => $comment_type->id(),
+        ),
+        '#default_value' => $language_configuration,
+      );
+
+      $form['#submit'][] = 'language_configuration_element_submit';
+    }
+
+    $form['actions'] = array('#type' => 'actions');
+    $form['actions']['submit'] = array(
+      '#type' => 'submit',
+      '#value' => t('Save'),
+    );
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function save(array $form, array &$form_state) {
+    $comment_type = $this->entity;
+    $status = $comment_type->save();
+
+    $edit_link = \Drupal::linkGenerator()->generateFromUrl($this->t('Edit'), $this->entity->urlInfo());
+    if ($status == SAVED_UPDATED) {
+      drupal_set_message(t('Comment type %label has been updated.', array('%label' => $comment_type->label())));
+      watchdog('comment', 'Comment type %label has been updated.', array('%label' => $comment_type->label()), WATCHDOG_NOTICE, $edit_link);
+    }
+    else {
+      drupal_set_message(t('Comment type %label has been added.', array('%label' => $comment_type->label())));
+      watchdog('comment', 'Comment type %label has been added.', array('%label' => $comment_type->label()), WATCHDOG_NOTICE, $edit_link);
+    }
+
+    $form_state['redirect_route']['route_name'] = 'comment.type_list';
+  }
+
+}
diff --git a/core/modules/comment/lib/Drupal/comment/CommentTypeInterface.php b/core/modules/comment/lib/Drupal/comment/CommentTypeInterface.php
new file mode 100644
index 0000000..e768063
--- /dev/null
+++ b/core/modules/comment/lib/Drupal/comment/CommentTypeInterface.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\comment\Entity\CommentTypeInterface.
+ */
+
+namespace Drupal\comment;
+
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+
+/**
+ * Provides an interface defining a comment type entity.
+ */
+interface CommentTypeInterface extends ConfigEntityInterface {
+
+  /**
+   * Returns the comment type description.
+   *
+   * @return string
+   */
+  public function getDescription();
+
+  /**
+   * Sets the description of the comment type.
+   *
+   * @param string $description
+   *   The new description.
+   *
+   * @return $this
+   *
+   */
+  public function setDescription($description);
+
+  /**
+   * Gets the target entity type id for this comment type.
+   *
+   * @return string
+   *   The target entity type id.
+   */
+  public function getTargetEntityTypeId();
+
+}
diff --git a/core/modules/comment/lib/Drupal/comment/CommentTypeListBuilder.php b/core/modules/comment/lib/Drupal/comment/CommentTypeListBuilder.php
new file mode 100644
index 0000000..faadcdc
--- /dev/null
+++ b/core/modules/comment/lib/Drupal/comment/CommentTypeListBuilder.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\comment\CommentTypeListBuilder.
+ */
+
+namespace Drupal\comment;
+
+use Drupal\Component\Utility\Xss;
+use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Utility\LinkGeneratorInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Defines a class to build a listing of comment type entities.
+ *
+ * @see \Drupal\comment\Entity\CommentType
+ */
+class CommentTypeListBuilder extends ConfigEntityListBuilder {
+
+  /**
+   * The link generator service.
+   *
+   * @var \Drupal\Core\Utility\LinkGeneratorInterface
+   */
+
+  protected $linkGenerator;
+  /**
+   * {@inheritdoc}
+   */
+  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
+    return new static(
+      $entity_type,
+      $container->get('entity.manager')->getStorage($entity_type->id()),
+      $container->get('link_generator')
+    );
+  }
+
+  /**
+   * Constructs a new EntityListBuilder object.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+   *   The entity type definition.
+   * @param \Drupal\Core\Entity\EntityStorageInterface $storage
+   *   The entity storage class.
+   * @param \Drupal\Core\Utility\LinkGeneratorInterface $link_generator
+   *   The link generator service.
+   */
+  public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, LinkGeneratorInterface $link_generator) {
+    $this->entityTypeId = $entity_type->id();
+    $this->storage = $storage;
+    $this->entityType = $entity_type;
+    $this->linkGenerator = $link_generator;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
+    // Place the edit operation after the operations added by field_ui.module
+    // which have the weights 15, 20, 25.
+    if (isset($operations['edit'])) {
+      $operations['edit']['weight'] = 30;
+    }
+    return $operations;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildHeader() {
+    $header['type'] = t('Comment type');
+    $header['description'] = t('Description');
+    return $header + parent::buildHeader();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildRow(EntityInterface $entity) {
+    $row['type'] = $this->linkGenerator->generateFromUrl($entity->label(), $entity->urlInfo());
+    $row['description'] = Xss::filterAdmin($entity->getDescription());
+    return $row + parent::buildRow($entity);
+  }
+
+}
diff --git a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
index 5a75d43..df3ab6c 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
@@ -113,7 +113,7 @@ public function buildComponents(array &$build, array $entities, array $displays,
         throw new \InvalidArgumentException(t('Invalid entity for comment.'));
       }
       $build[$id]['#entity'] = $entity;
-      $build[$id]['#theme'] = 'comment__' . $entity->getFieldId() . '__' . $commented_entity->bundle();
+      $build[$id]['#theme'] = 'comment__' . $entity->getFieldName() . '__' . $commented_entity->bundle();
       $callback = '\Drupal\comment\CommentViewBuilder::renderLinks';
       $context = array(
         'comment_entity_id' => $entity->id(),
diff --git a/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php b/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php
index 9c8d43c..4c1592f 100644
--- a/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php
+++ b/core/modules/comment/lib/Drupal/comment/Controller/AdminController.php
@@ -7,12 +7,8 @@
 
 namespace Drupal\comment\Controller;
 
-use Drupal\comment\CommentManagerInterface;
-use Drupal\field\FieldConfigInterface;
-use Drupal\Component\Utility\String;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Form\FormBuilderInterface;
-use Drupal\field_ui\FieldUI;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -22,13 +18,6 @@
 class AdminController extends ControllerBase {
 
   /**
-   * The comment manager service.
-   *
-   * @var \Drupal\comment\CommentManagerInterface
-   */
-  protected $commentManager;
-
-  /**
    * The form builder.
    *
    * @var \Drupal\Core\Form\FormBuilderInterface
@@ -40,7 +29,6 @@ class AdminController extends ControllerBase {
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('comment.manager'),
       $container->get('form_builder')
     );
   }
@@ -48,137 +36,14 @@ public static function create(ContainerInterface $container) {
   /**
    * Constructs an AdminController object.
    *
-   * @param \Drupal\comment\CommentManagerInterface $comment_manager
-   *   The comment manager service.
    * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
    *   The form builder.
    */
-  public function __construct(CommentManagerInterface $comment_manager, FormBuilderInterface $form_builder) {
-    $this->commentManager = $comment_manager;
+  public function __construct(FormBuilderInterface $form_builder) {
     $this->formBuilder = $form_builder;
   }
 
   /**
-   * Returns an overview of comment fields in use on the site.
-   *
-   * @return array
-   *   A renderable array containing a list of comment fields, the entity
-   *   type and bundle combinations on which they are in use and various
-   *   operation links for configuring each field.
-   */
-  public function overviewBundles() {
-    $header = array(
-      'field_name' => $this->t('Field name'),
-      'description' => array(
-        'data' => $this->t('Description'),
-        'class' => array(RESPONSIVE_PRIORITY_MEDIUM),
-      ),
-      'usage' => array(
-        'data' => $this->t('Used in'),
-        'class' => array(RESPONSIVE_PRIORITY_MEDIUM),
-      ),
-      'type' => $this->t('Type'),
-    );
-
-    // Add a column for field UI operations if the Field UI module is enabled.
-    $field_ui_enabled = $this->moduleHandler()->moduleExists('field_ui');
-    if ($field_ui_enabled) {
-      $header['operations'] = $this->t('Operations');
-    }
-
-    $entity_bundles = $this->entityManager()->getAllBundleInfo();
-    $entity_types = $this->entityManager()->getDefinitions();
-    $rows = array();
-
-    // Fetch a list of all comment fields.
-    $fields = $this->commentManager->getAllFields();
-
-    foreach ($fields as $entity_type => $data) {
-      $field_storage_definitions = $this->entityManager()->getFieldStorageDefinitions($entity_type);
-      foreach ($data as $field_name => $field_info_map) {
-        $storage_definition = $field_storage_definitions[$field_name];
-        // Initialize the row.
-        $row = array(
-          'class' => $storage_definition->get('locked') ? array('field-disabled') : array(''),
-        );
-
-        $label = $storage_definition->getLabel();
-        if ($storage_definition instanceof FieldConfigInterface) {
-          $bundles = $storage_definition->getBundles();
-          $sample_bundle = reset($bundles);
-          $field_definitions = $this->entityManager()->getFieldDefinitions($entity_type, $sample_bundle);
-          $label = $field_definitions[$field_name]->getLabel();
-        }
-
-        $tokens = array(
-          '@label' => $label,
-          '@field_name' => $field_name,
-        );
-        $row['data']['field_name']['data'] = $storage_definition->get('locked') ? $this->t('@label (@field_name) (Locked)', $tokens) : $this->t('@label (@field_name)', $tokens);
-
-        $row['data']['description']['data'] = $storage_definition->getSetting('description');
-        $row['data']['usage']['data'] = array(
-          '#theme' => 'item_list',
-          '#items' => array(),
-        );
-        foreach ($field_info_map['bundles'] as $bundle) {
-          if (isset($entity_bundles[$entity_type][$bundle])) {
-            // Add the current instance.
-            if ($field_ui_enabled && $route_info = FieldUI::getOverviewRouteInfo($entity_type, $bundle)) {
-              $row['data']['usage']['data']['#items'][] = \Drupal::linkGenerator()->generateFromUrl($entity_bundles[$entity_type][$bundle]['label'], $route_info);
-            }
-            else {
-              $row['data']['usage']['data']['#items'][] = $entity_bundles[$entity_type][$bundle]['label'];
-            }
-          }
-        }
-
-        $row['data']['type']['data'] = String::checkPlain($entity_types[$entity_type]->getLabel());
-
-        if ($field_ui_enabled) {
-          if ($this->currentUser()->hasPermission('administer comment fields')) {
-            $links['fields'] = array(
-              'title' => $this->t('Manage fields'),
-              'href' => 'admin/structure/comments/manage/' . $entity_type . '__' . $field_name . '/fields',
-              'weight' => 5,
-            );
-          }
-          if ($this->currentUser()->hasPermission('administer comment display')) {
-            $links['display'] = array(
-              'title' => $this->t('Manage display'),
-              'href' => 'admin/structure/comments/manage/' . $entity_type . '__' . $field_name . '/display',
-              'weight' => 10,
-            );
-          }
-          if ($this->currentUser()->hasPermission('administer comment form display')) {
-            $links['form_display'] = array(
-              'title' => $this->t('Manage form display'),
-              'href' => 'admin/structure/comments/manage/' . $entity_type . '__' . $field_name . '/form-display',
-              'weight' => 10,
-            );
-          }
-
-          $row['data']['operations']['data'] = array(
-            '#type' => 'operations',
-            '#links' => $links,
-          );
-        }
-        $rows[$entity_type . '__' . $field_name] = $row;
-      }
-    }
-
-    $build['overview'] = array(
-      '#type' => 'table',
-      '#header' => $header,
-      '#rows' => $rows,
-      '#empty' => $this->t('No comment forms available.'),
-    );
-    $build['#title'] = $this->t('Comment forms');
-
-    return $build;
-  }
-
-  /**
    * Presents an administrative comment listing.
    *
    * @param \Symfony\Component\HttpFoundation\Request $request
diff --git a/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php b/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php
index 1e73008..94fb25e 100644
--- a/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php
+++ b/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php
@@ -255,7 +255,7 @@ public function getReplyForm(Request $request, $entity_type, $entity_id, $field_
       'entity_id' => $entity->id(),
       'pid' => $pid,
       'entity_type' => $entity->getEntityTypeId(),
-      'field_id' => $entity->getEntityTypeId() . '__' . $field_name,
+      'field_name' => $field_name,
     ));
     $build['comment_form'] = $this->entityFormBuilder()->getForm($comment);
 
diff --git a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
index de10346..33e5fef 100644
--- a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
+++ b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
@@ -13,8 +13,6 @@
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Field\FieldDefinition;
-use Drupal\Core\Language\Language;
-use Drupal\Core\TypedData\DataDefinition;
 use Drupal\user\UserInterface;
 
 /**
@@ -40,7 +38,7 @@
  *   translatable = TRUE,
  *   entity_keys = {
  *     "id" = "cid",
- *     "bundle" = "field_id",
+ *     "bundle" = "comment_type",
  *     "label" = "subject",
  *     "uuid" = "uuid"
  *   },
@@ -48,8 +46,9 @@
  *     "canonical" = "comment.permalink",
  *     "delete-form" = "comment.confirm_delete",
  *     "edit-form" = "comment.edit_page",
- *     "admin-form" = "comment.bundle"
- *   }
+ *     "admin-form" = "comment.type_edit"
+ *   },
+ *   bundle_entity_type = "comment_type"
  * )
  */
 class Comment extends ContentEntityBase implements CommentInterface {
@@ -284,21 +283,15 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
       ->setLabel(t('Entity type'))
       ->setDescription(t('The entity type to which this comment is attached.'));
 
-    // @todo Convert to the entity_reference field in
-    // https://drupal.org/node/2149859.
-    $fields['field_id'] = FieldDefinition::create('string')
-      ->setLabel(t('Field ID'))
-      ->setDescription(t('The comment field id.'));
+    $fields['comment_type'] = FieldDefinition::create('string')
+      ->setLabel(t('Comment Type'))
+      ->setDescription(t('The comment type.'));
 
     $fields['field_name'] = FieldDefinition::create('string')
       ->setLabel(t('Comment field name'))
       ->setDescription(t('The field name through which this comment was added.'))
       ->setComputed(TRUE);
 
-    $item_definition = $fields['field_name']->getItemDefinition();
-    $item_definition->setClass('\Drupal\comment\CommentFieldNameItem');
-    $fields['field_name']->setItemDefinition($item_definition);
-
     return $fields;
   }
 
@@ -306,10 +299,14 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    * {@inheritdoc}
    */
   public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
-    list($target_type) = explode('__', $bundle, 2);
-    $fields['entity_id'] = clone $base_field_definitions['entity_id'];
-    $fields['entity_id']->setSetting('target_type', $target_type);
-    return $fields;
+    if ($entity_type->id() == 'comment') {
+      if ($comment_type = entity_load('comment_type', $bundle)) {
+        $fields['entity_id'] = clone $base_field_definitions['entity_id'];
+        $fields['entity_id']->setSetting('target_type', $comment_type->getTargetEntityTypeId());
+        return $fields;
+      }
+      return array();
+    }
   }
 
   /**
@@ -351,15 +348,8 @@ public function getCommentedEntityTypeId() {
   /**
    * {@inheritdoc}
    */
-  public function getFieldId() {
-    return $this->get('field_id')->value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setFieldId($field_id) {
-    $this->set('field_id', $field_id);
+  public function setFieldName($field_name) {
+    $this->set('field_name', $field_name);
     return $this;
   }
 
@@ -505,8 +495,10 @@ public function getChangedTime() {
    * {@inheritdoc}
    */
   public static function preCreate(EntityStorageInterface $storage, array &$values) {
-    if (empty($values['field_id']) && !empty($values['field_name']) && !empty($values['entity_type'])) {
-      $values['field_id'] = $values['entity_type'] . '__' . $values['field_name'];
+    if (empty($values['comment_type']) && !empty($values['field_name']) && !empty($values['entity_type'])) {
+      /** @var \Drupal\field\FieldConfigInterface $field */
+      $field = entity_load('field_config', $values['entity_type'] . '.' . $values['field_name']);
+      $values['comment_type'] = $field->getSetting('comment_type');
     }
   }
 
@@ -540,4 +532,14 @@ public function setOwner(UserInterface $account) {
     return $this;
   }
 
+  /**
+   * Get the comment type id for this comment.
+   *
+   * @return string
+   *   The id of the comment type.
+   */
+  public function getTypeId() {
+    return $this->bundle();
+  }
+
 }
diff --git a/core/modules/comment/lib/Drupal/comment/Entity/CommentType.php b/core/modules/comment/lib/Drupal/comment/Entity/CommentType.php
new file mode 100644
index 0000000..eaf8232
--- /dev/null
+++ b/core/modules/comment/lib/Drupal/comment/Entity/CommentType.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\comment\Entity\CommentType.
+ */
+
+namespace Drupal\comment\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\comment\CommentTypeInterface;
+
+/**
+ * Defines the comment type entity.
+ *
+ * @ConfigEntityType(
+ *   id = "comment_type",
+ *   label = @Translation("Comment type"),
+ *   controllers = {
+ *     "form" = {
+ *       "default" = "Drupal\comment\CommentTypeForm",
+ *       "add" = "Drupal\comment\CommentTypeForm",
+ *       "edit" = "Drupal\comment\CommentTypeForm",
+ *       "delete" = "Drupal\comment\Form\CommentTypeDeleteForm"
+ *     },
+ *     "list_builder" = "Drupal\comment\CommentTypeListBuilder"
+ *   },
+ *   admin_permission = "administer comment types",
+ *   config_prefix = "type",
+ *   bundle_of = "comment",
+ *   entity_keys = {
+ *     "id" = "id",
+ *     "label" = "label"
+ *   },
+ *   links = {
+ *     "delete-form" = "comment.type_delete",
+ *     "edit-form" = "comment.type_edit",
+ *     "add-form" = "comment.type_add"
+ *   }
+ * )
+ */
+class CommentType extends ConfigEntityBundleBase implements CommentTypeInterface {
+
+  /**
+   * The comment type ID.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The comment type label.
+   *
+   * @var string
+   */
+  public $label;
+
+  /**
+   * The description of the comment type.
+   *
+   * @var string
+   */
+  public $description;
+
+  /**
+   * The target entity type.
+   *
+   * @var string
+   */
+  public $targetEntityTypeId;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDescription() {
+    return $this->description;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setDescription($description) {
+    $this->description = $description;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTargetEntityTypeId() {
+    return $this->targetEntityTypeId;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
+    parent::postSave($storage, $update);
+    if (!$update && !$this->isSyncing()) {
+      \Drupal::service('comment.manager')->addBodyField($this->id());
+    }
+  }
+
+}
diff --git a/core/modules/comment/lib/Drupal/comment/Form/CommentTypeDeleteForm.php b/core/modules/comment/lib/Drupal/comment/Form/CommentTypeDeleteForm.php
new file mode 100644
index 0000000..c20577c
--- /dev/null
+++ b/core/modules/comment/lib/Drupal/comment/Form/CommentTypeDeleteForm.php
@@ -0,0 +1,138 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\comment\Form\CommentTypeDeleteForm.
+ */
+
+namespace Drupal\comment\Form;
+
+use Drupal\comment\CommentManagerInterface;
+use Drupal\Core\Entity\EntityConfirmFormBase;
+use Drupal\Core\Entity\EntityManager;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\Url;
+use Drupal\field\Entity\FieldConfig;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a confirmation form for deleting a comment type entity.
+ */
+class CommentTypeDeleteForm extends EntityConfirmFormBase {
+
+  /**
+   * The query factory to create entity queries.
+   *
+   * @var \Drupal\Core\Entity\Query\QueryFactory
+   */
+  public $queryFactory;
+
+  /**
+   * The comment manager service.
+   *
+   * @var \Drupal\comment\CommentManagerInterface
+   */
+  protected $commentManager;
+
+  /**
+   * The entity manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityManager
+   */
+  protected $entityManager;
+
+  /**
+   * The entity being used by this form.
+   *
+   * @var \Drupal\comment\CommentTypeInterface
+   */
+  protected $entity;
+
+  /**
+   * Constructs a query factory object.
+   *
+   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
+   *   The entity query object.
+   * @param \Drupal\comment\CommentManagerInterface $comment_manager
+   *   The comment manager service.
+   * @param \Drupal\Core\Entity\EntityManager $entity_manager
+   *   The entity manager service.
+   */
+  public function __construct(QueryFactory $query_factory, CommentManagerInterface $comment_manager, EntityManager $entity_manager) {
+    $this->queryFactory = $query_factory;
+    $this->commentManager = $comment_manager;
+    $this->entityManager = $entity_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity.query'),
+      $container->get('comment.manager'),
+      $container->get('entity.manager')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQuestion() {
+    return $this->t('Are you sure you want to delete %label?', array('%label' => $this->entity->label()));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCancelRoute() {
+    return new Url('comment.type_list');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfirmText() {
+    return $this->t('Delete');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state) {
+    $comments = $this->queryFactory->get('comment')->condition('comment_type', $this->entity->id())->execute();
+    $entity_type = $this->entity->getTargetEntityTypeId();
+    $caption = '';
+    foreach (array_keys($this->commentManager->getFields($entity_type)) as $field_name) {
+      /** @var \Drupal\field\FieldConfigInterface $field */
+      if (($field = FieldConfig::loadByName($entity_type, $field_name)) && $field->getSetting('comment_type') == $this->entity->id() && !$field->deleted) {
+        $caption .= '<p>' . $this->t('%label is used by the %field field on your site. You can not remove this comment type until you have removed the field.', array(
+          '%label' => $this->entity->label(),
+          '%field' => $field->label(),
+        )) . '</p>';
+      }
+    }
+
+    if (!empty($comments)) {
+      $caption .= '<p>' . $this->formatPlural(count($comments), '%label is used by 1 comment on your site. You can not remove this comment type until you have removed all of the %label comments.', '%label is used by @count comments on your site. You may not remove %label until you have removed all of the %label comments.', array('%label' => $this->entity->label())) . '</p>';
+    }
+    if ($caption) {
+      $form['description'] = array('#markup' => $caption);
+      return $form;
+    }
+    else {
+      return parent::buildForm($form, $form_state);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submit(array $form, array &$form_state) {
+    $this->entity->delete();
+    $form_state['redirect_route']['route_name'] = 'comment.type_list';
+    drupal_set_message(t('comment type %label has been deleted.', array('%label' => $this->entity->label())));
+    watchdog('comment', 'comment type %label has been deleted.', array('%label' => $this->entity->label()), WATCHDOG_NOTICE);
+  }
+
+}
diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php
index 50799b8..637f2a8 100644
--- a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php
+++ b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\comment\Plugin\Field\FieldType;
 
+use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\Field\FieldItemBase;
@@ -30,7 +31,7 @@ class CommentItem extends FieldItemBase implements CommentItemInterface {
    */
   public static function defaultSettings() {
     return array(
-      'description' => '',
+      'comment_type' => 'new',
     ) + parent::defaultSettings();
   }
 
@@ -102,16 +103,12 @@ public function instanceSettingsForm(array $form, array &$form_state) {
 
     $settings = $this->getSettings();
 
-    $entity_type = $this->getEntity()->getEntityTypeId();
-    $field_name = $this->getFieldDefinition()->getName();
     $anonymous_user = new AnonymousUserSession();
 
     $element['comment'] = array(
       '#type' => 'details',
       '#title' => t('Comment form settings'),
       '#open' => TRUE,
-      '#bundle' => "{$entity_type}__{$field_name}",
-      '#process' => array(array(get_class($this), 'processSettingsElement')),
       '#attributes' => array(
         'class' => array('comment-instance-settings-form'),
       ),
@@ -194,41 +191,100 @@ public function isEmpty() {
   }
 
   /**
-   * Process callback to add submit handler for instance settings form.
-   *
-   * Attaches the required translation entity handlers for the instance which
-   * correlates one to one with the comment bundle.
+   * {@inheritdoc}
    */
-  public static function processSettingsElement($element) {
-    // Settings should not be stored as nested.
-    $parents = $element['#parents'];
-    array_pop($parents);
-    $element['#parents'] = $parents;
-    // Add translation entity handlers.
-    if (\Drupal::moduleHandler()->moduleExists('content_translation')) {
-      $comment_form = $element;
-      $comment_form_state['content_translation']['key'] = 'language_configuration';
-      $element += content_translation_enable_widget('comment', $element['#bundle'], $comment_form, $comment_form_state);
-      $element['content_translation']['#parents'] = $element['content_translation']['#array_parents'] = array(
-        'content_translation'
-      );
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
+    $element = array();
+
+    // @todo Inject storage controller once typed-data supports container
+    //   injection.
+    $comment_types = entity_load_multiple('comment_type');
+    $options = array('new' => t('Create new'));
+    $entity_type = $this->getEntity()->getEntityTypeId();
+    foreach ($comment_types as $comment_type) {
+      if ($comment_type->getTargetEntityTypeId() == $entity_type) {
+        $options[$comment_type->id()] = $comment_type->label();
+      }
     }
+    $element['comment_type'] = array(
+      '#type' => 'select',
+      '#title' => t('Comment type'),
+      '#options' => $options,
+      '#description' => t('Select the Comment type to use for this comment field.'),
+      '#default_value' => $this->getSetting('comment_type'),
+      '#disabled' => $has_data,
+    );
+    $element['new_comment_type'] = array(
+      '#tree' => TRUE,
+      '#type' => 'fieldset',
+      '#title' => t('Create new comment type'),
+      '#states' => array(
+        'visible' => array(
+          ':input[name="field[settings][comment_type]"]' => array('value' => 'new'),
+        ),
+      ),
+    );
+    $element['new_comment_type']['label'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Label'),
+      '#maxlength' => 255,
+      '#default_value' => '',
+      '#description' => t("Provide a label for the new comment type to help identify it in the administration pages."),
+    );
+    $element['new_comment_type']['id'] = array(
+      '#type' => 'machine_name',
+      '#default_value' => '',
+      '#machine_name' => array(
+        'exists' => '\Drupal\comment\Entity\CommentType::load',
+        'source' => array(
+          'field', 'settings', 'new_comment_type', 'label',
+        ),
+      ),
+      '#required' => FALSE,
+      '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
+    );
+
+    $element['new_comment_type']['description'] = array(
+      '#type' => 'textarea',
+      '#default_value' => '',
+      '#description' => t('Enter a description for the new comment type.'),
+      '#title' => t('Description'),
+    );
+    $element['new_comment_type']['targetEntityTypeId'] = array(
+      '#type' => 'value',
+      '#value' => $entity_type,
+    );
+    $form['#submit'][] = array($this, 'createNewCommentType');
+    $form['#validate'][] = array($this, 'validateNewCommentType');
     return $element;
   }
 
   /**
-   * {@inheritdoc}
+   * Submit handler to create a new comment type if required.
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
-    $element = array();
+  public function createNewCommentType($form, &$form_state) {
+    $settings = $form_state['values']['field']['settings'];
+    if ($settings['comment_type'] == 'new') {
+      // @todo Inject this once typed-data supports ContainerInjectionInterface.
+      $comment_type = entity_create('comment_type', $settings['new_comment_type']);
+      $comment_type->save();
+      $form_state['values']['field']['settings']['comment_type'] = $comment_type->id();
+    }
+  }
 
-    $element['description'] = array(
-      '#type' => 'textarea',
-      '#title' => t('Field description'),
-      '#description' => t('Describe this comment field. The text will be displayed on the <em>Comments Forms</em> page.'),
-      '#default_value' => $this->getSetting('description'),
-    );
-    return $element;
+  /**
+   * Validation handler for creating a new comment type if required.
+   */
+  public function validateNewCommentType($form, &$form_state) {
+    $settings = $form_state['values']['field']['settings'];
+    if ($settings['comment_type'] == 'new') {
+      if (empty($settings['new_comment_type']['label'])) {
+        \Drupal::formBuilder()->setErrorByName('field][settings][new_comment_type][label', $form_state, t('Please provide a label for the new comment type'));
+      }
+      if (empty($settings['new_comment_type']['id'])) {
+        \Drupal::formBuilder()->setErrorByName('field][settings][new_comment_type][id', $form_state, t('Please provide a machine name for the new comment type'));
+      }
+    }
   }
 
 }
diff --git a/core/modules/comment/lib/Drupal/comment/Routing/CommentBundleEnhancer.php b/core/modules/comment/lib/Drupal/comment/Routing/CommentBundleEnhancer.php
deleted file mode 100644
index 783fcda..0000000
--- a/core/modules/comment/lib/Drupal/comment/Routing/CommentBundleEnhancer.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\comment\Routing\CommentBundleEnhancer.
- */
-
-namespace Drupal\comment\Routing;
-
-use Drupal\Core\Entity\EntityManagerInterface;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface;
-use Symfony\Cmf\Component\Routing\RouteObjectInterface;
-
-/**
- * Constructs a route enhancer to extract values from comment bundles.
- *
- * Comment bundle names are of the form {entity_type}__{field_name}. This
- * enhancer extracts them from the path and makes them available as arguments
- * to controllers.
- */
-class CommentBundleEnhancer implements RouteEnhancerInterface {
-
-  /**
-   * The entity manager service.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
-  /**
-   * Constructs a CommentBundleEnhancer object.
-   *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager service.
-   */
-  public function __construct(EntityManagerInterface $entity_manager) {
-    $this->entityManager = $entity_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function enhance(array $defaults, Request $request) {
-    if (isset($defaults['bundle']) && ($bundles = $this->entityManager->getBundleInfo('comment')) && isset($bundles[$defaults['bundle']])) {
-      list($entity_type, $field_name) = explode('__', $defaults['bundle'], 2);
-      $defaults['commented_entity_type'] = $entity_type;
-      $defaults['field_name'] = $field_name;
-    }
-    return $defaults;
-  }
-
-}
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentAdminTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentAdminTest.php
index 4f2f211..11d4113 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentAdminTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentAdminTest.php
@@ -157,11 +157,10 @@ public function testCommentAdmin() {
     // Login.
     $this->drupalLogin($this->admin_user);
     // Browse to comment bundle overview.
-    $this->drupalGet('admin/structure/comments');
+    $this->drupalGet('admin/structure/comment');
     $this->assertResponse(200);
     // Make sure titles visible.
-    $this->assertText('Field name');
-    $this->assertText('Used in');
+    $this->assertText('Comment type');
     $this->assertText('Description');
     // Make sure the description is present.
     $this->assertText('Default comment field');
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentDefaultFormatterCacheTagsTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentDefaultFormatterCacheTagsTest.php
index 3fe2a3f..7fb615a 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentDefaultFormatterCacheTagsTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentDefaultFormatterCacheTagsTest.php
@@ -56,25 +56,7 @@ public function setUp() {
 
     // Set up a field, so that the entity that'll be referenced bubbles up a
     // cache tag when rendering it entirely.
-    entity_create('field_config', array(
-      'name' => 'comment',
-      'entity_type' => 'entity_test',
-      'type' => 'comment',
-      'settings' => array(),
-    ))->save();
-    entity_create('field_instance_config', array(
-      'entity_type' => 'entity_test',
-      'bundle' => 'entity_test',
-      'field_name' => 'comment',
-      'label' => 'Comment',
-      'settings' => array(),
-    ))->save();
-    entity_get_display('entity_test', 'entity_test', 'default')
-      ->setComponent('comment', array(
-        'type' => 'comment_default',
-        'settings' => array(),
-      ))
-      ->save();
+    \Drupal::service('comment.manager')->addDefaultField('entity_test', 'entity_test');
   }
 
   /**
@@ -109,6 +91,7 @@ public function testCacheTags() {
       'entity_id' => $commented_entity->id(),
       'entity_type' => 'entity_test',
       'field_name' => 'comment',
+      'comment_type' => 'comment',
       'status' => CommentInterface::PUBLISHED,
       'uid' => $user->id(),
     ));
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php
index 86172a1..7582c93 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentFieldsTest.php
@@ -39,7 +39,7 @@ function testCommentDefaultFields() {
     $this->container->get('comment.manager')->addDefaultField('node', 'test_node_type');
 
     // Check that the 'comment_body' field is present on the comment bundle.
-    $instance = $this->container->get('field.info')->getInstance('comment', 'node__comment', 'comment_body');
+    $instance = $this->container->get('field.info')->getInstance('comment', 'comment', 'comment_body');
     $this->assertTrue(!empty($instance), 'The comment_body field is added when a comment bundle is created');
 
     $instance->delete();
@@ -58,10 +58,10 @@ function testCommentDefaultFields() {
     $field = $this->container->get('field.info')->getField('comment', 'comment_body');
     $this->assertTrue($field, 'The comment_body field exists');
     $instances = $this->container->get('field.info')->getInstances('comment');
-    $this->assertTrue(isset($instances['node__comment']['comment_body']), format_string('The comment_body field is present for comments on type @type', array('@type' => $type_name)));
+    $this->assertTrue(isset($instances['comment']['comment_body']), format_string('The comment_body field is present for comments on type @type', array('@type' => $type_name)));
 
     // Test adding a field that defaults to CommentItemInterface::CLOSED.
-    $this->container->get('comment.manager')->addDefaultField('node', 'test_node_type', 'who_likes_ponies', CommentItemInterface::CLOSED);
+    $this->container->get('comment.manager')->addDefaultField('node', 'test_node_type', 'who_likes_ponies', CommentItemInterface::CLOSED, 'who_likes_ponies');
     $field = entity_load('field_instance_config', 'node.test_node_type.who_likes_ponies');
     $this->assertEqual($field->default_value[0]['status'], CommentItemInterface::CLOSED);
   }
@@ -128,10 +128,10 @@ function testCommentFormat() {
     // Disable text processing for comments.
     $this->drupalLogin($this->admin_user);
     $edit = array('instance[settings][text_processing]' => 0);
-    $this->drupalPostForm('admin/structure/comments/manage/node__comment/fields/comment.node__comment.comment_body', $edit, t('Save settings'));
+    $this->drupalPostForm('admin/structure/comment/manage/comment/fields/comment.comment.comment_body', $edit, t('Save settings'));
 
     // Change formatter settings.
-    $this->drupalGet('admin/structure/comments/manage/node__comment/display');
+    $this->drupalGet('admin/structure/comment/manage/comment/display');
     $edit = array('fields[comment_body][type]' => 'text_trimmed', 'refresh_rows' => 'comment_body');
     $commands = $this->drupalPostAjaxForm(NULL, $edit, array('op' => t('Refresh')));
     $this->assertTrue($commands, 'Ajax commands returned');
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php
index 260834f..aa3d5aa 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLanguageTest.php
@@ -121,7 +121,7 @@ function testCommentLanguage() {
           ->fields('c', array('cid'))
           ->condition('entity_id', $node->id())
           ->condition('entity_type', 'node')
-          ->condition('field_id', 'node__comment')
+          ->condition('field_name', 'comment')
           ->orderBy('cid', 'DESC')
           ->range(0, 1)
           ->execute()
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentNonNodeTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentNonNodeTest.php
index dd0c0fe..d3c2ccd 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentNonNodeTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentNonNodeTest.php
@@ -39,12 +39,18 @@ function setUp() {
 
     // Create a bundle for entity_test.
     entity_test_create_bundle('entity_test', 'Entity Test', 'entity_test');
+    entity_create('comment_type', array(
+      'id' => 'comment',
+      'label' => 'Comment settings',
+      'description' => 'Comment settings',
+      'targetEntityTypeId' => 'entity_test',
+    ))->save();
     // Create comment field on entity_test bundle.
     $this->container->get('comment.manager')->addDefaultField('entity_test', 'entity_test');
 
     // Verify that bundles are defined correctly.
     $bundles = \Drupal::entityManager()->getBundleInfo('comment');
-    $this->assertEqual($bundles['entity_test__comment']['label'], 'Comment settings');
+    $this->assertEqual($bundles['comment']['label'], 'Comment settings');
 
     // Create test user.
     $this->admin_user = $this->drupalCreateUser(array(
@@ -362,10 +368,47 @@ function testCommentFunctionality() {
       'fields[_add_new_field][type]' => 'comment',
     );
     $this->drupalPostForm(NULL, $edit, t('Save'));
-    $this->drupalPostForm(NULL, array(), t('Save field settings'));
+    // Attempt to save with a new comment-type but incomplete form.
+    $this->drupalPostForm(NULL, array(
+      'field[settings][comment_type]' => 'new',
+    ), t('Save field settings'));
+    $this->assertText(t('Please provide a label for the new comment type'));
+    $this->assertText(t('Please provide a machine name for the new comment type'));
+    // Now provide the required values.
+    $this->drupalPostForm(NULL, array(
+      'field[settings][comment_type]' => 'new',
+      'field[settings][new_comment_type][id]' => 'foobar',
+      'field[settings][new_comment_type][label]' => 'Foobar',
+    ), t('Save field settings'));
+
     $this->drupalPostForm(NULL, array(), t('Save settings'));
     $this->assertRaw(t('Saved %name configuration', array('%name' => 'Foobar')));
 
+    // Check the new comment_type was created.
+    $comment_type = entity_load('comment_type', 'foobar');
+    $this->assertTrue($comment_type);
+    $this->assertEqual($comment_type->label(), 'Foobar');
+
+    // Add a third comment field.
+    $this->drupalGet('entity_test/structure/entity_test/fields');
+    $edit = array(
+      'fields[_add_new_field][label]' => 'Barfoo',
+      'fields[_add_new_field][field_name]' => 'barfoo',
+      'fields[_add_new_field][type]' => 'comment',
+    );
+    $this->drupalPostForm(NULL, $edit, t('Save'));
+    // Re-use another comment type.
+    $this->drupalPostForm(NULL, array(
+      'field[settings][comment_type]' => 'foobar',
+    ), t('Save field settings'));
+    $this->drupalPostForm(NULL, array(), t('Save settings'));
+    $this->assertRaw(t('Saved %name configuration', array('%name' => 'Barfoo')));
+
+    // Check the field contains the correct comment type.
+    $field = entity_load('field_config', 'entity_test.field_barfoo');
+    $this->assertTrue($field);
+    $this->assertEqual($field->getSetting('comment_type'), 'foobar');
+
     // Test the new entity commenting inherits default.
     $random_label = $this->randomName();
     $data = array('bundle' => 'entity_test', 'name' => $random_label);
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php
index c1edf13..ff6d2e3 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php
@@ -58,6 +58,7 @@ function setUp() {
     $this->admin_user = $this->drupalCreateUser(array(
       'administer content types',
       'administer comments',
+      'administer comment types',
       'administer comment fields',
       'administer comment display',
       'skip comment approval',
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php
index e79e165..3b1567e 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php
@@ -39,7 +39,7 @@ public static function getInfo() {
   function setUp() {
     $this->entityTypeId = 'comment';
     $this->nodeBundle = 'article';
-    $this->bundle = 'node__comment_article';
+    $this->bundle = 'comment_article';
     $this->testLanguageSelector = FALSE;
     $this->subject = $this->randomName();
     parent::setUp();
@@ -52,14 +52,14 @@ function setupBundle() {
     parent::setupBundle();
     $this->drupalCreateContentType(array('type' => $this->nodeBundle, 'name' => $this->nodeBundle));
     // Add a comment field to the article content type.
-    $this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment_article');
+    $this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment_article', CommentItemInterface::OPEN, 'comment_article');
     // Create a page content type.
     $this->drupalCreateContentType(array('type' => 'page', 'name' => 'page'));
     // Add a comment field to the page content type - this one won't be
     // translatable.
     $this->container->get('comment.manager')->addDefaultField('node', 'page', 'comment');
     // Mark this bundle as translatable.
-    content_translation_set_config('comment', 'node__comment_article', 'enabled', TRUE);
+    content_translation_set_config('comment', 'comment_article', 'enabled', TRUE);
     // Refresh entity info.
     entity_info_cache_clear();
   }
@@ -84,12 +84,8 @@ function setupTestFields() {
   /**
    * Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::createEntity().
    */
-  protected function createEntity($values, $langcode, $node_bundle = 'node__comment_article') {
-    // The argument is called 'node_bundle' but its actually just the entity
-    // bundle. Comment entity's bundle is of the form
-    // {entity_type}__{field_name}. Based on the passed bundle we need to
-    // determine the type of node and the name of the comment field.
-    if ($node_bundle == 'node__comment_article') {
+  protected function createEntity($values, $langcode, $comment_type = 'comment_article') {
+    if ($comment_type == 'comment_article') {
       // This is the article node type, with the 'comment_article' field.
       $node_type = 'article';
       $field_name = 'comment_article';
@@ -107,9 +103,9 @@ protected function createEntity($values, $langcode, $node_bundle = 'node__commen
     ));
     $values['entity_id'] = $node->id();
     $values['entity_type'] = 'node';
-    $values['field_id'] = $node_bundle;
+    $values['field_name'] = $field_name;
     $values['uid'] = $node->getOwnerId();
-    return parent::createEntity($values, $langcode, $node_bundle);
+    return parent::createEntity($values, $langcode, $comment_type);
   }
 
   /**
@@ -159,7 +155,7 @@ function testTranslateLinkCommentAdminPage() {
     $this->drupalLogin($this->admin_user);
 
     $cid_translatable = $this->createEntity(array(), $this->langcodes[0]);
-    $cid_untranslatable = $this->createEntity(array(), $this->langcodes[0], 'node__comment');
+    $cid_untranslatable = $this->createEntity(array(), $this->langcodes[0], 'comment');
 
     // Verify translation links.
     $this->drupalGet('admin/content/comment');
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTypeTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTypeTest.php
new file mode 100644
index 0000000..924b5e5
--- /dev/null
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTypeTest.php
@@ -0,0 +1,202 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\comment\Tests\CommentTypeTest.
+ */
+
+namespace Drupal\comment\Tests;
+use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
+use Drupal\field\Field;
+
+/**
+ * Tests related to custom comment types.
+ */
+class CommentTypeTest extends CommentTestBase {
+
+  /**
+   * Admin user
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $adminUser;
+
+  /**
+   * Permissions to grant admin user.
+   *
+   * @var array
+   */
+  protected $permissions = array(
+    'administer comments',
+    'administer comment fields',
+    'administer comment types',
+  );
+
+  /**
+   * Sets the test up.
+   */
+  public function setUp() {
+    parent::setUp();
+    $this->adminUser = $this->drupalCreateUser($this->permissions);
+  }
+
+  /**
+   * Declares test information.
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Comment types',
+      'description' => 'Ensures that comment type functions work correctly.',
+      'group' => 'Comment',
+    );
+  }
+
+  /**
+   * Tests creating a comment type programmatically and via a form.
+   */
+  public function testCommentTypeCreation() {
+    // Create a comment type programmaticaly.
+    $type = $this->createCommentType('other');
+
+    $comment_type = entity_load('comment_type', 'other');
+    $this->assertTrue($comment_type, 'The new comment type has been created.');
+
+    // Login a test user.
+    $this->drupalLogin($this->adminUser);
+
+    $this->drupalGet('admin/structure/comment/manage/' . $type->id());
+    $this->assertResponse(200, 'The new comment type can be accessed at the edit form.');
+
+    // Create a comment type via the user interface.
+    $edit = array(
+      'id' => 'foo',
+      'label' => 'title for foo',
+      'description' => '',
+      'targetEntityTypeId' => 'node',
+    );
+    $this->drupalPostForm('admin/structure/comment/types/add', $edit, t('Save'));
+    $comment_type = entity_load('comment_type', 'foo');
+    $this->assertTrue($comment_type, 'The new comment type has been created.');
+
+    // Check that the comment type was created in site default language.
+    $default_langcode = \Drupal::languageManager()->getDefaultLanguage()->id;
+    $this->assertEqual($comment_type->langcode, $default_langcode);
+  }
+
+  /**
+   * Tests editing a comment type using the UI.
+   */
+  public function testCommentTypeEditing() {
+    $this->drupalLogin($this->adminUser);
+
+    $instance = field_info_instance('comment', 'comment_body', 'comment');
+    $this->assertEqual($instance->getLabel(), 'Comment', 'Comment body field was found.');
+
+    // Change the comment type name.
+    $this->drupalGet('admin/structure/comment');
+    $edit = array(
+      'label' => 'Bar',
+    );
+    $this->drupalPostForm('admin/structure/comment/manage/comment', $edit, t('Save'));
+    field_info_cache_clear();
+
+    $this->drupalGet('admin/structure/comment');
+    $this->assertRaw('Bar', 'New name was displayed.');
+    $this->clickLink('Manage fields');
+    $this->assertEqual(url('admin/structure/comment/manage/comment/fields', array('absolute' => TRUE)), $this->getUrl(), 'Original machine name was used in URL.');
+
+    // Remove the body field.
+    $this->drupalPostForm('admin/structure/comment/manage/comment/fields/comment.comment.comment_body/delete', array(), t('Delete'));
+    // Resave the settings for this type.
+    $this->drupalPostForm('admin/structure/comment/manage/comment', array(), t('Save'));
+    // Check that the body field doesn't exist.
+    $this->drupalGet('admin/structure/comment/manage/comment/fields');
+    $this->assertNoRaw('comment_body', 'Body field was not found.');
+  }
+
+  /**
+   * Tests deleting a comment type that still has content.
+   */
+  public function testCommentTypeDeletion() {
+    // Create a comment type programmatically.
+    $type = $this->createCommentType('foo');
+    $this->drupalCreateContentType(array('type' => 'page'));
+    \Drupal::service('comment.manager')->addDefaultField('node', 'page', 'foo', CommentItemInterface::OPEN, 'foo');
+    $field = Field::fieldInfo()->getField('node', 'foo');
+
+    $this->drupalLogin($this->adminUser);
+
+    // Create a node.
+    $node = entity_create('node', array(
+      'type' => 'page',
+      'title' => 'foo'
+    ));
+    $node->save();
+
+    // Add a new comment of this type.
+    $comment = entity_create('comment', array(
+      'comment_type' => 'foo',
+      'entity_type' => 'node',
+      'field_name' => 'foo',
+      'entity_id' => $node->id(),
+    ));
+    $comment->save();
+
+    // Attempt to delete the comment type, which should not be allowed.
+    $this->drupalGet('admin/structure/comment/manage/' . $type->id() . '/delete');
+    $this->assertRaw(
+      t('%label is used by 1 comment on your site. You can not remove this comment type until you have removed all of the %label comments.', array('%label' => $type->label())),
+      'The comment type will not be deleted until all comments of that type are removed.'
+    );
+    $this->assertRaw(
+      t('%label is used by the %field field on your site. You can not remove this comment type until you have removed the field.', array(
+        '%label' => 'foo',
+        '%field' => 'node.foo',
+      )),
+      'The comment type will not be deleted until all fields of that type are removed.'
+    );
+    $this->assertNoText(t('This action cannot be undone.'), 'The comment type deletion confirmation form is not available.');
+
+    // Delete the comment and the field.
+    $comment->delete();
+    $field->delete();
+    // Attempt to delete the comment type, which should now be allowed.
+    $this->drupalGet('admin/structure/comment/manage/' . $type->id() . '/delete');
+    $this->assertRaw(
+      t('Are you sure you want to delete %type?', array('%type' => $type->id())),
+      'The comment type is available for deletion.'
+    );
+    $this->assertText(t('This action cannot be undone.'), 'The comment type deletion confirmation form is available.');
+
+    // Test exception thrown when re-using an existing comment type.
+    try {
+      \Drupal::service('comment.manager')->addDefaultField('comment', 'comment', 'bar');
+    }
+    catch (\InvalidArgumentException $e) {
+      $this->pass('Exception thrown if attempting to re-use comment-type from another entity type.');
+      return;
+    }
+    $this->fail('Exception not thrown.');
+  }
+
+  /**
+   * Creates a comment comment type (bundle).
+   *
+   * @param string $label
+   *   The comment type label.
+   *
+   * @return \Drupal\comment\Entity\CommentType
+   *   Created comment type.
+   */
+  protected function createCommentType($label) {
+    $bundle = entity_create('comment_type', array(
+      'id' => $label,
+      'label' => $label,
+      'description' => '',
+      'targetEntityTypeId' => 'node',
+    ));
+    $bundle->save();
+    return $bundle;
+  }
+
+}
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentValidationTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentValidationTest.php
index 03a0e82..168c875 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentValidationTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentValidationTest.php
@@ -46,11 +46,21 @@ public function setUp() {
    * Tests the comment validation constraints.
    */
   public function testValidation() {
+    // Add comment type.
+    $this->entityManager->getStorage('comment_type')->create(array(
+      'id' => 'comment',
+      'label' => 'comment',
+      'targetEntityTypeId' => 'node',
+    ))->save();
+
     // Add comment field to content.
     $this->entityManager->getStorage('field_config')->create(array(
       'entity_type' => 'node',
       'name' => 'comment',
       'type' => 'comment',
+      'settings' => array(
+        'comment_type' => 'comment',
+      )
     ))->save();
 
     // Create a page node type.
diff --git a/core/modules/comment/tests/Drupal/comment/Tests/Routing/CommentBundleEnhancerTest.php b/core/modules/comment/tests/Drupal/comment/Tests/Routing/CommentBundleEnhancerTest.php
deleted file mode 100644
index 95fbe8f..0000000
--- a/core/modules/comment/tests/Drupal/comment/Tests/Routing/CommentBundleEnhancerTest.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\comment\Tests\Routing\CommentBundleEnhancerTest.
- */
-namespace Drupal\comment\Tests\Routing;
-
-use Drupal\comment\Routing\CommentBundleEnhancer;
-use Drupal\Tests\UnitTestCase;
-use Symfony\Component\HttpFoundation\Request;
-
-/**
- * Tests the comment bundle enhancer route enhancer.
- *
- * @see \Drupal\comment\Routing\CommentBundleEnhancer
- */
-class CommentBundleEnhancerTest extends UnitTestCase {
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Comment route enhancer test',
-      'description' => 'Tests the comment route enhancer.',
-      'group' => 'Comment',
-    );
-  }
-
-  /**
-   * Data provider for testEnhancer().
-   *
-   * @see testEnhancer()
-   *
-   * @return array
-   *   An array of arrays containing strings:
-   *     - The bundle name.
-   *     - The commented entity type.
-   *     - The field name.
-   */
-  public function providerTestEnhancer() {
-    return array(
-      array(
-        'node__comment',
-        'comment',
-        'node',
-      ),
-      array(
-        'node__comment_forum__schnitzel',
-        'comment_forum__schnitzel',
-        'node',
-      ),
-      array(
-        'node__field_foobar',
-        FALSE,
-        FALSE
-      ),
-    );
-  }
-  /**
-   * Tests the enhancer method.
-   *
-   * @param string $bundle
-   *   The bundle name to test.
-   * @param string $field_name
-   *   The field name expected to be extracted from the bundle.
-   * @param string $commented_entity_type
-   *   The entity type expected to be extracted from the bundle.
-   *
-   * @see \Drupal\comment\Routing\CommentBundleEnhancer::enhancer()
-   *
-   * @group Drupal
-   * @group Routing
-   *
-   * @dataProvider providerTestEnhancer
-   */
-  public function testEnhancer($bundle, $field_name, $commented_entity_type) {
-    $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
-    $entity_manager->expects($this->any())
-      ->method('getBundleInfo')
-      ->will($this->returnValue(array(
-        'node__comment' => array(),
-        // Test two sets of __.
-        'node__comment_forum__schnitzel' => array(),
-      )));
-    $route_enhancer = new CommentBundleEnhancer($entity_manager);
-
-    // Test the enhancer.
-    $request = new Request();
-    $defaults = array('bundle' => $bundle);
-    $new_defaults = $route_enhancer->enhance($defaults, $request);
-    if ($commented_entity_type) {
-      // A valid comment bundle.
-      $this->assertEquals($new_defaults['field_name'], $field_name);
-      $this->assertEquals($new_defaults['commented_entity_type'], $commented_entity_type);
-    }
-    else {
-      // Non-comment bundle.
-      $this->assertTrue(empty($new_defaults['field_name']));
-      $this->assertTrue(empty($new_defaults['commented_entity_type']));
-    }
-  }
-
-}
diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php
index 059cb79..5de32fe 100644
--- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php
+++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSettingsTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\content_translation\Tests;
 
+use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
 use Drupal\Core\Language\Language;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\simpletest\WebTestBase;
@@ -38,9 +39,9 @@ function setUp() {
     // bundles.
     $this->drupalCreateContentType(array('type' => 'article'));
     $this->drupalCreateContentType(array('type' => 'page'));
-    $this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment_article');
+    $this->container->get('comment.manager')->addDefaultField('node', 'article', 'comment_article', CommentItemInterface::OPEN, 'comment_article');
 
-    $admin_user = $this->drupalCreateUser(array('access administration pages', 'administer languages', 'administer content translation', 'administer content types', 'administer node fields', 'administer comment fields'));
+    $admin_user = $this->drupalCreateUser(array('access administration pages', 'administer languages', 'administer content translation', 'administer content types', 'administer node fields', 'administer comment fields', 'administer comments', 'administer comment types'));
     $this->drupalLogin($admin_user);
   }
 
@@ -54,21 +55,21 @@ function testSettingsUI() {
     $this->assertText('Configure language and translation support for content.');
     // Test that the translation settings are ignored if the bundle is marked
     // translatable but the entity type is not.
-    $edit = array('settings[comment][node__comment_article][translatable]' => TRUE);
+    $edit = array('settings[comment][comment_article][translatable]' => TRUE);
     $this->assertSettings('comment', NULL, FALSE, $edit);
 
     // Test that the translation settings are ignored if only a field is marked
     // as translatable and not the related entity type and bundle.
-    $edit = array('settings[comment][node__comment_article][fields][comment_body]' => TRUE);
+    $edit = array('settings[comment][comment_article][fields][comment_body]' => TRUE);
     $this->assertSettings('comment', NULL, FALSE, $edit);
 
     // Test that the translation settings are not stored if an entity type and
     // bundle are marked as translatable but no field is.
     $edit = array(
       'entity_types[comment]' => TRUE,
-      'settings[comment][node__comment_article][translatable]' => TRUE,
+      'settings[comment][comment_article][translatable]' => TRUE,
     );
-    $this->assertSettings('comment', 'node__comment_article', FALSE, $edit);
+    $this->assertSettings('comment', 'comment_article', FALSE, $edit);
     $xpath_err = '//div[contains(@class, "error")]';
     $this->assertTrue($this->xpath($xpath_err), 'Enabling translation only for entity bundles generates a form error.');
 
@@ -76,37 +77,37 @@ function testSettingsUI() {
     // language is set as default and the language selector is hidden.
     $edit = array(
       'entity_types[comment]' => TRUE,
-      'settings[comment][node__comment_article][settings][language][langcode]' => Language::LANGCODE_NOT_SPECIFIED,
-      'settings[comment][node__comment_article][settings][language][language_show]' => FALSE,
-      'settings[comment][node__comment_article][translatable]' => TRUE,
-      'settings[comment][node__comment_article][fields][comment_body]' => TRUE,
+      'settings[comment][comment_article][settings][language][langcode]' => Language::LANGCODE_NOT_SPECIFIED,
+      'settings[comment][comment_article][settings][language][language_show]' => FALSE,
+      'settings[comment][comment_article][translatable]' => TRUE,
+      'settings[comment][comment_article][fields][comment_body]' => TRUE,
     );
-    $this->assertSettings('comment', 'node__comment_article', FALSE, $edit);
+    $this->assertSettings('comment', 'comment_article', FALSE, $edit);
     $this->assertTrue($this->xpath($xpath_err), 'Enabling translation with a fixed non-configurable language generates a form error.');
 
     // Test that a field shared among different bundles can be enabled without
     // needing to make all the related bundles translatable.
     $edit = array(
       'entity_types[comment]' => TRUE,
-      'settings[comment][node__comment_article][settings][language][langcode]' => 'current_interface',
-      'settings[comment][node__comment_article][settings][language][language_show]' => TRUE,
-      'settings[comment][node__comment_article][translatable]' => TRUE,
-      'settings[comment][node__comment_article][fields][comment_body]' => TRUE,
+      'settings[comment][comment_article][settings][language][langcode]' => 'current_interface',
+      'settings[comment][comment_article][settings][language][language_show]' => TRUE,
+      'settings[comment][comment_article][translatable]' => TRUE,
+      'settings[comment][comment_article][fields][comment_body]' => TRUE,
     );
-    $this->assertSettings('comment', 'node__comment_article', TRUE, $edit);
+    $this->assertSettings('comment', 'comment_article', TRUE, $edit);
     field_info_cache_clear();
     $field = FieldConfig::loadByName('comment', 'comment_body');
     $this->assertTrue($field->isTranslatable(), 'Comment body is translatable.');
 
     // Test that language settings are correctly stored.
-    $language_configuration = language_get_default_configuration('comment', 'node__comment_article');
+    $language_configuration = language_get_default_configuration('comment', 'comment_article');
     $this->assertEqual($language_configuration['langcode'], 'current_interface', 'The default language for article comments is set to the current interface language.');
     $this->assertTrue($language_configuration['language_show'], 'The language selector for article comments is shown.');
 
-    // Verify language widget appears on node type form.
-    $this->drupalGet('admin/structure/comments/manage/node__comment_article/fields/comment.node__comment_article.comment_body/field');
-    $this->assertField('field[translatable]');
-    $this->assertFieldChecked('edit-field-translatable');
+    // Verify language widget appears on comment type form.
+    $this->drupalGet('admin/structure/comment/manage/comment_article');
+    $this->assertField('language_configuration[content_translation]');
+    $this->assertFieldChecked('edit-language-configuration-content-translation');
 
     // Verify that translation may be enabled for the article content type.
     $edit = array(
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
index d347815..7766dcf 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
@@ -84,7 +84,7 @@ public static function schema(FieldStorageDefinitionInterface $field_definition)
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     $element = array();
 
     $element['datetime_type'] = array(
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
index e5ad209..36769ef 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
@@ -159,7 +159,7 @@ public static function schema(FieldStorageDefinitionInterface $field_definition)
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     $element['target_type'] = array(
       '#type' => 'select',
       '#title' => t('Type of item to reference'),
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php
index 19f5035..0742a6e 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php
@@ -454,7 +454,7 @@ public function testCommentHandler() {
           array(NULL, 'CONTAINS'),
         ),
         'result' => array(
-          'node__comment' => array(
+          'comment' => array(
             $comments['published_published']->cid->value => $comment_labels['published_published'],
           ),
         ),
@@ -464,7 +464,7 @@ public function testCommentHandler() {
           array('Published', 'CONTAINS'),
         ),
         'result' => array(
-          'node__comment' => array(
+          'comment' => array(
             $comments['published_published']->cid->value => $comment_labels['published_published'],
           ),
         ),
@@ -493,7 +493,7 @@ public function testCommentHandler() {
           array(NULL, 'CONTAINS'),
         ),
         'result' => array(
-          'node__comment' => array(
+          'comment' => array(
             $comments['published_published']->cid->value => $comment_labels['published_published'],
             $comments['published_unpublished']->cid->value => $comment_labels['published_unpublished'],
           ),
@@ -511,7 +511,7 @@ public function testCommentHandler() {
           array(NULL, 'CONTAINS'),
         ),
         'result' => array(
-          'node__comment' => array(
+          'comment' => array(
             $comments['published_published']->cid->value => $comment_labels['published_published'],
             $comments['published_unpublished']->cid->value => $comment_labels['published_unpublished'],
             $comments['unpublished_published']->cid->value => $comment_labels['unpublished_published'],
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php
index fcc599c..2d662fd 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php
@@ -77,7 +77,7 @@ public static function schema(FieldStorageDefinitionInterface $field_definition)
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     $form['test_field_setting'] = array(
       '#type' => 'textfield',
       '#title' => t('Field test field setting'),
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
index 068bd71..68e6849 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
@@ -151,6 +151,8 @@ public function buildForm(array $form, array &$form_state, FieldInstanceConfigIn
 
     $form['actions'] = array('#type' => 'actions');
     $form['actions']['submit'] = array('#type' => 'submit', '#value' => $this->t('Save field settings'));
+    $form['#submit'][] = array($this, 'submitForm');
+    $form['#validate'][] = array($this, 'validateForm');
     return $form;
   }
 
diff --git a/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php b/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php
index 27ce2ab..7f479dd 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php
@@ -106,7 +106,7 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     $element = array();
 
     $element['#attached']['library'][] = 'file/drupal.file';
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
index 416ea07..a75ae47 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileFieldWidgetTest.php
@@ -258,7 +258,7 @@ function testPrivateFileComment() {
       'fields[_add_new_field][field_name]' => $name = strtolower($this->randomName()),
       'fields[_add_new_field][type]' => 'file',
     );
-    $this->drupalPostForm('admin/structure/comments/manage/node__comment/fields', $edit, t('Save'));
+    $this->drupalPostForm('admin/structure/comment/manage/comment/fields', $edit, t('Save'));
     $edit = array('field[settings][uri_scheme]' => 'private');
     $this->drupalPostForm(NULL, $edit, t('Save field settings'));
     $this->drupalPostForm(NULL, array(), t('Save settings'));
diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install
index dafedba..1f5ed4f 100644
--- a/core/modules/forum/forum.install
+++ b/core/modules/forum/forum.install
@@ -4,6 +4,8 @@
  * @file
  * Install, update, and uninstall functions for the Forum module.
  */
+
+use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
 use Drupal\field\Entity\FieldConfig;
 
 /**
@@ -84,7 +86,7 @@ function forum_install() {
       'include_deleted' => FALSE,
     ));
     if (empty($fields)) {
-      Drupal::service('comment.manager')->addDefaultField('node', 'forum', 'comment_forum');
+      Drupal::service('comment.manager')->addDefaultField('node', 'forum', 'comment_forum', CommentItemInterface::OPEN, 'comment_forum');
     }
   }
 }
diff --git a/core/modules/forum/lib/Drupal/forum/ForumManager.php b/core/modules/forum/lib/Drupal/forum/ForumManager.php
index 2f1dff9..719ea92 100644
--- a/core/modules/forum/lib/Drupal/forum/ForumManager.php
+++ b/core/modules/forum/lib/Drupal/forum/ForumManager.php
@@ -170,7 +170,7 @@ public function getTopics($tid, AccountInterface $account) {
         ->extend('Drupal\Core\Database\Query\TableSortExtender');
       $query->fields('n', array('nid'));
 
-      $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_id = 'node__comment_forum' AND ces.entity_type = 'node'");
+      $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_name = 'comment_forum' AND ces.entity_type = 'node'");
       $query->fields('ces', array(
         'cid',
         'last_comment_uid',
@@ -341,7 +341,7 @@ protected function getLastPost($tid) {
     // Query "Last Post" information for this forum.
     $query = $this->connection->select('node_field_data', 'n');
     $query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $tid));
-    $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_id = 'node__comment_forum' AND ces.entity_type = 'node'");
+    $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_name = 'comment_forum' AND ces.entity_type = 'node'");
     $query->join('users', 'u', 'ces.last_comment_uid = u.uid');
     $query->addExpression('CASE ces.last_comment_uid WHEN 0 THEN ces.last_comment_name ELSE u.name END', 'last_comment_name');
 
@@ -379,7 +379,7 @@ protected function getForumStatistics($tid) {
     if (empty($this->forumStatistics)) {
       // Prime the statistics.
       $query = $this->connection->select('node_field_data', 'n');
-      $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_id = 'node__comment_forum' AND ces.entity_type = 'node'");
+      $query->join('comment_entity_statistics', 'ces', "n.nid = ces.entity_id AND ces.field_name = 'comment_forum' AND ces.entity_type = 'node'");
       $query->join('forum', 'f', 'n.vid = f.vid');
       $query->addExpression('COUNT(n.nid)', 'topic_count');
       $query->addExpression('SUM(ces.comment_count)', 'comment_count');
@@ -500,14 +500,14 @@ public function unreadTopics($term, $uid) {
    * {@inheritdoc}
    */
   public function updateIndex($nid) {
-    $count = $this->connection->query("SELECT COUNT(cid) FROM {comment} c INNER JOIN {forum_index} i ON c.entity_id = i.nid WHERE c.entity_id = :nid AND c.field_id = 'node__comment_forum' AND c.entity_type = 'node' AND c.status = :status", array(
+    $count = $this->connection->query("SELECT COUNT(cid) FROM {comment} c INNER JOIN {forum_index} i ON c.entity_id = i.nid WHERE c.entity_id = :nid AND c.field_name = 'comment_forum' AND c.entity_type = 'node' AND c.status = :status", array(
       ':nid' => $nid,
       ':status' => CommentInterface::PUBLISHED,
     ))->fetchField();
 
     if ($count > 0) {
       // Comments exist.
-      $last_reply = $this->connection->queryRange("SELECT cid, name, created, uid FROM {comment} WHERE entity_id = :nid AND field_id = 'node__comment_forum' AND entity_type = 'node' AND status = :status ORDER BY cid DESC", 0, 1, array(
+      $last_reply = $this->connection->queryRange("SELECT cid, name, created, uid FROM {comment} WHERE entity_id = :nid AND field_name = 'comment_forum' AND entity_type = 'node' AND status = :status ORDER BY cid DESC", 0, 1, array(
         ':nid' => $nid,
         ':status' => CommentInterface::PUBLISHED,
       ))->fetchObject();
diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php
index 130143f..3b38876 100644
--- a/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php
+++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumUninstallTest.php
@@ -77,7 +77,7 @@ function testForumUninstallWithField() {
     // We want to test the handling of removing the forum comment field, so we
     // ensure there is at least one other comment field attached to a node type
     // so that comment_entity_load() runs for nodes.
-    \Drupal::service('comment.manager')->addDefaultField('node', 'forum', 'another_comment_field', CommentItemInterface::OPEN);
+    \Drupal::service('comment.manager')->addDefaultField('node', 'forum', 'another_comment_field', CommentItemInterface::OPEN, 'another_comment_field');
 
     $this->drupalGet('node/' . $node->nid->value);
     $this->assertResponse(200);
diff --git a/core/modules/hal/lib/Drupal/hal/Tests/EntityTest.php b/core/modules/hal/lib/Drupal/hal/Tests/EntityTest.php
index bfbe6f1..c2873c8 100644
--- a/core/modules/hal/lib/Drupal/hal/Tests/EntityTest.php
+++ b/core/modules/hal/lib/Drupal/hal/Tests/EntityTest.php
@@ -54,6 +54,15 @@ public function testNode() {
     $user = entity_create('user', array('name' => $this->randomName()));
     $user->save();
 
+    // Add comment type.
+    $this->container->get('entity.manager')->getStorage('comment_type')->create(array(
+      'id' => 'comment',
+      'label' => 'comment',
+      'targetEntityTypeId' => 'node',
+    ))->save();
+
+    $this->container->get('comment.manager')->addDefaultField('node', 'example_type');
+
     $node = entity_create('node', array(
       'title' => $this->randomName(),
       'uid' => $user->id(),
@@ -129,6 +138,15 @@ public function testComment() {
     $user = entity_create('user', array('name' => $this->randomName()));
     $user->save();
 
+    // Add comment type.
+    $this->container->get('entity.manager')->getStorage('comment_type')->create(array(
+      'id' => 'comment',
+      'label' => 'comment',
+      'targetEntityTypeId' => 'node',
+    ))->save();
+
+    $this->container->get('comment.manager')->addDefaultField('node', 'example_type');
+
     $node = entity_create('node', array(
       'title' => $this->randomName(),
       'uid' => $user->id(),
@@ -143,8 +161,6 @@ public function testComment() {
     ));
     $node->save();
 
-    $this->container->get('comment.manager')->addDefaultField('node', 'example_type');
-
     $comment = entity_create('comment', array(
       'uid' => $user->id(),
       'subject' => $this->randomName(),
diff --git a/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php
index 249933e..17f8ce5 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php
@@ -152,7 +152,7 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     $element = array();
 
     // We need the field-level 'default_image' setting, and $this->getSettings()
diff --git a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityComment.php b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityComment.php
index 42d3723..7066970 100644
--- a/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityComment.php
+++ b/core/modules/migrate/lib/Drupal/migrate/Plugin/migrate/destination/EntityComment.php
@@ -80,6 +80,8 @@ public static function create(ContainerInterface $container, array $configuratio
   public function import(Row $row, array $old_destination_id_values = array()) {
     if (($stub = !$row->getSourceProperty('entity_type')) && ($state = $this->state->get('comment.maintain_entity_statistics', 0))) {
       $this->state->set('comment.maintain_entity_statistics', 0);
+      // Set default bundle.
+      $row->setDestinationProperty('comment_type', 'comment');
     }
     $return = parent::import($row, $old_destination_id_values);
     if ($stub && $state) {
diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment.yml
index 961cb40..34e681e 100644
--- a/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment.yml
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment.yml
@@ -3,7 +3,8 @@ label: Drupal 6 comments
 source:
   plugin: d6_comment
   constants:
-    field_id: node__comment
+    field_name: comment
+    comment_type: comment
     entity_type: node
 process:
   cid: cid
@@ -19,7 +20,8 @@ process:
     migration: d6_node
     source: nid
   entity_type: constants.entity_type
-  field_id: constants.field_id
+  field_name: constants.field_name
+  comment_type: constants.comment_type
   subject: subject
   uid:
     -
@@ -44,6 +46,8 @@ process:
 destination:
   plugin: entity:comment
 migration_dependencies:
+  optional:
+    - d6_comment_type
   required:
     - d6_node
     - d6_user
diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment_field.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment_field.yml
index 5c4dd3b..2a5ccc4 100644
--- a/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment_field.yml
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment_field.yml
@@ -7,10 +7,13 @@ source:
     type: comment
     id: node.comment
     name: comment
+    settings:
+      content_type: comment
 process:
   entity_type: constants.entity_type
   id: constants.id
   name: constants.name
   type: constants.type
+  settings: constants.settings
 destination:
   plugin: entity:field_config
diff --git a/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment_type.yml b/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment_type.yml
new file mode 100644
index 0000000..b183580
--- /dev/null
+++ b/core/modules/migrate_drupal/config/install/migrate.migration.d6_comment_type.yml
@@ -0,0 +1,18 @@
+id: d6_comment_type
+label: Drupal 6 comment type
+source:
+  plugin: variable
+  variables:
+    - site_name
+  constants:
+    entity_type: node
+    id: comment
+    label: comment
+    description: comment
+process:
+  targetEntityTypeId: constants.entity_type
+  id: constants.id
+  label: constants.label
+  description: constants.description
+destination:
+  plugin: entity:comment_type
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentTest.php
index 409f6d2..ffc3752 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentTest.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentTest.php
@@ -37,6 +37,12 @@ public static function getInfo() {
   public function setUp() {
     parent::setUp();
     entity_create('node_type', array('type' => 'page'))->save();
+    $this->container->get('entity.manager')->getStorage('comment_type')->create(array(
+      'id' => 'comment',
+      'label' => 'comment',
+      'targetEntityTypeId' => 'node',
+    ))->save();
+
     $node = entity_create('node', array(
       'type' => 'page',
       'nid' => 1,
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentTypeTest.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentTypeTest.php
new file mode 100644
index 0000000..363cf42
--- /dev/null
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateCommentTypeTest.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate_drupal\Tests\d6\MigrateCommentTypeTest.
+ */
+
+namespace Drupal\migrate_drupal\Tests\d6;
+
+use Drupal\comment\Entity\Comment;
+use Drupal\Core\Language\Language;
+use Drupal\migrate\MigrateExecutable;
+use Drupal\migrate_drupal\Tests\MigrateDrupalTestBase;
+
+/**
+ * Tests the Drupal 6 to Drupal 6 comment type migration.
+ */
+class MigrateCommentTypeTest extends MigrateDrupalTestBase {
+
+  static $modules = array('node', 'comment');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name'  => 'Migrate comment type.',
+      'description'  => 'Upgrade comment type.',
+      'group' => 'Migrate Drupal',
+    );
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+
+    /** @var \Drupal\migrate\entity\Migration $migration */
+    $migration = entity_load('migration', 'd6_comment_type');
+
+    $dumps = array(
+      $this->getDumpDirectory() . '/Drupal6SystemSite.php',
+    );
+    $this->prepare($migration, $dumps);
+    $executable = new MigrateExecutable($migration, $this);
+    $executable->import();
+  }
+
+  /**
+   * Tests the Drupal 6 to Drupal 6 comment type migration.
+   */
+  public function testCommentType() {
+    $comment_type = entity_load('comment_type', 'comment');
+    $this->assertEqual('node', $comment_type->getTargetEntityTypeId());
+  }
+}
diff --git a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDrupal6Test.php b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDrupal6Test.php
index adcf35b..4ce626e 100644
--- a/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDrupal6Test.php
+++ b/core/modules/migrate_drupal/lib/Drupal/migrate_drupal/Tests/d6/MigrateDrupal6Test.php
@@ -61,6 +61,7 @@ class MigrateDrupal6Test extends MigrateFullDrupalTestBase {
     'd6_book_settings',
     'd6_cck_field_values:*',
     'd6_cck_field_revision:*',
+    'd6_comment_type',
     'd6_comment',
     'd6_comment_entity_display',
     'd6_comment_entity_form_display',
@@ -228,6 +229,7 @@ protected function getTestClassesList() {
       __NAMESPACE__ . '\MigrateBookConfigsTest',
       __NAMESPACE__ . '\MigrateCckFieldValuesTest',
       __NAMESPACE__ . '\MigrateCckFieldRevisionTest',
+      __NAMESPACE__ . '\MigrateCommentTypeTest',
       __NAMESPACE__ . '\MigrateCommentTest',
       __NAMESPACE__ . '\MigrateCommentVariableEntityDisplay',
       __NAMESPACE__ . '\MigrateCommentVariableEntityFormDisplay',
diff --git a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListBooleanItem.php b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListBooleanItem.php
index 095c89c..5d16585 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListBooleanItem.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListBooleanItem.php
@@ -102,7 +102,7 @@ public function isEmpty() {
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     $allowed_values = $this->getSetting('allowed_values');
     $allowed_values_function = $this->getSetting('allowed_values_function');
 
diff --git a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListItemBase.php b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListItemBase.php
index 64604e5..d61aef1 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListItemBase.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/Field/FieldType/ListItemBase.php
@@ -72,7 +72,7 @@ public function isEmpty() {
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     $allowed_values = $this->getSetting('allowed_values');
     $allowed_values_function = $this->getSetting('allowed_values_function');
 
diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php
index f152e0b..8157e35 100644
--- a/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php
+++ b/core/modules/rdf/lib/Drupal/rdf/Tests/CommentAttributesTest.php
@@ -68,7 +68,7 @@ public function setUp() {
     $user_mapping->setFieldMapping('homepage', array('properties' => array('foaf:page'), 'mapping_type' => 'rel'))->save();
 
     // Save comment mapping.
-    $mapping = rdf_get_mapping('comment', 'node__comment');
+    $mapping = rdf_get_mapping('comment', 'comment');
     $mapping->setBundleMapping(array('types' => array('sioc:Post', 'sioct:Comment')))->save();
     $field_mappings = array(
       'subject' => array(
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php
index cc8ef7e..fb6a93e 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Field/FieldType/TaxonomyTermReferenceItem.php
@@ -119,7 +119,7 @@ public static function schema(FieldStorageDefinitionInterface $field_definition)
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     $vocabularies = entity_load_multiple('taxonomy_vocabulary');
     $options = array();
     foreach ($vocabularies as $vocabulary) {
diff --git a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItem.php b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItem.php
index b2ba0a1..6bacea6 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItem.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItem.php
@@ -78,7 +78,7 @@ public function getConstraints() {
   /**
    * {@inheritdoc}
    */
-  public function settingsForm(array $form, array &$form_state, $has_data) {
+  public function settingsForm(array &$form, array &$form_state, $has_data) {
     $element = array();
 
     $element['max_length'] = array(
diff --git a/core/profiles/standard/config/install/comment.type.comment.yml b/core/profiles/standard/config/install/comment.type.comment.yml
new file mode 100644
index 0000000..ee77bbe
--- /dev/null
+++ b/core/profiles/standard/config/install/comment.type.comment.yml
@@ -0,0 +1,9 @@
+id: comment
+label: comment
+description: 'Default comment field'
+targetEntityTypeId: node
+status: true
+langcode: en
+dependencies:
+  entity:
+    - comment.type.comment
diff --git a/core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml b/core/profiles/standard/config/install/rdf.mapping.comment.comment.yml
similarity index 87%
rename from core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml
rename to core/profiles/standard/config/install/rdf.mapping.comment.comment.yml
index 70f25b1..00abf0c 100644
--- a/core/profiles/standard/config/install/rdf.mapping.comment.node__comment.yml
+++ b/core/profiles/standard/config/install/rdf.mapping.comment.comment.yml
@@ -1,6 +1,6 @@
-id: comment.node__comment
+id: comment.comment
 targetEntityType: comment
-bundle: node__comment
+bundle: comment
 types:
   - 'schema:Comment'
 fieldMappings:
@@ -27,3 +27,5 @@ fieldMappings:
 dependencies:
   module:
     - comment
+  entity:
+    - comment.type.comment
