Wie man Zahlen für verschiedene Spracheinstellungen in Next.js (Pages Router) v16 formatiert
Zahlen mit sprachspezifischen Trennzeichen anzeigen
Problem
Zahlen werden weltweit unterschiedlich geschrieben. Was in den Vereinigten Staaten als 10,000.5 erscheint, wird in Deutschland zu 10.000,5 - Kommas und Punkte tauschen ihre Rollen vollständig. Dies ist keine Frage der Präferenz oder des Stils, sondern der Lesbarkeit. Ein deutscher Benutzer, der 10,000.5 sieht, könnte es als zehn lesen und die Gruppierungstrennzeichen ignorieren. Ein amerikanischer Benutzer, der 10.000,5 sieht, könnte es als zehntausend lesen und das Dezimaltrennzeichen ignorieren. Die gleichen Ziffern, entgegengesetzte Bedeutungen.
Wenn Anwendungen Zahlen ohne lokalisierungsbewusstes Formatting anzeigen, riskieren sie, Benutzer zu verwirren oder falsche Informationen zu vermitteln. Währungsbeträge, Prozentsätze, Messungen und Statistiken hängen alle von regionalen Konventionen ab, die Benutzer seit ihrer Kindheit gelernt haben.
Lösung
Formatieren Sie Zahlen basierend auf der Locale des Benutzers und verwenden Sie regionale Regeln für Dezimal- und Gruppierungstrennzeichen. Dies verwandelt numerische Werte in Zeichenketten, die den Formatierungsregeln folgen, die Benutzern in ihrer Region vertraut sind.
react-intl bietet zwei Ansätze: die <FormattedNumber>-Komponente für deklarative Formatierung in JSX und die formatNumber-Methode aus dem useIntl-Hook für imperative Formatierung. Beide basieren auf der Intl.NumberFormat-API des Browsers und wenden automatisch die in Ihrem IntlProvider konfigurierte Locale an. Die formatierte Ausgabe respektiert regionale Konventionen für Tausendertrennzeichen, Dezimalpunkte und Zifferngruppierung.
Schritte
1. Erstellen Sie eine Komponente, die Zahlen deklarativ formatiert
Die <FormattedNumber>-Komponente verwendet die formatNumber- und Intl.NumberFormat-APIs und akzeptiert eine value-Prop zusammen mit Optionen, die Intl.NumberFormatOptions entsprechen.
import { FormattedNumber } from "react-intl";
export default function ProductPrice({ price }: { price: number }) {
return (
<div>
<FormattedNumber value={price} />
</div>
);
}
Standardmäßig rendert <FormattedNumber> die formatierte Zahl in ein React.Fragment. Die Komponente liest die Locale vom nächsten IntlProvider und wendet die entsprechenden Formatierungsregeln an.
2. Zahlen mit spezifischen Optionen formatieren
Übergeben Sie Formatierungsoptionen, um zu steuern, wie Zahlen dargestellt werden. Häufige Optionen sind minimumFractionDigits, maximumFractionDigits und style.
import { FormattedNumber } from "react-intl";
export default function Statistics({ value }: { value: number }) {
return (
<dl>
<dt>Gesamtnutzer</dt>
<dd>
<FormattedNumber
value={value}
minimumFractionDigits={0}
maximumFractionDigits={0}
/>
</dd>
<dt>Konversionsrate</dt>
<dd>
<FormattedNumber
value={value / 100}
style="percent"
minimumFractionDigits={2}
/>
</dd>
</dl>
);
}
Diese Props entsprechen den Intl.NumberFormatOptions und geben Ihnen Kontrolle über Präzision und Darstellung, während gleichzeitig lokalspezifische Trennzeichen beibehalten werden.
3. Zahlen imperativ mit dem useIntl-Hook formatieren
Wenn eine Komponente als Funktionskomponente ausgedrückt werden kann, bietet der useIntl-Hook Zugriff auf das intl-Objekt, das eine formatNumber-Methode enthält.
import { useIntl } from "react-intl";
export default function DataTable({ rows }: { rows: number[] }) {
const intl = useIntl();
return (
<table>
<tbody>
{rows.map((value, index) => (
<tr key={index}>
<td>{intl.formatNumber(value)}</td>
</tr>
))}
</tbody>
</table>
);
}
Die formatNumber-Funktion gibt einen formatierten Zahlenstring zurück und akzeptiert einen Wert, der als Zahl geparst werden kann, zusammen mit Optionen, die den NumberFormatOptions entsprechen.
4. Zahlen in Nicht-JSX-Kontexten formatieren
Verwenden Sie formatNumber, wenn Sie formatierte Zahlen in Attributen, Variablen oder anderen Kontexten benötigen, in denen Komponenten nicht verwendet werden können.
import { useIntl } from "react-intl";
export default function Chart({ dataPoints }: { dataPoints: number[] }) {
const intl = useIntl();
const formattedLabel = intl.formatNumber(dataPoints[0], {
notation: "compact",
maximumFractionDigits: 1,
});
return (
<div>
<img
src="/chart.png"
alt={`Diagramm zeigt ${formattedLabel} Elemente`}
title={formattedLabel}
/>
</div>
);
}
Die imperative API ist essenziell für die Einstellung von Textattributen wie title, aria-label oder alt, bei denen React-Komponenten nicht gerendert werden können.