Aller au contenu principal

FormatJS Intl de base

Traduction Bêta Non Officielle

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 i -S @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éé.

Conseil

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.

Live Editor
intl.formatDate(Date.now(), {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
})
Result

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.

Live Editor
intl.formatTime(Date.now()) // "4:03 PM"
Result

formatRelativeTime

Prise en charge navigateur

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.

Live Editor
intl.formatRelativeTime(0)
Result
Live Editor
intl.formatRelativeTime(-24, 'hour', {style: 'narrow'})
Result

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.

Live Editor
intl.formatNumber(1000, {style: 'currency', currency: 'USD'})
Result

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 :

Live Editor
intl.formatNumber(1000, {
  style: 'unit',
  unit: 'kilobyte',
  unitDisplay: 'narrow',
})
Result
Live Editor
intl.formatNumber(1000, {
  unit: 'fahrenheit',
  unitDisplay: 'long',
  style: 'unit',
})
Result

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.

Live Editor
intl.formatPlural(1)
Result
Live Editor
intl.formatPlural(3, {style: 'ordinal'})
Result
Live Editor
intl.formatPlural(4, {style: 'ordinal'})
Result
Support multilingue

Cette fonction ne doit être utilisée que pour des applications supportant une seule langue. Pour des applications multilingues, utilisez plutôt formatMessage.

formatList

Prise en charge navigateur

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 :

Live Editor
intl.formatList(['Me', 'myself', 'I'], {type: 'conjunction'})
Result
Live Editor
intl.formatList(['5 hours', '3 minutes'], {type: 'unit'})
Result

formatDisplayName

Prise en charge navigateur

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 :

Live Editor
intl.formatDisplayName('zh-Hans-SG', {type: 'language'})
Result
Live Editor
// ISO-15924 four letters script code to localized display name
intl.formatDisplayName('Deva', {type: 'script'})
Result
Live Editor
// ISO-4217 currency code to localized display name
intl.formatDisplayName('CNY', {type: 'currency'})
Result
Live Editor
// ISO-3166 two letters region code to localized display name
intl.formatDisplayName('UN', {type: 'region'})
Result

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
}
Extraction des Message Descriptor

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 :

  1. Rechercher et formater le message traduit à l'id, passé à <IntlProvider>.

  2. Retomber sur le formatage du defaultMessage.

  3. Retomber sur la source du message traduit à l'id.

  4. Retomber sur la source du defaultMessage.

  5. Retomber sur l'id litté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.

Live Editor
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'})
}
Result

avec ReactElement

Live Editor
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>})
}
Result

avec formatage de texte enrichi

Live Editor
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>,
  })
}
Result

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.

message simple

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',
})