How Drupal Does Multilingual

Error message

The spam filter installed on this site is currently unavailable. Per site policy, we are unable to accept new submissions until that problem is resolved. Please try resubmitting the form in a couple of minutes.

So your company has an awesome Drupal site. Now, the company is expanding overseas and you need identical sites in Spanish, German, and Italian. Thankfully, Drupal makes supporting multiple languages on a single site easy. Instead of having one site for every language, you can have a single site that supports all languages and intelligently supports switching between them.

Translating your content

Drupal actually supports two different approaches to translating content: content translation and field translation.

Content Translation

As of Drupal 7, this module is included in core. Essentially, the approach taken by this module involves creating a copy of each piece of content for each language (creating a separate node in Drupal terms) and trying to keep shared, untranslated fields (such as images) in sync. While there are use cases where this approach is better, I've found that most of the time it just makes things more difficult for everyone involved.

Entity Translation (translation at the field level)

The alternative to Content Translation is Entity Translation. With Entity Translation, the translation is handled at the field level so instead of creating an entirely new node, individual fields are translated but still associated with the original node. This functionality is not in core for Drupal 7 but the module that enables it (Entity Translation) is maintained by the Drupal core internationalization team. In Drupal 8, the default method of handling translations is very similar to the Entity Translation module.

How do I choose?

While there are some use cases where the Content Translation approach of having separate nodes makes sense (for example if you have comments enabled and want each language to have a separate comments section), for most routine tasks Entity Translation is a better approach and that's what this tutorial will be focusing on. Thankfully, if you do need to use Content Translation for something it is possible to configure multilingual support separately for each content type so it is possible to mix and match translation methods.

Translating your content fields

Now that we've established that field translation is the way to go, the next question is "how do I actually use it?"

  1. Start by downloading the "Title", "Internationalization" and "Entity Translation" projects and their dependencies then enabling the following modules:
    • Entity Translation
    • Menu Translation
    • Block Languages
    • String Translation
    • Field Translation
    • Title
  2. Login to the site as an administrator, visit /admin/config/regional/language and add one or more languages.
    • OPTIONAL: download and install corresponding translations from https://localize.drupal.org/translate or use the "Localization update" module to do it automatically. This will provide translations for many of the user interface strings from Drupal core. Translations are also available for many contributed modules and if you are using "Localization Update" these can be downloaded and installed automatically if they are available. If you choose not to use "Localization Update", you can still search for the contributed module translations on localize.drupal.org and install them manually.
  3. Return to the language config section and click on the "Detection and Selection" tab (admin/config/regional/language/configure). Under "User interface text language detection" and "Content language detection", choose one or more methods of determining how Drupal will determine which language to use. You can drag them to re-order and some have additional configuration options.

Once you have that configured, you will need to enable translation for each field that you want to be able to translate. Once Entity Translation has been enabled, a new "Enable translation" link will be available at the bottom of the field settings form for every field. Clicking that will enable translation for all instances of that field.

One challenge to this approach is that it doesn't allow node titles to be translated. The Drupal core i18n team addressed this with the "Title" module (http://www.drupal.org/project/title) which replaces node titles with a field. This allows them to be translated just like any other field.

Once you have everything configured and have enabled translations for some fields, you're ready to start adding translations. The first thing that needs to happen is the content must have a language associated with it. If you enabled the multilingual features on an existing site that already had content, the existing content will show up as "Language neutral" and must be edited to change the language before it can be translated. When adding or editing content, there will be a "Language" dropdown that lists all enabled languages. You should select the language that the content is in and save.

Once you save the node, there should be a new "Translate" tab at the top of the page beside "View" and "Edit".

Clicking on that tab will bring up a page that will let you manage the translations for that node.

If you click "add" to create a new translation, you will be presented with an edit form pre-populated with values from the original content. One important thing to notice here is that some fields have "(all languages)" beside their name. These fields are have not been enabled for translation and instead, the value will be shared across all languages. Aside from that, adding or updating a translation is as simple as updating a node.

But my menus are still in English!

So, now you've translated all of your content but your menus are still in English. The "Menu translation" module, which is included with the Internationalization module will let you translate your menu items. After the module is installed you can enable translation for a menu by editing the menu and setting the "Translation mode" to "Translate and Localize".

Once translation is enabled, you actually have a couple options for translating menu items.

Option #1: just translate the text

If you navigate to the admin page for the menu that lists the links, you will see a new "translate" operation beside "edit" and "delete". If you just want to translate the text of the menu item and don't need anything else to change, you can just leave the language of the menu item as "language neutral" and click the "translate" link.

Once you click on that, you will be taken to another page which lists all of the translations for the menu item. As you might guess, clicking the "translate" link for a language will take you to a page where you can add translation for the text of the menu item (if you've already translated the item into a language, the link will say "edit" instead")

Once you enter the translation and save it, you're done.

Option #2: create a whole new menu item

If you need to do more than just translate the text (eg you want to have a different order for items in each language), you can edit the original item and set a language. Once that's done, you can go back to the list and click on the "translate" link as before. You will still be taken to a list of translations like option #1 but this page will be a bit different. Click the "add translation" link for a language to translate the item.

That will take you to a page where you can edit all of the properties of the menu item. Anything you change here will only apply to the language you selected. Once you've edited everything to your satisfaction, save the item and you're done.

Translating your blocks

Now that you've translated your content and menus, what about the blocks that you've created? That's where the "Block languages" (included with the Internationalization module) comes into play. Once enabled, it adds a "Language" section to the block settings. To enable translation for the block, check the "Make this block translatable" box in this section.

Once that is checked, a new "Save and translate" button will appear. Click that to be taken to a page that shows the available languages and translations. From there click the translate link for the language you want to add a translation for.

Enter the translations for the title and body in the fields and click the save. That's it! You've just translated a block.

Everything else

You've translated your content, your menus, and your blocks. Odds are there are still some things left that aren't translated. How do you translate all of the bits and pieces that aren't covered by one of the previous modules? That's where interface translation comes in.

There are two important modules that help with interface translation:

  • String Translation: exposes user-defined strings to Drupal's core Locale module to be translated.
  • Field Translation: allows you to translate various field properties (eg labels, help text, etc).

All translatable user interface strings (such as text from a module that was passed through the t() function) can be found Admin > Config >Translated Interface > Translate (/admin/config/regional/translate/translate). If you installed translations from Drupal.org earlier, much of your work here will already be done and you will only need to supply translations for strings that weren't included in the translations.

From that page, you can search all of the strings that can be translated. When you find one that you want to translate, click on the "Edit" button beside it.

That will take you to a page with text fields for each available language where you can add translations for the string. If there is already a translation for the string, the field will be pre filled but you can still edit it to change the translation.

Typically, Drupal does not know about translatable strings until the first time they are used (ie someone visits a page there the string is being used). If you have String Translation enabled, you can speed things up a little. There will be a "Strings" tab within the Interface Translation section of the admin area:

Clicking on that will take you to a page where you can refresh the list of translatable strings (any existing translations will be preserved.

What about Webforms?

If you're using webforms on your multilingual site, then you need the Webform Localization module. Once you enabled that, you will have several new options on the form settings - "localization by string translation" and "localization by sync".

If you are using the "content translation" method, you will have a separate webform for each translated node. "Localization by sync" will attempt to keep various properties synced between all of the webforms on all of the nodes in a translation set.

Since this tutorial covers the "field translation" method, the only setting that you need to worry about if you're using that is under "localization by string translation". Enabling the "Expose webform component strings suitable for translation." option will allow you to expose the field labels for translation view the interface translation system (see the "Everything else" section).

The downside to this approach is that all of the submissions will go the same place regardless of language. If you need to have webform submissions for different languages handled separately (eg sent to different email addresses), that is one of the cases where "content translation" might be a better option.

But I want to use field translation AND have forms that users can submit!

There is an alternative to the Webform module that can help with that: Entityform. The Entityform module provides user-submittable forms similar to Webform but it uses new features introduced in Drupal 7 to make form submissions fieldable entities. This tutorial won't get into all the implications of that but among other things, it means that things that were previously handled by the webform module can now be handled by popular contrib modules (such as using Views to display results or Rules for email notifications).

So what does this mean for a multilingual site? First, you will have to translate the field labels and the various other pieces of text via the interface translation system just like you would if you used Webform with field translation. Second, since the submissions are entities, they have a "language" property that can be used to specify what language is being used. While Entityform doesn't do this "out of the box", all it takes is a few lines of code to set the language of the entity that is created to the active language (and so a little sanity checking in the process):

<?php
 
function mymodule_custom_entity_presave($entity, $type) {
    if(
$type == 'entityform') {
     
$lang_code = check_plain($GLOBALS['language']->language);
     
// Check the language code against the list of enabled languages.
     
$installed_languages = language_list('enabled');
      if(
in_array($lang_code, array_keys($installed_languages[1]))) {
       
$entity->language = $lang_code;
      }
    }
  }
 
?>

Once you have a language associated with the submission, you can filter the submissions view by language, add conditions to the notification rules based on language, etc.

Speaking of views…

These days, views is pretty smart about languages out of the box. If the Locale module is enabled, views can automatically select a translation to use when displaying a field. Under the "Advanced" settings on the edit form for a view, there is a "Field Language" option under the "Other" heading.

By default, this is set to "Current user's language" which will automatically choose the appropriate translation when available based on the language the user is currently using. If necessary, this can also be used to force Views to use a specific translation for fields.

Views also integrates nicely with the interface translation system and can automatically expose much of the text entered on the view configuration form for translation. This includes field labels, rewritten text, and even the contents of "Custom text" fields.