Login / Status
developer.Resource
Home . Documentation . Document Library . Core Documentation
Sponsors
hosted by punkt.deTYPO3 and Open Source Magazine

1.3. Localized content

The topic of localizing the actual content of pages is where different paradigms and preferences may step in. One clear difference is whether you want to localize or translate a page.

  • When you wish you translate a page 1:1 you might like to using “content binding” which secures exactly that. The pages content is then always defined by the default language records and any translation is solely depending on whether a localized record for the default language record exists. This is least flexible but has less room for error.

  • When you wish to localize a page you can build up a separate set of content elements for the page in their own order. You can still maintain references between original and translation if you wish. Most flexible, but could be too much freedom.

Now you will learn about the differences of these approaches in the context of the classic Page module.

Content binding

When working with the classic column based content delivery in TYPO3 (Web>Page module) you have the choice of two different localization approaches:

  • No binding: Each language can have varying number of content elements in their own order and possibly without a relation to any default language element.

  • Binding to default language: All translations follow the elements of the default language 1-1

The modes are described visually here:

No binding

This is the default situation. No additional configuration of the backend or frontend is needed.

The Web>Page module has a view like this:

As you can see, there are three Danish elements and only two default elements.

The translations all have the language setting set to Danish (seen by the Danish flag) but may or may not have a relation to “Transl. Orig”:

If there is a “Transl.Orig” value it will be used to display what the default language content is (useful for translators):

The website displays the content like this:

Binding

Binding translations to follow the default language translations requires a configuration of both frontend and backend:

  • Web>Page: The page module must know that a translation must be bound 1-1 to the default translation. This is configured by setting “mod.web_layout.defLangBinding = 1” in Page TSconfig.

  • TypoScript: You must ask the frontend rendering to select content from the default language and look for overlay records from the translation. This is configured with “config.sys_language_overlay = 1” in the TypoScript Template.

In the Web>Page module this is reflected like this:

Notice how the elements in the “Danish” column is aligned in rows bound to each element in the Default column. For the element in the middle there turn out to be no Danish translation at all.

The binding from the Danish element to the Default element is done with the “Transl. Orig” field which plays a crucial role now.

You can also notice that for each default element a localization button “Copy default content elements” will prepare a record ready for Danish translation.

In the frontend the result looks like this:

You see to the right how the top and button element is displayed in the Danish translation while the middle element is displayed in the default original since no translation exists.

Conclusion is: With content binding it is the default elements which decide over the element order and appearance on the page.

Overlay modes

When using the overlay mode you can choose a few variants:

config.sys_language_overlay = hideNonTranslated

This will change the output to this:

As you can see, the element that was not translated is simply not displayed in the default language.

Another one is this setting:

config.sys_language_softMergeIfNotBlank = tt_content:image, tt_content:header

This setting will look if the “image” and “header” fields of translations are blank and if that is the case the value of the default language record is allowed to be used.

Since the translation of the lower element has no images entered, the image field is blank and the images from the default element is used instead:

So with this setting you can inherit values from the original record (default language) by leaving a field blank - or provide a translation (like for the “header” field which had a value in the translation: “[Translate to Danish:] Nullam fermentum...”).

Notice: If the “l10n_mode” for columns in TCA is set to “exclude” or “mergeIfNotBlank”, inheritance of values from default records is already happening. But since you might like to enable this on a per-site basis, “config.sys_language_softmergeIfNotBlank” has been provided to add the “mergeIfNotBlank” setting to additional fields from the template record.

If you are designing a database table for localization you should look closer at the “l10n_mode” setting from TCA. You should also consider that when using the core localization features, references between records should ideally be between the default language records and never to the translations themselves; translations should be selected and overlaid default language records during rendering (assuming “config.sys_language_overlay” is set). Inheritance of field values from the original record will also happen only when a translation is shown through selecting its default language original and applying the translation over it.

Elements with language “[All]”

When using language binding combined with “config.sys_language_overlay = hideNonTranslated”  there is a special significance of the language value “[All]” (technically the -1 value): These elements will not be hidden in the translation - and they are not meant to be translated although you can choose to do so.

The setting looks like this:

It is reflected in the Web>Page module like this (notice the flag):

Typical applications of the “[All]” language is for “Insert Record”, “Plugin” elements (placeholders for something else) or “Flexible Content Element” (“templavoila” extension, typically having localization enabled in the FlexForm content).

Notes

  • “Hide default translation of the page” incompatible with content binding:  When using the “Binding” method (ie. “config.sys_language_overlay = 1 / hideNonTranslated”) you must supply placeholder records in the default language if you use the “Localization setting” for pages “Hide default translation of the page”.

  • Support for content binding: The TypoScript cObjects CONTENT and RECORD both supports the “sys_language_overlay” setting by selecting default language elements and overlaying according to the setting. This should be observed anywhere else content is selected (like in extension plugins). Technically, the function $GLOBALS['TSFE']->sys_page->getRecordOverlay() does this, but before using it, please look at how it has been used inside a class like “class.tslib_content.php” from the “cms” extension (tslib/)

  • “Search” content elements: “Search” content elements should be thought carefully about since they should search in the chosen language. The search query executed with the “SEARCHRESULT” cObject takes “sys_language_uid” into the query. Therefore the best is to create a search form element for each language (that is; do not inherit it). Alternatively let the search form reside on a page which is not translated at all (provided that “content_fallback” is used!)

FlexForms

FlexForms has the interesting capability of being able to store localizations internally in its XML. Whether this is enabled or not depends on the <meta>-tags in the Data Structure. But a prerequisite is that an ISO-code has been associated with the system languages:

(This requires “static_info_tables”).

Where localized content in TYPO3 identifies its language by a uid-value (the content of [languageField]) pointing to a “Website Language” record, flexforms use the universal ISO-code which is a newer and better architecture of course.

In the following the FlexForm localization modes are described. They apply universally to FlexForms but to illustrate the usage they are described in the context of a TemplaVoila based website and in relation to “Flexible Content Elements”. This is far the most typical application of FlexForm fields carrying localized content. Other applications are for Plugin configuration but in this case you will most likely disable localization all together.

FlexForm Localization modes

There are three localization modes possible for FlexForm content:

  • Disabled: No inline localization of the element.

  • Inheritance: Each default value in the FlexForm can be translated 1-1. Thus the translation closely follows the default language. This also allows for inheritance of default language values (like link values or images)

  • Separate: Each localization of the element can have a separate structure. This is only relevant if the flexform element provides deep structures like link lists which must be different in each language.

These modes are configured by the <meta> tag in the Data Structure.

As soon as you have begun using a Data Structure you cannot switch between Inheritance and Separate (<langChildren> = 1/0) without loosing localized content. However default content is never lost. (There might exist tools to make this conversion for you).

Overview

This overview shows the possible localization modes for a FlexForm field.

Where a FlexForm field is used to store references to content elements - called “container elements” - additional consideration especially related to TemplaVoila applies. For a discussion of this, please refer to subsequent chapters.

Disabled

Inheritance

Separate

Description:

No inline localization of the element.

Each default value in the FlexForm can be translated 1-1. The translations follows the default language.

Each localization of the element can have a separate, independent structure. Translation has no technical relation to default language.

Usage:

Universal: For all languages

Translation: Default content is faithfully translated 1-1 in each language.

Localization: Content in other languages can divert from the structure of the default language

Record language

(“languageField” value)

Use: [All] language

Alternatively you can of course localize the record with the core supported localization like any other record.

Use: [All] language

Use: [All] language

Data Structure configuration:

<meta>

    <langDisable>1</langDisable>

</meta>

Notice: <langChildren> is insignificant in this case.

<meta>

    <langChildren>1</langChildren>

    <langDisable>0</langDisable>

</meta>

<meta>

    <langChildren>0</langChildren>

    <langDisable>0</langDisable>

</meta>

Inheriting default content:

Not Applicable

Default content is inherited if there is no translated content (“blank” string or zero).

Configurations apply, see later

Not possible since there is no technical relation between localized content.

Recommended usage:

Use this type for FlexForm fields working as “container elements” providing structures for other content elements. In such cases it is unlikely that you want localization of the content element references(*).

Could also be Plugin configuration (also independent of language)

Recommended for container elements!

Recommended type since most websites only need a 1-1 translation of content. In cases where certain elements should be ignored in the translation there are ways to work around that.

Recommended for content!

Could be considered for Data Structures with substructures of sections/arrays (like the link list below) but for any Data Structure with only a single level you should avoid this type since its less flexible.

Avoid, unless expert

Warnings:

  • Be careful if using them as “container elements”

  • Never use as “container element”

Special notice related to “Free” paradigm (see later) and container elements

In the “Free” paradigm, “Disabled” usually indicates that no localization is intended for a container element. This is opposite to the “Bound” paradigm where “Disabled” is the recommended mode.

The reason is that the “Free” paradigm doesn't expect localization overlays of default language records but rather base itself on building separate structures of localized elements, hence needing either “Inheritance” or “Separate” modes. However, there are some flaws  which makes that paradigm problematic. Please refer to discussion later.

In the “Free” paradigm, this mode is recommended since a separate structure of content elements is built. However, as a content structure grows deeper than a single level this makes it impossible  to keep the order in sync with the default language since that will be located in another element.

See note for “Inheritance” mode, same applies.

In the following each type will be illustrated:

Disabled

This is a FlexForm element with localization disabled. It appears under the exact same terms as any other content element does: Based on its language setting in the field defined by “[languageField]” (see later).

Since this Data Structure is used to display the differences between localization modes lets take a look at it:

  • There is a Header and Body field on the root level

  • Then, there is a link section where we can add zero to many items, which in turn lets us choose between the item type “Link header” (single field) or “Link” (header + url field)

In the output on the page it looks like this:

Inheritance

With Inheritance the translation is included closely bound to the default value. In the FlexForm it looks like this:

Notice that for each field (“Header”) you find a counterpart for the available languages (“Header (vDA)”).

The code indicating the language (“vDA”) is a “v” + language ISO code.

Notice that the field “Url (vDA)” for the second link is blank. When this is the case the value from the “Url” field (default value) is inherited. This can be useful for such as URLs which doesn't change between languages - or might just change in which case you can optionally supply them!

The website display of the default record is this:

The danish display is this:

As you can see the text is translated. Only a mouse-over or click on the second link will show that the URL is inherited - but trust me, it is ;-)

Separate

In the “Separate” mode the two languages are separated completely in the form. This doesn't make any difference for the “Header” and “Body” fields but the “Link section” can be composed differently in the two languages. Below it is very easy to see this difference because for the Danish translation (“DA”) there is only one “Link” entry contrary to the “Link header” / “Link” / “Link” composition of the default language.

The result on the website is as expected.

First the Default display:

Then the Danish “localization”:

This is the flexibility of the “Separate” approach - that you can truely localize you content, not just translate it. But the price is that the relation between the default and translated content is lost in a technical sense.

FlexForm Data XML

The following is quite technical but for those who wish to take a look at how the FlexForm XML data is different in each scenario you can compare these listings:

“Disabled”:

  1: <?xml version="1.0" encoding="utf-8" standalone="yes" ?>

   2: <T3FlexForms>

   3:     <data type="array">

   4:         <sheet index="sDEF" type="array">

   5:             <language index="lDEF" type="array">

   6:                 <field index="field_header" type="array">

   7:                     <vDEF>Localization: Disabled</vDEF>

   8:                 </field>

   9:                 <field index="field_body" type="array">

  10:                     <vDEF>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras id quam ut sem ullamcorper aliquam. Aliquam faucibus urna sit amet massa. Quisque rutrum enim sed libero mollis fringilla. Maecenas eget sapien ac est vehicula ullamcorper. Aenean nunc tellus, sollicitudin id, ornare nec, euismod non, nunc. Sed aliquam, pede eu suscipit posuere, elit quam facilisis neque, vel dignissim arcu lacus at nulla.</vDEF>

  11:                 </field>

  12:                 <field index="field_links" type="array">

  13:                     <el type="array">

  14:                         <field index="1" type="array">

  15:                             <field_linkheader type="array">

  16:                                 <el type="array">

  17:                                     <field index="field_headerstr" type="array">

  18:                                         <vDEF>Maecenas eget</vDEF>

  19:                                     </field>

  20:                                 </el>

  21:                             </field_linkheader>

  22:                         </field>

  23:                         <field index="2" type="array">

  24:                             <field_linkcontent type="array">

  25:                                 <el type="array">

  26:                                     <field index="field_linktext" type="array">

  27:                                         <vDEF>My link to TYPO3.org</vDEF>

  28:                                     </field>

  29:                                     <field index="field_url" type="array">

  30:                                         <vDEF>http://typo3.org/</vDEF>

  31:                                     </field>

  32:                                 </el>

  33:                             </field_linkcontent>

  34:                         </field>

  35:                         <field index="3" type="array">

  36:                             <field_linkcontent type="array">

  37:                                 <el type="array">

  38:                                     <field index="field_linktext" type="array">

  39:                                         <vDEF>My link to TYPO3.com</vDEF>

  40:                                     </field>

  41:                                     <field index="field_url" type="array">

  42:                                         <vDEF>http://typo3.com/</vDEF>

  43:                                     </field>

  44:                                 </el>

  45:                             </field_linkcontent>

  46:                         </field>

  47:                     </el>

  48:                 </field>

  49:             </language>

  50:         </sheet>

  51:     </data>

  52: </T3FlexForms>

 

“Inheritance”:

   1: <?xml version="1.0" encoding="utf-8" standalone="yes" ?>

   2: <T3FlexForms>

   3:     <data type="array">

   4:         <sheet index="sDEF" type="array">

   5:             <language index="lDEF" type="array">

   6:                 <field index="field_header" type="array">

   7:                     <vDEF>Localization: Inheritance</vDEF>

   8:                     <vDA>Danish alternative header (Localization: Inheritance)</vDA>

   9:                     <vRU></vRU>

  10:                 </field>

  11:                 <field index="field_body" type="array">

  12:                     <vDEF>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras id quam ut sem ullamcorper aliquam. Aliquam faucibus urna sit amet massa. Quisque rutrum enim sed libero mollis fringilla. Maecenas eget sapien ac est vehicula ullamcorper. Aenean nunc tellus, sollicitudin id, ornare nec, euismod non, nunc. Sed aliquam, pede eu suscipit posuere, elit quam facilisis neque, vel dignissim arcu lacus at nulla.</vDEF>

  13:                     <vDA>Danish alternative bodytext here. Maecenas eget sapien ac est vehicula ullamcorper. Aenean nunc tellus, sollicitudin id, ornare nec, euismod non, nunc. Sed aliquam, pede eu suscipit posuere, elit quam facilisis neque, vel dignissim arcu lacus at nulla.</vDA>

  14:                     <vRU></vRU>

  15:                 </field>

  16:                 <field index="field_links" type="array">

  17:                     <el type="array">

  18:                         <field index="1" type="array">

  19:                             <field_linkheader type="array">

  20:                                 <el type="array">

  21:                                     <field index="field_headerstr" type="array">

  22:                                         <vDEF>Maecenas eget</vDEF>

  23:                                         <vDA>Danish header</vDA>

  24:                                         <vRU></vRU>

  25:                                     </field>

  26:                                 </el>

  27:                             </field_linkheader>

  28:                         </field>

  29:                         <field index="2" type="array">

  30:                             <field_linkcontent type="array">

  31:                                 <el type="array">

  32:                                     <field index="field_linktext" type="array">

  33:                                         <vDEF>My link to TYPO3.org</vDEF>

  34:                                         <vDA>Mit link til TYPO3.org</vDA>

  35:                                         <vRU></vRU>

  36:                                     </field>

  37:                                     <field index="field_url" type="array">

  38:                                         <vDEF>http://typo3.org/</vDEF>

  39:                                         <vDA>http://typo3.org/dk/</vDA>

  40:                                         <vRU></vRU>

  41:                                     </field>

  42:                                 </el>

  43:                             </field_linkcontent>

  44:                         </field>

  45:                         <field index="3" type="array">

  46:                             <field_linkcontent type="array">

  47:                                 <el type="array">

  48:                                     <field index="field_linktext" type="array">

  49:                                         <vDEF>My link to TYPO3.com</vDEF>

  50:                                         <vDA>Mit link til TYPO3.com</vDA>

  51:                                         <vRU></vRU>

  52:                                     </field>

  53:                                     <field index="field_url" type="array">

  54:                                         <vDEF>http://typo3.com/</vDEF>

  55:                                         <vDA></vDA>

  56:                                         <vRU></vRU>

  57:                                     </field>

  58:                                 </el>

  59:                             </field_linkcontent>

  60:                         </field>

  61:                     </el>

  62:                 </field>

  63:             </language>

  64:         </sheet>

  65:     </data>

  66: </T3FlexForms>

“Separate”:

  1: <?xml version="1.0" encoding="utf-8" standalone="yes" ?>

   2: <T3FlexForms>

   3:     <data type="array">

   4:         <sheet index="sDEF" type="array">

   5:             <language index="lDEF" type="array">

   6:                 <field index="field_header" type="array">

   7:                     <vDEF>Localization: Separate</vDEF>

   8:                 </field>

   9:                 <field index="field_body" type="array">

  10:                     <vDEF>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Cras id quam ut sem ullamcorper aliquam. Aliquam faucibus urna sit amet massa. Quisque rutrum enim sed libero mollis fringilla. Maecenas eget sapien ac est vehicula ullamcorper. Aenean nunc tellus, sollicitudin id, ornare nec, euismod non, nunc. Sed aliquam, pede eu suscipit posuere, elit quam facilisis neque, vel dignissim arcu lacus at nulla.</vDEF>

  11:                 </field>

  12:                 <field index="field_links" type="array">

  13:                     <el type="array">

  14:                         <field index="1" type="array">

  15:                             <field_linkheader type="array">

  16:                                 <el type="array">

  17:                                     <field index="field_headerstr" type="array">

  18:                                         <vDEF>Maecenas eget</vDEF>

  19:                                     </field>

  20:                                 </el>

  21:                             </field_linkheader>

  22:                         </field>

  23:                         <field index="2" type="array">

  24:                             <field_linkcontent type="array">

  25:                                 <el type="array">

  26:                                     <field index="field_linktext" type="array">

  27:                                         <vDEF>My link to TYPO3.org</vDEF>

  28:                                     </field>

  29:                                     <field index="field_url" type="array">

  30:                                         <vDEF>http://typo3.org/</vDEF>

  31:                                     </field>

  32:                                 </el>

  33:                             </field_linkcontent>

  34:                         </field>

  35:                         <field index="3" type="array">

  36:                             <field_linkcontent type="array">

  37:                                 <el type="array">

  38:                                     <field index="field_linktext" type="array">

  39:                                         <vDEF>My link to TYPO3.com</vDEF>

  40:                                     </field>

  41:                                     <field index="field_url" type="array">

  42:                                         <vDEF>http://typo3.com/</vDEF>

  43:                                     </field>

  44:                                 </el>

  45:                             </field_linkcontent>

  46:                         </field>

  47:                     </el>

  48:                 </field>

  49:             </language>

  50:             <language index="lDA" type="array">

  51:                 <field index="field_header" type="array">

  52:                     <vDEF>Danish alternative header (Localization: Separate)</vDEF>

  53:                 </field>

  54:                 <field index="field_body" type="array">

  55:                     <vDEF>Danish alternative bodytext here. Maecenas eget sapien ac est vehicula ullamcorper. Aenean nunc tellus, sollicitudin id, ornare nec, euismod non, nunc. Sed aliquam, pede eu suscipit posuere, elit quam facilisis neque, vel dignissim arcu lacus at nulla.</vDEF>

  56:                 </field>

  57:                 <field index="field_links" type="array">

  58:                     <el type="array">

  59:                         <field index="1" type="array">

  60:                             <field_linkcontent type="array">

  61:                                 <el type="array">

  62:                                     <field index="field_linktext" type="array">

  63:                                         <vDEF>Danish link to a completely other site</vDEF>

  64:                                     </field>

  65:                                     <field index="field_url" type="array">

  66:                                         <vDEF>http://joomla.org/</vDEF>

  67:                                     </field>

  68:                                 </el>

  69:                             </field_linkcontent>

  70:                         </field>

  71:                     </el>

  72:                 </field>

  73:             </language>

  74:             <language index="lRU" type="array">

  75:                 <field index="field_header" type="array">

  76:                     <vDEF></vDEF>

  77:                 </field>

  78:                 <field index="field_body" type="array">

  79:                     <vDEF></vDEF>

  80:                 </field>

  81:             </language>

  82:         </sheet>

  83:     </data>

  84: </T3FlexForms>

Conclusion:

The interesting difference is that for “Inheritance” you find the translation of the default value (<vDEF>) in a tag on the same level in the XML (eg. “<vDA>”) - all within the <language index=”lDEF”> tag. With “Separate” you find the translation in a separate structure under <language index=”lDA”> while all values are stored with <vDEF>. In both cases the default language content is stored in the same way.

This also tells you why you cannot switch between the two types when you have first added localized content: You will simply loose it since TYPO3 will look for the translation of content in another position in the XML. There might be tools that can re-map the content for you if you need to make this change.

Language access control

If a translator is restricted to a single language (here: Danish) then the flexform will display only that/those languages - and the default language content (to be translated) is displayed read-only:

FlexForm - Containter Elements

A “Container Element” refers to a Flexible Content Element which has one or more fields on root level where references to other content elements can be placed. Typically such elements are used to create zones in a grid where content can be placed, thus they serve a structural purpose.

A classic container element could be a 2-column element, here named “Curabitur venenatis...” having a “Left column” and “Right column”:

In each column you see another content element placed.

On the website it looks like this:

Notice that container elements usually must have the “[All]” language set so they are rendered for all languages:

Two paradigms of using container elements

Unfortunately, two different approaches to localizing a website with container elements have developed. Inside TemplaVoilas Page module we had to implement support for both.

By default TemplaVoila follows the “Bound” paradigm which is the recommended mode taught by this document while the “Free” paradigm must be configured via Page TSconfig in order to be reflected in TemplaVoilas Page module.

This is the difference:

  • “Bound” paradigm (default, recommended): Promotes that the structure (order and nesting) of content elements on a page should be the same for all languages. Consequently, all container elements should have data structures where localization mode is “Disabled”. All content carrying elements (such as “Text w/Image”) is placed as default language elements which can have overlaid localizations (requiring “config.sys_language_overlay” to be set). Elements unique to a language can be placed separately if needed and in the rare case where a separate page structure is required, “Inheritance” mode could be used for the container element DS.

  • “Free” paradigm (alternative, configurable): Promotes that the structure (order and nesting) of content elements is build separately for each language, using either “Inheritance” or “Separate” mode in the data structure. While this may seem natural it imposes lots of problems; the core localization features are used in a less optimal way excluding the possibility of content inheritance; elements can be ordered differently which would usually be a mistake; content structures deeper than a single level is impossible to synchronize technically.

The “Free” paradigm is configured by setting this line in Page TSconfig:

mod.web_txtemplavoilaM1.translationParadigm = free

The bottom line is that the “Bound” paradigm is the most flexible with the least complexity. Therefore this document promotes this solution. In the following I will try to notify where the difference between the two is necessary to keep in mind.

Localization mode of Container Elements (“Bound” paradigm)

When using Container Elements under the “Bound” paradigm (default and recommended) you should never use “Separate” mode, you should avoid “Inheritance” since it can confuse and the preferred mode is “Disabled”.

This recommendation is based on the assumption that most multilingual websites basically want to translate pages to other languages and therefore want the same order and hierarchy of content elements for each language. For this purpose “Disabled” mode for container elements is the way to go since that will ensure that the page structure is built by the same content elements regardless of language (localizations of content carrying elements are supplied as overlays).

However, you might like that some pages on your website could look entirely different in another language. Maybe you want two columns and five elements in the bottom for some reason. In such cases you have moved from translating the page to localizing the page. If this is a need of yours you should select the “Inheritance” mode because it gives you this flexibility. Basically; by default it will inherit the default structure for all languages unless you explicitly choose to implement one or more languages with their independent structure.

If you are really radical and want all pages in alternative languages to have its own structure built you can use the “Separate” mode, but my opinion is that you should probably have chosen not to use the “one-tree-fits-all” paradigm of localization then! If you want so radically different a website chances are good that you should have built a completely separate site for that language then! Otherwise you will find that all these nice localization techniques mostly work against you and not with you.

Localization mode of Container Elements (“Free” paradigm)

When using Container Elements under the “Free” paradigm it only makes sense to use “Inheritance” or “Separate” modes.

Each translation of the page is built by placing content elements in the container for that particular language. Usually you will try to place localizations  of the default language records in the separate structure. If you configure TemplaVoilas Page module with “mod.web_txtemplavoilaM1.translationParadigm = free” in Page TSconfig you will obtain support for this since the link to localize a record will not only create a localization but also place a reference in the container field.

Localization mode of Container Elements (Advanced details for “Bound” paradigm)

Here is a more in-depth and technical description:

Separate mode:

In “Separate” localization mode (<langChildren>0</langChildren>) the fields containing the relations to the localized content elements are separate from the default language fields:

What it means is that if you want any elements to appear in Danish you will have to create relations in the two Danish fields. TemplaVoilas page module supports this when you switch the “Show page language version” to the desired language. But experience shows that users will be puzzled why nothing is shown for Danish! This is only useful for building separate structures of content elements.

So altogether the “Separate” localization mode for Flexible Content Elements with container fields is discouraged.

In the Web>TemplaVoila control center you will see all Data Structures with this problem marked with a warning (if “Show Details” is enabled).

In the TemplaVoila page module you will also see the warning:

Notice: If “Free” paradigm is enabled with “mod.web_txtemplavoilaM1.translationParadigm = free” these warnings are removed and references to localizations are created automatically for you, thus making this mode usable, however not exempt from its theoretical problems.

Inheritance mode:

In “Inheritance” localization mode (<langChildren>1</langChildren>) the fields containing the relations to the localized content elements are bound to the default language fields:

Since inheritance of values is enabled by default (gray arrows) this will work because values are also used for Danish rendering. But - if a user adds a relation to any of the Danish fields that relation is used instead (as expected) but TemplaVoila will only reflect this in the Page module if that language is selected (in “Show page language version”). This could be confusing for users.

Here, you can see how the view for the default language looks:

And here is the view for the Danish language selected:

On the website for the Danish page you will see a funny mix because the left column will contain the rendering of the element “Fusce adipiscing...” specifically set for the Danish view while the right column inherits the reference to the element “Universal content”.

In the TemplaVoila control center a warning is shown for container elements with “Inheritance” mode:

In the TemplaVoila page module you will also see a warning:

In case you use “Inheritance” on purpose for your container elements you can disable this warning using Page TSconfig:

mod.web_txtemplavoilaM1.disableContainerElementLocalizationWarning_warningOnly = 1

Cases where you might use “Inheritance” for container elements is if such elements also contains regular input fields which needs localization.

Notice: If “Free” paradigm is enabled with “mod.web_txtemplavoilaM1.translationParadigm = free” these warnings are removed and references to localizations are created automatically for you, thus making this mode usable, however not exempt from its theoretical problems.

Disabled mode:

In “Disabled” localization mode (<langDisable>1</langDisable>) the fields containing the relations to the localized content elements are used regardless of language! This means that it is the same relations - those of the default language and shown by the TemplaVoila page module - which is used for all languages and with no possibilities of confusion!

It looks like this:

In the TemplaVoila control center you see no errors or warnings:

Notice: If “Free” paradigm is enabled with “mod.web_txtemplavoilaM1.translationParadigm = free” localization is not possible since the “Free” paradigm expects to build separate structures of content elements for each language.

Working with “Inheritance” and “Separate” modes for container elements

If you choose to work with Inheritance and Separate mode for container elements you will use the “Show page language version” to switch between the views (goes for both “Bound” and “Free” paradigms):

Inheritance settings (specific for TemplaVoila!)

The “Inheritance” localization mode of FlexForms can be modified further. It is possible to completely disable inheritance by the “dontInheritValueFromDefault” property of the tx_templavoila_pi1” plugin. For content elements this can be done with

plugin.tx_templavoila_pi1.dontInheritValueFromDefault = 1

It can also be used for TemplaVoila page templates, typically

page.10.dontInheritValueFromDefault = 1

<langOverlayMode>

More advanced is the tag “<langOverlayMode>” applicable in both Data Structures and the local processing of Template Objects.

With this tag you can set modes like “ifFalse”, “ifBlank”, “never”, “removeIfBlank”. The latter will enable you to exclude the display of elements if a certain field is blank, thus making up for some of the flexibility lost when using the “Inheritance” mode compared to “Separate”.

You must consult the TemplaVoila documentation on the Data Structure XML for more information.

Advanced usage of Inheritance - an example

In this example I will show how <langOverlayMode> can be used to change number of link objects displayed for this Flexible Content Element:

The setting we will use for “<langOverlayMode>” is “removeIfBlank” and we will apply it to the “Link text” field! With that setting this is what happens for each link:

  • Link, top: Has content for both default and danish, will be shown of course.

  • Link, middle: Has no content for the danish URL. This will be inherited from the default url (default setting, no effect of <langOverlayMode>)

  • Link, bottom: Has no content for the danish “Link text” and that affects the whole display of that link because <langOverlayMode> is “removeIfBlank” for the “Link text” field and according to the documentation that will block the rendering of the whole group of fields.

Visually, this is how the default links render:

And this is how they render in Danish. Obviously the last link is missing altogether:

Where to set <langOverlayMode>?

Well, you can set it in the Data Structure (DS), but alternatively you can set it in a Template Objects (TO) “Local processing” field. This allows you to vary the setting based on which TO renders the DS.

The “Local processing” field looked like this:

<T3DataStructure>

    <ROOT type="array">

        <el type="array">

            <field_links type="array">

                <el type="array">

                    <field_linkcontent type="array">

                        <el type="array">

                            <field_linktext type="array">

                                <tx_templavoila type="array">

                           <langOverlayMode>removeIfBlank</langOverlayMode>

                                </tx_templavoila>

                            </field_linktext>

                        </el>

                    </field_linkcontent>

                </el>

            </field_links>

        </el>

    </ROOT>

</T3DataStructure>

Notice: If “Free” paradigm is used, FlexForm content using Inheritance or Separate modes is possible only if the same element is used from each languages content structure. These problems are a main objection agains the “Free” paradigm because it so easily leads to confusion.

Limiting access to FlexForm fields for translators

Strictly, this is related to permissions, but it is interesting in the context. Consider if you wanted translators to only deal with the “Link text” fields of the form above, not the “Url” fields? Or it could be an image field where you want to inherit the default image - but translators would mistakenly insert new images if they see the field is blank. Well, what you can do is use a special display condition in the Data Structure to block display of some fields for translators:

<TCEforms type="array">

<displayCond>HIDE_L10N_SIBLINGS:except_admin</displayCond>

<config type="array">

<type>input</type>

<size>15</size>

...

Now, the magic lies in “HIDE_L10N_SIBLINGS” and the added parameter “except_admin” means that admin-users will see the URL fields (thus they can set exceptional values if needed). But the point is: Any other user will see this form with no Url fields:

 

Localized TemplaVoila Template Objects

TemplaVoila offers to select an alternative Template Object (TO) when the language is changed. What you do is to create an TO as a “Sub-template” of the main TO:

Of course you must select the correct language and then provide a mapping for this TO as well.

In the Web > TemplaVoila module you see the sub template displayed indented with the parent TO:

The localized template is selected based on the value of TSFE->sys_language_uid

TemplaVoila Page Module

TemplaVoilas page module has a tab for localization specific options:

  • “Show page language version”: This defines the language used to select from the FlexForm data structure. Usually the effect will be to see Flexible Content Elements show their content preview in that language. If you have container elements with localization enabled you might see an altogether different composition of that page! (Used especially for the “Free” paradigm)

  • “Edit language header”: Click a flag to edit the page header / Alternative Page Language record. This also shows the languages in which the page exists already.

  • “Create new page translation”: Select a language which the page has not yet been translated to in order to start translation!

For the “Bound” paradigm the “Show page language version” selector may be further filtered using a control that allows to scale down the number of languages displayed in the common structure:

Localization modes for a page Data Structure (“Bound” paradigm)

Almost by definition a Page Data Structure is a “container element” because without at least one field that can contain content elements there is not much content management to do.

As for Flexible Content Elements the most simple localization mode is the “Disabled” mode for a page Data Structure. This means the same structure of content elements is used for all languages. This is the “translation” mode where you do a 1-1 translation of the site. In the discussion for Flexible Content Elements this has been labeled the “Bound” paradigm. Opposite to this stands the “Free” paradigm which essentially is based on creating separate structures of content elements for each language.

Paradigms

I have chosen the word “paradigm” to describe the difference between these concepts because they are basically differences in how you think of localization. The discussion prior to defining these paradigms also showed that it was quite hard to tune ones brain into understanding the other paradigm. If you have a hard time to understand how the “Bound” paradigm could ever work since it builds the pages for all languages in the “Default language” structure it is simply because you have missed a feature in TYPO3 called “content overlay” (“config.sys_language_overlay” in TypoScript). This little feature means that when a page is displayed in Danish the rendering engine first selects the default language elements of the page but subsequently looks for a danish translation related to the default language element. If found, the Danish content is shown instead. If you are not familiar with that feature, of course the “Bound” paradigm seems like an illogical solution.

So, in the “Bound” paradigm the “Disabled” mode allows for a single content structure to be created which serves all languages.

However, you can choose the other modes as well. Lets try the “Inheritance mode”:

This will show a blank ”Main Content Area” inside of which you can build a completely different page structure for the danish language. Since the Inheritance principle applies, this structure will only be used if you put content element references there - otherwise the default language structure is used.

Using the “Separate” localization mode will do the same except you will have to put in content in the Danish language version, otherwise the page is blank.

Disabled

Inheritance

Separate

Usage

All pages must have exact same structure.

All pages will have same structure by default - but switching to another language will allow separate structures to be built for some languages

All pages must be separately built for each language.

Rating

Recommended for most projects

Recommended if more flexibility is needed for localization of certain pages, or if the Data Structure with the container fields also needs to carry content like a background image or header text.

Most like you will not need this mode unless all pages are sure to be different in all language. But you will not loose anything by using “Inheritance”, rather gain the possibility of fallback to the default language. And further, if you carry through that all pages must be specially localized it questions if you should have chosen the one-tree-fits-all approach in the first place instead of making a separate tree.

Philosophy

Translation 1-1

Recommended

Translation / Localization (customized)

Localization (customized)

 

Element language in “Inheritance” and “Separate” modes.

When building a separate structure of content elements using “Inheritance” or “Separate” modes for a page or FCE container element you strictly don't need to tag these elements with a language. However, for two reasons you will have to:

  • If you want language access control to be enforced you will have to set the language for elements.

  • If you have set up your TypoScript template with “config.sys_language_overlay = hideNonTranslated” (recommended) you will not see anything unless you tag elements with the correct language!

Here is an example. First the layout of the page/frontend in default language:

Then, how it looks with Danish language selected and in the frontend:

Notice how the page structures are very different: For the default language there were two columns, for the Danish “localized” version there was only a single content element placed directly in the “Main Content Area”.

Under normal circumstances where the localization mode of the Page Data Structure is “Disabled” (or “Inheritance” but with no elements added for the Danish page language version) you should see this view:

The reason why the page will show danish content is that the individual elements of the page are localized 1-1 (“config.sys_language_overlay” is set of course in order to overlay default records with their localizations):

  • The element “FCE DS: Disabled”: Container element creating two columns. Is set to the universal language “[All]” and will therefore be rendered regardless of selected language on the website.

  • The element “Default language here...”:  Normal “Text” content element that has a localized version in Danish. When the page is rendered, the default version is selected but overlaid with the danish localization on the website (because of “config.sys_language_overlay = 1”)

  • The element “Universal content”: A Flexible Content Element with a FlexForm Data Structure where localization is enabled (either “Inheritance” or “Separate”) and therefore the element in itself is set to the universal “[All]” language since the localized content is embedded in the FlexForm data.

In case the page Data Structure had localization mode set to “Disabled” you will see no difference of the Page module view when you switch “Show page language version” to Danish.

In case the page Data Structure had localization mode set to “Inheritance” you would see an empty structure when changing to Danish. Since the mode was “Inheritance” and the danish “Main Content Area” is blank, the danish rendering will be done with the Default language structure. But as shown above, the empty Danish structure could be used to build completely different structures if needed. But the recommendation is that you only do this when strictly needed!  

What you just saw is a good case of how the “Bound” paradigm works! Notice how the localized page was build without creating a separate structure of elements in the Danish “Main Content Area” but rather achieved through binding of localizations to their default elements.

Adding elements in only one language

Since for TemplaVoila localized websites using the “Bound” paradigm you must use the setting “sys_language_overlay” (unless using “Free” paradigm; building separate structures with “Separate” mode for containers) you will be able to place solo elements on a page for the translated languages:

This example shows a danish element which is not bound to a default language elements but appears solo on the page. It will only be shown when the danish language is selected. So for the default display it looks like this:

The Danish display looks like this (notice the extra element in the bottom):

“Disable”, “Inheritance” and “Separate” modes for containers - case study

One would think I have wasted enough time already trying to explain the details of these modes for container elements but I will not spare you a chance to see a comparison between them in how they solve the same problem! Maybe this will visualize it a bit more how the “Bound” paradigm works.

First, take a look at how the website output looks for both default language and Danish. This view will be reproduced using the three difference approaches, representing “Bound” and “Free” paradigms.

Normal display (default language):

When “Danish” is selected:

Two content elements are positioned side-by-side by a 2-column container element

In Danish the two content elements are translated but a third element has been added specifically for Danish.

Let's take a look at how this can be achieved with TemplaVoila using either of the localization modes for the 2-column container element:

“Disabled” mode / “Bound” paradigm:

When the container has localization mode set to “Disabled” you will see this view for the above content. The table also explains how rendering progresses for English and Danish display:

Show page language version: “English” (Default)

Show page language version: “Danish”

  • Element [1] is rendered because it has the “Default” language set.

  • Element [2] is rendered because it has the “[All]” language set, thus universal

  • Element [3] and [4] are not rendered - they are set to Danish

For Danish, the structure shown in the page module is the same as for Default because the localization mode is “Disabled” for the container element - thus all the localization is handled by the elements themselves:

  • Element [1] is selected because it has “Default” language - but TYPO3 looks for a localized version (because of config.sys_language_overlay = 1) and finds Element [3] which is rendered (possibly with merged fields according to l10n_mode)

  • Element [2] is rendered because it has the “[All]” language set, thus universal. The element is a Flexible Content Element and we can see that it has localization enabled for its FlexForm so localization is handled internally in the element.

  • Element [3] is rendered because it has the Danish language set (this was not shown in the default display)

“Inheritance” mode / Typically “Free” paradigm:

If “Inheritance” mode was used for the container element you would need this structure to create the same result:

Show page language version: “English” (Default)

Show page language version: “Danish”

  • Element [5] is rendered because it has the “Default” language set.

  • Element [6] is rendered because it has the “[All]” language set, thus universal

For Danish, the structure shown in the page module is different.

  • Left column:

    • Element [7] is meant to be a localization of Element[5] from the default view (typically created under the “Free” paradigm), but essentially it is just an unrelated copy of that element with Danish set as language. (It is considered inconsistent if this element was a true localized version of the default element pointing back to it with its “transOrigPointerField”. However, that is what the “Free” paradigm does when the “Localize” link is clicked for a default record.).

    • Element [8] is essentially Element [4] which in the “Inheritance” mode is moved to the Danish structure.

  • Right column [8]

    • This is empty - but because of the “Inheritance” mode it will inherit the content from default language (=Element [6]). Since Element [6] has the [All] language set it will also render for the danish view.

Interestingly, the structure from “Disabled” mode would also work as well under “Inheritance” mode. This is a great flexibility as I have mentioned before but might be two confusing and error-prone if the users doesn't understand it.

“Separate” mode / Only “Free” paradigm:

With “Separate” mode you will have to create these structures:

Show page language version: “English” (Default)

Show page language version: “Danish”

For the default language it is exactly the same as for “Inheritance” mode:

  • Element [10] is rendered because it has the “Default” language set.

  • Element [11] is rendered because it has the “[All]” language set, thus universal

For Danish, the structure is almost similar to that of “Inheritance” mode above - except that we had to duplicate (or reference) the element [14] in the right column since no inheritance exists for “Separate” mode.

Notice: Elements [11] and [14] didn't have to be [All], could have been Default and Danish respectively.

Notes:

For this example I used a Flexible Content Element as container element but there is no difference if the page Data Structure itself had two columns (which is probably more typical).

Also, the Page TSconfig was set to disable the warnings/errors display when container elements has localization mode set to “Inheritance” or “Separate”:

mod.web_txtemplavoilaM1.disableContainerElementLocalizationWarning = 1

Finally “config.sys_language_overlay = 1” was set in the TypoScript Template record to enable the overlay of localized versions used in the “Disabled” mode.

TemplaVoila: Best-practice

This table shows various best-practice recommendations for localized websites when using TemplaVoila. The assumption is that the “Bound” paradigm is used.

Topic

Recommendation

TypoScript Template Configuration

A typical, generic TypoScript configuration for setting up support for one additional language (here “dk”) looks like this:

# Localization:
config {
  linkVars = L
  sys_language_mode = content_fallback
  sys_language_overlay = hideNonTranslated
}
[globalVar = GP:L=1]
config {
  sys_language_uid = 1
  language = dk
  locale_all = da_DK
}
[global]

Setting “sys_language_overlay” to at least “1” is mandatory for the “Bound” paradigm and TemplaVoila (only column based websites and the “Free” paradigm can do without) and most likely you would like to set the more strict “hideNonTranslated” keyword which requires a record to have a translation before it can be displayed.

Page Data Structure localization mode

Create a page template using TemplaVoilas wizard. Modify the Data Structure XML so localization is “Disabled”. In rare cases you might like the ability to localize some pages with entirely different structures of content elements in which case “Inheritance” is a good option.

Stay clear of “Separate” mode.

FCE Data Structures localization mode

For Flexible Content Elements you should localize them according to their characteristics:

  • Pure container elements: Use “Disabled” localization mode (least complex)

  • Pure hierarchical content: Use “Inheritance” localization mode (least complex, most features)

  • Mixed containers and content: Use “Inheritance” localization (least complex)

Stay clear of “Separate” mode.

Always use the “[All]” language for a Flexible Content Element! See below.

“[All]” language?

If "sys_language_overlay" is set to "hideNonTranslated" it becomes very important that all "multilanguagerecords" like all Flexible Content Elements is set to "[All]" - otherwise they will not be selected in translations.

Generally these content element types should use the “[All]” language:

  • “Insert Plugins”

  • “Insert Records” (and make relations to default language records!)

  • “Flexible Content Elements” (internally localized in FlexForm)

The “[All]” langauge is set in the “languageField” of the record, for Content Elements:

This will be clearly reflected in the Page module of TemplaVoila:

TemplaVoila: Translator workflow

When you are limited users to languages you effectively define translator roles. This can have a few pleasant effects in terms of simplified interfaces in TYPO3. One is the use of display conditions in FlexForms, “HIDE_L10N_SIBLINGS” (see elsewhere).

Another is that TemplaVoilas Page module will scale down its buttons when a user does not have access to the default language (thus assumed to be a translator). It works out of the box:

Translators (with access to only alternative languages):

Users with access to default language:

Notice how all buttons has been stripped away. There are not even context menu links on item icons and no texts are clickable. Translators simply doesn't need any of this; all they need is links to translate the content.

This is the normal view of the Page module for TemplaVoila. Here you see all the additional buttons.

The concept of the scaled down view for translators is to provide a very simply rule for them: “Click the flag!”. All flags either leads to localization of a record or to editing of an existing translation. No confusion possible.

Another feature is that the view page icon will send the &L parameter according to language selected:

Having Danish selected will automatically add “&L=xx” to the preview URL: