Arguments in a label: sprintf and ICU plurals
A label can carry values that TYPO3 fills in when it translates. Pass them as an array to the translation call, after the label reference. The keys of that array decide how TYPO3 reads the label:
- A list, so keys
0,1,2, makes TYPO3 treat the label as a sprintf() format string, with%sand%das the placeholders. - An array with names as keys makes TYPO3 read the label as an
ICU MessageFormat
pattern, with
{name}as the placeholder.
Plurals and selections with ICU MessageFormat
New in version 14.2 Feature: #104546 - Support ICU MessageFormat for plural forms
ICU MessageFormat picks one wording by a value. Use it where a count or a
gender changes the sentence, because the rules for that differ per language.
A German label needs two forms for a count, a Polish one needs four, and
sprintf cannot express either.
Write the pattern into the label as it stands:
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="locallang.xlf">
<header/>
<body>
<trans-unit id="file_count">
<source>{count, plural, one {# file} other {# files}}</source>
</trans-unit>
<trans-unit id="item_count">
<source>{count, plural, =0 {no items} one {# item} other {# items}}</source>
</trans-unit>
<trans-unit id="greeting">
<source>Hello {name}, you have {count, plural, one {# message} other {# messages}}.</source>
</trans-unit>
<trans-unit id="profile_update">
<source>{gender, select, male {He} female {She} other {They}} updated the profile.</source>
</trans-unit>
<trans-unit id="welcome">
<source>Welcome, {name}!</source>
</trans-unit>
</body>
</file>
</xliff>
{count, plural, …}- Chooses by the plural category of the value:
one,other, and the categories of the current language.=0matches exactly zero, which gives a sentence like "no items" its own wording. A#inside a branch prints the number. {gender, select, …}- Chooses by an exact value.
othercatches the rest. {name}- Prints the value.
Then pass the values under their names:
$this->getTranslator()->label(
'my_extension.messages:file_count',
['count' => 5],
);
<f:translate key="my_extension.messages:file_count"
arguments="{count: files}" />
TYPO3 reads the plural rules of the current locale, and falls back to en_
where it knows no locale. So the same label gives "5 files" in English and
"5 Dateien" in German, each with the forms of that language.
Where a pattern is invalid, TYPO3 returns the label unchanged, with the braces still in it. A sentence of curly braces on a page is the sign to look for a typo in the pattern.
Positional values with sprintf()
A list of values keeps the behavior that TYPO3 always had: the label is a
sprintf format string.
$this->getTranslator()->label(
'my_extension.messages:greeting_sprintf',
['World'],
);
TYPO3 uses vsprintf here, which reports a count of values that does not
match the count of placeholders. A label with one %s and no value therefore
raises an error instead of printing an empty string.
Do not mix the two. A label written for sprintf keeps its %s untouched
when the call passes named values. An ICU pattern reaches the output with its
braces when the call passes a list.