Wie man mit Locale-Fallback umgeht, wenn die bevorzugte Locale nicht verfügbar ist

Automatische Auswahl unterstützter Sprachen, wenn Benutzer nicht unterstützte Locales bevorzugen

Einführung

Nicht jede Webanwendung unterstützt jede Sprache der Welt. Wenn ein Benutzer eine Sprache bevorzugt, die Ihre Anwendung nicht unterstützt, benötigen Sie einen Fallback-Mechanismus, um Inhalte in der nächstbesten Sprache anzuzeigen, anstatt Fehler oder nicht übersetzte Texte zu zeigen.

Locale-Fallback ist der Prozess der Auswahl einer alternativen Locale, wenn die bevorzugte Locale nicht verfügbar ist. Die Intl-API von JavaScript handhabt dies automatisch, indem sie mehrere Locale-Optionen akzeptiert und die erste auswählt, die sie unterstützt. Dies stellt sicher, dass Ihre Anwendung immer korrekt formatierte Inhalte anzeigt, selbst wenn die exakt bevorzugte Locale nicht verfügbar ist.

Diese Lektion erklärt, wie Locale-Fallback in JavaScript funktioniert, wie man es effektiv implementiert und wie man benutzerdefinierte Fallback-Logik für Anwendungen mit spezifischen Locale-Unterstützungsanforderungen erstellt.

Das Problem mit nicht unterstützten Locales

Wenn Sie eine Locale-Kennung an eine Intl-API übergeben, muss die JavaScript-Laufzeitumgebung diese Locale unterstützen, um Inhalte korrekt zu formatieren. Wenn Sie eine Formatierung für Norwegisch Nynorsk anfordern, die Laufzeitumgebung aber nur Norwegisch Bokmål unterstützt, benötigt der Formatierer einen Weg, um damit elegant umzugehen.

Ohne Fallback würden Anwendungen bei nicht unterstützten Locales keine Inhalte anzeigen oder nicht übersetzte Texte zeigen. Benutzer aus Regionen mit weniger verbreiteten Sprachvarianten würden fehlerhafte Benutzeroberflächen erleben.

Stellen Sie sich einen Benutzer vor, der kanadisches Französisch spricht. Wenn Ihre Anwendung nur europäisches Französisch unterstützt, möchten Sie, dass der Formatierer die europäischen französischen Konventionen verwendet, anstatt komplett zu versagen. Obwohl nicht perfekt, bietet dies eine bessere Erfahrung als gar keine Lokalisierung.

Wie die Intl-API Fallback automatisch handhabt

Jeder Intl-Konstruktor akzeptiert entweder einen einzelnen Locale-String oder ein Array von Locale-Strings. Wenn Sie ein Array übergeben, wertet die Laufzeitumgebung jede Locale der Reihe nach aus und verwendet die erste, die sie unterstützt.

const locales = ["fr-CA", "fr-FR", "en-US"];
const formatter = new Intl.DateTimeFormat(locales);

const date = new Date("2025-03-15");
console.log(formatter.format(date));
// Verwendet fr-CA, wenn verfügbar
// Fällt auf fr-FR zurück, wenn fr-CA nicht verfügbar ist
// Fällt auf en-US zurück, wenn keine der französischen Varianten verfügbar ist

Die Laufzeitumgebung prüft das Array von links nach rechts. Wenn sie kanadisches Französisch unterstützt, verwendet sie das. Wenn nicht, versucht sie europäisches Französisch. Wenn keine der französischen Varianten verfügbar ist, fällt sie auf amerikanisches Englisch zurück.

Dieser automatische Fallback bedeutet, dass Sie die Unterstützung nicht manuell überprüfen oder Fehler behandeln müssen, wenn Sie bestimmte Locales anfordern. Die Intl-API garantiert, dass sie eine unterstützte Locale auswählt oder auf die Systemstandard-Locale zurückfällt.

Bereitstellung mehrerer Locale-Optionen

Der einfachste Weg, einen Fallback zu implementieren, ist die Übergabe eines Arrays von Locales in der Reihenfolge der Präferenz. Dies funktioniert mit allen Intl-Konstruktoren, einschließlich DateTimeFormat, NumberFormat, Collator und anderen.

const locales = ["es-MX", "es-ES", "es", "en"];
const numberFormatter = new Intl.NumberFormat(locales, {
  style: "currency",
  currency: "USD"
});

console.log(numberFormatter.format(1234.56));
// Verwendet mexikanisches Spanisch, wenn verfügbar
// Fällt zurück auf europäisches Spanisch
// Fällt zurück auf allgemeines Spanisch
// Fällt zurück auf Englisch als letzte Option

Dieses Muster bietet einen eleganten Degradationspfad. Benutzer erhalten Inhalte in ihrem bevorzugten Dialekt, wenn verfügbar, dann in einer breiteren Variante ihrer Sprache und schließlich in einer allgemeinen Fallback-Sprache.

Die Reihenfolge ist wichtig. Die Laufzeitumgebung wählt die erste Locale aus, die sie unterstützt, daher sollten die spezifischsten und bevorzugten Locales zuerst platziert werden.

Verstehen, wie Locale-Matching funktioniert

Wenn Sie mehrere Locales angeben, verwendet die JavaScript-Laufzeitumgebung einen Locale-Matching-Algorithmus, um die beste verfügbare Option auszuwählen. Dieser Algorithmus vergleicht Ihre angeforderten Locales mit der Menge der Locales, die die Laufzeitumgebung unterstützt.

Wenn eine angeforderte Locale exakt mit einer unterstützten Locale übereinstimmt, verwendet die Laufzeitumgebung diese sofort. Wenn keine exakte Übereinstimmung existiert, kann die Laufzeitumgebung eine verwandte Locale basierend auf Sprach- und Regionscodes auswählen.

Wenn Sie beispielsweise en-AU (australisches Englisch) anfordern, aber die Laufzeitumgebung nur en-US und en-GB unterstützt, wird sie eine dieser englischen Varianten auswählen, anstatt auf eine völlig andere Sprache zurückzufallen.

const locales = ["en-AU", "en"];
const formatter = new Intl.DateTimeFormat(locales);

const resolvedLocale = formatter.resolvedOptions().locale;
console.log(resolvedLocale);
// Könnte "en-US" oder "en-GB" anzeigen, abhängig von der Laufzeitumgebung
// Die Laufzeitumgebung hat eine unterstützte englische Variante ausgewählt

Die Methode resolvedOptions() gibt die tatsächliche Locale zurück, die der Formatierer verwendet. Dies ermöglicht es Ihnen zu überprüfen, welche Locale nach dem Fallback ausgewählt wurde.

Überprüfen, welche Locales unterstützt werden

Die statische Methode supportedLocalesOf() prüft, welche Locales aus einer Liste von einem bestimmten Intl-Konstruktor unterstützt werden. Diese Methode gibt ein Array zurück, das nur die unterstützten Locales enthält.

const requestedLocales = ["fr-CA", "fr-FR", "de-DE", "ja-JP"];
const supportedLocales = Intl.DateTimeFormat.supportedLocalesOf(requestedLocales);

console.log(supportedLocales);
// Ausgabe hängt von der Laufzeitunterstützung ab
// Beispiel: ["fr-FR", "de-DE", "ja-JP"]
// Kanadisches Französisch wurde nicht unterstützt, andere schon

Diese Methode filtert die angeforderten Locales, um zu zeigen, welche die Laufzeit verwenden kann, ohne auf Standardwerte zurückzugreifen. Nicht unterstützte Locales werden aus dem zurückgegebenen Array entfernt.

Sie können diese Methode verwenden, um die Unterstützung zu überprüfen, bevor Sie Formatierer erstellen, oder um anzuzeigen, welche Sprachoptionen für Benutzer verfügbar sind.

const availableLocales = ["en-US", "es-MX", "fr-FR", "de-DE", "ja-JP"];
const supported = Intl.NumberFormat.supportedLocalesOf(availableLocales);

console.log("Diese Laufzeit unterstützt:", supported);
// Zeigt, welche Ihrer Anwendungslocales in dieser Umgebung funktionieren

Jeder Intl-Konstruktor hat seine eigene supportedLocalesOf()-Methode, da die Locale-Unterstützung zwischen verschiedenen Internationalisierungsfunktionen variieren kann. Eine Laufzeit könnte Französisch für die Zahlenformatierung unterstützen, aber nicht für die Textsegmentierung.

Erstellen von Fallback-Ketten aus Locale-Kennungen

Wenn Sie wissen, dass Ihre Anwendung bestimmte Locales unterstützt, können Sie eine Fallback-Kette erstellen, die progressiv weniger spezifisch wird. Dieses Muster beginnt mit einer vollständigen Locale-Kennung und entfernt Komponenten, bis eine Übereinstimmung gefunden wird.

function buildFallbackChain(locale) {
  const chain = [locale];

  const parts = locale.split("-");
  if (parts.length > 1) {
    chain.push(parts[0]);
  }

  chain.push("en");

  return chain;
}

const fallbacks = buildFallbackChain("zh-Hans-CN");
console.log(fallbacks);
// ["zh-Hans-CN", "zh", "en"]

const formatter = new Intl.DateTimeFormat(fallbacks);
// Versucht vereinfachtes Chinesisch für China
// Fällt zurück auf generisches Chinesisch
// Fällt zurück auf Englisch

Diese Funktion erstellt eine Fallback-Kette, indem sie den Sprachcode aus einer Locale-Kennung extrahiert und einen endgültigen englischen Fallback hinzufügt. Sie können diese Logik erweitern, um komplexere Fallback-Regeln basierend auf den unterstützten Locales Ihrer Anwendung einzubeziehen.

Für Anwendungen, die mehrere Varianten einer Sprache unterstützen, möchten Sie möglicherweise auf verwandte Dialekte zurückgreifen, bevor Sie zu Englisch wechseln.

function buildSmartFallbackChain(locale) {
  const chain = [locale];

  if (locale.startsWith("es-")) {
    chain.push("es-MX", "es-ES", "es");
  } else if (locale.startsWith("fr-")) {
    chain.push("fr-FR", "fr-CA", "fr");
  } else if (locale.startsWith("zh-")) {
    chain.push("zh-Hans-CN", "zh-Hant-TW", "zh");
  }

  const parts = locale.split("-");
  if (parts.length > 1 && !chain.includes(parts[0])) {
    chain.push(parts[0]);
  }

  if (!chain.includes("en")) {
    chain.push("en");
  }

  return chain;
}

const fallbacks = buildSmartFallbackChain("es-AR");
console.log(fallbacks);
// ["es-AR", "es-MX", "es-ES", "es", "en"]
// Versucht argentinisches Spanisch
// Fällt zurück auf mexikanisches Spanisch
// Fällt zurück auf europäisches Spanisch
// Fällt zurück auf generisches Spanisch
// Fällt zurück auf Englisch

Dieser Ansatz stellt sicher, dass Benutzer Inhalte in einem verwandten Dialekt ihrer Sprache sehen, bevor auf Englisch zurückgegriffen wird.

Auswahl eines Algorithmus für die Gebietsschemaabgleichung

Die Intl-API unterstützt zwei Algorithmen für die Gebietsschemaabgleichung: Lookup und Best Fit. Sie können über die Option localeMatcher beim Erstellen von Formatierern festlegen, welcher Algorithmus verwendet werden soll.

Der Lookup-Algorithmus folgt der BCP 47 Lookup-Spezifikation. Er führt einen strengen Abgleich durch, indem er Gebietsschema-Kennungen systematisch vergleicht und die erste exakte Übereinstimmung auswählt.

const locales = ["de-DE", "en-US"];
const formatter = new Intl.NumberFormat(locales, {
  localeMatcher: "lookup"
});

console.log(formatter.resolvedOptions().locale);
// Verwendet strenge Lookup-Abgleichsregeln

Der Best-Fit-Algorithmus ermöglicht es der Laufzeitumgebung, ein Gebietsschema mit ihrer eigenen Abgleichslogik auszuwählen. Dieser Algorithmus kann intelligente Entscheidungen darüber treffen, welches Gebietsschema den Bedürfnissen des Benutzers am besten dient, auch wenn es keine exakte Übereinstimmung gibt.

const locales = ["de-DE", "en-US"];
const formatter = new Intl.NumberFormat(locales, {
  localeMatcher: "best fit"
});

console.log(formatter.resolvedOptions().locale);
// Verwendet den Best-Fit-Algorithmus der Laufzeitumgebung
// Könnte ein verwandtes Gebietsschema intelligenter auswählen

Der Standardalgorithmus ist Best Fit. Die meisten Anwendungen sollten den Standard verwenden, da er über verschiedene JavaScript-Laufzeitumgebungen hinweg bessere Ergebnisse liefert. Verwenden Sie Lookup nur, wenn Sie ein vorhersehbares, strenges Abgleichsverhalten benötigen.

Verwendung der Browser-Spracheinstellungen für automatischen Fallback

Die Eigenschaft navigator.languages gibt ein Array der bevorzugten Sprachen des Benutzers in der Reihenfolge der Präferenz zurück. Sie können dieses Array direkt an Intl-Konstruktoren übergeben, um einen automatischen Fallback basierend auf den Browser-Einstellungen zu implementieren.

const formatter = new Intl.DateTimeFormat(navigator.languages);

const date = new Date("2025-03-15");
console.log(formatter.format(date));
// Verwendet automatisch die bevorzugte unterstützte Sprache des Benutzers

Dieser Ansatz überlässt dem Browser die gesamte Fallback-Logik. Wenn die erste Präferenz des Benutzers nicht unterstützt wird, versucht die Intl-API automatisch die zweite Präferenz, dann die dritte und so weiter.

Dieses Muster funktioniert gut, wenn Sie alle Sprachpräferenzen des Benutzers respektieren möchten, ohne manuell Fallback-Ketten zu erstellen.

console.log(navigator.languages);
// ["fr-CA", "fr", "en-US", "en"]

const numberFormatter = new Intl.NumberFormat(navigator.languages, {
  style: "currency",
  currency: "USD"
});

console.log(numberFormatter.format(1234.56));
// Versucht zuerst Kanadisches Französisch
// Fällt durch die vollständige Präferenzliste des Benutzers zurück

Die Intl-API evaluiert jede Sprache im Array und wählt die erste aus, die sie unterstützt, was diese zu einer robusten Lösung für die Handhabung verschiedener Benutzerpräferenzen macht.

Kombination von Anwendungsunterstützung mit Benutzereinstellungen

Für Anwendungen mit eingeschränkter Locale-Unterstützung können Sie Benutzereinstellungen filtern, um sie mit Ihren unterstützten Locales abzugleichen, bevor Sie Formatter erstellen. Dies stellt sicher, dass Sie nur Locales verwenden, die Ihre Anwendung verarbeiten kann.

const supportedLocales = ["en-US", "es-MX", "fr-FR", "de-DE"];

function findBestLocale(userPreferences, appSupported) {
  const preferences = userPreferences.map(pref => {
    const parts = pref.split("-");
    return [pref, parts[0]];
  }).flat();

  for (const pref of preferences) {
    if (appSupported.includes(pref)) {
      return pref;
    }
  }

  return appSupported[0];
}

const userLocale = findBestLocale(navigator.languages, supportedLocales);
const formatter = new Intl.DateTimeFormat(userLocale);

console.log(formatter.resolvedOptions().locale);
// Selected locale matches both user preference and app support

Diese Funktion findet die erste Übereinstimmung zwischen Benutzereinstellungen und unterstützten Locales, einschließlich des Versuchs, Sprachcodes ohne Regionscodes für eine breitere Übereinstimmung zu verwenden.

Für eine anspruchsvollere Zuordnung können Sie prüfen, welche der Benutzereinstellungen von der Intl-API in dieser Laufzeitumgebung unterstützt werden.

const supportedLocales = ["en-US", "es-MX", "fr-FR", "de-DE"];

function findBestSupportedLocale(userPreferences, appSupported) {
  const runtimeSupported = Intl.DateTimeFormat.supportedLocalesOf(appSupported);

  for (const pref of userPreferences) {
    if (runtimeSupported.includes(pref)) {
      return pref;
    }

    const lang = pref.split("-")[0];
    const match = runtimeSupported.find(s => s.startsWith(lang));
    if (match) {
      return match;
    }
  }

  return runtimeSupported[0] || "en";
}

const userLocale = findBestSupportedLocale(navigator.languages, supportedLocales);
const formatter = new Intl.DateTimeFormat(userLocale);

Dieser Ansatz stellt sicher, dass die ausgewählte Locale sowohl von Ihrer Anwendung als auch von der JavaScript-Laufzeitumgebung unterstützt wird.

Behandlung von Fällen, in denen keine Locale übereinstimmt

Wenn keine der angeforderten Locales unterstützt wird, greift die Intl-API auf die Standardlocale des Systems zurück. Diese Standardeinstellung variiert je nach Umgebung und wird durch das Betriebssystem, den Browser oder die Node.js-Konfiguration bestimmt.

const unsupportedLocales = ["non-existent-locale"];
const formatter = new Intl.DateTimeFormat(unsupportedLocales);

console.log(formatter.resolvedOptions().locale);
// Shows the system default locale
// Might be "en-US" or another locale depending on the system

Die Systemstandardeinstellung stellt sicher, dass Formatter immer funktionieren, selbst bei völlig ungültigen oder nicht unterstützten Locale-Listen. Ihre Anwendung wird keine Fehler aufgrund von Locale-Problemen werfen.

Um einen bestimmten Fallback sicherzustellen, anstatt sich auf die Systemstandardeinstellung zu verlassen, fügen Sie immer eine weit verbreitete Locale wie en oder en-US am Ende Ihres Locale-Arrays ein.

const locales = ["xyz-INVALID", "en"];
const formatter = new Intl.DateTimeFormat(locales);

console.log(formatter.resolvedOptions().locale);
// Will use "en" since the first locale is invalid
// Guaranteed fallback to English instead of system default

Dieses Muster macht das Verhalten Ihrer Anwendung in verschiedenen Umgebungen vorhersehbarer.

Praktische Muster für Produktionsanwendungen

Beim Erstellen von Produktionsanwendungen sollten mehrere Fallback-Strategien kombiniert werden, um eine robuste Gebietsschemabehandlung für unterschiedliche Nutzergruppen zu gewährleisten.

Ein gängiges Muster erstellt Formatierer mit einer vollständigen Fallback-Kette, die Benutzereinstellungen, von der Anwendung unterstützte Gebietsschemas und einen garantierten endgültigen Fallback umfasst.

class LocaleManager {
  constructor(supportedLocales) {
    this.supportedLocales = supportedLocales;
    this.defaultLocale = "en-US";
  }

  buildLocaleChain(userPreference) {
    const chain = [];

    if (userPreference) {
      chain.push(userPreference);

      const lang = userPreference.split("-")[0];
      if (lang !== userPreference) {
        chain.push(lang);
      }
    }

    chain.push(...navigator.languages);
    chain.push(...this.supportedLocales);
    chain.push(this.defaultLocale);

    const unique = [...new Set(chain)];
    return unique;
  }

  createDateFormatter(userPreference, options = {}) {
    const locales = this.buildLocaleChain(userPreference);
    return new Intl.DateTimeFormat(locales, options);
  }

  createNumberFormatter(userPreference, options = {}) {
    const locales = this.buildLocaleChain(userPreference);
    return new Intl.NumberFormat(locales, options);
  }
}

const manager = new LocaleManager(["en-US", "es-MX", "fr-FR", "de-DE"]);
const dateFormatter = manager.createDateFormatter("pt-BR");

console.log(dateFormatter.resolvedOptions().locale);
// Verwendet umfassende Fallback-Kette
// Versucht Portugiesisch für Brasilien
// Fällt zurück auf Portugiesisch
// Fällt zurück durch navigator.languages
// Fällt zurück durch unterstützte Gebietsschemas
// Garantiert die Verwendung von en-US, wenn nichts anderes übereinstimmt

Diese Klasse kapselt die Logik für Gebietsschema-Fallbacks und stellt ein konsistentes Verhalten in Ihrer Anwendung sicher.

Für Anwendungen, die zur Laufzeit auf Änderungen des Benutzergebietsschemas reagieren müssen, kombinieren Sie den Locale-Manager mit Event-Listenern.

class LocaleAwareFormatter {
  constructor(supportedLocales) {
    this.supportedLocales = supportedLocales;
    this.updateFormatters();

    window.addEventListener("languagechange", () => {
      this.updateFormatters();
    });
  }

  updateFormatters() {
    const locales = [...navigator.languages, ...this.supportedLocales, "en"];

    this.dateFormatter = new Intl.DateTimeFormat(locales);
    this.numberFormatter = new Intl.NumberFormat(locales);
  }

  formatDate(date) {
    return this.dateFormatter.format(date);
  }

  formatNumber(number) {
    return this.numberFormatter.format(number);
  }
}

const formatter = new LocaleAwareFormatter(["en-US", "es-MX", "fr-FR"]);
console.log(formatter.formatDate(new Date()));
// Aktualisiert automatisch, wenn der Benutzer die Spracheinstellungen ändert

Dieses Muster erstellt Formatierer, die mit Änderungen der Browser-Spracheinstellungen synchronisiert bleiben und sicherstellen, dass Ihre Anwendung Inhalte immer entsprechend den aktuellen Präferenzen anzeigt.

Zusammenfassung

Locale-Fallback stellt sicher, dass Ihre Anwendung ordnungsgemäß formatierte Inhalte anzeigt, selbst wenn Benutzer Locales bevorzugen, die Sie nicht explizit unterstützen. Die Intl-API verarbeitet Fallbacks automatisch, indem sie Arrays von Locale-Präferenzen akzeptiert und die erste unterstützte Option auswählt.

Wichtige Konzepte:

  • Übergeben Sie Arrays von Locales an Intl-Konstruktoren für automatischen Fallback
  • Die Laufzeitumgebung wählt die erste Locale aus dem Array aus, die sie unterstützt
  • Verwenden Sie supportedLocalesOf(), um zu prüfen, welche Locales verfügbar sind
  • Erstellen Sie Fallback-Ketten, die von spezifischen zu allgemeinen Locales fortschreiten
  • Die Option localeMatcher steuert den Matching-Algorithmus
  • Übergeben Sie navigator.languages direkt für automatische Benutzerpräferenz-Verarbeitung
  • Fügen Sie immer einen weit verbreiteten finalen Fallback wie Englisch hinzu
  • Die Laufzeitumgebung fällt auf Systemstandards zurück, wenn keine Locales übereinstimmen

Verwenden Sie für die meisten Anwendungen automatischen Fallback mit Locale-Arrays. Implementieren Sie benutzerdefinierte Fallback-Logik, wenn Sie spezifische Kontrolle darüber benötigen, welche Locales in welcher Reihenfolge versucht werden.