Intl MessageFormat
Questa pagina è stata tradotta da PageTurner AI (beta). Non ufficialmente approvata dal progetto. Hai trovato un errore? Segnala problema →
Formatta stringhe di messaggio ICU con segnaposto per numeri, date, plurali e selezione per creare messaggi localizzati.
Panoramica
Obiettivi
Questo pacchetto fornisce un modo per gestire e formattare i messaggi stringa della tua app JavaScript in stringhe localizzate per gli utenti. Puoi utilizzarlo sia nel browser che su server tramite Node.js.
Questa implementazione si basa sulla proposta Strawman, ma presenta alcune divergenze.
L'API IntlMessageFormat potrebbe cambiare per allinearsi a ECMA-402, ma questo pacchetto seguirà il versionamento semantico.
Funzionamento
I messaggi vengono forniti al costruttore come stringa String o come oggetto AST pre-analizzato.
const msg = new IntlMessageFormat(message, locales, [formats], [opts])
La stringa message viene analizzata e memorizzata internamente in forma compilata, ottimizzata per il metodo format() per produrre la stringa formattata da mostrare all'utente.
const output = msg.format(values)
Esempio Comune d'Uso
Un esempio molto comune è la formattazione di messaggi con numeri ed etichette plurali. Con questo pacchetto puoi assicurarti che la stringa sia formattata correttamente per la lingua dell'utente, ad esempio:
new IntlMessageFormat( `{numPhotos, plural, =0 {You have no photos.} =1 {You have one photo.} other {You have # photos.} }`, 'en-US' ).format({numPhotos: 1000})
new IntlMessageFormat( `{numPhotos, plural, =0 {Usted no tiene fotos.} =1 {Usted tiene una foto.} other {Usted tiene # fotos.} }`, 'es-ES' ).format({numPhotos: 1000})
Sintassi dei Messaggi
La sintassi dei messaggi utilizzata non è proprietaria: è uno standard comune che funziona tra linguaggi di programmazione e noto ai traduttori professionali. Questo pacchetto usa la sintassi ICU Message ed è compatibile con tutte le lingue CLDR che definiscono regole di pluralizzazione.
Caratteristiche
-
Utilizza standard industriali: sintassi ICU Message e dati locali CLDR.
-
Supporta argomenti di messaggio: plural, select e selectordinal.
-
Formatta numeri e date/orari nei messaggi usando rispettivamente
Intl.NumberFormateIntl.DateTimeFormat. -
Ottimizzato per chiamate ripetute al metodo
format()di un'istanzaIntlMessageFormat. -
Supporta la definizione di stili/opzioni di formattazione personalizzati.
-
Supporta sequenze di escape per caratteri sintattici, es:
"'{foo}'"produrrà"{foo}"invece di interpretarlo come argomentofoo.
Utilizzo
Dipendenza Moderna Intl
Questo pacchetto presuppone l'esistenza dell'oggetto globale Intl nel runtime. Intl è presente in tutti i browser moderni (IE11+) e in Node (con ICU completo). I metodi Intl utilizzati sono:
-
Intl.NumberFormatper la formattazione numerica (polifillabile con @formatjs/intl-numberformat) -
Intl.DateTimeFormatper la formattazione di date e orari (può essere polifillato usando @formatjs/intl-datetimeformat) -
Intl.PluralRulesper la formattazione di plurali/ordinali (può essere polifillato usando @formatjs/intl-pluralrules)
Caricamento di Intl MessageFormat nel browser
<script src="intl-messageformat/intl-messageformat.min.js"></script>
Caricamento di Intl MessageFormat in Node.js
Scegli una delle opzioni:
import IntlMessageFormat from 'intl-messageformat'
const IntlMessageFormat = require('intl-messageformat').default
NOTA: Il tuo Node deve includere full ICU
API Pubblica
Costruttore IntlMessageFormat
Per creare un messaggio da formattare, utilizza il costruttore IntlMessageFormat che accetta tre parametri:
-
message: string | AST- Stringa del messaggio (o AST pre-analizzata) che funge da pattern di formattazione. -
locales: string | string[]- Stringa con tag linguistico BCP 47 o array di tali stringhe. Senza specifica locale, verrà usato quello predefinito. Con array di locali, viene restituito il primo con dati registrati. Vedi: Risoluzione del Locale per dettagli. -
formats?: object- Oggetto opzionale con opzioni definite dall'utente per stili di formattazione. -
opts?: { formatters?: Formatters, ignoreTag?: boolean }- Opzioni facoltative.formatters: Mappa contenente formattatori memorizzati per performance.ignoreTag: Se trattare tag HTML/XML come letterali invece di analizzarli. Sefalsesono permessi solo tag semplici senza attributi.
const msg = new IntlMessageFormat('My name is {name}.', 'en-US')
Risoluzione del Locale
IntlMessageFormat utilizza Intl.NumberFormat.supportedLocalesOf() per determinare i dati locali basati sul valore locales passato al costruttore. Il risultato è ottenibile tramite resolvedOptions().
Metodo resolvedOptions()
Restituisce un oggetto con le opzioni risolte durante la creazione dell'istanza. Contiene attualmente solo la proprietà locale:
new IntlMessageFormat('', 'en-us').resolvedOptions().locale
Nota come il locale specificato in minuscolo "en-us" sia stato risolto e normalizzato in "en-US".
Metodo format(values)
Dopo la creazione del messaggio, la formattazione avviene chiamando format() sull'istanza e passando una collezione di values:
new IntlMessageFormat('My name is {name}.', 'en-US').format({name: 'Eric'})
È necessario fornire un valore per ogni argomento nel pattern del messaggio.
Supporto Rich Text
new IntlMessageFormat('hello <b>world</b>', 'en').format({ b: chunks => <strong>{chunks}</strong>, })
Supportiamo tag XML incorporati nel messaggio, ad esempio this is a <b>strong</b> tag. Questo non è un metodo completo per incorporare HTML, ma serve per contrassegnare parti di testo specifiche per rendere la traduzione più contestuale. Pertanto, si applicano le seguenti restrizioni:
-
Gli attributi sui tag HTML sono ignorati.
-
I tag self-closing sono trattati come letterali (usare invece segnaposto ICU:
{placeholder}). -
Tutti i tag specificati devono avere valori corrispondenti, altrimenti errore:
function () { try { return new IntlMessageFormat('a <foo>strong</foo>').format() } catch (e) { return String(e) } }
- I tag XML/HTML si eseguono con apostrofo come altri costrutti ICU:
new IntlMessageFormat("I '<'3 cats").format()
new IntlMessageFormat("raw '<b>HTML</b>'").format()
new IntlMessageFormat("raw '<b>HTML</b>' with '<a>'{placeholder}'</a>'").format( {placeholder: 'some word'} )
- L'embedding di tag HTML validi è attualmente un'area grigia (supporto parziale).
Metodo getAst
Restituisce l'AST sottostante per il messaggio compilato.
Scheletro per Data/Ora/Numero
Supportiamo lo scheletro ICU per i numeri e un sottoinsieme dello scheletro per data/ora per un'ulteriore personalizzazione dei formati.
Scheletro per Numeri
Esempio:
new IntlMessageFormat( 'The price is: {price, number, ::currency/EUR}', 'en-GB' ).format({price: 100})
Un set completo di opzioni e sintassi è disponibile qui
Scheletro per Data/Ora
ICU offre un'ampia gamma di pattern per personalizzare il formato data/ora. Tuttavia, non tutti sono disponibili tramite l'API Intl di ECMA402. Pertanto, il nostro parser supporta esclusivamente i seguenti pattern:
| Symbol | Meaning | Notes |
|---|---|---|
| G | Era designator | |
| y | year | |
| M | month in year | |
| L | stand-alone month in year | |
| d | day in month | |
| E | day of week | |
| e | local day of week | e..eee is not supported |
| c | stand-alone local day of week | c..ccc is not supported |
| a | AM/PM marker | |
| h | Hour [1-12] | |
| H | Hour [0-23] | |
| K | Hour [0-11] | |
| k | Hour [1-24] | |
| m | Minute | |
| s | Second | |
| z | Time Zone |
Esempio:
new IntlMessageFormat('Today is: {now, date, ::yyyyMMdd}', 'en-GB').format({ now: new Date(), })
Utilizzo Avanzato
Passaggio di AST
È possibile passare un AST pre-analizzato a IntlMessageFormat in questo modo:
new IntlMessageFormat('hello').format() // prints out hello
// is equivalent to
import IntlMessageFormat from 'intl-messageformat'
import {parse} from '@formatjs/icu-messageformat-parser'
new IntlMessageFormat(parse('hello')).format() // prints out hello
Ciò migliora le prestazioni in scenari come SSR o piattaforme che supportano precaricamento/precompilazione poiché l'AST può essere memorizzato nella cache.
Se tutti i messaggi sono in AST, è possibile impostare un alias per @formatjs/icu-messageformat-parser a {default: undefined} per risparmiare byte durante il bundling.
Formattatori
Per messaggi complessi, l'inizializzazione dei costruttori Intl.* può essere onerosa. Consentiamo quindi di passare formatters per fornire istanze memoizzate di questi oggetti Intl. Questa opzione combinata con il passaggio di AST e fast-memoize può accelerare le operazioni di 30x come mostrato nel benchmark seguente.
Ad esempio:
import IntlMessageFormat from 'intl-messageformat'
import {memoize} from '@formatjs/fast-memoize'
const formatters = {
getNumberFormat: memoize(
(locale, opts) => new Intl.NumberFormat(locale, opts)
),
getDateTimeFormat: memoize(
(locale, opts) => new Intl.DateTimeFormat(locale, opts)
),
getPluralRules: memoize((locale, opts) => new Intl.PluralRules(locale, opts)),
}
new IntlMessageFormat('hello {number, number}', 'en', undefined, {
formatters,
}).format({number: 3}) // prints out `hello, 3`
Benchmark
format_cached_complex_msg x 153,868 ops/sec ±1.13% (85 runs sampled)
format_cached_string_msg x 21,661,621 ops/sec ±4.06% (84 runs sampled)
new_complex_msg_preparsed x 719,056 ops/sec ±2.83% (78 runs sampled)
new_complex_msg x 12,844 ops/sec ±1.97% (85 runs sampled)
new_string_msg x 409,770 ops/sec ±2.57% (79 runs sampled)
complex msg format x 12,065 ops/sec ±1.66% (81 runs sampled)
complex msg w/ formatters format x 11,649 ops/sec ±2.05% (78 runs sampled)
complex preparsed msg w/ formatters format x 597,153 ops/sec ±1.46% (90 runs sampled)
complex preparsed msg w/ new formatters format x 684,263 ops/sec ±1.37% (89 runs sampled)