# General Translation Knowledge Base: Che cos'è l'ICU formato dei messaggi?
URL: https://generaltranslation.com/it/kb/icu-message-format.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: L'ICU formato dei messaggi è una sintassi che permette a una singola stringa traducibile di contenere variabili, plurali, scelte select e ordinali, come {count, plural, one {# file} other {# files}}. Ogni lingua usa le categorie di plurale CLDR di cui ha bisogno: l'inglese usa one e other, mentre il polacco aggiunge few e many.
Category: Formattazione per impostazione regionale
Last updated: 2026-10-20
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

La sintassi deriva dalla classe MessageFormat di ICU (International Components for Unicode), le librerie di internazionalizzazione dell&#39;Unicode Consortium per C/C++ e Java. Librerie JavaScript come FormatJS implementano la stessa grammatica. Oggi è nota anche come MessageFormat 1, dato che ne esiste una versione riprogettata, MessageFormat 2.

## Quale problema risolve l&#39;ICU formato dei messaggi?

Il codice che costruisce le frasi assemblando frammenti funziona in inglese, ma si rompe nelle altre lingue. `'You have ' + n + ' files'` vincola il codice all&#39;ordine delle parole dell&#39;inglese e alle sue due forme plurali. Il polacco richiede quattro forme per la stessa frase: 1 plik, 2 pliki, 5 plików e 1,5 pliku. In molte lingue una frase marcata per genere (&quot;She replied&quot; o &quot;He replied&quot;) modifica anche altre parole, e gli ordinali (1°, 2°, 3°) seguono regole proprie.

L&#39;ICU formato dei messaggi riunisce tutti questi casi in un&#39;unica stringa. Il traduttore vede l&#39;intera frase con tutti i branch, la riscrive per la propria lingua e aggiunge o rimuove branch secondo quanto richiesto dalla grammatica. Per lo stesso motivo, la [guida utente di ICU](https://unicode-org.github.io/icu/userguide/format_parse/messages/) consiglia di scrivere una frase completa in ogni branch: un traduttore non può correggere la grammatica di un frammento che non vede.

## La sintassi, con esempi eseguibili

Tutti gli esempi seguenti sono stati eseguiti con [`intl-messageformat`](https://formatjs.github.io/docs/intl-messageformat) 12.1.4 di FormatJS su Node.js 24. Un messaggio viene analizzato una sola volta e poi formattato con dei valori:

```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.'
```

### Argomenti

`{name}` inserisce un valore: `Hello, {name}!` con `{ name: 'Ada' }` restituisce &quot;Hello, Ada!&quot;. Gli argomenti tipizzati formattano il valore in base all&#39;impostazione regionale: ad esempio, in inglese `Total: {price, number, ::currency/EUR}` con `1234.5` restituisce &quot;Total: €1,234.50&quot;.

### plural, `#` e corrispondenze esatte

`{count, plural, ...}` seleziona un branch in base alla categoria di plurale dell&#39;impostazione regionale: `zero`, `one`, `two`, `few`, `many` o `other`. All&#39;interno di un branch, `#` rappresenta il numero, formattato secondo l&#39;impostazione regionale; il messaggio tedesco `{count, plural, one {Sie haben # Nachricht.} other {Sie haben # Nachrichten.}}` stampa &quot;Sie haben 1.234 Nachrichten.&quot; Una corrispondenza esatta come `=0` ha la precedenza sulla categoria: è così che l&#39;esempio precedente mostra &quot;no messages&quot; anziché &quot;0 messages&quot;.

La stessa frase in polacco, con i branch previsti dal polacco:

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

Con `pl`, questo formatta 1, 2, 5, 22 e 1.5 rispettivamente come &quot;1 plik&quot;, &quot;2 pliki&quot;, &quot;5 plików&quot;, &quot;22 pliki&quot; e &quot;1,5 pliku&quot;.

### select

`select` sceglie un branch in base al valore di una stringa, mentre il branch `other` gestisce tutti gli altri casi:

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

`{ gender: 'female' }` restituisce &quot;She replied to your comment.&quot; e `{ gender: 'nonbinary' }` restituisce &quot;They replied to your comment.&quot; Mantieni la frase completa all&#39;interno di ogni branch: in un&#39;altra lingua il genere può influire non solo sul pronome, ma anche sul verbo.

### selectordinal

`selectordinal` usa le regole degli ordinali, che in inglese prevedono quattro categorie:

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

Per le posizioni 1, 2 e 11, gli output sono `You finished 1st.`, `You finished 2nd.` e `You finished 11th.` I suffissi per 3, 4, 22 e 103 sono rispettivamente `rd`, `th`, `nd` e `rd`.

### offset

`offset:1` sottrae uno dal numero prima di scegliere la categoria e di stampare `#`, ed è quindi ideale per messaggi del tipo &quot;tu e altri N&quot;. Le corrispondenze esatte vengono invece confrontate con il valore originale:

```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.}}
```

Con `host: 'Mia'`, 0, 1, 2 e 5 ospiti restituiscono rispettivamente &quot;Nobody is going.&quot;, &quot;Mia is going.&quot;, &quot;Mia and 1 other person are going.&quot; e &quot;Mia and 4 other people are going.&quot;

### Argomenti annidati

Gli argomenti possono essere annidati. La guida ICU consiglia di mettere `select` all&#39;esterno e `plural` all&#39;interno, con una frase completa in ciascun branch:

```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}}}}
```

### Apostrofi ed escape

Un apostrofo ASCII serve a citare (quoting) i caratteri di sintassi, mentre due apostrofi consecutivi ne producono uno. A partire da ICU 4.8, un apostrofo singolo apre una sezione di testo citato solo quando precede immediatamente un carattere che richiede il quoting, perciò le normali elisioni e contrazioni funzionano senza problemi:

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

Con `{ name: 'Ada' }`, l&#39;output è `It's Ada's turn. Type {name} to insert a name. I'm here.` All&#39;interno di un plurale, `'#'` produce un `#` letterale. La [guida alla sintassi ICU](https://formatjs.github.io/docs/core-concepts/icu-syntax) di FormatJS consiglia di usare l&#39;apostrofo tipografico (’) nel testo leggibile da persone, evitando così il problema alla radice.

## Cosa sono le categorie di plurale CLDR?

Le categorie provengono dalle [regole del plurale di Unicode CLDR](https://cldr.unicode.org/index/cldr-spec/plural-rules), gli stessi dati su cui si basa `Intl.PluralRules` di JavaScript. Ecco cosa restituisce `Intl.PluralRules` per alcune lingue:

| Lingua                       | Categorie cardinali                          |
| ---------------------------- | -------------------------------------------- |
| Inglese (`en`)               | `one`, `other`                               |
| Polacco (`pl`), russo (`ru`) | `one`, `few`, `many`, `other`                |
| Arabo (`ar`)                 | `zero`, `one`, `two`, `few`, `many`, `other` |
| Giapponese (`ja`)            | `other`                                      |

`one` non corrisponde esattamente a 1: in russo, ad esempio, anche 21 rientra in `one`. Usa `=1` solo quando ti riferisci proprio al numero 1. Per l&#39;equivalente a livello di componente in React, consulta [Come gestisco i plurali in React?](/kb/how-to-handle-plurals-in-react).

## Problemi comuni

* **Gli errori di sintassi emergono tardi.** Una parentesi graffa mancante resta una semplice stringa finché non viene analizzata, e a quel punto `intl-messageformat` solleva l&#39;eccezione `EXPECT_ARGUMENT_CLOSING_BRACE`. Esegui il parsing o il lint dei messaggi in CI, oppure precompilali.
* **Manca il branch `other`.** `intl-messageformat` solleva l&#39;eccezione `MISSING_OTHER_CLAUSE` per un plurale senza `other`, e FormatJS lo richiede anche per `select`.
* **Branch non adatti alla lingua di destinazione.** Un messaggio in inglese ha `one` e `other`; la traduzione polacca richiede anche `few` e `many`, mentre quella giapponese solo `other`. Il processo di traduzione deve aggiungere e rimuovere branch, non limitarsi a tradurre il testo al loro interno.
* **Frammenti.** `{count} {count, plural, one {file} other {files}} deleted` lascia ai traduttori dei pezzi da riordinare. Inserisci l&#39;intera frase in ogni branch.
* **Dialetti misti.** La sintassi predefinita di i18next è `{{name}}`, con chiavi plurali come `key_one`, non ICU. I team che vogliono usare ICU con i18next aggiungono il plugin [`i18next-icu`](https://github.com/i18next/i18next-icu).

## Quali librerie supportano l&#39;ICU formato dei messaggi?

* **ICU4J e ICU4C** sono le implementazioni di riferimento, rispettivamente in Java e in C/C++.
* **FormatJS**: [`intl-messageformat`](https://formatjs.github.io/docs/intl-messageformat) è il parser e formatter su cui si basa react-intl, con skeleton per numeri e date come `::currency/EUR` e tag per il rich text. (Vedi [General Translation vs. react-intl](/kb/general-translation-vs-react-intl).)
* **messageformat**: [`@messageformat/core`](https://messageformat.github.io/messageformat/) compila i messaggi ICU in funzioni JavaScript; la versione 4 del pacchetto `messageformat`, invece, implementa MessageFormat 2.
* **i18next-icu**: il plugin di i18next, basato su `intl-messageformat`, che fa adottare a i18next la sintassi ICU.
* **Lingui**: le sue [macro](https://lingui.dev/ref/macro) trasformano JSX e tagged template in messaggi ICU MessageFormat in fase di compilazione.
* **next-intl**: i suoi [messaggi usano la sintassi ICU](https://next-intl.dev/docs/usage/messages).

## Cosa cambia in MessageFormat 2?

MessageFormat 2 (MF2) è la versione riprogettata dall&#39;Unicode Consortium, con una nuova sintassi: dichiarazioni come `.input` e `.match` e modelli racchiusi tra doppie parentesi graffe. La specifica è la [Parte 9 di Unicode LDML](https://www.unicode.org/reports/tr35/tr35-messageFormat.html), contrassegnata come documento stabile (alcune funzioni sono ancora indicate come Draft), ed è integrata in ICU4C e ICU4J. In JavaScript, la [proposta `Intl.MessageFormat`](https://github.com/tc39/proposal-intl-messageformat) del TC39 è allo Stage 1, quindi non fa ancora parte del linguaggio; il pacchetto `messageformat` 4.x è un polyfill. Ecco l&#39;esempio del plurale in MF2:

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

Se eseguito con `messageformat` 4.1.0, stampa &quot;You have no messages.&quot;, &quot;You have 1 message.&quot; e &quot;You have 1,234 messages.&quot; rispettivamente per 0, 1 e 1234. I messaggi MF2 non sono compatibili con le stringhe MessageFormat 1, mentre le altre librerie citate sopra leggono MessageFormat 1.

## Come General Translation gestisce ICU

In `gt-react` e `gt-next`, [`useGT`](/docs/react/reference/hooks/use-gt) restituisce una funzione che accetta un messaggio ICU e i relativi valori:

```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) estrae queste stringhe e genera una traduzione per ogni impostazione regionale di destinazione, usando come contesto `$context`, il tuo Glossario e i prompt personalizzati. Nella locale di origine, `gt-react` 11.4.12 stampa gli stessi tre output dell&#39;esempio con `intl-messageformat` visto sopra.

* **Dizionari.** Le voci lette tramite [`useTranslations`](/docs/react/reference/hooks/use-translations) possono usare la formattazione ICU, ad esempio `{dollars, number, ::currency/USD}`.
* **Cataloghi JSON esistenti.** La CLI rileva next-intl e i18next (incluso `i18next-icu`) da `package.json` e ne traduce i file JSON mantenendo la sintassi della libreria. (Vedi [File JSON](/docs/cli/reference/formats/json-files).)
* **Formattazione senza traduzione.** La funzione [`formatMessage`](/docs/platform/core/reference/utility-functions/formatting/format-message) della libreria Core formatta un messaggio ICU per una determinata impostazione regionale.
* **Linting.** La regola `static-string` di `@generaltranslation/react-core-linter` segnala i messaggi ICU non validi. (Vedi [Regole di lint](/docs/react/reference/lint-rules#static-string).)

Non tutte le API interpretano la sintassi ICU: la funzione [`tx`](/docs/node/reference/functions/tx) di `gt-node` tratta le parentesi graffe come testo letterale. In JSX, [`<Plural>`](/docs/react/reference/components/plural) e [`<Branch>`](/docs/react/reference/components/branch) all&#39;interno di [`<T>`](/docs/react/reference/components/t) gestiscono gli stessi casi di plurale e selezione senza bisogno di scrivere la sintassi a mano.

## Punti chiave

* L&#39;ICU formato dei messaggi racchiude variabili, `plural`, `select`, `selectordinal` e `offset` in un&#39;unica stringa traducibile, con `#` per il numero formattato e corrispondenze esatte come `=0`.
* Le categorie di plurale sono definite da CLDR: l&#39;inglese ha 2 forme cardinali, il polacco e il russo 4, l&#39;arabo 6 e il giapponese 1, quindi nelle traduzioni occorre aggiungere o eliminare branch.
* Scrivi frasi complete in ogni branch, includi sempre `other` e valida la sintassi prima che arrivi in produzione.
* MessageFormat 2 è una specifica Unicode stabile, integrata in ICU4C e ICU4J, ma `Intl.MessageFormat` è ancora una proposta TC39 in Stage 1.
* [`useGT`](/docs/react/reference/hooks/use-gt) di General Translation accetta stringhe ICU in `gt-react` e `gt-next`, mentre [`npx gt translate`](/docs/cli/reference/commands/translate) genera le traduzioni.

## Related questions

- [Come si gestiscono i plurali in React?](https://generaltranslation.com/it/kb/how-to-handle-plurals-in-react.mdx): Per gestire i plurali in React, fornisci per ogni lingua una frase per ciascuna forma plurale e scegli quella corretta in base alle regole del plurale di quella lingua, dato che l'inglese ha 2 forme, il russo 4 e l'arabo 6. Il componente `<Plural>` di General Translation in gt-react e gt-next accetta le tue forme sorgente, e General Translation genera le forme necessarie per ogni lingua di destinazione.
- [Alternative a react-intl: General Translation o react-intl](https://generaltranslation.com/it/kb/general-translation-vs-react-intl.mdx): General Translation consente ai team React di mantenere la sintassi dei messaggi ICU, aggiungendo la generazione delle traduzioni, una terminologia condivisa e la revisione nella Dashboard. react-intl fornisce la formattazione e gli strumenti di FormatJS per la gestione dei cataloghi; General Translation, invece, produce anche le traduzioni.
- [Come si traducono i file JSON di i18n?](https://generaltranslation.com/it/kb/translate-json-files.mdx): Traduci solo i valori stringa di un file JSON di impostazione regionale. Lascia invariati le chiavi non plurali, i segnaposto come {{name}} e i tag, ma tieni presente che le chiavi plurali cambiano da una lingua all'altra: il polacco, ad esempio, richiede inbox_few e inbox_many. Usa uno strumento o un'API in grado di gestire il formato, quindi esegui il parsing dell'output e validalo prima della revisione.
- [Alternative a i18next: General Translation vs. i18next](https://generaltranslation.com/it/kb/general-translation-vs-i18next.mdx): Scegli General Translation per mantenere i testi inline nei componenti React e generare le traduzioni sfruttando la struttura JSX e il contesto del prodotto. In alternativa, puoi continuare a usare i18next e affidarti a General Translation per tradurre i cataloghi esistenti. i18next si occupa del rendering dei messaggi e della selezione dei plurali, mentre la generazione delle traduzioni è affidata a un servizio separato.
- [Come assegnare i nomi alle chiavi di traduzione i18n?](https://generaltranslation.com/it/kb/i18n-key-naming.mdx): Assegna i nomi alle chiavi in base a dove compare il testo e a cosa significa, ad esempio checkout.summary.title, e non in base alla formulazione inglese. Dai a ogni uso distinto una chiave propria, anche quando il testo inglese è identico: in tedesco il pulsante Open diventa Öffnen, mentre lo stato Open diventa Offen.

## Previous and next questions

- Previous question: [Che cos'è hreflang e come si configura?](https://generaltranslation.com/it/kb/what-is-hreflang.mdx)
- Next question: [Che cos'è la pseudo-localizzazione?](https://generaltranslation.com/it/kb/pseudo-localization.mdx)

## Sitemap

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