Comment ajouter des sous-balises probables aux locales incomplètes

Utilisez JavaScript pour compléter les identifiants de locale partiels avec le script et la région les plus probables

Introduction

Lorsque vous travaillez avec des identifiants de locale, vous recevez parfois des informations incomplètes. Un utilisateur peut spécifier uniquement un code de langue comme ja sans indiquer le script ou la région. Bien que cet identifiant partiel soit valide, il manque de spécificité nécessaire pour certaines opérations comme la comparaison de locales ou la détermination des conventions de formatage.

JavaScript fournit un moyen de compléter ces identifiants partiels en ajoutant les composants manquants les plus probables. Ce processus utilise des données linguistiques pour déduire le script et la région que les utilisateurs de cette langue utilisent généralement.

Ce guide explique ce que sont les sous-balises probables, comment JavaScript les détermine et quand utiliser cette fonctionnalité dans vos applications.

Que sont les sous-balises probables

Les sous-balises probables sont les codes de script et de région qui apparaissent le plus couramment avec une langue donnée. Ces associations proviennent de données d'utilisation linguistique réelles maintenues par le Unicode Consortium.

Par exemple, l'anglais est généralement écrit en script latin et le plus couramment utilisé aux États-Unis. Si vous avez uniquement le code de langue en, les sous-balises probables sont Latn pour le script et US pour la région, vous donnant l'identifiant complet en-Latn-US.

La probabilité est basée sur les populations de locuteurs et les modèles d'utilisation historiques. L'algorithme retourne toujours la combinaison statistiquement la plus courante.

Pourquoi ajouter des sous-balises probables

Les identifiants de locale partiels fonctionnent pour la plupart des opérations de formatage. Les API Intl.DateTimeFormat et Intl.NumberFormat acceptent en et appliqueront des valeurs par défaut sensées. Cependant, il existe des situations où avoir des identifiants complets est nécessaire.

Comparaison des identifiants de locale

Lors de la comparaison de deux identifiants de locale pour vérifier s'ils font référence à la même langue et région, les identifiants partiels créent une ambiguïté. Est-ce que en signifie la même chose que en-US, ou est-ce différent parce que l'un spécifie une région et l'autre non ?

L'ajout de sous-balises probables élimine cette ambiguïté. en et en-US sont tous deux maximisés en en-Latn-US, ce qui les rend directement comparables.

const locale1 = new Intl.Locale("en");
const locale2 = new Intl.Locale("en-US");

console.log(locale1.baseName === locale2.baseName);
// false - they look different

const maximized1 = locale1.maximize();
const maximized2 = locale2.maximize();

console.log(maximized1.baseName === maximized2.baseName);
// true - both are "en-Latn-US"

Stockage des formes canoniques

Lors du stockage des identifiants de locale dans des bases de données ou des fichiers de configuration, l'utilisation de formes complètes garantit la cohérence. Chaque locale française devient fr-Latn-FR, chaque locale japonaise devient ja-Jpan-JP, et ainsi de suite.

Cette cohérence rend la recherche, le filtrage et le regroupement par locale plus fiables.

Détermination du comportement spécifique au script

Certaines langues utilisent plusieurs scripts, et le script affecte le rendu du texte, la sélection des polices et le classement. Le chinois peut être écrit en caractères simplifiés ou traditionnels, et le serbe peut utiliser l'alphabet cyrillique ou latin.

L'ajout de sous-balises probables rend le script explicite. Si un utilisateur fournit zh sans spécifier de script, sa maximisation produit zh-Hans-CN, indiquant que des caractères chinois simplifiés sont attendus.

Fonctionnement de l'algorithme

L'algorithme d'ajout de sous-balises probables utilise une base de données d'informations sur l'utilisation des langues pour déterminer les composants manquants. Cette base de données est maintenue par le Unicode Consortium dans le cadre du Common Locale Data Repository.

L'algorithme examine les informations que vous fournissez et comble les lacunes :

  • Si vous ne fournissez qu'une langue, il ajoute le script et la région les plus courants pour cette langue
  • Si vous fournissez une langue et un script, il ajoute la région la plus courante pour cette combinaison
  • Si vous fournissez une langue et une région, il ajoute le script le plus courant pour cette combinaison
  • Si vous fournissez les trois composants, ils restent inchangés

Les décisions sont basées sur des données statistiques concernant l'utilisation des langues dans le monde.

Utilisation de la méthode maximize

La méthode maximize() est disponible sur les objets Intl.Locale. Elle renvoie un nouvel objet locale avec des sous-balises probables ajoutées au nom de base.

const locale = new Intl.Locale("ja");
const maximized = locale.maximize();

console.log(locale.baseName);
// "ja"

console.log(maximized.baseName);
// "ja-Jpan-JP"

La méthode ne modifie pas l'objet locale d'origine. Elle en crée et en renvoie un nouveau.

Exemples avec différentes langues

Différentes langues ont différentes sous-balises probables en fonction de l'endroit où elles sont principalement parlées et des systèmes d'écriture qu'elles utilisent.

Langues européennes

Le français se maximise vers la France avec l'écriture latine :

const french = new Intl.Locale("fr");
const maximized = french.maximize();

console.log(maximized.baseName);
// "fr-Latn-FR"

L'allemand se maximise vers l'Allemagne avec l'écriture latine :

const german = new Intl.Locale("de");
const maximized = german.maximize();

console.log(maximized.baseName);
// "de-Latn-DE"

Langues avec des systèmes d'écriture non latins

Le japonais se maximise vers le Japon avec l'écriture japonaise :

const japanese = new Intl.Locale("ja");
const maximized = japanese.maximize();

console.log(maximized.baseName);
// "ja-Jpan-JP"

L'arabe se maximise vers l'Égypte avec l'écriture arabe :

const arabic = new Intl.Locale("ar");
const maximized = arabic.maximize();

console.log(maximized.baseName);
// "ar-Arab-EG"

Le chinois sans système d'écriture se maximise vers les caractères simplifiés et la Chine :

const chinese = new Intl.Locale("zh");
const maximized = chinese.maximize();

console.log(maximized.baseName);
// "zh-Hans-CN"

Identifiants partiels avec régions

Lorsque vous fournissez une langue et une région mais pas de système d'écriture, l'algorithme ajoute le système d'écriture :

const britishEnglish = new Intl.Locale("en-GB");
const maximized = britishEnglish.maximize();

console.log(maximized.baseName);
// "en-Latn-GB"

La région reste telle que spécifiée. Seul le système d'écriture manquant est ajouté.

Identifiants partiels avec systèmes d'écriture

Lorsque vous fournissez une langue et un système d'écriture mais pas de région, l'algorithme ajoute la région la plus courante pour ce système d'écriture :

const traditionalChinese = new Intl.Locale("zh-Hant");
const maximized = traditionalChinese.maximize();

console.log(maximized.baseName);
// "zh-Hant-TW"

Les caractères chinois traditionnels sont principalement utilisés à Taïwan, donc TW est ajouté comme région.

Les balises d'extension sont préservées

Les balises d'extension Unicode spécifient les préférences de formatage telles que les systèmes de calendrier, les systèmes de numérotation et les cycles horaires. Ces balises apparaissent après -u- dans l'identifiant de locale.

La méthode maximize() ne modifie pas les balises d'extension. Elle affecte uniquement les composants de langue, d'écriture et de région.

const locale = new Intl.Locale("fr", {
  calendar: "gregory",
  numberingSystem: "latn",
  hourCycle: "h23"
});

console.log(locale.toString());
// "fr-u-ca-gregory-hc-h23-nu-latn"

const maximized = locale.maximize();

console.log(maximized.toString());
// "fr-Latn-FR-u-ca-gregory-hc-h23-nu-latn"

Le nom de base change de fr à fr-Latn-FR, mais les balises d'extension restent identiques.

Quand utiliser maximize

Utilisez la méthode maximize() lorsque vous avez besoin d'identifiants de locale complets à des fins de cohérence ou de comparaison.

Normalisation de la saisie utilisateur

Les utilisateurs peuvent saisir des locales sous diverses formes. Certains peuvent taper en, d'autres en-US, et d'autres en-Latn-US. Maximiser toutes les entrées crée un format cohérent :

function normalizeLocale(input) {
  try {
    const locale = new Intl.Locale(input);
    const maximized = locale.maximize();
    return maximized.baseName;
  } catch (error) {
    return null;
  }
}

console.log(normalizeLocale("en"));
// "en-Latn-US"

console.log(normalizeLocale("en-US"));
// "en-Latn-US"

console.log(normalizeLocale("en-Latn-US"));
// "en-Latn-US"

Les trois entrées produisent la même forme normalisée.

Construction de chaînes de repli de locale

Lorsqu'une locale spécifique n'est pas disponible, les applications se replient sur des locales plus générales. Maximiser aide à construire ces chaînes correctement :

function buildFallbackChain(localeString) {
  const locale = new Intl.Locale(localeString);
  const maximized = locale.maximize();

  const chain = [maximized.toString()];

  if (maximized.script && maximized.region) {
    const withoutRegion = new Intl.Locale(
      `${maximized.language}-${maximized.script}`
    );
    chain.push(withoutRegion.toString());
  }

  if (maximized.region) {
    chain.push(maximized.language);
  }

  chain.push("en");

  return chain;
}

console.log(buildFallbackChain("zh-TW"));
// ["zh-Hant-TW", "zh-Hant", "zh", "en"]

Cela crée un repli approprié de la locale la plus spécifique à la plus générale.

Correspondance des préférences utilisateur aux locales disponibles

Lorsque vous disposez d'un ensemble de traductions disponibles et que vous devez trouver la meilleure correspondance pour une préférence utilisateur, maximiser les deux côtés permet une comparaison précise :

function findBestMatch(userPreference, availableLocales) {
  const userMaximized = new Intl.Locale(userPreference).maximize();

  const matches = availableLocales.map(available => {
    const availableMaximized = new Intl.Locale(available).maximize();

    let score = 0;
    if (userMaximized.language === availableMaximized.language) score += 1;
    if (userMaximized.script === availableMaximized.script) score += 1;
    if (userMaximized.region === availableMaximized.region) score += 1;

    return { locale: available, score };
  });

  matches.sort((a, b) => b.score - a.score);

  return matches[0].locale;
}

const available = ["en-US", "en-GB", "fr-FR", "de-DE"];
console.log(findBestMatch("en", available));
// "en-US"

La fonction développe la préférence utilisateur en en en-Latn-US et trouve la correspondance la plus proche.

Quand ne pas utiliser maximize

Vous n'avez pas besoin de maximiser les locales avant de les transmettre aux API de formatage. Les constructeurs Intl.DateTimeFormat, Intl.NumberFormat et autres gèrent correctement les identifiants partiels.

const date = new Date("2025-03-15");

const partial = new Intl.DateTimeFormat("fr").format(date);
const maximized = new Intl.DateTimeFormat("fr-Latn-FR").format(date);

console.log(partial);
// "15/03/2025"

console.log(maximized);
// "15/03/2025"

Les deux produisent un résultat identique. La spécificité supplémentaire ne modifie pas le comportement de formatage dans ce cas.

Utilisez maximize() lorsque vous avez besoin des informations explicites pour votre propre logique, et non lors de la transmission de locales aux formateurs intégrés.

Compatibilité des navigateurs

La méthode maximize() est disponible dans tous les navigateurs modernes. Chrome, Firefox, Safari et Edge la prennent tous en charge dans le cadre de l'API Intl.Locale.

Node.js prend en charge maximize() à partir de la version 12, avec une prise en charge complète dans la version 14 et ultérieures.

Résumé

Les sous-balises probables complètent les identifiants de locale partiels en ajoutant le script et la région les plus courants pour une langue donnée. La méthode Intl.Locale.maximize() implémente l'algorithme Unicode Add Likely Subtags pour effectuer cette expansion.

Points clés :

  • Les sous-balises probables sont basées sur des données d'utilisation linguistique réelles
  • La méthode maximize() ajoute les codes de script et de région manquants
  • Les balises d'extension pour les calendriers et les systèmes de numération restent inchangées
  • Utilisez la maximisation pour normaliser les entrées utilisateur et comparer les locales
  • Les API de formatage ne nécessitent pas de locales maximisées

La méthode maximize() fournit un moyen standardisé de travailler avec des identifiants de locale complets lorsque la logique de votre application nécessite des informations explicites sur le script et la région.