# General Translation Knowledge Base: Qu’est-ce que le format de message ICU ?
URL: https://generaltranslation.com/fr/kb/icu-message-format.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Le format de message ICU est une syntaxe qui permet à une seule chaîne traduisible de contenir des variables, des formes plurielles, des choix select et des ordinaux, par exemple {count, plural, one {# file} other {# files}}. Chaque langue utilise les catégories de pluriel CLDR dont elle a besoin : l’anglais utilise one et other, tandis que le polonais y ajoute few et many.
Category: Formatage selon les paramètres régionaux
Last updated: 2026-10-20
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

Cette syntaxe provient de la classe MessageFormat d’ICU (International Components for Unicode), les bibliothèques d’internationalisation du Consortium Unicode pour C/C++ et Java. Des bibliothèques JavaScript comme FormatJS implémentent la même grammaire. Depuis l’apparition d’une version entièrement repensée, MessageFormat 2, on la désigne aussi sous le nom de MessageFormat 1.

## Quel problème le format de message ICU résout-il ?

Le code qui assemble des phrases à partir de fragments fonctionne en anglais, mais pas dans les autres langues. `'You have ' + n + ' files'` code en dur l&#39;ordre des mots de l&#39;anglais et ses deux formes du pluriel. Le polonais a besoin de quatre formes pour la même phrase : 1 plik, 2 pliki, 5 plików et 1,5 pliku. Dans de nombreuses langues, une phrase genrée (« Elle a répondu » ou « Il a répondu ») entraîne la modification d&#39;autres mots, et les ordinaux (1er, 2e, 3e) obéissent à leurs propres règles.

Le format de message ICU regroupe tous ces cas dans une seule chaîne de caractères. Le traducteur voit la phrase entière avec toutes ses branches, la réécrit pour sa langue, puis ajoute ou supprime des branches selon les besoins de la grammaire. C&#39;est d&#39;ailleurs pour cette raison que le [guide utilisateur ICU](https://unicode-org.github.io/icu/userguide/format_parse/messages/) recommande d&#39;écrire une phrase complète dans chaque branche : un traducteur ne peut pas corriger la grammaire d&#39;un fragment qu&#39;il ne voit pas.

## La syntaxe, avec des exemples exécutables

Tous les exemples ci-dessous ont été exécutés avec [`intl-messageformat`](https://formatjs.github.io/docs/intl-messageformat) 12.1.4 de FormatJS sous Node.js 24. Un message est analysé une seule fois, puis formaté avec des valeurs :

```js
import { IntlMessageFormat } from 'intl-messageformat';

const msg = new IntlMessageFormat(
  '{count, plural, =0 {You have no messages.} one {You have # message.} other {You have # messages.}}',
  'en'
);

msg.format({ count: 0 });    // 'You have no messages.'
msg.format({ count: 1 });    // 'You have 1 message.'
msg.format({ count: 1234 }); // 'You have 1,234 messages.'
```

### Arguments

`{name}` insère une valeur : `Hello, {name}!` avec `{ name: 'Ada' }` donne « Hello, Ada! ». Les arguments typés formatent la valeur selon le paramètre régional : par exemple, `Total: {price, number, ::currency/EUR}` avec `1234.5` donne « Total: €1,234.50 » en anglais.

### plural, `#` et correspondances exactes

`{count, plural, ...}` sélectionne une branche en fonction de la catégorie de pluriel du paramètre régional : `zero`, `one`, `two`, `few`, `many` ou `other`. Dans une branche, `#` représente le nombre, formaté selon le paramètre régional ; le message allemand `{count, plural, one {Sie haben # Nachricht.} other {Sie haben # Nachrichten.}}` affiche « Sie haben 1.234 Nachrichten. » Une correspondance exacte comme `=0` prévaut sur la catégorie : c&#39;est ce qui permet à l&#39;exemple ci-dessus d&#39;afficher « aucun message » plutôt que « 0 messages ».

La même phrase en polonais, avec les branches propres au polonais :

```text
{count, plural, one {# plik} few {# pliki} many {# plików} other {# pliku}}
```

Avec `pl`, cela formate 1, 2, 5, 22 et 1.5 respectivement en « 1 plik », « 2 pliki », « 5 plików », « 22 pliki » et « 1,5 pliku ».

### select

`select` choisit une branche selon une valeur de type chaîne de caractères, et la branche `other` intercepte tous les autres cas :

```text
{gender, select,
  female {She replied to your comment.}
  male {He replied to your comment.}
  other {They replied to your comment.}}
```

`{ gender: 'female' }` donne &quot;She replied to your comment.&quot; et `{ gender: 'nonbinary' }` donne &quot;They replied to your comment.&quot; Gardez la phrase complète dans chaque branche : dans une autre langue, le genre peut modifier le verbe en plus du pronom.

### selectordinal

`selectordinal` s&#39;appuie sur les règles ordinales, qui comptent quatre catégories en anglais :

```text
{place, selectordinal,
  one {You finished #st.}
  two {You finished #nd.}
  few {You finished #rd.}
  other {You finished #th.}}
```

Pour les places 1, 2 et 11, on obtient respectivement `You finished 1st.`, `You finished 2nd.` et `You finished 11th.` Pour 3, 4, 22 et 103, les suffixes sont respectivement `rd`, `th`, `nd` et `rd`.

### offset

`offset:1` soustrait un au nombre avant de choisir la catégorie et d&#39;afficher `#`, ce qui est idéal pour les messages du type « vous et N autres personnes ». Les correspondances exactes, elles, s&#39;appliquent à la valeur d&#39;origine :

```text
{guests, plural, offset:1
  =0 {Nobody is going.}
  =1 {{host} is going.}
  one {{host} and # other person are going.}
  other {{host} and # other people are going.}}
```

Avec `host: 'Mia'`, 0, 1, 2 et 5 invités produisent respectivement &quot;Nobody is going.&quot;, &quot;Mia is going.&quot;, &quot;Mia and 1 other person are going.&quot; et &quot;Mia and 4 other people are going.&quot;

### Arguments imbriqués

Les arguments peuvent s&#39;imbriquer. Le guide ICU recommande de placer `select` au niveau externe et `plural` à l&#39;intérieur, avec une phrase complète dans chaque branche :

```text
{gender, select,
  female {{count, plural, one {She has # new follower} other {She has # new followers}}}
  other {{count, plural, one {They have # new follower} other {They have # new followers}}}}
```

### Apostrophes et échappement

Une apostrophe ASCII permet d’échapper les caractères de syntaxe, et deux apostrophes en produisent une seule. Depuis ICU 4.8, une apostrophe simple n’ouvre un passage échappé que si elle précède immédiatement un caractère à échapper. Les élisions courantes fonctionnent donc normalement :

```text
It's {name}'s turn. Type '{name}' to insert a name. I''m here.
```

Avec `{ name: 'Ada' }`, cela affiche `It's Ada's turn. Type {name} to insert a name. I'm here.` Dans un pluriel, `'#'` affiche un `#` littéral. Le [guide de la syntaxe ICU](https://formatjs.github.io/docs/core-concepts/icu-syntax) de FormatJS recommande d’utiliser l’apostrophe typographique (’) dans le texte lisible par l’humain, ce qui évite tout simplement le problème.

## Que sont les catégories de pluriel CLDR ?

Ces catégories proviennent des [règles de pluriel Unicode CLDR](https://cldr.unicode.org/index/cldr-spec/plural-rules), les mêmes données que celles sur lesquelles repose `Intl.PluralRules` en JavaScript. Voici ce que `Intl.PluralRules` renvoie pour quelques langues :

| Langue                        | Catégories cardinales                        |
| ----------------------------- | -------------------------------------------- |
| Anglais (`en`)                | `one`, `other`                               |
| Polonais (`pl`), russe (`ru`) | `one`, `few`, `many`, `other`                |
| Arabe (`ar`)                  | `zero`, `one`, `two`, `few`, `many`, `other` |
| Japonais (`ja`)               | `other`                                      |

`one` ne signifie pas forcément 1 : en russe, 21 relève aussi de `one`. N’utilisez `=1` que si vous visez précisément le nombre 1. Pour l’équivalent au niveau des composants dans React, consultez [Comment gérer les formes plurielles dans React ?](/kb/how-to-handle-plurals-in-react).

## Problèmes courants

* **Les erreurs de syntaxe se manifestent tardivement.** Une accolade manquante n&#39;est qu&#39;une simple chaîne de caractères jusqu&#39;à ce que le message soit analysé ; `intl-messageformat` lève alors une exception `EXPECT_ARGUMENT_CLOSING_BRACE`. Analysez ou lintez les messages dans votre CI, ou précompilez-les.
* **Absence de branche `other`.** `intl-messageformat` lève une exception `MISSING_OTHER_CLAUSE` pour un pluriel sans `other`, et FormatJS l&#39;exige également pour `select`.
* **Des branches inadaptées à la langue cible.** Un message en anglais comporte `one` et `other` ; la traduction polonaise nécessite en plus `few` et `many`, tandis que la traduction japonaise n&#39;a besoin que de `other`. Votre processus de traduction doit pouvoir ajouter et supprimer des branches, et pas seulement traduire le texte qu&#39;elles contiennent.
* **Fragments.** `{count} {count, plural, one {file} other {files}} deleted` laisse aux traducteurs des morceaux à réordonner. Placez la phrase complète dans chaque branche.
* **Dialectes mélangés.** La syntaxe par défaut d&#39;i18next n&#39;est pas ICU : elle utilise `{{name}}`, avec des clés de pluriel comme `key_one`. Les équipes qui souhaitent y utiliser ICU ajoutent le plugin [`i18next-icu`](https://github.com/i18next/i18next-icu).

## Quelles bibliothèques prennent en charge le format de message ICU ?

* **ICU4J et ICU4C** sont les implémentations de référence, en Java et en C/C++.
* **FormatJS** : [`intl-messageformat`](https://formatjs.github.io/docs/intl-messageformat) est l’analyseur et le formateur sur lesquels repose react-intl ; il prend en charge les squelettes de nombres et de dates, comme `::currency/EUR`, ainsi que les balises de texte enrichi. (Voir [General Translation vs. react-intl](/kb/general-translation-vs-react-intl).)
* **messageformat** : [`@messageformat/core`](https://messageformat.github.io/messageformat/) compile les messages ICU en fonctions JavaScript ; la version 4 du paquet `messageformat` implémente quant à elle MessageFormat 2.
* **i18next-icu** : le plugin i18next qui fait basculer i18next vers la syntaxe ICU, basé sur `intl-messageformat`.
* **Lingui** : ses [macros](https://lingui.dev/ref/macro) transforment le JSX et les gabarits étiquetés en messages ICU MessageFormat lors de la compilation.
* **next-intl** : ses [messages utilisent la syntaxe ICU](https://next-intl.dev/docs/usage/messages).

## Qu’est-ce qui change avec MessageFormat 2 ?

MessageFormat 2 (MF2) est la refonte menée par le Consortium Unicode, avec une nouvelle syntaxe : des déclarations comme `.input` et `.match`, et des motifs entre doubles accolades. Sa spécification constitue la [Partie 9 d’Unicode LDML](https://www.unicode.org/reports/tr35/tr35-messageFormat.html), qui a le statut de document stable (certaines fonctions sont encore marquées Draft), et elle est intégrée à ICU4C et ICU4J. Côté JavaScript, la [proposition `Intl.MessageFormat`](https://github.com/tc39/proposal-intl-messageformat) du TC39 n’en est qu’au Stage 1 et ne fait donc pas encore partie du langage ; le paquet `messageformat` 4.x sert de polyfill. Voici à quoi ressemble l’exemple de pluriel en MF2 :

```text
.input {$count :number}
.match $count
0   {{You have no messages.}}
one {{You have {$count} message.}}
*   {{You have {$count} messages.}}
```

Exécuté avec `messageformat` 4.1.0, ce code affiche « You have no messages. », « You have 1 message. » et « You have 1,234 messages. » pour 0, 1 et 1234. Les messages MF2 ne sont pas compatibles avec les chaînes MessageFormat 1, or les autres bibliothèques mentionnées ci-dessus utilisent MessageFormat 1.

## Comment General Translation gère ICU

Dans `gt-react` et `gt-next`, [`useGT`](/docs/react/reference/hooks/use-gt) renvoie une fonction qui prend en paramètres un message ICU et ses valeurs :

```tsx title="Inbox.tsx"
import { useGT } from 'gt-react';

export function Inbox({ count }: { count: number }) {
  const gt = useGT();
  return (
    <p>
      {gt('{count, plural, =0 {You have no messages.} one {You have # message.} other {You have # messages.}}', {
        count,
        $context: 'Unread message count in the inbox',
      })}
    </p>
  );
}
```

[`npx gt translate`](/docs/cli/reference/commands/translate) extrait ces chaînes et génère une traduction pour chaque locale cible, en s&#39;appuyant sur `$context`, votre glossaire et vos instructions personnalisées comme contexte. Dans le paramètre régional source, `gt-react` 11.4.12 affiche les trois mêmes résultats que l&#39;exemple `intl-messageformat` ci-dessus.

* **Dictionnaires.** Les entrées lues via [`useTranslations`](/docs/react/reference/hooks/use-translations) peuvent utiliser le formatage ICU, par exemple `{dollars, number, ::currency/USD}`.
* **Catalogues JSON existants.** La CLI détecte next-intl et i18next (y compris `i18next-icu`) à partir de `package.json` et traduit leurs fichiers JSON en conservant la syntaxe propre à chaque bibliothèque. (Voir [Fichiers JSON](/docs/cli/reference/formats/json-files).)
* **Formatage sans traduction.** La fonction [`formatMessage`](/docs/platform/core/reference/utility-functions/formatting/format-message) de la bibliothèque Core formate un message ICU pour un paramètre régional donné.
* **Linting.** La règle `static-string` de `@generaltranslation/react-core-linter` signale les messages ICU mal formés. (Voir [Règles de lint](/docs/react/reference/lint-rules#static-string).)

Les API n&#39;analysent pas toutes la syntaxe ICU : la fonction [`tx`](/docs/node/reference/functions/tx) de `gt-node` traite les accolades comme du texte littéral. En JSX, [`<Plural>`](/docs/react/reference/components/plural) et [`<Branch>`](/docs/react/reference/components/branch) placés dans [`<T>`](/docs/react/reference/components/t) couvrent les mêmes cas de pluriel et de sélection, sans qu&#39;il soit nécessaire d&#39;écrire la syntaxe à la main.

## Points clés

* Le format de message ICU regroupe les variables, `plural`, `select`, `selectordinal` et `offset` dans une seule chaîne traduisible, avec `#` pour le nombre formaté et des correspondances exactes de type `=0`.
* Les catégories de pluriel sont définies par le CLDR : l&#39;anglais compte 2 formes cardinales, le polonais et le russe 4, l&#39;arabe 6 et le japonais 1 ; les traductions doivent donc ajouter ou supprimer des branches.
* Rédigez des phrases complètes dans chaque branche, incluez toujours `other` et validez la syntaxe avant tout passage en production.
* MessageFormat 2 est une spécification Unicode stable, intégrée à ICU4C et ICU4J, mais `Intl.MessageFormat` n&#39;est encore qu&#39;une proposition TC39 au stade 1.
* Le hook [`useGT`](/docs/react/reference/hooks/use-gt) de General Translation accepte les chaînes ICU dans `gt-react` et `gt-next`, et [`npx gt translate`](/docs/cli/reference/commands/translate) génère les traductions.

## Related questions

- [Comment gérer les formes plurielles dans React ?](https://generaltranslation.com/fr/kb/how-to-handle-plurals-in-react.mdx): Pour gérer les formes plurielles dans React, fournissez à chaque langue une phrase par forme du pluriel et sélectionnez-la selon les règles de pluriel de cette langue, car l’anglais compte 2 formes, le russe 4 et l’arabe 6. Le composant `<Plural>` de General Translation, disponible dans gt-react et gt-next, prend vos formes source, et General Translation génère les formes requises par chaque langue cible.
- [Alternatives à react-intl : General Translation ou react-intl](https://generaltranslation.com/fr/kb/general-translation-vs-react-intl.mdx): General Translation permet aux équipes React de conserver la syntaxe de messages ICU tout en y ajoutant la génération de traductions, une terminologie partagée et la relecture dans le tableau de bord. react-intl fournit le formatage et l’outillage de catalogues FormatJS ; General Translation produit en plus les traductions.
- [Comment traduire des fichiers JSON i18n ?](https://generaltranslation.com/fr/kb/translate-json-files.mdx): Traduisez uniquement les valeurs de type chaîne de caractères d’un fichier JSON de paramètres régionaux. Conservez telles quelles les clés non plurielles, les espaces réservés comme {{name}} et les balises, mais attendez-vous à ce que les clés de pluriel varient selon la langue : le polonais exige inbox_few et inbox_many. Utilisez un outil ou une API qui prend en charge le format, puis analysez et validez le résultat avant la relecture.
- [Alternatives à i18next : General Translation ou i18next](https://generaltranslation.com/fr/kb/general-translation-vs-i18next.mdx): Choisissez General Translation pour conserver vos textes directement dans vos composants React et générer des traductions en tirant parti de leur structure JSX et du contexte de votre produit. Vous pouvez aussi conserver i18next et utiliser General Translation pour traduire vos catalogues existants. i18next assure le rendu des messages et la sélection des formes plurielles ; la génération des traductions relève d’un service distinct.
- [Comment nommer les clés de traduction i18n ?](https://generaltranslation.com/fr/kb/i18n-key-naming.mdx): Nommez les clés selon l’endroit où le texte apparaît et ce qu’il signifie, par exemple checkout.summary.title, et non selon sa formulation anglaise. Attribuez une clé distincte à chaque usage, même si le texte anglais est identique : en allemand, le bouton Open se traduit par Öffnen, alors que l’état Open se traduit par Offen.

## Previous and next questions

- Previous question: [Qu’est-ce que la pseudo-localisation ?](https://generaltranslation.com/fr/kb/pseudo-localization.mdx)
- Next question: [Redirections linguistiques et SEO : URL, cookie ou Accept-Language ?](https://generaltranslation.com/fr/kb/locale-routing-seo.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/fr/kb/sitemap.md) for every article.
