diff --git a/core/includes/tablesort.inc b/core/includes/tablesort.inc
index 1f6962b..2fb0e66 100644
--- a/core/includes/tablesort.inc
+++ b/core/includes/tablesort.inc
@@ -43,7 +43,7 @@ function tablesort_header($cell, $header, $ts) {
   // Special formatting for the currently sorted column header.
   if (is_array($cell) && isset($cell['field'])) {
     $title = t('sort by @s', array('@s' => $cell['data']));
-    if ($cell['data'] == $ts['name']) {
+    if ($cell['field'] == $ts['field']) {
       // aria-sort is a WAI-ARIA property that indicates if items in a table
       // or grid are sorted in ascending or descending order. See
       // http://www.w3.org/TR/wai-aria/states_and_properties#aria-sort
@@ -57,7 +57,7 @@ function tablesort_header($cell, $header, $ts) {
       $ts['sort'] = 'asc';
       $image = '';
     }
-    $cell['data'] = l($cell['data'] . $image, current_path(), array('attributes' => array('title' => $title), 'query' => array_merge($ts['query'], array('sort' => $ts['sort'], 'order' => $cell['data'])), 'html' => TRUE));
+    $cell['data'] = l($cell['data'] . $image, current_path(), array('attributes' => array('title' => $title), 'query' => array_merge($ts['query'], array('sort' => $ts['sort'], 'order' => $cell['field'])), 'html' => TRUE));
 
     unset($cell['field'], $cell['sort']);
   }
@@ -82,7 +82,7 @@ function tablesort_header($cell, $header, $ts) {
  *   A properly formatted cell, ready for _theme_table_cell().
  */
 function tablesort_cell($cell, $header, $ts, $i) {
-  if (isset($header[$i]['data']) && $header[$i]['data'] == $ts['name'] && !empty($header[$i]['field'])) {
+  if (isset($header[$i]['field']) && $header[$i]['field'] == $ts['field']) {
     if (is_array($cell)) {
       $cell['class'][] = 'active';
     }
@@ -112,14 +112,15 @@ function tablesort_get_query_parameters() {
  *
  * @return
  *   An associative array describing the criterion, containing the keys:
- *   - "name": The localized title of the table column.
- *   - "sql": The name of the database field to sort on.
+ *   - "field": The name of the field to sort on.
+ *   - "query_field": The name of the database field to sort on.
+ *   - "query_reverse": TRUE for normal sorting, FALSE for reverse sorting.
  */
 function tablesort_get_order($headers) {
   $order = \Drupal::request()->query->get('order', '');
   foreach ($headers as $header) {
     if (is_array($header)) {
-      if (isset($header['data']) && $order == $header['data']) {
+      if (isset($header['field']) && $order == $header['field']) {
         $default = $header;
         break;
       }
@@ -137,8 +138,9 @@ function tablesort_get_order($headers) {
     }
   }
 
-  $default += array('data' => NULL, 'field' => NULL);
-  return array('name' => $default['data'], 'sql' => $default['field']);
+  $default += array('field' => NULL);
+  $default += array('query_field' => $default['field'], 'query_reverse' => FALSE);
+  return array('field' => $default['field'], 'query_field' => $default['query_field'], 'query_reverse' => $default['query_reverse']);
 }
 
 /**
@@ -161,7 +163,7 @@ function tablesort_get_sort($headers) {
     // Find out which header is currently being sorted.
     $ts = tablesort_get_order($headers);
     foreach ($headers as $header) {
-      if (is_array($header) && isset($header['data']) && $header['data'] == $ts['name'] && isset($header['sort'])) {
+      if (is_array($header) && isset($header['field']) && $header['field'] == $ts['field'] && isset($header['sort'])) {
         return $header['sort'];
       }
     }
diff --git a/core/lib/Drupal/Core/Database/Query/TableSortExtender.php b/core/lib/Drupal/Core/Database/Query/TableSortExtender.php
index a9bcd40..dcbccef 100644
--- a/core/lib/Drupal/Core/Database/Query/TableSortExtender.php
+++ b/core/lib/Drupal/Core/Database/Query/TableSortExtender.php
@@ -42,13 +42,17 @@ public function __construct(SelectInterface $query, Connection $connection) {
   public function orderByHeader(array $header) {
     $this->header = $header;
     $ts = $this->init();
-    if (!empty($ts['sql'])) {
+    if (!empty($ts['field'])) {
+      $field = isset($ts['query_field']) ? $ts['query_field'] : $ts['field'];
       // Based on code from db_escape_table(), but this can also contain a dot.
-      $field = preg_replace('/[^A-Za-z0-9_.]+/', '', $ts['sql']);
+      $field = preg_replace('/[^A-Za-z0-9_.]+/', '', $field);
 
       // Sort order can only be ASC or DESC.
       $sort = drupal_strtoupper($ts['sort']);
       $sort = in_array($sort, array('ASC', 'DESC')) ? $sort : '';
+      if (isset($ts['query_reverse']) && $ts['query_reverse'] && strlen($sort) > 0) {
+        $sort = ($sort == 'ASC') ? 'DESC' : 'ASC';
+      }
       $this->orderBy($field, $sort);
     }
     return $this;
diff --git a/core/lib/Drupal/Core/Entity/Query/QueryBase.php b/core/lib/Drupal/Core/Entity/Query/QueryBase.php
index d3b7b66..87a255f 100644
--- a/core/lib/Drupal/Core/Entity/Query/QueryBase.php
+++ b/core/lib/Drupal/Core/Entity/Query/QueryBase.php
@@ -280,17 +280,11 @@ protected function initializePager() {
    * Implements \Drupal\Core\Entity\Query\QueryInterface::tableSort().
    */
   public function tableSort(&$headers) {
-    // If 'field' is not initialized, the header columns aren't clickable.
-    foreach ($headers as $key =>$header) {
-      if (is_array($header) && isset($header['specifier'])) {
-        $headers[$key]['field'] = '';
-      }
-    }
 
-    $order = tablesort_get_order($headers);
+    $ts = tablesort_get_order($headers);
     $direction = tablesort_get_sort($headers);
     foreach ($headers as $header) {
-      if (is_array($header) && ($header['data'] == $order['name'])) {
+      if (is_array($header) && ($header['field'] == $ts['field'])) {
         $this->sort($header['specifier'], $direction, isset($header['langcode']) ? $header['langcode'] : NULL);
       }
     }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/TableSortExtenderUnitTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/TableSortExtenderUnitTest.php
index 241949f..21178a8 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/TableSortExtenderUnitTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/TableSortExtenderUnitTest.php
@@ -55,8 +55,9 @@ function testTableSortInit() {
     // Reset $_GET to prevent parameters from Simpletest and Batch API ending
     // up in $ts['query'].
     $expected_ts = array(
-      'name' => 'foo',
-      'sql' => '',
+      'field' => NULL,
+      'query_field' => NULL,
+      'query_reverse' => false,
       'sort' => 'asc',
       'query' => array(),
     );
@@ -120,9 +121,10 @@ function testTableSortInit() {
     \Drupal::getContainer()->set('request', $request);
     $ts = tablesort_init($headers);
     $expected_ts = array(
-      'name' => '2',
-      'sql' => 'two',
-      'sort' => 'desc',
+      'field' => 'one',
+      'query_field' => 'one',
+      'query_reverse' => false,
+      'sort' => 'asc',
       'query' => array(),
     );
     $this->verbose(strtr('$ts: <pre>!ts</pre>', array('!ts' => check_plain(var_export($ts, TRUE)))));
@@ -139,8 +141,9 @@ function testTableSortInit() {
     \Drupal::getContainer()->set('request', $request);
     $ts = tablesort_init($headers);
     $expected_ts = array(
-      'name' => '1',
-      'sql' => 'one',
+      'field' => 'one',
+      'query_field' => 'one',
+      'query_reverse' => false,
       'sort' => 'asc',
       'query' => array(),
     );
@@ -159,10 +162,13 @@ function testTableSortInit() {
     ));
     \Drupal::getContainer()->set('request', $request);
     $expected_ts = array(
-      'name' => '1',
-      'sql' => 'one',
+      'field' => 'one',
+      'query_field' => 'one',
+      'query_reverse' => false,
       'sort' => 'asc',
-      'query' => array('alpha' => 'beta'),
+      'query' => array(
+        'alpha' => 'beta',
+      ),
     );
     $ts = tablesort_init($headers);
     $this->verbose(strtr('$ts: <pre>!ts</pre>', array('!ts' => check_plain(var_export($ts, TRUE)))));
diff --git a/core/modules/system/lib/Drupal/system/Tests/Database/SelectTableSortDefaultTest.php b/core/modules/system/lib/Drupal/system/Tests/Database/SelectTableSortDefaultTest.php
index 200a82a..62a6577 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Database/SelectTableSortDefaultTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Database/SelectTableSortDefaultTest.php
@@ -28,10 +28,10 @@ public static function getInfo() {
    */
   function testTableSortQuery() {
     $sorts = array(
-      array('field' => t('Task ID'), 'sort' => 'desc', 'first' => 'perform at superbowl', 'last' => 'eat'),
-      array('field' => t('Task ID'), 'sort' => 'asc', 'first' => 'eat', 'last' => 'perform at superbowl'),
-      array('field' => t('Task'), 'sort' => 'asc', 'first' => 'code', 'last' => 'sleep'),
-      array('field' => t('Task'), 'sort' => 'desc', 'first' => 'sleep', 'last' => 'code'),
+      array('field' => 'tid', 'sort' => 'desc', 'first' => 'perform at superbowl', 'last' => 'eat'),
+      array('field' => 'tid', 'sort' => 'asc', 'first' => 'eat', 'last' => 'perform at superbowl'),
+      array('field' => 'task', 'sort' => 'asc', 'first' => 'code', 'last' => 'sleep'),
+      array('field' => 'task', 'sort' => 'desc', 'first' => 'sleep', 'last' => 'code'),
       // more elements here
 
     );
@@ -56,10 +56,10 @@ function testTableSortQuery() {
    */
   function testTableSortQueryFirst() {
     $sorts = array(
-      array('field' => t('Task ID'), 'sort' => 'desc', 'first' => 'perform at superbowl', 'last' => 'eat'),
-      array('field' => t('Task ID'), 'sort' => 'asc', 'first' => 'eat', 'last' => 'perform at superbowl'),
-      array('field' => t('Task'), 'sort' => 'asc', 'first' => 'code', 'last' => 'sleep'),
-      array('field' => t('Task'), 'sort' => 'desc', 'first' => 'sleep', 'last' => 'code'),
+      array('field' => 'tid', 'sort' => 'desc', 'first' => 'perform at superbowl', 'last' => 'eat'),
+      array('field' => 'tid', 'sort' => 'asc', 'first' => 'eat', 'last' => 'perform at superbowl'),
+      array('field' => 'task', 'sort' => 'asc', 'first' => 'code', 'last' => 'sleep'),
+      array('field' => 'task', 'sort' => 'desc', 'first' => 'sleep', 'last' => 'code'),
       // more elements here
 
     );
