Comment ajouter des 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 des 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'usage linguistique réel maintenues par le Consortium Unicode.

Par exemple, l'anglais est généralement écrit en script latin et le plus communément utilisé aux États-Unis. Si vous avez juste 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 renvoie 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 voir 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 supprime cette ambiguïté. en et en-US se maximisent tous deux en en-Latn-US, les rendant directement comparables.

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

console.log(locale1.baseName === locale2.baseName);
// false - ils semblent différents

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

console.log(maximized1.baseName === maximized2.baseName);
// true - les deux sont "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 assure 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 de police 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.

Comment fonctionne l'algorithme

L'algorithme Add Likely Subtags utilise une base de données d'informations sur l'usage des langues pour déterminer les composants manquants. Cette base de données est maintenue par le Consortium Unicode 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'usage des langues dans le monde entier.

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 crée et renvoie un nouveau.

Exemples avec différentes langues

Différentes langues ont différentes balises probables basées sur l'endroit où elles sont principalement parlées et les scripts qu'elles utilisent.

Langues européennes

Le français se maximise vers la France avec le script latin :

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 le script latin :

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

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

Langues avec des scripts non latins

Le japonais se maximise vers le Japon avec le script japonais :

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 le script arabe :

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

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

Le chinois sans script 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 script, l'algorithme ajoute le script :

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 script manquant est ajouté.

Identifiants partiels avec scripts

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

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 des préférences de formatage comme 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 n'affecte que les composants de langue, de script 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 pour des raisons de cohérence ou de comparaison.

Normalisation des entrées utilisateur

Les utilisateurs peuvent saisir des locales sous différentes formes. Certains peuvent taper en, d'autres en-US, et d'autres encore 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. La maximisation aide à construire correctement ces chaînes :

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 avec les 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 étend la préférence utilisateur 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 constructeurs de formatage 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 d'informations explicites pour votre propre logique, pas lorsque vous transmettez des 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 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 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érotation 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 une façon standardisée 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.