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 4fb924f..5b79b92 100644
--- a/core/modules/aggregator/src/Plugin/views/field/TitleLink.php
+++ b/core/modules/aggregator/src/Plugin/views/field/TitleLink.php
@@ -9,7 +9,7 @@
 
 use Drupal\Core\Form\FormStateInterface;
 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;
 
@@ -21,7 +21,7 @@
  *
  * @ViewsField("aggregator_title_link")
  */
-class TitleLink extends FieldPluginBase {
+class TitleLink extends EntityLink {
 
   /**
    * {@inheritdoc}
@@ -75,12 +75,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;
-      $this->options['alter']['path'] = $link;
-      $this->options['alter']['html'] = TRUE;
-      $this->options['alter']['absolute'] = TRUE;
+      parent::renderLink($this->getEntity($values), $values);
     }
 
     return $data;
diff --git a/core/modules/comment/config/schema/comment.views.schema.yml b/core/modules/comment/config/schema/comment.views.schema.yml
index 51953ad..8f345b0 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 2a7083c..069a812 100644
--- a/core/modules/comment/src/CommentViewsData.php
+++ b/core/modules/comment/src/CommentViewsData.php
@@ -108,30 +108,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 f22563b..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']['path'] = $comment->getSystemPath('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 4e687a3..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']['path'] = "comment/" . $comment->id() . "/edit";
-
-    return $text;
-  }
-
-}
diff --git a/core/modules/node/config/install/views.view.content.yml b/core/modules/node/config/install/views.view.content.yml
index 2a44101..0b08eef 100644
--- a/core/modules/node/config/install/views.view.content.yml
+++ b/core/modules/node/config/install/views.view.content.yml
@@ -256,7 +256,7 @@ display:
           label: ''
           exclude: true
           text: Edit
-          plugin_id: node_link_edit
+          plugin_id: entity_link_edit
           entity_type: node
         delete_node:
           id: delete_node
@@ -265,7 +265,7 @@ display:
           label: ''
           exclude: true
           text: Delete
-          plugin_id: node_link_delete
+          plugin_id: entity_link_delete
           entity_type: node
         dropbutton:
           id: dropbutton
diff --git a/core/modules/node/config/install/views.view.content_recent.yml b/core/modules/node/config/install/views.view.content_recent.yml
index 9456436..a20d75c 100644
--- a/core/modules/node/config/install/views.view.content_recent.yml
+++ b/core/modules/node/config/install/views.view.content_recent.yml
@@ -263,7 +263,7 @@ display:
           empty_zero: false
           hide_alter_empty: true
           text: edit
-          plugin_id: node_link_edit
+          plugin_id: entity_link_edit
           entity_type: node
         delete_node:
           id: delete_node
@@ -314,7 +314,7 @@ display:
           empty_zero: false
           hide_alter_empty: true
           text: delete
-          plugin_id: node_link_delete
+          plugin_id: entity_link_delete
           entity_type: node
       filters:
         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 b1d24d9..9f2a53d 100644
--- a/core/modules/node/config/schema/node.views.schema.yml
+++ b/core/modules/node/config/schema/node.views.schema.yml
@@ -102,37 +102,13 @@ views.field.node_language:
       label: 'Native language'
 
 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 ca2bb26..1e1644f 100644
--- a/core/modules/node/src/NodeViewsData.php
+++ b/core/modules/node/src/NodeViewsData.php
@@ -36,7 +36,6 @@ public function getViewsData() {
     $data['node_field_data']['title']['field']['id'] = 'node';
     $data['node_field_data']['title']['field']['link_to_node default'] = TRUE;
 
-    $data['node_field_data']['type']['field']['id'] = 'node_type';
     $data['node_field_data']['type']['argument']['id'] = 'node_type';
 
     $data['node_field_data']['langcode']['help'] = t('The language of the content or translation.');
@@ -83,30 +82,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 a62e0f2..3740639 100644
--- a/core/modules/node/src/Plugin/views/field/Node.php
+++ b/core/modules/node/src/Plugin/views/field/Node.php
@@ -8,10 +8,10 @@
 namespace Drupal\node\Plugin\views\field;
 
 use Drupal\Core\Form\FormStateInterface;
+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.
@@ -22,10 +22,10 @@
  *
  * @ViewsField("node")
  */
-class Node extends FieldPluginBase {
+class Node extends EntityLink {
 
   /**
-   * Overrides \Drupal\views\Plugin\views\field\FieldPluginBase::init().
+   * {@inheritdoc}
    */
   public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
     parent::init($view, $display, $options);
@@ -36,6 +36,18 @@ 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);
@@ -72,16 +84,6 @@ protected function renderLink($data, ResultRow $values) {
       if ($data !== NULL && $data !== '') {
         $this->options['alter']['make_link'] = TRUE;
         $this->options['alter']['path'] = "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/config/install/views.view.user_admin_people.yml b/core/modules/user/config/install/views.view.user_admin_people.yml
index ff62509..8dd2bde 100644
--- a/core/modules/user/config/install/views.view.user_admin_people.yml
+++ b/core/modules/user/config/install/views.view.user_admin_people.yml
@@ -458,10 +458,10 @@ display:
           plugin_id: date
           entity_type: user
           entity_field: access
-        edit_node:
-          id: edit_node
+        edit_user:
+          id: edit_user
           table: users
-          field: edit_node
+          field: edit_user
           relationship: none
           group_type: group
           admin_label: ''
@@ -507,7 +507,7 @@ display:
           empty_zero: false
           hide_alter_empty: true
           text: Edit
-          plugin_id: user_link_edit
+          plugin_id: entity_link_edit
           entity_type: user
         dropbutton:
           id: dropbutton
diff --git a/core/modules/user/config/schema/user.views.schema.yml b/core/modules/user/config/schema/user.views.schema.yml
index e1b83f3..52aafc7 100644
--- a/core/modules/user/config/schema/user.views.schema.yml
+++ b/core/modules/user/config/schema/user.views.schema.yml
@@ -83,10 +83,6 @@ views.field.user_link_cancel:
   type: views.field.user_link
   label: 'User cancel link'
 
-views.field.user_link_edit:
-  type: views.field.user_link
-  label: 'User edit link'
-
 views.field.user_mail:
   type: views_field_user
   label: 'User language'
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 acf2100..2361f52 100644
--- a/core/modules/user/src/UserViewsData.php
+++ b/core/modules/user/src/UserViewsData.php
@@ -250,15 +250,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 c515361..574047a 100644
--- a/core/modules/views/config/schema/views.field.schema.yml
+++ b/core/modules/views/config/schema/views.field.schema.yml
@@ -178,3 +178,27 @@ views.field.xss:
 views.field.language:
   type: views_field
   label: 'Language'
+
+views.field.entity_link:
+  type: views_field
+  label: 'Entity link'
+  mapping:
+    text:
+      type: label
+      label: 'Text to display'
+
+views.field.entity_link_delete:
+  type: views.field.entity_link
+  label: 'Entity delete link'
+  mapping:
+    text:
+      type: label
+      label: 'Text to display'
+
+views.field.entity_link_edit:
+  type: views.field.entity_link
+  label: 'Entity edit link'
+  mapping:
+    text:
+      type: label
+      label: 'Text to display'
diff --git a/core/modules/views/src/EntityViewsData.php b/core/modules/views/src/EntityViewsData.php
index cb30422..e7188fa 100644
--- a/core/modules/views/src/EntityViewsData.php
+++ b/core/modules/views/src/EntityViewsData.php
@@ -183,6 +183,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());
@@ -210,6 +212,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 c1aac0f..72bdb42 100644
--- a/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
+++ b/core/modules/views/tests/src/Unit/EntityViewsDataTest.php
@@ -627,6 +627,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
