Drupal 7's new multilingual systems (part 1) - The basics

This is part one in a series of posts on the new multilingual features in Drupal 7 core and contrib. I was sadly not as involved in the core mutilingual work that I wanted to (was busy working on localize.drupal.org), so I need a refresher myself on some of the finer details of what is going on. Therefore my journey through the new features, which I thought would be useful for you dear readers too. Thankfully many bright folks picked up the work and drove a good bunch of new functionality in terms of multilingual support into the new version. Let's begin!

New regional settings

Even before you enable any multilingual features, Drupal 7 comes with a new Regional settings configuration pane under Administration » Configuration » Regional and language. First day of week moved here from Date and time settings. You now have the ability to set a default country. This will not do much in itself, but contributed modules can build on the functionality. The time zone is now also set here and there were very heroic concentrated efforts to make this more intelligent. Previously if you set a timezone, you needed to revisit it twice a year when daylight savings time kicked in or was over. Instead of merely storing a time offset, Drupal 7 now stores the name of the timezone which is then used with PHP 5.2+ DateTime objects to calculate the right timezone offset at any given time. It all works like magic now.

Language support

To add language support to Drupal, you still need to enable the Locale module, like in previous versions. While Drupal core itself has language handling baked in at multiple levels, the locale module provides a user interface on top of basic language configuration with the assumption that if you need multilingual support, you probably need translated interfaces as well.

Once you enable locale module, the items Languages and Translate interface show up under Administration » Configuration » Regional and language. The role of the former is to let you configure your languages and which one should Drupal pick in given scenarios. The role of the later is to let you manage your interface translations (much more coming on that in part 2).

Let's look at language configuration first. On the outset, it looks like nothing changed from Drupal 6. You can still set up any number of languages to be supported by your site with one being the default. Out of the box, English is this default language. Languages can have native names, language codes, path prefixes and custom language domains set up. There is a similar list of built-in languages to choose from like in Drupal 6, which let you add new languages fast.

The big change here hides under the Detection and selection tab. While Drupal 6 has a fixed selection of pre-baked combinations of options to choose from in terms of how Drupal should decide on the language used, Drupal 7 totally modularized this and offers you with finer grained control in terms of which decision methods to use in which configurations, and you can even set the order of them! No more debating in issue queues over how inapplicable certain methods are to your use case, you can build your own puzzle here. The interface language can be determined based on URL information (path, domain), session data, user setting, browser preference or can fall back on the default. Contributed modules can extend on this list and implement other ways to detect language even. One can easily imagine a module providing a specific language based on your source IP (like Google does).

Interface translation changes

The interface translation features again did not change much on the outset. However, the translation user interface got some usability attention, so now it looks much more like other filter & action screens (like users, content, logs and so on). You get several filters on the top of the page that you can use and the results show underneath. Drupal 6 had an incosistent user interface approach here that is finally done away with.

The translation table highlights another subtle looking but possibly huge new feature to Drupal 7's localization system. String context support for translation. What does that mean? Well, think of the word view. What does that mean? Is it a noun? Is it a verb? Even if it is a noun, does it have one fixed meaning? Consider these uses of view:

View this piece of content.

Set up a new view with views.

You have such a nice view from this window!

I just set up a database view to speed this query up.

While Drupal could easily end up needing to translate view as a standalone word applicable to either of these situations, there was no way before to tell Drupal which situation should apply. Now in Drupal 7, a standard way to provide this was added called contexts.

Drupal core only comes with two contexts by default Font weight which is applied to Strong and Long month name which is applied to May. Again, you can imagine the words "strong" and "May" have varying meanings depending on context, and telling translators that they are used as font weight or long month name makes it possible to provide the right translation.

Unfortunately we did not define guidelines for contexts yet, given we are still into figuring out how best to use them. Several contributed modules started to use them in incosistent ways, and I'd expect the names of the contexts to still evolve and be set with discussion between translators and module maintainers. As the examples hopefully shown, contexts are not to be used to have per-module translatability for strings, but rather to have per-meaning translatability.

Best practices of using community interface translation

Drupal 7 still builds on the well proven Gettext .po format (which also includes support for the above mentioned contexts), but how you get them changed in the past year or so. That is not just a Drupal 7 change, it also applies to older Drupal versions, but you are most probably faced with this change now. Part 2 of my series will continue by covering this topic.

What timezone you set makes dates show up in the timezone on the frontend by default. What language is choosen for display affects the pages shown to the user. Interface translation still makes no difference between frontend and backend. Eg, if the string "Save" shows up, it will be translated the same on the front and backend.

On i18n module, yes, you'll still need that module or some other module replacing its functionality. Yes, there seems to be a diversity of modules possibly setting in but i18n is in active development. I'll get to these topics later on in the series, planning to focus on interface localization first (because this is much more solidified) and then move over to content/structure translation.

Well, currently this information is exposed as part of the available filters for translation. When you become a member of a translation team, new tabs titled "Translate", "Import", "Export" will show up on team pages, and lead to paths like http://localize.drupal.org/translate/languages/hu/translate. There among the many filters, you'll find a dropdown with all contexts used in all contributed modules so far (like the list pictured in the blog post above).

It would indeed make a lot of sense to expose this information in some kind of "catalog" so contributed module maintainers could look up existing contexts and reuse them as appropriate. I've submitted a feature request for this at http://drupal.org/node/1034882

Thanks a lot Gábor for your excellent review and for the great work you are doing.
It was really helpful when I tried to summarize the new multilingual features available in Drupal 7 core and contributed modules in my presentation at the recent DrupalCamp Kyiv 2011.

detection and selection works fine. Too fine in my case! There is no fallback to default language when all options on detection and selection are enabled (User/Url/Session/Browser/Default). if there is no translation of a node in the default langauge, the node in default language stays invisible to users or browsers in other than the default language ... I cannot find the trick to something like fallback option as it were in drupal 6. That shows both translated nodes, and if not translated the default nodes, with a pemanent UI langauge due to the user/browser selection ...