diff -u b/term_reference_tree.module b/term_reference_tree.module
--- b/term_reference_tree.module
+++ b/term_reference_tree.module
@@ -118,8 +118,6 @@
         }
       }
 
-      // Resolve label and add the term to the final array.
-      _term_reference_tree_taxonomy_resolve_label($term);
       $terms[$term->tid] = $term;
     }
   }
@@ -203,24 +201,37 @@
  * @param object $term
  *   The taxonomy term object.
  */
-function _term_reference_tree_taxonomy_resolve_label($term) {
-  // Ajax calls the process function twice so we set a property of the term
-  // in order no to resolve it twice.
-  if (!isset($term->term_reference_tree_label_resolved) || !$term->term_reference_tree_label_resolved) {
-    // If a callback is implemented to get the label name use it.
-    if ($callback = variable_get('term_reference_tree_taxonomy_resolve_label_callback')) {
-      if (function_exists($callback)) {
-        $term->name = call_user_func($callback, $term);
+function _term_reference_tree_taxonomy_resolve_labels($terms, $token_display) {
+  if (!empty($token_display) && module_exists('token')) {
+    $loaded = entity_load('taxonomy_term', array_keys($terms));
+    foreach ($loaded as $term) {
+      $terms[$term->tid]->term_reference_tree_token = token_replace($token_display, array('term' => $term), array('clear' => TRUE));
+    }
+  }
+  elseif (module_exists('locale')) {
+    $to_resolve = array();
+    foreach ($terms as $term) {
+      if (!isset($term->term_reference_tree_label)) {
+        $to_resolve[$term->tid] = $term->tid;
       }
     }
-    // Otherwise fallback to entity_label().
-    elseif (module_exists('locale')) {
-      $term = taxonomy_term_load($term->tid);
-      $term->name = entity_label('taxonomy_term', $term);
+
+    $loaded = entity_load('taxonomy_term', array_keys($to_resolve));
+    foreach ($loaded as $term) {
+      $terms[$term->tid]->term_reference_tree_label = entity_label('taxonomy_term', $term);
     }
+  }
+}
 
-    $term->term_reference_tree_label_resolved = TRUE;
+function _term_reference_tree_hierarchy_flatten($terms_hierarchy) {
+  $terms = array();
+  foreach ($terms_hierarchy as $term) {
+    $terms[$term->tid] = $term;
+    if (!empty($term->children)) {
+      $terms += _term_reference_tree_hierarchy_flatten($term->children);
+    }
   }
+  return $terms;
 }
 
 function _term_reference_tree_get_parent($tid) {
diff -u b/term_reference_tree.widget.inc b/term_reference_tree.widget.inc
--- b/term_reference_tree.widget.inc
+++ b/term_reference_tree.widget.inc
@@ -287,8 +287,19 @@
     $default = !empty($element['#default_value']) ? $element['#default_value'] : array();
     $opened = !empty($form_state['children']) ? $form_state['children'] : array();
     $max_depth = !empty($element['#max_depth']) ? $element['#max_depth'] : NULL;
+
+    // Build the terms hierarchy.
     $element['#options_tree'] = _term_reference_tree_get_term_hierarchy($element['#parent_tid'], $element['#vocabulary']->vid, $allowed, $default, $opened, $element['#use_ajax'], $max_depth);
 
+    // Flatten the hierarchy.
+    $terms_flat = _term_reference_tree_hierarchy_flatten($element['#options_tree']);
+
+    // Give other modules a chance to alter the terms.
+    drupal_alter('term_reference_tree_process_terms', $terms_flat, $element);
+
+    // Resolve labels.
+    _term_reference_tree_taxonomy_resolve_labels($terms_flat, $element['#token_display']);
+
     $max_choices = !empty($element['#max_choices']) ? $element['#max_choices'] : 1;
     if ($max_choices != '-1') {
       drupal_add_js(array('term_reference_tree' => array('trees' => array($element['#id'] => array('max_choices' => $element['#max_choices'])))), 'setting');
@@ -374,7 +385,7 @@
     $attributes['class'] = array_merge($attributes['class'], $element['#attributes']['class']);
   }
   return
-      '<div' . drupal_attributes($attributes) . '>'
+    '<div' . drupal_attributes($attributes) . '>'
     . (!empty($element['#children']) ? $element['#children'] : '')
     . '</div>';
 }
@@ -471,9 +482,9 @@
   }
 
   $label = format_plural(
-      $variables['element']['#max_choices'],
-      'Selected item (click the item to uncheck it)',
-      'Selected items (click an item to uncheck it)'
+    $variables['element']['#max_choices'],
+    'Selected item (click the item to uncheck it)',
+    'Selected items (click an item to uncheck it)'
   );
   $output = '<div class="term-reference-track-list-container">';
   $output .= '<div class="term-reference-track-list-label">' . $label . '</div>';
@@ -670,11 +681,19 @@
  *   possibly a checkbox_tree_level element as well.
  */
 function _term_reference_tree_build_item($element, $term, $form_state, $value, $max_choices, $parent_tids, $parent, $depth) {
+  $term_name = $term->name;
+  if (!empty($element['#token_display']) && module_exists('token') && !empty($term->term_reference_tree_token)) {
+    $term_name = $term->term_reference_tree_token;
+  }
+  elseif (!empty($term->term_reference_tree_label)) {
+    $term_name = $term->term_reference_tree_label;
+  }
+
   $container = array(
     '#type' => 'checkbox_tree_item',
     '#max_choices' => $max_choices,
     '#leaves_only' => isset($element['#leaves_only']) ? $element['#leaves_only'] : FALSE,
-    '#term_name' => $term->name,
+    '#term_name' => $term_name,
     '#level_start_minimized' => FALSE,
     '#depth' => $depth,
     '#has_children' => FALSE,
@@ -683,7 +702,7 @@
   if (!$element['#leaves_only'] || empty($term->children)) {
     $e = array(
       '#type' => ($max_choices == 1) ? 'radio' : 'checkbox',
-      '#title' => $term->name,
+      '#title' => $term_name,
       '#on_value' => $term->tid,
       '#off_value' => 0,
       '#return_value' => $term->tid,
@@ -693,12 +712,6 @@
       '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
     );
 
-    if (!empty($element['#token_display']) && module_exists('token')) {
-      // @TODO Load term and resolve tokens in the process part?
-      $t = taxonomy_term_load($term->tid);
-      $e['#title'] = token_replace($element['#token_display'], array('term' => $t), array('clear' => TRUE));
-    }
-
     if ($e['#type'] == 'radio') {
       $parents_for_id = array_merge($element['#parents'], array($term->tid));
       $e['#id'] = drupal_html_id('edit-' . implode('-', $parents_for_id));
@@ -708,7 +721,7 @@
   else {
     $e = array(
       '#type' => 'checkbox_tree_label',
-      '#value' => $term->name,
+      '#value' => $term_name,
     );
   }
 
