diff --git a/sites/all/modules/i18n/i18nviews/includes/i18nviews.views.inc b/sites/all/modules/i18n/i18nviews/includes/i18nviews.views.inc
index 1a5b1fa..414e7aa 100644
--- a/sites/all/modules/i18n/i18nviews/includes/i18nviews.views.inc
+++ b/sites/all/modules/i18n/i18nviews/includes/i18nviews.views.inc
@@ -17,11 +17,42 @@ function i18nviews_views_data() {
  */
 function i18nviews_views_handlers() {
   return array(
+    'info' => array(
+      'path' => drupal_get_path('module', 'i18nviews') . '/includes',
+     ),
     'handlers' => array(
       'content_negotiation_filter_handler' => array(
         'parent' => 'views_handler_filter',
         'file' => 'includes/content_negotiation_filter_handler.inc'
       ),
+      'i18nviews_handler_field_taxonomy' => array(
+         'parent' => 'views_handler_field_taxonomy',
+      ),
+      'i18nviews_handler_field_term_description' => array(
+         'parent' => 'views_handler_field_markup',
+      ),
+      'i18nviews_handler_field_term_node_tid' => array(
+         'parent' => 'views_handler_field_term_node_tid',
+      ),
+      'i18nviews_handler_argument_term_node_tid' => array(
+         'parent' => 'views_handler_argument_term_node_tid',
+      ),
+      'i18nviews_handler_filter_term_node_tid' => array(
+         'parent' => 'views_handler_filter_term_node_tid',
+      ),
     ),
   );
 }
+
+/**
+ * Implemenation of hook_views_data_alter().
+ */
+function i18nviews_views_data_alter(&$data) {
+  $data['term_data']['name']['field']['handler'] = 'i18nviews_handler_field_taxonomy';
+  $data['term_data']['description']['field']['handler'] = 'i18nviews_handler_field_term_description';
+  $data['term_node']['tid']['field']['handler'] = 'i18nviews_handler_field_term_node_tid';
+  $data['term_node']['tid']['argument']['handler'] = 'i18nviews_handler_argument_term_node_tid';
+  $data['term_node']['tid']['filter']['handler'] = 'i18nviews_handler_filter_term_node_tid';
+  //dsm($data);
+}
+
diff --git a/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_argument_term_node_tid.inc b/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_argument_term_node_tid.inc
new file mode 100644
index 0000000..e554b22
--- /dev/null
+++ b/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_argument_term_node_tid.inc
@@ -0,0 +1,19 @@
+<?php
+// $Id$
+
+/**
+ * Allow taxonomy term ID(s) as argument
+ */
+class i18nviews_handler_argument_term_node_tid extends views_handler_argument_term_node_tid {
+  function title_query() {
+    $titles = array();
+    $placeholders = implode(', ', array_fill(0, sizeof($this->value), '%d'));
+
+    $result = db_query("SELECT name, tid FROM {term_data} WHERE tid IN ($placeholders)", $this->value);
+    while ($term = db_fetch_object($result)) {
+      $titles[] = check_plain(tt('taxonomy:term:'. $term->tid .':name', $term->name));
+    }
+    return $titles;
+  }
+}
+
diff --git a/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_field_taxonomy.inc b/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_field_taxonomy.inc
new file mode 100644
index 0000000..1265b77
--- /dev/null
+++ b/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_field_taxonomy.inc
@@ -0,0 +1,17 @@
+<?php
+// $Id$
+
+/**
+ * Field handler to provide simple renderer that allows linking to a taxonomy
+ * term.
+ */
+class i18nviews_handler_field_taxonomy extends views_handler_field_taxonomy {
+  function pre_render($values) {
+    foreach ($values as $key => $value) {
+      if (isset($value->term_data_name)) {
+        $tid = (isset($value->term_data_tid)) ? $value->term_data_tid : $value->tid;
+        $values[$key]->term_data_name = tt('taxonomy:term:'. $tid .':name', $value->term_data_name);
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_field_term_description.inc b/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_field_term_description.inc
new file mode 100644
index 0000000..db1cd0f
--- /dev/null
+++ b/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_field_term_description.inc
@@ -0,0 +1,17 @@
+<?php
+// $Id$
+
+/**
+ * Field handler to provide simple renderer that allows linking to a taxonomy
+ * term.
+ */
+class i18nviews_handler_field_term_description extends views_handler_field_markup {
+  function pre_render($values) {
+    foreach ($values as $key => $value) {
+      if (isset($value->term_data_description)) {
+        $tid = (isset($value->term_data_tid)) ? $value->term_data_tid : $value->tid;
+        $values[$key]->term_data_description = tt('taxonomy:term:'. $tid .':description', $value->term_data_description);
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_field_term_node_tid.inc b/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_field_term_node_tid.inc
new file mode 100644
index 0000000..808e82b
--- /dev/null
+++ b/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_field_term_node_tid.inc
@@ -0,0 +1,40 @@
+<?php
+// $Id$
+
+/**
+ * Field handler for terms.
+ */
+class i18nviews_handler_field_term_node_tid extends views_handler_field_term_node_tid {
+  function pre_render($values) {
+    $this->field_alias = $this->aliases['vid'];
+    $vids = array();
+    foreach ($values as $result) {
+      if (!empty($result->{$this->aliases['vid']})) {
+        $vids[] = $result->{$this->aliases['vid']};
+      }
+    }
+
+    if ($vids) {
+      $voc = '';
+      if (!empty($this->options['limit']) && !empty($this->options['vids'])) {
+        $voc = " AND td.vid IN (" . implode(', ', array_keys(array_filter($this->options['vids']))) . ")";
+      }
+
+      $result = db_query("SELECT tn.vid AS node_vid, td.*, v.name as vocabulary FROM {term_data} td INNER JOIN {term_node} tn ON td.tid = tn.tid INNER JOIN {vocabulary} v ON v.vid = td.vid WHERE tn.vid IN (" . implode(', ', $vids) . ")$voc ORDER BY td.weight, td.name");
+
+      while ($term = db_fetch_object($result)) {
+      $name = tt('taxonomy:term:'. $term->tid .':name', $term->name);
+        $this->items[$term->node_vid][$term->tid]['name'] = check_plain($name);
+        $this->items[$term->node_vid][$term->tid]['tid'] = $term->tid;
+        $this->items[$term->node_vid][$term->tid]['vid'] = $term->vid;
+        $this->items[$term->node_vid][$term->tid]['vocabulary'] = check_plain($term->vocabulary);
+        
+        if (!empty($this->options['link_to_taxonomy'])) {
+          $this->items[$term->node_vid][$term->tid]['make_link'] = TRUE;
+          $this->items[$term->node_vid][$term->tid]['path'] = taxonomy_term_path($term);
+        }
+      }
+    }
+  }
+}
+
diff --git a/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_filter_term_node_tid.inc b/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_filter_term_node_tid.inc
new file mode 100644
index 0000000..b6d3784
--- /dev/null
+++ b/sites/all/modules/i18n/i18nviews/includes/i18nviews_handler_filter_term_node_tid.inc
@@ -0,0 +1,170 @@
+<?php
+
+// $Id$
+
+/**
+ * Filter by term id.
+ */
+class i18nviews_handler_filter_term_node_tid extends views_handler_filter_term_node_tid {
+
+  function value_form(&$form, &$form_state) {
+    $vocabulary = taxonomy_vocabulary_load($this->options['vid']);
+    if (empty($vocabulary) && $this->options['limit']) {
+      $form['markup'] = array(
+        '#prefix' => '<div class="form-item">',
+        '#suffix' => '</div>',
+        '#value' => t('An invalid vocabulary is selected. Please change it in the options.'),
+      );
+      return;
+    }
+
+    if ($this->options['type'] == 'textfield') {
+      $default = '';
+      if ($this->value) {
+        $result = db_query("SELECT * FROM {term_data} td WHERE td.tid IN (" . implode(', ', $this->value) . ')');
+        while ($term = db_fetch_object($result)) {
+          if ($default) {
+            $default .= ', ';
+          }
+          $default .= tt('taxonomy:term:'. $term->tid .':name', $term->name);
+        }
+      }
+
+      $form['value'] = array(
+        '#title' => $this->options['limit'] ? t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name)) : t('Select terms'),
+        '#type' => 'textfield',
+        '#default_value' => $default,
+      );
+
+      if ($this->options['limit']) {
+        $form['value']['#autocomplete_path'] = 'taxonomy/autocomplete/' . $vocabulary->vid;
+      }
+    }
+    else {
+      if (!empty($this->options['hierarchy']) && $this->options['limit']) {
+        $tree = taxonomy_get_tree($vocabulary->vid);
+        $options = array();
+
+        if ($tree) {
+          foreach ($tree as $term) {
+            $choice = new stdClass();
+            $choice->option = array($term->tid => str_repeat('-', $term->depth) . tt('taxonomy:term:'. $term->tid .':name', $term->name));
+            $options[] = $choice;
+          }
+        }
+      }
+      else {
+        $options = array();
+        if ($this->options['limit']) {
+          $result = db_query("SELECT * FROM {term_data} WHERE vid = %d ORDER BY weight, name", $vocabulary->vid);
+        }
+        else {
+          $result = db_query("SELECT td.* FROM {term_data} td INNER JOIN {vocabulary} v ON td.vid = v.vid ORDER BY v.weight, v.name, td.weight, td.name");
+        }
+        while ($term = db_fetch_object($result)) {
+          $options[$term->tid] = tt('taxonomy:term:'. $term->tid .':name', $term->name);
+        }
+      }
+
+      $default_value = (array) $this->value;
+
+      if (!empty($form_state['exposed'])) {
+        $identifier = $this->options['expose']['identifier'];
+
+        if (!empty($this->options['expose']['reduce'])) {
+          $options = $this->reduce_value_options($options);
+
+          if (empty($this->options['expose']['single']) && !empty($this->options['expose']['optional'])) {
+            $default_value = array();
+          }
+        }
+
+        if (!empty($this->options['expose']['single'])) {
+          if (!empty($this->options['expose']['optional']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) {
+            $default_value = 'All';
+          }
+          else if (empty($default_value)) {
+            $keys = array_keys($options);
+            $default_value = array_shift($keys);
+          }
+          else {
+            $copy = $default_value;
+            $default_value = array_shift($copy);
+          }
+        }
+      }
+      $form['value'] = array(
+        '#type' => 'select',
+        '#title' => $this->options['limit'] ? t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name)) : t('Select terms'),
+        '#multiple' => TRUE,
+        '#options' => $options,
+        '#size' => min(9, count($options)),
+        '#default_value' => $default_value,
+      );
+
+      if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier])) {
+        $form_state['input'][$identifier] = $default_value;
+      }
+    }
+
+
+    if (empty($form_state['exposed'])) {
+      // Retain the helper option
+      $this->helper->options_form($form, $form_state);
+    }
+  }
+
+  /**
+   * Validate the user string. Since this can come from either the form
+   * or the exposed filter, this is abstracted out a bit so it can
+   * handle the multiple input sources.
+   */
+  function validate_term_strings(&$form, $values) {
+    if (empty($values)) {
+      return array();
+    }
+
+    $tids = array();
+    $placeholders = array();
+    $args = array();
+    $results = array();
+    foreach ($values as $value) {
+      $missing[strtolower($value)] = TRUE;
+      $args[] = $value;
+      $placeholders[] = "'%s'";
+    }
+
+    if (!$args) {
+      return;
+    }
+
+    // add the taxonomy vid to the argument list.
+    $args[] = $this->options['vid'];
+
+    $result = db_query("SELECT * FROM {term_data} WHERE name IN (" . implode(', ', $placeholders) . ") AND vid = %d", $args);
+    while ($term = db_fetch_object($result)) {
+      unset($missing[strtolower(tt('taxonomy:term:'. $term->tid .':name', $term->name))]);
+      $tids[] = $term->tid;
+    }
+
+    if ($missing) {
+      form_error($form, format_plural(count($missing), 'Unable to find term: @terms', 'Unable to find terms: @terms', array('@terms' => implode(', ', array_keys($missing)))));
+    }
+
+    return $tids;
+  }
+
+  function admin_summary() {
+    // set up $this->value_options for the parent summary
+    $this->value_options = array();
+
+    if ($this->value) {
+      $result = db_query("SELECT * FROM {term_data} td WHERE td.tid IN ("  . implode(', ', $this->value) . ")");
+
+      while ($term = db_fetch_object($result)) {
+        $this->value_options[$term->tid] = tt('taxonomy:term:'. $term->tid .':name', $term->name);
+      }
+    }
+    return parent::admin_summary();
+  }
+}
