Formatage de messages Intl
Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →
Formate les chaînes de messages ICU avec des espaces réservés pour les nombres, dates, pluriels et sélections afin de créer des messages localisés.
Vue d'ensemble
Objectifs
Ce package vise à fournir un moyen de gérer et formater les messages textuels de votre application JavaScript en chaînes localisées pour les utilisateurs. Il peut être utilisé dans le navigateur et sur le serveur via Node.js.
Cette implémentation est basée sur la proposition Strawman, mais présente quelques divergences.
L'API IntlMessageFormat pourra évoluer pour rester synchronisée avec ECMA-402, mais ce package respectera semver.
Fonctionnement
Les messages sont fournis au constructeur sous forme de chaîne String ou d'objet AST pré-analysé.
const msg = new IntlMessageFormat(message, locales, [formats], [opts])
La chaîne message est analysée puis stockée sous une forme compilée optimisée pour la méthode format(), qui génère la chaîne formatée destinée à l'utilisateur.
const output = msg.format(values)
Exemple d'utilisation courante
Un cas typique concerne le formatage de messages avec nombres et libellés de pluriel. Ce package garantit un formatage correct selon la locale de l'utilisateur, par exemple :
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})
Syntaxe des messages
La syntaxe utilisée n'est pas propriétaire : il s'agit d'un standard interlangages bien connu des traducteurs professionnels. Ce package utilise la syntaxe ICU Message et fonctionne pour toutes les langues CLDR disposant de règles de pluralisation.
Fonctionnalités
-
Utilise des standards industriels : syntaxe ICU Message et données locales CLDR.
-
Prend en charge les arguments de type plural, select et selectordinal.
-
Formate les nombres et dates/heures via
Intl.NumberFormatetIntl.DateTimeFormat. -
Optimisé pour les appels répétés à la méthode
format()des instancesIntlMessageFormat. -
Permet de définir des styles/options de format personnalisés.
-
Gère les séquences d'échappement pour les caractères syntaxiques, ex. :
"'{foo}'"produit"{foo}"plutôt que d'interpréterfoocomme argument.
Utilisation
Dépendance Intl moderne
Ce package nécessite la présence globale de l'objet Intl dans l'environnement d'exécution. Intl est disponible dans tous les navigateurs modernes (IE11+) et Node.js (avec ICU complet). Les méthodes Intl utilisées sont :
-
Intl.NumberFormatpour le formatage numérique (polyfillable via @formatjs/intl-numberformat) -
Intl.DateTimeFormatpour le formatage des dates et heures (peut être complété par @formatjs/intl-datetimeformat) -
Intl.PluralRulespour le formatage des pluriels et ordinaux (peut être complété par @formatjs/intl-pluralrules)
Chargement d'Intl MessageFormat dans un navigateur
<script src="intl-messageformat/intl-messageformat.min.js"></script>
Chargement d'Intl MessageFormat dans Node.js
Vous pouvez faire :
import IntlMessageFormat from 'intl-messageformat'
const IntlMessageFormat = require('intl-messageformat').default
REMARQUE : Votre Node doit inclure full ICU
API publique
Constructeur IntlMessageFormat
Pour créer un message à formater, utilisez le constructeur IntlMessageFormat. Il prend trois paramètres :
-
message: string | AST- Message sous forme de chaîne (ou AST pré-analysé) servant de modèle de formatage. -
locales: string | string[]- Chaîne avec une balise de langue BCP 47, ou tableau de telles chaînes. Si aucune locale n'est fournie, la locale par défaut sera utilisée. Pour un tableau de locales, chaque élément et ses locales parentes sont vérifiés, et la première avec des données enregistrées est retenue. Voir : Résolution de locale pour plus de détails. -
formats?: object- Objet optionnel contenant des options de format personnalisées. -
opts?: { formatters?: Formatters, ignoreTag?: boolean }- Options facultatives.formatters: Map contenant des formateurs mémoïsés pour la performance.ignoreTag: Indique si les balises HTML/XML doivent être traitées comme des littéraux plutôt que comme des jetons. Àfalse, seules les balises simples sans attributs sont autorisées.
const msg = new IntlMessageFormat('My name is {name}.', 'en-US')
Résolution de locale
IntlMessageFormat utilise Intl.NumberFormat.supportedLocalesOf() pour déterminer les données de locale à utiliser, basées sur la valeur locales passée au constructeur. Le résultat est consultable via la méthode prototype resolvedOptions().
Méthode resolvedOptions()
Cette méthode retourne un objet contenant les options résolues lors de la création de l'instance. Actuellement, seule la propriété locale est présente ; exemple :
new IntlMessageFormat('', 'en-us').resolvedOptions().locale
Notez que la locale spécifiée en minuscules "en-us" a été résolue et normalisée en "en-US".
Méthode format(values)
Une fois le message créé, son formatage s'effectue en appelant format() sur l'instance avec une collection de values :
new IntlMessageFormat('My name is {name}.', 'en-US').format({name: 'Eric'})
Une valeur doit être fournie pour chaque argument du modèle de message utilisé lors de la construction de l'instance.
Prise en charge du texte enrichi
new IntlMessageFormat('hello <b>world</b>', 'en').format({ b: chunks => <strong>{chunks}</strong>, })
Nous prenons en charge les balises XML intégrées (ex: this is a <b>strong</b> tag). Ce n'est pas une méthode complète d'intégration HTML, mais un balisage contextuel pour la traduction. Restrictions :
-
Les attributs des balises HTML sont ignorés.
-
Les balises auto-fermantes sont traitées comme des littéraux et non prises en charge ; utilisez plutôt des paramètres ICU standard comme
{placeholder}. -
Toutes les balises spécifiées doivent avoir des valeurs correspondantes, sinon une erreur est levée :
function () { try { return new IntlMessageFormat('a <foo>strong</foo>').format() } catch (e) { return String(e) } }
- Les balises XML/HTML sont échappées par apostrophe comme les autres constructions ICU. Exemple d'échappement :
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'intégration de balises HTML valides reste floue car nous ne supportons pas entièrement les spécifications HTML/XHTML/XML.
Méthode getAst
Retourne l'AST sous-jacent du message compilé.
Squelette Date/Heure/Nombre
Nous prenons en charge le squelette de nombre ICU et un sous-ensemble du squelette date/heure pour une personnalisation avancée des formats.
Squelette de nombre
Exemple :
new IntlMessageFormat( 'The price is: {price, number, ::currency/EUR}', 'en-GB' ).format({price: 100})
Un ensemble complet d'options et de syntaxe est disponible ici
Squelette date/heure
ICU propose une large gamme de motifs pour personnaliser le format de date et d'heure. Cependant, tous ne sont pas disponibles via l'API Intl d'ECMA402. Par conséquent, notre analyseur ne prend en charge que les motifs suivants :
| 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 |
Exemple :
new IntlMessageFormat('Today is: {now, date, ::yyyyMMdd}', 'en-GB').format({ now: new Date(), })
Utilisation avancée
Passage d'AST
Vous pouvez passer un AST pré-analysé à IntlMessageFormat comme ceci :
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
Cela améliore les performances dans des cas comme le SSR ou les plateformes supportant le préchargement/précompilation, car l'AST peut être mis en cache.
Si tous vos messages sont sous forme d'AST, vous pouvez définir un alias pour @formatjs/icu-messageformat-parser vers {default: undefined} pour économiser des octets lors du bundling.
Formateurs
Pour les messages complexes, l'initialisation des constructeurs Intl.* peut être coûteuse. Nous autorisons donc l'utilisateur à passer des formatters pour fournir des instances mémorisées de ces objets Intl. Cette option combinée avec le passage d'AST et fast-memoize peut accélérer les traitements jusqu'à 30x selon le benchmark ci-dessous.
Par exemple :
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)