diff --git a/core/modules/entity_reference/entity_reference.views.inc b/core/modules/entity_reference/entity_reference.views.inc
index 030841552b993d4a9e41caf34693b476d2834f70..486fca131ac813ca23bb29520ce5e4730a819728 100644
--- a/core/modules/entity_reference/entity_reference.views.inc
+++ b/core/modules/entity_reference/entity_reference.views.inc
@@ -11,7 +11,7 @@
  * Implements hook_field_views_data().
  */
 function entity_reference_field_views_data(FieldStorageConfigInterface $field_storage) {
-  $data = field_views_field_default_views_data($field_storage);
+  $data = views_field_default_views_data($field_storage);
   $entity_manager = \Drupal::entityManager();
   $table_mapping = $entity_manager->getStorage($field_storage->getTargetEntityTypeId())->getTableMapping();
   foreach ($data as $table_name => $table_data) {
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 143e8c51f3a306489c28855e0de7cce7395b997e..82865d2e05489154c2a00ac361660ee465ef5f12 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -264,20 +264,6 @@ function _field_create_entity_from_ids($ids) {
   return entity_create($ids->entity_type, $id_properties);
 }
 
-/**
- * Implements hook_hook_info().
- */
-function field_hook_info() {
-  $hooks['field_views_data'] = array(
-    'group' => 'views',
-  );
-  $hooks['field_views_data_alter'] = array(
-    'group' => 'views',
-  );
-
-  return $hooks;
-}
-
 /**
  * Implements hook_config_import_steps_alter().
  */
diff --git a/core/modules/field/field.views.inc b/core/modules/field/field.views.inc
deleted file mode 100644
index cc263668baa108da3aa5af7417d9bf3e366e74a8..0000000000000000000000000000000000000000
--- a/core/modules/field/field.views.inc
+++ /dev/null
@@ -1,494 +0,0 @@
-<?php
-
-/**
- * @file
- * Provide Views data for field.module.
- */
-
-use Drupal\Component\Utility\NestedArray;
-use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
-use Drupal\Core\Entity\EntityStorageInterface;
-use Drupal\field\FieldStorageConfigInterface;
-use Drupal\field\FieldConfigInterface;
-
-/**
- * Implements hook_views_data().
- *
- * Field modules can implement hook_field_views_data() to override the default
- * behavior for adding fields.
- */
-function field_views_data() {
-  $data = array();
-  $module_handler = \Drupal::moduleHandler();
-
-  foreach (\Drupal::entityManager()->getStorage('field_storage_config')->loadMultiple() as $field_storage) {
-    if (_field_views_get_entity_type_storage($field_storage)) {
-      $result = (array) $module_handler->invoke($field_storage->module, 'field_views_data', array($field_storage));
-      if (empty($result)) {
-        $result = field_views_field_default_views_data($field_storage);
-      }
-      $module_handler->alter('field_views_data', $result, $field_storage);
-
-      if (is_array($result)) {
-        $data = NestedArray::mergeDeep($result, $data);
-      }
-    }
-  }
-
-  return $data;
-}
-
-/**
- * Implements hook_views_data_alter().
- *
- * Field modules can implement hook_field_views_data_views_data_alter() to
- * alter the views data on a per field basis. This is weirdly named so as
- * not to conflict with the \Drupal::moduleHandler()->alter('field_views_data')
- * in field_views_data.
- */
-function field_views_data_alter(&$data) {
-  foreach (\Drupal::entityManager()->getStorage('field_storage_config')->loadMultiple() as $field_storage) {
-    if (_field_views_get_entity_type_storage($field_storage)) {
-      $function = $field_storage->module . '_field_views_data_views_data_alter';
-      if (function_exists($function)) {
-        $function($data, $field_storage);
-      }
-    }
-  }
-}
-
-/**
- * Determines whether the entity type the field appears in is SQL based.
- *
- * @param \Drupal\field\FieldStorageConfigInterface $field_storage
- *   The field storage definition.
- *
- * @return \Drupal\Core\Entity\Sql\SqlContentEntityStorage
- *   Returns the entity type storage if supported.
- */
-function _field_views_get_entity_type_storage(FieldStorageConfigInterface $field_storage) {
-  $result = FALSE;
-  $entity_manager = \Drupal::entityManager();
-  if ($entity_manager->hasDefinition($field_storage->getTargetEntityTypeId())) {
-    $storage = $entity_manager->getStorage($field_storage->getTargetEntityTypeId());
-    $result = $storage instanceof SqlContentEntityStorage ? $storage : FALSE;
-  }
-  return $result;
-}
-
-/**
- * Returns the label of a certain field.
- *
- * Therefore it looks up in all bundles to find the most used field.
- */
-function field_views_field_label($entity_type, $field_name) {
-  $label_counter = array();
-  $all_labels = array();
-  // Count the amount of fields per label per field storage.
-  foreach (array_keys(\Drupal::entityManager()->getBundleInfo($entity_type)) as $bundle) {
-    $bundle_fields = array_filter(\Drupal::entityManager()->getFieldDefinitions($entity_type, $bundle), function ($field_definition) {
-      return $field_definition instanceof FieldConfigInterface;
-    });
-    if (isset($bundle_fields[$field_name])) {
-      $field = $bundle_fields[$field_name];
-      $label = $field->getLabel();
-      $label_counter[$label] = isset($label_counter[$label]) ? ++$label_counter[$label] : 1;
-      $all_labels[$label] = TRUE;
-    }
-  }
-  if (empty($label_counter)) {
-    return array($field_name, $all_labels);
-  }
-  // Sort the field labels by it most used label and return the most used one.
-  arsort($label_counter);
-  $label_counter = array_keys($label_counter);
-  return array($label_counter[0], $all_labels);
-}
-
-/**
- * Default views data implementation for a field.
- *
- * @param \Drupal\field\FieldStorageConfigInterface $field_storage
- *   The field definition.
- *
- * @return array
- *   The default views data for the field.
- */
-function field_views_field_default_views_data(FieldStorageConfigInterface $field_storage) {
-  $data = array();
-
-  // Check the field type is available.
-  if (!\Drupal::service('plugin.manager.field.field_type')->hasDefinition($field_storage->getType())) {
-    return $data;
-  }
-  // Check the field storage has fields.
-  if (!$field_storage->getBundles()) {
-    return $data;
-  }
-  // Check whether the entity type storage is supported.
-  $storage = _field_views_get_entity_type_storage($field_storage);
-  if (!$storage) {
-    return $data;
-  }
-
-  $field_name = $field_storage->getName();
-  $field_columns = $field_storage->getColumns();
-
-  // Grab information about the entity type tables.
-  // We need to join to both the base table and the data table, if available.
-  $entity_manager = \Drupal::entityManager();
-  $entity_type_id = $field_storage->getTargetEntityTypeId();
-  $entity_type = $entity_manager->getDefinition($entity_type_id);
-  if (!$base_table = $entity_type->getBaseTable()) {
-    // We cannot do anything if for some reason there is no base table.
-    return $data;
-  }
-  $entity_tables = array($base_table => $entity_type_id);
-  // Some entities may not have a data table.
-  $data_table = $entity_type->getDataTable();
-  if ($data_table) {
-    $entity_tables[$data_table] = $entity_type_id;
-  }
-  $entity_revision_table = $entity_type->getRevisionTable();
-  $supports_revisions = $entity_type->hasKey('revision') && $entity_revision_table;
-  if ($supports_revisions) {
-    $entity_tables[$entity_revision_table] = $entity_type_id;
-    $entity_revision_data_table = $entity_type->getRevisionDataTable();
-    if ($entity_revision_data_table) {
-      $entity_tables[$entity_revision_data_table] = $entity_type_id;
-    }
-  }
-
-  // Description of the field tables.
-  // @todo Generalize this code to make it work with any table layout. See
-  //   https://drupal.org/node/2079019.
-  $table_mapping = $storage->getTableMapping();
-  $field_tables = array(
-    EntityStorageInterface::FIELD_LOAD_CURRENT => array(
-      'table' => $table_mapping->getDedicatedDataTableName($field_storage),
-      'alias' => "{$entity_type_id}__{$field_name}",
-    ),
-  );
-  if ($supports_revisions) {
-    $field_tables[EntityStorageInterface::FIELD_LOAD_REVISION] = array(
-      'table' => $table_mapping->getDedicatedRevisionTableName($field_storage),
-      'alias' => "{$entity_type_id}_revision__{$field_name}",
-    );
-  }
-
-  // Build the relationships between the field table and the entity tables.
-  $table_alias = $field_tables[EntityStorageInterface::FIELD_LOAD_CURRENT]['alias'];
-  if ($data_table) {
-    // Tell Views how to join to the base table, via the data table.
-    $data[$table_alias]['table']['join'][$base_table] = array(
-      'left_table' => $data_table,
-      'left_field' => $entity_type->getKey('id'),
-      'field' => 'entity_id',
-      'extra' => array(
-        array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
-        array('left_field' => 'langcode', 'field' => 'langcode'),
-      ),
-    );
-  }
-  else {
-    // If there is no data table, just join directly.
-    $data[$table_alias]['table']['join'][$base_table] = array(
-      'left_field' => $entity_type->getKey('id'),
-      'field' => 'entity_id',
-      'extra' => array(
-        array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
-      ),
-    );
-  }
-
-  if ($supports_revisions) {
-    $table_alias = $field_tables[EntityStorageInterface::FIELD_LOAD_REVISION]['alias'];
-    if ($entity_revision_data_table) {
-      // Tell Views how to join to the revision table, via the data table.
-      $data[$table_alias]['table']['join'][$entity_revision_table] = array(
-        'left_table' => $entity_revision_data_table,
-        'left_field' => $entity_type->getKey('revision'),
-        'field' => 'revision_id',
-        'extra' => array(
-          array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
-          array('left_field' => 'langcode', 'field' => 'langcode'),
-        ),
-      );
-    }
-    else {
-      // If there is no data table, just join directly.
-      $data[$table_alias]['table']['join'][$entity_revision_table] = array(
-        'left_field' => $entity_type->getKey('revision'),
-        'field' => 'revision_id',
-        'extra' => array(
-          array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
-        ),
-      );
-    }
-  }
-
-  $group_name = $entity_type->getLabel();
-  // Get the list of bundles the field appears in.
-  $bundles_names = $field_storage->getBundles();
-  // Build the list of additional fields to add to queries.
-  $add_fields = array('delta', 'langcode', 'bundle');
-  foreach (array_keys($field_columns) as $column) {
-    $add_fields[] = $table_mapping->getFieldColumnName($field_storage, $column);
-  }
-  // Determine the label to use for the field. We don't have a label available
-  // at the field level, so we just go through all fields and take the one
-  // which is used the most frequently.
-  list($label, $all_labels) = field_views_field_label($entity_type_id, $field_name);
-
-  // Expose data for the field as a whole.
-  foreach ($field_tables as $type => $table_info) {
-    $table = $table_info['table'];
-    $table_alias = $table_info['alias'];
-
-    if ($type == EntityStorageInterface::FIELD_LOAD_CURRENT) {
-      $group = $group_name;
-      $field_alias = $field_name;
-    }
-    else {
-      $group = t('@group (historical data)', array('@group' => $group_name));
-      $field_alias = $field_name . '-revision_id';
-    }
-
-    $data[$table_alias][$field_alias] = array(
-      'group' => $group,
-      'title' => $label,
-      'title short' => $label,
-      'help' =>  t('Appears in: @bundles.', array('@bundles' => implode(', ', $bundles_names))),
-    );
-
-    // Go through and create a list of aliases for all possible combinations of
-    // entity type + name.
-    $aliases = array();
-    $also_known = array();
-    foreach ($all_labels as $label_name => $true) {
-      if ($type == EntityStorageInterface::FIELD_LOAD_CURRENT) {
-        if ($label != $label_name) {
-          $aliases[] = array(
-            'base' => $base_table,
-            'group' => $group_name,
-            'title' => $label_name,
-            'help' => t('This is an alias of @group: @field.', array('@group' => $group_name, '@field' => $label)),
-          );
-          $also_known[] = t('@group: @field', array('@group' => $group_name, '@field' => $label_name));
-        }
-      }
-      elseif ($supports_revisions && $label != $label_name) {
-        $aliases[] = array(
-          'base' => $table,
-          'group' => t('@group (historical data)', array('@group' => $group_name)),
-          'title' => $label_name,
-          'help' => t('This is an alias of @group: @field.', array('@group' => $group_name, '@field' => $label)),
-        );
-        $also_known[] = t('@group (historical data): @field', array('@group' => $group_name, '@field' => $label_name));
-      }
-    }
-    if ($aliases) {
-      $data[$table_alias][$field_alias]['aliases'] = $aliases;
-      $data[$table_alias][$field_alias]['help'] .= ' ' . t('Also known as: !also.', array('!also' => implode(', ', $also_known)));
-    }
-
-    $keys = array_keys($field_columns);
-    $real_field = reset($keys);
-    $data[$table_alias][$field_alias]['field'] = array(
-      'table' => $table,
-      'id' => 'field',
-      'field_name' => $field_name,
-      'entity_type' => $entity_type_id,
-      // Provide a real field for group by.
-      'real field' => $field_alias . '_' . $real_field,
-      'additional fields' => $add_fields,
-      'entity_tables' => $entity_tables,
-      // Default the element type to div, let the UI change it if necessary.
-      'element type' => 'div',
-      'is revision' => $type == EntityStorageInterface::FIELD_LOAD_REVISION,
-    );
-  }
-
-  // Expose data for each field property individually.
-  foreach ($field_columns as $column => $attributes) {
-    $allow_sort = TRUE;
-
-    // Identify likely filters and arguments for each column based on field type.
-    switch ($attributes['type']) {
-      case 'int':
-      case 'mediumint':
-      case 'tinyint':
-      case 'bigint':
-      case 'serial':
-      case 'numeric':
-      case 'float':
-        $filter = 'numeric';
-        $argument = 'numeric';
-        $sort = 'standard';
-        break;
-      case 'text':
-      case 'blob':
-        // It does not make sense to sort by blob or text.
-        $allow_sort = FALSE;
-      default:
-        $filter = 'string';
-        $argument = 'string';
-        $sort = 'standard';
-        break;
-    }
-
-    if (count($field_columns) == 1 || $column == 'value') {
-      $title = t('@label (!name)', array('@label' => $label, '!name' => $field_name));
-      $title_short = $label;
-    }
-    else {
-      $title = t('@label (!name:!column)', array('@label' => $label, '!name' => $field_name, '!column' => $column));
-      $title_short = t('@label:!column', array('@label' => $label, '!column' => $column));
-    }
-
-    // Expose data for the property.
-    foreach ($field_tables as $type => $table_info) {
-      $table = $table_info['table'];
-      $table_alias = $table_info['alias'];
-
-      if ($type == EntityStorageInterface::FIELD_LOAD_CURRENT) {
-        $group = $group_name;
-      }
-      else {
-        $group = t('@group (historical data)', array('@group' => $group_name));
-      }
-      $column_real_name = $table_mapping->getFieldColumnName($field_storage, $column);
-
-      // Load all the fields from the table by default.
-      $additional_fields = $table_mapping->getAllColumns($table);
-
-      $data[$table_alias][$column_real_name] = array(
-        'group' => $group,
-        'title' => $title,
-        'title short' => $title_short,
-        'help' =>  t('Appears in: @bundles.', array('@bundles' => implode(', ', $bundles_names))),
-      );
-
-      // Go through and create a list of aliases for all possible combinations of
-      // entity type + name.
-      $aliases = array();
-      $also_known = array();
-      foreach ($all_labels as $label_name => $true) {
-        if ($label != $label_name) {
-          if (count($field_columns) == 1 || $column == 'value') {
-            $alias_title = t('@label (!name)', array('@label' => $label_name, '!name' => $field_name));
-          }
-          else {
-            $alias_title = t('@label (!name:!column)', array('@label' => $label_name, '!name' => $field_name, '!column' => $column));
-          }
-          $aliases[] = array(
-            'group' => $group_name,
-            'title' => $alias_title,
-            'help' => t('This is an alias of @group: @field.', array('@group' => $group_name, '@field' => $title)),
-          );
-          $also_known[] = t('@group: @field', array('@group' => $group_name, '@field' => $title));
-        }
-      }
-      if ($aliases) {
-        $data[$table_alias][$column_real_name]['aliases'] = $aliases;
-        $data[$table_alias][$column_real_name]['help'] .= ' ' . t('Also known as: !also.', array('!also' => implode(', ', $also_known)));
-      }
-
-      $data[$table_alias][$column_real_name]['argument'] = array(
-        'field' => $column_real_name,
-        'table' => $table,
-        'id' => $argument,
-        'additional fields' => $additional_fields,
-        'field_name' => $field_name,
-        'entity_type' => $entity_type_id,
-        'empty field name' => t('- No value -'),
-      );
-      $data[$table_alias][$column_real_name]['filter'] = array(
-        'field' => $column_real_name,
-        'table' => $table,
-        'id' => $filter,
-        'additional fields' => $additional_fields,
-        'field_name' => $field_name,
-        'entity_type' => $entity_type_id,
-        'allow empty' => TRUE,
-      );
-      if (!empty($allow_sort)) {
-        $data[$table_alias][$column_real_name]['sort'] = array(
-          'field' => $column_real_name,
-          'table' => $table,
-          'id' => $sort,
-          'additional fields' => $additional_fields,
-          'field_name' => $field_name,
-          'entity_type' => $entity_type_id,
-        );
-      }
-
-      // Expose additional delta column for multiple value fields.
-      if ($field_storage->isMultiple()) {
-        $title_delta = t('@label (!name:delta)', array('@label' => $label, '!name' => $field_name));
-        $title_short_delta = t('@label:delta', array('@label' => $label));
-
-        $data[$table_alias]['delta'] = array(
-          'group' => $group,
-          'title' => $title_delta,
-          'title short' => $title_short_delta,
-          'help' => t('Delta - Appears in: @bundles.', array('@bundles' => implode(', ', $bundles_names))),
-        );
-        $data[$table_alias]['delta']['field'] = array(
-          'id' => 'numeric',
-        );
-        $data[$table_alias]['delta']['argument'] = array(
-          'field' => 'delta',
-          'table' => $table,
-          'id' => 'numeric',
-          'additional fields' => $additional_fields,
-          'empty field name' => t('- No value -'),
-          'field_name' => $field_name,
-          'entity_type' => $entity_type_id,
-        );
-        $data[$table_alias]['delta']['filter'] = array(
-          'field' => 'delta',
-          'table' => $table,
-          'id' => 'numeric',
-          'additional fields' => $additional_fields,
-          'field_name' => $field_name,
-          'entity_type' => $entity_type_id,
-          'allow empty' => TRUE,
-        );
-        $data[$table_alias]['delta']['sort'] = array(
-          'field' => 'delta',
-          'table' => $table,
-          'id' => 'standard',
-          'additional fields' => $additional_fields,
-          'field_name' => $field_name,
-          'entity_type' => $entity_type_id,
-        );
-      }
-    }
-  }
-
-  return $data;
-}
-
-/**
- * Have a different filter handler for lists. This should allow to select values of the list.
- */
-function list_field_views_data(FieldStorageConfigInterface $field_storage) {
-  $data = field_views_field_default_views_data($field_storage);
-  foreach ($data as $table_name => $table_data) {
-    foreach ($table_data as $field_name => $field_data) {
-      if (isset($field_data['filter']) && $field_name != 'delta') {
-        $data[$table_name][$field_name]['filter']['id'] = 'field_list';
-      }
-      if (isset($field_data['argument']) && $field_name != 'delta') {
-        if ($field_storage->getType() == 'list_string') {
-          $data[$table_name][$field_name]['argument']['id'] = 'field_list_string';
-        }
-        else {
-          $data[$table_name][$field_name]['argument']['id'] = 'field_list';
-        }
-      }
-    }
-  }
-  return $data;
-}
diff --git a/core/modules/file/file.views.inc b/core/modules/file/file.views.inc
index ee523b7fc186f9ff50f89c04493a3239c8214000..a2edb20508df8f5174447921deb1a18f453e0832 100644
--- a/core/modules/file/file.views.inc
+++ b/core/modules/file/file.views.inc
@@ -13,10 +13,10 @@
  * Views integration for file fields. Adds a file relationship to the default
  * field data.
  *
- * @see field_views_field_default_views_data()
+ * @see views_field_default_views_data()
  */
 function file_field_views_data(FieldStorageConfigInterface $field_storage) {
-  $data = field_views_field_default_views_data($field_storage);
+  $data = views_field_default_views_data($field_storage);
   foreach ($data as $table_name => $table_data) {
     // Add the relationship only on the fid field.
     $data[$table_name][$field_storage->getName() . '_target_id']['relationship'] = array(
@@ -45,7 +45,7 @@ function file_field_views_data_views_data_alter(array &$data, FieldStorageConfig
   /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
   $table_mapping = $entity_manager->getStorage($entity_type_id)->getTableMapping();
 
-  list($label) = field_views_field_label($entity_type_id, $field_name);
+  list($label) = views_entity_field_label($entity_type_id, $field_name);
 
   $data['file_managed'][$pseudo_field_name]['relationship'] = array(
     'title' => t('@entity using @field', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
diff --git a/core/modules/image/image.views.inc b/core/modules/image/image.views.inc
index 2424b1a896f1aaa51fbd6020ff5a0d426fb41999..36e5dfcc357ea2a8a7d2db3b4463d0fe9c799b89 100644
--- a/core/modules/image/image.views.inc
+++ b/core/modules/image/image.views.inc
@@ -13,10 +13,10 @@
  * Views integration for image fields. Adds an image relationship to the default
  * field data.
  *
- * @see field_views_field_default_views_data()
+ * @see views_field_default_views_data()
  */
 function image_field_views_data(FieldStorageConfigInterface $field_storage) {
-  $data = field_views_field_default_views_data($field_storage);
+  $data = views_field_default_views_data($field_storage);
   foreach ($data as $table_name => $table_data) {
     // Add the relationship only on the target_id field.
     $data[$table_name][$field_storage->getName() . '_target_id']['relationship'] = array(
@@ -44,7 +44,7 @@ function image_field_views_data_views_data_alter(array &$data, FieldStorageConfi
   /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
   $table_mapping = $entity_manager->getStorage($entity_type_id)->getTableMapping();
 
-  list($label) = field_views_field_label($entity_type_id, $field_name);
+  list($label) = views_entity_field_label($entity_type_id, $field_name);
 
   $data['file_managed'][$pseudo_field_name]['relationship'] = array(
     'title' => t('@entity using @field', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
diff --git a/core/modules/taxonomy/taxonomy.views.inc b/core/modules/taxonomy/taxonomy.views.inc
index 4de1876c954d8d2360b11328b156ee7e67199eef..fc7cc0b5d410e5879691f6f8478aec09ace5c93c 100644
--- a/core/modules/taxonomy/taxonomy.views.inc
+++ b/core/modules/taxonomy/taxonomy.views.inc
@@ -57,10 +57,10 @@ function taxonomy_views_data_alter(&$data) {
  * Views integration for taxonomy_term_reference fields. Adds a term relationship to the default
  * field data.
  *
- * @see field_views_field_default_views_data()
+ * @see views_field_default_views_data()
  */
 function taxonomy_field_views_data(FieldStorageConfigInterface $field_storage) {
-  $data = field_views_field_default_views_data($field_storage);
+  $data = views_field_default_views_data($field_storage);
   foreach ($data as $table_name => $table_data) {
     foreach ($table_data as $field_name => $field_data) {
       if (isset($field_data['filter']) && $field_name != 'delta') {
@@ -98,7 +98,7 @@ function taxonomy_field_views_data_views_data_alter(array &$data, FieldStorageCo
   /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
   $table_mapping = $entity_manager->getStorage($entity_type_id)->getTableMapping();
 
-  list($label) = field_views_field_label($entity_type_id, $field_name);
+  list($label) = views_entity_field_label($entity_type_id, $field_name);
 
   $data['taxonomy_term_data'][$pseudo_field_name]['relationship'] = array(
     'title' => t('@entity using @field', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
diff --git a/core/modules/field/src/Plugin/views/argument/FieldList.php b/core/modules/views/src/Plugin/views/argument/FieldList.php
similarity index 95%
rename from core/modules/field/src/Plugin/views/argument/FieldList.php
rename to core/modules/views/src/Plugin/views/argument/FieldList.php
index c93cccd95dbc1a7add2f927527f40002522837d0..118b4cce02e01abbb80e77aefd085ef4cf26af95 100644
--- a/core/modules/field/src/Plugin/views/argument/FieldList.php
+++ b/core/modules/views/src/Plugin/views/argument/FieldList.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Definition of views_handler_argument_field_list.
+ * Contains \Drupal\views\Plugin\views\argument\FieldList.
  */
 
-namespace Drupal\field\Plugin\views\argument;
+namespace Drupal\views\Plugin\views\argument;
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Field\AllowedTagsXssTrait;
diff --git a/core/modules/field/src/Plugin/views/argument/ListString.php b/core/modules/views/src/Plugin/views/argument/ListString.php
similarity index 95%
rename from core/modules/field/src/Plugin/views/argument/ListString.php
rename to core/modules/views/src/Plugin/views/argument/ListString.php
index 1b8f9ef0af8bea89a8f6d1d771b36308d369dbf7..f24ca79b42ad6e75dff200465c6ac6d319739100 100644
--- a/core/modules/field/src/Plugin/views/argument/ListString.php
+++ b/core/modules/views/src/Plugin/views/argument/ListString.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Definition of Drupal\field\Plugin\views\argument\ListString.
+ * Contains \Drupal\views\Plugin\views\argument\ListString.
  */
 
-namespace Drupal\field\Plugin\views\argument;
+namespace Drupal\views\Plugin\views\argument;
 
 use Drupal\Component\Utility\String as UtilityString;
 use Drupal\Core\Field\AllowedTagsXssTrait;
diff --git a/core/modules/field/src/Plugin/views/field/Field.php b/core/modules/views/src/Plugin/views/field/Field.php
similarity index 99%
rename from core/modules/field/src/Plugin/views/field/Field.php
rename to core/modules/views/src/Plugin/views/field/Field.php
index afb643d33b07b26a54fed485d172799236f67466..025ee0295075807d65a5598be742fa9fedd4516c 100644
--- a/core/modules/field/src/Plugin/views/field/Field.php
+++ b/core/modules/views/src/Plugin/views/field/Field.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Definition of Drupal\field\Plugin\views\field\Field.
+ * Contains \Drupal\views\Plugin\views\field\Field.
  */
 
-namespace Drupal\field\Plugin\views\field;
+namespace Drupal\views\Plugin\views\field;
 
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\Xss;
diff --git a/core/modules/field/src/Plugin/views/filter/FieldList.php b/core/modules/views/src/Plugin/views/filter/FieldList.php
similarity index 76%
rename from core/modules/field/src/Plugin/views/filter/FieldList.php
rename to core/modules/views/src/Plugin/views/filter/FieldList.php
index f365fc4b6d0c3f4ffc0ea36cae8b904ec4c99a9a..ff7ef179ccc41c7026e117f0740937e649634cef 100644
--- a/core/modules/field/src/Plugin/views/filter/FieldList.php
+++ b/core/modules/views/src/Plugin/views/filter/FieldList.php
@@ -2,12 +2,10 @@
 
 /**
  * @file
- * Definition of Drupal\field\Plugin\views\filter\FieldList.
+ * Contains \Drupal\views\Plugin\views\filter\FieldList.
  */
 
-namespace Drupal\field\Plugin\views\filter;
-
-use Drupal\views\Plugin\views\filter\ManyToOne;
+namespace Drupal\views\Plugin\views\filter;
 
 /**
  * Filter handler which uses list-fields as options.
diff --git a/core/modules/field/src/Plugin/views/relationship/EntityReverse.php b/core/modules/views/src/Plugin/views/relationship/EntityReverse.php
similarity index 96%
rename from core/modules/field/src/Plugin/views/relationship/EntityReverse.php
rename to core/modules/views/src/Plugin/views/relationship/EntityReverse.php
index fee9e790fbcc4748134102d6ff6e5bed570ff5e4..49d552791d4ce2ad6ea1f2f1f23eff87760c0f9c 100644
--- a/core/modules/field/src/Plugin/views/relationship/EntityReverse.php
+++ b/core/modules/views/src/Plugin/views/relationship/EntityReverse.php
@@ -2,10 +2,10 @@
 
 /**
  * @file
- * Definition of Drupal\field\Plugin\views\relationship\EntityReverse.
+ * Contains \Drupal\views\Plugin\views\relationship\EntityReverse.
  */
 
-namespace Drupal\field\Plugin\views\relationship;
+namespace Drupal\views\Plugin\views\relationship;
 
 use Drupal\views\Plugin\ViewsHandlerManager;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
diff --git a/core/modules/views/views.api.php b/core/modules/views/views.api.php
index a0d27ca17ec753ee5c35e66cdb6c7deb191fb9b2..120bed0725fdd6713fa408fd99e1abb6337175de 100644
--- a/core/modules/views/views.api.php
+++ b/core/modules/views/views.api.php
@@ -431,7 +431,7 @@ function hook_views_data_alter(array &$data) {
  * in other modules.
  *
  * If no hook implementation exists, hook_views_data() falls back to
- * field_views_field_default_views_data().
+ * views_field_default_views_data().
  *
  * @param \Drupal\field\FieldStorageConfigInterface $field_storage
  *   The field storage config entity.
@@ -440,12 +440,12 @@ function hook_views_data_alter(array &$data) {
  *   An array of views data, in the same format as the return value of
  *   hook_views_data().
  *
- * @see field_views_data()
+ * @see views_views_data()
  * @see hook_field_views_data_alter()
  * @see hook_field_views_data_views_data_alter()
  */
 function hook_field_views_data(\Drupal\field\FieldStorageConfigInterface $field_storage) {
-  $data = field_views_field_default_views_data($field_storage);
+  $data = views_field_default_views_data($field_storage);
   foreach ($data as $table_name => $table_data) {
     // Add the relationship only on the target_id field.
     $data[$table_name][$field_storage->getName() . '_target_id']['relationship'] = array(
@@ -464,7 +464,7 @@ function hook_field_views_data(\Drupal\field\FieldStorageConfigInterface $field_
  *
  * This is called on all modules even if there is no hook_field_views_data()
  * implementation for the field, and therefore may be used to alter the
- * default data that field_views_field_default_views_data() supplies for the
+ * default data that views_field_default_views_data() supplies for the
  * field storage.
  *
  *  @param array $data
@@ -473,7 +473,7 @@ function hook_field_views_data(\Drupal\field\FieldStorageConfigInterface $field_
  *  @param \Drupal\field\FieldStorageConfigInterface $field_storage
  *    The field storage config entity.
  *
- * @see field_views_data()
+ * @see views_views_data()
  * @see hook_field_views_data()
  * @see hook_field_views_data_views_data_alter()
  */
@@ -484,7 +484,7 @@ function hook_field_views_data_alter(array &$data, \Drupal\field\FieldStorageCon
   $pseudo_field_name = 'reverse_' . $field_name . '_' . $entity_type_id;
   $table_mapping = \Drupal::entityManager()->getStorage($entity_type_id)->getTableMapping();
 
-  list($label) = field_views_field_label($entity_type_id, $field_name);
+  list($label) = views_entity_field_label($entity_type_id, $field_name);
 
   $data['file_managed'][$pseudo_field_name]['relationship'] = array(
     'title' => t('@entity using @field', array('@entity' => $entity_type->getLabel(), '@field' => $label)),
@@ -531,7 +531,7 @@ function hook_field_views_data_alter(array &$data, \Drupal\field\FieldStorageCon
  *
  * @see hook_field_views_data()
  * @see hook_field_views_data_alter()
- * @see field_views_data_alter()
+ * @see views_views_data_alter()
  */
 function hook_field_views_data_views_data_alter(array &$data, \Drupal\field\FieldStorageConfigInterface $field) {
   $field_name = $field->getName();
@@ -539,7 +539,7 @@ function hook_field_views_data_views_data_alter(array &$data, \Drupal\field\Fiel
   $entity_type_id = $field->entity_type;
   $entity_type = \Drupal::entityManager()->getDefinition($entity_type_id);
   $pseudo_field_name = 'reverse_' . $field_name . '_' . $entity_type_id;
-  list($label) = field_views_field_label($entity_type_id, $field_name);
+  list($label) = views_entity_field_label($entity_type_id, $field_name);
   $table_mapping = \Drupal::entityManager()->getStorage($entity_type_id)->getTableMapping();
 
   // Views data for this field is in $data[$data_key].
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index d291717d01922682c4b181e8e84b8012e6f3875e..128a7d1afb0a4bad53bc9e9a89c69bc8336cf272 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -593,6 +593,13 @@ function views_hook_info() {
     'views_query_alter',
   ), array('group' => 'views_execution'));
 
+  $hooks['field_views_data'] = array(
+    'group' => 'views',
+  );
+  $hooks['field_views_data_alter'] = array(
+    'group' => 'views',
+  );
+
   return $hooks;
 }
 
diff --git a/core/modules/views/views.views.inc b/core/modules/views/views.views.inc
index 34167b0cb25169d544bc7eebd155bf3e55592c86..4c9971ab3c26630d76427bf041139724114a14cd 100644
--- a/core/modules/views/views.views.inc
+++ b/core/modules/views/views.views.inc
@@ -6,6 +6,10 @@
  */
 
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
+use Drupal\field\FieldConfigInterface;
+use Drupal\field\FieldStorageConfigInterface;
 use Drupal\system\ActionConfigEntityInterface;
 
 /**
@@ -165,5 +169,486 @@ function views_views_data() {
     }
   }
 
+
+  // Field modules can implement hook_field_views_data() to override the default
+  // behavior for adding fields.
+  $module_handler = \Drupal::moduleHandler();
+
+  $entity_manager = \Drupal::entityManager();
+  if ($entity_manager->hasDefinition('field_storage_config')) {
+    foreach ($entity_manager->getStorage('field_storage_config')->loadMultiple() as $field_storage) {
+      if (_views_field_get_entity_type_storage($field_storage)) {
+        $result = (array) $module_handler->invoke($field_storage->module, 'field_views_data', array($field_storage));
+        if (empty($result)) {
+          $result = views_field_default_views_data($field_storage);
+        }
+        $module_handler->alter('field_views_data', $result, $field_storage);
+
+        if (is_array($result)) {
+          $data = NestedArray::mergeDeep($result, $data);
+        }
+      }
+    }
+  }
+
+  return $data;
+}
+
+/**
+ * Implements hook_views_data_alter().
+ *
+ * Field modules can implement hook_field_views_data_views_data_alter() to
+ * alter the views data on a per field basis. This is weirdly named so as
+ * not to conflict with the \Drupal::moduleHandler()->alter('field_views_data')
+ * in views_views_data().
+ */
+function views_views_data_alter(&$data) {
+  $entity_manager = \Drupal::entityManager();
+  if (!$entity_manager->hasDefinition('field_storage_config')) {
+    return;
+  }
+  foreach ($entity_manager->getStorage('field_storage_config')->loadMultiple() as $field_storage) {
+    if (_views_field_get_entity_type_storage($field_storage)) {
+      $function = $field_storage->module . '_field_views_data_views_data_alter';
+      if (function_exists($function)) {
+        $function($data, $field_storage);
+      }
+    }
+  }
+}
+
+/**
+ * Determines whether the entity type the field appears in is SQL based.
+ *
+ * @param \Drupal\field\FieldStorageConfigInterface $field_storage
+ *   The field storage definition.
+ *
+ * @return \Drupal\Core\Entity\Sql\SqlContentEntityStorage
+ *   Returns the entity type storage if supported.
+ */
+function _views_field_get_entity_type_storage(FieldStorageConfigInterface $field_storage) {
+  $result = FALSE;
+  $entity_manager = \Drupal::entityManager();
+  if ($entity_manager->hasDefinition($field_storage->getTargetEntityTypeId())) {
+    $storage = $entity_manager->getStorage($field_storage->getTargetEntityTypeId());
+    $result = $storage instanceof SqlContentEntityStorage ? $storage : FALSE;
+  }
+  return $result;
+}
+
+/**
+ * Returns the label of a certain field.
+ *
+ * Therefore it looks up in all bundles to find the most used field.
+ */
+function views_entity_field_label($entity_type, $field_name) {
+  $label_counter = array();
+  $all_labels = array();
+  // Count the amount of fields per label per field storage.
+  foreach (array_keys(\Drupal::entityManager()->getBundleInfo($entity_type)) as $bundle) {
+    $bundle_fields = array_filter(\Drupal::entityManager()->getFieldDefinitions($entity_type, $bundle), function ($field_definition) {
+      return $field_definition instanceof FieldConfigInterface;
+    });
+    if (isset($bundle_fields[$field_name])) {
+      $field = $bundle_fields[$field_name];
+      $label = $field->getLabel();
+      $label_counter[$label] = isset($label_counter[$label]) ? ++$label_counter[$label] : 1;
+      $all_labels[$label] = TRUE;
+    }
+  }
+  if (empty($label_counter)) {
+    return array($field_name, $all_labels);
+  }
+  // Sort the field labels by it most used label and return the most used one.
+  arsort($label_counter);
+  $label_counter = array_keys($label_counter);
+  return array($label_counter[0], $all_labels);
+}
+
+/**
+ * Default views data implementation for a field.
+ *
+ * @param \Drupal\field\FieldStorageConfigInterface $field_storage
+ *   The field definition.
+ *
+ * @return array
+ *   The default views data for the field.
+ */
+function views_field_default_views_data(FieldStorageConfigInterface $field_storage) {
+  $data = array();
+
+  // Check the field type is available.
+  if (!\Drupal::service('plugin.manager.field.field_type')->hasDefinition($field_storage->getType())) {
+    return $data;
+  }
+  // Check the field storage has fields.
+  if (!$field_storage->getBundles()) {
+    return $data;
+  }
+  // Check whether the entity type storage is supported.
+  $storage = _views_field_get_entity_type_storage($field_storage);
+  if (!$storage) {
+    return $data;
+  }
+
+  $field_name = $field_storage->getName();
+  $field_columns = $field_storage->getColumns();
+
+  // Grab information about the entity type tables.
+  // We need to join to both the base table and the data table, if available.
+  $entity_manager = \Drupal::entityManager();
+  $entity_type_id = $field_storage->getTargetEntityTypeId();
+  $entity_type = $entity_manager->getDefinition($entity_type_id);
+  if (!$base_table = $entity_type->getBaseTable()) {
+    // We cannot do anything if for some reason there is no base table.
+    return $data;
+  }
+  $entity_tables = array($base_table => $entity_type_id);
+  // Some entities may not have a data table.
+  $data_table = $entity_type->getDataTable();
+  if ($data_table) {
+    $entity_tables[$data_table] = $entity_type_id;
+  }
+  $entity_revision_table = $entity_type->getRevisionTable();
+  $supports_revisions = $entity_type->hasKey('revision') && $entity_revision_table;
+  if ($supports_revisions) {
+    $entity_tables[$entity_revision_table] = $entity_type_id;
+    $entity_revision_data_table = $entity_type->getRevisionDataTable();
+    if ($entity_revision_data_table) {
+      $entity_tables[$entity_revision_data_table] = $entity_type_id;
+    }
+  }
+
+  // Description of the field tables.
+  // @todo Generalize this code to make it work with any table layout. See
+  //   https://drupal.org/node/2079019.
+  $table_mapping = $storage->getTableMapping();
+  $field_tables = array(
+    EntityStorageInterface::FIELD_LOAD_CURRENT => array(
+      'table' => $table_mapping->getDedicatedDataTableName($field_storage),
+      'alias' => "{$entity_type_id}__{$field_name}",
+    ),
+  );
+  if ($supports_revisions) {
+    $field_tables[EntityStorageInterface::FIELD_LOAD_REVISION] = array(
+      'table' => $table_mapping->getDedicatedRevisionTableName($field_storage),
+      'alias' => "{$entity_type_id}_revision__{$field_name}",
+    );
+  }
+
+  // Build the relationships between the field table and the entity tables.
+  $table_alias = $field_tables[EntityStorageInterface::FIELD_LOAD_CURRENT]['alias'];
+  if ($data_table) {
+    // Tell Views how to join to the base table, via the data table.
+    $data[$table_alias]['table']['join'][$base_table] = array(
+      'left_table' => $data_table,
+      'left_field' => $entity_type->getKey('id'),
+      'field' => 'entity_id',
+      'extra' => array(
+        array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
+        array('left_field' => 'langcode', 'field' => 'langcode'),
+      ),
+    );
+  }
+  else {
+    // If there is no data table, just join directly.
+    $data[$table_alias]['table']['join'][$base_table] = array(
+      'left_field' => $entity_type->getKey('id'),
+      'field' => 'entity_id',
+      'extra' => array(
+        array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
+      ),
+    );
+  }
+
+  if ($supports_revisions) {
+    $table_alias = $field_tables[EntityStorageInterface::FIELD_LOAD_REVISION]['alias'];
+    if ($entity_revision_data_table) {
+      // Tell Views how to join to the revision table, via the data table.
+      $data[$table_alias]['table']['join'][$entity_revision_table] = array(
+        'left_table' => $entity_revision_data_table,
+        'left_field' => $entity_type->getKey('revision'),
+        'field' => 'revision_id',
+        'extra' => array(
+          array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
+          array('left_field' => 'langcode', 'field' => 'langcode'),
+        ),
+      );
+    }
+    else {
+      // If there is no data table, just join directly.
+      $data[$table_alias]['table']['join'][$entity_revision_table] = array(
+        'left_field' => $entity_type->getKey('revision'),
+        'field' => 'revision_id',
+        'extra' => array(
+          array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE),
+        ),
+      );
+    }
+  }
+
+  $group_name = $entity_type->getLabel();
+  // Get the list of bundles the field appears in.
+  $bundles_names = $field_storage->getBundles();
+  // Build the list of additional fields to add to queries.
+  $add_fields = array('delta', 'langcode', 'bundle');
+  foreach (array_keys($field_columns) as $column) {
+    $add_fields[] = $table_mapping->getFieldColumnName($field_storage, $column);
+  }
+  // Determine the label to use for the field. We don't have a label available
+  // at the field level, so we just go through all fields and take the one
+  // which is used the most frequently.
+  list($label, $all_labels) = views_entity_field_label($entity_type_id, $field_name);
+
+  // Expose data for the field as a whole.
+  foreach ($field_tables as $type => $table_info) {
+    $table = $table_info['table'];
+    $table_alias = $table_info['alias'];
+
+    if ($type == EntityStorageInterface::FIELD_LOAD_CURRENT) {
+      $group = $group_name;
+      $field_alias = $field_name;
+    }
+    else {
+      $group = t('@group (historical data)', array('@group' => $group_name));
+      $field_alias = $field_name . '-revision_id';
+    }
+
+    $data[$table_alias][$field_alias] = array(
+      'group' => $group,
+      'title' => $label,
+      'title short' => $label,
+      'help' =>  t('Appears in: @bundles.', array('@bundles' => implode(', ', $bundles_names))),
+    );
+
+    // Go through and create a list of aliases for all possible combinations of
+    // entity type + name.
+    $aliases = array();
+    $also_known = array();
+    foreach ($all_labels as $label_name => $true) {
+      if ($type == EntityStorageInterface::FIELD_LOAD_CURRENT) {
+        if ($label != $label_name) {
+          $aliases[] = array(
+            'base' => $base_table,
+            'group' => $group_name,
+            'title' => $label_name,
+            'help' => t('This is an alias of @group: @field.', array('@group' => $group_name, '@field' => $label)),
+          );
+          $also_known[] = t('@group: @field', array('@group' => $group_name, '@field' => $label_name));
+        }
+      }
+      elseif ($supports_revisions && $label != $label_name) {
+        $aliases[] = array(
+          'base' => $table,
+          'group' => t('@group (historical data)', array('@group' => $group_name)),
+          'title' => $label_name,
+          'help' => t('This is an alias of @group: @field.', array('@group' => $group_name, '@field' => $label)),
+        );
+        $also_known[] = t('@group (historical data): @field', array('@group' => $group_name, '@field' => $label_name));
+      }
+    }
+    if ($aliases) {
+      $data[$table_alias][$field_alias]['aliases'] = $aliases;
+      $data[$table_alias][$field_alias]['help'] .= ' ' . t('Also known as: !also.', array('!also' => implode(', ', $also_known)));
+    }
+
+    $keys = array_keys($field_columns);
+    $real_field = reset($keys);
+    $data[$table_alias][$field_alias]['field'] = array(
+      'table' => $table,
+      'id' => 'field',
+      'field_name' => $field_name,
+      'entity_type' => $entity_type_id,
+      // Provide a real field for group by.
+      'real field' => $field_alias . '_' . $real_field,
+      'additional fields' => $add_fields,
+      'entity_tables' => $entity_tables,
+      // Default the element type to div, let the UI change it if necessary.
+      'element type' => 'div',
+      'is revision' => $type == EntityStorageInterface::FIELD_LOAD_REVISION,
+    );
+  }
+
+  // Expose data for each field property individually.
+  foreach ($field_columns as $column => $attributes) {
+    $allow_sort = TRUE;
+
+    // Identify likely filters and arguments for each column based on field type.
+    switch ($attributes['type']) {
+      case 'int':
+      case 'mediumint':
+      case 'tinyint':
+      case 'bigint':
+      case 'serial':
+      case 'numeric':
+      case 'float':
+        $filter = 'numeric';
+        $argument = 'numeric';
+        $sort = 'standard';
+        break;
+      case 'text':
+      case 'blob':
+        // It does not make sense to sort by blob or text.
+        $allow_sort = FALSE;
+      default:
+        $filter = 'string';
+        $argument = 'string';
+        $sort = 'standard';
+        break;
+    }
+
+    if (count($field_columns) == 1 || $column == 'value') {
+      $title = t('@label (!name)', array('@label' => $label, '!name' => $field_name));
+      $title_short = $label;
+    }
+    else {
+      $title = t('@label (!name:!column)', array('@label' => $label, '!name' => $field_name, '!column' => $column));
+      $title_short = t('@label:!column', array('@label' => $label, '!column' => $column));
+    }
+
+    // Expose data for the property.
+    foreach ($field_tables as $type => $table_info) {
+      $table = $table_info['table'];
+      $table_alias = $table_info['alias'];
+
+      if ($type == EntityStorageInterface::FIELD_LOAD_CURRENT) {
+        $group = $group_name;
+      }
+      else {
+        $group = t('@group (historical data)', array('@group' => $group_name));
+      }
+      $column_real_name = $table_mapping->getFieldColumnName($field_storage, $column);
+
+      // Load all the fields from the table by default.
+      $additional_fields = $table_mapping->getAllColumns($table);
+
+      $data[$table_alias][$column_real_name] = array(
+        'group' => $group,
+        'title' => $title,
+        'title short' => $title_short,
+        'help' =>  t('Appears in: @bundles.', array('@bundles' => implode(', ', $bundles_names))),
+      );
+
+      // Go through and create a list of aliases for all possible combinations of
+      // entity type + name.
+      $aliases = array();
+      $also_known = array();
+      foreach ($all_labels as $label_name => $true) {
+        if ($label != $label_name) {
+          if (count($field_columns) == 1 || $column == 'value') {
+            $alias_title = t('@label (!name)', array('@label' => $label_name, '!name' => $field_name));
+          }
+          else {
+            $alias_title = t('@label (!name:!column)', array('@label' => $label_name, '!name' => $field_name, '!column' => $column));
+          }
+          $aliases[] = array(
+            'group' => $group_name,
+            'title' => $alias_title,
+            'help' => t('This is an alias of @group: @field.', array('@group' => $group_name, '@field' => $title)),
+          );
+          $also_known[] = t('@group: @field', array('@group' => $group_name, '@field' => $title));
+        }
+      }
+      if ($aliases) {
+        $data[$table_alias][$column_real_name]['aliases'] = $aliases;
+        $data[$table_alias][$column_real_name]['help'] .= ' ' . t('Also known as: !also.', array('!also' => implode(', ', $also_known)));
+      }
+
+      $data[$table_alias][$column_real_name]['argument'] = array(
+        'field' => $column_real_name,
+        'table' => $table,
+        'id' => $argument,
+        'additional fields' => $additional_fields,
+        'field_name' => $field_name,
+        'entity_type' => $entity_type_id,
+        'empty field name' => t('- No value -'),
+      );
+      $data[$table_alias][$column_real_name]['filter'] = array(
+        'field' => $column_real_name,
+        'table' => $table,
+        'id' => $filter,
+        'additional fields' => $additional_fields,
+        'field_name' => $field_name,
+        'entity_type' => $entity_type_id,
+        'allow empty' => TRUE,
+      );
+      if (!empty($allow_sort)) {
+        $data[$table_alias][$column_real_name]['sort'] = array(
+          'field' => $column_real_name,
+          'table' => $table,
+          'id' => $sort,
+          'additional fields' => $additional_fields,
+          'field_name' => $field_name,
+          'entity_type' => $entity_type_id,
+        );
+      }
+
+      // Expose additional delta column for multiple value fields.
+      if ($field_storage->isMultiple()) {
+        $title_delta = t('@label (!name:delta)', array('@label' => $label, '!name' => $field_name));
+        $title_short_delta = t('@label:delta', array('@label' => $label));
+
+        $data[$table_alias]['delta'] = array(
+          'group' => $group,
+          'title' => $title_delta,
+          'title short' => $title_short_delta,
+          'help' => t('Delta - Appears in: @bundles.', array('@bundles' => implode(', ', $bundles_names))),
+        );
+        $data[$table_alias]['delta']['field'] = array(
+          'id' => 'numeric',
+        );
+        $data[$table_alias]['delta']['argument'] = array(
+          'field' => 'delta',
+          'table' => $table,
+          'id' => 'numeric',
+          'additional fields' => $additional_fields,
+          'empty field name' => t('- No value -'),
+          'field_name' => $field_name,
+          'entity_type' => $entity_type_id,
+        );
+        $data[$table_alias]['delta']['filter'] = array(
+          'field' => 'delta',
+          'table' => $table,
+          'id' => 'numeric',
+          'additional fields' => $additional_fields,
+          'field_name' => $field_name,
+          'entity_type' => $entity_type_id,
+          'allow empty' => TRUE,
+        );
+        $data[$table_alias]['delta']['sort'] = array(
+          'field' => 'delta',
+          'table' => $table,
+          'id' => 'standard',
+          'additional fields' => $additional_fields,
+          'field_name' => $field_name,
+          'entity_type' => $entity_type_id,
+        );
+      }
+    }
+  }
+
+  return $data;
+}
+
+/**
+ * Have a different filter handler for lists. This should allow to select values of the list.
+ */
+function list_field_views_data(FieldStorageConfigInterface $field_storage) {
+  $data = views_field_default_views_data($field_storage);
+  foreach ($data as $table_name => $table_data) {
+    foreach ($table_data as $field_name => $field_data) {
+      if (isset($field_data['filter']) && $field_name != 'delta') {
+        $data[$table_name][$field_name]['filter']['id'] = 'field_list';
+      }
+      if (isset($field_data['argument']) && $field_name != 'delta') {
+        if ($field_storage->getType() == 'list_string') {
+          $data[$table_name][$field_name]['argument']['id'] = 'field_list_string';
+        }
+        else {
+          $data[$table_name][$field_name]['argument']['id'] = 'field_list';
+        }
+      }
+    }
+  }
   return $data;
 }