Vai al contenuto principale

Intl MessageFormat

Traduzione Beta Non Ufficiale

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.

npm Version intl-messageformat minzipped size

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.

Modifiche Future

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:

Live Editor
new IntlMessageFormat(
  `{numPhotos, plural,
      =0 {You have no photos.}
      =1 {You have one photo.}
      other {You have # photos.}
    }`,
  'en-US'
).format({numPhotos: 1000})
Result
Live Editor
new IntlMessageFormat(
  `{numPhotos, plural,
      =0 {Usted no tiene fotos.}
      =1 {Usted tiene una foto.}
      other {Usted tiene # fotos.}
    }`,
  'es-ES'
).format({numPhotos: 1000})
Result

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.NumberFormat e Intl.DateTimeFormat.

  • Ottimizzato per chiamate ripetute al metodo format() di un'istanza IntlMessageFormat.

  • Supporta la definizione di stili/opzioni di formattazione personalizzati.

  • Supporta sequenze di escape per caratteri sintattici, es: "'{foo}'" produrrà "{foo}" invece di interpretarlo come argomento foo.

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:

  1. Intl.NumberFormat per la formattazione numerica (polifillabile con @formatjs/intl-numberformat)

  2. Intl.DateTimeFormat per la formattazione di date e orari (può essere polifillato usando @formatjs/intl-datetimeformat)

  3. Intl.PluralRules per 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. Se false sono 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:

Live Editor
new IntlMessageFormat('', 'en-us').resolvedOptions().locale
Result

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:

Live Editor
new IntlMessageFormat('My name is {name}.', 'en-US').format({name: 'Eric'})
Result
segnaposto

È necessario fornire un valore per ogni argomento nel pattern del messaggio.

Supporto Rich Text

Live Editor
new IntlMessageFormat('hello <b>world</b>', 'en').format({
  b: chunks => <strong>{chunks}</strong>,
})
Result

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:

  1. Gli attributi sui tag HTML sono ignorati.

  2. I tag self-closing sono trattati come letterali (usare invece segnaposto ICU: {placeholder}).

  3. Tutti i tag specificati devono avere valori corrispondenti, altrimenti errore:

Live Editor
function () {
  try {
    return new IntlMessageFormat('a <foo>strong</foo>').format()
  } catch (e) {
    return String(e)
  }
}
Result
  1. I tag XML/HTML si eseguono con apostrofo come altri costrutti ICU:
Live Editor
new IntlMessageFormat("I '<'3 cats").format()
Result
Live Editor
new IntlMessageFormat("raw '<b>HTML</b>'").format()
Result
Live Editor
new IntlMessageFormat("raw '<b>HTML</b>' with '<a>'{placeholder}'</a>'").format(
  {placeholder: 'some word'}
)
Result
  1. 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:

Live Editor
new IntlMessageFormat(
  'The price is: {price, number, ::currency/EUR}',
  'en-GB'
).format({price: 100})
Result

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:

SymbolMeaningNotes
GEra designator
yyear
Mmonth in year
Lstand-alone month in year
dday in month
Eday of week
elocal day of weeke..eee is not supported
cstand-alone local day of weekc..ccc is not supported
aAM/PM marker
hHour [1-12]
HHour [0-23]
KHour [0-11]
kHour [1-24]
mMinute
sSecond
zTime Zone

Esempio:

Live Editor
new IntlMessageFormat('Today is: {now, date, ::yyyyMMdd}', 'en-GB').format({
  now: new Date(),
})
Result

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)