ICU MessageFormat è uno standard Unicode per scrivere un’unica stringa traducibile che si adatta a quantità, genere e altre variabili. È ancora difficile da tradurre perché la sintassi è stata progettata per il codice, non per chi localizza. La specifica esiste da ben più di dieci anni e a rompersi più spesso sono i traduttori non tecnici davanti a parentesi graffe annidate. globalize.now è un’infrastruttura di localizzazione basata su IA che si colloca un livello sotto questo problema: estrae le stringhe e genera i file di traduzione in cui vivono questi pattern ICU, poi li mantiene sincronizzati a ogni push su Git.
Cos’è ICU MessageFormat?
ICU MessageFormat è una sintassi per esprimere un messaggio la cui formulazione finale dipende dai dati disponibili a runtime. Invece di concatenare frammenti nel codice, scrivi un unico pattern e lasci che il formatter scelga il ramo corretto per ogni locale.
L’uso più comune è la gestione dei plurali:
{count, plural,
one {You have # message}
other {You have # messages}
}
# viene sostituito dal numero, mentre i rami one / other corrispondono alle categorie di plurale di una lingua. L’inglese ne ha due; il polacco, il russo e l’arabo ne hanno di più. ICU gestisce anche il genere e altre scelte tramite select:
{gender, select,
male {He liked your post}
female {She liked your post}
other {They liked your post}
}
Ecco perché ICU è diventato lo standard de facto per i plurali: sposta la complessità grammaticale nei dati, che possono variare da una lingua all’altra, invece di inserirla in una logica condizionale che funziona solo nella lingua per cui è stata scritta. Le librerie runtime come FormatJS, i18next e next-intl lo supportano tutte.
Perché ICU MessageFormat è così difficile da tradurre?
È difficile da tradurre perché la sintassi è stata costruita per gli sviluppatori, mentre chi traduce davvero le stringhe di solito non è uno sviluppatore.
Aprendo un file di traduzione, un traduttore non vede «Hai 3 messaggi». Vede parentesi graffe, le parole chiave plural e select, categorie di plurale che potrebbe non riconoscere e un placeholder # che sembra un errore di battitura. Basta eliminare una parentesi o rinominare una categoria perché la stringa generi un errore a runtime invece di essere renderizzata. La struttura che rende ICU potente per gli ingegneri è la stessa che lo rende fragile nelle mani di un linguista.
È il divario con cui il settore della localizzazione convive in silenzio da anni. La maggior parte dei tool lo gestisce mostrando il pattern grezzo e sperando che il traduttore non tocchi il carattere sbagliato, oppure nascondendo le forme plurali dietro un editor separato che richiede comunque di capire le categorie di plurale. Nessun vendor ha colmato del tutto la distanza tra la complessità della specifica e il modello mentale di un traduttore non tecnico.
Cosa è cambiato con MessageFormat 2.0?
MessageFormat 2.0 è una riprogettazione completa della sintassi e nel 2025 è diventato uno standard stabile, non più una bozza.
MF2 ha raggiunto lo stato di Final Candidate a marzo 2025 e ora è una parte stabile di CLDR, pubblicata come parte dello standard tecnico Unicode LDML e perfezionata nelle release LDML 47 e 48. L’implementazione di riferimento segue la specifica della versione LDML 48.2, rilasciata all’inizio del 2026. La nuova sintassi separa gli input dalla logica di matching e supporta funzioni di formattazione con nome, rendendo più leggibili i messaggi complessi:
.input {$count :number}
.match $count
one {{You have {$count} message}}
* {{You have {$count} messages}}
L’obiettivo è un pattern più facile da estendere e leggermente meno ostile da leggere rispetto alle parentesi graffe annidate originali.
MessageFormat 2.0 risolve il problema dei traduttori?
Non ancora, per due motivi.
Primo, MF2 migliora l’ergonomia della sintassi, ma resta una sintassi. Un traduttore incontra ancora .match, chiavi di plurale e parentesi graffe. Il carico cognitivo è inferiore rispetto a MF1, ma non è scomparso, e un traduttore non tecnico può ancora rompere un messaggio modificando il token sbagliato.
Secondo, quasi nessuno lo usa in produzione. L’adozione resta limitata ancora per buona parte del 2026: il processo TC39 per la parte JavaScript richiede circa una dozzina di organizzazioni che usino MF2 in produzione prima di procedere, e questa soglia non è stata raggiunta. In pratica, la maggior parte delle app che rilasci oggi usa ancora l’ICU MessageFormat originale tramite librerie come FormatJS e i18next. Quindi il problema dal punto di vista del traduttore non si risolve con una specifica: si risolve decidendo dove la sintassi viene prodotta e mantenuta.
Dove si rompe ICU MessageFormat nelle app generate dall’IA?
Si rompe presto, perché i tool di coding basati su IA raramente producono ICU corretto al primo tentativo.
Quando costruisci con Cursor, Claude Code o Lovable, il codice generato tende a gestire le quantità nel modo più ingenuo:
// What an AI coding tool often generates
const label = count + " " + (count === 1 ? "message" : "messages");
Quella logica è corretta per l’inglese e sbagliata per la maggior parte delle altre lingue, perché presume esattamente due forme di plurale. Inoltre incorpora la frase nel codice dell’applicazione, quindi in un file di traduzione non esiste alcun pattern ICU da localizzare. La stringa resta invisibile al livello di localizzazione finché qualcuno non nota la grammatica errata in produzione. I tool di IA duplicano anche le chiavi e disseminano testo hardcoded nei componenti, quindi persino i team che vogliono usare ICU finiscono con stringhe che non sono mai entrate in un file traducibile. La panoramica per sviluppatori di globalize.now è progettata proprio per intercettare questa classe di stringhe prima del rilascio.
Come dovrebbero gestire ICU MessageFormat gli sviluppatori nel 2026?
Tratta ICU come infrastruttura generata, non come contenuto scritto a mano.
La regola pratica è questa: gli sviluppatori e i tool di IA non dovrebbero scrivere concatenazioni di plurali nel codice, e i traduttori non dovrebbero modificare a mano le parentesi graffe ICU grezze. Il pattern ICU deve vivere in un file di traduzione prodotto e mantenuto aggiornato automaticamente, poi renderizzato a runtime da una libreria come FormatJS, i18next o next-intl. In questo modo la sintassi resta corretta nel punto in cui viene creata e coerente in ogni lingua mentre l’app cambia. Se stai valutando come inserire ICU rispetto al tuo runtime, il confronto tra globalize.now e i18next spiega come infrastruttura e runtime si dividono il lavoro.
Questo è il livello su cui opera globalize.now. Estrae le stringhe hardcoded dalla tua codebase, genera le chiavi e i file di traduzione che contengono i pattern ICU e li sincronizza di nuovo a ogni push su Git, così la struttura resta corretta senza un passaggio di export manuale. Non vuole sostituirsi all’editor del traduttore né alla tua libreria runtime: si assicura che i file con struttura ICU da cui dipendono questi strumenti esistano davvero e restino sincronizzati. La guida per vibe coder mostra la stessa configurazione per app create con Lovable, Bolt e Replit; il workflow completo è sulla homepage di globalize.now.
globalize.now trasforma il testo hardcoded dell'app in file di localizzazione pronti e li mantiene aggiornati mentre rilasci.
Prova globalize.now gratis