Translations and languages
This page is for developers who build a site in more than one language. In Exponential a translation is not a copy of a page: it is another language of the same object, so relations, locations, permissions and the tree are shared by every language, and only the texts differ.
Contents
- Two kinds of language
- Translations belong to the object
- Which fields are translated
- Which language a visitor sees
- Always available objects
- One siteaccess per language
- Template strings
- Translations from code
- Caches after language changes
Two kinds of language
| Content language | Interface language | |
|---|---|---|
| What | the language objects are written in | the texts of templates and the administration |
| Stored | in the database, per object | in .ts translation files (share/translations/<locale>/, an extension's translations/) |
| Chosen by | site.ini [RegionalSettings] SiteLanguageList[] of the siteaccess | [RegionalSettings] Locale of the siteaccess |
They are independent: a siteaccess can show German content with an English interface (Content languages, section 1).
Translations belong to the object
Content languages are added on Setup > Languages before anyone translates into them. Each language is one bit in a mask (2 for the first, 4 for the second and so on), and every object records its languages in its own mask, so "objects in German" is one bit test on any database. Each object has a main language, the one it was created in, which cannot be removed while it is the main one. How the storage works and the limit of 62 languages: Content languages, section 2.
Because all translations are versions of one object, publishing a German translation creates a new version of the object, and the English text in that version is unchanged (Versions, drafts and publishing).
Which fields are translated
Each class attribute has a translatable flag (can_translate). Untick it for values that must be equal in every
language: dates, prices, e-mail addresses, images that contain no text, relations to shared objects. Translators then
see the value of the main language and cannot change it per language. Classes have translatable names and
descriptions too, which editors see in the create menu (Content classes and attributes).
Which language a visitor sees
Per siteaccess, in settings/siteaccess/<name>/site.ini.append.php:
[RegionalSettings]
Locale=ger-DE
ContentObjectLocale=ger-DE
SiteLanguageList[]
SiteLanguageList[]=ger-DE
SiteLanguageList[]=eng-US
ShowUntranslatedObjects=disabled
TextTranslation=enabledAn object is shown in the first language of SiteLanguageList[] it has. With ShowUntranslatedObjects=disabled (the
shipped value) objects in none of the listed languages are hidden, unless they are always available. The empty
SiteLanguageList[] line clears what other files set. Every setting:
Content languages, section 5.
Fetches follow the same rules, so a German list shows German titles, falls back to English, and leaves out what has
neither. The list fetch has language and only_translated parameters for lists that must differ
(Fetching content in templates).
Always available objects
Always available is a flag per object (bit 0 of its mask): such an object is shown in its main language where no
listed language exists. Folders, users, user groups and media are usually always available, so a German site still
finds the image folder and the author of an article. A class sets the default for new objects (always_available)
(Content languages, section 6).
One siteaccess per language
A multi-language site usually has one public siteaccess per language, matched by a URL element (/de/) or a host
name, sharing one database and listed in [SiteAccessSettings] RelatedSiteAccessList[]. Each language has its own
URL aliases for the same node (URL aliases and routing). For links between the language
versions of a page, [RegionalSettings] TranslationSA[] names the translation siteaccesses, and the template operator
language_switcher with the module switchlanguage/to builds the links. Setup in the installation book:
10.14 Multi-language sites, and
Siteaccesses and multisite.
Template strings
Fixed texts in your templates are translated with the i18n operator and a context:
<a href='/content/search'|ezurl>'Search'|i18n( 'extension/exp_mysite' )</a>The translations live in your extension's translations/<locale>/translation.ts, and the extension is listed in
site.ini [RegionalSettings] TranslationExtensions[]
(Translating template strings,
Translations in an extension).
Translations from code
eZContentFunctions::updateAndPublishObject() takes a language parameter, so an import adds a translation to an
existing object instead of creating a second object. Import the main language first, then each translation to the same
object, found by its remote ID (Content from PHP,
Mapping content: translations).
Caches after language changes
php bin/php/ezcache.php --clear-tag=ini --allow-root-user # after changing [RegionalSettings]
php bin/php/ezcache.php --clear-tag=content --allow-root-user # lists and pages drawn again
php bin/php/ezcache.php --clear-tag=i18n --allow-root-user # after changing a .ts fileWith Velocity, also ./console exp:velocity cache clear --apply. The full list, including URL alias rebuilds:
Content languages, section 10.
Related pages
- Content languages: the complete guide
- Languages: the editor's view
- Right-to-left
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.