Published on

Twig: Migrate transchoice to trans with ICU messages

Authors

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.