Zum Hauptinhalt springen

Imperative API

Inoffizielle Beta-Übersetzung

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

React Intl basiert auf mehreren API-Schichten und stellt diese bereit. Bei der Nutzung interagieren Sie sowohl mit der hier dokumentierten API als auch mit React-Komponenten.

Warum imperative API?

Während unsere Komponenten nahtlose React-Integration bieten, wird die imperative API in mehreren Szenarien empfohlen (manchmal benötigt):

  • Setzen von Textattributen wie title, aria-label etc., wo React-Komponenten nicht verwendbar sind (z.B. <img title/>)

  • Formatierung von Text/Datumsangaben in non-React-Umgebungen wie Node, Server-APIs, Redux-Store, Tests...

  • Hochperformante Szenarien, wo die Anzahl gerenderter React-Komponenten zum Engpass wird (z.B. Finanz-Portfoliodarstellung, virtuelle Tabellen mit vielen Zellen...)

Das intl-Objekt

Das Herzstück von react-intl ist das intl-Objekt (vom Typ IntlShape). Es speichert einen Cache aller Intl.*-APIs, Konfigurationen, kompilierten Nachrichten etc. Der Lebenszyklus des intl-Objekts ist typischerweise an das locale und die enthaltenen messages gebunden. Bei locale-Wechsel sollte es neu erstellt werden.

Tipp

Das intl-Objekt sollte aus Performance-Gründen möglichst wiederverwendet werden.

Es gibt mehrere Wege, auf das intl-Objekt zuzugreifen:

  • useIntl-Hook: Nach Deklaration Ihres IntlProvider erhalten Sie Zugriff auf das intl-Objekt via Aufruf in funktionalen React-Komponenten

  • injectIntl-HOC: In class-basierten Komponenten wrappen Sie diese mit dem injectIntl-HOC; intl wird dann als prop verfügbar

  • createIntl: In non-React-Umgebungen (Node, Vue, Angular, Tests etc.) erstellen Sie direkt ein intl-Objekt mit derselben Konfiguration wie für IntlProvider

useIntl-Hook

Für funktionale Komponenten ist der useIntl-Hook praktisch. Dieser useIntl-Hook erwartet keine Optionen als Argument. Typische Nutzung:

import React from 'react'
import {useIntl, FormattedDate} from 'react-intl'

const FunctionComponent: React.FC<{date: number | Date}> = ({date}) => {
const intl = useIntl()
return (
<span title={intl.formatDate(date)}>
<FormattedDate value={date} />
</span>
)
}

export default FunctionComponent

Um die API-Oberfläche sauber und einfach zu halten, bieten wir nur den useIntl-Hook im Paket an. Bei Bedarf können Benutzer diesen integrierten Hook wrappen, um benutzerdefinierte Hooks wie useFormatMessage einfach zu erstellen. Weitere allgemeine Informationen finden Sie in der offiziellen Einführung in React-Hooks auf der React-Website.

injectIntl-HOC

type WrappedComponentProps<IntlPropName extends string = 'intl'> = {
[k in IntlPropName]: IntlShape
}

type WithIntlProps<P> = Omit<P, keyof WrappedComponentProps> & {
forwardedRef?: React.Ref<any>
}

function injectIntl<
IntlPropName extends string = 'intl',
P extends WrappedComponentProps<IntlPropName> = WrappedComponentProps<any>,
>(
WrappedComponent: React.ComponentType<P>,
options?: Opts<IntlPropName>
): React.ComponentType<WithIntlProps<P>> & {
WrappedComponent: typeof WrappedComponent
}

Diese vom react-intl-Paket exportierte Factory erzeugt Higher-Order Components (HOCs). Sie wrappt React-Komponenten und injiziert die imperative Formatierungs-API via props (ähnlich dem connect-to-stores-Pattern in Flux-Implementierungen).

Standardmäßig wird die API via props.intl bereitgestellt, aber durch options.intlPropName konfigurierbar. Der Prop-Wert entspricht dem Typ IntlShape.

import React from 'react'
import {injectIntl, FormattedDate} from 'react-intl'

interface Props {
date: Date | number
}

const FunctionalComponent: React.FC<Props> = props => {
const {
date,
intl, // Injected by `injectIntl`
} = props
return (
<span title={intl.formatDate(date)}>
<FormattedDate value={date} />
</span>
)
}

export default injectIntl(FunctionalComponent)

createIntl

Dies ermöglicht die Erstellung eines IntlShape-Objekts ohne Verwendung von Provider. Dies ermöglicht die Formatierung von Elementen außerhalb des React-Lebenszyklus unter Wiederverwendung desselben intl-Objekts. Beispiel:

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)

// Call imperatively
intl.formatNumber(20)

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

createIntlCache

Erstellt eine Cache-Instanz für die globale Nutzung über alle Locales hinweg. Dies memoisiert zuvor erstellte Intl.*-Konstruktoren für bessere Performance und ist lediglich ein In-Memory-Cache.

IntlShape

interface IntlConfig {
locale: string
timeZone?: string
formats: CustomFormats
textComponent?: React.ComponentType | keyof React.JSX.IntrinsicElements
messages: Record<string, string> | Record<string, MessageFormatElement[]>
defaultLocale: string
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

Dieses Interface wird vom react-intl-Paket exportiert und mit dem injectIntl-HOC kombiniert.

Das via injectIntl injizierte props.intl-Objekt besteht aus zwei Teilen:

  • IntlConfig: Die Intl-Metadaten, die als Props an das übergeordnete <IntlProvider>-Element übergeben werden.

  • IntlFormatters: Die imperative Formatierungs-API, wie unten beschrieben.

locale, formats und messages

Das aktuelle Locale des Benutzers und in welchem die App gerendert werden soll. defaultLocale und defaultFormats dienen als Fallback oder während der Entwicklung und repräsentieren die Standardeinstellungen der App. Beachten Sie, dass es kein defaultMessages gibt, da jeder Nachrichtendeskriptor ein defaultMessage bereitstellt.

defaultLocale und defaultFormats

Standard-Locale und -Formate für den Fall, dass eine Nachricht nicht übersetzt ist (fehlt in messages). defaultLocale sollte das Locale sein, in dem die defaultMessages deklariert sind, um Satzkohärenz in einem Locale zu gewährleisten. Ohne defaultLocale oder bei falscher Konfiguration kann es vorkommen, dass ein Satz auf Englisch ist, aber eingebettete Datums-/Zeitangaben auf Spanisch erscheinen.

textComponent

Ermöglicht die Konfiguration des Standard-Wrappers für die <Formatted*>-Komponenten von React Intl. Wenn nicht angegeben, wird <React.Fragment> verwendet. Vor Version 3 kam span zum Einsatz; weitere Details finden Sie im Migrationsleitfaden.

onError

Ermöglicht die Bereitstellung eines benutzerdefinierten Fehlerhandlers. Standardmäßig werden Fehlermeldungen via console.error protokolliert, sofern NODE_ENV nicht auf production gesetzt ist.

wrapRichTextChunksInFragment

Bei der Formatierung von Rich-Text-Nachrichten erzeugt die Ausgabe den Typ Array<string | React.ReactElement>, was einen Key-Fehler auslösen kann. Dies umschließt die Ausgabe in einem einzelnen React.Fragment, um dies zu unterdrücken.

defaultRichTextElements

Eine Zuordnung von Tags zu Rich-Text-Formatierungsfunktionen. Dient der zentralisierten Formatierung gängiger Tags wie <b>, <p> oder der Durchsetzung von Design-Systemen im Codebase (z.B. standardisierte <a> oder <button>). Siehe https://github.com/formatjs/formatjs/issues/1752 für weitere Details.

formatDate

function formatDate(
value: number | Date | string,
options?: Intl.DateTimeFormatOptions & {format?: string}
): string

Diese Funktion gibt eine formatierte Datumszeichenkette zurück. Erwartet einen als Datum parsbaren value (d.h. isFinite(new Date(value)) ist wahr) und akzeptiert options, die DateTimeFormatOptions entsprechen.

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

formatTime

function formatTime(
value: number | Date | string,
options?: Intl.DateTimeFormatOptions & {format?: string}
): string

Diese Funktion gibt ebenfalls eine formatierte Datumszeichenkette zurück, unterscheidet sich jedoch von formatDate durch folgende Standardoptionen:

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

Erwartet einen als Datum parsbaren value (d.h. isFinite(new Date(value)) ist wahr) und akzeptiert options, die DateTimeFormatOptions entsprechen.

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

formatDateTimeRange

Browserunterstützung

Erfordert Intl.DateTimeFormat.prototype.formatRange, das nur eingeschränkt unterstützt wird. Verwenden Sie unser Polyfill für entsprechende Browser.

function formatDateTimeRange(
from: number | Date | string,
to: number | Date | string,
options?: Intl.DateTimeFormatOptions & {format?: string}
): string

Gibt eine formatierte Datums-/Zeitbereichszeichenkette zurück. Sowohl from als auch to müssen als Datum parsbar sein (d.h. isFinite(new Date(value)) muss wahr sein).

Erwartet 2 Werte (ein from-Datum und ein to-Datum) und akzeptiert options, die DateTimeFormatOptions entsprechen.

Live Editor
intl.formatDateTimeRange(new Date('2020-1-1'), new Date('2020-1-15'))
Result

formatRelativeTime

Browser-Unterstützung

Dies erfordert Intl.RelativeTimeFormat mit begrenzter Browserunterstützung. Verwenden Sie unser Polyfill für Kompatibilität.

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

Gibt eine formatierte relative Zeitzeichenkette zurück (z.B. "vor 1 Stunde"). Erwartet einen numerischen value, eine unit und options, die Intl.RelativeTimeFormatOptions entsprechen.

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

formatNumber

Verwendet Optionen von Intl.NumberFormat.

function formatNumber(
value: number,
options?: Intl.NumberFormatOptions & {format?: string}
): string

Gibt eine formatierte Zahlenzeichenkette zurück. Erwartet einen als Zahl parsbaren value und akzeptiert options, die NumberFormatOptions entsprechen.

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

Zahlenformatierung mit unit

Dies ist Teil von ES2020 NumberFormat. Wir stellen ein Polyfill hier bereit. Die Typen von react-intl erlauben die Übergabe einer zulässigen Einheit:

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'

Gibt eine Pluralkategoriezeichenkette zurück: "zero", "one", "two", "few", "many" oder "other". Erwartet einen als Zahl parsbaren value und akzeptiert options, die PluralFormatOptions entsprechen.

Niedrige Abstraktionsebene – die Ausgabe kann in einer switch-Anweisung verwendet werden, um spezifische Anzeigetexte auszuwählen.

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

Nur für Apps mit einer Sprache geeignet. Für mehrsprachige Apps stattdessen formatMessage verwenden.

formatList

Browser-Unterstützung

Dies erfordert Intl.ListFormat, das nur eingeschränkte Browserunterstützung bietet. Verwenden Sie unser Polyfill, falls Sie diese Browser unterstützen möchten.

type ListFormatOptions = {
type?: 'disjunction' | 'conjunction' | 'unit'
style?: 'long' | 'short' | 'narrow'
}

function formatList(
elements: (string | React.ReactNode)[],
options?: Intl.ListFormatOptions
): string | React.ReactNode[]

Diese Funktion ermöglicht die i18n-sichere Verkettung von Listen. Beispiel bei en-Locale:

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

formatDisplayName

Browser-Unterstützung

Dies erfordert Intl.DisplayNames, das nur eingeschränkte Browserunterstützung bietet. Verwenden Sie unser Polyfill, falls Sie diese Browser unterstützen möchten.

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

Anwendungsbeispiele:

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

Nachrichtensyntax

Die String-/Nachrichtenformatierung ist eine Kernfunktion von React Intl und basiert auf ICU Message Formatting mittels ICU Message Syntax. Diese Syntax ermöglicht die Definition, Übersetzung und Laufzeitformatierung einfacher bis komplexer Nachrichten.

Einfache Nachricht:

Hello, {name}

Komplexe Nachricht:

Hello, {name}, you have {itemCount, plural,
=0 {no items}
one {# item}
other {# items}
}.

Siehe: Nachrichtensyntax-Leitfaden.

Nachrichtendeskriptor

React Intl verwendet Nachrichtendeskriptoren zur Definition von Standardnachrichten, die an formatMessage übergeben werden. Sie enthalten alle notwendigen Daten für Übersetzungen mit folgenden Eigenschaften:

  • id: Eindeutige, stabile Kennung der Nachricht

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

  • defaultMessage: Standardnachricht (üblicherweise auf Englisch)

type MessageDescriptor = {
id: string
defaultMessage?: string
description?: string | object
}
Nachrichtendeskriptor-Extraktion

Inline deklarierte Nachrichten können mit unserem CLI aus Quellcode extrahiert werden.

Fallbacks bei der Nachrichtenformatierung

Die Nachrichtenformatierungs-APIs gehen einen Schritt weiter, um Fallbacks für häufige Fehlersituationen bereitzustellen; mindestens sollte immer ein nicht-leerer String zurückgegeben werden. Hier ist der Fallback-Algorithmus für die Nachrichtenformatierung:

  1. Formatierung der übersetzten Nachricht via id aus <IntlProvider>

  2. Fallback: defaultMessage formatieren.

  3. Fallback auf Originaltext der übersetzten Nachricht via id

  4. Fallback auf Originaltext von defaultMessage

  5. Fallback: Literale Nachricht id ausgeben.

"Originaltext" bezeichnet hier die unveränderte Vorlage ohne Substitutionen.

Verwendung

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[]

Diese Funktion formatiert Nachrichtenstrings. Erwartet wird ein MessageDescriptor mit mindestens id und ein values-Objekt zur Platzhalterfüllung.

Wenn eine übersetzte Nachricht mit der id via messages-Prop an den <IntlProvider> übergeben wurde, wird diese formatiert, andernfalls wird auf die Formatierung von defaultMessage zurückgegriffen. Details siehe Formatierungsfallbacks.

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

mit 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

mit Rich-Text-Formatierung

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

Die Nachricht wurde mittels defineMessages für Extraktion via babel-plugin-formatjs definiert, ist aber ohne Babel-Plugin optional.

Einfache Nachrichten

Nachrichten ohne Platzhalter sind zulässig und stellen den häufigsten Typ dar.

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

Diese Funktionen werden vom react-intl-Paket exportiert und dienen als Hook für unser CLI und Babel/TS-Plugin zur Kompilierung von Standardnachrichten in JavaScript-Dateien. Diese Funktion gibt das übergebene Nachrichtendeskriptor-Map-Objekt unverändert zurück.

import {defineMessages, defineMessage} from 'react-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',
})