Multiple Languages
Multi-Language Support - including Fallbacks
Neos <=8.x content
This is content for Neos <= 8.x releases.
This content is obsolete with Neos 9.0 and the event sourced Content Repository.
Neos supports content in multiple languages through a concept called content dimensions. On this page, we'll focus on the common case of having a single language dimension to achieve a multi-lingual website. Later on, we'll generalize this for arbitrary dimensions.
#Concepts
Here, we'll explain the concept of node variants and fallbacks.
#Introducing Node Variants
So far, we have explained the Content Repository as a big tree of nodes. It turns out that this is not 100% correct: At each tree node, there might be multiple so-called node variants, so one node variant for German and one for English.
When running Neos with just a single language, every node has exactly one node variant.
Using node variants, you can easily find all other variants of a given node, i.e. from the German version of a page, link to the English version of the same page. This allows to build good language menus.
Furthermore, the concept of Node Variants allows arbitrary translation directions: It is common that some pages might exist only in German, others only in English, while the majority of pages exists in both languages.
#Introducing Language Fallbacks
Aside from disjunct languages (i.e. languages which have nothing in common), Neos also supports languages which are pretty similar to each other, like British English and American English. In this case, you probably do not want to maintain your full content in both languages, but on the other hand, certain teaser and introduction texts should be customized to each individual audience.
Using language fallbacks, you can define e.g. that British English falls back to American English. In practice, this means if content is available in British English, it will be shown; whereas all other content is shown from American English.
We usually visualize this like layers in a photo editing application: The final rendering is a combination of the base layer (i.e. American English in our example), plus the British English layer on top.
Make sure to remove the Neos.Demo Site
Before you start, make sure to remove the Neos.Demo site from your distribution, as it contains numerous language definitions which might interfere with the definitions we're doing below.
#Configuring a monolingual site
We first start with a monolingual site, and later extend it with a second language and fallbacks.
First, we'll have a look at the Configuration/Settings.yaml of your Site package and configure an English dimension:
Neos:
Neos:
routing:
supportEmptySegmentForDimensions: true
ContentRepository:
contentDimensions:
language: # (1)
label: 'Language'
# The default dimension that is applied when creating nodes without specifying a dimension
default: en_US # (2)
# The default preset to use if no URI segment was given when resolving languages in the router
defaultPreset: en # (3)
presets:
en: # (4)
label: 'English (US)'
values: # (5)
- en_US
uriSegment: '' # (6)
- We define a content dimension called language at (1).
- The language dimension consists of one preset: en (4). A preset is what users can select in the Neos User Interface to switch between languages/dimensions.
- Each preset configures a label which is used in the User Interface and (optionally) in the Dimension Menu, a list of values (5) (more on that a few lines down), and an uriSegment (6) with which URIs will be prefixed with.
- If your site has only one language, you can leave the uriSegment blank. This will remove the language snippet from the uris.
- Also, please be sure to set supportEmptySegmentForDimensions to true
- Crucially important are the default and defaultPreset keys: They define what language you get when visiting the root of the website; and when logging into the backend. So the default (2) must reference the value en_US, while the defaultPreset (3) must reference the preset en.
So what's the matter with the values key? This is what is stored inside the node variant in the database. Below, we will use multiple values to configure language fallbacks.
Clear your cache after changing the dimension configuration
You may have to clear your cache using ./flow flow:cache:flush after adjustments to the content dimensions, because e.g. URLs have to be regenerated after modifications.
#Migrate existing content
With the above configuration, when we refresh our website, our complete website has no visible content anymore, as the content in the system is not yet moved to the language dimension.
This can be done with a node migration which is included in the Neos.ContentRepository package:
./flow node:migrate 20150716212459
Now, every content in the system is moved to language en_US, because this is the dimension's default in the configuration above.
Basically, your content is visible again in en_US.
#Configuring a bilingual site
Next up, we're looking at the setup of a bilingual site, and later extend it with fallbacks.
To add/remove/change dimensions, open the Configuration/Settings.yaml of your Site package and configure your dimension. In the example we're using English and German:
Neos:
ContentRepository:
contentDimensions:
language: # (1)
label: 'Language'
default: en_US # (2)
defaultPreset: en # (3)
presets:
en: # (4)
label: 'English (US)'
values: # (5)
- en_US
uriSegment: '' # (6)
de: # (7)
label: German
values:
- de
uriSegment: de
- We define a content dimension called language at (1).
- The language dimension consists of two presets en (4) and de (7). A preset is what you select in the Neos User Interface to choose which content you want to see.
- Each preset configures a label which is used in the User Interface and (optionally) in the Dimension Menu, a list of values (5) (more on that a few lines down), and an uriSegment (6) with which URIs will be prefixed with.
- An empty uriSegment is allowed (6); so in the example above, the English website is available directly at /, while the German website starts with URLs at /de.
- Crucially important are the default and defaultPreset keys: They define what language you get when visiting the root of the website; and when logging into the backend. So the default (2) must reference the value en_US, while the defaultPreset (3) must reference the preset en.
So what's the matter with the values key? This is what is stored inside the node variant in the database. Below, we will use multiple values to configure language fallbacks.
uriSegment is not allowed to contain underscore (_)
The property uriSegment is not allowed to contain any underscores. As an example, a valid identifier is de-DE, but not de_DE.
There's an open bug report which explains the background of that.
Clear your cache after changing the dimension configuration
You may have to clear your cache using ./flow flow:cache:flush after adjustments to the content dimensions, because e.g. URLs have to be regenerated after modifications.
#Migrate existing content
With the above configuration, when we refresh our website, our complete website has no visible content anymore, as the content in the system is not yet moved to the language dimension.
This can be done with a node migration which is included in the Neos.ContentRepository package:
./flow node:migrate 20150716212459
Now, every content in the system is moved to language en_US, because this is the dimension's default in the configuration above.
This means your content is visible again in en_US, and you can start translating from en_US to de.
#Configuring a Fallback Language
We will now take the example from above and extend it with British English, which should fall back to American English:
Neos:
ContentRepository:
contentDimensions:
language:
label: 'Language'
default: en_US
defaultPreset: en
presets:
en:
label: 'English (US)'
values:
- en_US
uriSegment: ''
de:
label: German
values:
- de
uriSegment: de
##### modification starts here
en_UK: # (1)
label: 'English (UK)' # (2)
values: # (3)
- en_UK
- en_US
uriSegment: uk # (4)
- We define a new preset en_UK (1), and give it a human readable label for the User Interface (2).
- The values now contain two elements (3) meaning: "Please use the content from en_UK, falling back to content from en_US".
- We also need to configure an uriSegment (4).
That's it :) By configuring multiple values, we specify the fallback order.
#Behind the Scenes
The language fallbacks are applied while reading the content from the CR. This means in the database, if you check for British English content, you'll see the language: en_UK value.
#Translating Content
When you switch to a language in the Neos User Interface, there are two things which can happen:
- If the page already exists in the target language, it is shown.
- If the page does not exist yet, a popup appears where you can create this node variant.
For translating with language fallbacks, you simply switch to the British English version of the website. At first, the default (American English) content will shine through. As soon as a shine-through node is updated, it will be automatically copied to the British English variant.
#Additional Resources
In case you need to support more advanced cases like combinations of language and country, continue reading the chapter about content dimensions next.