Creating a website in multiple languages with TYPO3 can be done in a
variety of ways - as usual. Unfortunately, all the options are hard to
understand unless described in a context where used. In addition, even
if you understand the context you might like to get some suggestions
for what others have found to be best-practices.
This document tries to document everything you need to know about
localizing websites with TYPO3. Ideally, it should mention every
feature and what it is good for. However, be sure to use
reference documents like the TypoScript Reference,
TYPO3 Explained, etc. to look up the
exact syntax for the features mentioned.
Since the main goal of this document is to include all knowledge areas
of localization, it might suffer from a poor composition where advanced
content is mixed here and there. A later revision could maybe make
up for this by better prioritizing the content. For now that has not been
a priority. On the other hand, you will come out as an expert in the
other end.
Localization and Translation
The two terms are often used to express the same. Also in this
document. But more precisely this is how we understand the difference:
Translation
means that a specific composition of words are translated to another
language. In other words: If there is a header and an image in the default
language, so there will be in the translation. No more, no less.
Localization
means more broadly that a page is represented in another language. This
means information in that language ("translation") but could also include
alternative templates, additional composition of content directed to another
audience, etc. In other words: There might be another number of headers and
images than in the default language.
TYPO3 handles both types of approaches, but this flexibility has the
price that you need to read this document to find out which approach
to choose for your project!
Credits
This document was originally written by Kasper Skårhøj.
Dedication
I want to dedicate this document to every native English speaker who
has over the years learned to live with my gazillions of documents
full of weird syntactical compositions and understood that it was a
privilege that a non-native like me after all chose to communicate in
a foreign language to the best of my abilities.
-- Kasper
Character sets
All TYPO3 websites use UTF-8 as their character set. Using UTF-8 means that you
have a consistent data storage and can store any glyph from any language without
worrying further about character sets.
Database field lengths
The TYPO3 Core is compatible with UTF-8.
However, you might face the problem that the database field lengths of some
extensions need to be extended. For example, each Chinese glyph takes three
bytes. So if a field is a varchar(10) and an author enters 10 Chinese
glyphs, only the first 3 glyphs will be stored (as they require 9 bytes). UTF-8
is tricky in this respect, as all ASCII characters only need 1 byte, while
European special characters usually need 2 and Asian character sets 3 bytes -
but some special characters can even need 5-6 bytes!
See also
For more information on how to set up your database to use UTF-8, please
read here:
Languages are defined in the site configuration
for each root page. When creating a new page on root level via TYPO3 backend,
a very basic site configuration is generated on the fly. It prevents immediate
errors due to missing configuration and can also serve as a starting point for
all further actions.
Site Management
The Introduction Package's default languages are English, Danish
and German languages. Adding a new language is done in the
Site Management > Sites module of the backend.
Editing form for a site configuration
Tip
Detailed information on how to extend the site configuration
with additional languages can be found in the
site handling documentation.
Once you have defined at least one additional language, you will be able to
translate pages and content. For example, the Web > List module will
show links for translation if you have translated the page.
The Web > List view, with page translations and localize links for content elements
Translated elements appears nested "under" their default language
parent element in the Web > List view.
The Web > List view shows translations nested under their parent
Translating pages
In order to translate a page in the page tree, create a
copy of it with a new language relation. Use the module Page and on the top of the right side
Language Comparison and the lower dropdown Create a new translation of this page.
As soon as you choose a language of this dropdown the translation process will start with the copy of this page.
The page copy will be generated in the default language with page property fields like title or description prefixed by a text similar to "[Translate to Language X:]".
The translated content needs to be put here, replacing the placeholder text (including the prefix and
the copied default language contents).
Select the Language Comparison function in the upper menu bar of the
Web > Page module. Then use the select box to create a new
translation of the page:
Create a new translation of the page
The form with the fields for the translated page will then be displayed:
Editing the page fields for an alternative page language
Most of the fields are the same as for the page of the default language. Below
the fields the content of the default language is shown.
As long as a page has no translated page record,
its contents cannot be translated, no matter how many system languages
have been defined.
You can get a complete overview of the page tree and page
translations by using the Web > Info module and choosing
the Localization Overview function.
Overview of existing translations in a blank Introduction Package
All the green entries indicate which languages the respective page is available
in. The gray areas mean that no translation is available, but access to the
page specifying this language is tolerated. It is also fast
to create new translations from this module: use the checkboxes and hit
the Create new translation headers button.
Creating translations for a whole selection of pages at once
Hiding pages if no translation exist
If there is no translation of a page, it will still appear by default in the
website menu when this language is used. Here the home page of the Introduction
Package is in German (as can be seen from the translate page title in
<title> tag), and all other (untranslated) pages still appear in the
menu, albeit in the default language (English).
The German home page with untranslated pages appearing in the menu
This behaviour can be changed. Let us edit the "Customizing" page.
In the Language tab, check the
Hide page if no translation for current language exists:
Hide the page if it is not translated
This is reflected in the Localization Overview:
The Localization Overview reflects the change in visibility of the "Customizing" page
From this it is clear that when viewing the website in
German the "Customizing" page is not accessible. The menu
reflects this in the frontend.
The "Customizing" page does not appear in the menu anymore
Trying to access the "Customizing" page directly with its ID will
produce an error.
An error message indicates a missing translation
Hiding default translation of pages
If you want pages only in the alternative languages you must still
create a default language page in the page tree which simply acts as a
placeholder. Setting this status is done by selecting the checkbox
Hide default translation of page:
Hide the page in the default language
This is reflected in the Localization Overview:
The Localization Overview shows the page as being unavailable in the default language
Note
The page also appears as being unavailable in Danish, because Danish falls
back to English and English is not available.
On the web site, the menu now looks like this in German:
The German-specific page shows up in the German version of the web site
and in English:
The German-specific page does not show up in the default version of the web site
Trying to access the "Nur für Deutschland" page in the default language will
yield an error.
Hiding pages in the default language is probably a rare thing to do,
but it is possible to imagine cases where the topic of a page or
section is only relevant in one of the alternative languages.
Especially, if a language of the site is not only a translation but may
serve subsidiaries of a company in a local context.
Inverse control of hidden translations
It is also possible to hide all untranslated pages by default
with a global setting:
The Localization Overview reflects this immediately:
The Localization Overview shows that all untranslated pages are hidden by default
Note how the behaviour of specific localization setting for the
"Customizing" pages has been inverted. We had earlier defined the page
to be hidden if no translation existed. Now it is forced to display
even if no translation exists (this is reflected by its background
being gray instead of red).
When editing the page properties, the label of the corresponding
checkbox has changed:
Inverted behaviour: choose to show the page even if no translation exists
Final notes
Summary of colors in the Localization Overview:
Green background
Page is translated and viewable in this
language. For translations it means that an active Alternative Page
Language overlay record is present.
Red background
Page cannot be viewed in this language and you
will see an error message if you try. Menus should automatically
filter out links to pages with this translation.
Gray background (not available for default language)
Page will fall back to the specified fallback mode for content.
It depends on the language fallback configuration set in your site
configuration.
There are two strategies for handling the translation of content on pages:
Connected mode
Translating content will create a direct connection between the original
language and the language you translate to. This means that moving an
element or setting meta information like start time or end time will be
taken from the original content and you will not be able to set these values
on a translated content element. Translated records will hold the connection
to their original language record in the l10n_parent field.
This mode is best for a strict translation workflow.
Free mode
Copying content will take the content elements from the source language
and create copies in a different language. This means that you will be able
to move content elements around freely, but you will not have the benefit of
being able to compare changes made in the source language later on.
Use this mode, when the translated pages content can largely differ from
the original language and you want to have that freedom in designing your
translated website.
When you start translating a page, the Web > Page module will ask
you about this choice when clicking on the Translate button:
The translation wizard asks for a choice of localization strategy
The Translate button corresponds to the connected mode, the
Copy button to the free mode. Furthers details on how to proceed with
translations are found in the Editor's Tutorial.
Connected content
If you opted for the connected content strategy, this is the default way
that translated pages will be handled in the frontend and requires
no further configuration in the site configuration.
In the site configuration, the fallbackType "strict" would look like this:
config/sites/my_site/config.yaml
languages:-# ... other language settings ...fallbackType:strict
Copied!
In this connected mode, TYPO3 will first internally fetch the records of the
default language, then overlay them with the target language. If a record is
not translated into the target language, then it is discarded and not shown at
all.
The German version will be reduced to the actually translated elements:
English and German translation without overlays
Another way to view connected content in the frontend is by creating a fallback
chain. For this we have to adjust the site configuration and provide a
comma-separated list of fallback languages:
config/sites/my_site/config.yaml
languages:-# ... other language settings ...fallbackType:fallback# 1 = Danish, 0 = Englishfallbacks:'1,0'
Copied!
In this mode, TYPO3 will also first internally fetch the records of the
default language and then overlay them with the target language. If no translation
exists for the target language, it will now go from left to right through the
fallback chain and first try to find a translation for the language ID 1 (Danish)
and, if that is a miss as well, fall back to language ID 0 (English).
The English version and its German translation, with overlays
Warning
If you want to use the "connected content" paradigm in conjunction with the
"Hide default translation of the page"
setting, you will need to provide placeholder content elements
in the default language and translate them, since the whole frontend
rendering process starts from the default language in such a configuration.
Free content
With the free mode content strategy, the
site configuration will have to be
adjusted accordingly:
config/sites/my_site/config.yaml
languages:-# ... other language settings ...fallbackType:free
Copied!
This means, TYPO3 will directly fetch the translated records and not care
about the records in the default language at all.
Tip
For more information on how to add languages and configure their
behaviour in the site configuration, see
Adding Languages.
The "All" language
When using overlays, it becomes possible to use a particular
language called "All", which will be automatically visible across all
translations. The uid of that particular language is "-1".
A content element valid for all languages
It is also marked with the special language icon in the Web > Page
module:
An "All" language content element displayed in the Web > Page module
Note that no Translate button appears, the new content element
is valid for all languages.
Localizing inline elements (IRRE)
When localizing a record with inline elements (IRRE),
the inline elements will be grayed out and not automatically localized. TYPO3
will display two buttons to help you localize and keep the elements in
sync.
Buttons for localizing and synchronizing inline elements
Localize all records (1) creates localized versions of all inline
elements from the default language in your current language so that
you can translate them. Each element that has not yet been localized
will also have a Localize button (3) that will allow you to localize
individual elements.
Synchronize with original language (2) can be clicked when you have
translated the elements and the content in the default language changed.
Localized labels
Using XLF labels in TypoScript structures
XLIFF (XLF) files are XML files containing labels that
the system can retrieve in a localized version if the appropriate translations
are installed. It is possible to retrieve values from XLF files using TypoScript:
page.20 = TEXT
page.20.data = LLL:EXT:indexed_search/Resources/Private/Language/locallang.xlf:form.submit
Copied!
This looks for the label form.submit in the file
Resources/Private/Language/locallang.xlf from the extension
"indexed_search".
If the frontend is now accessed in the language "de", the German language
is configured in the site configuration and the German
translations are installed in getLabelsPath()/de/,
the output should be "Suche" (instead "Search" which is what you will get if the
label is retrieved for the default language).
Using XLF labels in frontend plugins
Making your code ready for internationalization is covered in
Localization and
basics about XLIFF files are found in XLIFF Format ("TYPO3 Explained").
Properly made plugins should use XLIFF files for every label that
they used, so that they can be translated and thus generate a proper
output when a specific language is requested.
For instance, if the page is accessed in the language "de" and
the German translations are installed, you will see this page for "indexed search":
Output from the Indexed Search plugin in German
Overriding an existing translation is possible using custom XLIFF files.
This process is described in Custom translations.
You can also create XLIFF files for a language into which
TYPO3 is not translated yet. This process is described in
Custom languages.
Language selection menu
To properly navigate a multilingual web site you probably want
to have a language selection menu somewhere. This menu should
show an entry for each possible, with variation of aspect
depending on translation availability:
page = PAGE
page {
10.dataProcessing {
40 = TYPO3\CMS\Frontend\DataProcessing\LanguageMenuProcessor
40 {
languages = <insert language-id> or "auto"
as = languagenavigation
}
}
}
Copied!
The value for languages is a list of comma-separated language
IDs (for example: 0,1,2) or auto to load from
site configuration.
The menu is then passed as a hierarchical array to
Fluid in the variable {languagenavigation}.
The Fluid template iterates through the array and creates the language links:
The support for localization in the Core of TYPO3 is based around a scheme where
a record in the default language (id "0") can have other records pointing to it,
offering a translation of its content. This implies some requirements for the
structure of any database tables which we want to be available for translation:
A field holding the reference to the language defined in the
site configuration must be defined.
A field holding the reference to the default language record must be
defined.
Optionally, a field holding the reference to the record it was translated
from can be defined.
These fields are declared in the "[ctrl]" section
of the TCA for the table.
The entry for the [All] language gets automatically added with the
TCA type language.
Note
This field is traditionally named sys_language_uid, but any name can
be used since it is registered with the languageField property in the
ctrl section.
Deprecated since version 11.2
This field can only be used with the TCA type "language". All other field
types will be automatically migrated on-the-fly possibly losing configurations.
See Migration to the language type.
[transOrigPointerField]
The first field is defined by the
"transOrigPointerField"
property and contains a reference to the record in the default language.
Here is how such a field is configured (example from the tt_content
table):
This field is traditionally named l10n_parent, but any name can be
used since it is registered with the transOrigPointerField property.
The l18n_parent name used in table tt_content is a historical
mistake.
Obviously, the table name has to be adapted in properties foreign_table
and foreign_table_where for each table.
Notice the display condition set on the field, which will check the value of
the sys_language_uid and display the l18n_parent field only when
it is greater than zero (that means, it is a translation).
Another interesting point is that it will only look for a default language
record in the current pid. This means that a
default language record and all its translations must be on the same page!
This principle is also respected by the API function
\TYPO3\CMS\Core\Domain\Repository\PageRepository::getLanguageOverlay()
which fetches translations of records for the frontend display.
When the transOrigPointerField and languageField are defined for a
table you will see references to the content of the default language
record when editing the translation:
Original content shows up under the input fields when translating a record
Warning
The configured $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']
cannot be excluded as this leads to inconsistent data stored in the database.
This happens when a non-admin user creates a localization while not having
the permission to edit the transOrigPointerField. Remove
exclude => true from TCA, if set.
[transOrigDiffSourceField]
There is one more field which can be used on a translatable table, defined by
the property "languageField".
It is optional. It points to a blob database field which will store the content
of the default language record as it was when the translation was made. Then
this is used to display any changes that have occurred in the default record
since translation happened. For example, in the tt_content table, it may
look like this for the header field:
Changes in the original content are highlighted below the input field
This allows a translator to spot easily what has changed in order to adjust the
translation accordingly.
[translationSource]
The "translationSource" property
defines a name of the field used by translations to point back to the original
record (that means, the record in any language of which they are a translation).
This property is often set to l10n_source in Core tables.
This property is similar to
transOrigPointerField.
In connected mode, while transOrigPointerField
always contains the uid of the default language record, this field contains the
uid of the record the translation was created from.
For example, if a tt_content record in default language (English) with
uid 13 exists, this record is translated to French with uid 17, and the Danish
translation is later created based on the French translation, then the Danish
translation has uid 13 set as l10n_parent and 17 as l10n_source.
DataHandler commands for localization
Localizing a record can be done by the
"localize" command of the
DataHandler. This is the command that is sent
when you press the translate buttons in Web > List or
Web > Page for an element.
You can only localize a record which is not already localized and which is in
"default" or "All" language (a record in "All" language is supposed to be
somehow valid for any language, but can still be translated if needed).
It is possible to manually create two or more translations of the
same record but this is considered an error in the system, although
not fatal, yet producing unpredictable results.
Localization command options per field
Each field may contain special instructions which will affect the "localize"
command. Most important is the
"l10n_mode" field with which,
for example, a field can be entirely excluded from the translation process.
Permissions
You can restrict backend users and groups to edit records in specific languages
only. The permissions are enforced across all tables by checking the language
specified in the TCA configuration of the
"languageField" of the table.
Navigate to the backend module System > Backend Users. Select a
backend user group. The Limit to languages setting is found in the
Access Lists tab:
Restricting backend users or groups to one or more languages
Settings from groups and sub-groups are merged.
If a user has no Limit to languages checkboxes set at all they can
edit all languages.
Regardless of Limit to languages all users can edit records with
[All] language.
Setting Limit to languages is not only good to protect translators
from editing other languages or default content - it is also helpful
to limit the confusion a user might have when faced with modules
displaying translations for a variety of other languages!
Sitemap
Reference to the headline
Copy and freely share the link
This link target has no permanent anchor assigned.The link below can be used, but is prone to change if the page gets moved.