diff --git a/translators/tmgmt_local/includes/tmgmt_local.plugin.inc b/translators/tmgmt_local/includes/tmgmt_local.plugin.inc
index 6ef7fd1..5aaf793 100644
--- a/translators/tmgmt_local/includes/tmgmt_local.plugin.inc
+++ b/translators/tmgmt_local/includes/tmgmt_local.plugin.inc
@@ -44,7 +44,7 @@ class TMGMTLocalTranslatorPluginController extends TMGMTDefaultTranslatorPluginC
    * Overrides TMGMTDefaultTranslatorPluginController::getSupportedTargetLanguages().
    */
   public function getSupportedTargetLanguages(TMGMTTranslator $translator, $source_language) {
-    $languages = drupal_map_assoc(tmgmt_local_translation_capabilities($source_language));
+    $languages = tmgmt_local_supported_target_languages($source_language);
     if ($translator->getSetting('allow_all')) {
       $languages += parent::getSupportedTargetLanguages($translator, $source_language);
     }
diff --git a/translators/tmgmt_local/skills/tmgmt_language_combination.module b/translators/tmgmt_local/skills/tmgmt_language_combination.module
index 58ca1bf..0e417f3 100644
--- a/translators/tmgmt_local/skills/tmgmt_language_combination.module
+++ b/translators/tmgmt_local/skills/tmgmt_language_combination.module
@@ -170,7 +170,7 @@ function tmgmt_language_combination_field_formatter_view($entity_type, $entity,
     case 'tmgmt_language_combination_default':
       $element['#theme'] = 'item_list';
       $element['#items'] = array();
-
+//tmgmt_local_supported_language_pairs();
       foreach ($items as $delta => $item) {
         $from = tmgmt_language_combination_language_label($item['language_from']);
         $to = tmgmt_language_combination_language_label($item['language_to']);
diff --git a/translators/tmgmt_local/tmgmt_local.api.php b/translators/tmgmt_local/tmgmt_local.api.php
index e091d96..d1dca86 100644
--- a/translators/tmgmt_local/tmgmt_local.api.php
+++ b/translators/tmgmt_local/tmgmt_local.api.php
@@ -5,26 +5,4 @@
  * API documentation for the tmgmt_local module.
  */
 
-/**
- * Return language capabilities.
- *
- * @param $source_language
- *   (optional) Only return capabilities for the given source language.
- * @param $account
- *   (optional) Only return capabilities for the given user.
- *
- * @return array
- *   An array of arrays with the keys source and target.
- */
-function hook_tmgmt_local_translation_capabilities($source_language = NULL, $account = NULL) {
-  return array(
-    array(
-      'source' => 'de',
-      'target' => 'en',
-    ),
-    array(
-      'source' => 'en',
-      'target' => 'de',
-    ),
-  );
-}
+
diff --git a/translators/tmgmt_local/tmgmt_local.module b/translators/tmgmt_local/tmgmt_local.module
index 5552134..38222b5 100644
--- a/translators/tmgmt_local/tmgmt_local.module
+++ b/translators/tmgmt_local/tmgmt_local.module
@@ -303,49 +303,13 @@ function tmgmt_local_translation_access(TMGMTLocalTask $task, $account = NULL) {
   }
 
   // Lastly, check for the translation capabilities.
-  $input = $job->source_language;
-  $required = $job->target_language;
-  $capabilities = tmgmt_local_translation_capabilities($input, $account);
-  $rights[$account->uid][$job->tjid] = in_array($required, $capabilities);
+  $target_languages = tmgmt_local_supported_target_languages($job->source_language, array($account->uid));
+  $rights[$account->uid][$job->tjid] = in_array($job->target_language, $target_languages);
 
   return $rights[$account->uid][$job->tjid];
 }
 
 /**
- * Determines the translation capabilities of a specific user or all users.
- *
- * @param $source_language
- *   (optional) The source language for which to check the translation
- *   capabilities for.
- * @param $account
- *   (optional) A user object representing the user for whom to check the
- *   translation capabilities for.
- *
- * @return array
- *   An array of supported target languages if a source language is given, an
- *   array of language pairs as array with the source and target keys otherwise.
- */
-function tmgmt_local_translation_capabilities($source_language = NULL, $account = NULL) {
-  $capabilities = &drupal_static(__FUNCTION__);
-
-  $key = ($account ? $account->uid : 'all') . ':' . ($source_language ? $source_language : 'all');
-  if (!isset($capabilities[$key])) {
-    $capabilities[$key] = module_invoke_all('tmgmt_local_translation_capabilities', $source_language, $account);
-
-    // If a source key is given, simplify array.
-    // @todo: this is used to ensure backwards compatibility of this hook.
-    //   Possibly rethink this hook completely, use a plugin?
-    if ($source_language) {
-      foreach ($capabilities[$key] as &$capability) {
-        $capability = $capability['target'];
-      }
-    }
-  }
-
-  return $capabilities[$key];
-}
-
-/**
  * Helper function for clearing the languages cache of all local translators.
  *
  * Can be used in oder to clear the cache for supported target languages after
@@ -608,56 +572,6 @@ function tmgmt_local_tasks_languages($tasks) {
 }
 
 /**
- * Return users that belongs to local translation role.
- *
- * @todo: This does not scale when having many translators.
- *
- * @return array
- *   Array of uid => name translators or empty array if there are no translator
- *   users.
- */
-function tmgmt_local_translators($source_language = NULL, $target_language = NULL) {
-  // Get all local user translators.
-  $roles = user_roles(TRUE, 'provide translation services');
-  $query = db_select('users', 'u');
-  $query->fields('u', array('uid'));
-  $query->condition('u.status', 1);
-
-  // Add role condition only if authenticated user role does not have perms.
-  if (!in_array(DRUPAL_AUTHENTICATED_RID, array_keys($roles))) {
-    $query->leftJoin('users_roles', 'ur', 'u.uid = ur.uid');
-    $query->condition('ur.rid', array_keys($roles));
-  }
-
-  $uids = $query->distinct()
-    ->execute()
-    ->fetchCol();
-
-  if (!empty($target_language) && !is_array($target_language)) {
-    $target_language = array($target_language);
-  }
-
-  $translators = array();
-  if (!empty($uids)) {
-    foreach (user_load_multiple($uids) as $user) {
-      // @todo: There is no capabilities API yet for returning users, so
-      //   re-check every user.
-      $capabilities = tmgmt_local_translation_capabilities($source_language, $user);
-      if (empty($capabilities)) {
-        continue;
-      }
-      // In case provided target languages exceed users capabilities exclude.
-      if (!empty($target_language) && count(array_diff($target_language, $capabilities)) > 0) {
-        continue;
-      }
-      $translators[$user->uid] = entity_label('user', $user);
-    }
-  }
-
-  return $translators;
-}
-
-/**
  * Gets translators able to translate all given tasks.
  *
  * @param array $tasks
@@ -787,20 +701,126 @@ function tmgmt_local_field_attach_delete($entity_type, $entity) {
 }
 
 /**
- * Implements hook_tmgmt_local_translation_capabilities().
+ * Gets list of language pairs.
+ *
+ * @param string $source_language
+ *   Source language code for which to limit the selection.
+ * @param array $uids
+ *   List of user ids for whom to get the language pairs.
+ *
+ * @return array
+ *   List of language pairs where a pair is defined by associative array of
+ *   source_language and target_language keys.
  */
-function tmgmt_local_tmgmt_local_translation_capabilities($source_language = NULL, $account = NULL, $target_language = NULL) {
-  // Only considers users with the 'provide translation services' permission.
-  $roles = user_roles(TRUE, 'provide translation services');
+function tmgmt_local_supported_language_pairs($source_language = NULL, $uids = array()) {
+  $language_pairs = &drupal_static(__FUNCTION__);
+  $cache_key = $source_language . '_' . implode('_', $uids);
+
+  if (isset($language_pairs[$cache_key])) {
+    return $language_pairs[$cache_key];
+  }
+
+  $query = tmgmt_local_capabilities_query($source_language, NULL, $uids);
+  $language_pairs[$cache_key] = array();
+
+  foreach ($query->execute()->fetchAll() as $row) {
+    // Prevent duplicates.
+    $pair_key = $row->tmgmt_translation_skills_language_from . '__' . $row->tmgmt_translation_skills_language_to;
+    $language_pairs[$cache_key][$pair_key] = array(
+      'source_language' => $row->tmgmt_translation_skills_language_from,
+      'target_language' => $row->tmgmt_translation_skills_language_to,
+    );
+  }
+
+  return $language_pairs[$cache_key];
+}
+
+/**
+ * Gets supported target languages.
+ *
+ * @param string $source_language
+ *   Source language for which to get target languages.
+ * @param array $uids
+ *   List of user ids for whom to get the target languages.
+ *
+ * @return array
+ *   List of target languages where code is the key as well as the value.
+ */
+function tmgmt_local_supported_target_languages($source_language, $uids = array()) {
+  $pairs = tmgmt_local_supported_language_pairs($source_language, $uids);
+  $supported_languages = array();
+
+  foreach ($pairs as $pair) {
+    $supported_languages[$pair['target_language']] = $pair['target_language'];
+  }
+
+  return $supported_languages;
+}
+
+/**
+ * Gets local translator for given language combination.
+ *
+ * @param string $source_language
+ * @param array $target_languages
+ * @return array
+ *   Array of uid => name translators or empty array if there are no translator
+ *   users.
+ */
+function tmgmt_local_translators($source_language = NULL, $target_languages = array()) {
+  $translators = &drupal_static(__FUNCTION__);
+
+  if (!empty($target_languages) && !is_array($target_languages)) {
+    $target_languages = array($target_languages);
+  }
+
+  $key = $source_language . '_' . implode('_', $target_languages);
+
+  if (isset($translators[$key])) {
+    return $translators[$key];
+  }
+
+  // Get all capabilities keyed by uids for given source language.
+  $query = tmgmt_local_capabilities_query($source_language);
+  $translators_capabilities = array();
+  foreach ($query->execute()->fetchAll() as $row) {
+    $translators_capabilities[$row->uid][] = $row->tmgmt_translation_skills_language_to;
+  }
+
+  // Filter out translator uids who's capabilities are not sufficient for given
+  // target languages.
+  $translators_uids = array();
+  foreach ($translators_capabilities as $uid => $translator_capabilities) {
+    // In case provided target languages exceed users capabilities exclude.
+    if (!empty($target_languages) && count(array_diff($target_languages, $translator_capabilities)) > 0) {
+      continue;
+    }
+    $translators_uids[] = $uid;
+  }
+
+  // Finally build the translators list.
+  $translators[$key] = array();
+  if (!empty($translators_uids)) {
+    foreach (user_load_multiple($translators_uids) as $account) {
+      $translators[$key][$account->uid] = entity_label('user', $account);
+    }
+  }
+
+  return $translators[$key];
+}
+
+/**
+ * @param string $source_language
+ * @param string $target_language
+ * @param array $uids
+ *
+ * @return SelectQuery
+ */
+function tmgmt_local_capabilities_query($source_language = NULL, $target_language = NULL, $uids = array()) {
 
-  // Check for all the available languages. We are directly querying the
-  // field values here instead of using an EntityFieldQuery but that is
-  // okay in this case and there is no other way.
   $query = db_select('field_data_tmgmt_translation_skills', 'ts')
     ->fields('ts', array('tmgmt_translation_skills_language_from', 'tmgmt_translation_skills_language_to'))
     ->condition('ts.deleted', 0)
-    ->condition('ts.entity_type', 'user')
-    ->distinct(TRUE);
+    ->condition('ts.entity_type', 'user');
 
   if ($source_language) {
     $query->condition('ts.tmgmt_translation_skills_language_from', $source_language);
@@ -810,30 +830,22 @@ function tmgmt_local_tmgmt_local_translation_capabilities($source_language = NUL
     $query->condition('ts.tmgmt_translation_skills_language_to', $target_language);
   }
 
-  // Only consider active users.
+  // Join only active users.
   $query->innerJoin('users', 'u', 'u.uid = ts.entity_id AND u.status = 1');
+  $query->fields('u', array('uid', 'name', 'mail'));
 
-  if (isset($account)) {
-    $query->condition('u.uid', $account->uid);
+  if (!empty($uids)) {
+    $query->condition('u.uid', $uids);
   }
 
-  // Only consider users that have the 'provide translation services'
-  // permission or the admin user.
-  $query->leftJoin('users_roles', 'ur', "ur.uid = u.uid AND ur.rid IN (:roles) OR u.uid = 1", array(':roles' => implode(', ', array_keys($roles))));
+  // Only consider users that have the 'provide translation services' perm.
+  $roles = user_roles(TRUE, 'provide translation services');
+  $query->leftJoin('users_roles', 'ur', "ur.uid = u.uid AND ur.rid IN (:roles)", array(':roles' => implode(', ', array_keys($roles))));
 
   // Add a tag so other modules can alter this query at will.
   $query->addTag('tmgmt_translation_combination');
 
-  // Only return languages that are supported by at least one user.
-  $result = $query->execute();
+  return $query;
+}
 
-  $combination = array();
-  foreach ($result as $item) {
-    $combination[] = array(
-      'source' => $item->tmgmt_translation_skills_language_from,
-      'target' => $item->tmgmt_translation_skills_language_to,
-    );
-  }
 
-  return $combination;
-}
diff --git a/translators/tmgmt_local/tmgmt_local.test b/translators/tmgmt_local/tmgmt_local.test
index fc842f6..018948a 100644
--- a/translators/tmgmt_local/tmgmt_local.test
+++ b/translators/tmgmt_local/tmgmt_local.test
@@ -437,4 +437,119 @@ class TMGMTLocalTestCase extends TMGMTBaseTestCase {
     $this->assertIdentical(NULL, $job->requestTranslation(), 'Translation request was successfull');
     $this->assertTrue($job->isActive());
   }
+
+  function testCapabilitiesAPI() {
+
+    $this->setEnvironment('fr');
+    $this->setEnvironment('ru');
+    $this->setEnvironment('it');
+
+    $all_translators = array();
+
+    $translator1 = $this->drupalCreateUser($this->local_translator_permissions);
+    $all_translators[$translator1->uid] = $translator1->name;
+    $this->drupalLogin($translator1);
+    $edit = array(
+      'tmgmt_translation_skills[und][0][language_from]' => 'en',
+      'tmgmt_translation_skills[und][0][language_to]' => 'de',
+    );
+    $this->drupalPost('user/' . $translator1->uid . '/edit', $edit, t('Save'));
+
+    $translator2 = $this->drupalCreateUser($this->local_translator_permissions);
+    $all_translators[$translator2->uid] = $translator2->name;
+    $this->drupalLogin($translator2);
+    $edit = array(
+      'tmgmt_translation_skills[und][0][language_from]' => 'en',
+      'tmgmt_translation_skills[und][0][language_to]' => 'ru',
+    );
+    $this->drupalPost('user/' . $translator2->uid . '/edit', $edit, t('Save'));
+    $edit = array(
+      'tmgmt_translation_skills[und][1][language_from]' => 'en',
+      'tmgmt_translation_skills[und][1][language_to]' => 'fr',
+    );
+    $this->drupalPost('user/' . $translator2->uid . '/edit', $edit, t('Save'));
+    $edit = array(
+      'tmgmt_translation_skills[und][2][language_from]' => 'fr',
+      'tmgmt_translation_skills[und][2][language_to]' => 'it',
+    );
+    $this->drupalPost('user/' . $translator2->uid . '/edit', $edit, t('Save'));
+
+    $translator3 = $this->drupalCreateUser($this->local_translator_permissions);
+    $all_translators[$translator3->uid] = $translator3->name;
+    $this->drupalLogin($translator3);
+    $edit = array(
+      'tmgmt_translation_skills[und][0][language_from]' => 'fr',
+      'tmgmt_translation_skills[und][0][language_to]' => 'ru',
+    );
+    $this->drupalPost('user/' . $translator3->uid . '/edit', $edit, t('Save'));
+    $edit = array(
+      'tmgmt_translation_skills[und][1][language_from]' => 'it',
+      'tmgmt_translation_skills[und][1][language_to]' => 'en',
+    );
+    $this->drupalPost('user/' . $translator3->uid . '/edit', $edit, t('Save'));
+
+    // Test target languages.
+    $target_languages = tmgmt_local_supported_target_languages('fr');
+    $this->assertTrue(isset($target_languages['it']));
+    $this->assertTrue(isset($target_languages['ru']));
+    $target_languages = tmgmt_local_supported_target_languages('en');
+    $this->assertTrue(isset($target_languages['fr']));
+    $this->assertTrue(isset($target_languages['ru']));
+
+    // Test language pairs.
+    $this->assertEqual(tmgmt_local_supported_language_pairs(), array (
+      'en__de' =>
+      array (
+        'source_language' => 'en',
+        'target_language' => 'de',
+      ),
+      'en__ru' =>
+      array (
+        'source_language' => 'en',
+        'target_language' => 'ru',
+      ),
+      'en__fr' =>
+      array (
+        'source_language' => 'en',
+        'target_language' => 'fr',
+      ),
+      'fr__it' =>
+      array (
+        'source_language' => 'fr',
+        'target_language' => 'it',
+      ),
+      'fr__ru' =>
+      array (
+        'source_language' => 'fr',
+        'target_language' => 'ru',
+      ),
+      'it__en' =>
+      array (
+        'source_language' => 'it',
+        'target_language' => 'en',
+      ),
+    ));
+    $this->assertEqual(tmgmt_local_supported_language_pairs('fr', array($translator2->uid)), array (
+      'fr__it' =>
+      array (
+        'source_language' => 'fr',
+        'target_language' => 'it',
+      ),
+    ));
+
+    // Test if we got all translators.
+    $translators = tmgmt_local_translators();
+    foreach ($all_translators as $uid => $name) {
+      if (!isset($translators[$uid])) {
+        $this->fail('Expected translator not present');
+      }
+      if (!in_array($name, $all_translators)) {
+        $this->fail('Expected translator name not present');
+      }
+    }
+
+    // Only translator2 has such capabilities.
+    $translators = tmgmt_local_translators('en', array('ru', 'fr'));
+    $this->assertTrue(isset($translators[$translator2->uid]));
+  }
 }
diff --git a/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_filter_eligible.inc b/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_filter_eligible.inc
index 2aeae68..38d39d7 100644
--- a/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_filter_eligible.inc
+++ b/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_filter_eligible.inc
@@ -19,9 +19,10 @@ class tmgmt_local_task_handler_filter_eligible extends views_handler_filter {
     // and target language combinations.
     $this->query->set_where_group('OR', 'eligible');
     // Return all language capabilities for the current user.
-    foreach (tmgmt_local_translation_capabilities(NULL, $GLOBALS['user']) as $key => $capability) {
-      $arguments = array(':source_' . $key => $capability['source'], ':target_' . $key => $capability['target']);
+    foreach (tmgmt_local_supported_language_pairs(NULL, array($GLOBALS['user']->uid)) as $key => $capability) {
+      $key = str_replace('-', '_', $key);
+      $arguments = array(':source_' . $key => $capability['source_language'], ':target_' . $key => $capability['target_language']);
       $this->query->add_where_expression('eligible', "$source = :source_$key AND $target = :target_$key", $arguments);
-      }
+    }
   }
 }
