FormatJS Intl de base
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 →
Cette bibliothèque contient l'API intl fondamentale utilisée par react-intl.
Installation
- npm
- yarn
npm i -S @formatjs/intl
yarn add @formatjs/intl
L'objet intl
Le cœur de @formatjs/intl est l'objet intl (de type IntlShape), qui sert d'instance pour stocker un cache de toutes les API Intl.*, configurations, messages compilés et éléments similaires. Le cycle de vie de l'objet intl est généralement lié à la locale et à la liste des messages qu'il contient, ce qui signifie que lorsque vous changez de locale, cet objet doit être recréé.
L'objet intl doit être réutilisé autant que possible pour des raisons de performance.
createIntl
Permet de créer un objet IntlShape contenant toutes les méthodes format*. Par exemple :
import {createIntl, createIntlCache} from '@formatjs/intl'
// This is optional but highly recommended
// since it prevents memory leak
const cache = createIntlCache()
const intl = createIntl(
{
locale: 'fr-FR',
messages: {},
},
cache
)
// Call imperatively
intl.formatNumber(20)
createIntlCache
Crée une instance de cache utilisable globalement pour toutes les locales. Cela mémorise les constructeurs Intl.* précédemment créés pour des performances optimales et ne constitue qu'un cache en mémoire.
IntlShape
interface IntlConfig {
locale: string
timeZone?: string
fallbackOnEmptyString?: boolean
formats: CustomFormats
messages: Record<string, string> | Record<string, MessageFormatElement[]>
defaultLocale: string
defaultRichTextElements?: Record<string, FormatXMLElementFn<React.ReactNode>>
defaultFormats: CustomFormats
onError(err: string): void
onWarn(warning: string): void
}
interface IntlFormatters {
formatDate(value: number | Date | string, opts?: FormatDateOptions): string
formatTime(value: number | Date | string, opts?: FormatDateOptions): string
formatDateToParts(
value: number | Date | string,
opts?: FormatDateOptions
): Intl.DateTimeFormatPart[]
formatTimeToParts(
value: number | Date | string,
opts?: FormatDateOptions
): Intl.DateTimeFormatPart[]
formatRelativeTime(
value: number,
unit?: FormattableUnit,
opts?: FormatRelativeTimeOptions
): string
formatNumber(value: number, opts?: FormatNumberOptions): string
formatNumberToParts(
value: number,
opts?: FormatNumberOptions
): Intl.NumberFormatPart[]
formatPlural(
value: number | string,
opts?: FormatPluralOptions
): ReturnType<Intl.PluralRules['select']>
formatMessage(
descriptor: MessageDescriptor,
values?: Record<string, PrimitiveType | FormatXMLElementFn<string, string>>
): string
formatMessage(
descriptor: MessageDescriptor,
values?: Record<string, PrimitiveType | T | FormatXMLElementFn<T, R>>
): R
formatList(values: Iterable<string>, opts?: FormatListOptions): string
formatList(
values: Iterable<string | T>,
opts?: FormatListOptions
): T | string | Array<string | T>
formatListToParts(
values: Iterable<string | T>,
opts?: FormatListOptions
): Part[]
formatDisplayName(
value: string,
opts?: FormatDisplayNameOptions
): string | undefined
}
type IntlShape = IntlConfig & IntlFormatters
La définition ci-dessus montre à quoi ressemble l'objet intl. Il se compose de deux parties :
-
IntlConfig: Les métadonnées intl passées comme props au parent<IntlProvider>. -
IntlFormatters: L'API de formatage impératif décrite ci-dessous.
locale, formats et messages
La locale actuelle de l'utilisateur et celle dans laquelle l'application doit être rendue. Tandis que defaultLocale et defaultFormats servent de fallbacks ou durant le développement pour représenter les valeurs par défaut de l'application. Notez l'absence de defaultMessages car chaque Message Descriptor fournit déjà un defaultMessage.
defaultLocale et defaultFormats
Locale et formats par défaut utilisés lorsqu'un message n'est pas traduit (absent de messages). defaultLocale doit correspondre à la locale dans laquelle les defaultMessage sont déclarés pour garantir la cohérence des phrases dans une seule locale. Sans defaultLocale ou si celui-ci est mal configuré, vous pourriez obtenir des phrases en anglais avec des dates/heures intégrées en espagnol.
onError
Permet à l'utilisateur de fournir un gestionnaire d'erreurs personnalisé. Par défaut, les erreurs sont journalisées via console.error si NODE_ENV n'est pas défini sur production.
defaultRichTextElements
Une correspondance entre balises et fonctions de formatage de texte enrichi. Conçu pour centraliser le formatage de balises courantes comme <b>, <p>... ou imposer un Design System spécifique dans la base de code (ex: <a> ou <button> standardisés). Voir https://github.com/formatjs/formatjs/issues/1752 pour plus de contexte.
fallbackOnEmptyString
Valeur par défaut : true.
Cette option booléenne est utile pour fournir intentionnellement des valeurs vides dans certaines locales via des chaînes vides. Lorsque fallbackOnEmptyString est false, les chaînes vides sont retournées au lieu de déclencher la procédure de fallback. Ce comportement permet "d'ignorer" du contenu dans des locales spécifiques.
Voir cette issue pour plus de contexte.
formatDate
function formatDate(
value: number | Date,
options?: Intl.DateTimeFormatOptions & {format?: string}
): string
Cette fonction retourne une chaîne de caractères représentant une date formatée. Elle attend une value interprétable comme date (c'est-à-dire isFinite(new Date(value))), et accepte des options conformes à DateTimeFormatOptions.
intl.formatDate(Date.now(), { year: 'numeric', month: 'numeric', day: 'numeric', })
formatTime
function formatTime(
value: number | Date,
options?: Intl.DateTimeFormatOptions & {format?: string}
): string
Cette fonction retourne également une chaîne de caractères de date formatée, mais diffère de formatDate par ses options par défaut :
{
hour: 'numeric',
minute: 'numeric',
}
Elle attend une value interprétable comme date (c'est-à-dire isFinite(new Date(value))), et accepte des options conformes à DateTimeFormatOptions.
intl.formatTime(Date.now()) // "4:03 PM"
formatRelativeTime
Cette fonction nécessite Intl.RelativeTimeFormat dont le support navigateur est limité. Utilisez notre polyfill si vous prévoyez de les prendre en charge.
type Unit =
| 'second'
| 'minute'
| 'hour'
| 'day'
| 'week'
| 'month'
| 'quarter'
| 'year'
type RelativeTimeFormatOptions = {
numeric?: 'always' | 'auto'
style?: 'long' | 'short' | 'narrow'
}
function formatRelativeTime(
value: number,
unit: Unit,
options?: Intl.RelativeTimeFormatOptions & {
format?: string
}
): string
Cette fonction retourne une chaîne de temps relatif formatée (ex : "il y a 1 heure"). Elle attend une value numérique, une unit et des options conformes à Intl.RelativeTimeFormatOptions.
intl.formatRelativeTime(0)
intl.formatRelativeTime(-24, 'hour', {style: 'narrow'})
formatNumber
Cette fonction utilise les options d'Intl.NumberFormat.
function formatNumber(
value: number,
options?: Intl.NumberFormatOptions & {format?: string}
): string
Cette fonction retourne une chaîne de nombre formatée. Elle attend une value interprétable comme nombre, et accepte des options conformes à NumberFormatOptions.
intl.formatNumber(1000, {style: 'currency', currency: 'USD'})
Formatage numérique avec unit
Actuellement, cette fonctionnalité fait partie d'ES2020 NumberFormat.
Nous fournissons un polyfill ici et les types @formatjs/intl permettent de spécifier
une unité standardisée :
intl.formatNumber(1000, { style: 'unit', unit: 'kilobyte', unitDisplay: 'narrow', })
intl.formatNumber(1000, { unit: 'fahrenheit', unitDisplay: 'long', style: 'unit', })
formatPlural
type PluralFormatOptions = {
type?: 'cardinal' | 'ordinal' = 'cardinal'
}
function formatPlural(
value: number,
options?: Intl.PluralFormatOptions
): 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'
Cette fonction retourne une catégorie de pluriel : "zero", "one", "two", "few", "many", ou "other". Elle attend une value interprétable comme nombre, et accepte des options conformes à PluralFormatOptions.
C'est une utilitaire bas niveau dont le résultat peut être utilisé dans une instruction switch pour sélectionner une chaîne spécifique à afficher.
intl.formatPlural(1)
intl.formatPlural(3, {style: 'ordinal'})
intl.formatPlural(4, {style: 'ordinal'})
Cette fonction ne doit être utilisée que pour des applications supportant une seule langue. Pour des applications multilingues, utilisez plutôt formatMessage.
formatList
Cette fonction nécessite Intl.ListFormat dont le support navigateur est limité. Utilisez notre polyfill si vous prévoyez de les prendre en charge.
type ListFormatOptions = {
type?: 'disjunction' | 'conjunction' | 'unit'
style?: 'long' | 'short' | 'narrow'
}
function formatList(
elements: Iterable<string | React.ReactNode>,
options?: Intl.ListFormatOptions
): string | React.ReactNode[]
Cette fonction permet de joindre des listes d'éléments de manière compatible i18n. Par exemple, lorsque la locale est en :
intl.formatList(['Me', 'myself', 'I'], {type: 'conjunction'})
intl.formatList(['5 hours', '3 minutes'], {type: 'unit'})
formatDisplayName
Cette fonction nécessite Intl.DisplayNames dont le support navigateur est limité. Utilisez notre polyfill si vous prévoyez de les prendre en charge.
type FormatDisplayNameOptions = {
style?: 'narrow' | 'short' | 'long'
type?: 'language' | 'region' | 'script' | 'currency'
fallback?: 'code' | 'none'
}
function formatDisplayName(
value: string | number | Record<string, unknown>,
options: FormatDisplayNameOptions
): string | undefined
Exemples d'utilisation :
intl.formatDisplayName('zh-Hans-SG', {type: 'language'})
// ISO-15924 four letters script code to localized display name intl.formatDisplayName('Deva', {type: 'script'})
// ISO-4217 currency code to localized display name intl.formatDisplayName('CNY', {type: 'currency'})
// ISO-3166 two letters region code to localized display name intl.formatDisplayName('UN', {type: 'region'})
formatMessage
Syntaxe des messages
Le formatage des chaînes/messages est une fonction essentielle de React Intl, basée sur le formatage de messages ICU via la syntaxe de message ICU. Cette syntaxe permet de définir, traduire puis formater à l'exécution des messages simples à complexes.
Message simple :
Hello, {name}
Message complexe :
Hello, {name}, you have {itemCount, plural,
=0 {no items}
one {# item}
other {# items}
}.
Voir : Le guide de syntaxe des messages.
Message Descriptor
React Intl utilise le concept de Descripteur de message pour définir les messages/chaînes par défaut de votre application, qui est passé à formatMessage. Les Descripteurs de message sont optimaux pour fournir les données nécessaires à la traduction des chaînes/messages et contiennent les propriétés suivantes :
-
id: Identifiant unique et stable pour le message -
description: Contexte pour le traducteur sur l'utilisation dans l'UI -
defaultMessage: Le message par défaut (probablement en anglais)
type MessageDescriptor = {
id: string
defaultMessage?: string
description?: string | object
}
Vous pouvez extraire les messages déclarés dans le code source via notre CLI.
Fallbacks de formatage des messages
Les API de formatage de messages vont au-delà pour fournir des solutions de repli dans les situations courantes où le formatage échoue ; au minimum, une chaîne non vide devrait toujours être retournée. Voici l'algorithme de repli pour le formatage des messages :
-
Rechercher et formater le message traduit à l'
id, passé à<IntlProvider>. -
Retomber sur le formatage du
defaultMessage. -
Retomber sur la source du message traduit à l'
id. -
Retomber sur la source du
defaultMessage. -
Retomber sur l'
idlittéral du message.
Ci-dessus, "source" fait référence à l'utilisation du modèle tel quel, sans aucune substitution.
Utilisation
type MessageFormatPrimitiveValue = string | number | boolean | null | undefined
function formatMessage(
descriptor: MessageDescriptor,
values?: Record<string, MessageFormatPrimitiveValue>
): string
function formatMessage(
descriptor: MessageDescriptor,
values?: Record<
string,
MessageFormatPrimitiveValue | React.ReactElement | FormatXMLElementFn
>
): string | React.ReactNode[]
Cette fonction retourne une chaîne de message formatée. Elle attend un MessageDescriptor avec au moins une propriété id, et accepte un objet values peu profond qui est utilisé pour remplir les espaces réservés dans le message.
Si un message traduit avec l'id a été passé au <IntlProvider> via sa prop messages, il sera formaté ; sinon, il retombera sur le formatage du defaultMessage. Voir : Fallbacks de formatage de message pour plus de détails.
function () { const messages = defineMessages({ greeting: { id: 'app.greeting', defaultMessage: 'Hello, {name}!', description: 'Greeting to welcome the user to the app', }, }) return intl.formatMessage(messages.greeting, {name: 'Eric'}) }
avec ReactElement
function () { const messages = defineMessages({ greeting: { id: 'app.greeting', defaultMessage: 'Hello, {name}!', description: 'Greeting to welcome the user to the app', }, }) return intl.formatMessage(messages.greeting, {name: <b>Eric</b>}) }
avec formatage de texte enrichi
function () { const messages = defineMessages({ greeting: { id: 'app.greeting', defaultMessage: 'Hello, <bold>{name}</bold>!', description: 'Greeting to welcome the user to the app', }, }) return intl.formatMessage(messages.greeting, { name: 'Eric', bold: str => <b>{str}</b>, }) }
Le message que nous avons défini en utilisant defineMessages pour supporter l'extraction via babel-plugin-formatjs, mais ce n'est pas obligatoire si vous n'utilisez pas le plugin Babel.
Les messages peuvent être des chaînes simples sans espaces réservés, et c'est le type de message le plus courant.
defineMessages/defineMessage
interface MessageDescriptor {
id?: string
description?: string | object
defaultMessage?: string
}
function defineMessages(
messageDescriptors: Record<string, MessageDescriptor>
): Record<string, MessageDescriptor>
function defineMessage(messageDescriptor: MessageDescriptor): MessageDescriptor
Exportées par @formatjs/intl, ces fonctions servent de point d'ancrage pour notre CLI et les plugins Babel/TS lors de la compilation des messages par défaut. Elles retournent simplement l'objet Message Descriptor fourni en entrée.
import {defineMessages, defineMessage} from '@formatjs/intl'
const messages = defineMessages({
greeting: {
id: 'app.home.greeting',
description: 'Message to greet the user.',
defaultMessage: 'Hello, {name}!',
},
})
const msg = defineMessage({
id: 'single',
defaultMessage: 'single message',
description: 'header',
})