Pose una domanda e ottieni un riassunto del documento facendo riferimento a questa pagina e al provider AI di tua scelta
Il contenuto di questa pagina è stato tradotto con un'IA.
Vedi l'ultima versione del contenuto originale in ingleseSe hai un’idea per migliorare questa documentazione, non esitare a contribuire inviando una pull request su GitHub.
Collegamento GitHub alla documentazioneCopia il Markdown del documento nella porta-documenti
Formato dei Messaggi ICU: la sintassi e i punti critici
ICU MessageFormat è una sintassi di stringhe che consente a una traduzione di contenere la propria logica condizionale: plurali, forme di genere, formattazione di numeri e date. Esiste perché la grammatica appartiene al traduttore, non allo sviluppatore che scrive if (count === 1). Questo articolo esamina la sintassi, le peculiarità linguistiche che mandano in crisi le implementazioni superficiali e il modo in cui l'ecosistema JS gestisce queste sfide.
Indice
Il problema, concretamente
Ecco il codice che quasi tutti scrivono all'inizio:
Copiare il codice nella clipboard
Questo approccio funziona in inglese ma si rivela fallimentare in quasi tutte le altre lingue:
- Il russo e il polacco necessitano di tre o quattro forme, non due.
- Il giapponese ne richiede solo una, e lo spazio concatenato è errato.
- L'arabo ne richiede sei, e il numero stesso dovrebbe essere formattato secondo il sistema numerico locale.
- Il francese inserisce uno spazio unificatore prima di determinati segni di punteggiatura, che la concatenazione
+ " "distrugge.
Il problema strutturale è che la frase è stata spezzata in frammenti isolati. Un traduttore vede item e items senza contesto e senza alcuna possibilità di riorganizzare l'ordine delle parole. ICU MessageFormat risolve il problema mantenendo l'intera frase in un'unica stringa traducibile e fornendo al traduttore gli operatori logici necessari.
Argomenti semplici
L'unità fondamentale è un segnaposto racchiuso tra parentesi graffe singole:
Copiare il codice nella clipboard
Passando { name: "Alice" } durante la formattazione si ottiene Hello, Alice!. Le parentesi graffe sono gli unici caratteri speciali. Per visualizzare una parentesi graffa letterale, è sufficiente racchiuderla tra apici singoli: '{'.
Questa è l'intera funzionalità di interpolazione. Tutto il resto in ICU è costruito su questa base.
Plurale
plural seleziona un ramo in base a un valore numerico:
Copiare il codice nella clipboard
Tre elementi fondamentali da comprendere:
#viene sostituito dal valore formattato dicountsecondo la lingua attiva. Quindi1234diventa1,234inen-USe1.234init-IT.otherè obbligatorio. Qualsiasi implementazione ICU restituirà un errore o fallirà la validazione se manca. È il valore di fallback quando nessuna categoria corrisponde.=0,=1, … corrispondono a valori numerici esatti e vengono valutati prima delle categorie CLDR. Vanno usati per diciture speciali ("Nessun messaggio"), non in sostituzione dione.
Copiare il codice nella clipboard
offset
offset:n sottrae n dal valore prima sia della selezione della categoria sia della sostituzione di #. Viene utilizzato per pattern come "Alice e altre 3 persone hanno apprezzato questo post":
Copiare il codice nella clipboard
Con count: 4, # restituirà 3. L'opzione offset è molto utile ma non sempre supportata in modo uniforme da tutti i runtime. Verificate la compatibilità prima di utilizzarla.
Le categorie dei plurali dipendono dalla lingua
Questo è l'aspetto su cui si generano più equivoci. Le etichette zero, one, two, few, many, other non sono contenitori universali validi per ogni lingua. Ogni locale utilizza un sottoinsieme, regolato dalle regole dei plurali CLDR, e tali regole sono grammaticali, non puramente intuitive.
Apri la tabella in una finestra modale per visualizzare tutti i dati in modo chiaro
| Lingua | Tag | Categorie utilizzate | Totale |
|---|---|---|---|
| Giapponese | ja | other | 1 |
| Cinese | zh | other | 1 |
| Inglese | en | one, other | 2 |
| Tedesco | de | one, other | 2 |
| Francese | fr | one, many, other | 3 |
| Ceco | cs | one, few, many, other | 4 |
| Polacco | pl | one, few, many, other | 4 |
| Russo | ru | one, few, many, other | 4 |
| Arabo | ar | zero, one, two, few, many, other | 6 |
| Gallese | cy | zero, one, two, few, many, other | 6 |
Due conseguenze che spesso sorprendono:
onenon significa necessariamente "1". In russo,onecopre 1, 21, 31, 101: ogni numero che termina per 1, esclusi quelli che terminano per 11. In francese, anche0rientra inone.- Aggiungere una categoria alla stringa sorgente inglese non produce alcun effetto. Il messaggio in inglese necessita solo di
oneeother. La traduzione polacca richiede quattro rami, e tale struttura appartiene alla stringa polacca, non a quella inglese. Qualsiasi formato che obblighi tutte le lingue ad avere la stessa struttura di chiavi creerà conflitti.
È possibile verificare il comportamento effettivo del runtime senza installare nulla:
Copiare il codice nella clipboard
Intl.PluralRules include i dati CLDR in tutti i browser moderni e in Node. Una libreria che dichiara la compatibilità CLDR richiama quasi sempre questa API sottostante.
select e selectordinal
select permette di creare rami basati su una stringa arbitraria: un genere, un ruolo, uno stato o un piano di abbonamento.
Copiare il codice nella clipboard
Le chiavi vengono confrontate letteralmente e other è obbligatorio anche in questo caso. select è lo strumento adatto ogni volta che la sintassi di una frase dipende da un'enumerazione, poiché le lingue divergono sulle categorie che influenzano la grammatica.
selectordinal condivide la stessa struttura di plural, ma fa riferimento alle regole dei plurali ordinali, definite in una tabella diversa da quella dei cardinali:
Copiare il codice nella clipboard
L'inglese impiega quattro categorie ordinali (1st, 2nd, 3rd, 4th) nonostante utilizzi solo due categorie cardinali. Questa asimmetria spiega perché i due operatori siano tenuti separati.
Argomenti di numeri, date e ore
ICU è in grado di formattare direttamente i valori che interpola:
Copiare il codice nella clipboard
Lo standard contemporaneo è rappresentato dagli skeletons, introdotti con ICU 60 e contrassegnati dal prefisso ::. Gli skeletons sono molto più espressivi rispetto agli stili tradizionali:
Copiare il codice nella clipboard
Il supporto per gli skeletons varia tra i diversi strumenti. FormatJS li implementa integralmente, mentre altri runtime accettano solo i formati storici number, currency o date, long. Verificate la compatibilità nel vostro ambiente prima del rilascio in produzione.
Nidificazione e leggibilità
ICU è componibile. Un ramo di plurale può contenere un select, che a sua volta può contenere un altro plurale:
Copiare il codice nella clipboard
Questo è l'esempio classico di ICU, ma anche l'argomentazione principale contro un annidamento eccessivo. Già a partire dal secondo livello, i traduttori rischiano di commettere errori con le parentesi graffe e gli editor TMS faticano a fornire assistenza. È consigliabile non superare due livelli di annidamento; qualora ne servisse un terzo, dividete la frase in due messaggi distinti.
Supporto di ICU nelle librerie JavaScript
Apri la tabella in una finestra modale per visualizzare tutti i dati in modo chiaro
| Libreria | Supporto ICU | Cosa si scrive concretamente |
|---|---|---|
| react-intl (FormatJS) | Nativo, completo | Stringhe ICU, inclusi skeletons e tag rich-text |
| next-intl | Nativo | Stringhe ICU, tramite intl-messageformat di FormatJS |
| i18next | Richiede plugin | Suffissi di chiave key_one / key_other e {{name}}; ICU via i18next-icu |
| vue-i18n | Parziale / proprietario | Interpolazione {name} e rami plurali separati da pipe |
Angular ($localize) | Sottoinsieme | ICU plural / select nei template, esportati in XLIFF |
Alcune precisazioni per una corretta interpretazione della tabella:
- La sintassi di default di i18next non è ICU, senza che questo sia uno svantaggio. I suffissi (
item_one,item_few) corrispondono alle categorie diIntl.PluralRulese risultano spesso più facili da gestire in file JSON lineari. Tuttavia,selecte i rami annidati non sono integrati nativamente, obbligando all'uso dii18next-icuo alla gestione della logica nel codice applicativo. - I plurali a barre di vue-i18n utilizzano per impostazione predefinita una funzione per locale anziché le categorie CLDR. Il sistema funziona, ma la regola risiede nella configurazione dell'app anziché nei dati.
- FormatJS è l'implementazione di riferimento in JS. Quando in ambito JavaScript si parla di "ICU MessageFormat", ci si riferisce quasi sempre alla specifica adottata da FormatJS.
- Il supporto completo a ICU ha un costo sul bundle. Il parser e la gestione degli skeleton aggiungono circa 10 KB di JavaScript compresso. Scopri perché ICU non è fatto per JavaScript.
L'approccio di Intlayer
Intlayer non si affida a un DSL basato su stringhe. Gli operatori di ramificazione sono funzioni all'interno di file di dichiarazione di contenuto tipizzati, permettendo a ciascun locale di dichiarare unicamente le categorie richieste dalla propria grammatica:
Copiare il codice nella clipboard
Copiare il codice nella clipboard
La corrispondenza con i concetti ICU è immediata:
Apri la tabella in una finestra modale per visualizzare tutti i dati in modo chiaro
| Costrutto ICU | Intlayer |
|---|---|
{name} | insert("Hello {{name}}"), o rilevamento automatico |
{count, plural, …} | plural({ one, few, many, other }) |
{value, select, …} | select({ draft, published, fallback }) |
ramo di genere in select | gender({ male, female, fallback }) |
ramo booleano in select | cond({ true, false }) |
| intervalli numerici (non-CLDR) | enu({ "0": …, ">5": …, fallback: … }) |
{n, number, ::currency/EUR} | useCurrency()(1234.5, { currency: "EUR" }) |
plural delega la selezione delle categorie a Intl.PluralRules, garantendo la piena applicazione della tabella CLDR sopra indicata. La formattazione resta separata: numeri, date, valute ed elenchi vengono gestiti tramite gli appositi hook di formattazione anziché essere integrati all'interno della stringa.
Limiti oggettivi:
- Intlayer richiede una fase di compilazione: il compilatore estrae le dichiarazioni in fase di build. Per un modello con caricamento runtime di JSON semplice, la logica è diversa.
pluralnon supporta attualmente unt()annidato all'interno dei suoi rami: si inseriscepluralall'interno dit(), non viceversa.- L'ecosistema è più recente rispetto a quello di i18next, con meno integrazioni TMS pronte all'uso.
Per i progetti che contengono già stringhe ICU, l'adattatore di compatibilità react-intl le analizza direttamente: plural, select, selectordinal, # e i parametri storici number, date, time. Gli skeletons e l'opzione offset: non sono gestiti da questo resolver e richiedono verifica in fase di migrazione. L'adattatore i18next gestisce invece la convenzione a suffissi (key_one, key_male) mediante Intl.PluralRules.
Errori comuni
- Codificare la logica plurale direttamente in JS.
count === 1 ? a : bproduce risultati errati per 8 delle 10 lingue elencate nella tabella precedente. Una volta inserito l'operatore ternario nel codice, nessun traduttore può correggerlo. - Concatenare frammenti tradotti. L'ordine sintattico, gli accordi e la spaziatura attorno alla punteggiatura variano da lingua a lingua. Mantenete sempre la frase nella sua interezza.
- Omettere
other. È un requisito vincolante della specifica, non una convenzione facoltativa. La maggior parte dei parser rifiuterà la stringa, mentre altri non mostreranno nulla. - Dare per scontato che le categorie siano universali. Una frase sorgente inglese con
oneeothernon implica che il file polacco contenga solo due rami. Ogni lingua deve poter dichiarare la propria struttura. Consultate la dichiarazione dei contenuti per lingua. - Usare
=1al posto dione.=1intercetta esclusivamente il numero esatto 1. In russo, 21 richiede la categoriaone, e la regola=1non scatterà mai. - Inserire
#all'esterno di un ramo di plurale. Assume un significato speciale solo all'interno dipluraloselectordinal. In qualsiasi altro punto è un semplice carattere cancelletto. - Dimenticare che
#è già formattato. Se desiderate il numero grezzo senza formattazione numerica locale, interpolate l'argomento per nome.
Risorse utili
Commenti
Ancora nessun commento. Sii il primo a condividere i tuoi pensieri.
