Comment supprimer les informations redondantes des identifiants de locale

Utilisez la méthode minimize pour créer des identifiants de locale compacts sans perdre de sens

Introduction

Les identifiants de locale comme en-Latn-US et zh-Hans-CN contiennent plusieurs composants qui spécifient la langue, le script et la région. Cependant, tous ces composants ne sont pas nécessaires pour identifier une locale. Certains composants sont redondants car ils peuvent être déduits à partir d'autres parties de l'identifiant.

La méthode minimize() supprime ces composants redondants pour créer l'identifiant de locale équivalent le plus court. Cela produit des identifiants compacts qui préservent le sens tout en réduisant la taille de stockage et en améliorant la lisibilité.

Comprendre la redondance dans les identifiants de locale

Un identifiant de locale devient redondant lorsqu'il indique explicitement des informations qui sont déjà implicites dans d'autres composants. La redondance se produit car chaque langue possède des valeurs par défaut probables pour le script et la région.

Prenons l'identifiant en-Latn-US. Cet identifiant spécifie :

  • Langue : anglais (en)
  • Script : latin (Latn)
  • Région : États-Unis (US)

L'anglais n'est écrit qu'en script latin, et lorsqu'aucune région n'est spécifiée, l'anglais est par défaut associé aux États-Unis. Les composants de script et de région sont redondants car ils correspondent aux valeurs par défaut probables pour l'anglais. L'identifiant en transmet les mêmes informations.

Le même principe s'applique à d'autres langues. Le coréen (ko) est écrit en script hangul (Kore) et principalement parlé en Corée du Sud (KR). L'identifiant ko-Kore-KR contient des informations redondantes car ko seul implique ces valeurs par défaut.

Comment fonctionne la méthode minimize

La méthode minimize() est disponible sur les instances Intl.Locale. Elle analyse l'identifiant de locale et supprime les composants qui correspondent aux valeurs par défaut probables.

const locale = new Intl.Locale("en-Latn-US");
const minimized = locale.minimize();

console.log(minimized.baseName);
// Résultat : "en"

La méthode renvoie une nouvelle instance Intl.Locale avec les sous-étiquettes redondantes supprimées. Elle ne modifie pas l'objet locale d'origine.

Le processus de minimisation suit l'algorithme "Remove Likely Subtags" de l'Unicode CLDR. Cet algorithme utilise une base de données d'associations de sous-étiquettes probables pour déterminer quels composants peuvent être supprimés sans perdre d'information.

Composants affectés par minimize

La méthode minimize() n'affecte que les composants principaux de la locale : langue, script et région. Elle ne supprime ni ne modifie les sous-balises d'extension Unicode qui spécifient les préférences de formatage.

const locale = new Intl.Locale("en-Latn-US-u-ca-gregory-nu-latn");
const minimized = locale.minimize();

console.log(minimized.toString());
// Résultat : "en-u-ca-gregory-nu-latn"

Les extensions de calendrier (ca-gregory) et de système de numération (nu-latn) restent intactes. Seuls les composants redondants de script (Latn) et de région (US) sont supprimés.

Exemples de minimisation

Différents identifiants de locale se minimisent à différentes longueurs selon les composants qui sont redondants.

Suppression du script et de la région

Lorsque le script et la région correspondent aux valeurs par défaut, les deux sont supprimés :

const english = new Intl.Locale("en-Latn-US");
console.log(english.minimize().baseName);
// Résultat : "en"

const korean = new Intl.Locale("ko-Kore-KR");
console.log(korean.minimize().baseName);
// Résultat : "ko"

const japanese = new Intl.Locale("ja-Jpan-JP");
console.log(japanese.minimize().baseName);
// Résultat : "ja"

Conservation des régions non par défaut

Lorsque la région diffère de la valeur par défaut, elle reste dans l'identifiant minimisé :

const britishEnglish = new Intl.Locale("en-Latn-GB");
console.log(britishEnglish.minimize().baseName);
// Résultat : "en-GB"

const canadianFrench = new Intl.Locale("fr-Latn-CA");
console.log(canadianFrench.minimize().baseName);
// Résultat : "fr-CA"

const mexicanSpanish = new Intl.Locale("es-Latn-MX");
console.log(mexicanSpanish.minimize().baseName);
// Résultat : "es-MX"

Le composant script est supprimé car il correspond à la valeur par défaut, mais la région est conservée car elle spécifie une variante non par défaut de la langue.

Conservation des scripts non par défaut

Lorsque le script diffère de la valeur par défaut, il reste dans l'identifiant minimisé :

const simplifiedChinese = new Intl.Locale("zh-Hans-CN");
console.log(simplifiedChinese.minimize().baseName);
// Résultat : "zh-Hans"

const traditionalChinese = new Intl.Locale("zh-Hant-TW");
console.log(traditionalChinese.minimize().baseName);
// Résultat : "zh-Hant"

const serbianCyrillic = new Intl.Locale("sr-Cyrl-RS");
console.log(serbianCyrillic.minimize().baseName);
// Résultat : "sr-Cyrl"

Le chinois nécessite le composant script pour distinguer entre les variantes simplifiée et traditionnelle. Le serbe nécessite le composant script pour distinguer entre les écritures cyrillique et latine.

Identifiants déjà minimaux

Lorsqu'un identifiant de locale est déjà minimal, la méthode renvoie une locale équivalente sans changements :

const minimal = new Intl.Locale("fr");
console.log(minimal.minimize().baseName);
// Résultat : "fr"

Relation avec maximize

La méthode minimize() est l'inverse de maximize(). La méthode maximize() ajoute des sous-balises probables pour créer un identifiant complet, tandis que minimize() supprime les sous-balises redondantes pour créer un identifiant compact.

Ces méthodes forment une paire qui permet une conversion bidirectionnelle entre les formes complètes et compactes :

const compact = new Intl.Locale("en");
const complete = compact.maximize();
console.log(complete.baseName);
// Résultat : "en-Latn-US"

const compactAgain = complete.minimize();
console.log(compactAgain.baseName);
// Résultat : "en"

Le cycle aller-retour de compact à complet puis de nouveau à compact produit la forme originale.

Cependant, toutes les locales ne retrouvent pas leur forme originale exacte après un cycle aller-retour. La méthode produit une forme minimale canonique plutôt que de préserver la structure originale :

const locale = new Intl.Locale("en-US");
const maximized = locale.maximize();
console.log(maximized.baseName);
// Résultat : "en-Latn-US"

const minimized = maximized.minimize();
console.log(minimized.baseName);
// Résultat : "en"

L'identifiant original en-US contenait une région non redondante, mais après maximisation et minimisation, il devient en. Cela se produit parce que les États-Unis sont la région par défaut probable pour l'anglais.

Quand utiliser minimize

Utilisez minimize() lorsque vous avez besoin d'identifiants de locale compacts qui restent non ambigus. Plusieurs scénarios bénéficient de la minimisation.

Stockage des préférences de locale

Les identifiants minimisés réduisent l'espace de stockage dans les bases de données, le stockage local ou les fichiers de configuration :

function saveUserLocale(localeString) {
  const locale = new Intl.Locale(localeString);
  const minimized = locale.minimize().toString();

  localStorage.setItem("userLocale", minimized);
}

saveUserLocale("en-Latn-US");
// Stocke "en" au lieu de "en-Latn-US"

Cela réduit la taille des données stockées sans perdre d'informations.

Création d'URLs lisibles

Les identifiants minimisés produisent des URLs plus propres pour la sélection de langue :

function createLocalizedURL(path, localeString) {
  const locale = new Intl.Locale(localeString);
  const minimized = locale.minimize().baseName;

  return `/${minimized}${path}`;
}

const url = createLocalizedURL("/products", "en-Latn-US");
console.log(url);
// Output: "/en/products"

L'URL /en/products est plus lisible que /en-Latn-US/products.

Comparaison des identifiants de locale

La minimisation aide à déterminer si deux identifiants de locale représentent la même locale :

function areLocalesEquivalent(locale1String, locale2String) {
  const locale1 = new Intl.Locale(locale1String).minimize();
  const locale2 = new Intl.Locale(locale2String).minimize();

  return locale1.toString() === locale2.toString();
}

console.log(areLocalesEquivalent("en", "en-Latn-US"));
// Output: true

console.log(areLocalesEquivalent("en-US", "en-Latn-US"));
// Output: true

console.log(areLocalesEquivalent("en-US", "en-GB"));
// Output: false

La minimisation produit une forme canonique qui permet une comparaison directe.

Normalisation des entrées utilisateur

Lors de l'acceptation d'identifiants de locale provenant d'utilisateurs ou de systèmes externes, minimisez-les pour obtenir une forme standard :

function normalizeLocale(localeString) {
  try {
    const locale = new Intl.Locale(localeString);
    return locale.minimize().toString();
  } catch (error) {
    return null;
  }
}

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

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

console.log(normalizeLocale("en-GB"));
// Output: "en-GB"

Cette fonction accepte différentes formes de la même locale et renvoie une représentation cohérente.

Combinaison de minimize avec d'autres opérations de locale

La méthode minimize() fonctionne avec d'autres fonctionnalités d'Intl.Locale pour créer une gestion flexible des locales.

Minimisation après modification des propriétés de locale

Lors de la construction d'une locale à partir de composants, minimisez-la pour supprimer les parties inutiles :

const locale = new Intl.Locale("en", {
  region: "US",
  script: "Latn"
});

const minimized = locale.minimize();
console.log(minimized.baseName);
// Output: "en"

Cela garantit que l'identifiant final est aussi compact que les composants d'entrée le permettent.

Préservation des extensions lors de la minimisation

Les extensions restent intactes pendant la minimisation, vous permettant de minimiser les composants principaux tout en conservant les préférences de formatage :

function createCompactLocaleWithPreferences(language, region, preferences) {
  const locale = new Intl.Locale(language, {
    region: region,
    ...preferences
  });

  return locale.minimize().toString();
}

const localeString = createCompactLocaleWithPreferences("en", "US", {
  hourCycle: "h23",
  calendar: "gregory"
});

console.log(localeString);
// Output: "en-u-ca-gregory-hc-h23"

Les composants principaux se minimisent en en, mais les extensions de calendrier et de cycle horaire restent.