eZ Platform offers the ability to create multiple language versions (translations) of a Content item. Translations are created per version of the item, so each version of the content can have a different set of translations.
A version always has at least one translation which by default is the initial/main translation. Further versions can be added, but only for languages that have previously been added to the global translation list, that is a list of all languages available in the system. The maximum number of languages in the system is 64.
Different translations of the same Content item can be edited separately. This means that different users can work on translations into different languages at the same time.
Adding available languages¶
The multilanguage system operates based on a global translation list that contains all languages available in the installation. Languages can be added to this list from the Admin Panel in the Back Office. After adding a language be sure to dump all assets to the file system:
The new language must then be added to the SiteAccess configuration. Once this is done, any user with proper permissions can create Content item versions in these languages in the user interface.
Translatable and untranslatable Fields¶
Language versions consist of translated values of the Content item's Fields. In the Content Type definition every Field is set to be Translatable or not.
eZ Platform does not decide by itself which Fields can be translated and which cannot. For some Field values the need for a translation can be obvious, for example for the body of an article. In other cases, for instance images without text, integer numbers or e-mail addresses, translation is usually unnecessary. Despite that, eZ Platform gives you the possibility to mark any Field as translatable regardless of its Field Type. It is only your decision to exclude the translation possibility for those Fields where it makes no sense.
When a Field is not flagged as Translatable, its value will be copied from the initial/main translation when a new language version is created. This copied value cannot be modified. When a Field is Translatable, you will have to enter its value in a new language version manually.
For example, let's say that you need to store information about marathon contestants and their results. You build a "contestant" Content Type using the following Fields: name, photo, age, nationality, finish time. Allowing the translation of anything other than nationality would be pointless, since the values stored by the other Fields are the same regardless of the language used to describe the contestant. In other words, the name, photo, age and finish time would be the same in, for example, both English and Norwegian.
You can control whether a User or User group is able to translate content or not. You do this by adding a Language Limitation to Policies that allow creating or editing content. This limitation enables you to define which Role can work with which languages in the system. (For more information of the permissions system, see Permissions.)
In addition, you can also control the access to the global translation list by using the Content/Translations Policy. This Policy allows users to add and remove languages from the global translation list.
Exposing translations to the user¶
Once more than one language is defined in the global translation list and there is content in different languages, the question is how can this be exposed to use by the visitor. There are two ways to do this:
- Implement a mechanism called language switcher. It lets you create links to switch between different translations of a Content item.
- If you want to have completely separate versions of the website, each with content in its own language, you can use SiteAccesses. In this case, depending on the URI used to access the website, a different site will open, with a language set in configuration settings. All Content items will then be displayed in this language.
When viewing a Content item, it may be useful to let the user switch from one translation to another, more appropriate to them. This is precisely the goal of the language switcher.
The language switcher relies on the Cross-SiteAccess linking feature to generate links to the Content item's translation, and on RouteReference feature.
In a template¶
To generate a language switch link, you need to generate the
RouteReference, with the
language parameter. This can easily be done with the
ez_route() Twig function:
1 2 3 4 5
You can also omit the route, in this case, the current route will be used (i.e. switch the current page):
1 2 3 4 5
When using sub-requests, you lose the context of the master request (e.g. current route, current location, etc.). This is because sub-requests can be displayed separately, with ESI.
If you want to render language switch links in a sub-request with a correct
RouteReference, you must pass it as an argument to your sub-controller from the master request.
1 2 3 4 5 6 7 8 9 10 11 12
1 2 3 4 5 6 7 8 9
ezpublish.translationSiteAccess( language )returns the SiteAccess name for provided language (or
nullif it cannot be found)
ezpublish.availableLanguages()returns the list of available languages.
You can generate language switch links from PHP too, with the
1 2 3 4 5
You can also retrieve all available languages with the
1 2 3
Using SiteAccesses for handling translations¶
Another way of using multiple languages is setting up a separate SiteAccess for each language. For more details, see Multi-language SiteAccess.
Explicit translation SiteAccesses¶
Configuration is not mandatory, but can help to distinguish which SiteAccesses can be considered translation SiteAccesses.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
The top prioritized language is always used the SiteAccess language reference (e.g.
fre SiteAccess in the example above).
If several translation SiteAccesses share the same language reference, the first declared SiteAccess always applies.
Custom locale configuration¶
If you need to use a custom locale, you can configure it in
ezplatform.yml, adding it to the conversion map:
1 2 3 4 5
A locale conversion map example can be found in the
core bundle, on
More complex translation setup¶
There are some cases where your SiteAccesses share settings (repository, content settings, etc.), but you don't want all of them to share the same
translation_siteaccesses setting. This can be for example the case when you use separate SiteAccesses for mobile versions of a website.
The solution is defining new groups:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
Using implicit related SiteAccesses¶
translation_siteaccesses setting is not provided, implicit related SiteAccesses will be used instead. SiteAccesses are considered related if they share:
- The same repository
- The same root
Fallback languages and missing translations¶
When setting up SiteAccesses with different language versions, you can specify a list of preset languages for each SiteAccess. When this SiteAccess is used, the system will go through this list. If a Content item is unavailable in the first (prioritized) language, it will attempt to use the next language in the list, and so on. Thanks to this you can have a fallback in case of a lacking translation.
You can also assign a Default content availability flag to Content Types (available in the Admin Panel). When this flag is assigned, Content items of this type will be available even when they do not have a language version in any of the languages configured for the current SiteAccess.
Note that if a language is not provided in the list of prioritized languages and it is not the Content item's first language, the URL alias for this content in this language will not be generated.