- Published on
Twig: Migrate transchoice to trans with ICU messages
- Authors
- Name
- Susanne Moog
While migrating a Symfony project from v3 to v4, I needed to move from the deprecated {% transchoice %}
(or the transchoice
filter) to {% trans %}
using ICU messages for pluralization and more. Here’s a concise guide with examples. For the official docs, see https://symfony.com/doc/current/translation/message_format.html
1) Old pluralization syntax (transchoice)
Previously, pluralized messages often looked like this (in XLF target or inline):
{0}never
|{1}once
|{2}twice
|]2,Inf[%count% times
2) Switch to ICU message format
First, rename your translation file to the ICU variant so Symfony’s Translation component uses the ICU formatter:
- From:
messages.en.xlf
- To:
messages+intl-icu.en.xlf
Repeat this for each locale file.
3) Rewrite messages using ICU plural rules
Example XLF entry with ICU pluralization:
<trans-unit id="countLabel">
<source>countLabel</source>
<target>{
count, plural,
=0 {never}
=1 {once}
=2 {twice}
other {# times}
}</target>
</trans-unit>
Use it in Twig with the trans
filter and provide count
:
{{ 'countLabel' | trans({ 'count': countVariable }) }}
This renders “never”, “once”, “twice”, or “12 times” depending on countVariable
.
4) Variables in ICU messages
ICU messages no longer use %foo%
placeholders. Use {foo}
braces instead:
<trans-unit id="countLabel">
<source>countLabel</source>
<target>{
count, plural,
=0 {No {type} pony - so sad.}
one {One {type} pony.}
other {# {type} ponies}
}</target>
</trans-unit>
{{ 'countLabel' | trans({ 'count': countVariable, 'type': 'shiny' }) }}
5) More complex messages (select + plural)
You can combine select
with plural
:
{ gender, select,
female {{
count, plural,
=0 {She loves no man.}
one {She loves one man.}
other {She loves many men.}
}}
other {{
count, plural,
=0 {They love no man.}
one {They love one man.}
other {They love many men.}
}}
}
Tip: Try the ICU message editor: https://format-message.github.io/icu-message-format-for-translators/editor.html
6) Register ICU files in PHP (if wiring Translator manually)
If you bootstrap the Translator yourself, ensure you load messages+intl-icu.*.xlf
and use the ICU domain:
use Symfony\Component\Translation\Loader\XliffFileLoader;
use Symfony\Component\Translation\Translator;
$translator = new Translator('en');
$translator->addLoader('xlf', new XliffFileLoader());
$translator->addResource(
'xlf',
__DIR__ . '/i18n/messages+intl-icu.en.xlf',
'en',
'messages+intl-icu'
);
That’s it — your Twig templates now use {% trans %}
with ICU messages for powerful, locale-aware formatting and pluralization.