diff --git a/core/modules/aggregator/config/schema/aggregator.views.schema.yml b/core/modules/aggregator/config/schema/aggregator.views.schema.yml
index 23cc642..ff423c5 100644
--- a/core/modules/aggregator/config/schema/aggregator.views.schema.yml
+++ b/core/modules/aggregator/config/schema/aggregator.views.schema.yml
@@ -9,7 +9,7 @@ views.argument.aggregator_iid:
   label: 'Aggregator item ID'
 
 views.field.aggregator_title_link:
-  type: views_field
+  type: views.field.entity_link
   label: 'Title link'
   mapping:
     display_as_link:
diff --git a/core/modules/aggregator/src/Plugin/views/field/TitleLink.php b/core/modules/aggregator/src/Plugin/views/field/TitleLink.php
index ba05199..f1a6cdc 100644
--- a/core/modules/aggregator/src/Plugin/views/field/TitleLink.php
+++ b/core/modules/aggregator/src/Plugin/views/field/TitleLink.php
@@ -10,7 +10,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
-use Drupal\views\Plugin\views\field\FieldPluginBase;
+use Drupal\views\Plugin\views\field\EntityLink;
 use Drupal\views\ResultRow;
 use Drupal\views\ViewExecutable;
 
@@ -23,7 +23,7 @@
  *
  * @ViewsField("aggregator_title_link")
  */
-class TitleLink extends FieldPluginBase {
+class TitleLink extends EntityLink {
 
   /**
    * {@inheritdoc}
@@ -77,9 +77,8 @@ public function render(ResultRow $values) {
    *   Returns a string for the link text.
    */
   protected function renderLink($data, ResultRow $values) {
-    $link = $this->getValue($values, 'link');
     if (!empty($this->options['display_as_link'])) {
-      $this->options['alter']['make_link'] = TRUE;
+      parent::renderLink($this->getEntity($values), $values);
       // Note: $link is an external URI, pointing to the feed itself.
       $this->options['alter']['url'] = Url::fromUri($link);
       $this->options['alter']['html'] = TRUE;
diff --git a/core/modules/comment/config/schema/comment.views.schema.yml b/core/modules/comment/config/schema/comment.views.schema.yml
index cdb22cf..3d892b8 100644
--- a/core/modules/comment/config/schema/comment.views.schema.yml
+++ b/core/modules/comment/config/schema/comment.views.schema.yml
@@ -46,18 +46,6 @@ views.field.comment_link_approve:
   type: views.field.comment_link
   label: 'Comment approve link'
 
-views.field.comment_link_delete:
-  type: views.field.comment_link
-  label: 'Comment delete link'
-
-views.field.comment_link_edit:
-  type: views.field.comment_link
-  label: 'Comment edit link'
-  mapping:
-    destination:
-      type: boolean
-      label: 'Use destination'
-
 views.field.comment_link_reply:
   type: views.field.comment_link
   label: 'Comment reply link'
diff --git a/core/modules/comment/src/CommentViewsData.php b/core/modules/comment/src/CommentViewsData.php
index 894236e..b65a1ed 100644
--- a/core/modules/comment/src/CommentViewsData.php
+++ b/core/modules/comment/src/CommentViewsData.php
@@ -105,30 +105,6 @@ public function getViewsData() {
     $data['comment_field_data']['status']['filter']['label'] = t('Approved comment status');
     $data['comment_field_data']['status']['filter']['type'] = 'yes-no';
 
-    $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']['approve_comment'] = array(
       'field' => array(
         'title' => t('Link to approve comment'),
diff --git a/core/modules/comment/src/Plugin/views/field/LinkDelete.php b/core/modules/comment/src/Plugin/views/field/LinkDelete.php
deleted file mode 100644
index b36c223..0000000
--- a/core/modules/comment/src/Plugin/views/field/LinkDelete.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\comment\Plugin\views\field\LinkDelete.
- */
-
-namespace Drupal\comment\Plugin\views\field;
-
-use Drupal\Core\Session\AccountInterface;
-use Drupal\views\ResultRow;
-
-/**
- * Field handler to present a link to delete a comment.
- *
- * @ingroup views_field_handlers
- *
- * @ViewsField("comment_link_delete")
- */
-class LinkDelete extends Link {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function access(AccountInterface $account) {
-    //needs permission to administer comments in general
-    return $account->hasPermission('administer comments');
-  }
-
-  /**
-   * Prepares the link for deleting 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) {
-    $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Delete');
-    $comment = $this->getEntity($values);
-
-    $this->options['alter']['make_link'] = TRUE;
-    $this->options['alter']['url'] = $comment->urlInfo('delete-form');
-    $this->options['alter']['query'] = drupal_get_destination();
-
-    return $text;
-  }
-
-}
diff --git a/core/modules/comment/src/Plugin/views/field/LinkEdit.php b/core/modules/comment/src/Plugin/views/field/LinkEdit.php
deleted file mode 100644
index 316c272..0000000
--- a/core/modules/comment/src/Plugin/views/field/LinkEdit.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\comment\Plugin\views\field\LinkEdit.
- */
-
-namespace Drupal\comment\Plugin\views\field;
-
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\views\ResultRow;
-
-/**
- * Field handler to present a link to edit a comment.
- *
- * @ingroup views_field_handlers
- *
- * @ViewsField("comment_link_edit")
- */
-class LinkEdit extends Link {
-
-  protected function defineOptions() {
-    $options = parent::defineOptions();
-    $options['destination'] = array('default' => FALSE);
-
-    return $options;
-  }
-
-  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
-    parent::buildOptionsForm($form, $form_state);
-
-    $form['destination'] = array(
-      '#type' => 'checkbox',
-      '#title' => $this->t('Use destination'),
-      '#description' => $this->t('Add destination to the link'),
-      '#default_value' => $this->options['destination'],
-    );
-  }
-
-  /**
-   * Prepare the link for editing 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) {
-    parent::renderLink($data, $values);
-    // Ensure user has access to edit this comment.
-    $comment = $this->getValue($values);
-    if (!$comment->access('update')) {
-      return;
-    }
-
-    $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Edit');
-    unset($this->options['alter']['fragment']);
-
-    if (!empty($this->options['destination'])) {
-      $this->options['alter']['query'] = drupal_get_destination();
-    }
-
-    $this->options['alter']['url'] = $comment->urlInfo('edit-form');
-
-    return $text;
-  }
-
-}
diff --git a/core/modules/node/config/optional/views.view.content_recent.yml b/core/modules/node/config/optional/views.view.content_recent.yml
index 7cd39e1..31d157e 100644
--- a/core/modules/node/config/optional/views.view.content_recent.yml
+++ b/core/modules/node/config/optional/views.view.content_recent.yml
@@ -242,7 +242,7 @@ display:
           hide_alter_empty: true
           text: Edit
           entity_type: node
-          plugin_id: node_link_edit
+          plugin_id: entity_link_edit
         delete_node:
           id: delete_node
           table: node
@@ -293,7 +293,7 @@ display:
           hide_alter_empty: true
           text: Delete
           entity_type: node
-          plugin_id: node_link_delete
+          plugin_id: entity_link_delete
       filters:
         status_extra:
           id: status_extra
diff --git a/core/modules/node/config/schema/node.views.schema.yml b/core/modules/node/config/schema/node.views.schema.yml
index abd96b6..9426a12 100644
--- a/core/modules/node/config/schema/node.views.schema.yml
+++ b/core/modules/node/config/schema/node.views.schema.yml
@@ -94,37 +94,13 @@ views.argument_validator.node:
       label: 'Filter value format'
 
 views.field.node:
-  type: views_field
+  type: views.field.entity_link
   label: 'Node'
   mapping:
     link_to_node:
       type: boolean
       label: 'Link this field to the original piece of content'
 
-views.field.node_link:
-  type: views_field
-  label: 'Node link'
-  mapping:
-    text:
-      type: label
-      label: 'Text to display'
-
-views.field.node_link_delete:
-  type: views_field
-  label: 'Node delete link'
-  mapping:
-    text:
-      type: label
-      label: 'Text to display'
-
-views.field.node_link_edit:
-  type: views_field
-  label: 'Node edit link'
-  mapping:
-    text:
-      type: label
-      label: 'Text to display'
-
 views.field.node_bulk_form:
   type: views_field_bulk_form
   label: 'Node bulk form'
diff --git a/core/modules/node/src/NodeViewsData.php b/core/modules/node/src/NodeViewsData.php
index dfe7317..fc6ba9e 100644
--- a/core/modules/node/src/NodeViewsData.php
+++ b/core/modules/node/src/NodeViewsData.php
@@ -71,30 +71,6 @@ public function getViewsData() {
       );
     }
 
-    $data['node']['view_node'] = array(
-      'field' => array(
-        'title' => t('Link to content'),
-        'help' => t('Provide a simple link to the content.'),
-        'id' => 'node_link',
-      ),
-    );
-
-    $data['node']['edit_node'] = array(
-      'field' => array(
-        'title' => t('Link to edit content'),
-        'help' => t('Provide a simple link to edit the content.'),
-        'id' => 'node_link_edit',
-      ),
-    );
-
-    $data['node']['delete_node'] = array(
-      'field' => array(
-        'title' => t('Link to delete content'),
-        'help' => t('Provide a simple link to delete the content.'),
-        'id' => 'node_link_delete',
-      ),
-    );
-
     $data['node']['path'] = array(
       'field' => array(
         'title' => t('Path'),
diff --git a/core/modules/node/src/Plugin/views/field/Node.php b/core/modules/node/src/Plugin/views/field/Node.php
index 43077e2..0750c52 100644
--- a/core/modules/node/src/Plugin/views/field/Node.php
+++ b/core/modules/node/src/Plugin/views/field/Node.php
@@ -9,10 +9,10 @@
 
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
+use Drupal\views\Plugin\views\field\EntityLink;
 use Drupal\views\ResultRow;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
-use Drupal\views\Plugin\views\field\FieldPluginBase;
 
 /**
  * Field handler to provide simple renderer that allows linking to a node.
@@ -23,7 +23,7 @@
  *
  * @ViewsField("node")
  */
-class Node extends FieldPluginBase {
+class Node extends EntityLink {
 
   /**
    * {@inheritdoc}
@@ -33,6 +33,7 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
 
     // Don't add the additional fields to groupby
     if (!empty($this->options['link_to_node'])) {
+      $this->additional_fields['nid'] = array('table' => 'node', 'field' => 'nid');
       $this->additional_fields['nid'] = array('table' => 'node_field_data', 'field' => 'nid');
     }
   }
@@ -40,6 +41,15 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
   /**
    * {@inheritdoc}
    */
+  public function query() {
+    $this->ensureMyTable();
+    // Add the field.
+    $params = $this->options['group_type'] != 'group' ? array('function' => $this->options['group_type']) : array();
+    $this->field_alias = $this->query->addField($this->tableAlias, $this->realField, NULL, $params);
+
+    $this->addAdditionalFields();
+  }
+
   protected function defineOptions() {
     $options = parent::defineOptions();
     $options['link_to_node'] = array('default' => isset($this->definition['link_to_node default']) ? $this->definition['link_to_node default'] : FALSE);
@@ -76,16 +86,6 @@ protected function renderLink($data, ResultRow $values) {
       if ($data !== NULL && $data !== '') {
         $this->options['alter']['make_link'] = TRUE;
         $this->options['alter']['url'] = Url::fromRoute('entity.node.canonical', ['node' => $this->getValue($values, 'nid')]);
-        if (isset($this->aliases['langcode'])) {
-          $languages = \Drupal::languageManager()->getLanguages();
-          $langcode = $this->getValue($values, 'langcode');
-          if (isset($languages[$langcode])) {
-            $this->options['alter']['language'] = $languages[$langcode];
-          }
-          else {
-            unset($this->options['alter']['language']);
-          }
-        }
       }
       else {
         $this->options['alter']['make_link'] = FALSE;
diff --git a/core/modules/user/src/Plugin/views/field/LinkEdit.php b/core/modules/user/src/Plugin/views/field/LinkEdit.php
deleted file mode 100644
index bb288631..0000000
--- a/core/modules/user/src/Plugin/views/field/LinkEdit.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\user\Plugin\views\field\LinkEdit.
- */
-
-namespace Drupal\user\Plugin\views\field;
-
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\views\ResultRow;
-
-/**
- * Field handler to present a link to user edit.
- *
- * @ingroup views_field_handlers
- *
- * @ViewsField("user_link_edit")
- */
-class LinkEdit extends Link {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function renderLink(EntityInterface $entity, ResultRow $values) {
-    if ($entity && $entity->access('update')) {
-      $this->options['alter']['make_link'] = TRUE;
-
-      $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Edit');
-
-      $this->options['alter']['url'] = $entity->urlInfo('edit-form', ['query' => ['destination' => drupal_get_destination()]]);
-
-      return $text;
-    }
-  }
-
-}
diff --git a/core/modules/user/src/UserViewsData.php b/core/modules/user/src/UserViewsData.php
index d47651c..d217f546 100644
--- a/core/modules/user/src/UserViewsData.php
+++ b/core/modules/user/src/UserViewsData.php
@@ -227,15 +227,6 @@ public function getViewsData() {
       );
     }
 
-    $data['users']['edit_node'] = array(
-      'field' => array(
-        'title' => t('Link to edit user'),
-        'help' => t('Provide a simple link to edit the user.'),
-        'id' => 'user_link_edit',
-        'click sortable' => FALSE,
-      ),
-    );
-
     $data['users']['cancel_node'] = array(
       'field' => array(
         'title' => t('Link to cancel user'),
diff --git a/core/modules/views/config/schema/views.field.schema.yml b/core/modules/views/config/schema/views.field.schema.yml
index de8ffcb..6c310a2 100644
--- a/core/modules/views/config/schema/views.field.schema.yml
+++ b/core/modules/views/config/schema/views.field.schema.yml
@@ -171,11 +171,22 @@ views.field.url:
 views.field.language:
   type: views_field
   label: 'Language'
+
+views.field.entity_link:
+  type: views_field
+  label: 'Entity link'
   mapping:
     native_language:
       type: boolean
       label: 'Display in native language'
+    text:
+      type: label
+      label: 'Text to display'
 
+views.field.entity_link_delete:
+  type: views.field.entity_link
+  label: 'Entity delete link'
+  mapping:
 views.field.bulk_form:
   type: views_field_bulk_form
   label: 'Bulk form'
@@ -183,8 +194,12 @@ views.field.bulk_form:
 views.field.field:
   type: views_field
   label: 'Views entity field handler'
+views.field.entity_link_edit:
+  type: views.field.entity_link
+  label: 'Entity edit link'
   mapping:
     click_sort_column:
+    text:
       type: string
       label: 'Column used for click sorting'
     type:
@@ -223,6 +238,7 @@ views.field.field:
     separator:
       type: label
       label: 'Separator'
+      label: 'Text to display'
     field_api_classes:
       type: boolean
       label: 'Use field template'
diff --git a/core/modules/views/src/EntityViewsData.php b/core/modules/views/src/EntityViewsData.php
index a22fd02..fa1cf3e 100644
--- a/core/modules/views/src/EntityViewsData.php
+++ b/core/modules/views/src/EntityViewsData.php
@@ -203,6 +203,8 @@ public function getViewsData() {
       }
     }
 
+    $this->addEntityLinks($data[$base_table]);
+
     // Load all typed data definitions of all fields. This should cover each of
     // the entity base, revision, data tables.
     $field_definitions = $this->entityManager->getBaseFieldDefinitions($this->entityType->id());
@@ -230,6 +232,44 @@ public function getViewsData() {
   }
 
   /**
+   * Sets the entity links in case corresponding link templates exist.
+   *
+   * @param array $data
+   *   The views data of the base table.
+   */
+  protected function addEntityLinks(array &$data) {
+    $entity_type_id = $this->entityType->id();
+    $t_arguments = ['@entity_type_label' => $this->entityType->getLabel()];
+    if ($this->entityType->hasLinkTemplate('canonical')) {
+      $data['view_' . $entity_type_id] = [
+        'field' => [
+          'title' => $this->t('Link to @entity_type_label', $t_arguments),
+          'help' => $this->t('Provide a view link to the @entity_type_label.', $t_arguments),
+          'id' => 'entity_link',
+        ],
+      ];
+    }
+    if ($this->entityType->hasLinkTemplate('edit-form')) {
+      $data['edit_' . $entity_type_id] = [
+        'field' => [
+          'title' => $this->t('Link to edit @entity_type_label', $t_arguments),
+          'help' => $this->t('Provide an edit link to the @entity_type_label.', $t_arguments),
+          'id' => 'entity_link_edit',
+        ],
+      ];
+    }
+    if ($this->entityType->hasLinkTemplate('delete-form')) {
+      $data['delete_' . $entity_type_id] = [
+        'field' => [
+          'title' => $this->t('Link to delete @entity_type_label', $t_arguments),
+          'help' => $this->t('Provide a delete link to the @entity_type_label.', $t_arguments),
+          'id' => 'entity_link_delete',
+        ],
+      ];
+    }
+  }
+
+  /**
    * Puts the views data for a single field onto the views data.
    *
    * @param string $table
diff --git a/core/modules/views/src/Plugin/views/field/EntityLink.php b/core/modules/views/src/Plugin/views/field/EntityLink.php
new file mode 100644
index 0000000..7cf6fff
--- /dev/null
+++ b/core/modules/views/src/Plugin/views/field/EntityLink.php
@@ -0,0 +1,121 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Plugin\views\field\EntityLink.
+ */
+
+namespace Drupal\views\Plugin\views\field;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\views\Plugin\views\display\DisplayPluginBase;
+use Drupal\views\Plugin\views\field\FieldPluginBase;
+use Drupal\views\ResultRow;
+use Drupal\views\ViewExecutable;
+
+/**
+ * Field handler to present a link to the entity_link.
+ *
+ * @ingroup views_field_handlers
+ *
+ * @ViewsField("entity_link")
+ */
+class EntityLink extends FieldPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
+    parent::init($view, $display, $options);
+
+    // @FIXME
+    // $this->additional_fields['langcode'] = ['table' => 'node_field_data', 'field' => 'langcode'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function usesGroupBy() {
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function defineOptions() {
+    $options = parent::defineOptions();
+    $options['text'] = ['default' => '', 'translatable' => TRUE];
+    return $options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+    $form['text'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Text to display'),
+      '#default_value' => $this->options['text'],
+    ];
+    parent::buildOptionsForm($form, $form_state);
+
+    // The path is set by renderLink function so don't allow to set it.
+    $form['alter']['path'] = ['#access' => FALSE];
+    $form['alter']['external'] = ['#access' => FALSE];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function query() {
+    $this->addAdditionalFields();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function render(ResultRow $values) {
+    if ($entity = $this->getEntity($values)) {
+      return $this->renderLink($entity, $values);
+    }
+  }
+
+  /**
+   * Prepares the link to view a entity.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The node entity this field belongs to.
+   * @param \Drupal\views\ResultRow $values
+   *   The values retrieved from the view's result set.
+   *
+   * @return string
+   *   Returns a string for the link text.
+   */
+  protected function renderLink($entity, ResultRow $values) {
+    if ($entity->access('view')) {
+      $this->options['alter']['make_link'] = TRUE;
+      $this->options['alter']['path'] = $entity->getSystemPath();
+
+      $this->addLangcode($values);
+
+      $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('view');
+      return $text;
+    }
+  }
+
+  /**
+   * @param \Drupal\views\ResultRow $values
+   */
+  protected function addLangcode(ResultRow $values) {
+    if (isset($this->aliases['langcode'])) {
+      $languages = language_list();
+      $langcode = $this->getValue($values, 'langcode');
+      if (isset($languages[$langcode])) {
+        $this->options['alter']['language'] = $languages[$langcode];
+      }
+      else {
+        unset($this->options['alter']['language']);
+      }
+    }
+  }
+}
diff --git a/core/modules/views/src/Plugin/views/field/EntityLinkDelete.php b/core/modules/views/src/Plugin/views/field/EntityLinkDelete.php
new file mode 100644
index 0000000..e08b7bc
--- /dev/null
+++ b/core/modules/views/src/Plugin/views/field/EntityLinkDelete.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Plugin\views\field\EntityLinkDelete.
+ */
+
+namespace Drupal\views\Plugin\views\field;
+
+use Drupal\views\ResultRow;
+
+/**
+ * Field handler to present a link to delete an entity.
+ *
+ * @ingroup views_field_handlers
+ *
+ * @ViewsField("entity_link_delete")
+ */
+class EntityLinkDelete extends EntityLink {
+
+  /**
+   * Prepares the link to delete an entity.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The node entity this field belongs to.
+   * @param \Drupal\views\ResultRow $values
+   *   The values retrieved from the view's result set.
+   *
+   * @return string
+   *   Returns a string for the link text.
+   */
+  protected function renderLink($entity, ResultRow $values) {
+    // Ensure user has access to delete this node.
+    if ($entity && $entity->access('delete')) {
+      $this->options['alter']['make_link'] = TRUE;
+      $this->options['alter']['path'] = $entity->getSystemPath('delete-form');
+      $this->options['alter']['query'] = drupal_get_destination();
+
+      $this->addLangcode($values);
+
+      $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('delete');
+      return $text;
+    }
+  }
+
+}
diff --git a/core/modules/views/src/Plugin/views/field/EntityLinkEdit.php b/core/modules/views/src/Plugin/views/field/EntityLinkEdit.php
new file mode 100644
index 0000000..38911b4
--- /dev/null
+++ b/core/modules/views/src/Plugin/views/field/EntityLinkEdit.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\views\Plugin\views\field\EntityLinkEdit.
+ */
+
+namespace Drupal\views\Plugin\views\field;
+
+use Drupal\views\ResultRow;
+
+/**
+ * Field handler to present a link to edit an entity.
+ *
+ * @ingroup views_field_handlers
+ *
+ * @ViewsField("entity_link_edit")
+ */
+class EntityLinkEdit extends EntityLink {
+
+  /**
+   * Prepares the link to edit an entity.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The node entity this field belongs to.
+   * @param \Drupal\views\ResultRow $values
+   *   The values retrieved from the view's result set.
+   *
+   * @return string
+   *   Returns a string for the link text.
+   */
+  protected function renderLink($entity, ResultRow $values) {
+    // Ensure user has access to delete this node.
+    if ($entity && $entity->access('update')) {
+      $this->options['alter']['make_link'] = TRUE;
+      $this->options['alter']['path'] = $entity->getSystemPath('edit-form');
+      $this->options['alter']['query'] = drupal_get_destination();
+
+      $this->addLangcode($values);
+
+      $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('edit');
+      return $text;
+    }
+  }
+
+}
diff --git a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
index 56d1596..fb34794 100644
--- a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
+++ b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
@@ -712,6 +712,33 @@ protected function assertField($data, $field_name) {
   }
 
   /**
+   * Tests add link types.
+   */
+  public function testEntityLinks() {
+    $this->baseEntityType->setLinkTemplate('canonical', '/entity_test/{entity_test}');
+    $this->baseEntityType->setLinkTemplate('edit-form', '/entity_test/{entity_test}/edit');
+    $this->baseEntityType->setLinkTemplate('delete-form', '/entity_test/{entity_test}/delete');
+
+    $data = $this->viewsData->getViewsData();
+    $this->assertEquals('entity_link', $data['entity_test']['view_entity_test']['field']['id']);
+    $this->assertEquals('entity_link_edit', $data['entity_test']['edit_entity_test']['field']['id']);
+    $this->assertEquals('entity_link_delete', $data['entity_test']['delete_entity_test']['field']['id']);
+  }
+
+  /**
+   * Tests additional edit links.
+   */
+  public function testEntityLinksJustEditForm() {
+    $this->baseEntityType->setLinkTemplate('edit-form', '/entity_test/{entity_test}/edit');
+
+    $data = $this->viewsData->getViewsData();
+    $this->assertFalse(isset($data['entity_test']['view_entity_test']));
+    $this->assertFalse(isset($data['entity_test']['delete_entity_test']));
+
+    $this->assertEquals('entity_link_edit', $data['entity_test']['edit_entity_test']['field']['id']);
+  }
+
+  /**
    * Tests views data for a string field.
    *
    * @param $data
