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.
Translators can check the existing contexts used by all drupal.org projects on localize.drupal.org (some of which look pretty broken, see screenshot on the side). Drupal.org issues should be tagged with string context when discussing string context issues for easy identification.
Not all APIs support contexts consistently. Menu items and strings used in Javascript will not support contexts in Drupal 7. Also, we did not step forward in supporting plural versions of strings in watchdog entries even (let alone context support for them).
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.
very useful
thanks, this is a very much needed article, keep them coming. It would be nice to learn about recommended/required contrib modules.
hajrá Gábor!
How does it relate to i18n?
Hi Gabor,
Thnx very much! This is a much appreciated blog post, and I'm really looking forward to the next parts!
Two questions though:
Anyway, thanks mate, and keep up the good work!
frontend, i18n
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.
Thanks!
Thanks Gabor
for writing your Drupal 7 multilingual experiences down, much appreciated! That's exactly what I was looking for. Expect some follow-up questions as I start trying this out.
How the strings translation
How the strings translation implemented in D7?
In D6, strings translation to other language is based on source language (default language), if default language changed, all translated strings will break.
not changed fundamentally
Drupal still expects you can decide on the default language up front, the translations are still based on default language.
Thanks for a great starter tutorial
Hi Gábor,
Thanks for a great starter tutorial. I'm looking forward to reading the rest of it as this is something I am investigating for a client at the moment.
Thanks,
Dave
Great article, thank you
Great article, thank you Gabor! Will part 2 also cover how to create multilingual blocks?
yes, but not part 2
Yes, that is coming in a later piece (multilingual blocks are still a bit in flux), I hope to build this article series out to be more detailed instead of jumping right away to blocks :)
How to discover contexts for t()
You say
but I can't figure out where that information is. Can you give me the step-by-step to find contexts?
Contexts sound like a great step forward... But I understand from your article we aren't through taking that step ;-)
team members can look that up
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!
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.
fallback - language negotiation
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 ...
hi
hi
I made this for bengali, all is ok, but problem is with date, count etc. That mean every kind of numerical system. What is the solution