Guide de mise à niveau (v1 -> v2)
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 →
Utiliser React 0.14 ou 15
React Intl v2 nécessite une dépendance peer sur react@^0.14.0 || ^15.0.0-0 et tire désormais parti des fonctionnalités et changements de React 0.14 tout en étant compatible avec React 15.
Mettre à jour l'ajout des données de locale
Les modules de données locales dans React Intl v2 ont été refactorisés pour fournir des données au lieu de muter le registre interne des locales de React Intl. Les fichiers react-intl/locale-data/* sont également découplés du global ReactIntl et fournissent désormais des modules UMD avec un nouveau global ReactIntlLocaleData. Ces changements impliquent que les applications doivent mettre à jour leur méthode d'enregistrement des données locales dans le navigateur.
Ajouter un appel à addLocaleData() dans le navigateur
Une fonction addLocaleData() doit désormais être appelée avec les données locales chargées. Vous pouvez procéder ainsi dans votre point d'entrée JavaScript principal côté client :
Cela suppose qu'une balise <script> de données locale est ajoutée en fonction de la requête ; par exemple pour des utilisateurs francophones :
<script src="react-intl/locale-data/fr.js"></script>
Utilisation de <script src="react-intl/dist/react-intl.js>
if ('ReactIntl' in window && 'ReactIntlLocaleData' in window) {
Object.keys(ReactIntlLocaleData).forEach(lang => {
ReactIntl.addLocaleData(ReactIntlLocaleData[lang])
})
}
Utilisation de Browserify/Webpack pour charger React Intl
import {addLocaleData} from 'react-intl'
if ('ReactIntlLocaleData' in window) {
Object.keys(ReactIntlLocaleData).forEach(lang => {
addLocaleData(ReactIntlLocaleData[lang])
})
}
Ce découplage de la bibliothèque et des données locales permet de charger les fichiers via <script async>. Avec des scripts asynchrones, votre code d'initialisation client devra attendre l'événement load, y compris pour le code ci-dessus.
Supprimer le mixin Intl
Le IntlMixin a été retiré dans React Intl v2. Ce mixin assurait deux fonctions : il propageait automatiquement locales, formats et messages dans la hiérarchie de l'application, et fournissait une API impérative via les fonctions format*(). Ces rôles sont désormais respectivement gérés par <IntlProvider> et injectIntl() :
Passer à IntlProvider
Dans React Intl v1, vous ajoutiez le IntlMixin à votre composant racine (ex: <App>). Supprimez le IntlMixin et encapsulez plutôt votre composant racine avec <IntlProvider> :
import ReactDOM from 'react-dom'
import {IntlProvider} from 'react-intl'
ReactDOM.render(
<IntlProvider locale="en">
<App />
</IntlProvider>,
document.getElementById('container')
)
La prop locale est singulière, obligatoire, et n'accepte qu'une valeur chaîne. Cela simplifie la prop plurielle locales utilisée par l'IntlMixin.
Passer à injectIntl()
L'IntlMixin fournissait également l'API impérative permettant aux composants personnalisés d'utiliser les méthodes format*() ; par exemple formatDate() pour obtenir des chaînes formatées utilisables dans des attributs comme title ou aria. Supprimez l'IntlMixin et utilisez plutôt la fonction factory de composant d'ordre supérieur (HOC) injectIntl() pour injecter l'API impérative via les props.
Voici un exemple de composant stateless personnalisé <RelativeTime> utilisant injectIntl() et l'API impérative formatDate() :
import React from 'react'
import {injectIntl, FormattedRelative} from 'react-intl'
const to2Digits = num => `${num < 10 ? `0${num}` : num}`
const RelativeTime = ({date, intl}) => {
date = new Date(date)
let year = date.getFullYear()
let month = date.getMonth() + 1
let day = date.getDate()
let formattedDate = intl.formatDate(date, {
year: 'long',
month: 'numeric',
day: 'numeric',
})
return (
<time
dateTime={`${year}-${to2Digits(month)}-${to2Digits(day)}`}
title={formattedDate}
>
<FormattedRelative value={date} />
</time>
)
}
export default injectIntl(RelativeTime)
injectIntl() est similaire à une fonction factory HOC connect() que vous pourriez trouver dans un framework Flux pour connecter un composant à un store.
Changer la méthode de formatage des messages
La méthode de formatage des messages chaînes dans React Intl v2 a radicalement changé ! Il s'agit du changement le plus perturbant lors de la mise à niveau de v1 vers v2, mais il permet de nombreuses nouvelles fonctionnalités.
React Intl v2 introduit un nouveau concept de Descripteur de message qui peut être utilisé pour définir les messages chaînes par défaut d'une application. Un descripteur de message est un objet avec les propriétés suivantes, id étant la seule prop obligatoire :
-
id: Un identifiant unique et stable pour le message -
description: Contexte destiné au traducteur sur l'utilisation dans l'interface -
defaultMessage: Le message par défaut (probablement en anglais)
Ce guide de mise à niveau se concentrera sur l'utilisation de descripteurs de message contenant uniquement la propriété id.
Aplatir l'objet messages
React Intl v2 ne prend plus en charge les objets messages imbriqués. La collection de messages traduits passée à <IntlProvider> doit désormais être plate. Ce choix de conception explicite simplifie la structure tout en augmentant la flexibilité. React Intl v2 n'applique aucune sémantique spéciale aux chaînes contenant des points (par ex. "namespaced.string_id").
Les applications utilisant une structure d'objet messages imbriquée peuvent utiliser la fonction suivante pour aplatir leur objet selon la sémantique de React Intl v1 :
function flattenMessages(nestedMessages, prefix = '') {
return Object.keys(nestedMessages).reduce((messages, key) => {
let value = nestedMessages[key]
let prefixedKey = prefix ? `${prefix}.${key}` : key
if (typeof value === 'string') {
messages[prefixedKey] = value
} else {
Object.assign(messages, flattenMessages(value, prefixedKey))
}
return messages
}, {})
}
let messages = flattenMessages(nestedMessages)
Les identifiants de message peuvent toujours contenir des ".", donc les IDs eux-mêmes restent identiques. Seule la structure de l'objet messages doit changer.
Remplacer les appels getIntlMessage() par des descripteurs de message
La méthode getIntlMessage() fournie par IntlMixin a été supprimée dans React Intl v2. C'était simplement un helper qui interprétait un identifiant de message avec des "." en recherchant le message traduit dans un objet messages imbriqué. Avec la suppression d'IntlMixin et le passage à un objet messages plat, cette méthode a été retirée.
Tous les appels à getIntlMessage() doivent être remplacés par un descripteur de message.
Remplacer :
this.getIntlMessage('some.message.id')
Avec :
{
id: 'some.message.id'
}
Mettre à jour les appels à formatMessage()
Un schéma typique lors de l'appel à formatMessage() consiste à imbriquer un appel à getIntlMessage(). Ces cas peuvent être mis à jour facilement :
1.0 :
let message = this.formatMessage(this.getIntlMessage('some.message.id'), values)
2.0 :
let message = this.props.intl.formatMessage({id: 'some.message.id'}, values)
Dans React Intl v2, la fonction formatMessage() est injectée via injectIntl().
Mettre à jour les instances de FormattedMessage et FormattedHTMLMessage
Les props de ces deux composants ont complètement changé dans React Intl v2. Au lieu de prendre une prop message et de traiter toutes les autres props comme valeurs à insérer dans les espaces réservés d'un message, <FormattedMessage> et <FormattedHTMLMessage> prennent désormais les mêmes props qu'un descripteur de message, plus une nouvelle prop values.
La nouvelle prop values regroupe toutes les valeurs des espaces réservés du message dans un objet.
L'exemple suivant montre comment mettre à jour une instance de <FormattedMessage> pour utiliser les nouvelles props et supprimer l'appel à getIntlMessage() :
1.0 :
<FormattedMessage message={this.getIntlMessage('greeting')} name="Eric" />
2.0 :
<FormattedMessage id="greeting" values={{name: 'Eric'}} />
Mise à jour de la mise en forme des temps relatifs
Des modifications mineures ont été apportées à la façon dont le temps de référence "maintenant" est spécifié lors du formatage des temps relatifs dans React Intl v2. Il est rare de spécifier cette valeur en dehors des tests, donc elle pourrait ne pas exister dans votre application.
Renommer la prop now de FormattedRelative en initialNow
Une nouvelle fonctionnalité a été ajoutée aux instances de <FormattedRelative> dans React Intl v2 : elles "raffraîchissent" désormais leur valeur pour rester à jour. Comme le temps avance, il était déroutant d'avoir une prop nommée now, donc elle a été renommée en initialNow. Toutes les instances de <FormattedRelative> utilisant now doivent mettre à jour le nom de la prop en initialNow :
1.0 :
<FormattedRelative value={date} now={otherDate} />
2.0 :
<FormattedRelative value={date} initialNow={otherDate} />
Le composant <IntlProvider> dispose également d'une prop initialNow qui peut être assignée pour stabiliser la référence temporelle "maintenant" pour toutes les instances de <FormattedRelative>. Ceci est particulièrement utile dans les applications universelles/isomorphes pour garantir les checksums React entre le rendu initial serveur et client.
Fusion des deuxième et troisième arguments de formatRelative()
La signature de la fonction formatRelative() a été alignée sur les autres fonctions format*(). Dans React Intl v2, elle n'accepte plus que deux arguments : value et options. Pour spécifier une référence temporelle "now", ajoutez-la à l'argument options et supprimez le troisième argument formatOptions :
1.0 :
let relative = this.formatRelative(date, {units: 'hour'}, {now: otherDate})
2.0 :
let relative = this.props.intl.formatRelative(date, {
units: 'hour',
now: otherDate,
})
Dans React Intl v2, la fonction formatRelative() est injectée via injectIntl().