Aller au contenu principal

Composants

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 →

React Intl propose un ensemble de composants React offrant une approche déclarative pour configurer un contexte i18n et formater des dates, nombres et chaînes de caractères dans une interface web. Ces composants génèrent des éléments React en s'appuyant sur l'API impérative de React Intl.

Pourquoi des composants ?

Au-delà d'offrir une intégration idiomatique de l'internationalisation dans React, les composants <Formatted*> présentent des avantages par rapport à l'utilisation directe de l'API impérative :

  • Génèrent des éléments React qui s'intègrent naturellement avec d'autres composants

  • Supportent le formatage de texte enrichi dans <FormattedMessage>

  • Implémentent des fonctionnalités avancées comme la mise à jour dynamique de <FormattedRelativeTime>

  • Fournissent des définitions de types TypeScript

IntlProvider

React Intl utilise le modèle de provider pour délimiter un contexte i18n à un arbre de composants. Cette approche permet de fournir au niveau racine des configurations comme la locale courante et les messages traduits, rendus disponibles pour les composants <Formatted*>. C'est le même concept que les frameworks Flux comme Redux utilisent pour exposer un store dans un arbre de composants.

Attention

Toute application utilisant React Intl doit employer le composant <IntlProvider> ou <RawIntlProvider>.

Ce composant configure le contexte i18n pour un arbre. Typiquement, il englobe le composant racine de l'application pour que l'ensemble de l'app soit dans le contexte i18n configuré. Voici les propriétés de configuration i18n disponibles :

interface IntlConfig {
locale: string
formats: CustomFormats
messages: Record<string, string> | Record<string, MessageFormatElement[]>
defaultLocale: string
defaultFormats: CustomFormats
timeZone?: string
textComponent?: React.ComponentType | keyof React.JSX.IntrinsicElements
wrapRichTextChunksInFragment?: boolean
defaultRichTextElements?: Record<string, FormatXMLElementFn<React.ReactNode>>
onError(err: string): void
}

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.

textComponent

Configure le wrapper par défaut des composants <Formatted*> de React Intl. Par défaut, <React.Fragment> est utilisé. Avant la version 3, span était employé ; consultez le guide de migration pour plus de détails.

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.

onWarn

Permet de définir un gestionnaire d'avertissements personnalisé. Par défaut, les avertissements sont journalisés via console.warning si NODE_ENV n'est pas en production.

wrapRichTextChunksInFragment

Lors du formatage de texte enrichi, la sortie est de type Array<string | React.ReactElement>, ce qui génère une erreur de clé. Cette option englobe le résultat dans un React.Fragment unique pour résoudre ce problème.

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.

Ces propriétés de configuration sont combinées avec les props spécifiques à <IntlProvider> :

Props :

props: IntlConfig &
{
children: ReactNode,
}

Des éléments enfants doivent impérativement être fournis à <IntlProvider>.

Exemple :

const App = ({importantDate}) => (
<div>
<FormattedDate
value={importantDate}
year="numeric"
month="long"
day="numeric"
weekday="long"
/>
</div>
)

ReactDOM.render(
<IntlProvider locale={navigator.language}>
<App importantDate={new Date(1459913574887)} />
</IntlProvider>,
document.getElementById('container')
)

En supposant que navigator.language vaut "fr" :

<div>mardi 5 avril 2016</div>

RawIntlProvider

Il s'agit du React.Context.Provider sous-jacent utilisé par IntlProvider. Peut être employé conjointement avec createIntl :

import {createIntl, createIntlCache, RawIntlProvider} from 'react-intl'

// This is optional but highly recommended
// since it prevents memory leak
const cache = createIntlCache()

const intl = createIntl({
locale: 'fr-FR',
messages: {}
}, cache)

// Pass it to IntlProvider
<RawIntlProvider value={intl}>{foo}</RawIntlProvider>

FormattedDate

Ce composant utilise les API formatDate et Intl.DateTimeFormat, avec des props correspondant aux DateTimeFormatOptions mentionnés précédemment.

Props :

props: Intl.DateTimeFormatOptions &
{
value: any,
format: string,
children: (formattedDate: string) => ReactElement,
}

Par défaut, <FormattedDate> affiche la date formatée dans un <React.Fragment>. Pour personnaliser le rendu, vous pouvez soit l'englober dans un autre élément React (recommandé), soit passer une fonction comme enfant.

Exemple :

Live Editor
<FormattedDate value={new Date(1459832991883)} />
Result

Exemple avec options :

Live Editor
<FormattedDate
  value={new Date(1459832991883)}
  year="numeric"
  month="long"
  day="2-digit"
/>
Result

FormattedDateParts

compatibilité navigateur

Cette fonctionnalité nécessite Intl.DateTimeFormat.prototype.formatToParts qui n'est pas disponible dans IE11. Utilisez notre polyfill si vous devez supporter IE11.

Ce composant offre davantage de personnalisation pour FormattedDate en permettant à une fonction enfant d'accéder aux éléments sous-jacents de la date formatée. Les parties disponibles sont listées ici.

Props :

props: Intl.DateTimeFormatOptions &
{
value: any,
format: string,
children: (parts: Intl.DateTimeFormatPart[]) => ReactElement,
}
Live Editor
<FormattedDateParts
  value={new Date(1459832991883)}
  year="numeric"
  month="long"
  day="2-digit"
>
  {parts => (
    <>
      <b>{parts[0].value}</b>
      {parts[1].value}
      <small>{parts[2].value}</small>
    </>
  )}
</FormattedDateParts>
Result

FormattedTime

Ce composant utilise les APIs formatTime et Intl.DateTimeFormat et a props qui correspondent aux DateTimeFormatOptions spécifiés ci-dessus, avec ces valeurs par défaut :

{
hour: 'numeric',
minute: 'numeric',
}

Props :

props: DateTimeFormatOptions &
{
value: any,
format: string,
children: (formattedDate: string) => ReactElement,
}

Par défaut, <FormattedTime> rend le temps formaté dans un React.Fragment. Pour personnaliser le rendu, vous pouvez soit l'encapsuler dans un autre élément React (recommandé), soit passer une fonction comme enfant.

Exemple :

Live Editor
<FormattedTime value={new Date(1459832991883)} />
Result

FormattedTimeParts

compatibilité navigateur

Cette fonctionnalité nécessite Intl.DateTimeFormat.prototype.formatToParts qui n'est pas disponible dans IE11. Utilisez notre polyfill si vous devez supporter IE11.

Ce composant offre davantage de personnalisation pour FormattedTime en permettant à une fonction enfant d'accéder aux éléments sous-jacents de l'heure formatée. Les parties disponibles sont listées ici.

Props :

props: Intl.DateTimeFormatOptions &
{
value: any,
format: string,
children: (parts: Intl.DateTimeFormatPart[]) => ReactElement,
}
Live Editor
<FormattedTimeParts value={new Date(1459832991883)}>
  {parts => (
    <>
      <b>{parts[0].value}</b>
      {parts[1].value}
      <small>{parts[2].value}</small>
    </>
  )}
</FormattedTimeParts>
Result

FormattedDateTimeRange

compatibilité navigateur

Cette fonctionnalité nécessite l'API stage-3 Intl.RelativeTimeFormat.prototype.formatRange qui a un support navigateur limité. Utilisez notre polyfill si vous devez la supporter.

Ce composant utilise les APIs formatDateTimeRange et Intl.DateTimeFormat avec des props correspondant aux DateTimeFormatOptions spécifiés ci-dessus.

Props :

props: DateTimeFormatOptions &
{
from: number | Date,
to: number | Date,
children: (formattedDate: string) => ReactElement,
}

Par défaut, <FormattedDateTimeRange> rend la plage temporelle formatée dans un React.Fragment. Pour personnaliser le rendu, vous pouvez soit l'encapsuler dans un autre élément React (recommandé), soit passer une fonction comme enfant.

Exemple :

Live Editor
<FormattedDateTimeRange
  from={new Date('2020-1-1')}
  to={new Date('2020-1-15')}
/>
Result

FormattedRelativeTime

compatibilité navigateur

Cette fonctionnalité nécessite Intl.RelativeTimeFormat qui a un support navigateur limité. Utilisez notre polyfill si vous devez la supporter.

Ce composant utilise l'API formatRelativeTime et a des props qui correspondent aux options de formatage relatif suivantes :

type RelativeTimeFormatOptions = {
numeric?: 'always' | 'auto'
style?: 'long' | 'short' | 'narrow'
}

Types de propriétés :

props: RelativeTimeFormatOptions &
{
value: number,
unit: Unit,
format: string,
updateIntervalInSeconds: number,
children: (formattedDate: string) => ReactElement,
}

Par défaut, <FormattedRelativeTime> rend le temps relatif formaté dans un React.Fragment. Pour personnaliser le rendu, vous pouvez soit l'encapsuler dans un autre élément React (recommandé), soit passer une fonction comme enfant.

Exemple :

Live Editor
<FormattedRelativeTime value={0} numeric="auto" updateIntervalInSeconds={1} />
Result
intervalle maximum

Vous pouvez ajuster l'intervalle maximum entre les rafraîchissements du composant en définissant updateIntervalInSeconds. Une valeur falsy désactivera le rafraîchissement automatique. Le système est intelligent et planifiera le prochain rafraîchissement au prochain moment pertinent.

Un moment pertinent est défini comme la prochaine value non fractionnaire pour cette unit. Par exemple :

Live Editor
<FormattedRelativeTime value={-50} updateIntervalInSeconds={1} />
Result

Initialement, cela affichera 59 seconds ago. Après 1 seconde, cela affichera 1 minute ago, et ne se rafraîchira pas avant qu'une minute entière ne s'écoule, affichant alors 2 minutes ago. Il n'essaiera pas d'afficher 1.2 minutes ago.

limitation

updateIntervalInSeconds ne peut pas être activé pour des unit supérieures à hour (donc pas pour day, week, quarter, year). Principalement parce qu'il n'est pas pertinent de planifier un timeout en days, et que le nombre de ms dans une journée dépasse le timeout maximum accepté par setTimeout.

FormattedNumber

Ce composant utilise les API formatNumber et Intl.NumberFormat avec des props correspondant aux Intl.NumberFormatOptions.

Props :

props: NumberFormatOptions &
{
value: number,
format: string,
children: (formattedNumber: string) => ReactElement,
}

Par défaut, <FormattedNumber> rend le nombre formaté dans un React.Fragment. Pour personnaliser le rendu, vous pouvez soit l'encapsuler dans un autre élément React (recommandé), soit passer une fonction comme enfant.

Exemple :

Live Editor
<FormattedNumber value={1000} />
Result

Exemple de formatage monétaire

Live Editor
<FormattedNumber value={1000} style="currency" currency="USD" />
Result

Formatage numérique avec unit

Cette fonctionnalité fait actuellement partie de l'ES2020 NumberFormat. Nous fournissons un polyfill ici et les types react-intl permettent d'utiliser des unités standardisées. Par exemple :

Live Editor
<FormattedNumber
  value={1000}
  style="unit"
  unit="kilobyte"
  unitDisplay="narrow"
/>
Result
Live Editor
<FormattedNumber
  value={1000}
  unit="fahrenheit"
  unitDisplay="long"
  style="unit"
/>
Result

FormattedNumberParts

support navigateur

Nécessite Intl.NumberFormat.prototype.formatToParts non disponible dans IE11. Utilisez notre polyfill pour supporter IE11.

Ce composant offre plus de flexibilité que FormattedNumber en exposant les parties constitutives du nombre formaté via une fonction enfant. Les parties disponibles sont listées ici.

Props :

props: NumberFormatOptions &
{
value: number,
format: string,
children: (parts: Intl.NumberFormatPart[]) => ReactElement,
}

Exemple :

Live Editor
<FormattedNumberParts value={1000}>
  {parts => (
    <>
      <b>{parts[0].value}</b>
      {parts[1].value}
      <small>{parts[2].value}</small>
    </>
  )}
</FormattedNumberParts>
Result

FormattedPlural

Ce composant utilise les API formatPlural et Intl.PluralRules avec des props correspondant aux Intl.PluralRulesOptions.

Props :

props: PluralFormatOptions &
{
value: any,

other: ReactElement,
zero: ReactElement,
one: ReactElement,
two: ReactElement,
few: ReactElement,
many: ReactElement,

children: (formattedPlural: ReactElement) => ReactElement,
}

Par défaut, <FormattedPlural> sélectionne une catégorie de pluriel (zero, one, two, few, many, ou other) et rend l'élément React correspondant dans un React.Fragment. Pour personnaliser le rendu, encapsulez-le ou passez une fonction comme enfant.

Exemple :

Live Editor
<FormattedPlural value={10} one="message" other="messages" />
Result

FormattedList

Compatibilité navigateur

Cette fonctionnalité nécessite Intl.ListFormat dont le support navigateur est limité. Utilisez notre polyfill si vous prévoyez de les prendre en charge.

Ce composant utilise l'API formatList et Intl.ListFormat. Ses props correspondent à Intl.ListFormatOptions.

Props :

props: ListFormatOptions &
{
children: (chunksOrString: string | React.ReactElement[]) => ReactElement,
}

Exemple :

Lorsque la locale est en :

Live Editor
<FormattedList type="conjunction" value={['Me', 'myself', 'I']} />
Result
Live Editor
<FormattedList type="conjunction" value={['Me', <b>myself</b>, 'I']} />
Result

FormattedListParts

Compatibilité navigateur

Cette fonctionnalité nécessite Intl.ListFormat dont le support navigateur est limité. Utilisez notre polyfill si vous prévoyez de les prendre en charge.

Ce composant utilise l'API formatListToParts et Intl.ListFormat. Ses props correspondent à Intl.ListFormatOptions.

Props :

props: ListFormatOptions &
{
children: (chunks: Array<React.ReactElement | string>) => ReactElement,
}

Exemple :

Lorsque la locale est en :

Live Editor
<FormattedListParts type="conjunction" value={['Me', 'myself', 'I']}>
  {parts => (
    <>
      <b>{parts[0].value}</b>
      {parts[1].value}
      <small>{parts[2].value}</small>
      {parts[3].value}
      <small>{parts[4].value}</small>
    </>
  )}
</FormattedListParts>
Result

FormattedDisplayName

Compatibilité navigateur

Cette fonctionnalité nécessite Intl.DisplayNames dont le support navigateur est limité. Utilisez notre polyfill si vous prévoyez de les prendre en charge.

Ce composant utilise formatDisplayName et Intl.DisplayNames. Ses props correspondent à DisplayNameOptions. Vous aurez peut-être besoin d'un polyfill.

Props :

props: FormatDisplayNameOptions &
{
value: string | number | Record<string, unknown>,
}

Exemple :

Lorsque la locale est en :

Live Editor
<FormattedDisplayName type="language" value="zh-Hans-SG" />
Result
Live Editor
<FormattedDisplayName type="currency" value="JPY" />
Result

FormattedMessage

Ce composant utilise l'API formatMessage et possède des props qui correspondent à un Message Descriptor.

Props :

props: MessageDescriptor &
{
values: object,
tagName: string,
children: (chunks: ReactElement) => ReactElement,
}

Syntaxe des messages

Le formatage des chaînes/messages est une fonctionnalité essentielle de React Intl, basée sur le formatage de messages ICU via la syntaxe ICU. Cette syntaxe permet de définir des messages simples à complexes, de les traduire, puis de les formater à l'exécution.

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 Message Descriptor pour définir les messages par défaut de votre application. Les props de <FormattedMessage> correspondent à un Message Descriptor. Ces descripteurs sont particulièrement adaptés 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
}
Compilation des descripteurs

Les packages babel-plugin-formatjs et @formatjs/ts-transformer peuvent compiler les Message Descriptors définis dans les fichiers source JavaScript en AST pour optimiser les performances.

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 le message traduit à la source de l'id.

  4. Retomber sur la source du defaultMessage.

  5. Retomber sur l'id littéral du message.

Utilisation

Par défaut, <FormattedMessage> rendra la chaîne formatée dans un <React.Fragment>. Si vous devez personnaliser le rendu, vous pouvez soit l'encapsuler avec un autre élément React (recommandé), spécifier un tagName différent (par exemple 'div'), ou passer une fonction comme enfant.

Exemple :

Live Editor
<FormattedMessage
  id="app.greeting"
  description="Greeting to welcome the user to the app"
  defaultMessage="Hello, {name}!"
  values={{
    name: 'Eric',
  }}
/>
Result

Exemple : fonction comme enfant

Live Editor
<FormattedMessage id="title">{txt => <h1>{txt}</h1>}</FormattedMessage>
Result
message simple

Les messages peuvent être de simples chaînes sans espaces réservés, ce qui constitue le type de message le plus courant. Ce cas est hautement optimisé, tout en bénéficiant des avantages de la procédure de repli.

Formatage de texte enrichi

<FormattedMessage> prend également en charge le formatage de texte enrichi en spécifiant une balise XML dans le message et en résolvant cette balise dans la prop values. Voici un exemple :

Live Editor
<FormattedMessage
  id="app.greeting"
  description="Greeting to welcome the user to the app"
  defaultMessage="Hello, <b>Eric</b> {icon}"
  values={{
    b: chunks => <b>{chunks}</b>,
    icon: <svg />,
  }}
/>
Result

En permettant d'incorporer des balises XML, nous voulons nous assurer que le contexte n'est pas perdu lorsque vous devez styliser une partie de la chaîne. Dans un exemple plus complexe comme :

Live Editor
<FormattedMessage
  id="foo"
  defaultMessage="To buy a shoe, <a>visit our website</a> and <cta>buy a shoe</cta>"
  values={{
    a: chunks => (
      <a
        class="external_link"
        target="_blank"
        href="https://www.example.com/shoe"
      >
        {chunks}
      </a>
    ),
    cta: chunks => <strong class="important">{chunks}</strong>,
  }}
/>
Result

Fonction en tant qu'enfant

Puisque le formatage de texte enrichi permet d'incorporer des ReactElement, dans le scénario où une fonction est passée comme enfant, cette fonction recevra les fragments du message formaté comme paramètre unique.

Live Editor
<FormattedMessage
  id="foo"
  defaultMessage="To buy a shoe, <a>visit our website</a> and <cta>buy a shoe</cta>"
  values={{
    a: chunks => (
      <a
        class="external_link"
        target="_blank"
        href="https://www.example.com/shoe"
      >
        {chunks}
      </a>
    ),
    cta: chunks => <strong class="important">{chunks}</strong>,
  }}
>
  {chunks => <h2>{chunks}</h2>}
</FormattedMessage>
Result

L'ensemble du texte enrichi est traduit ensemble, ce qui produit un résultat de meilleure qualité. Cela permet également d'atteindre la parité fonctionnelle avec d'autres bibliothèques de traduction comme fluent de Mozilla (utilisant le concept d'overlays).

Cette extension permet également aux utilisateurs d'exploiter potentiellement d'autres formats de texte enrichi, comme le Markdown.