Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough
Feb 10 2015
Feb 10

Multi lingual sites is a desired feature for sites targeting audiences of multiple countries or of more than one linguistic groups for example my first experience with the module was translating the Wanderlust Festival website for audiences in Quebec, where French and English are national languages. For Drupal there are many features which streamline the process. We will go into some of the standard translation techniques. In a later post I will go into identifying and translating certain hard to target strings such as those in complex views.

The Translate Function:

When we are dealing with content in templates for pages/nodes/content-types, etc. some strings are hardcoded in these tpl.php files.

Drupal provides us a smart way to let its template engine know which strings to consider for translation and which strings to treat as constant literals – that don’t need translation.

There is a translate function, also known as t function or t(). Anything passed inside this function is processed and considered for translation before getting passed to html content. Example: t(“text for translation”).

String literals that are not enclosed in this function are considered as constant strings and are passed as is into the html content. Example: Anything that doesn’t require translation – like Names of places, persons, etc. (in case we are translating in the same script like English to French)

The prototype of the translate function is:

t($string, array $args = array(), array $options = array());

Here, $string is the variable containing the English string to translate.
$args is an associative array of replacements to make. Occurrences in $string of any key in $args are replaced with the corresponding value, after optional sanitization and formatting. The type of sanitization and formatting depends on the first character of the key:

  • @variable: Value is inserted as plain text.
  • %variable: This makes it display as <em>emphasized</em> text.
  • !variable: Inserted as is, with no sanitization or formatting. Only use this for text that has already been prepared for HTML display (for example, user-supplied text that has already been run through check_plain() previously, or is expected to contain some limited HTML tags and has already been run through filter_xss() previously).

This is an example to demonstrate above three keys:

t("This is my <b>text</b>", array( '@This' => 'yeh', '%is my' => 'hi', '!<b>text</b>' =>  '<i>text</i>'));

It will translate from “This is my text” to “yeh hi text”.
The simplest call to t() looks like this:
t(“This is my text”);

Where to call t() function ?

  • Any string that is a name, url, address passed in t() should specify the translated string also either from the admin panel or in the translate function call itself by passing through $args array.
  • In case you are making a Form with form API, it is a good practice to pass the title, placeholder and labels in t() function. Example:$form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Subject'),
    '#required' => TRUE,
  • In case your are using a php field in views, it is advisable to output any text in t(), except for dates or dynamic data.

Where not to call t() function ?

It is NOT advisable to use t() in following scenarios:

  • t($text);
    unless the text that the variable holds has been passed through t() elsewhere (e.g., $text is one of several translated literal strings in an array).
  • It is especially important never to call
    where $user_text is some text that a user entered – doing that can lead to cross-site scripting and other security problems.

However, you can use variable substitution in your string, to put variable text such as user names or link URLs into translated text. Variable substitution looks like this:

$text = t("@name's blog", array('@name' => format_username($account)));

Basically, you can put variables like @name into your string, and t() will substitute their sanitized values at translation time. Translators can then rearrange the string as necessary for the language (e.g., in Spanish, it might be “blog de @name”).

Jan 25 2015
Jan 25


Our fourth  multilingual site and significantly more of a challange.  When in the past I had dealt with latin alphabet only, this time I was dealing with Arabic and there were some major differences here. In the Arabic language everything reads right to left. So through simply checking a setting in i18n admin panel you can add the attribute dir="rtl" to the <html>  tag. This conveniently moves all your content to the right side of your page and changes text highlight from this direction as well. This caused quite a few issues mainly with CSS.   Sprites were off on the Arabic version by a few px, but luckily this was easy to fix, as Drupal adds the class i18n-ar to the body tag, so it was easy to target Arabic only views. One other major issue I had was a large left margin of > 1000px when language was set to Arabic, this was fixed by setting body tag to overflow:none;

Translating Fields and Taxonomy

First enable translation on the content type you want to translate.  You can find this  at the bottom  in the  ‘Publishing options’ tab.  There you need to select ‘Enabled with translation’ . After saving  you will see a new tab – ‘Multilingual settings’.  Afterwards select checkbox ‘Set current language as default for new content’ – This makes it easier for editors creating a post if they primarily post in a certain language, it will be set to that language by default without having to manually choose a language.

To translate fields in content type (labels, descriptions etc.) –  enable ‘Field translation’ module. After this we can go to the field in the ‘manage fields’ section.

and click translate tab –

and there you can translate needed title

Replace text

and click ‘Save translation’.

To translate taxonomy terms enable – ‘Taxonomy translation’ module. After this we can go to the vocabulary and edit it.

With this method we can translate terms via the admin panel. If we need different terms for each language – we must choose ‘Translate.  Different terms will be allowed for each language and they can be translated.’ – this method can also be used too in some cases. You must decide before development what method you want to use.
Now we can translate the term in admin section. Go to yoursite.com/admin/config/regional/translate/translate and search term –

now we can see the term in the translation interface.

and translate –

Oct 29 2012
Oct 29

Over here at Drupalize.Me we have been working on transcribing and translating our videos for a few months now. We've also had a number of people step up to help us out with them, and we now have translations beginning to appear. So far, we have Chinese, Croatian, Estonian, Persian, and Spanish versions of a few of our videos. While we are always looking for more folks to join our internal subtitle team, we have also opened up our workflow to the public, so that we can share our work with a wider audience, and let anyone who wants to help ramp up more quickly, without any specific commitment to the amount of time you have. We've now started putting our free videos up on our public page on dotSUB, so everyone can find them, and jump in to help transcribing or translating as they have the time and inclination.

Why would you want to help with this effort? Well, we'd like to help as many people as we can with their Drupal learning curve, and by creating transcripts and subtitles we are opening the world of Drupal to so many more people. Our free videos can be used by anyone around the world, and they are a great resource for local user groups to use at meetups, and for organizations to use for training, or for anyone to use as a way to evangelize Drupal. If you'd like to use these videos for your group or organization but your audience are not native English speakers, having subtitles in your language of choice helps considerably with the Drupal barrier. If there is a free Drupalize.Me video you love and want to be able to share with even more people, it is now easier to help with that process.

You can find all of our free videos available for work on our dotSUB page. Once you get a free account on dotSUB, you can immediately pick a video of your choice and get started. Here is a little more information about how things are set up.


Transcribing is the process of creating an English transcript (and captions) for the videos. If you can understand and write English, you can help with these. English transcripts form the base from which our translations are made, and they are a huge assistance to those that have difficulty listening to or watching the videos. You can watch a dotSUB video that explains how to transcribe videos.

When you go to our dotSUB page you can see which videos have already been transcribed and those that still need some help. If the video listing states that it is "Waiting to be transcribed" then no one has started work yet at all. If it states "Transcription in progress" then that means someone else has started the work, but there is still work that needs to be done to make it complete.

To help with transcriptions, just click on the video to go to the full video page, and then click the "Transcribe Video" link on the sidebar. If that link is not available, then the transcript is likely already complete and published, so it can't be edited any longer.


Things work in very much the same way for translations as they do for transcriptions. You can watch a dotSUB video on how to translate videos.

Once a video has been transcribed, it will state "Transcribed" on our dotSUB page, which means that it is now available for translation.

Once people have started to create translations you will see the listing indicate the number of translations, e.g. "3 Translations." When you go to the full video page you will be able to see the languages that have been started and completed in the "Transcribe and Translate" box in the sidebar. Each language will be listed, along with the percentage completed. You can select the language you want to work on in the "Translate into:" dropdown selector. If you do not see the language you wish to work on listed, it likely means that the translation has already been completed and published, so no further edits are permitted.

We're excited about spreading the Drupal knowledge far and wide. If you have some time to spare and want to help out, we want to make it as easy as possible. We think this is a step in the right direction to make Drupal knowledge more accessible to more people, all over the world.

Apr 08 2011
Apr 08

I wanted to create a node view containing both the original node and its translation, sort of like this neat Meedan.net page. I decided to build this page as a Panels node view template, but to reach the translation(s) I had to write a new CTools relationship plugin that I am sharing here:

// @file mymodule.module/**
* Implementation of hook_ctools_plugin_directory().
* It simply tells panels where to find the .inc files that define various
* args, contexts, content_types.
function mymodule_ctools_plugin_directory($module, $plugin) {
  if (
$module == 'ctools' && !empty($plugin)) {

Place the following file in a plugins/relationships subfolder of your module:

// @file node_translation.inc/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
$plugin = array(
'title' => t('Node translation'),
'keyword' => 'translation',
'description' => t('Creates the translation of a node as a node context.'),
'required context' => new ctools_context_required(t('Node'), 'node'),
'context' => 'ctools_translation_from_node_context',
'settings form' => 'ctools_translation_from_node_settings_form',
'defaults' => array('language' => 'en', 'fallback' => FALSE),
* Return a new context based on an existing context.
function ctools_translation_from_node_context($context, $conf) {
// If unset it wants a generic, unfilled context, which is just NULL.
if (empty($context->data)) {
ctools_context_create_empty('node', NULL);
  }  if (isset(
$context->data->nid)) {
$original = node_load($context->data->nid);
$tnids = translation_node_get_translations($original->tnid);
    if (empty(
$tnids[$conf['language']])) {
$conf['fallback'] ?
ctools_context_create('node', $original) :
ctools_context_create_empty('node', NULL);
$translation = node_load($tnids[$conf['language']]->nid);    // Send it to ctools.
return ctools_context_create('node', $translation);
ctools_translation_from_node_settings_form($conf) {
$form['language'] = array(
'#type' => 'select',
'#title' => t('Language'),
'#options' => locale_language_list(),
'#default_value' => $conf['language'],
$form['fallback'] = array(
'#type' => 'checkbox',
'#title' => t('Fallback to original node'),
'#description' => t('Use original node if desired translation is not found.'),
'#default_value' => $conf['fallback'],

To use this plugin, create a new variant of the Panels node view template. In the Contexts page, add a Node translation relationship for every language that you want to support. You can specify the desired language in the relationship settings. In your Content layout, you will then be able to use those relationships to access the node translations.

To go back to the original Meedan.net example above, we want the English version on the left and the Arabic on the right. To achieve this, I created two node translation relationships, one for English and the other for Arabic. I placed a node content panel in each of my two columns, and set the left panel to refer to the English translation and the right panel to the Arabic translation. Note that I didn't use the original "Node being viewed" content because there would be no way of telling if it's Arabic or English, given that this node template could be accessed via either versions.

What's missing is to replicate the bilingual comments view, and I'll share my solution once I implement it :-)

May 01 2006
May 01

Wheee! Drupal 4.7.0, the new stable release of the CMS, has been released. After more than one year of development, we are now finally able to enjoy all the goodies which this new release brings.

For German speaking people we can now proudly claim to have a completed translation of the user interface, thanks to all the contributors! If you don't speak German, you can choose from one of the other 40+ translations for your site.

Read the release announcement for more information, I'm off upgrading a couple of sites now ;)

Jan 10 2006
Jan 10

Just a quick note: Drupal 4.7.0 beta 3 is available now, fixing more than 100 bugs since the last beta. If you have any further issues or suggestions for 4.7 — now is the time to speak up, file bug reports, post patches etc.

I haven't had too much time for Drupal development recently, but I guess I should really start updating the poormanscron module now (finally!) and help with getting the German translation up-to-date...

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web