Great news Drupalists! Fresh for 2013 is the new 1.0 version of the Entity module. That means we're on stable ground to build our entity-based sites that allow us to translate anything in Drupal. To celebrate the 1.0 milestone, we're finalizing and documenting our build recipe that we use to build multilingual sites.
entity and entity_token
i18n and i18n_menu
First enable the locale and the l10n_update modules. I put the l10n_update in there because I like to see the translated Drupal strings in all their glory.
Go to Configuration > Languages
Enable your second, third, or more additional languages. Drupal will fetch the strings for each language for the modules that you have installed using the l10n_update module.
Edit the English language, add a prefix "en". This will help us deal with English when we setup language negotiation.
Go to Configuration > Languages > Detection and Selection.
Enable path translation, and put it at the top. Then I would enable the browser setting as a fallback. This means that if a user with a French web browser comes to our site, we will give them FR content, unless they explicitly put a different language in the path. For this reason we don't need to worry about what "default" language the site has - the site will always default to the user's default.
Ok. We have languages and a way to manage which one we're using. Now we need an interface to do that.
Go to Structure > Blocks.
Enable the "Language switcher (user interface)" block. Put it somewhere you can get at easily so we can do some testing with it. If you need to change the text name for the language that appears in this block, you can go back to the Config > Languages page and update the title there.
At this point you've configured Drupal to do multiple languages, negotiate between them, and you have an interface to do that as a user. Additionally, Drupal translated itself by fetching all the strings from drupal.org for each module you have installed. As you add more modules, l10n_update will continue to pull down new updates to the text. So to your translators, Drupal will provide service in all the languages that you support. Handy.
Translating Content with Entity Translation
Enabling Entity Translation
Go to Structure > Content Types > Edit the type you want
Publication options: Enabled, with field translation.
Then go to Structure > Content Types > Manage fields for the type you enabled above
Edit the body field, scroll to the bottom, and check the box to enable translation. Repeat this step for every field that you wish to translate. Leave it unchecked if you wish to have the content synchronize all versions.
For the title field, get the
title module. Enable it, then go to Structure > Content Types > Manage fields
Then choose the "replace" option for the title field. This will create a new field_title that behaves the same way as the traditional field, but with multilingual features. Edit this field. Remove the description text. Save.
Entity now fully supports revisions. Each update to a translation creates a new revision to the host node.
Rollbacks of versions are not separated by language, so if you must roll back, do it before someone adds new content in a different language. Rolling back will affect all languages that have been updated between the revisions.
Making Menus Entity Translatable
Entities can now have translatable menus. You can structure your entity-based menus two different ways. The entity_translation_menus module takes care of setting up a different menu entry for each version of a page. That is awesome. How you structure the menus are therefor up to you.
- Create one menu that has all the language versions grouped together, or...
- Create a copy of the menu for each version of the language, and allow editors to put the entry in any of those trees when they select where it goes
With the first strategy, if you go to Structure > Menus > Main Menu > List links you will see all the pages at once, but only on this page and when the editor puts something into the site (if you have big menus this could quickly become a big jumbly multi-language mess).
The second method means that when the user selects where they want to put the content into the menu, they must first find the right language menu and put it within the same language part of the site. In other words, the drop-down menu that lets you pick where the menu entry will be, is grouped by language.
This one is a workflow/editorial question I would consider depending on the size of the site and how many languages are being supported. In any case, the decision doesn't matter because you have only one option to configure:
Structure > Menu > Edit menu > Translate and localize (even if you are using it as fixed language)
Then, when you edit... remember to check off "Menu link enabled only for the English language" when you do the original version of the post. It would be really nice if that was set to be the default somehow, but I have not found any settings for this yet.
Entity Translated Paths
By default the pathauto module will do most of what you need here. It will generate aliases for each language version of a node. You can also enable the entity_tokens module to give yourself some additional translated tokens if you need to create some more complex URLs.
Since we are dealing with a multilingual site here, there is one additional module I have to tell you about: transliteration.
This module converts non-ascii characters to ascii for the URL. So rather than "catégories" becoming "cat_gories" we get "categories" as you would more logically expect.
Enable the transliteration module, then:
Configuration > URL aliases > Transliterate prior to creating alias. Done.
This applies more to specific field configurations, but it is likely something you are going to have to take a look at. If you go to the following configuration page you will find your options:
Configuration > Date and Time > Localize
You can also change the first day of the week in the site to change how calendars will be displayed. You can do that at Configuration > Regional Settings.
Use the i18n_blocks module. When you create a new block, you will need to specify what language it is. Usually you will want to create blocks with a fixed language, as otherwise you will need to search for the block content as a string. So far we've managed to stay away from Drupal's built-in translation engine, and I like that, because we should only really need to use it to translate strings in Drupal's interface.
Blocks are not the greatest with translations but they do the job. In some cases, it might be easier to just create a new content type and display the translated data with a View.