diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityListBuilder.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityListBuilder.php
index b42e63a..2bf8807 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityListBuilder.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityListBuilder.php
@@ -30,8 +30,9 @@ public function load() {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $entity */
+    $operations = parent::getDefaultOperations($entity);
 
     if ($this->entityType->hasKey('status')) {
       if (!$entity->status() && $entity->hasLinkTemplate('enable')) {
diff --git a/core/lib/Drupal/Core/Entity/EntityListBuilder.php b/core/lib/Drupal/Core/Entity/EntityListBuilder.php
index 33a4008..b7b1347 100644
--- a/core/lib/Drupal/Core/Entity/EntityListBuilder.php
+++ b/core/lib/Drupal/Core/Entity/EntityListBuilder.php
@@ -93,6 +93,25 @@ protected function getLabel(EntityInterface $entity) {
    * {@inheritdoc}
    */
   public function getOperations(EntityInterface $entity) {
+    $operations = $this->getDefaultOperations($entity);
+    $operations += $this->moduleHandler()->invokeAll('entity_operation', array($entity));
+    $this->moduleHandler->alter('entity_operation', $operations, $entity);
+    uasort($operations, '\Drupal\Component\Utility\SortArray::sortByWeightElement');
+
+    return $operations;
+  }
+
+  /**
+   * Gets this list's default operations.
+   *
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity the operations are for.
+   *
+   * @return array
+   *   The array structure is identical to the return value of
+   *   self::getOperations().
+   */
+  protected function getDefaultOperations(EntityInterface $entity) {
     $operations = array();
     if ($entity->access('update') && $entity->hasLinkTemplate('edit-form')) {
       $operations['edit'] = array(
@@ -151,14 +170,11 @@ public function buildRow(EntityInterface $entity) {
    * @see \Drupal\Core\Entity\EntityListBuilder::buildRow()
    */
   public function buildOperations(EntityInterface $entity) {
-    // Retrieve and sort operations.
-    $operations = $this->getOperations($entity);
-    $this->moduleHandler()->alter('entity_operation', $operations, $entity);
-    uasort($operations, array('Drupal\Component\Utility\SortArray', 'sortByWeightElement'));
     $build = array(
       '#type' => 'operations',
-      '#links' => $operations,
+      '#links' => $this->getOperations($entity),
     );
+
     return $build;
   }
 
diff --git a/core/modules/action/lib/Drupal/action/ActionListBuilder.php b/core/modules/action/lib/Drupal/action/ActionListBuilder.php
index 76c4f2f..2351cbc 100644
--- a/core/modules/action/lib/Drupal/action/ActionListBuilder.php
+++ b/core/modules/action/lib/Drupal/action/ActionListBuilder.php
@@ -101,8 +101,8 @@ public function buildHeader() {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = $entity->isConfigurable() ? parent::getOperations($entity) : array();
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = $entity->isConfigurable() ? parent::getDefaultOperations($entity) : array();
     if (isset($operations['edit'])) {
       $operations['edit']['title'] = t('Configure');
     }
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockListBuilder.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockListBuilder.php
index 94c9e31..5df5a19 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockListBuilder.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockListBuilder.php
@@ -36,8 +36,8 @@ public function buildRow(EntityInterface $entity) {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
     if (isset($operations['edit'])) {
       $operations['edit']['query']['destination'] = 'admin/structure/block/custom-blocks';
     }
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListBuilder.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListBuilder.php
index 1c09e9f..67f2bff 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListBuilder.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeListBuilder.php
@@ -20,8 +20,8 @@ class CustomBlockTypeListBuilder extends ConfigEntityListBuilder {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
     // Place the edit operation after the operations added by field_ui.module
     // which have the weights 15, 20, 25.
     if (isset($operations['edit'])) {
diff --git a/core/modules/block/lib/Drupal/block/BlockListBuilder.php b/core/modules/block/lib/Drupal/block/BlockListBuilder.php
index 1b93f8c..0bd7045 100644
--- a/core/modules/block/lib/Drupal/block/BlockListBuilder.php
+++ b/core/modules/block/lib/Drupal/block/BlockListBuilder.php
@@ -378,8 +378,8 @@ public function buildForm(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
 
     if (isset($operations['edit'])) {
       $operations['edit']['title'] = t('Configure');
diff --git a/core/modules/config_translation/config_translation.module b/core/modules/config_translation/config_translation.module
index 0db169e..bfa9275 100644
--- a/core/modules/config_translation/config_translation.module
+++ b/core/modules/config_translation/config_translation.module
@@ -144,15 +144,17 @@ function config_translation_config_translation_info(&$info) {
 }
 
 /**
- * Implements hook_entity_operation_alter().
+ * Implements hook_entity_operation().
  */
-function config_translation_entity_operation_alter(array &$operations, EntityInterface $entity) {
+function config_translation_entity_operation(EntityInterface $entity) {
+  $operatoins = array();
   if (\Drupal::currentUser()->hasPermission('translate configuration')) {
     $operations['translate'] = array(
       'title' => t('Translate'),
       'weight' => 50,
     ) + $entity->urlInfo('drupal:config-translation-overview')->toArray();
   }
+  return $operations;
 }
 
 /**
diff --git a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListBuilder.php b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListBuilder.php
index 44f5aad..9d94468 100644
--- a/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListBuilder.php
+++ b/core/modules/config_translation/lib/Drupal/config_translation/Controller/ConfigTranslationEntityListBuilder.php
@@ -83,13 +83,13 @@ public function buildHeader() {
   /**
    * {@inheritdoc}
    */
-  public function buildOperations(EntityInterface $entity) {
-    $operations = parent::buildOperations($entity);
-    foreach (array_keys($operations['#links']) as $operation) {
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
+    foreach (array_keys($operations) as $operation) {
       // This is a translation UI for translators. Show the translation
       // operation only.
       if (!($operation == 'translate')) {
-        unset($operations['#links'][$operation]);
+        unset($operations[$operation]);
       }
     }
     return $operations;
diff --git a/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php b/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php
index 3eea9cb..a87208d 100644
--- a/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php
+++ b/core/modules/field/lib/Drupal/field/Entity/FieldInstanceConfig.php
@@ -23,6 +23,7 @@
  *   id = "field_instance_config",
  *   label = @Translation("Field instance"),
  *   controllers = {
+ *     "list_builder" = "\Drupal\field_ui\FieldInstanceConfigListBuilder",
  *     "storage" = "Drupal\field\FieldInstanceConfigStorage"
  *   },
  *   config_prefix = "instance",
diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module
index 24e5221..5f96f28 100644
--- a/core/modules/field_ui/field_ui.module
+++ b/core/modules/field_ui/field_ui.module
@@ -158,9 +158,10 @@ function field_ui_form_node_type_form_alter(&$form, $form_state) {
 }
 
 /**
- * Implements hook_entity_operation_alter().
+ * Implements hook_entity_operation().
  */
-function field_ui_entity_operation_alter(array &$operations, EntityInterface $entity) {
+function field_ui_entity_operation(EntityInterface $entity) {
+  $operations = array();
   $info = $entity->getEntityType();
   // Add manage fields and display links if this entity type is the bundle
   // of another.
@@ -184,6 +185,8 @@ function field_ui_entity_operation_alter(array &$operations, EntityInterface $en
       ) + $entity->urlInfo('field_ui-display')->toArray();
     }
   }
+
+  return $operations;
 }
 
 /**
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldInstanceConfigListBuilder.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldInstanceConfigListBuilder.php
new file mode 100644
index 0000000..9eefbea
--- /dev/null
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldInstanceConfigListBuilder.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\field_ui\FieldInstanceListConfigBuilder.
+ */
+
+namespace Drupal\field_ui;
+
+use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides lists of field instance config entities.
+ */
+class FieldInstanceListConfigBuilder extends ConfigEntityListBuilder {
+
+  /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
+   * Constructs a new class instance.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+   *   The entity type definition.
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   */
+  public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager) {
+    parent::__construct($entity_type, $entity_manager->getStorage($entity_type->id()));
+    $this->entityManager = $entity_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
+    return new static($entity_type, $container->get('entity.manager'));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function render() {
+    // The actual field instance config overview is rendered by
+    // \Drupal\field_ui\FieldOverview, so we should not use this class to build
+    // lists.
+    throw new \Exception('This class is only used for operations and not for building lists.');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefaultOperations(EntityInterface $entity) {
+    /** @var \Drupal\field\FieldInstanceConfigInterface $entity */
+    $operations = parent::getDefaultOperations($entity);
+
+    $target_entity_type_bundle_entity_type_id = $this->entityManager->getDefinition($entity->getTargetEntityTypeId())->getBundleEntityType();
+    $route_parameters = array(
+      $target_entity_type_bundle_entity_type_id => $entity->targetBundle(),
+      'field_instance_config' => $entity->id(),
+    );
+    $operations['edit'] = array(
+      'title' => $this->t('Edit'),
+      'route_name' => 'field_ui.instance_edit_' . $entity->getTargetEntityTypeId(),
+      'route_parameters' => $route_parameters,
+      'attributes' => array('title' => $this->t('Edit instance settings.')),
+    );
+    $operations['field-settings'] = array(
+      'title' => $this->t('Field settings'),
+      'route_name' => 'field_ui.field_edit_' . $entity->getTargetEntityTypeId(),
+      'route_parameters' => $route_parameters,
+      'attributes' => array('title' => $this->t('Edit field settings.')),
+    );
+    $operations['delete'] = array(
+      'title' => $this->t('Delete'),
+      'route_name' => 'field_ui.delete_' . $entity->getTargetEntityTypeId(),
+      'route_parameters' => $route_parameters,
+      'attributes' => array('title' => $this->t('Delete instance.')),
+    );
+
+    return $operations;
+  }
+
+}
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
index 01c65ed..0ddd582 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\field_ui;
 
+use Drupal\Core\Entity\EntityListBuilderInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Field\FieldTypePluginManagerInterface;
@@ -27,26 +28,16 @@ class FieldOverview extends OverviewBase {
   protected $fieldTypeManager;
 
   /**
-   * The module handler service.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
    * Constructs a new FieldOverview.
    *
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
    *   The entity manager.
    * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
    *   The field type manager
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
    */
-  public function __construct(EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager, ModuleHandlerInterface $module_handler) {
+  public function __construct(EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager) {
     parent::__construct($entity_manager);
     $this->fieldTypeManager = $field_type_manager;
-    $this->moduleHandler = $module_handler;
   }
 
   /**
@@ -55,8 +46,7 @@ public function __construct(EntityManagerInterface $entity_manager, FieldTypePlu
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('entity.manager'),
-      $container->get('plugin.manager.field.field_type'),
-      $container->get('module_handler')
+      $container->get('plugin.manager.field.field_type')
     );
   }
 
@@ -145,30 +135,9 @@ public function buildForm(array $form, array &$form_state, $entity_type_id = NUL
         ),
       );
 
-      $links = array();
-      $links['edit'] = array(
-        'title' => $this->t('Edit'),
-        'route_name' => 'field_ui.instance_edit_' . $this->entity_type,
-        'route_parameters' => $route_parameters,
-        'attributes' => array('title' => $this->t('Edit instance settings.')),
-      );
-      $links['field-settings'] = array(
-        'title' => $this->t('Field settings'),
-        'route_name' => 'field_ui.field_edit_' . $this->entity_type,
-        'route_parameters' => $route_parameters,
-        'attributes' => array('title' => $this->t('Edit field settings.')),
-      );
-      $links['delete'] = array(
-        'title' => $this->t('Delete'),
-        'route_name' => 'field_ui.delete_' . $this->entity_type,
-        'route_parameters' => $route_parameters,
-        'attributes' => array('title' => $this->t('Delete instance.')),
-      );
-      // Allow altering the operations on this entity listing.
-      $this->moduleHandler->alter('entity_operation', $links, $instance);
       $table[$name]['operations']['data'] = array(
         '#type' => 'operations',
-        '#links' => $links,
+        '#links' => $this->entityManager->getListBuilder('field_instance_config')->getOperations($instance),
       );
 
       if (!empty($field->locked)) {
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
index 979d68b..8860010 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageFieldsTest.php
@@ -106,6 +106,11 @@ function manageFieldsPage($type = '') {
     foreach (array('Add new field', 'Re-use existing field') as $element) {
       $this->assertText($element, format_string('"@element" was found.', array('@element' => $element)));
     }
+
+    // Assert entity operations for all field instances.
+    $this->assertLinkByHref("admin/structure/types/manage/$type/fields/node.$type.body");
+    $this->assertLinkByHref("admin/structure/types/manage/$type/fields/node.$type.body/delete");
+    $this->assertLinkByHref("admin/structure/types/manage/$type/fields/node.$type.body/field");
   }
 
   /**
diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatListBuilder.php b/core/modules/filter/lib/Drupal/filter/FilterFormatListBuilder.php
index a22b998..06ad870 100644
--- a/core/modules/filter/lib/Drupal/filter/FilterFormatListBuilder.php
+++ b/core/modules/filter/lib/Drupal/filter/FilterFormatListBuilder.php
@@ -118,8 +118,8 @@ public function buildRow(EntityInterface $entity) {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
 
     if (isset($operations['edit'])) {
       $operations['edit']['title'] = t('Configure');
diff --git a/core/modules/image/lib/Drupal/image/ImageStyleListBuilder.php b/core/modules/image/lib/Drupal/image/ImageStyleListBuilder.php
index 26642dd..73dfe6c 100644
--- a/core/modules/image/lib/Drupal/image/ImageStyleListBuilder.php
+++ b/core/modules/image/lib/Drupal/image/ImageStyleListBuilder.php
@@ -74,13 +74,15 @@ public function buildRow(EntityInterface $entity) {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
+  public function getDefaultOperations(EntityInterface $entity) {
     $flush = array(
       'title' => t('Flush'),
       'weight' => 200,
     ) + $entity->urlInfo('flush-form')->toArray();
 
-    return parent::getOperations($entity) + array('flush' => $flush);
+    return parent::getDefaultOperations($entity) + array(
+      'flush' => $flush,
+    );
   }
 
   /**
diff --git a/core/modules/language/lib/Drupal/language/LanguageListBuilder.php b/core/modules/language/lib/Drupal/language/LanguageListBuilder.php
index 99fb967..c5bd66a 100644
--- a/core/modules/language/lib/Drupal/language/LanguageListBuilder.php
+++ b/core/modules/language/lib/Drupal/language/LanguageListBuilder.php
@@ -44,8 +44,8 @@ public function getFormId() {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
     $default = language_default();
 
     // Deleting the site default language is not allowed.
diff --git a/core/modules/menu/lib/Drupal/menu/MenuListBuilder.php b/core/modules/menu/lib/Drupal/menu/MenuListBuilder.php
index 31f5db4..57d62b6 100644
--- a/core/modules/menu/lib/Drupal/menu/MenuListBuilder.php
+++ b/core/modules/menu/lib/Drupal/menu/MenuListBuilder.php
@@ -45,8 +45,8 @@ public function buildRow(EntityInterface $entity) {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
 
     if (isset($operations['edit'])) {
       $operations['edit']['title'] = t('Edit menu');
diff --git a/core/modules/node/lib/Drupal/node/NodeListBuilder.php b/core/modules/node/lib/Drupal/node/NodeListBuilder.php
index c888155..51b2485 100644
--- a/core/modules/node/lib/Drupal/node/NodeListBuilder.php
+++ b/core/modules/node/lib/Drupal/node/NodeListBuilder.php
@@ -124,8 +124,8 @@ public function buildRow(EntityInterface $entity) {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  protected function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
 
     $destination = drupal_get_destination();
     foreach ($operations as $key => $operation) {
diff --git a/core/modules/node/lib/Drupal/node/NodeTypeListBuilder.php b/core/modules/node/lib/Drupal/node/NodeTypeListBuilder.php
index 9dfe695..45bac57 100644
--- a/core/modules/node/lib/Drupal/node/NodeTypeListBuilder.php
+++ b/core/modules/node/lib/Drupal/node/NodeTypeListBuilder.php
@@ -83,8 +83,8 @@ public function buildRow(EntityInterface $entity) {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
     // Place the edit operation after the operations added by field_ui.module
     // which have the weights 15, 20, 25.
     if (isset($operations['edit'])) {
diff --git a/core/modules/responsive_image/lib/Drupal/responsive_image/ResponsiveImageMappingListBuilder.php b/core/modules/responsive_image/lib/Drupal/responsive_image/ResponsiveImageMappingListBuilder.php
index ce1f56d..b12fb61 100644
--- a/core/modules/responsive_image/lib/Drupal/responsive_image/ResponsiveImageMappingListBuilder.php
+++ b/core/modules/responsive_image/lib/Drupal/responsive_image/ResponsiveImageMappingListBuilder.php
@@ -36,8 +36,8 @@ public function buildRow(EntityInterface $entity) {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
     $operations['duplicate'] = array(
       'title' => t('Duplicate'),
       'weight' => 15,
diff --git a/core/modules/search/lib/Drupal/search/SearchPageListBuilder.php b/core/modules/search/lib/Drupal/search/SearchPageListBuilder.php
index 6d82d20..d9bb5e3 100644
--- a/core/modules/search/lib/Drupal/search/SearchPageListBuilder.php
+++ b/core/modules/search/lib/Drupal/search/SearchPageListBuilder.php
@@ -260,9 +260,9 @@ public function buildForm(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
+  public function getDefaultOperations(EntityInterface $entity) {
     /** @var $entity \Drupal\search\SearchPageInterface */
-    $operations = parent::getOperations($entity);
+    $operations = parent::getDefaultOperations($entity);
 
     // Prevent the default search from being disabled or deleted.
     if ($entity->isDefaultSearch()) {
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetListBuilder.php b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetListBuilder.php
index fcdfb97..907f470 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetListBuilder.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/ShortcutSetListBuilder.php
@@ -28,8 +28,8 @@ public function buildHeader() {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
 
     if (isset($operations['edit'])) {
       $operations['edit']['title'] = t('Edit shortcut set');
diff --git a/core/modules/system/entity.api.php b/core/modules/system/entity.api.php
index 315d55d..947bf38 100644
--- a/core/modules/system/entity.api.php
+++ b/core/modules/system/entity.api.php
@@ -756,6 +756,27 @@ function hook_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\Entit
 }
 
 /**
+ * Declares entity operations.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity on which the linked operations will be performed.
+ *
+ * @return array
+ *   An operations array as returned by
+ *   \Drupal\Core\Entity\EntityListBuilderInterface::getOperations().
+ */
+function hook_entity_operation(\Drupal\Core\Entity\EntityInterface $entity) {
+  $operations = array();
+  $operations['translate'] = array(
+    'title' => t('Translate'),
+    'route_name' => 'foo_module.entity.translate',
+    'weight' => 50,
+  );
+
+  return $operations;
+}
+
+/**
  * Alter entity operations.
  *
  * @param array $operations
@@ -765,10 +786,11 @@ function hook_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\Entit
  *   The entity on which the linked operations will be performed.
  */
 function hook_entity_operation_alter(array &$operations, \Drupal\Core\Entity\EntityInterface $entity) {
-  $operations['translate'] = array(
-    'title' => t('Translate'),
-    'weight' => 50,
-  ) + $entity->urlInfo('my-custom-link-template')->toArray();
+  // Alter the title and weight.
+  $operations['translate']['title'] = t('Translate @entity_type', array(
+    '@entity_type' => $entity->getEntityTypeId(),
+  ));
+  $operations['translate']['weight'] = 99;
 }
 
 /**
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListBuilder.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListBuilder.php
index f760aa5..8018876 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListBuilder.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyListBuilder.php
@@ -32,8 +32,8 @@ public function getFormId() {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
 
     if (isset($operations['edit'])) {
       $operations['edit']['title'] = t('edit vocabulary');
diff --git a/core/modules/user/lib/Drupal/user/RoleListBuilder.php b/core/modules/user/lib/Drupal/user/RoleListBuilder.php
index 0d557c7..afe8d7b 100644
--- a/core/modules/user/lib/Drupal/user/RoleListBuilder.php
+++ b/core/modules/user/lib/Drupal/user/RoleListBuilder.php
@@ -43,8 +43,8 @@ public function buildRow(EntityInterface $entity) {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
 
     if ($entity->hasLinkTemplate('edit-permissions-form')) {
       $operations['permissions'] = array(
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewListBuilder.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewListBuilder.php
index 2adf662..0242f5b 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewListBuilder.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewListBuilder.php
@@ -135,8 +135,8 @@ public function buildHeader() {
   /**
    * {@inheritdoc}
    */
-  public function getOperations(EntityInterface $entity) {
-    $operations = parent::getOperations($entity);
+  public function getDefaultOperations(EntityInterface $entity) {
+    $operations = parent::getDefaultOperations($entity);
 
     if ($entity->hasLinkTemplate('clone')) {
       $operations['clone'] = array(
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php
index b413675..f6d4129 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php
@@ -7,7 +7,9 @@
 
 namespace Drupal\Tests\Core\Entity;
 
+use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityListBuilder;
 use Drupal\entity_test\EntityTestListBuilder;
 use Drupal\Tests\UnitTestCase;
 
@@ -21,6 +23,41 @@
 class EntityListBuilderTest extends UnitTestCase {
 
   /**
+   * The entity type used for testing.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $entityType;
+
+  /**
+   * The module handler used for testing.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $moduleHandler;
+
+  /**
+   * The translation manager used for testing.
+   *
+   * @var \Drupal\Core\StringTranslation\TranslationInterface
+   */
+  protected $translationManager;
+
+  /**
+   * The role storage used for testing.
+   *
+   * @var \Drupal\user\RoleStorageInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $roleStorage;
+
+  /**
+   * The service container used for testing.
+   *
+   * @var \Drupal\Core\DependencyInjection\ContainerBuilder
+   */
+  protected $container;
+
+  /**
    * The entity used to construct the EntityListBuilder.
    *
    * @var \Drupal\user\RoleInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -49,10 +86,65 @@ protected function setUp() {
     parent::setUp();
 
     $this->role = $this->getMock('Drupal\user\RoleInterface');
-    $role_storage = $this->getMock('Drupal\user\RoleStorageInterface');
-    $module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
-    $entity_type = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
-    $this->entityListBuilder = new TestEntityListBuilder($entity_type, $role_storage, $module_handler);
+    $this->roleStorage = $this->getMock('\Drupal\user\RoleStorageInterface');
+    $this->moduleHandler = $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface');
+    $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface');
+    $this->translationManager = $this->getMock('\Drupal\Core\StringTranslation\TranslationInterface');
+    $this->entityListBuilder = new TestEntityListBuilder($this->entityType, $this->roleStorage, $this->moduleHandler);
+    $this->container = new ContainerBuilder();
+    \Drupal::setContainer($this->container);
+  }
+
+  /**
+   * @covers \Drupal\Core\Entity\EntityListBuilder::getOperations
+   */
+  public function testGetOperations() {
+    $operation_name = $this->randomName();
+    $operations = array(
+      $operation_name => array(
+        'title' => $this->randomName(),
+      ),
+    );
+    $this->moduleHandler->expects($this->once())
+      ->method('invokeAll')
+      ->with('entity_operation', array($this->role))
+      ->will($this->returnValue($operations));
+    $this->moduleHandler->expects($this->once())
+      ->method('alter')
+      ->with('entity_operation');
+
+    $this->container->set('module_handler', $this->moduleHandler);
+
+    $this->role->expects($this->any())
+      ->method('access')
+      ->will($this->returnValue(TRUE));
+    $this->role->expects($this->any())
+      ->method('hasLinkTemplate')
+      ->will($this->returnValue(TRUE));
+    $url = $this->getMockBuilder('\Drupal\Core\Url')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $url->expects($this->any())
+      ->method('toArray')
+      ->will($this->returnValue(array()));
+    $this->role->expects($this->any())
+      ->method('urlInfo')
+      ->will($this->returnValue($url));
+
+    $list = new EntityListBuilder($this->entityType, $this->roleStorage, $this->moduleHandler);
+    $list->setTranslationManager($this->translationManager);
+
+    $operations = $list->getOperations($this->role);
+    $this->assertInternalType('array', $operations);
+    $this->assertArrayHasKey('edit', $operations);
+    $this->assertInternalType('array', $operations['edit']);
+    $this->assertArrayHasKey('title', $operations['edit']);
+    $this->assertArrayHasKey('delete', $operations);
+    $this->assertInternalType('array', $operations['delete']);
+    $this->assertArrayHasKey('title', $operations['delete']);
+    $this->assertArrayHasKey($operation_name, $operations);
+    $this->assertInternalType('array', $operations[$operation_name]);
+    $this->assertArrayHasKey('title', $operations[$operation_name]);
   }
 
   /**
