diff --git a/core/modules/comment/comment.links.menu.yml b/core/modules/comment/comment.links.menu.yml
index e4d4488..94a2ad6 100644
--- a/core/modules/comment/comment.links.menu.yml
+++ b/core/modules/comment/comment.links.menu.yml
@@ -2,7 +2,7 @@ comment.admin:
   title: Comments
   route_name: comment.admin
   parent: system.admin_content
-  description: 'List and edit site comments and the comment approval queue.'
+  description: 'List and edit site comments and the comment unpublished queue.'
 comment.type_list:
   title: 'Comment types'
   route_name: comment.type_list
diff --git a/core/modules/comment/comment.links.task.yml b/core/modules/comment/comment.links.task.yml
index a976171..9cfed06 100644
--- a/core/modules/comment/comment.links.task.yml
+++ b/core/modules/comment/comment.links.task.yml
@@ -23,10 +23,10 @@ comment.admin_new:
   route_name: comment.admin
   parent_id: comment.admin
 
-comment.admin_approval:
-  title: 'Unapproved comments'
-  route_name: comment.admin_approval
-  class: Drupal\comment\Plugin\Menu\LocalTask\UnapprovedComments
+comment.admin_unpublished:
+  title: 'Unpublished comments'
+  route_name: comment.admin_unpublished
+  class: Drupal\comment\Plugin\Menu\LocalTask\UnpublishedComments
   parent_id: comment.admin
   weight: 1
 
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index bdf53bf..cb84bad 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -73,7 +73,7 @@ function comment_help($route_name, RouteMatchInterface $route_match) {
       $output .= '<dt>' . t('Overriding default settings') . '</dt>';
       $output .= '<dd>' . t('When you create an entity item, you can override the default comment settings. Changing the entity sub-type defaults will not affect existing entity items, whether they used the default settings or had overrides.') . '</dd>';
       $output .= '<dt>' . t('Approving and managing comments') . '</dt>';
-      $output .= '<dd>' . t('Comments from users who have the <em>Skip comment approval</em> permission are published immediately. All other comments are placed in the <a href="!comment-approval">Unapproved comments</a> queue, until a user who has permission to <em>Administer comments and comment settings</em> publishes or deletes them. Published comments can be bulk managed on the <a href="!admin-comment">Published comments</a> administration page. When a comment has no replies, it remains editable by its author, as long as the author has <em>Edit own comments</em> permission.', array('!comment-approval' => \Drupal::url('comment.admin_approval'), '!admin-comment' => \Drupal::url('comment.admin'))) . '</dd>';
+      $output .= '<dd>' . t('Comments from users who have the <em>Skip comment approval</em> permission are published immediately. All other comments are placed in the <a href="!comment-approval">Unpublished comments</a> queue, until a user who has permission to <em>Administer comments and comment settings</em> publishes or deletes them. Published comments can be bulk managed on the <a href="!admin-comment">Published comments</a> administration page. When a comment has no replies, it remains editable by its author, as long as the author has <em>Edit own comments</em> permission.', array('!comment-approval' => \Drupal::url('comment.admin_unpublished'), '!admin-comment' => \Drupal::url('comment.admin'))) . '</dd>';
       $output .= '</dl>';
       return $output;
 
diff --git a/core/modules/comment/comment.routing.yml b/core/modules/comment/comment.routing.yml
index ca37c61..57b25fe 100644
--- a/core/modules/comment/comment.routing.yml
+++ b/core/modules/comment/comment.routing.yml
@@ -7,12 +7,12 @@ comment.admin:
   requirements:
     _permission: 'administer comments'
 
-comment.admin_approval:
-  path: '/admin/content/comment/approval'
+comment.admin_unpublished:
+  path: '/admin/content/comment/unpublished'
   defaults:
-    _title: 'Unapproved comments'
+    _title: 'Unpublished comments'
     _content: '\Drupal\comment\Controller\AdminController::adminPage'
-    type: 'approval'
+    type: 'unpublished'
   requirements:
     _permission: 'administer comments'
 
@@ -24,14 +24,24 @@ entity.comment.edit_form:
   requirements:
     _entity_access: 'comment.update'
 
-comment.approve:
-  path: '/comment/{comment}/approve'
+comment.publish:
+  path: '/comment/{comment}/publish'
   defaults:
-    _title: 'Approve'
-    _content: '\Drupal\comment\Controller\CommentController::commentApprove'
+    _title: 'Publish'
+    _content: '\Drupal\comment\Controller\CommentController::commentPublish'
     entity_type: 'comment'
   requirements:
-    _entity_access: 'comment.approve'
+    _entity_access: 'comment.publish'
+    _csrf_token: 'TRUE'
+
+comment.unpublish:
+  path: '/comment/{comment}/unpublish'
+  defaults:
+    _title: 'Unpublish'
+    _content: '\Drupal\comment\Controller\CommentController::commentUnpublish'
+    entity_type: 'comment'
+  requirements:
+    _entity_access: 'comment.unpublish'
     _csrf_token: 'TRUE'
 
 entity.comment.canonical:
diff --git a/core/modules/comment/comment.views.inc b/core/modules/comment/comment.views.inc
index cdd7ec0..1c72b16 100644
--- a/core/modules/comment/comment.views.inc
+++ b/core/modules/comment/comment.views.inc
@@ -6,6 +6,621 @@
  */
 
 /**
+ * Implements hook_views_data().
+ */
+function comment_views_data() {
+
+  // Define the base group of this table. Fields that don't have a group defined
+  // will go into this field by default.
+  $data['comment']['table']['group']  = t('Comment');
+
+  $data['comment']['table']['base'] = array(
+    'field' => 'cid',
+    'title' => t('Comment'),
+    'help' => t("Comments are responses to node content."),
+    'access query tag' => 'comment_access',
+  );
+  $data['comment']['table']['entity type'] = 'comment';
+  $data['comment']['table']['wizard_id'] = 'comment';
+
+  $data['comment_field_data']['table']['group'] = t('Comment');
+  $data['comment_field_data']['table']['entity type'] = 'comment';
+  $data['comment_field_data']['table']['join']['comment'] = array(
+    'type' => 'INNER',
+    'left_field' => 'cid',
+    'field' => 'cid',
+  );
+
+  $data['comment_field_data']['subject'] = array(
+    'title' => t('Title'),
+    'help' => t('The title of the comment.'),
+    'field' => array(
+      'id' => 'comment',
+    ),
+    'filter' => array(
+      'id' => 'string',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+    'argument' => array(
+      'id' => 'string',
+    ),
+  );
+
+  $data['comment']['cid'] = array(
+    'title' => t('ID'),
+    'help' => t('The comment ID of the field'),
+    'field' => array(
+      'id' => 'comment',
+    ),
+    'filter' => array(
+      'id' => 'numeric',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+    'argument' => array(
+      'id' => 'numeric',
+    ),
+  );
+
+  $data['comment_field_data']['name'] = array(
+    'title' => t('Author'),
+    'help' => t("The name of the comment's author. Can be rendered as a link to the author's homepage."),
+    'field' => array(
+      'id' => 'comment_username',
+    ),
+    'filter' => array(
+      'id' => 'string',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+    'argument' => array(
+      'id' => 'string',
+    ),
+  );
+
+  $data['comment_field_data']['homepage'] = array(
+    'title' => t("Author's website"),
+    'help' => t("The website address of the comment's author. Can be rendered as a link. Will be empty if the author is a registered user."),
+    'field' => array(
+      'id' => 'url',
+    ),
+    'filter' => array(
+      'id' => 'string',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+    'argument' => array(
+      'id' => 'string',
+    ),
+  );
+
+  $data['comment_field_data']['hostname'] = array(
+    'title' => t('Hostname'),
+    'help' => t('Hostname of user that posted the comment.'),
+    'field' => array(
+      'id' => 'standard',
+    ),
+    'filter' => array(
+      'id' => 'string',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+    'argument' => array(
+      'id' => 'string',
+    ),
+  );
+
+  $data['comment_field_data']['mail'] = array(
+    'title' => t('Email'),
+    'help' => t('Email of user that posted the comment. Will be empty if the author is a registered user.'),
+    'field' => array(
+      'id' => 'standard',
+    ),
+    'filter' => array(
+      'id' => 'string',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+    'argument' => array(
+      'id' => 'string',
+    ),
+  );
+
+  $data['comment_field_data']['created'] = array(
+    'title' => t('Post date'),
+    'help' => t('Date and time of when the comment was created.'),
+    'field' => array(
+      'id' => 'date',
+    ),
+    'sort' => array(
+      'id' => 'date',
+    ),
+    'filter' => array(
+      'id' => 'date',
+    ),
+  );
+
+  if (\Drupal::moduleHandler()->moduleExists('language')) {
+    $data['comment']['langcode'] = array(
+      'title' => t('Language'),
+      'help' => t('The language the comment is in.'),
+      'field' => array(
+        'id' => 'language',
+      ),
+      'filter' => array(
+        'id' => 'language',
+      ),
+      'argument' => array(
+        'id' => 'language',
+      ),
+      'sort' => array(
+        'id' => 'standard',
+      ),
+    );
+  }
+
+  $data['comment_field_data']['changed'] = array(
+    'title' => t('Updated date'),
+    'help' => t('Date and time of when the comment was last updated.'),
+    'field' => array(
+      'id' => 'date',
+    ),
+    'sort' => array(
+      'id' => 'date',
+    ),
+    'filter' => array(
+      'id' => 'date',
+    ),
+  );
+
+  $data['comment_field_data']['changed_fulldata'] = array(
+    'title' => t('Created date'),
+    'help' => t('Date in the form of CCYYMMDD.'),
+    'argument' => array(
+      'field' => 'changed',
+      'id' => 'date_fulldate',
+    ),
+  );
+
+  $data['comment_field_data']['changed_year_month'] = array(
+    'title' => t('Created year + month'),
+    'help' => t('Date in the form of YYYYMM.'),
+    'argument' => array(
+      'field' => 'changed',
+      'id' => 'date_year_month',
+    ),
+  );
+
+  $data['comment_field_data']['changed_year'] = array(
+    'title' => t('Created year'),
+    'help' => t('Date in the form of YYYY.'),
+    'argument' => array(
+      'field' => 'changed',
+      'id' => 'date_year',
+    ),
+  );
+
+  $data['comment_field_data']['changed_month'] = array(
+    'title' => t('Created month'),
+    'help' => t('Date in the form of MM (01 - 12).'),
+    'argument' => array(
+      'field' => 'changed',
+      'id' => 'date_month',
+    ),
+  );
+
+  $data['comment_field_data']['changed_day'] = array(
+    'title' => t('Created day'),
+    'help' => t('Date in the form of DD (01 - 31).'),
+    'argument' => array(
+      'field' => 'changed',
+      'id' => 'date_day',
+    ),
+  );
+
+  $data['comment_field_data']['changed_week'] = array(
+    'title' => t('Created week'),
+    'help' => t('Date in the form of WW (01 - 53).'),
+    'argument' => array(
+      'field' => 'changed',
+      'id' => 'date_week',
+    ),
+  );
+
+  $data['comment_field_data']['status'] = array(
+    'title' => t('Published status'),
+    'help' => t('Whether or not the comment is published.'),
+    'field' => array(
+      'id' => 'boolean',
+      'output formats' => array(
+        'published-notpublished' => array(t('Published'), t('Not published')),
+      ),
+    ),
+    'filter' => array(
+      'id' => 'boolean',
+      'label' => t('Published status'),
+      'type' => 'yes-no',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+  );
+
+  $data['comment']['view_comment'] = array(
+    'field' => array(
+      'title' => t('Link to comment'),
+      'help' => t('Provide a simple link to view the comment.'),
+      'id' => 'comment_link',
+    ),
+  );
+
+  $data['comment']['edit_comment'] = array(
+    'field' => array(
+      'title' => t('Link to edit comment'),
+      'help' => t('Provide a simple link to edit the comment.'),
+      'id' => 'comment_link_edit',
+    ),
+  );
+
+  $data['comment']['delete_comment'] = array(
+    'field' => array(
+      'title' => t('Link to delete comment'),
+      'help' => t('Provide a simple link to delete the comment.'),
+      'id' => 'comment_link_delete',
+    ),
+  );
+
+  $data['comment']['publish_comment'] = array(
+    'field' => array(
+      'title' => t('Link to publish comment'),
+      'help' => t('Provide a simple link to publish the comment.'),
+      'id' => 'comment_link_publish',
+    ),
+  );
+
+  $data['comment']['unpublish_comment'] = array(
+    'field' => array(
+      'title' => t('Link to unpublish comment'),
+      'help' => t('Provide a simple link to unpublish the comment.'),
+      'id' => 'comment_link_unpublish',
+    ),
+  );
+
+  $data['comment']['replyto_comment'] = array(
+    'field' => array(
+      'title' => t('Link to reply-to comment'),
+      'help' => t('Provide a simple link to reply to the comment.'),
+      'id' => 'comment_link_reply',
+    ),
+  );
+
+  $data['comment_field_data']['thread'] = array(
+    'field' => array(
+      'title' => t('Depth'),
+      'help' => t('Display the depth of the comment if it is threaded.'),
+      'id' => 'comment_depth',
+    ),
+    'sort' => array(
+      'title' => t('Thread'),
+      'help' => t('Sort by the threaded order. This will keep child comments together with their parents.'),
+      'id' => 'comment_thread',
+    ),
+  );
+
+  $data['comment_field_data']['entity_id'] = array(
+    'title' => t('Entity ID'),
+    'help' => t('The Entity ID to which the comment is a reply to.'),
+    'field' => array(
+      'id' => 'standard',
+    ),
+    'filter' => array(
+      'id' => 'numeric',
+    ),
+    'argument' => array(
+      'id' => 'numeric',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+  );
+
+  $data['comment_field_data']['entity_type'] = array(
+    'title' => t('Entity type'),
+    'help' => t('The Entity type to which the comment is a reply to.'),
+    'field' => array(
+      'id' => 'standard',
+    ),
+    'filter' => array(
+      'id' => 'string',
+    ),
+    'argument' => array(
+      'id' => 'string',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+  );
+
+  $data['comment_field_data']['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',
+    ),
+    'filter' => array(
+      'id' => 'string',
+    ),
+    'argument' => array(
+      'id' => 'string',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+  );
+
+  $entities_types = \Drupal::entityManager()->getDefinitions();
+
+  // Provide a relationship for each entity type except comment.
+  foreach ($entities_types as $type => $entity_type) {
+    if ($type == 'comment' || !$entity_type->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface') || !$entity_type->getBaseTable()) {
+      continue;
+    }
+    if ($fields = \Drupal::service('comment.manager')->getFields($type)) {
+      $data['comment_field_data'][$type] = array(
+        'relationship' => array(
+          'title' => $entity_type->getLabel(),
+          'help' => t('The @entity_type to which the comment is a reply to.', array('@entity_type' => $entity_type->getLabel())),
+          'base' => $entity_type->getBaseTable(),
+          'base field' => $entity_type->getKey('id'),
+          'relationship field' => 'entity_id',
+          'id' => 'standard',
+          'label' => $entity_type->getLabel(),
+          'extra' => array(
+            array(
+              'field' => 'entity_type',
+              'value' => $type,
+              'table' => 'comment_field_data'
+            ),
+          ),
+        ),
+      );
+    }
+  }
+
+  $data['comment_field_data']['uid'] = array(
+    'title' => t('Author uid'),
+    'help' => t('If you need more fields than the uid add the comment: author relationship'),
+    'relationship' => array(
+      'title' => t('Author'),
+      'help' => t("The User ID of the comment's author."),
+      'base' => 'users',
+      'base field' => 'uid',
+      'id' => 'standard',
+      'label' => t('author'),
+    ),
+    'filter' => array(
+      'id' => 'numeric',
+    ),
+    'argument' => array(
+      'id' => 'numeric',
+    ),
+    'field' => array(
+      'id' => 'user',
+    ),
+  );
+
+  $data['comment_field_data']['pid'] = array(
+    'title' => t('Parent CID'),
+    'help' => t('The Comment ID of the parent comment.'),
+    'field' => array(
+      'id' => 'standard',
+    ),
+    'relationship' => array(
+      'title' => t('Parent comment'),
+      'help' => t('The parent comment.'),
+      'base' => 'comment',
+      'base field' => 'cid',
+      'id' => 'standard',
+      'label' => t('Parent comment'),
+    ),
+  );
+
+  if (\Drupal::moduleHandler()->moduleExists('content_translation')) {
+    $data['comment']['translation_link'] = array(
+      'title' => t('Translation link'),
+      'help' => t('Provide a link to the translations overview for comments.'),
+      'field' => array(
+        'id' => 'content_translation_link',
+      ),
+    );
+  }
+
+  // Define the base group of this table. Fields that don't have a group defined
+  // will go into this field by default.
+  $data['comment_entity_statistics']['table']['group']  = t('Comment Statistics');
+
+  // Provide a relationship for each entity type except comment.
+  foreach ($entities_types as $type => $entity_type) {
+    if ($type == 'comment' || !$entity_type->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface') || !$entity_type->getBaseTable()) {
+      continue;
+    }
+    // This relationship does not use the 'field id' column, if the entity has
+    // multiple comment-fields, then this might introduce duplicates, in which
+    // case the site-builder should enable aggregation and SUM the comment_count
+    // field. We cannot create a relationship from the base table to
+    // {comment_entity_statistics} for each field as multiple joins between
+    // the same two tables is not supported.
+    if (\Drupal::service('comment.manager')->getFields($type)) {
+      $data['comment_entity_statistics']['table']['join'][$entity_type->getBaseTable()] = array(
+        'type' => 'INNER',
+        'left_field' => $entity_type->getKey('id'),
+        'field' => 'entity_id',
+        'extra' => array(
+          array(
+            'field' => 'entity_type',
+            'value' => $type,
+          ),
+        ),
+      );
+    }
+  }
+
+  $data['comment_entity_statistics']['last_comment_timestamp'] = array(
+    'title' => t('Last comment time'),
+    'help' => t('Date and time of when the last comment was posted.'),
+    'field' => array(
+      'id' => 'comment_last_timestamp',
+    ),
+    'sort' => array(
+      'id' => 'date',
+    ),
+    'filter' => array(
+      'id' => 'date',
+    ),
+  );
+
+  $data['comment_entity_statistics']['last_comment_name'] = array(
+    'title' => t("Last comment author"),
+    'help' => t('The name of the author of the last posted comment.'),
+    'field' => array(
+      'id' => 'comment_ces_last_comment_name',
+      'no group by' => TRUE,
+    ),
+    'sort' => array(
+      'id' => 'comment_ces_last_comment_name',
+      'no group by' => TRUE,
+    ),
+  );
+
+  $data['comment_entity_statistics']['comment_count'] = array(
+    'title' => t('Comment count'),
+    'help' => t('The number of comments an entity has.'),
+    'field' => array(
+      'id' => 'numeric',
+    ),
+    'filter' => array(
+      'id' => 'numeric',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+    'argument' => array(
+      'id' => 'standard',
+    ),
+  );
+
+  $data['comment_entity_statistics']['last_updated'] = array(
+    'title' => t('Updated/commented date'),
+    'help' => t('The most recent of last comment posted or entity updated time.'),
+    'field' => array(
+      'id' => 'comment_ces_last_updated',
+      'no group by' => TRUE,
+    ),
+    'sort' => array(
+      'id' => 'comment_ces_last_updated',
+      'no group by' => TRUE,
+    ),
+    'filter' => array(
+      'id' => 'comment_ces_last_updated',
+    ),
+  );
+
+  $data['comment_entity_statistics']['cid'] = array(
+    'title' => t('Last comment CID'),
+    'help' => t('Display the last comment of an entity'),
+    'relationship' => array(
+      'title' => t('Last comment'),
+      'help' => t('The last comment of an entity.'),
+      'group' => t('Comment'),
+      'base' => 'comment',
+      'base field' => 'cid',
+      'id' => 'standard',
+      'label' => t('Last Comment'),
+    ),
+  );
+
+  $data['comment_entity_statistics']['last_comment_uid'] = array(
+    'title' => t('Last comment uid'),
+    'help' => t('The User ID of the author of the last comment of an entity.'),
+    'relationship' => array(
+      'title' => t('Last comment author'),
+      'base' => 'users',
+      'base field' => 'uid',
+      'id' => 'standard',
+      'label' => t('Last comment author'),
+    ),
+    'filter' => array(
+      'id' => 'numeric',
+    ),
+    'argument' => array(
+      'id' => 'numeric',
+    ),
+    'field' => array(
+      'id' => 'numeric',
+    ),
+  );
+
+  $data['comment_entity_statistics']['entity_type'] = array(
+    'title' => t('Entity type'),
+    'help' => t('The entity type to which the comment is a reply to.'),
+    'field' => array(
+      'id' => 'standard',
+    ),
+    'filter' => array(
+      'id' => 'string',
+    ),
+    'argument' => array(
+      'id' => 'string',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+  );
+  $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',
+    ),
+    'filter' => array(
+      'id' => 'string',
+    ),
+    'argument' => array(
+      'id' => 'string',
+    ),
+    'sort' => array(
+      'id' => 'standard',
+    ),
+  );
+
+  return $data;
+}
+
+/**
  * Implements hook_views_data_alter().
  */
 function comment_views_data_alter(&$data) {
diff --git a/core/modules/comment/config/schema/comment.views.schema.yml b/core/modules/comment/config/schema/comment.views.schema.yml
index 0bd1332..f5f4700 100644
--- a/core/modules/comment/config/schema/comment.views.schema.yml
+++ b/core/modules/comment/config/schema/comment.views.schema.yml
@@ -42,9 +42,13 @@ views.field.comment_link:
       type: views_field
       label: 'Link field to the entity if there is no comment'
 
-views.field.comment_link_approve:
+views.field.comment_link_publish:
   type: views.field.comment_link
-  label: 'Comment approve link'
+  label: 'Comment publish link'
+
+views.field.comment_link_unpublish:
+  type: views.field.comment_link
+  label: 'Comment unpublish link'
 
 views.field.comment_link_delete:
   type: views.field.comment_link
diff --git a/core/modules/comment/src/CommentAccessControlHandler.php b/core/modules/comment/src/CommentAccessControlHandler.php
index b78c4b0..c88c4f2 100644
--- a/core/modules/comment/src/CommentAccessControlHandler.php
+++ b/core/modules/comment/src/CommentAccessControlHandler.php
@@ -34,11 +34,23 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A
 
     switch ($operation) {
       case 'view':
-        return AccessResult::allowedIf($account->hasPermission('access comments') && $entity->isPublished())->cachePerRole()->cacheUntilEntityChanges($entity)
-          ->andIf($entity->getCommentedEntity()->access($operation, $account, TRUE));
+        return AccessResult::allowedIfHasPermission($account, 'access comments')
+          ->andIf(AccessResult::allowedIf($entity->isPublished()))
+          ->andIf(AccessResult::allowedIf($entity->getCommentedEntity()->access($operation, $account, TRUE)))
+          ->cachePerRole()->cacheUntilEntityChanges($entity);
 
       case 'update':
-        return AccessResult::allowedIf($account->id() && $account->id() == $entity->getOwnerId() && $entity->isPublished() && $account->hasPermission('edit own comments'))->cachePerRole()->cachePerUser()->cacheUntilEntityChanges($entity);
+        return AccessResult::allowedIfHasPermission($account, 'edit own comments')
+          ->andIf(AccessResult::allowedIf($account->id() && $account->id() == $entity->getOwnerId() && $entity->isPublished()))
+          ->cachePerRole()->cachePerUser()->cacheUntilEntityChanges($entity);
+
+      case 'publish':
+        return AccessResult::allowedIfHasPermission($account, 'administer comments');
+        break;
+
+      case 'unpublish':
+        return AccessResult::allowedIfHasPermission($account, 'administer comments');
+        break;
 
       default:
         // No opinion.
@@ -96,7 +108,8 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_
       // fields on comment creation.
       if (in_array($field_definition->getName(), ['name', 'mail', 'homepage'], TRUE)) {
         $admin_access = AccessResult::allowedIfHasPermission($account, 'administer comments');
-        $anonymous_access = AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && $anonymous_contact != COMMENT_ANONYMOUS_MAYNOT_CONTACT && $account->hasPermission('post comments'))
+        $anonymous_access = AccessResult::allowedIfHasPermission($account, 'post comments')
+          ->andIf(AccessResult::allowedIf($entity->isNew() && $account->isAnonymous() && $anonymous_contact != COMMENT_ANONYMOUS_MAYNOT_CONTACT))
           ->cachePerRole()
           ->cacheUntilEntityChanges($entity)
           ->cacheUntilEntityChanges($field_definition->getConfig($commented_entity->bundle()))
@@ -109,9 +122,11 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_
       // Admins can view any fields except hostname, other users need both the
       // "access comments" permission and for the comment to be published. The
       // mail field is hidden from non-admins.
-      $admin_access = AccessResult::allowedIf($account->hasPermission('administer comments') && $field_definition->getName() != 'hostname')
+      $admin_access = AccessResult::allowedIfHasPermission($account, 'administer comments')
+        ->andIf(AccessResult::allowedIf($field_definition->getName() != 'hostname'))
         ->cachePerRole();
-      $anonymous_access = AccessResult::allowedIf($account->hasPermission('access comments') && $entity->isPublished() && !in_array($field_definition->getName(), array('mail', 'hostname'), TRUE))
+      $anonymous_access = AccessResult::allowedIfHasPermission($account, 'access comments')
+        ->andIf(AccessResult::allowedIf($entity->isPublished() && !in_array($field_definition->getName(), array('mail', 'hostname'), TRUE)))
         ->cacheUntilEntityChanges($entity)
         ->cachePerRole();
       return $admin_access->orIf($anonymous_access);
diff --git a/core/modules/comment/src/CommentInterface.php b/core/modules/comment/src/CommentInterface.php
index e7a4ee9..17f769e 100644
--- a/core/modules/comment/src/CommentInterface.php
+++ b/core/modules/comment/src/CommentInterface.php
@@ -17,7 +17,7 @@
 interface CommentInterface extends ContentEntityInterface, EntityChangedInterface, EntityOwnerInterface {
 
   /**
-   * Comment is awaiting approval.
+   * Comment is unpublished and awaiting approval.
    */
   const NOT_PUBLISHED = 0;
 
diff --git a/core/modules/comment/src/CommentStorage.php b/core/modules/comment/src/CommentStorage.php
index 2cbaed7..7a27c06 100644
--- a/core/modules/comment/src/CommentStorage.php
+++ b/core/modules/comment/src/CommentStorage.php
@@ -25,6 +25,7 @@
  */
 class CommentStorage extends SqlContentEntityStorage implements CommentStorageInterface {
 
+
   /**
    * The current user.
    *
@@ -321,7 +322,49 @@ public function loadThread(EntityInterface $entity, $field_name, $mode, $comment
   /**
    * {@inheritdoc}
    */
-  public function getUnapprovedCount() {
+  public function getSchema() {
+    $schema = parent::getSchema();
+
+    // Marking the respective fields as NOT NULL makes the indexes more
+    // performant.
+    $schema['comment_field_data']['fields']['created']['not null'] = TRUE;
+    $schema['comment_field_data']['fields']['thread']['not null'] = TRUE;
+
+    unset($schema['comment_field_data']['indexes']['comment_field__pid__target_id']);
+    unset($schema['comment_field_data']['indexes']['comment_field__entity_id__target_id']);
+    $schema['comment_field_data']['indexes'] += array(
+      'comment__status_pid' => array('pid', 'status'),
+      'comment__num_new' => array(
+        'entity_id',
+        'entity_type',
+        'comment_type',
+        'status',
+        'created',
+        'cid',
+        'thread',
+      ),
+      'comment__entity_langcode' => array(
+        'entity_id',
+        'entity_type',
+        'comment_type',
+        'default_langcode',
+      ),
+      'comment__created' => array('created'),
+    );
+    $schema['comment_field_data']['foreign keys'] += array(
+      'comment__author' => array(
+        'table' => 'users',
+        'columns' => array('uid' => 'uid'),
+      ),
+    );
+
+    return $schema;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getUnpublishedCount() {
     return  $this->database->select('comment_field_data', 'c')
       ->condition('status', CommentInterface::NOT_PUBLISHED, '=')
       ->condition('default_langcode', 1)
@@ -330,4 +373,6 @@ public function getUnapprovedCount() {
       ->fetchField();
   }
 
+  public function updateEntityStatistics(CommentInterface $comment) {}
+
 }
diff --git a/core/modules/comment/src/CommentStorageInterface.php b/core/modules/comment/src/CommentStorageInterface.php
index 5be4776..6d9aa75 100644
--- a/core/modules/comment/src/CommentStorageInterface.php
+++ b/core/modules/comment/src/CommentStorageInterface.php
@@ -108,11 +108,28 @@ public function getChildCids(array $comments);
   public function loadThread(EntityInterface $entity, $field_name, $mode, $comments_per_page = 0, $pager_id = 0);
 
   /**
-   * Returns the number of unapproved comments.
+   * Updates the comment statistics for a given node.
+   *
+   * The {comment_entity_statistics} table has the following fields:
+   * - last_comment_timestamp: The timestamp of the last comment for the entity,
+   *   or the entity created timestamp if no comments exist for the entity.
+   * - last_comment_name: The name of the anonymous poster for the last comment.
+   * - last_comment_uid: The user ID of the poster for the last comment for
+   *   this entity, or the entity author's user ID if no comments exist for the
+   *   entity.
+   * - comment_count: The total number of published comments on this entity.
+   *
+   * @param \Drupal\comment\CommentInterface $comment
+   *   The comment being saved.
+   */
+  public function updateEntityStatistics(CommentInterface $comment);
+
+  /**
+   * Returns the number of unpublished comments.
    *
    * @return int
-   *   The number of unapproved comments.
+   *   The number of unpublished comments.
    */
-  public function getUnapprovedCount();
+  public function getUnpublishedCount();
 
 }
diff --git a/core/modules/comment/src/CommentViewBuilder.php b/core/modules/comment/src/CommentViewBuilder.php
index cd9a5b9..1682aba 100644
--- a/core/modules/comment/src/CommentViewBuilder.php
+++ b/core/modules/comment/src/CommentViewBuilder.php
@@ -270,10 +270,19 @@ protected static function buildLinks(CommentInterface $entity, EntityInterface $
           'html' => TRUE,
         );
       }
-      if (!$entity->isPublished() && $entity->access('approve')) {
-        $links['comment-approve'] = array(
-          'title' => t('Approve'),
-          'url' => Url::fromRoute('comment.approve', ['comment' => $entity->id()]),
+      if (!$entity->isPublished() && $entity->access('publish')) {
+        $links['comment-publish'] = array(
+          'title' => t('Publish'),
+          'route_name' => 'comment.publish',
+          'route_parameters' => array('comment' => $entity->id()),
+          'html' => TRUE,
+        );
+      }
+      if ($entity->isPublished() && $entity->access('unpublish')) {
+        $links['comment-unpublish'] = array(
+          'title' => t('Unpublish'),
+          'route_name' => 'comment.unpublish',
+          'route_parameters' => array('comment' => $entity->id()),
           'html' => TRUE,
         );
       }
diff --git a/core/modules/comment/src/Controller/AdminController.php b/core/modules/comment/src/Controller/AdminController.php
index 4c1592f..3895456 100644
--- a/core/modules/comment/src/Controller/AdminController.php
+++ b/core/modules/comment/src/Controller/AdminController.php
@@ -49,7 +49,7 @@ public function __construct(FormBuilderInterface $form_builder) {
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The request of the page.
    * @param string $type
-   *   The type of the overview form ('approval' or 'new') default to 'new'.
+   *   The type of the overview form ('unpublished' or 'new') default to 'new'.
    *
    * @return array
    *   Then comment multiple delete confirmation form or the comments overview
diff --git a/core/modules/comment/src/Controller/CommentController.php b/core/modules/comment/src/Controller/CommentController.php
index af415d0..12dcdd8 100644
--- a/core/modules/comment/src/Controller/CommentController.php
+++ b/core/modules/comment/src/Controller/CommentController.php
@@ -73,11 +73,30 @@ public static function create(ContainerInterface $container) {
    * @return \Symfony\Component\HttpFoundation\RedirectResponse.
    *   Redirects to the permalink URL for this comment.
    */
-  public function commentApprove(CommentInterface $comment) {
+  public function commentPublish(CommentInterface $comment) {
     $comment->setPublished(TRUE);
     $comment->save();
 
-    drupal_set_message($this->t('Comment approved.'));
+    drupal_set_message($this->t('Comment published.'));
+    $permalink_uri = $comment->permalink();
+    $permalink_uri->setAbsolute();
+    return new RedirectResponse($permalink_uri->toString());
+  }
+
+  /**
+   * Unpublishes the specified comment.
+   *
+   * @param \Drupal\comment\CommentInterface $comment
+   *   A comment entity.
+   *
+   * @return \Symfony\Component\HttpFoundation\RedirectResponse.
+   *   Redirects to the permalink URL for this comment.
+   */
+  public function commentUnpublish(CommentInterface $comment) {
+    $comment->setPublished(FALSE);
+    $comment->save();
+
+    drupal_set_message($this->t('Comment unpublished.'));
     $permalink_uri = $comment->permalink();
     $permalink_uri->setAbsolute();
     return new RedirectResponse($permalink_uri->toString());
diff --git a/core/modules/comment/src/Form/CommentAdminOverview.php b/core/modules/comment/src/Form/CommentAdminOverview.php
index 4abff68..6adc416 100644
--- a/core/modules/comment/src/Form/CommentAdminOverview.php
+++ b/core/modules/comment/src/Form/CommentAdminOverview.php
@@ -112,7 +112,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $type = '
       '#attributes' => array('class' => array('container-inline')),
     );
 
-    if ($type == 'approval') {
+    if ($type == 'unpublished') {
       $options['publish'] = $this->t('Publish the selected comments');
     }
     else {
@@ -133,7 +133,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $type = '
     );
 
     // Load the comments that need to be displayed.
-    $status = ($type == 'approval') ? CommentInterface::NOT_PUBLISHED : CommentInterface::PUBLISHED;
+    $status = ($type == 'unpublished') ? CommentInterface::NOT_PUBLISHED : CommentInterface::PUBLISHED;
     $header = array(
       'subject' => array(
         'data' => $this->t('Subject'),
diff --git a/core/modules/comment/src/Plugin/Menu/LocalTask/UnapprovedComments.php b/core/modules/comment/src/Plugin/Menu/LocalTask/UnapprovedComments.php
deleted file mode 100644
index 0b8f6da..0000000
--- a/core/modules/comment/src/Plugin/Menu/LocalTask/UnapprovedComments.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\comment\Plugin\Menu\LocalTask\UnapprovedComments.
- */
-
-namespace Drupal\comment\Plugin\Menu\LocalTask;
-
-use Drupal\comment\CommentStorageInterface;
-use Drupal\Core\Menu\LocalTaskDefault;
-use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides a local task that shows the amount of unapproved comments.
- */
-class UnapprovedComments extends LocalTaskDefault implements ContainerFactoryPluginInterface {
-
-  /**
-   * The comment storage service.
-   *
-   * @var \Drupal\comment\CommentStorageInterface
-   */
-  protected $commentStorage;
-
-  /**
-   * Construct the UnapprovedComments object.
-   *
-   * @param array $configuration
-   *   A configuration array containing information about the plugin instance.
-   * @param string $plugin_id
-   *   The plugin_id for the plugin instance.
-   * @param array $plugin_definition
-   *   The plugin implementation definition.
-   * @param \Drupal\comment\CommentStorageInterface $comment_storage
-   *   The comment storage service.
-   */
-  public function __construct(array $configuration, $plugin_id, array $plugin_definition, CommentStorageInterface $comment_storage) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-    $this->commentStorage = $comment_storage;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container->get('entity.manager')->getStorage('comment')
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getTitle() {
-    return t('Unapproved comments (@count)', array('@count' => $this->commentStorage->getUnapprovedCount()));
-  }
-
-}
diff --git a/core/modules/comment/src/Plugin/Menu/LocalTask/UnpublishedComments.php b/core/modules/comment/src/Plugin/Menu/LocalTask/UnpublishedComments.php
new file mode 100644
index 0000000..116641f
--- /dev/null
+++ b/core/modules/comment/src/Plugin/Menu/LocalTask/UnpublishedComments.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\comment\Plugin\Menu\LocalTask\UnpublishedComments.
+ */
+
+namespace Drupal\comment\Plugin\Menu\LocalTask;
+
+use Drupal\comment\CommentStorageInterface;
+use Drupal\Core\Menu\LocalTaskDefault;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a local task that shows the amount of unpublished comments.
+ */
+class UnpublishedComments extends LocalTaskDefault implements ContainerFactoryPluginInterface {
+
+  /**
+   * The comment storage service.
+   *
+   * @var \Drupal\comment\CommentStorageInterface
+   */
+  protected $commentStorage;
+
+  /**
+   * Construct the UnpublishedComments object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\comment\CommentStorageInterface $comment_storage
+   *   The comment storage service.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, CommentStorageInterface $comment_storage) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->commentStorage = $comment_storage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity.manager')->getStorage('comment')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTitle() {
+    return t('Unpublished comments (@count)', array('@count' => $this->commentStorage->getUnpublishedCount()));
+  }
+
+}
diff --git a/core/modules/comment/src/Plugin/views/field/LinkApprove.php b/core/modules/comment/src/Plugin/views/field/LinkApprove.php
index 095eacd..87e5896 100644
--- a/core/modules/comment/src/Plugin/views/field/LinkApprove.php
+++ b/core/modules/comment/src/Plugin/views/field/LinkApprove.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\comment\Plugin\views\field\LinkApprove.
+ * Definition of Drupal\comment\Plugin\views\field\LinkPublish.
  */
 
 namespace Drupal\comment\Plugin\views\field;
@@ -12,13 +12,13 @@
 use Drupal\views\ResultRow;
 
 /**
- * Provides a comment approve link.
+ * Provides a comment publish link.
  *
  * @ingroup views_field_handlers
  *
- * @ViewsField("comment_link_approve")
+ * @ViewsField("comment_link_publish")
  */
-class LinkApprove extends Link {
+class LinkPublish extends Link {
 
   /**
    * {@inheritdoc}
@@ -29,7 +29,7 @@ public function access(AccountInterface $account) {
   }
 
   /**
-   * Prepares the link pointing for approving the comment.
+   * Prepares the link for publishing the comment.
    *
    * @param \Drupal\Core\Entity\EntityInterface $data
    *   The comment entity.
@@ -42,16 +42,16 @@ public function access(AccountInterface $account) {
   protected function renderLink($data, ResultRow $values) {
     $status = $this->getValue($values, 'status');
 
-    // Don't show an approve link on published comment.
+    // Don't show a publish link on published comment.
     if ($status == CommentInterface::PUBLISHED) {
       return;
     }
 
-    $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Approve');
+    $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Publish');
     $comment = $this->get_entity($values);
 
     $this->options['alter']['make_link'] = TRUE;
-    $this->options['alter']['path'] = "comment/" . $comment->id() . "/approve";
+    $this->options['alter']['path'] = "comment/" . $comment->id() . "/publish";
     $this->options['alter']['query'] = drupal_get_destination() + array('token' => \Drupal::csrfToken()->get($this->options['alter']['path']));
 
     return $text;
diff --git a/core/modules/comment/src/Plugin/views/field/LinkUnpublish.php b/core/modules/comment/src/Plugin/views/field/LinkUnpublish.php
new file mode 100644
index 0000000..a11bc0a
--- /dev/null
+++ b/core/modules/comment/src/Plugin/views/field/LinkUnpublish.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\comment\Plugin\views\field\LinkUnpublish.
+ */
+
+namespace Drupal\comment\Plugin\views\field;
+
+use Drupal\comment\CommentInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\views\ResultRow;
+
+/**
+ * Provides a comment unpublish link.
+ *
+ * @ingroup views_field_handlers
+ *
+ * @ViewsField("comment_link_unpublish")
+ */
+class LinkUnpublish extends Link {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access(AccountInterface $account) {
+    //needs permission to administer comments in general
+    return $account->hasPermission('administer comments');
+  }
+
+  /**
+   * Prepares the link for unpublishing the comment.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $data
+   *   The comment entity.
+   * @param \Drupal\views\ResultRow $values
+   *   The values retrieved from a single row of a view's query result.
+   *
+   * @return string
+   *   Returns a string for the link text.
+   */
+  protected function renderLink($data, ResultRow $values) {
+    $status = $this->getValue($values, 'status');
+
+    // Don't show an unpublish link on unpublished comment.
+    if ($status == CommentInterface::NOT_PUBLISHED) {
+      return;
+    }
+
+    $text = !empty($this->options['text']) ? $this->options['text'] : t('Unpublish');
+    $comment = $this->get_entity($values);
+
+    $this->options['alter']['make_link'] = TRUE;
+    $this->options['alter']['path'] = "comment/" . $comment->id() . "/unpublish";
+    $this->options['alter']['query'] = drupal_get_destination() + array('token' => \Drupal::csrfToken()->get($this->options['alter']['path']));
+
+    return $text;
+  }
+
+}
diff --git a/core/modules/comment/src/Tests/CommentAdminTest.php b/core/modules/comment/src/Tests/CommentAdminTest.php
index 811dfde..5c63316 100644
--- a/core/modules/comment/src/Tests/CommentAdminTest.php
+++ b/core/modules/comment/src/Tests/CommentAdminTest.php
@@ -8,15 +8,15 @@
 namespace Drupal\comment\Tests;
 
 /**
- * Tests comment approval functionality.
+ * Tests comment administration functionality.
  *
  * @group comment
  */
 class CommentAdminTest extends CommentTestBase {
   /**
-   * Test comment approval functionality through admin/content/comment.
+   * Tests comment overview with published and unpublished comments.
    */
-  function testApprovalAdminInterface() {
+  function testContentAdminPages() {
     // Set anonymous comments to require approval.
     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       'access comments' => TRUE,
@@ -38,9 +38,9 @@ function testApprovalAdminInterface() {
     $this->postComment($this->node, $body, $subject, TRUE); // Set $contact to true so that it won't check for id and message.
     $this->assertText(t('Your comment has been queued for review by site administrators and will be published after approval.'), 'Comment requires approval.');
 
-    // Get unapproved comment id.
+    // Get unpublished comment id.
     $this->drupalLogin($this->admin_user);
-    $anonymous_comment4 = $this->getUnapprovedComment($subject);
+    $anonymous_comment4 = $this->getUnpublishedComment($subject);
     $anonymous_comment4 = entity_create('comment', array(
       'cid' => $anonymous_comment4,
       'subject' => $subject,
@@ -53,7 +53,7 @@ function testApprovalAdminInterface() {
 
     $this->assertFalse($this->commentExists($anonymous_comment4), 'Anonymous comment was not published.');
 
-    // Approve comment.
+    // Publish comment.
     $this->drupalLogin($this->admin_user);
     $this->performCommentOperation($anonymous_comment4, 'publish', TRUE);
     $this->drupalLogout();
@@ -67,14 +67,14 @@ function testApprovalAdminInterface() {
 
     // Publish multiple comments in one operation.
     $this->drupalLogin($this->admin_user);
-    $this->drupalGet('admin/content/comment/approval');
-    $this->assertText(t('Unapproved comments (@count)', array('@count' => 2)), 'Two unapproved comments waiting for approval.');
+    $this->drupalGet('admin/content/comment/unpublished');
+    $this->assertText(t('Unpublished comments (@count)', array('@count' => 2)), 'Two unpublished comments waiting for approval.');
     $edit = array(
       "comments[{$comments[0]->id()}]" => 1,
       "comments[{$comments[1]->id()}]" => 1,
     );
     $this->drupalPostForm(NULL, $edit, t('Update'));
-    $this->assertText(t('Unapproved comments (@count)', array('@count' => 0)), 'All comments were approved.');
+    $this->assertText(t('Unpublished comments (@count)', array('@count' => 0)), 'All comments were unpublished.');
 
     // Delete multiple comments in one operation.
     $edit = array(
@@ -96,9 +96,9 @@ function testApprovalAdminInterface() {
   }
 
   /**
-   * Tests comment approval functionality through the node interface.
+   * Tests comment publish functionality through the node interface.
    */
-  function testApprovalNodeInterface() {
+  function testPublishNodeInterface() {
     // Set anonymous comments to require approval.
     user_role_change_permissions(DRUPAL_ANONYMOUS_RID, array(
       'access comments' => TRUE,
@@ -115,9 +115,9 @@ function testApprovalNodeInterface() {
     $this->postComment($this->node, $body, $subject, TRUE); // Set $contact to true so that it won't check for id and message.
     $this->assertText(t('Your comment has been queued for review by site administrators and will be published after approval.'), 'Comment requires approval.');
 
-    // Get unapproved comment id.
+    // Get unpublished comment id.
     $this->drupalLogin($this->admin_user);
-    $anonymous_comment4 = $this->getUnapprovedComment($subject);
+    $anonymous_comment4 = $this->getUnpublishedComment($subject);
     $anonymous_comment4 = entity_create('comment', array(
       'cid' => $anonymous_comment4,
       'subject' => $subject,
@@ -130,20 +130,33 @@ function testApprovalNodeInterface() {
 
     $this->assertFalse($this->commentExists($anonymous_comment4), 'Anonymous comment was not published.');
 
-    // Approve comment.
+    // Publish comment.
     $this->drupalLogin($this->admin_user);
-    $this->drupalGet('comment/1/approve');
+    $this->drupalGet('comment/1/publish');
     $this->assertResponse(403, 'Forged comment approval was denied.');
-    $this->drupalGet('comment/1/approve', array('query' => array('token' => 'forged')));
+    $this->drupalGet('comment/1/publish', array('query' => array('token' => 'forged')));
     $this->assertResponse(403, 'Forged comment approval was denied.');
     $this->drupalGet('comment/1/edit');
     $this->assertFieldChecked('edit-status-0');
     $this->drupalGet('node/' . $this->node->id());
-    $this->clickLink(t('Approve'));
+    $this->clickLink(t('Publish'));
     $this->drupalLogout();
 
     $this->drupalGet('node/' . $this->node->id());
     $this->assertTrue($this->commentExists($anonymous_comment4), 'Anonymous comment visible.');
+
+    // Unpublish comment.
+    $this->drupalLogin($this->admin_user);
+    $this->drupalGet('comment/1/unpublish');
+    $this->assertResponse(403, 'Forged comment unpublishing was denied.');
+    $this->drupalGet('comment/1/unpublish', array('query' => array('token' => 'forged')));
+    $this->assertResponse(403, 'Forged comment unpublishing was denied.');
+    $this->drupalGet('node/' . $this->node->id());
+    $this->clickLink(t('Unpublish'));
+    $this->drupalLogout();
+
+    $this->drupalGet('node/' . $this->node->id());
+    $this->assertFalse($this->commentExists($anonymous_comment4), 'Anonymous comment not visible.');
   }
 
   /**
diff --git a/core/modules/comment/src/Tests/CommentAnonymousTest.php b/core/modules/comment/src/Tests/CommentAnonymousTest.php
index da4b453..2e70072 100644
--- a/core/modules/comment/src/Tests/CommentAnonymousTest.php
+++ b/core/modules/comment/src/Tests/CommentAnonymousTest.php
@@ -98,7 +98,7 @@ function testAnonymous() {
     // Unpublish comment.
     $this->performCommentOperation($anonymous_comment3, 'unpublish');
 
-    $this->drupalGet('admin/content/comment/approval');
+    $this->drupalGet('admin/content/comment/unpublished');
     $this->assertRaw('comments[' . $anonymous_comment3->id() . ']', 'Comment was unpublished.');
 
     // Publish comment.
diff --git a/core/modules/comment/src/Tests/CommentNonNodeTest.php b/core/modules/comment/src/Tests/CommentNonNodeTest.php
index 15eb7b7..7fcbb67 100644
--- a/core/modules/comment/src/Tests/CommentNonNodeTest.php
+++ b/core/modules/comment/src/Tests/CommentNonNodeTest.php
@@ -194,14 +194,14 @@ function commentContactInfoAvailable() {
    *   Comment to perform operation on.
    * @param string $operation
    *   Operation to perform.
-   * @param boolean $aproval
-   *   Operation is found on approval page.
+   * @param boolean $unpublished
+   *   Operation is found on unpublished comments page.
    */
-  function performCommentOperation($comment, $operation, $approval = FALSE) {
+  function performCommentOperation($comment, $operation, $unpublished = FALSE) {
     $edit = array();
     $edit['operation'] = $operation;
     $edit['comments[' . $comment->id() . ']'] = TRUE;
-    $this->drupalPostForm('admin/content/comment' . ($approval ? '/approval' : ''), $edit, t('Update'));
+    $this->drupalPostForm('admin/content/comment' . ($unpublished ? '/unpublished' : ''), $edit, t('Update'));
 
     if ($operation == 'delete') {
       $this->drupalPostForm(NULL, array(), t('Delete comments'));
@@ -213,7 +213,7 @@ function performCommentOperation($comment, $operation, $approval = FALSE) {
   }
 
   /**
-   * Gets the comment ID for an unapproved comment.
+   * Gets the comment ID for an unapproved (unpublished) comment.
    *
    * @param string $subject
    *   Comment subject to find.
@@ -221,8 +221,8 @@ function performCommentOperation($comment, $operation, $approval = FALSE) {
    * @return integer
    *   Comment ID.
    */
-  function getUnapprovedComment($subject) {
-    $this->drupalGet('admin/content/comment/approval');
+  function getUnpublishedComment($subject) {
+    $this->drupalGet('admin/content/comment/unpublished');
     preg_match('/href="(.*?)#comment-([^"]+)"(.*?)>(' . $subject . ')/', $this->drupalGetContent(), $match);
 
     return $match[2];
@@ -256,7 +256,7 @@ function testCommentFunctionality() {
 
     // Unpublish the comment.
     $this->performCommentOperation($comment1, 'unpublish');
-    $this->drupalGet('admin/content/comment/approval');
+    $this->drupalGet('admin/content/comment/unpublished');
     $this->assertRaw('comments[' . $comment1->id() . ']', 'Comment was unpublished.');
 
     // Publish the comment.
diff --git a/core/modules/comment/src/Tests/CommentTestBase.php b/core/modules/comment/src/Tests/CommentTestBase.php
index d86e3d4..7cb5bff 100644
--- a/core/modules/comment/src/Tests/CommentTestBase.php
+++ b/core/modules/comment/src/Tests/CommentTestBase.php
@@ -334,14 +334,14 @@ function commentContactInfoAvailable() {
    *   Comment to perform operation on.
    * @param string $operation
    *   Operation to perform.
-   * @param boolean $aproval
-   *   Operation is found on approval page.
+   * @param boolean $unpublished
+   *   Operation is found on unpublished comments page.
    */
-  function performCommentOperation(CommentInterface $comment, $operation, $approval = FALSE) {
+  function performCommentOperation(CommentInterface $comment, $operation, $unpublished = FALSE) {
     $edit = array();
     $edit['operation'] = $operation;
     $edit['comments[' . $comment->id() . ']'] = TRUE;
-    $this->drupalPostForm('admin/content/comment' . ($approval ? '/approval' : ''), $edit, t('Update'));
+    $this->drupalPostForm('admin/content/comment' . ($unpublished ? '/unpublished' : ''), $edit, t('Update'));
 
     if ($operation == 'delete') {
       $this->drupalPostForm(NULL, array(), t('Delete comments'));
@@ -353,7 +353,7 @@ function performCommentOperation(CommentInterface $comment, $operation, $approva
   }
 
   /**
-   * Gets the comment ID for an unapproved comment.
+   * Gets the comment ID for an unapproved (unpublished) comment.
    *
    * @param string $subject
    *   Comment subject to find.
@@ -361,8 +361,8 @@ function performCommentOperation(CommentInterface $comment, $operation, $approva
    * @return integer
    *   Comment id.
    */
-  function getUnapprovedComment($subject) {
-    $this->drupalGet('admin/content/comment/approval');
+  function getUnpublishedComment($subject) {
+    $this->drupalGet('admin/content/comment/unpublished');
     preg_match('/href="(.*?)#comment-([^"]+)"(.*?)>(' . $subject . ')/', $this->drupalGetContent(), $match);
 
     return $match[2];
