Multi-language Fluid templates
Consider you have to translate the following static texts in your Fluid template:
<h3>{post.title}</h3>
<p>By: {post.author.fullName}</p>
<p>{post.content -> f:format.nl2br()}</p>
<h3>Comments</h3>
<f:for each="{post.comments}" as="comment">
{comment.content -> f:format.nl2br()}
<hr>
</f:for>
To make such texts exchangeable, they have to be removed from the Fluid template and inserted into an XLIFF language file. Every text fragment to be translated is assigned an identifier (also called key) that can be inserted into the Fluid template.
The translation ViewHelper f:translate
To insert translations into a template, Fluid offers the ViewHelper f:translate.
This ViewHelper has a property called key
where the identifier of
the text fragment prefixed by the location file can be provided.
<f:translate key="LLL:EXT:my_extension/Resources/Private/Language/yourFile.xlf:yourKey" />
<!-- or as inline Fluid: -->
{f:translate(key: 'LLL:EXT:my_extension/Resources/Private/Language/yourFile.xlf:yourKey')}
The text fragment will now be displayed in the current frontend language defined in the site configuration, if the translation file of the requested language can be found in the location of the prefix.
If the key is not available in the translated file or if the language file is not found in the language, the key is looked up in the default language file. If it is not found there, nothing is displayed.
You can provide a default text fragment in the property default
to
avoid no text being displayed:
<f:translate
key="LLL:EXT:my_extension/Resources/Private/Language/yourFile.xlf:yourKey"
default="No translation available."
/>
The translation ViewHelper in Extbase
In Extbase, the translation file can be detected automatically. It is therefore possible to omit the language file prefix.
<f:translate key="commentHeader" />
<!-- or as inline Fluid: -->
{f:translate(key: 'commentHeader')}
In Extbase plugins <f:
looks up the key in
LLL:
.
The language string can be overridden by the values from
_LOCAL_
. See also property _LOCAL_LANG in a
plugin.
Attention
This short notation triggers TypoScript parsing via the Extbase ConfigurationManager. It should be avoided in backend context, for example in backend modules.
It is possible to use the translation file of another extension by supplying
the parameter extension
with the UpperCamelCased extension key:
<f:translate key="commentHeader" extensionName="MyOtherExtension" />
Note
The translation file has to be located at
EXT:
in the other extension as well.
There is no fallback to the file of the original extension in this case.
By replacing all static texts with translation ViewHelpers the above example can be replaced:
<h3>{post.title}</h3>
<p><f:translate key="authorPrefix"> {post.author.fullName}</p>
<p>{post.content -> f:format.nl2br()}</p>
<h3><f:translate key="commentHeader"></h3>
<f:for each="{post.comments}" as="comment">
{comment.content -> f:format.nl2br()}
<hr>
</f:for>
Source of the language file
If the Fluid template is called outside of an Extbase context there are two options on how to configure the correct language file.
-
Use the complete language string as key:
Prefix the translation key with
LLL:
and then the path to the translation file, followed by a colon and then the translation key.EXT: <f:translate key="LLL:EXT:my_extension/Resources/Private/Language/yourFile.xlf:yourKey" />
Copied! -
Or provide the parameter
extension
:Name <f:translate key="yourKey" extensionName="MyExtension" />
Copied!If the
extension
is provided, the translation string is searched inName EXT:
.my_ extension/ Resources/ Private/ Language/ locallang. xlf
Insert arguments into translated strings
In some translation situations it is useful to insert an argument into the translated string.
Let us assume you want to translate the following sentence:
Here is a list of 5 blogs:
As the number of blogs can change it is not possible to put the complete sentence into the translation file.
We could split the sentence up into two parts. However in different languages the number might have to appear in different positions in the sentence.
Splitting up the sentence should be avoided as the context would get lost in translation. Especially when a translation agency is involved.
Instead it is possible to insert a placeholder in the translation file:
<trans-unit id="blog.list" xml:space="preserve" approved="yes">
<source>Here is a list of %d blogs: </source>
<target>Eine Liste von %d Blogs ist hier: </target>
</trans-unit>
<trans-unit id="blog.list1" xml:space="preserve" approved="no">
<source>Here is a list of </source>
<target>Eine Liste von </target>
</trans-unit>
<trans-unit id="blog.list2" xml:space="preserve" approved="no">
<source>blogs: </source>
<target>Blogs ist hier: </target>
</trans-unit>
Argument types
The placeholder contains the expected type of the argument to be inserted. Common are:
%d
- The argument is treated as an integer and presented as a (signed)
decimal number. Example:
-42
%f
- The argument is treated as a float and presented as a floating-point
number (locale aware). Example:
3.
14159 %s
- The argument is treated and presented as a string. This can also be
a numeral formatted by another ViewHelper
Example:
Lorem ipsum dolor
,59,99 €
,12.
12. 1980
There is no placeholder for dates. Date and time values have to be formatted
by the according ViewHelper <f:
, see section
localization of date output .
For a complete list of placeholders / specifiers see PHP function sprintf.
Order of the arguments
More than one argument can be supplied. However for grammatical reasons the ordering of arguments may be different in the various languages.
One easy example are names. In English the first name is displayed followed by a space and then the family name. In Chinese the family name comes first followed by no space and then directly the first name. By the following syntax the ordering of the arguments can be made clear:
<trans-unit id="blog.author" xml:space="preserve" approved="yes">
<source>%1$s %2$s</source>
<target>%2$s%1$s</target>
</trans-unit>
<f:translate
key="author"
arguments="{1: blog.author.firstName, 2: blog.author.lastname}"
/>
The authors name would be displayed in English as Lina Wolf
while
it would be displayed in Chinese like 吴林娜
(WúLínnà).
Localization of date output
It often occurs that a date or time must be displayed in a template.
Every language area has its own convention on how the date is to be
displayed: While in Germany, the date is displayed in the form
Day.
, in the USA the form
Month/
is used. Depending on the language, the date
must be formatted different.
Generally the date or time is formatted by the
<f:
ViewHelper:
<f:format.date date="{dateObject}" format="d.m.Y" />
<!-- or -->
{dateObject -> f:format.date(format: 'd.m.Y')}
The date object {date
is displayed with the date
format given in the parameter format
. This format string must
be in a format that is readable by the PHP function date
and declares the format of the output.
The table below shows some important placeholders:
Format character | Description | Example |
---|---|---|
d | Day of the month as number, double-digit, with leading zero | 01 ... 31 |
m | Month as number, with leading zero | 01 ... 12 |
Y | Year as number, with 4 digits | 2011 |
y | Year as number, with 2 digits | 11 |
H | Hour in 24 hour format | 00 ... 23 |
i | Minutes, with leading zero | 00 ... 59 |
Depending on the language area, another format string should be used.
Here we combine the <f:
ViewHelper with the <f:
ViewHelper to supply a localized
date format:
<f:format.date date="{dateObject}" format="{f:translate(key: 'dateFormat')}" />
Then you can store another format string for every language in the
locallang.
file.
Tip
There are other formatting ViewHelpers for adjusting the output of
currencies or big numbers. These ViewHelpers all starts with
<f:
. You can find an overview of these ViewHelpers in
the ViewHelper Reference: format.