To implement a multilingual solution that covers all aspects of a Drupal site takes plenty of modules, configuration, time and knowledge. It can be hard, and sometimes near impossible to provide a robust multilingual solution long after a Drupal site has been architected, implemented and filled with content. The earlier multilingual functionality is planned and architected, the better.
When architecting Drupal projects there is no better place to start then with Drupal core. The purpose of this blog post is to explain what multilingual functionality Drupal 7 core comes packed with and outline its limitations and configurations.
Out of the box Drupal 7 can handle multiple site languages and multilingual content. However, Drupal 7 core multilingual functionality is a bit limited. The only objects that can be translated are content (nodes) and interface translations (strings wrapped in the t() function). For very basic sites this may be all that is needed, but for anything more robust additional modules are going to be required for a complete multilingual solution.
The two modules included in Drupal 7 core that handle multilingual functionality are the locale and content translation modules. The locale module is used for setting up site languages and configuring language detection. The content translation module provides multilingual support for nodes and translatable strings. To provide multilingual functionality for a core Drupal 7 site, both of these modules should be enabled. The content translation module actually requires that the locale module be enabled. Configuration for these modules can be accessed from admin > configure > Regional & Language.
Configuring Site Languages
The first thing to do in providing multilingual functionality for a Drupal 7 site is to setup multiple languages. The locale module provides an easy and intuitive way to setup additional languages. If a site has only a single language enabled then the functionality provided by the locale module will never be noticed. Enabling multiple languages will provide a core site with additional functionality such as allowing users to select their preferred language, allowing content authors to select the language for the content they create and providing the ability to translate interface text.
Initially the only language that will be enabled will be the sites default language, which for Drupal 7 is English. Each enabled language has a name, RFC 4646 designated language code, text direction (which can be passed as an HTML attribute to themes) and detection settings.
Adding additional languages to a Drupal 7 site is a very simple process, by clicking on the ‘+Add language’ button. Drupal comes packaged with support for 185 languages. To enable one of these languages, just simply select it from the provided drop down and click the ‘Add language’ button.
Any languages not supported (say for example Klingon), can be added by expanding the ‘custom language’ fieldset. When creating a custom language the language code, english name, native language name, text direction (either ‘left to right’ or ‘right to left’) and a path prefix or domain will need to be provided.
It is important to note that both a path prefix and domain cannot be set at the same time. The one that should be set depends on the configured language detection settings (more on this later).
After enabling multiple languages for a site, any one of them can be set as the default language. For some modules the order of the languages matters, it is always best practice to make sure the language that is set as the default is placed at the top.
After setting up multiple languages, it is important to configure how Drupal detects which language to use. This is done from the ‘Detection and Selection’ page of the Languages administrative section. This page displays a number of methods that Drupal can use to detect languages. A top down method of importance is followed for the enabled methods.
For example, in the above screenshot Drupal would first check the url to determine the language. If a language was not detected from the URL, then Drupal would use the default language (it is the only other method enabled). The most common method to use for language detection is by URL. When configuring this method, Drupal provides two choice.
Path prefix: If this method is chosen then Drupal will look at a path prefix to determine which language to use (if no language is present it will use the site default). As an example the default url “http://www.example.com/contact” would serve up the default language content while the url “http://www.example.com/klingon/contact” would serve the page using the Klingon language.
Domain: If this method is chosen, then Drupal will look at domain prefixes to determine which language to use (if no language is present it will use the site default). For example the domain “http://tlh.example.com/contact” would serve the page using the Klingon language.
Whichever one is selected, it is important that the site languages have the same configuration (either have a path prefix or language domain provided). It is important to note that changing the url detection method on an existing production site can be dangerous as it may break existing incoming urls. For any links or urls generated using the l() and url() functions, drupal will use these settings to generate the url for the current site language.
The locale module provides a “Language Switcher” block which can be placed on a site to provide users with a list of available languages to view the site. The language switcher block will only display if there are at least 2 enabled languages and either the URL or Session language detection method is enabled. The block displays a list of all enabled languages, and when a user clicks on a language, they will be redirected to that languages version of the current page they are on (and remain in that language version of the site)
The translate interface, provided by the content translation module provides the ability to set translated values for all strings that are wrapped in the t() function. This includes a majority of the strings provided by Drupal core and most contributed modules. The translate interface has a few administrative sections.
The overview page provides a table of all of the enabled languages on a Drupal site. Listed next to each language is the percentage of how many translatable strings have translations provided.
The translate page of the translation interface, displays a table of all of the strings that are available for translation, that is, all of the strings that have been discovered by the t() function. As this table can grow quite large, it is possible to search for specific strings (based on the original string value) and filter based on language and text group. It is important to note that new strings (provided by other modules) may not show up as translatable until they have been viewed in another language, and cron has run.
For each listed string in the table there is a languages column. If a language code is striked through, that means a translation for that string has yet to be set by that language. To provide a translation for a string, click on the ‘edit’ operation to load the string edit form.
The string edit form displays the original string value and a text area for each enabled language. In each text area, a translated value can be provided for the string. It is important to note that some strings may contain variables used by the t() function, these variables will start with either a !, % or @. Make sure not to translate these variables or they will not be replaced with their actual values. See the documentation on the t() function for more information.
Bulk String Translation
Bulk string translations can be provided by uploading individual Gettext Portable Object (.po) files for a language from the Translate Interface Import page. This page provides a simple form that allows for uploading a .po file, selecting which language it is for and how to apply the changes. Translations provided by a .po file can be used to either replace all existing translations for that language, or provide new string translations.
Thanks to the work of the Drupal community .po files can be found for all of the languages packaged with Drupal core. For more information visit https://localize.drupal.org/
The Translate Interface also provides the ability to export all of the string translations for a language from the Export page. This page displays a simple form for selecting which language to export and what type of file to generate. Either a .po or a .pot file can be generated. The difference between these two file formats is that a .po file will contain the original and translated values of strings and a .pot file will only export the original values of strings.
Before nodes can be translated by the content translation module, the content type needs to be configured to support multilingual functionality. Multilingual support for a content type can be configured from the content type edit form (located at administration > structure > content types). The Multilingual support options for a content type are located in the Publishing Options vertical tab.
A content type can be configured to support multilingual functionality one of three ways; Disabled, Enabled, Enabled with translation. Depending on the needs of the Drupal site and content type the right multilingual support option should be selected.
If the multilingual support for a content type is set to disabled, then that content type will not have an support for multilingual functionality. All nodes that are created of that content type will have their language automatically set to the site default language.
If the multilingual support for a content type is set to enabled, then the language for a node of this type can be set. On the node edit form a language select field will display, with a list of the enabled site languages to choose from.
Enabled, with translation
If the multilingual support for a content type is set to Enabled, with translation then a node can be saved in multiple languages. This is the most useful setting for out of the box content translation as it is the only option that allows node translations. Node translations are managed by the ‘translate’ tab that becomes available with this setting.
The translate tab displays a list of the site languages, and the status of the node in each language. To provide a translated version of a node, click on the ‘add translation’ operation for a language. It is important to note that when, providing a translation for a node what Drupal is actually doing is creating a new node. The translated nodes are mapped together, but each one is its own independent node (with it’s own nid and path).
The node mappings provide a seamless transition between the translated nodes when a user changes their site language.
Putting it all together
The multilingual functionality offered by Drupal 7 out of the box may be limited, but it provides the building blocks for creating a robust multilingual site experience. With the use of just two module (locale and content translation), alternate site languages can be configured and properly detected and the bulk of a sites content (nodes and interface strings) can be translated.
Each new Drupal release has made creating a multilingual site easier and more flexible. Drupal 7 has provided some great improvements for multilingual over Drupal 6, and it will be even easier in Drupal 8 thanks to the Drupal 8 Multilingual Initiative.