Displaying localized taxonomy terms with views

Translation support with Taxonomy can get tricky. Similar to content translation there are a few different 'modes' taxonomy translation can take. The most common mode to use is "Per language terms" where each term can be assigned to a given language. But in many cases this can be overkill as it requires that different content be assigned to each language term.

For most situations you just want to use the "Localize terms" mode. In his mode the text of the taxonomy term can be translated into the language of your choice using the string translation system. This way you have one term for all your content regardless of the language. The one major downfall to this method however is that it is not compatible with views.

Digging deeper into the views module I noticed that all the methods used to get the terms of a particular node or vocabulary rely on direct queries baked right into the views handlers instead of using Drupal api calls. The initial cause of this is that the returned values from the DB are outputted with a simple 'check_plain' instead of being passed through the translation system. Hence why translated taxonomy text doesn't work with Views.

We absolutely needed this fixed, but didn't want to 'hack' views to get it done. So instead I created module which creates views handlers that extend the existing taxonomy handlers and then override the handler to use mine instead. If that sounds a little confusing hopefully it'll make sense as I dive into the process.

I created a module called i18ntaxonomy_views which I will go through to outlined the process of overriding the default views handler

i18ntaxonomy_views.module

The only thing in this module is the implementation of hook_views_api which is required when doing anything with views. This method basically tells views what api version we are supporting and where it can find the files it needs

<?php
   
   
function i18ntaxonomy_views_views_api() {
      return array(
       
'api' => 2,
       
'path' => drupal_get_path('module', 'i18ntaxonomy_views'),
      );
    }
   
?>

i18ntaxonomy_views.views.inc

The module.views.inc file is responsible for all the major declaration of what your module will be adding to views. This includes the table declaration for the DB queries and handlers for fields, filters and sorts.

In this file I did two things.

  1. Alter the default handlers specified up by taxonomy.views.inc
  2. Registered my custom handlers that I'm going to use instead

<?php
   
/**
     * Implementation of hook_views_data().
     */
   
function i18ntaxonomy_views_views_data_alter(&$data) {

     
// tid field
     
$data['term_node']['tid']['field']['handler'] = 'views_handler_field_term_node_tid_i18n';
     
$data['term_node']['tid']['filter']['handler'] = 'views_handler_filter_term_node_tid_i18n';
      return
$data;
    }

   
/**
     * Implementation of hook_views_handlers() to register all of the basic handlers
     * views uses.
     */
   
function i18ntaxonomy_views_views_handlers() {
      return array(
       
'info' => array(
         
'path' => drupal_get_path('module', 'i18ntaxonomy_views'),
        ),
       
'handlers' => array(
         
'views_handler_field_term_node_tid_i18n' => array(
           
'parent' => 'views_handler_field_term_node_tid',
          ),
         
'views_handler_filter_term_node_tid_i18n' => array(
           
'parent' => 'views_handler_filter_term_node_tid',
          ),
        ),
      );
    }
?>

i18ntaxonomy_views_views_data_alter is an implementation of hook_views_data_alter which lets me change existing declaration of the views $data object. In this case I am changing what taxonomy.views.inc declared for it's handlers for tid field and tid filter

Then in i18ntaxonomy_views_views_handlers I registered my custom handlers views_handler_field_term_node_tid_i18n and views_handler_filter_term_node_tid_i18n. What is extremely important here is that I specified views_handler_field_term_node_tid and views_handler_filter_term_node_tid respectively as the parents of my hanlders. This is where the Object Oriented nature of development comes into play. I don't want to re-invent the wheel with my handler so instead I extend the existing handler that comes with views.

Basically my handler extends the taxonomy.views.inc handler which extends a base handler that views uses.

views_handler_field_term_node_tid_i18n -> views_handler_field_term_node_tid -> views_handler_field_prerender_list

What this means is that in my handler I only have to focus on the part I want to change as the rest of the stuff is taken from the original taxonomy handler. If you're confused or lost I highly recommend reading the views API documentation available when you install the 'Advanced Help' module, as well as looking through the code for the existing 'modules' within views. Start with taxonomy.views.inc and work your way from there.

Next we create our handlers.

views_handler_field_term_node_tid_i18n.inc

<?php
   
/**
     * Field handler for terms.
     */
   
class views_handler_field_term_node_tid_i18n 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)) {
           
$this->items[$term->node_vid][$term->tid]['name'] = i18nstrings("taxonomy:term:$term->tid:name", $term->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);
            }
          }
        }
      }


    }
?>

This first handler is responsible for displaying taxonomy terms associated with a node. The first thing to note is that again I have to declare the class for the handler views_handler_field_term_node_tid_i18n and what class it extends. In this case views_handler_field_term_node_tid. If you look at the original views_handler_field_term_node_tid.inc file there are a lot of functions in that file, but in ours I only copied one. This is because we have extended the original class so I only declare the methods I want to either change or create. In this case I focused on changing the pre_render function as that is responsible for getting the taxonomy terms.

I change the line

<?php
$this
->items[$term->node_vid][$term->tid]['name'] = check_plain($term->name);
?>

to this

<?php
$this
->items[$term->node_vid][$term->tid]['name'] = i18nstrings("taxonomy:term:$term->tid:name", $term->name);
?>

I won't go into the other handler since the concept is basically the same. Find the method you want to override and make changes to it. It may seem like a lot of work, but really it's a lot of copy and paste work with some minor modifications.

The code for this module is on github for anyone to grab and take a look at. https://github.com/freeform/i18ntaxonomy_views

Comments

StryKaizer

Thx for sharing. Seems to fix my troubles!
Definitly worth moving into contrib ;)

Taxonomy translation for term description

Thanks's for sharing these explanations.
That seems to be a very useful module.
I'd like to know if it also work for terms' description

Thanks! & term name

Thanks for sharing, this is very useful.

Now, extending the information: I needed translation to work for the term name in a taxonomy based view that outputs terms as links. Here's the fork: https://github.com/nelovishk/i18ntaxonomy_views

Thanks for the fork!

Thanks for the fork! This is exactly what I've been looking for.

Is there any solution for the

Is there any solution for the Drupal 7 available?

thanks both!

Thanks a lot! Freeform module opened my mind and nelovishk's one completely solved my problems! Huge thanks both!

Fantastic!

Nice job! This module is top notch!

Drupal 7 / views

The module doesn’t seem to work under Drupal 7, but views has got the same problem. Are there any plans to port this module to D7?

Thanks for the interest in

Thanks for the interest in the module. We don't currently have plans to port the module to Drupal 7.

If we are able to, in the future, the module will be posted on the Drupal site, so it may be worth subscribing there (or asking the community). Any support in migrating it to Drupal 7 is of course appreciated.

...
Kevin.

There may be Drupal 7 upgrade

Actually, we were just contacted by one of our clients that is interested in upgrading this module to Drupal 7. As a result, we may work on it and if we do, will release Drupal 7 version of this module some time in March-April 2013.

Please we need that for

Please we need that for Drupal 7 ...

I'm also waiting for this

I'm also waiting for this solution on Drupal 7.

Drupal 7

I wait the module for Drupal 7 too...

not working for me

Hey I have installed this module.
But my taxonomy terms are still coming in default's language.
Am I missing somthing?Please help

Which version are you working with?

Please let us know which version you are working with, Drupal 6? What modules versions? What language configuration are you using?

For D7 users

I successfully implemented the code published on this forum: http://ggordan.com/post/localising-taxonomy-terms-in-views.html

Post new comment

By submitting this form, you accept the Mollom privacy policy.