diff --git a/src/Form/LingotekManagementForm.php b/src/Form/LingotekManagementForm.php
index 9dc7e26..26f8c9d 100644
--- a/src/Form/LingotekManagementForm.php
+++ b/src/Form/LingotekManagementForm.php
@@ -213,37 +213,73 @@ class LingotekManagementForm extends FormBase {
 
     $entity_type = $this->entityManager->getDefinition($this->entityTypeId);
     $properties = $this->entityManager->getBaseFieldDefinitions($this->entityTypeId);
+    $has_bundles = $entity_type->get('bundle_entity_type') != 'bundle';
+    $id_field = $entity_type->getKey('id');
+    $label_field = $entity_type->hasKey('label') ? $entity_type->getKey('label') : NULL;
 
-    $query = $this->connection->select($entity_type->getBaseTable(), 'entity_table')->extend('\Drupal\Core\Database\Query\PagerSelectExtender');
-    $query->fields('entity_table', [$entity_type->getKey('id')]);
+    $headers = [];
 
-    $has_bundles = $entity_type->get('bundle_entity_type') != 'bundle';
+    if ($has_bundles) {
+      $headers['bundle'] = $entity_type->getBundleLabel();
+    }
+    $headers += [
+      'title' => [
+        'data' => $has_bundles && $label_field ? $properties[$label_field]->getLabel() : $entity_type->getLabel(),
+      ],
+      'source' => $this->t('Source'),
+      'translations' => $this->t('Translations'),
+      'profile' => $this->t('Profile'),
+    ];
 
-    $groupsExists = $this->moduleHandler->moduleExists('group') && $this->entityTypeId === 'node';
+    if ($label_field) {
+      $headers['title'] += [
+        'field' => 'entity_data.' . $label_field,
+        'sort' => 'asc',
+      ];
+    }
+
+    $alter_context = [
+      'entity_type' => $entity_type,
+      'form_config' => $temp_store
+    ];
+
+    // Allow other modules to alter the header.
+    $this->moduleHandler->alter('lingotek_mgmt_form_header', $headers, $alter_context);
+
+    $base_query = $this->connection->select($entity_type->getBaseTable(), 'entity_table');
+    $base_query->fields('entity_table', [$entity_type->getKey('id')]);
 
-    // Filter results.
+    // Join to entity data table.
+    $base_query->innerJoin($entity_type->getDataTable(), 'entity_data',
+      'entity_table.' . $id_field . ' = entity_data.' . $id_field);
+
+    $table_sort_query = $base_query
+      ->extend('Drupal\Core\Database\Query\TableSortExtender')
+      ->orderByHeader($headers);
+
+    $query = $table_sort_query->extend('Drupal\Core\Database\Query\PagerSelectExtender');
+    $query->condition('entity_data.default_langcode', 1);
+
+    $groupsExists = $this->moduleHandler->moduleExists('group') && $this->entityTypeId === 'node';
     $labelFilter = $temp_store->get('label');
     $bundleFilter = $temp_store->get('bundle');
     $profileFilter = $temp_store->get('profile');
     $sourceLanguageFilter = $temp_store->get('source_language');
     $groupFilter = $groupsExists ? $temp_store->get('group') : NULL;
 
+    // Bundle filter.
     if ($has_bundles && $bundleFilter) {
       $query->condition('entity_table.' . $entity_type->getKey('bundle'), $bundleFilter);
     }
-    if ($labelFilter) {
-      $labelKey = $entity_type->getKey('label');
-      if ($labelKey) {
-        $query->innerJoin($entity_type->getDataTable(), 'entity_data',
-          'entity_table.' . $entity_type->getKey('id') . '= entity_data.' . $entity_type->getKey('id'));
-        $query->condition('entity_data.' . $labelKey, '%' . $labelFilter . '%', 'LIKE');
-      }
+
+    // Label Filter.
+    if ($labelFilter && $label_field) {
+      $query->condition('entity_data.' . $label_field, '%' . $labelFilter . '%', 'LIKE');
     }
+
+    // Source language filter.
     if ($sourceLanguageFilter) {
-      $query->innerJoin($entity_type->getDataTable(), 'entity_data',
-        'entity_table.' . $entity_type->getKey('id') . '= entity_data.' . $entity_type->getKey('id'));
       $query->condition('entity_table.' . $entity_type->getKey('langcode'), $sourceLanguageFilter);
-      $query->condition('entity_data.default_langcode', 1);
     }
 
     // We don't want items with language undefined.
@@ -275,6 +311,9 @@ class LingotekManagementForm extends FormBase {
       $query->condition('group_content.type', $valid_values, 'IN');
     }
 
+    // Allow other modules to alter the query.
+    $this->moduleHandler->alter('lingotek_mgmt_form_query', $query, $alter_context);
+
     $ids = $query->limit($items_per_page)->execute()->fetchCol(0);
     $entities = $this->entityManager->getStorage($this->entityTypeId)->loadMultiple($ids);
 
@@ -306,16 +345,14 @@ class LingotekManagementForm extends FormBase {
         }
       }
     }
-    $headers = [];
-    if ($has_bundles) {
-      $headers['bundle'] = $entity_type->getBundleLabel();
-    }
-    $headers += [
-      'title' => $has_bundles && $entity_type->hasKey('label') ? $properties[$entity_type->getKey('label')]->getLabel() : $entity_type->getLabel(),
-      'source' => $this->t('Source'),
-      'translations' => $this->t('Translations'),
-      'profile' => $this->t('Profile'),
+
+    $alter_context = [
+      'entity_type' => $entity_type,
+      'entities' => $entities,
+      'form_config' => $temp_store,
     ];
+    // Allow other modules to alter the rows.
+    $this->moduleHandler->alter('lingotek_mgmt_form_rows', $rows, $alter_context);
 
     // Add filters.
     $form['filters'] = array(
@@ -1280,7 +1317,7 @@ class LingotekManagementForm extends FormBase {
       $operations[(string)$this->t('Check translation progress')]['check_translation:' . $langcode] = $this->t('Check progress of @language translation', ['@language' => $language->getName() . ' (' . $language->getId() .')']);
       $operations[(string)$this->t('Download')]['download:' . $langcode] = $this->t('Download @language translation', ['@language' => $language->getName()]);
     }
-  
+
     // We add the delete operation in nodes and comments, as we have those
     // operations in core.
     if ($this->entityTypeId === 'node') {
diff --git a/src/Tests/Form/LingotekNodeBulkFormTest.php b/src/Tests/Form/LingotekNodeBulkFormTest.php
index cb596bd..0e53617 100644
--- a/src/Tests/Form/LingotekNodeBulkFormTest.php
+++ b/src/Tests/Form/LingotekNodeBulkFormTest.php
@@ -88,12 +88,12 @@ class LingotekNodeBulkFormTest extends LingotekTestBase {
     $basepath = \Drupal::request()->getBasePath();
 
     // I can init the upload of content.
-    $this->assertLinkByHref($basepath . '/admin/lingotek/entity/upload/node/11?destination=' . $basepath . '/admin/lingotek/manage/node');
+    $this->assertLinkByHref($basepath . '/admin/lingotek/entity/upload/node/6?destination=' . $basepath . '/admin/lingotek/manage/node');
     $edit = [
       // Node 11.
-      'table[11]' => TRUE,
+      'table[6]' => TRUE,
       // Node 12.
-      'table[12]' => TRUE,
+      'table[7]' => TRUE,
       'operation' => 'upload',
     ];
     $this->drupalPostForm(NULL, $edit, t('Execute'));
@@ -106,7 +106,7 @@ class LingotekNodeBulkFormTest extends LingotekTestBase {
     // And we can already request a translation.
     $this->assertLinkByHref($basepath . '/admin/lingotek/entity/add_target/dummy-document-hash-id/es_MX?destination=' . $basepath . '/admin/lingotek/manage/node');
     $this->clickLink('EN');
-    $this->assertText('The import for node Llamas are cool 11 is complete.');
+    $this->assertText('The import for node Llamas are cool 6 is complete.');
 
     // The current page is kept.
     $this->assertUrl('admin/lingotek/manage/node?page=1');
@@ -179,7 +179,7 @@ class LingotekNodeBulkFormTest extends LingotekTestBase {
 
     // After we reset, we get back to having a pager and all the content.
     $this->drupalPostForm(NULL, [], 'Reset');
-    foreach (range(1, 10) as $j) {
+    foreach ([1, 2, 3, 4, 5, 10, 11, 12, 13, 14] as $j) {
       $this->assertLink('Llamas are cool ' . $j);
     }
     $this->assertLinkByHref('?page=1');
@@ -253,10 +253,10 @@ class LingotekNodeBulkFormTest extends LingotekTestBase {
     // After we reset, we get back to having a pager and all the content under
     // limit of 10.
     $this->drupalPostForm(NULL, [], 'Reset');
-    foreach ([1, 5, 7] as $j) {
+    foreach ([1] as $j) {
       $this->assertLink('Llamas are cool ' . $j);
     }
-    foreach ([2, 4, 6, 8, 10] as $j) {
+    foreach ([2, 4, 6, 8, 10, 12, 14] as $j) {
       $this->assertLink('Dogs are cool ' . $j);
     }
     foreach ([3, 9] as $j) {
@@ -336,15 +336,15 @@ class LingotekNodeBulkFormTest extends LingotekTestBase {
 
     // After we reset, we get back to having a pager and all the content.
     $this->drupalPostForm(NULL, [], 'Reset');
-    foreach ([1, 5, 7] as $j) {
+    foreach ([3, 9] as $j) {
+      $this->assertLink('Llamas are cool EN ' . $j);
+    }
+    foreach ([1, 11, 13, 5, 7] as $j) {
       $this->assertLink('Llamas are cool ES ' . $j);
     }
-    foreach ([2, 4, 6, 8, 10] as $j) {
+    foreach ([10, 12, 14] as $j) {
       $this->assertLink('Llamas are cool IT ' . $j);
     }
-    foreach ([3, 9] as $j) {
-      $this->assertLink('Llamas are cool EN ' . $j);
-    }
     $this->assertLinkByHref('?page=1');
   }
 
@@ -423,12 +423,13 @@ class LingotekNodeBulkFormTest extends LingotekTestBase {
 
     // After we reset, we get back to having a pager and all the content.
     $this->drupalPostForm(NULL, [], 'Reset');
-    foreach ([1, 2, 4, 5, 7, 8, 10] as $j) {
-      $this->assertLink('Llamas are cool page ' . $j);
-    }
-    foreach ([3, 6, 9] as $j) {
+    foreach ([3, 6, 9, 12] as $j) {
       $this->assertLink('Llamas are cool article ' . $j);
     }
+    foreach ([1, 10, 11, 13, 14, 2] as $j) {
+      $this->assertLink('Llamas are cool page ' . $j);
+    }
+
     $this->assertLinkByHref('?page=1');
   }
 
diff --git a/src/Tests/Form/LingotekNodeBulkFormWithGroupModuleTest.php b/src/Tests/Form/LingotekNodeBulkFormWithGroupModuleTest.php
index b8cac9e..776993e 100644
--- a/src/Tests/Form/LingotekNodeBulkFormWithGroupModuleTest.php
+++ b/src/Tests/Form/LingotekNodeBulkFormWithGroupModuleTest.php
@@ -202,13 +202,13 @@ class LingotekNodeBulkFormWithGroupModuleTest extends LingotekTestBase {
 
     // After we reset, we get back to having a pager and all the content.
     $this->drupalPostForm(NULL, [], 'Reset');
-    foreach ([1, 5, 7] as $j) {
+    foreach ([1, 11, 13, 5] as $j) {
       $this->assertLink('Llamas are cool ' . $j . ' at Group My Product 1.0');
     }
-    foreach ([2, 4, 6, 8, 10] as $j) {
+    foreach ([10, 12, 14, 2, 4] as $j) {
       $this->assertLink('Llamas are cool ' . $j . ' at Group My Product 2.0');
     }
-    foreach ([3, 9] as $j) {
+    foreach ([3] as $j) {
       $this->assertLink('Llamas are cool ' . $j . ' at Group My Product 2.4');
     }
     $this->assertLinkByHref('?page=1');
diff --git a/tests/src/Unit/Form/LingotekManagementFormTest.php b/tests/src/Unit/Form/LingotekManagementFormTest.php
index 2a733b9..e60aa8f 100644
--- a/tests/src/Unit/Form/LingotekManagementFormTest.php
+++ b/tests/src/Unit/Form/LingotekManagementFormTest.php
@@ -5,6 +5,7 @@ namespace Drupal\Tests\lingotek\Unit\Form {
   use Drupal\content_translation\ContentTranslationManagerInterface;
   use Drupal\Core\Database\Connection;
   use Drupal\Core\Database\Query\PagerSelectExtender;
+  use Drupal\Core\Database\Query\TableSortExtender;
   use Drupal\Core\Entity\EntityManagerInterface;
   use Drupal\Core\Entity\EntityStorageInterface;
   use Drupal\Core\Entity\EntityTypeInterface;
@@ -22,6 +23,7 @@ namespace Drupal\Tests\lingotek\Unit\Form {
   use Drupal\Tests\UnitTestCase;
   use Drupal\user\PrivateTempStore;
   use Drupal\user\PrivateTempStoreFactory;
+  use Drupal\Core\Database\Query\SelectInterface;
 
   /**
    * @coversDefaultClass \Drupal\lingotek\Form\LingotekManagementForm
@@ -167,40 +169,53 @@ namespace Drupal\Tests\lingotek\Unit\Form {
    * @covers ::buildForm
    */
     public function testQueryExcludesUndefinedLanguageContent() {
-      $select = $this->getMockBuilder(PagerSelectExtender::class)->disableOriginalConstructor()->getMock();
-      $select->expects(($this->any()))
-        ->method('extend')
-        ->with('\Drupal\Core\Database\Query\PagerSelectExtender')
-        ->willReturnSelf();
+      $select = $this->getMockBuilder(SelectInterface::class)->disableOriginalConstructor()->getMock();
+      $tablesort_select = $this->getMockBuilder(TableSortExtender::class)->disableOriginalConstructor()->getMock();
+      $pager_select = $this->getMockBuilder(PagerSelectExtender::class)->disableOriginalConstructor()->getMock();
+
       $select->expects(($this->any()))
         ->method('fields')
         ->with('entity_table', ['id'])
         ->willReturnSelf();
 
+      $select->expects(($this->any()))
+        ->method('extend')
+        ->with('Drupal\Core\Database\Query\TableSortExtender')
+        ->willReturn($tablesort_select);
+
+      $this->connection->expects($this->once())
+        ->method('select')
+        ->willReturn($select);
+
       $statement = $this->getMock('Drupal\Core\Database\StatementInterface');
 
       // Assert that condition is called filtering by the undefined language.
-      $select->expects($this->any())
+      $pager_select->expects($this->any())
         ->method('condition')
-        ->with('entity_table.langcode', 'und', '!=')
+        ->withAnyParameters()
         ->willReturnSelf();
-      $select->expects($this->once())
+      $pager_select->expects($this->once())
         ->method('limit')
         ->with(10)
         ->willReturnSelf();
-      $select->expects($this->once())
+      $pager_select->expects($this->once())
         ->method('execute')
         ->willReturn($statement);
 
+      $tablesort_select->expects($this->any())
+        ->method('extend')
+        ->with('Drupal\Core\Database\Query\PagerSelectExtender')
+        ->willReturn($pager_select);
+
+      $tablesort_select->expects($this->any())
+        ->method('orderByHeader')
+        ->willReturnSelf();
+
       $statement->expects($this->once())
         ->method('fetchCol')
         ->with(0)
         ->willReturn([]);
 
-      $this->connection->expects($this->once())
-        ->method('select')
-        ->willReturn($select);
-
       $tempStore = $this->getMockBuilder(PrivateTempStore::class)->disableOriginalConstructor()->getMock();
       $this->tempStoreFactory->expects($this->at(0))
         ->method('get')
@@ -273,7 +288,7 @@ namespace Drupal\Tests\lingotek\Unit\Form {
         ->with('lingotek.enable_debug_utilities')
         ->willReturn(FALSE);
 
-      $this->moduleHandler->expects($this->at(0))
+      $this->moduleHandler->expects($this->any())
         ->method('moduleExists')
         ->with('group')
         ->willReturn(FALSE);
