Zum Hauptinhalt springen

Upgrade-Leitfaden (v1 → v2)

Inoffizielle Beta-Übersetzung

Diese Seite wurde von PageTurner AI übersetzt (Beta). Nicht offiziell vom Projekt unterstützt. Fehler gefunden? Problem melden →

React 0.14 oder 15 verwenden

React Intl v2 hat eine Peer-Abhängigkeit von react@^0.14.0 || ^15.0.0-0 und nutzt Funktionen und Änderungen in React 0.14. Es funktioniert ebenfalls mit React 15.

Anpassung der Locale-Daten-Integration

Die Locale-Daten-Module in React Intl v2 wurden überarbeitet, um Daten bereitzustellen statt React Intls internes Locale-Daten-Register zu mutieren. Die react-intl/locale-data/*-Dateien sind zudem vom ReactIntl-Global entkoppelt und stellen stattdessen UMD-Module mit einem neuen ReactIntlLocaleData-Global bereit. Diese Änderungen erfordern Anpassungen bei der Registrierung benötigter Locale-Daten im Browser.

Aufruf von addLocaleData() im Browser hinzufügen

Es gibt nun eine addLocaleData()-Funktion, die mit den geladenen Locale-Daten aufgerufen werden muss. Implementieren Sie dies im Haupt-Entry-Point Ihres Client-JavaScript-Codes:

Dies setzt voraus, dass ein Locale-Daten-<script>-Tag basierend auf der Anfrage hinzugefügt wird; z.B. für französischsprachige Nutzer:

<script src="react-intl/locale-data/fr.js"></script>

Verwendung von <script src="react-intl/dist/react-intl.js>

if ('ReactIntl' in window && 'ReactIntlLocaleData' in window) {
Object.keys(ReactIntlLocaleData).forEach(lang => {
ReactIntl.addLocaleData(ReactIntlLocaleData[lang])
})
}

Verwendung von Browserify/Webpack zum Laden von React Intl

import {addLocaleData} from 'react-intl'

if ('ReactIntlLocaleData' in window) {
Object.keys(ReactIntlLocaleData).forEach(lang => {
addLocaleData(ReactIntlLocaleData[lang])
})
}
Info

Diese Entkopplung der Bibliothek von den Locale-Daten ermöglicht das Laden per <script async>. Bei asynchronen Skripten muss Ihr Client-Bootstrapping-Code auf das load-Ereignis warten, inklusive des oben gezeigten Codes.

Entfernung des Intl-Mixins

Das IntlMixin wurde in React Intl v2 entfernt. Das Mixin hatte zwei Funktionen: Es verbreitete automatisch locales, formats und messages durch die Komponentenhierarchie und stellte eine imperative API über format*()-Funktionen bereit. Diese Aufgaben übernehmen nun <IntlProvider> bzw. injectIntl():

Umstellung auf IntlProvider

In React Intl v1 wurde das IntlMixin der Root-Komponente (z.B. <App>) hinzugefügt. Entfernen Sie das IntlMixin und umschließen Sie stattdessen Ihre Root-Komponente mit <IntlProvider>:

import ReactDOM from 'react-dom'
import {IntlProvider} from 'react-intl'

ReactDOM.render(
<IntlProvider locale="en">
<App />
</IntlProvider>,
document.getElementById('container')
)
Info

Die locale-Prop ist singular, erforderlich und akzeptiert nur String-Werte. Dies vereinfacht die pluralische locales-Prop des IntlMixin.

Umstellung auf injectIntl()

Das IntlMixin stellte auch die imperative API für benutzerdefinierte Komponenten bereit, um format*()-Methoden (z.B. formatDate()) für Attribute wie title oder aria zu nutzen. Entfernen Sie das IntlMixin und verwenden Sie stattdessen die injectIntl()-HOC-Factory, um die imperative API über props einzubinden.

Beispiel einer stateless <RelativeTime>-Komponente mit injectIntl() und der imperativen formatDate()-API:

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() ähnelt einer connect()-HOC-Factory aus Flux-Frameworks zum Verbinden von Komponenten mit Stores.

Änderungen bei der Nachrichtenformatierung

Die Nachrichtenformatierung in React Intl v2 hat sich grundlegend geändert! Dies ist die disruptivste Änderung beim Upgrade von v1 auf v2, ermöglicht aber wichtige neue Funktionen.

React Intl v2 führt das Konzept des Message Descriptors ein, mit dem Standard-String-Nachrichten definiert werden können. Ein Message Descriptor ist ein Objekt mit folgenden Eigenschaften, wobei nur id verpflichtend ist:

  • id: Ein eindeutiger, stabiler Bezeichner für die Nachricht

  • description: Kontext für Übersetzer zur Verwendung in der UI

  • defaultMessage: Die Standardnachricht (wahrscheinlich auf Englisch)

Info

Dieser Upgrade-Leitfaden konzentriert sich auf Message Descriptors, die nur eine id-Eigenschaft enthalten.

messages-Objekt vereinfachen

React Intl v2 unterstützt keine verschachtelten messages-Objekte mehr. Stattdessen muss die Sammlung übersetzter String-Nachrichten, die an <IntlProvider> übergeben wird, flach sein. Diese bewusste Designentscheidung vereinfacht die Struktur und erhöht die Flexibilität. React Intl v2 wendet keine speziellen Semantiken auf Strings mit Punkten an; z.B. "namespaced.string_id".

Apps mit verschachtelter messages-Struktur können folgende Funktion verwenden, um ihr Objekt gemäß der Semantik von React Intl v1 zu vereinfachen:

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)
Info

Nachrichten-IDs können weiterhin "." enthalten, die IDs selbst bleiben also gleich. Nur die Struktur des messages-Objekts muss angepasst werden.

getIntlMessage()-Aufrufe durch Message Descriptors ersetzen

Die getIntlMessage()-Methode des IntlMixin wurde in React Intl v2 entfernt. Sie war lediglich ein Helfer, der Nachrichten-IDs mit "." interpretierte, indem sie die übersetzte Nachricht in einem verschachtelten messages-Objekt nachschlug. Mit dem Wegfall von IntlMixin und der Umstellung auf ein flaches messages-Objekt wurde diese Methode entfernt.

Alle Aufrufe von getIntlMessage() müssen durch einen Message Descriptor ersetzt werden.

Ersetze:

this.getIntlMessage('some.message.id')

getIntlMessage('foo.bar.baz')

{
id: 'some.message.id'
}

formatMessage()-Aufrufe aktualisieren

Ein typisches Muster beim Aufruf von formatMessage() ist, einen Aufruf von getIntlMessage() zu verschachteln. Diese können leicht aktualisiert werden:

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)
Info

In React Intl v2 wird die Funktion formatMessage() über injectIntl() eingebunden.

FormattedMessage- und FormattedHTMLMessage-Instanzen aktualisieren

Die Props für diese beiden Komponenten haben sich in React Intl v2 vollständig geändert. Anstatt eine message-Prop zu verwenden und alle anderen Props als Werte zum Ausfüllen von Platzhaltern in einer Nachricht zu behandeln, erwarten <FormattedMessage> und <FormattedHTMLMessage> nun dieselben Props wie ein Message Descriptor plus eine neue values-Prop.

Die neue values-Prop fasst alle Platzhalterwerte der Nachricht in einem Objekt zusammen.

Das folgende Beispiel zeigt, wie eine <FormattedMessage>-Instanz aktualisiert wird, um die neuen Props zu nutzen und den getIntlMessage()-Aufruf zu entfernen:

1.0:

<FormattedMessage message={this.getIntlMessage('greeting')} name="Eric" />

2.0:

<FormattedMessage id="greeting" values={{name: 'Eric'}} />

2.0:

In React Intl v2 wurden kleinere Änderungen an der Spezifikation der Referenzzeit "now" für die Formatierung relativer Zeiten vorgenommen. Da dieser Wert selten außerhalb von Testcode angegeben wird, könnte er in Ihrer Anwendung nicht vorhanden sein.

now-Prop von FormattedRelative in initialNow umbenennen

<FormattedRelative>-Instanzen in React Intl v2 erhalten ein neues Feature: Sie "ticken" jetzt und bleiben aktuell. Da die Zeit voranschreitet, war der Prop-Name now irreführend, daher wurde er in initialNow umbenannt. Alle <FormattedRelative>-Instanzen mit now sollten den Prop-Namen auf initialNow aktualisieren:

1.0:

<FormattedRelative value={date} now={otherDate} />

2.0:

<FormattedRelative value={date} initialNow={otherDate} />
Info

Die <IntlProvider>-Komponente bietet außerdem eine initialNow-Prop, der ein Wert zugewiesen werden kann, um die Referenzzeit "now" für alle <FormattedRelative>-Instanzen zu stabilisieren. Dies ist besonders nützlich für universelle/isomorphe Anwendungen, um korrekte React-Prüfsummen zwischen Server und Client beim initialen Rendering sicherzustellen.

Zusammenführen des zweiten und dritten Arguments von formatRelative()

Die Signatur der formatRelative()-Funktion wurde an die anderen format*()-Funktionen angeglichen und akzeptiert in React Intl v2 nur zwei Argumente: value und options. Um eine "now"-Referenzzeit anzugeben, fügen Sie diese dem options-Argument hinzu und entfernen Sie das dritte formatOptions-Argument:

1.0:

let relative = this.formatRelative(date, {units: 'hour'}, {now: otherDate})

2.0:

let relative = this.props.intl.formatRelative(date, {
units: 'hour',
now: otherDate,
})
Info

In React Intl v2 wird die formatRelative()-Funktion via injectIntl() eingefügt.