diff --git a/controller/tmgmt.controller.job_item.inc b/controller/tmgmt.controller.job_item.inc
index 02f4ffb..4c2437e 100644
--- a/controller/tmgmt.controller.job_item.inc
+++ b/controller/tmgmt.controller.job_item.inc
@@ -13,30 +13,54 @@
 class TMGMTJobItemController extends EntityAPIController {
 
   /**
-   * Overrides EntityAPIController::save().
+   * Overrides EntityAPIController::create(array $values = array()).
+   */
+  public function create(array $values = array()) {
+    $entity = parent::create($values);
+    $this->doCountWords($entity);
+    return $entity;
+  }
+
+  /**
+   * Count all translatable words from the given entity.
    *
-   * @todo Eliminate the need to flatten and unflatten the JobItem data.
+   * @param TMGMTJobItem $item
    */
-  public function save($entity, DatabaseTransaction $transaction = NULL) {
-    $entity->changed = REQUEST_TIME;
+  public function doCountWords(TMGMTJobItem &$item) {
+    // Set translatable data from the current entity to calculate words.
+    if (empty($item->data)) {
+      //$entity = entity_load_single($item->item_type, $item->item_id);
+      //$item->data = tmgmt_field_get_source_data($item->item_type, $entity, $item->getJob()->source_language, TRUE);
+      $item->data = $item->getSourceData();
+    }
 
     // Consider everything accepted when the job item is accepted.
-    if ($entity->isAccepted()) {
-      $entity->count_pending = 0;
-      $entity->count_translated = 0;
-      $entity->count_reviewed = 0;
-      $entity->count_accepted = count(array_filter(tmgmt_flatten_data($entity->data), '_tmgmt_filter_data'));
+    if ($item->isAccepted()) {
+      $item->count_pending = 0;
+      $item->count_translated = 0;
+      $item->count_reviewed = 0;
+      $item->count_accepted = count(array_filter(tmgmt_flatten_data($item->data), '_tmgmt_filter_data'));
     }
     // Count the data item states.
     else {
       // Reset counter values.
-      $entity->count_pending = 0;
-      $entity->count_translated = 0;
-      $entity->count_reviewed = 0;
-      $entity->count_accepted = 0;
-      $entity->word_count = 0;
-      $this->count($entity->data, $entity);
+      $item->count_pending = 0;
+      $item->count_translated = 0;
+      $item->count_reviewed = 0;
+      $item->count_accepted = 0;
+      $item->word_count = 0;
+      $this->count($item->data, $item);
     }
+  }
+
+  /**
+   * Overrides EntityAPIController::save().
+   *
+   * @todo Eliminate the need to flatten and unflatten the JobItem data.
+   */
+  public function save($entity, DatabaseTransaction $transaction = NULL) {
+    $entity->changed = REQUEST_TIME;
+    $this->doCountWords($entity);
     return parent::save($entity, $transaction);
   }
 
diff --git a/entity/tmgmt.entity.job.inc b/entity/tmgmt.entity.job.inc
index 86411d2..2816dfd 100644
--- a/entity/tmgmt.entity.job.inc
+++ b/entity/tmgmt.entity.job.inc
@@ -638,7 +638,7 @@ class TMGMTJob extends Entity {
    *   A nested array with the source data where the most upper key is the job
    *   item id.
    */
-  public function getData(array $key = array(), $index = null) {
+  public function getData(array $key = array(), $index = NULL) {
     $data = array();
     if (!empty($key)) {
       $tjiid = array_shift($key);
@@ -767,4 +767,39 @@ class TMGMTJob extends Entity {
     return array();
   }
 
+  /**
+   * Removes all suggestions from the given list which should not be processed.
+   *
+   * This function removes all suggestions from the given list which are already
+   * assigned to a translation job or which should not be processed because
+   * there are no words, no translation is needed, ...
+   *
+   * @param array &$suggestions
+   *   Associative array of translation suggestions. It must contain at least:
+   *   - tmgmt_job: An instance of a TMGMTJobItem.
+   */
+  public function cleanSuggestionsList(array &$suggestions) {
+    $keys = array_keys($suggestions);
+    foreach ($keys as $i) {
+      $suggestion = $suggestions[$i];
+      if (is_array($suggestion) && isset($suggestion['tmgmt_job']) && ($suggestion['tmgmt_job'] instanceof TMGMTJobItem)) {
+        $jobItem = $suggestion['tmgmt_job'];
+        // Items with no words to translate should not be presented.
+        if ($jobItem->getWordCount() <= 0) {
+          unset($suggestions[$i]);
+          continue;
+        }
+
+        // Check if there already exists a translation job for this item in the current language.
+        $items = tmgmt_job_item_load_all_latest($jobItem->plugin, $jobItem->item_type, $jobItem->item_id, $this->source_language);
+        if ($items && isset($items[$this->target_language])) {
+          unset($suggestions[$i]);
+          continue;
+        }
+      } else {
+        unset($suggestions[$i]);
+      }
+    }
+  }
+
 }
diff --git a/sources/entity/tmgmt_entity.module b/sources/entity/tmgmt_entity.module
index 0725931..bd99124 100644
--- a/sources/entity/tmgmt_entity.module
+++ b/sources/entity/tmgmt_entity.module
@@ -202,3 +202,74 @@ function tmgmt_entity_get_translatable_entities($entity_type, $property_conditio
 
   return $entities;
 }
+
+/**
+ * Implements hook_tmgmt_source_suggestions()
+ */
+function tmgmt_entity_tmgmt_source_suggestions(TMGMTJob $job) {
+  $suggestions = array();
+
+  foreach ($job->getItems() as $item) {
+    if (($item->plugin == 'entity') || ($item->plugin == 'node')) {
+      // Load the entity and extract the bundle name to get all fields from the
+      // current entity.
+      $entity = entity_load_single($item->item_type, $item->item_id);
+      list(, , $bundle) = entity_extract_ids($item->item_type, $entity);
+      $field_instances = field_info_instances($item->item_type, $bundle);
+
+      // Get all translatable entity types.
+      $entity_types = array_filter(variable_get('entity_translation_entity_types', array()));
+
+      // Create a link to the referenced entity to show in the table.
+      $entity_link = l( t('@title (@type)', array(
+        '@title' => check_plain($entity->title),
+        '@type' => check_plain($entity->type),
+      )), 'node/' . $entity->vid, array('attributes' => array('target' => '_blank')) );
+
+      // Loop over all fields, check if they are NOT translatable. Only if a
+      // field is not translatable we may have a referenced node/entity.
+      // If so, check for a valid type.
+      foreach ($field_instances as $instance) {
+        $field = field_info_field($instance['field_name']);
+        if (isset($field['translatable']) && !$field['translatable']) {
+          $field_type = $field['type'];
+          switch ($field_type) {
+            case 'file':
+            case 'image':
+              // Images and files must be a translatable entity type.
+              // Other files we not suggest here. Get all field items from the
+              // current entity and suggest them as translatable.
+              if (isset($entity_types['file'])) {
+                $field_name = $field['field_name'];
+                if ($field_items = field_get_items($item->item_type, $entity, $field_name)) {
+                  // Add all files as a suggestion.
+                  foreach ($field_items as $field_item) {
+                    $file_entity = entity_load_single('file', $field_item['fid']);
+
+                    // Check if there is already a translation available for this
+                    // file. If so, just continue with the next file.
+                    $handler = entity_translation_get_handler('file', $file_entity);
+                    if ($handler instanceof EntityTranslationHandlerInterface) {
+                      $translations = $handler->getTranslations();
+                      if (isset($translations->data[$job->target_language])) {
+                        continue;
+                      }
+                    }
+
+                    // Add the translation as a suggestion.
+                    $suggestions[] = array(
+                      'tmgmt_job' => tmgmt_job_item_create('entity', 'file', $file_entity->fid),
+                      'referenced' => t('Suggested from !entity', array('!entity' => $entity_link)),
+                    );
+                  }
+                }
+              }
+              break;
+          }
+        }
+      }
+    }
+  }
+
+  return $suggestions;
+}
diff --git a/sources/i18n_string/tmgmt_i18n_string.test b/sources/i18n_string/tmgmt_i18n_string.test
index 742d42c..d360ecd 100644
--- a/sources/i18n_string/tmgmt_i18n_string.test
+++ b/sources/i18n_string/tmgmt_i18n_string.test
@@ -20,7 +20,7 @@ class TMGMTI18nStringSourceTestCase extends TMGMTBaseTestCase {
    * Overrides SimplenewsTestCase::setUp()
    */
   function setUp() {
-    parent::setUp(array('tmgmt_i18n_string', 'i18n_menu', 'i18n_taxonomy'));
+    parent::setUp(array('tmgmt_i18n_string', 'i18n_menu', 'i18n_taxonomy', 'i18n_string'));
     $this->translator = $this->createTranslator();
   }
 
@@ -42,7 +42,7 @@ class TMGMTI18nStringSourceTestCase extends TMGMTBaseTestCase {
     $job->settings = array();
     $job->save();
 
-    $item1 = $job->addItem('i18n_string', 'i18n_string', $string_object_name);
+    $item1 = $job->addItem('i18n_string', 'node', $string_object_name);
     $job->requestTranslation();
 
     foreach ($job->getItems() as $item) {
diff --git a/tests/tmgmt.base.test b/tests/tmgmt.base.test
index 6ea7b96..207f5ec 100644
--- a/tests/tmgmt.base.test
+++ b/tests/tmgmt.base.test
@@ -160,6 +160,10 @@ class TMGMTBaseTestCase extends DrupalWebTestCase {
 
     // Assert that the translator was assigned a tid.
     $this->assertTrue($job->tjid > 0);
+
+    // Create two nodes to translate.
+    $this->drupalCreateNode();
+    $this->drupalCreateNode();
     return $job;
   }
 
diff --git a/tests/tmgmt.crud.test b/tests/tmgmt.crud.test
index c48fe63..6438697 100644
--- a/tests/tmgmt.crud.test
+++ b/tests/tmgmt.crud.test
@@ -74,8 +74,8 @@ class TMGMTCRUDTestCase extends TMGMTBaseTestCase {
     $this->assertEqual($job->reference, $loaded_job->reference);
 
     // Test the job items.
-    $item1 = $job->addItem('test_source', 'type', 5);
-    $item2 = $job->addItem('test_source', 'type', 4);
+    $item1 = $job->addItem('test_source', 'node', 1);
+    $item2 = $job->addItem('test_source', 'node', 2);
 
     // Load and compare the items.
     $items = $job->getItems();
@@ -101,8 +101,8 @@ class TMGMTCRUDTestCase extends TMGMTBaseTestCase {
     $job = $this->createJob();
     $job->translator = $translator->name;
     $job->save();
-    $item1 = $job->addItem('test_source', 'type', 5);
-    $item2 = $job->addItem('test_source', 'type', 4);
+    $item1 = $job->addItem('test_source', 'node', 1);
+    $item2 = $job->addItem('test_source', 'node', 2);
 
     $result = $item1->addRemoteMapping($data_key, 'id11', array('remote_identifier_2' => 'id12', 'remote_identifier_3' => 'id13'));
     $this->assertEqual($result, SAVED_NEW);
@@ -167,8 +167,8 @@ class TMGMTCRUDTestCase extends TMGMTBaseTestCase {
     $job = $this->createJob();
 
     // Add some test items.
-    $item1 = $job->addItem('test_source', 'type', 5);
-    $item2 = $job->addItem('test_source', 'type', 4);
+    $item1 = $job->addItem('test_source', 'node', 1);
+    $item2 = $job->addItem('test_source', 'node', 2);
 
     // Test single load callback.
     $item = tmgmt_job_item_load($item1->tjiid);
@@ -226,7 +226,7 @@ class TMGMTCRUDTestCase extends TMGMTBaseTestCase {
     $this->assertEqual(0, $job->getWordCount());
 
     // Add a test items.
-    $job_item1 = tmgmt_job_item_create('plugin', 'type', 4, array('tjid' => $job->tjid));
+    $job_item1 = tmgmt_job_item_create('entity', 'node', 1, array('tjid' => $job->tjid));
     $job_item1->save();
 
     // No pending, translated and confirmed data items.
@@ -345,7 +345,7 @@ class TMGMTCRUDTestCase extends TMGMTBaseTestCase {
     $this->assertEqual(5, $job->getCountReviewed());
 
     // Add several job items
-    $job_item2 = tmgmt_job_item_create('plugin', 'type', 5, array('tjid' => $job->tjid));
+    $job_item2 = tmgmt_job_item_create('entity', 'node', 2, array('tjid' => $job->tjid));
     for ($index = 1; $index <= 4; $index++) {
       $job_item2->data['data_item' . $index] = $data1;
     }
@@ -378,4 +378,67 @@ class TMGMTCRUDTestCase extends TMGMTBaseTestCase {
     $this->assertEqual(31, $job->getCountAccepted());
   }
 
+  /**
+   * Test suggested entities from a translation job.
+   */
+  function testSuggestions() {
+    $job = $this->createJob();
+
+    // Create a content type with fields which have translatable fields.
+    $type = $this->drupalCreateContentType();
+
+    $field1 = field_create_field(array(
+      'field_name' => 'field1',
+      'type' => 'file',
+      'entity_types' => array('node'),
+    ));
+    $field2 = field_create_field(array(
+      'field_name' => 'field2',
+      'type' => 'file',
+      'entity_types' => array('node'),
+    ));
+
+    field_create_instance(array(
+      'field_name' => $field1['field_name'],
+      'entity_type' => 'node',
+      'bundle' => $type->type,
+      'label' => 'Field 1',
+      'widget' => array('type' => 'file'),
+      'settings' => array(),
+    ));
+    field_create_instance(array(
+      'field_name' => $field2['field_name'],
+      'entity_type' => 'node',
+      'bundle' => $type->type,
+      'label' => 'Field 2',
+      'widget' => array('type' => 'file'),
+      'settings' => array(),
+    ));
+    $this->drupalCreateNode(array(
+      'type' => $type->type,
+      'field1' => array(
+        'alt_text' => array(
+          LANGUAGE_NONE => array('value' => 'Alt text'),
+        ),
+        'title_text' => array(
+          LANGUAGE_NONE => array('value' => 'Title text'),
+        ),
+      ),
+      'field2' => array(
+        'alt_text' => array(
+          LANGUAGE_NONE => array('value' => 'Alt text'),
+        ),
+        'title_text' => array(
+          LANGUAGE_NONE => array('value' => 'Title text'),
+        ),
+      ),
+    ));
+
+    // Add all three nodes to the job.
+    $item1 = $job->addItem('entity', 'node', 1);
+    $item2 = $job->addItem('entity', 'node', 2);
+    $item3 = $job->addItem('entity', 'file', 3);
+    
+  }
+
 }
diff --git a/tmgmt.api.php b/tmgmt.api.php
index 7e0c193..d22b889 100644
--- a/tmgmt.api.php
+++ b/tmgmt.api.php
@@ -38,6 +38,27 @@ function hook_tmgmt_source_plugin_info_alter(&$info) {
 }
 
 /**
+ * Return a list with TMGMTJobItem, title and a description.
+ *
+ * @param TMGMTJob $job
+ *   The current translation job to check for additional translation items.
+ *
+ * @return array
+ *   An array with all additional translation suggestions.
+ *   - tmgmt_job: A TMGMTJobItem instance.
+ *   - referenced: A string which indicates where this suggestion comes from.
+ *                 This string may include a link to let the user view the page.
+ */
+function tmgmt_entity_tmgmt_source_suggestions(TMGMTJob $job) {
+  return array(
+    array(
+      'tmgmt_job' => tmgmt_job_item_create('entity', 'node', 0),
+      'referenced' => t('Referenced from'),
+    )
+  );
+}
+
+/**
  * @} End of "addtogroup tmgmt_source".
  */
 
diff --git a/tmgmt.module b/tmgmt.module
index bc26e7f..d6ac828 100644
--- a/tmgmt.module
+++ b/tmgmt.module
@@ -330,7 +330,7 @@ function tmgmt_job_load_multiple(array $tjids = array(), $conditions = array())
 }
 
 /**
- * Loads job entities that have a job item with the identifiers.
+ * Loads active job entities that have a job item with the identifiers.
  *
  * @param $plugin
  *   The source plugin.
@@ -372,6 +372,45 @@ function tmgmt_job_item_load_latest($plugin, $item_type, $item_id, $source_langu
 }
 
 /**
+ * Loads all latest job entities that have a job item with the identifiers.
+ *
+ * @param $plugin
+ *   The source plugin.
+ * @param $item_type
+ *   The source item type.
+ * @param $item_id
+ *   The source item id.
+ * @param string $source_language
+ *   The source language of the item.
+ *
+ * @return array
+ *   An array of job entities.
+ */
+function tmgmt_job_item_load_all_latest($plugin, $item_type, $item_id, $source_language) {
+  $query = db_select('tmgmt_job_item', 'tji');
+  $query->innerJoin('tmgmt_job', 'tj', 'tj.tjid = tji.tjid');
+  $result = $query->condition('tj.source_language', $source_language)
+    ->condition('tji.state', TMGMT_JOB_ITEM_STATE_ACCEPTED, '<>')
+    ->condition('tji.plugin', $plugin)
+    ->condition('tji.item_type', $item_type)
+    ->condition('tji.item_id', $item_id)
+    ->fields('tji', array('tjiid'))
+    ->fields('tj', array('target_language'))
+    ->orderBy('tji.changed', 'DESC')
+    ->groupBy('tj.target_language')
+    ->groupBy('tji.tjiid')
+    ->execute();
+  if ($items = $result->fetchAllKeyed()) {
+    $return = array();
+    foreach (tmgmt_job_item_load_multiple(array_keys($items)) as $key => $item) {
+      $return[$items[$key]] = $item;
+    }
+    return $return;
+  }
+  return FALSE;
+}
+
+/**
  * Returns a job which matches the requested source- and target language by
  * user. If no job exists, a new job object will be created.
  *
diff --git a/translators/file/tmgmt_file.test b/translators/file/tmgmt_file.test
index 5fdfb8a..14791e2 100644
--- a/translators/file/tmgmt_file.test
+++ b/translators/file/tmgmt_file.test
@@ -43,8 +43,8 @@ class TMGMTFileTestCase extends TMGMTBaseTestCase {
 
     $job = $this->createJob();
     $job->translator = $translator->name;
-    $job->addItem('test_source', 'test', '1');
-    $job->addItem('test_source', 'test', '2');
+    $job->addItem('test_source', 'node', 1);
+    $job->addItem('test_source', 'node', 2);
 
     $job->requestTranslation();
     $messages = $job->getMessages();
@@ -82,8 +82,8 @@ class TMGMTFileTestCase extends TMGMTBaseTestCase {
 
     $job = $this->createJob();
     $job->translator = $translator->name;
-    $job->addItem('test_source', 'test', '1');
-    $job->addItem('test_source', 'test', '2');
+    $job->addItem('test_source', 'node', 1);
+    $job->addItem('test_source', 'node', 2);
 
     $job->requestTranslation();
     $messages = $job->getMessages();
@@ -180,8 +180,8 @@ class TMGMTFileTestCase extends TMGMTBaseTestCase {
 
     $job = $this->createJob();
     $job->translator = $translator->name;
-    $job->addItem('test_source', 'test', '1');
-    $job->addItem('test_source', 'test', '2');
+    $job->addItem('test_source', 'node', 1);
+    $job->addItem('test_source', 'node', 2);
 
     $job->requestTranslation();
     $messages = $job->getMessages();
diff --git a/translators/tmgmt_local/tmgmt_local.test b/translators/tmgmt_local/tmgmt_local.test
index fc842f6..26fe066 100644
--- a/translators/tmgmt_local/tmgmt_local.test
+++ b/translators/tmgmt_local/tmgmt_local.test
@@ -163,8 +163,8 @@ class TMGMTLocalTestCase extends TMGMTBaseTestCase {
     $job = $this->createJob();
     $job->translator = $translator->name;
     $job->settings['job_comment'] = $job_comment = 'Dummy job comment';
-    $job->addItem('test_source', 'test', '1');
-    $job->addItem('test_source', 'test', '2');
+    $job->addItem('test_source', 'node', 1);
+    $job->addItem('test_source', 'node', 2);
 
     // Create another local translator with the required capabilities.
     $other_translator_same = $this->drupalCreateUser($this->local_translator_permissions);
@@ -260,8 +260,8 @@ class TMGMTLocalTestCase extends TMGMTBaseTestCase {
     $this->assertEqual($first_task_item->getCountTranslated(), 0);
     $this->assertEqual($first_task_item->getCountUntranslated(), 1);
 
-    $this->assertText(t('Translation for @source', array('@source' => 'test_source:test:1')));
-    $this->assertText(t('Translation for @source', array('@source' => 'test_source:test:2')));
+    $this->assertText(t('Translation for @source', array('@source' => 'test_source:node:1')));
+    $this->assertText(t('Translation for @source', array('@source' => 'test_source:node:2')));
     $this->assertText(t('Untranslated'));
 
     // Translate the first item.
@@ -270,7 +270,7 @@ class TMGMTLocalTestCase extends TMGMTBaseTestCase {
     $this->assertText(t('Dummy'));
     // Job comment is present in the translate tool as well.
     $this->assertText($job_comment);
-    $this->assertText(t('Translation for @source', array('@source' => 'test_source:test:1')));
+    $this->assertText(t('Translation for @source', array('@source' => 'test_source:node:1')));
 
     // Try to complete a translation when translations are missing.
     $this->drupalPost(NULL, array(), t('Save as completed'));
@@ -425,8 +425,8 @@ class TMGMTLocalTestCase extends TMGMTBaseTestCase {
     $this->loginAsTranslator();
     $job = $this->createJob();
     $job->translator = $translator->name;
-    $job->addItem('test_source', 'test', '1');
-    $job->addItem('test_source', 'test', '2');
+    $job->addItem('test_source', 'node', 1);
+    $job->addItem('test_source', 'node', 2);
 
     $this->assertFalse($job->requestTranslation(), 'Translation request was denied.');
 
diff --git a/ui/css/tmgmt_ui.admin.css b/ui/css/tmgmt_ui.admin.css
index 7bc141b..cf543a4 100644
--- a/ui/css/tmgmt_ui.admin.css
+++ b/ui/css/tmgmt_ui.admin.css
@@ -8,17 +8,21 @@
   margin-right: 80px;
 }
 
-.tmgmt-ui-job-submit.tmgmt-ui-job-items {
-  max-width: 500px;
+.tmgmt-ui-translator-wrapper {
+  width: 500px;
+  margin-right: 20px;
   float: left;
 }
 
-#tmgmt-ui-translator-wrapper {
-  width: 500px;
-  margin-right: 20px;
+.tmgmt-ui-translator-wrapper-right {
+  max-width: 700px;
   float: left;
 }
 
+.tmgmt-ui-job-items-suggestions fieldset {
+  padding-top: 13px;
+}
+
 table.tmgmt-ui-review td {
   vertical-align: top;
 }
diff --git a/ui/includes/tmgmt_ui.pages.inc b/ui/includes/tmgmt_ui.pages.inc
index c57c371..92e6356 100644
--- a/ui/includes/tmgmt_ui.pages.inc
+++ b/ui/includes/tmgmt_ui.pages.inc
@@ -373,7 +373,16 @@ function tmgmt_job_form($form, &$form_state, TMGMTJob $job, $op = 'edit') {
   }
 
   if ($view = views_get_view('tmgmt_ui_job_items')) {
-    $form['items'] = array(
+    // Wrapper on the right side which holds the jobs and the suggestions.
+    $form['translator_wrapper_right'] = array(
+      '#type' => 'container',
+      '#prefix' => '<div class="tmgmt-ui-translator-wrapper-right">',
+      '#suffix' => '</div>',
+      '#weight' => 25,
+    );
+
+    // Translation jobs.
+    $form['translator_wrapper_right']['items'] = array(
       '#type' => 'item',
       '#title' => $view->get_title(),
       '#prefix' => '<div class="' . 'tmgmt-ui-job-items ' . ($job->isSubmittable() ? 'tmgmt-ui-job-submit' : 'tmgmt-ui-job-manage') . '">',
@@ -382,11 +391,78 @@ function tmgmt_job_form($form, &$form_state, TMGMTJob $job, $op = 'edit') {
       '#suffix' => '</div>',
       '#weight' => $job->isSubmittable() ? 30 : 10,
     );
+
+    // A Wrapper for a button and a table with all suggestions.
+    $form['translator_wrapper_right']['suggestions'] = array(
+      '#type' => 'fieldset',
+      '#title' => '',
+      '#prefix' => '<div class="tmgmt-ui-job-items-suggestions ' . ($job->isSubmittable() ? 'tmgmt-ui-job-suggestions-submit' : 'tmgmt-ui-job-suggestions-manage') . '">',
+      '#suffix' => '</div>',
+      '#weight' => $job->isSubmittable() ? 35 : 15,
+    );
+
+    // Button to load all translation suggestions with AJAX.
+    $form['translator_wrapper_right']['suggestions']['load'] = array(
+      '#type' => 'submit',
+      '#value' => t('Load suggestions'),
+      '#submit' => array('tmgmt_ui_ajax_submit_load_suggestions'),
+      '#limit_validation_errors' => array(),
+      '#attributes' => array(
+        'class' => array('tmgmt-ui-job-suggestions-load')
+      ),
+      '#ajax' => array(
+        'callback' => 'tmgmt_ui_ajax_callback_load_suggestions',
+        'wrapper' => 'tmgmt-ui-job-items-suggestions',
+        'method' => 'replace',
+        'effect' => 'fade',
+      ),
+      '#weight' => 10,
+    );
+
+    // Create the suggestions table.
+    $suggestions_table = array(
+      '#type' => 'tableselect',
+      '#header' => array(),
+      '#options' => array(),
+      '#multiple' => TRUE,
+      '#weight' => 20,
+    );
+
+    // If this is an AJAX-Request, load all related nodes and fill the table.
+    if ($form_state['rebuild'] && $form_state['rebuild_suggestions']) {
+      _tmgmt_ui_translation_suggestions($suggestions_table, $form_state);
+
+      // A save button on bottom of the table is needed.
+      $suggestions_table = array(
+        'suggestions_table' => $suggestions_table,
+        'suggestions_save' => array(
+          '#type' => 'submit',
+          '#value' => t('Save suggestions'),
+          '#submit' => array('tmgmt_ui_ajax_submit_save_suggestions'),
+          '#limit_validation_errors' => array(),
+          '#attributes' => array(
+            'class' => array('tmgmt-ui-job-suggestions-save')
+          ),
+          '#ajax' => array(
+            'callback' => 'tmgmt_ui_ajax_callback_load_suggestions',
+            'wrapper' => 'tmgmt-ui-job-items-suggestions',
+            'method' => 'replace',
+            'effect' => 'fade',
+          ),
+          '#weight' => 30,
+        ),
+      );
+    }
+    $form['translator_wrapper_right']['suggestions']['suggestions_list'] = array(
+      '#type' => 'container',
+      '#prefix' => '<div id="tmgmt-ui-job-items-suggestions" class="tmgmt-ui-job-items-suggestions">',
+      '#suffix' => '</div>',
+    ) + $suggestions_table;
   }
 
   $form['translator_wrapper'] = array(
     '#type' => 'container',
-    '#prefix' => '<div id="tmgmt-ui-translator-wrapper">',
+    '#prefix' => '<div class="tmgmt-ui-translator-wrapper">',
     '#suffix' => '</div>',
     '#weight' => 20,
   );
@@ -487,6 +563,115 @@ function tmgmt_job_form($form, &$form_state, TMGMTJob $job, $op = 'edit') {
 }
 
 /**
+ * Set a value in form_state to rebuild the form and fill with data.
+ */
+function tmgmt_ui_ajax_submit_load_suggestions(array $form, array &$form_state) {
+  $form_state['rebuild'] = TRUE;
+  $form_state['rebuild_suggestions'] = TRUE;
+}
+
+/**
+ * Saves selected suggestions as jobs and returns the outstanding suggestions.
+ */
+function tmgmt_ui_ajax_submit_save_suggestions($form, &$form_state) {
+  // Save all selected suggestion jobs.
+  if (isset($form_state['input']['suggestions_table']) && is_array($form_state['input']['suggestions_table'])) {
+    foreach ($form_state['input']['suggestions_table'] as $id) {
+      if (isset($form_state['tmgmt_suggestions'][$id]['tmgmt_job'])
+        && isset($form_state['tmgmt_job'])
+        && ($form_state['tmgmt_suggestions'][$id]['tmgmt_job'] instanceof TMGMTJobItem)
+        && ($form_state['tmgmt_job'] instanceof TMGMTJob)) {
+        $item = &$form_state['tmgmt_suggestions'][$id]['tmgmt_job'];
+        $item = $form_state['tmgmt_job']->addItem($item->plugin, $item->item_type, $item->item_id);
+        // @todo: Maybe add the new item to the main 'job items table' and
+        //        refresh that too. Or at least print a message to show success.
+      }
+    }
+  }
+
+  // Force a rebuild of the form.
+  $form_state['rebuild'] = TRUE;
+  $form_state['rebuild_suggestions'] = TRUE;
+}
+
+/**
+ * Returns the suggestions table for an AJAX-Call.
+ */
+function tmgmt_ui_ajax_callback_load_suggestions($form, &$form_state) {
+  return $form['translator_wrapper_right']['suggestions']['suggestions_list'];
+}
+
+/**
+ * Fills the tableselect with all translation suggestions.
+ *
+ * Calls hook_tmgmt_source_suggestions(TMGMTJob) and creates the resulting list
+ * based on the results from all modules.
+ *
+ * @param array $suggestions_table
+ *   Tableselect part for a $form array where the #options should be inserted.
+ * @param array $form_state
+ *   The main form_state.
+ */
+function _tmgmt_ui_translation_suggestions(array &$suggestions_table, array &$form_state) {
+  $options = array();
+  $job = $form_state['tmgmt_job'];
+  if ($job instanceof TMGMTJob) {
+    // Cache all suggestions.
+    if (TRUE || !isset($form_state['tmgmt_suggestions']) || (count($form_state['tmgmt_suggestions']) <= 0)) {
+      $form_state['tmgmt_suggestions'] = module_invoke_all('tmgmt_source_suggestions', $job);
+      // @todo: Recursive call to all jobs to get sub-suggestions as well.
+      //        A break-rule has to be defined, based on a level or whatever.
+    }
+
+    // Remove suggestions which are already processed, translated, ...
+    $job->cleanSuggestionsList($form_state['tmgmt_suggestions']);
+
+    // Process all valid entries.
+    foreach ($form_state['tmgmt_suggestions'] as $k => &$result) {
+      if (is_array($result) && isset($result['tmgmt_job']) && ($result['tmgmt_job'] instanceof TMGMTJobItem)) {
+        $entity = $result['tmgmt_job'];
+        $referenced = isset($result['referenced']) ? $result['referenced'] : NULL;
+        $options[$k] = _tmgmt_ui_add_suggestion_job($entity, $entity->label(), $referenced);
+      }
+    }
+
+    $suggestions_table['#options'] = $options;
+    $suggestions_table['#empty'] = t('No related suggestions available.');
+    $suggestions_table['#header'] = array(
+      'title' => t('Title'),
+      'referenced' => t('Reference'),
+      'words' => t('Word count'),
+    );
+  }
+}
+
+/**
+ * Create a Suggestion-Table entry based on a TMGMTJob and a title.
+ *
+ * @param TMGMTJobItem $entity
+ *   A translation jobitem created by a module which is a suggestion.
+ * @param string $title = NULL
+ *   (Optional) title for the suggestion row.
+ * @param string $referenced = NULL
+ *   (Optional) Text and/or link to the entity which suggests this job.
+ *
+ * @return array
+ *   Options-Entry for a tableselect array.
+ */
+function _tmgmt_ui_add_suggestion_job(TMGMTJobItem &$entity, $title = NULL, $referenced = NULL) {
+  return array(
+    'title' => isset($title) ? $title : t('From job #@id', array('@id' => $entity->identifier())),
+    'words' => $entity->getWordCount(),
+    'referenced' => array(
+      'data' => array(
+        '#type' => 'markup',
+        '#markup' => isset($referenced) ? $referenced : '',
+      )
+    ),
+  );
+}
+
+/**
  * Submit callback for the job checkout form.
  */
 function tmgmt_job_form_submit($form, &$form_state) {
