Feature: #104546 - Support ICU MessageFormat for plural forms 

See forge#104546

Description 

TYPO3 now supports ICU MessageFormat for translations, enabling proper handling of plural forms, gender-based selections, and other locale-aware formatting directly in language labels.

ICU MessageFormat is an internationalization standard that allows messages to contain placeholders that can vary based on parameters like quantity, gender, or other conditions. This is particularly useful for proper pluralization in languages with complex plural rules.

The format is automatically detected when using named arguments (associative arrays) in translation calls. If the message contains ICU patterns like {count, plural, ...} or {name}, and named arguments are provided, the ICU MessageFormatter will be used automatically.

Language file format 

ICU MessageFormat strings are stored as regular translation strings in XLIFF files:

EXT:my_extension/Resources/Private/Language/locallang.xlf
<?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">
        <body>
            <!-- Simple plural form -->
            <trans-unit id="file_count">
                <source>{count, plural, one {# file} other {# files}}</source>
            </trans-unit>

            <!-- Plural with zero case -->
            <trans-unit id="item_count">
                <source>{count, plural, =0 {no items} one {# item} other {# items}}</source>
            </trans-unit>

            <!-- Combined placeholder and plural -->
            <trans-unit id="greeting">
                <source>Hello {name}, you have {count, plural, one {# message} other {# messages}}.</source>
            </trans-unit>

            <!-- Gender selection -->
            <trans-unit id="profile_update">
                <source>{gender, select, male {He} female {She} other {They}} updated the profile.</source>
            </trans-unit>

            <!-- Simple named placeholder -->
            <trans-unit id="welcome">
                <source>Welcome, {name}!</source>
            </trans-unit>
        </body>
    </file>
</xliff>
Copied!

PHP usage 

Use named arguments (associative array) to trigger ICU MessageFormat processing:

Using ICU MessageFormat with LanguageService
use TYPO3\CMS\Core\Localization\LanguageServiceFactory;

$languageService = GeneralUtility::makeInstance(LanguageServiceFactory::class)
    ->createFromUserPreferences($backendUser);

// ICU plural forms - use named arguments
$label = $languageService->translate(
    'file_count',
    'my_extension.messages',
    ['count' => 5]
);
// Result: "5 files"

// Combined placeholder and plural
$label = $languageService->translate(
    'greeting',
    'my_extension.messages',
    ['name' => 'John', 'count' => 3]
);
// Result: "Hello John, you have 3 messages."

// sprintf-style still works with positional arguments
$label = $languageService->translate(
    'downloaded_times',  // Label: "Downloaded %d times"
    'my_extension.messages',
    [42]  // Positional arguments use sprintf
);
// Result: "Downloaded 42 times"
Copied!
Using ICU MessageFormat with LocalizationUtility
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;

// With named arguments for ICU format
$label = LocalizationUtility::translate(
    'file_count',
    'MyExtension',
    ['count' => 1]
);
// Result: "1 file"
Copied!

Fluid usage 

In Fluid templates, use named arguments in the arguments attribute:

EXT:my_extension/Resources/Private/Templates/Example.html
<!-- ICU plural forms with named arguments -->
<f:translate key="file_count" arguments="{count: numberOfFiles}" />

<!-- Combined placeholder and plural -->
<f:translate key="greeting" arguments="{name: userName, count: messageCount}" />

<!-- Gender selection -->
<f:translate key="profile_update" arguments="{gender: userGender}" />

<!-- sprintf-style with positional arguments still works -->
<f:translate key="downloaded_times" arguments="{0: downloadCount}" />
Copied!

ICU MessageFormat syntax reference 

Plural forms:

{variable, plural,
    =0 {zero case}
    one {singular case}
    other {plural case}
}
Copied!

Select (gender/choice):

{variable, select,
    male {He}
    female {She}
    other {They}
}
Copied!

Number formatting:

{count, number}           - Basic number
{price, number, currency} - Currency format
Copied!

The # symbol in plural patterns is replaced with the actual number.

Impact 

This feature provides a standards-based approach to pluralization that:

  • Uses the well-tested ICU library (via PHP's intl extension)
  • Automatically handles locale-specific plural rules
  • Supports complex pluralization for languages like Russian or Arabic
  • Is backward compatible - existing sprintf-style translations continue to work

The system automatically detects which format to use based on the arguments:

  • Named arguments (associative array): Uses ICU MessageFormat
  • Positional arguments (indexed array): Uses sprintf