ToolPal
Zahlen und mathematische Symbole auf dunklem Hintergrund

Zahlenformatierung in JavaScript: Ein vollständiger Leitfaden zu Intl.NumberFormat

📷 Antoine Dautry / Pexels

Zahlenformatierung in JavaScript: Ein vollständiger Leitfaden zu Intl.NumberFormat

Meistern Sie die Zahlenformatierung für internationale Zielgruppen. Lernen Sie, wie Sie Intl.NumberFormat für Währungen, Prozentsätze und lokalisierte Zahlenanzeigen in JavaScript einsetzen.

10. April 20267 Min. Lesezeit

Als ich das erste Mal eine Web-Anwendung für den deutschen Markt entwickelt habe, dachte ich, das sei kein großes Thema — schließlich sind Zahlen doch überall gleich. Ich irrte mich gewaltig. Meine amerikanisch formatierten Preise ($1,234.56) kamen bei deutschen Nutzern nicht gut an, weil sie gewohnt sind, den Punkt als Tausendertrenner und das Komma als Dezimaltrennzeichen zu lesen.

Der Gedanke, das mit Regex und manueller String-Manipulation zu lösen, verging mir schnell, als ich merkte, wie viele Sonderfälle es gibt. Glücklicherweise hat JavaScript eine integrierte Lösung: Intl.NumberFormat.

Das Problem: Unterschiedliche Zahlenformate weltweit

Die Zahl 1234567.89 sieht je nach Land völlig unterschiedlich aus:

  • Deutschland / Österreich: 1.234.567,89 (Punkt als Tausendertrenner, Komma als Dezimalzeichen)
  • USA / Großbritannien: 1,234,567.89 (Komma als Tausendertrenner, Punkt als Dezimalzeichen)
  • Frankreich: 1 234 567,89 (Leerzeichen als Tausendertrenner, Komma als Dezimalzeichen)
  • Schweiz: 1'234'567.89 (Apostroph als Tausendertrenner)
  • Indien: 12,34,567.89 (besonderes Gruppiersystem)

Besonders in Deutschland ist das Thema sensibel: 1,234.56 könnte ein Deutscher als "eins Komma zwei drei vier Punkt fünf sechs" lesen — also als eine völlig andere Zahl! In Finanzanwendungen kann das zu echten Problemen führen.

JavaScript's Intl.NumberFormat im Überblick

Die Intl-Schnittstelle wurde mit ES2015 eingeführt und bietet verschiedene Internationalisierungs-Werkzeuge. Intl.NumberFormat ist das richtige Werkzeug für Zahlen. Die Browser-Unterstützung ist ausgezeichnet: alle modernen Browser und Node.js 10+ unterstützen die API ohne Polyfills.

// Grundlegende Verwendung
const formatter = new Intl.NumberFormat('de-DE');
formatter.format(1234567.89);
// "1.234.567,89"

// Einmalige Verwendung
new Intl.NumberFormat('de-DE').format(1234567.89);
// "1.234.567,89"

// Vergleich verschiedener Locales
new Intl.NumberFormat('en-US').format(1234567.89);
// "1,234,567.89"

new Intl.NumberFormat('fr-FR').format(1234567.89);
// "1 234 567,89"

Dezimalstellen kontrollieren

// Immer genau 2 Dezimalstellen anzeigen
new Intl.NumberFormat('de-DE', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
}).format(1234.5);
// "1.234,50"

// Bis zu 3 Dezimalstellen, ohne nachfolgende Nullen
new Intl.NumberFormat('de-DE', {
  minimumFractionDigits: 0,
  maximumFractionDigits: 3
}).format(1234.5);
// "1.234,5"

Tausendertrenner deaktivieren

Für Jahreszahlen oder IDs, wo kein Tausendertrenner gewünscht ist:

new Intl.NumberFormat('de-DE', {
  useGrouping: false
}).format(2024);
// "2024" (nicht "2.024")

Währungsformatierung

Die Währungsformatierung ist ein Bereich, in dem Intl.NumberFormat wirklich glänzt. Verschiedene Währungen haben unterschiedliche Konventionen: die Anzahl der Dezimalstellen, die Position des Währungssymbols und die Schreibweise des Symbols selbst.

// Euro (deutsche Formatierung)
new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR'
}).format(1234.56);
// "1.234,56 €"

// US-Dollar
new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).format(1234.56);
// "$1,234.56"

// Japanischer Yen (keine Dezimalstellen)
new Intl.NumberFormat('ja-JP', {
  style: 'currency',
  currency: 'JPY'
}).format(1234);
// "¥1,234"

// Britisches Pfund
new Intl.NumberFormat('en-GB', {
  style: 'currency',
  currency: 'GBP'
}).format(1234.56);
// "£1,234.56"

Wichtiger Hinweis: currency (die Währung) und das Locale (die Formatierung) sind unabhängig voneinander. Man kann USD mit deutscher Formatierung anzeigen — das ist nützlich, wenn ein deutscher Nutzer etwas in US-Dollar kauft:

new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'USD'
}).format(1234.56);
// "1.234,56 $"

Darstellungsform der Währung wählen

const amount = 1234.56;

// Symbol (Standard)
new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'symbol'
}).format(amount);
// "1.234,56 $"

// ISO-Code
new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'code'
}).format(amount);
// "1.234,56 USD"

// Ausgeschriebener Name
new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'USD',
  currencyDisplay: 'name'
}).format(amount);
// "1.234,56 US-Dollar"

Mit currencyDisplay: 'name' im deutschen Locale erhält man "US-Dollar" — die API kennt die lokalisierten Währungsnamen.

Fallstrick mit bestimmten Währungen: Währungen wie Japanischer Yen (JPY) haben keine Untereinheiten. Bei Verwendung des currency-Stils mit diesen Währungen werden keine Dezimalstellen angezeigt, und Dezimalwerte werden automatisch gerundet.

Prozentsatzformatierung

Die Prozentformatierung hat eine typische Stolperfalle:

// Achtung: Als Dezimalbruch übergeben (0.75 = 75 %)
new Intl.NumberFormat('de-DE', {
  style: 'percent'
}).format(0.75);
// "75 %" (deutsches Locale setzt ein Leerzeichen vor das %-Zeichen)

// Mit Dezimalstellen
new Intl.NumberFormat('de-DE', {
  style: 'percent',
  minimumFractionDigits: 1,
  maximumFractionDigits: 1
}).format(0.7523);
// "75,2 %"

Häufiger Fehler: Der percent-Stil multipliziert den Eingabewert mit 100. Wenn man 75 übergibt, erscheint 7500 %. Wer bereits einen Prozentwert als ganze Zahl (75) hat, muss ihn zuerst durch 100 teilen:

const prozentwert = 75;
new Intl.NumberFormat('de-DE', {
  style: 'percent'
}).format(prozentwert / 100);
// "75 %"

Außerdem: Das deutsche Locale setzt ein geschütztes Leerzeichen vor das Prozentzeichen. Das sieht im Browser korrekt aus, kann aber bei String-Vergleichen oder CSS-Operationen unerwartet sein.

Wissenschaftliche Notation

Für technische und wissenschaftliche Anwendungen:

new Intl.NumberFormat('de-DE', {
  notation: 'scientific'
}).format(1234567890);
// "1,235E9"

new Intl.NumberFormat('de-DE', {
  notation: 'engineering'
}).format(1234567890);
// "1,235E9"

Kompakte Notation

Für Dashboards und Statistiken ist die kompakte Schreibweise sehr praktisch:

// Deutsche kompakte Notation
new Intl.NumberFormat('de-DE', {
  notation: 'compact',
  compactDisplay: 'short'
}).format(1200);
// "1,2 Tsd."

new Intl.NumberFormat('de-DE', {
  notation: 'compact',
  compactDisplay: 'short'
}).format(3500000);
// "3,5 Mio."

new Intl.NumberFormat('de-DE', {
  notation: 'compact',
  compactDisplay: 'long'
}).format(1200);
// "1,2 Tausend"

// Englische Kurzform zum Vergleich
new Intl.NumberFormat('en-US', {
  notation: 'compact'
}).format(1200);
// "1.2K"

Das Deutsche verwendet "Tsd." für Tausend und "Mio." für Millionen — Intl.NumberFormat kennt diese Abkürzungen und verwendet sie korrekt.

Häufige Fallstricke und Sonderfälle

NaN und Infinity:

new Intl.NumberFormat('de-DE').format(NaN);
// "NaN"

new Intl.NumberFormat('de-DE').format(Infinity);
// "∞"

Nutzern sollten diese technischen Symbole nicht direkt angezeigt werden. Eine Validierung vor der Formatierung ist empfehlenswert.

Performance: Das Erstellen eines Intl.NumberFormat-Instanz verursacht Overhead. Wer viele Zahlen mit denselben Optionen formatiert, sollte die Instanz wiederverwenden:

// Ineffizient
zahlen.forEach(n => new Intl.NumberFormat('de-DE').format(n));

// Effizient
const formatter = new Intl.NumberFormat('de-DE');
zahlen.forEach(n => formatter.format(n));

formatToParts()-Methode: Wenn einzelne Teile einer formatierten Zahl unterschiedlich gestylt werden sollen:

new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR'
}).formatToParts(1234.56);
// [
//   { type: 'integer', value: '1' },
//   { type: 'group', value: '.' },
//   { type: 'integer', value: '234' },
//   { type: 'decimal', value: ',' },
//   { type: 'fraction', value: '56' },
//   { type: 'literal', value: ' ' },
//   { type: 'currency', value: '€' }
// ]

In React-Komponenten lässt sich damit das Währungssymbol mit einer anderen Farbe oder Schriftgröße darstellen.

Große Zahlen und BigInt: JavaScript-Zahlen haben Präzisionsgrenzen. Für sehr große ganze Zahlen (über 2^53) kann es zu Ungenauigkeiten kommen. Intl.NumberFormat unterstützt auch BigInt:

new Intl.NumberFormat('de-DE').format(9007199254740993n); // BigInt
// "9.007.199.254.740.993"

Grenzen von Intl.NumberFormat

Die API ist leistungsfähig, hat aber Einschränkungen:

  • Keine Zahl-Parsierung: Es gibt keine Intl.NumberParse-API. "1.234,56" zurück in 1234.56 umzuwandeln, muss man selbst implementieren — das ist überraschend komplex.
  • Kein Buchhaltungsformat als direkter String-Ausdruck: Negative Zahlen in Klammern ((1.234,56)) sind über currencySign: 'accounting' teilweise verfügbar.
  • Keine benutzerdefinierten Format-Strings: Das Excel-Format #.##0,00 wird nicht unterstützt. Hier helfen Bibliotheken wie numeral.js.

Für die meisten Web-Anwendungen reicht Intl.NumberFormat aber vollkommen aus.

Der Number Formatter auf ToolBox Hub

Wer verschiedene Formatierungsoptionen ohne Codeschreiben ausprobieren möchte, kann das Number Formatter Tool auf ToolBox Hub verwenden:

  1. Zu formatierende Zahl eingeben
  2. Locale auswählen (über 30 Locales werden unterstützt)
  3. Stil wählen (decimal, currency, percent, scientific)
  4. Bei Währung die Währung auswählen
  5. Dezimalstellen festlegen
  6. Tausendertrenner aktivieren oder deaktivieren
  7. Ergebnis sofort sehen und JavaScript-Code kopieren

Besonders hilfreich, wenn man prüfen möchte, wie eine Zahl in einem unbekannten Locale aussieht.

Verwandte Tools

Fazit

Intl.NumberFormat ist eine der am besten durchdachten APIs in der JavaScript-Standardbibliothek. Auf den ersten Blick simpel, steckt dahinter ein umfassendes System für lokalisierte Zahlenformatierung.

Die wichtigsten Punkte zusammengefasst:

  • Immer Intl.NumberFormat für benutzerseitige Zahlen verwenden, nie manuelle String-Manipulation
  • currency und Locale sind unabhängige Parameter
  • percent-Stil multipliziert mit 100 — Dezimalbrüche übergeben
  • compact mit deutschem Locale gibt "Tsd." und "Mio." aus
  • Bei häufiger Verwendung dieselbe Instanz wiederverwenden
  • formatToParts() ermöglicht feingranulares Styling einzelner Teile

Richtig formatierte Zahlen sind kein Nice-to-have, sondern ein Zeichen von Professionalität. Wer internationale Nutzer ernst nimmt, verwendet Intl.NumberFormat.

Häufig gestellte Fragen

Artikel teilen

XLinkedIn

Verwandte Beiträge