Comment personnaliser les locales avec les extensions Unicode
Ajouter des systèmes de calendrier, des formats de numérotation et des préférences d'affichage de l'heure aux identifiants de locale
Introduction
Un identifiant de locale comme en-US indique à JavaScript quelle langue et quelle région utiliser pour le formatage. Cependant, il ne précise pas quel système de calendrier utiliser, quel format de numérotation afficher, ou si l'heure doit être affichée au format 12 heures ou 24 heures. Ces préférences de formatage varient selon le choix de l'utilisateur, et pas seulement selon l'emplacement.
Les extensions Unicode résolvent ce problème. Elles vous permettent d'ajouter des préférences de formatage directement aux identifiants de locale. Au lieu d'utiliser des options de configuration distinctes pour chaque formateur, vous encodez les préférences une seule fois dans la chaîne de locale elle-même.
Ce guide explique comment fonctionnent les extensions Unicode, quels types d'extensions sont disponibles et quand les utiliser dans votre code d'internationalisation.
Que sont les extensions Unicode
Les extensions Unicode sont des balises supplémentaires que vous ajoutez aux identifiants de locale pour spécifier les préférences de formatage. Elles suivent un format standard défini dans BCP 47, la même spécification qui définit les identifiants de locale.
Une extension commence par -u- suivi de paires clé-valeur. Le u signifie Unicode. Chaque clé comporte deux lettres, et les valeurs varient selon le type de clé.
const locale = "en-US-u-ca-gregory-hc-h12";
Cet identifiant de locale spécifie l'anglais américain avec le calendrier grégorien et l'affichage de l'heure au format 12 heures.
Comment ajouter des extensions aux chaînes de locale
Les extensions apparaissent à la fin d'un identifiant de locale, après les composants de langue, de script et de région. Le marqueur -u- sépare l'identifiant principal des extensions.
La structure de base suit ce modèle :
langue-région-u-clé-valeur-clé-valeur
Chaque paire clé-valeur spécifie une préférence de formatage. Vous pouvez inclure plusieurs paires clé-valeur dans une seule chaîne de locale.
const japanese = new Intl.Locale("ja-JP-u-ca-japanese-nu-jpan");
console.log(japanese.calendar); // "japanese"
console.log(japanese.numberingSystem); // "jpan"
L'ordre des paires clé-valeur n'a pas d'importance. "en-u-ca-gregory-nu-latn" et "en-u-nu-latn-ca-gregory" sont tous deux valides et équivalents.
Extensions de calendrier
La clé ca spécifie quel système de calendrier utiliser pour le formatage des dates. Différentes cultures utilisent différents systèmes de calendrier, et certains utilisateurs préfèrent les calendriers non grégoriens pour des raisons religieuses ou culturelles.
Les valeurs de calendrier courantes incluent :
gregorypour le calendrier grégorienbuddhistpour le calendrier bouddhisteislamicpour le calendrier islamiquehebrewpour le calendrier hébraïquechinesepour le calendrier chinoisjapanesepour le calendrier impérial japonais
const islamicLocale = new Intl.Locale("ar-SA-u-ca-islamic");
const date = new Date("2025-03-15");
const formatter = new Intl.DateTimeFormat(islamicLocale, {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(formatter.format(date));
// Output: "٢٠ رمضان ١٤٤٦ هـ"
Ceci formate la date selon le calendrier islamique. La même date grégorienne apparaît comme une année, un mois et un jour différents dans le système de calendrier islamique.
Le calendrier bouddhiste est couramment utilisé en Thaïlande. Il compte les années à partir de la naissance de Bouddha en 543 av. J.-C., ce qui fait que les années bouddhistes sont en avance de 543 ans sur les années grégoriennes.
const buddhistLocale = new Intl.Locale("th-TH-u-ca-buddhist");
const formatter = new Intl.DateTimeFormat(buddhistLocale, {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(formatter.format(new Date("2025-03-15")));
// Output: "15 มีนาคม 2568"
L'année 2025 dans le calendrier grégorien correspond à l'année 2568 dans le calendrier bouddhiste.
Extensions de système de numération
La clé nu spécifie quel système de numération utiliser pour afficher les nombres. Bien que la plupart des locales utilisent les chiffres arabes occidentaux (0-9), de nombreuses régions ont leurs propres systèmes de numération traditionnels.
Les valeurs courantes de système de numération incluent :
latnpour les chiffres arabes occidentaux (0-9)arabpour les chiffres indo-arabeshanidecpour les chiffres décimaux chinoisdevapour les chiffres devanagarithaipour les chiffres thaïlandais
const arabicLocale = new Intl.Locale("ar-EG-u-nu-arab");
const number = 123456;
const formatter = new Intl.NumberFormat(arabicLocale);
console.log(formatter.format(number));
// Output: "١٢٣٬٤٥٦"
Les chiffres indo-arabes ont un aspect différent des chiffres occidentaux mais représentent les mêmes valeurs. Le nombre 123456 apparaît comme ١٢٣٬٤٥٦.
Les chiffres thaïlandais fournissent un autre exemple :
const thaiLocale = new Intl.Locale("th-TH-u-nu-thai");
const formatter = new Intl.NumberFormat(thaiLocale);
console.log(formatter.format(123456));
// Output: "๑๒๓,๔๕๖"
De nombreuses locales arabes prennent en charge à la fois les chiffres indo-arabes et les chiffres latins. Les utilisateurs peuvent choisir leur système préféré en fonction de leurs préférences personnelles ou du contexte.
Extensions de cycle horaire
La clé hc spécifie comment afficher l'heure. Certaines régions préfèrent le format 12 heures avec les indicateurs AM et PM, tandis que d'autres préfèrent le format 24 heures. Le cycle horaire détermine également comment apparaît minuit.
Quatre valeurs de cycle horaire sont disponibles :
h12utilise les heures 1-12 avec minuit à 12:00 AMh11utilise les heures 0-11 avec minuit à 0:00 AMh23utilise les heures 0-23 avec minuit à 0:00h24utilise les heures 1-24 avec minuit à 24:00
Les valeurs h12 et h11 représentent le format 12 heures, tandis que h23 et h24 représentent le format 24 heures. La différence réside dans le fait que la plage horaire commence à 0 ou à 1.
const us12Hour = new Intl.Locale("en-US-u-hc-h12");
const japan11Hour = new Intl.Locale("ja-JP-u-hc-h11");
const europe23Hour = new Intl.Locale("en-GB-u-hc-h23");
const date = new Date("2025-03-15T00:30:00");
console.log(new Intl.DateTimeFormat(us12Hour, { hour: "numeric", minute: "numeric" }).format(date));
// Output: "12:30 AM"
console.log(new Intl.DateTimeFormat(japan11Hour, { hour: "numeric", minute: "numeric" }).format(date));
// Output: "0:30 AM"
console.log(new Intl.DateTimeFormat(europe23Hour, { hour: "numeric", minute: "numeric" }).format(date));
// Output: "00:30"
Le format h12 affiche minuit comme 12:30 AM, tandis que h11 l'affiche comme 0:30 AM. Le format h23 l'affiche comme 00:30 sans AM ou PM.
La plupart des applications utilisent soit h12 soit h23. Le format h11 est principalement utilisé au Japon, et h24 est rarement utilisé en pratique.
Extensions de collation
La clé co spécifie les règles de collation pour trier les chaînes de caractères. La collation détermine l'ordre des caractères lors du tri de texte. Différentes langues et régions ont différentes conventions de tri.
Les valeurs de collation courantes incluent :
standardpour la collation Unicode standardphonebkpour l'ordre de l'annuaire téléphonique (allemand)pinyinpour l'ordre Pinyin (chinois)strokepour l'ordre par nombre de traits (chinois)
La collation de l'annuaire téléphonique allemand traite les trémas différemment de la collation standard. L'ordre de l'annuaire téléphonique développe ä en ae, ö en oe, et ü en ue pour les besoins du tri.
const names = ["Müller", "Meyer", "Möller", "Mueller"];
const standard = new Intl.Collator("de-DE");
const phonebook = new Intl.Collator("de-DE-u-co-phonebk");
console.log(names.sort((a, b) => standard.compare(a, b)));
// Output: ["Meyer", "Möller", "Mueller", "Müller"]
console.log(names.sort((a, b) => phonebook.compare(a, b)));
// Output: ["Meyer", "Möller", "Mueller", "Müller"]
La collation chinoise offre plusieurs systèmes d'ordonnancement. L'ordre Pinyin trie par prononciation, tandis que l'ordre par traits trie par le nombre de coups de pinceau utilisés pour écrire chaque caractère.
const pinyinCollator = new Intl.Collator("zh-CN-u-co-pinyin");
const strokeCollator = new Intl.Collator("zh-CN-u-co-stroke");
Les extensions de collation n'affectent que l'API Intl.Collator et les méthodes comme Array.prototype.sort() lorsqu'elles sont utilisées avec des collateurs.
Extensions de priorité de casse
La clé kf détermine si les lettres majuscules ou minuscules sont triées en premier dans la collation. Cette préférence varie selon la langue et le cas d'utilisation.
Trois valeurs sont disponibles :
upperpour trier les lettres majuscules avant les minusculeslowerpour trier les lettres minuscules avant les majusculesfalsepour utiliser l'ordre de casse par défaut de la locale
const words = ["apple", "Apple", "APPLE", "banana"];
const upperFirst = new Intl.Collator("en-US-u-kf-upper");
const lowerFirst = new Intl.Collator("en-US-u-kf-lower");
console.log(words.sort((a, b) => upperFirst.compare(a, b)));
// Output: ["APPLE", "Apple", "apple", "banana"]
console.log(words.sort((a, b) => lowerFirst.compare(a, b)));
// Output: ["apple", "Apple", "APPLE", "banana"]
L'ordre de priorité de casse affecte la collation lorsque les mots sont par ailleurs identiques à l'exception de la casse. Il détermine l'ordre de tri secondaire après la comparaison des caractères de base.
Extensions de collation numérique
La clé kn active la collation numérique, qui trie les séquences numériques par leur valeur numérique au lieu de lexicographiquement. Sans collation numérique, "10" est trié avant "2" car "1" vient avant "2" dans l'ordre des caractères.
La collation numérique accepte deux valeurs :
truepour activer la collation numériquefalsepour désactiver la collation numérique (par défaut)
const items = ["item1", "item10", "item2", "item20"];
const standard = new Intl.Collator("en-US");
const numeric = new Intl.Collator("en-US-u-kn-true");
console.log(items.sort((a, b) => standard.compare(a, b)));
// Output: ["item1", "item10", "item2", "item20"]
console.log(items.sort((a, b) => numeric.compare(a, b)));
// Output: ["item1", "item2", "item10", "item20"]
Avec la collation numérique activée, "item2" est correctement trié avant "item10" car 2 est inférieur à 10. Cela produit l'ordre de tri attendu pour les chaînes contenant des nombres.
La collation numérique est utile pour trier les noms de fichiers, les numéros de version, les adresses et tout texte contenant des nombres intégrés.
Utilisation d'objets d'options au lieu de chaînes d'extension
Au lieu d'encoder les extensions dans la chaîne de paramètres régionaux, vous pouvez les passer comme options au constructeur Intl.Locale. Cette approche sépare les paramètres régionaux de base des préférences de formatage.
const locale = new Intl.Locale("ja-JP", {
calendar: "japanese",
numberingSystem: "jpan",
hourCycle: "h11"
});
console.log(locale.toString());
// Résultat : "ja-JP-u-ca-japanese-hc-h11-nu-jpan"
Le constructeur convertit automatiquement les options en balises d'extension. Les deux approches produisent des objets de paramètres régionaux identiques.
L'approche par objet d'options offre plusieurs avantages. Elle rend le code plus lisible en utilisant des noms de propriétés complets au lieu de codes à deux lettres. Elle facilite également la construction dynamique de paramètres régionaux à partir de données de configuration.
const userPreferences = {
language: "ar",
region: "SA",
calendar: "islamic",
numberingSystem: "arab"
};
const locale = new Intl.Locale(`${userPreferences.language}-${userPreferences.region}`, {
calendar: userPreferences.calendar,
numberingSystem: userPreferences.numberingSystem
});
Vous pouvez également passer des options directement aux constructeurs de formateurs :
const formatter = new Intl.DateTimeFormat("th-TH", {
calendar: "buddhist",
numberingSystem: "thai",
year: "numeric",
month: "long",
day: "numeric"
});
Cela combine les options de formatage spécifiques aux paramètres régionaux avec les options de présentation dans un seul appel de constructeur.
Quand utiliser les extensions par rapport aux options de formateur
Les extensions et les options de formateur servent des objectifs différents. Comprendre quand utiliser chaque approche vous aide à écrire un code plus propre et plus maintenable.
Utilisez les extensions dans la chaîne de paramètres régionaux lorsque les préférences de formatage sont inhérentes aux paramètres régionaux de l'utilisateur. Si un utilisateur thaïlandais souhaite toujours voir le calendrier bouddhiste et les chiffres thaïlandais, encodez ces préférences dans son identifiant de paramètres régionaux.
const userLocale = "th-TH-u-ca-buddhist-nu-thai";
Cela vous permet de passer les paramètres régionaux à n'importe quel formateur sans répéter les préférences :
const dateFormatter = new Intl.DateTimeFormat(userLocale);
const numberFormatter = new Intl.NumberFormat(userLocale);
Les deux formateurs utilisent automatiquement le calendrier bouddhiste et les chiffres thaïlandais.
Utilisez les options de formateur lorsque les préférences de formatage sont spécifiques à un cas d'utilisation. Si vous souhaitez afficher le calendrier islamique dans une partie de votre application mais le calendrier grégorien ailleurs, passez l'option de calendrier au formateur spécifique.
const islamicFormatter = new Intl.DateTimeFormat("ar-SA", {
calendar: "islamic"
});
const gregorianFormatter = new Intl.DateTimeFormat("ar-SA", {
calendar: "gregory"
});
Le même identifiant de paramètres régionaux produit un formatage différent en fonction de l'option de calendrier.
Les extensions dans la chaîne de paramètres régionaux agissent comme des valeurs par défaut. Les options de formateur remplacent ces valeurs par défaut lorsqu'elles sont spécifiées. Cela vous permet d'utiliser les préférences de l'utilisateur comme référence tout en personnalisant des formateurs spécifiques.
const locale = "en-US-u-hc-h23";
const formatter12Hour = new Intl.DateTimeFormat(locale, {
hourCycle: "h12"
});
L'utilisateur préfère le format 24 heures, mais ce formateur spécifique remplace cette préférence pour afficher le format 12 heures.
Lecture des valeurs d'extension à partir des locales
L'objet Intl.Locale expose les valeurs d'extension sous forme de propriétés. Vous pouvez lire ces propriétés pour inspecter ou valider les préférences de formatage d'une locale.
const locale = new Intl.Locale("ar-SA-u-ca-islamic-nu-arab-hc-h12");
console.log(locale.calendar); // "islamic"
console.log(locale.numberingSystem); // "arab"
console.log(locale.hourCycle); // "h12"
Ces propriétés renvoient les valeurs d'extension si elles sont présentes, ou undefined si l'extension n'est pas spécifiée.
Vous pouvez utiliser ces propriétés pour créer des interfaces de configuration ou valider les préférences utilisateur :
function describeLocalePreferences(localeString) {
const locale = new Intl.Locale(localeString);
return {
language: locale.language,
region: locale.region,
calendar: locale.calendar || "default",
numberingSystem: locale.numberingSystem || "default",
hourCycle: locale.hourCycle || "default"
};
}
console.log(describeLocalePreferences("th-TH-u-ca-buddhist-nu-thai"));
// Sortie : { language: "th", region: "TH", calendar: "buddhist", numberingSystem: "thai", hourCycle: "default" }
Les propriétés collation, caseFirst et numeric correspondent aux clés d'extension co, kf et kn :
const locale = new Intl.Locale("de-DE-u-co-phonebk-kf-upper-kn-true");
console.log(locale.collation); // "phonebk"
console.log(locale.caseFirst); // "upper"
console.log(locale.numeric); // true
Notez que la propriété numeric renvoie un booléen, pas une chaîne de caractères. La valeur true indique que le classement numérique est activé.
Combinaison de plusieurs extensions
Vous pouvez combiner plusieurs extensions dans un seul identifiant de locale. Cela vous permet de spécifier toutes les préférences de formatage en une seule fois.
const locale = new Intl.Locale("ar-SA-u-ca-islamic-nu-arab-hc-h12-co-standard");
const dateFormatter = new Intl.DateTimeFormat(locale, {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric"
});
const date = new Date("2025-03-15T14:30:00");
console.log(dateFormatter.format(date));
// La sortie utilise le calendrier islamique, les chiffres arabo-indiens et le format 12 heures
Chaque clé d'extension ne peut apparaître qu'une seule fois dans une chaîne de locale. Si vous spécifiez la même clé plusieurs fois, la dernière valeur prévaut.
const locale = new Intl.Locale("en-US-u-hc-h23-hc-h12");
console.log(locale.hourCycle); // "h12"
Lors de la construction programmatique des locales, assurez-vous que chaque clé d'extension n'apparaît qu'une seule fois pour éviter toute ambiguïté.
Cas d'utilisation pratiques
Les extensions Unicode résolvent des problèmes concrets dans les applications internationalisées. Comprendre les cas d'utilisation courants vous aide à appliquer efficacement ces extensions.
Stockage des préférences utilisateur
Stockez les préférences de formatage de l'utilisateur dans une seule chaîne de paramètres régionaux au lieu de plusieurs champs de configuration :
function saveUserPreferences(userId, localeString) {
const locale = new Intl.Locale(localeString);
return {
userId,
language: locale.language,
region: locale.region,
localeString: locale.toString(),
preferences: {
calendar: locale.calendar,
numberingSystem: locale.numberingSystem,
hourCycle: locale.hourCycle
}
};
}
const preferences = saveUserPreferences(123, "ar-SA-u-ca-islamic-nu-arab-hc-h12");
Cette approche stocke les préférences de formatage sous forme d'une chaîne unique tout en offrant un accès structuré aux composants individuels.
Construction de sélecteurs de paramètres régionaux
Permettez aux utilisateurs de choisir leurs préférences de formatage via une interface utilisateur en construisant des chaînes de paramètres régionaux avec extensions :
function buildLocaleFromUserInput(language, region, preferences) {
const options = {};
if (preferences.calendar) {
options.calendar = preferences.calendar;
}
if (preferences.numberingSystem) {
options.numberingSystem = preferences.numberingSystem;
}
if (preferences.hourCycle) {
options.hourCycle = preferences.hourCycle;
}
const locale = new Intl.Locale(`${language}-${region}`, options);
return locale.toString();
}
const userLocale = buildLocaleFromUserInput("th", "TH", {
calendar: "buddhist",
numberingSystem: "thai",
hourCycle: "h23"
});
console.log(userLocale);
// Résultat : "th-TH-u-ca-buddhist-hc-h23-nu-thai"
Respect des calendriers religieux
Les applications destinées aux communautés religieuses doivent prendre en charge leurs systèmes de calendrier :
function createReligiousCalendarFormatter(religion, baseLocale) {
const calendars = {
jewish: "hebrew",
muslim: "islamic",
buddhist: "buddhist"
};
const calendar = calendars[religion];
if (!calendar) {
return new Intl.DateTimeFormat(baseLocale);
}
const locale = new Intl.Locale(baseLocale, { calendar });
return new Intl.DateTimeFormat(locale, {
year: "numeric",
month: "long",
day: "numeric"
});
}
const jewishFormatter = createReligiousCalendarFormatter("jewish", "en-US");
console.log(jewishFormatter.format(new Date("2025-03-15")));
// Résultat : "15 Adar II 5785"
Tri avec règles personnalisées
Utilisez les extensions de collation pour implémenter un tri spécifique à la langue :
function sortNames(names, locale, collationType) {
const localeWithCollation = new Intl.Locale(locale, {
collation: collationType
});
const collator = new Intl.Collator(localeWithCollation);
return names.sort((a, b) => collator.compare(a, b));
}
const germanNames = ["Müller", "Meyer", "Möller", "Mueller"];
const sorted = sortNames(germanNames, "de-DE", "phonebk");
console.log(sorted);
Affichage des chiffres traditionnels
Affichez les nombres dans les systèmes de numération traditionnels pour un affichage culturellement approprié :
function formatTraditionalNumber(number, locale, numberingSystem) {
const localeWithNumbering = new Intl.Locale(locale, {
numberingSystem
});
return new Intl.NumberFormat(localeWithNumbering).format(number);
}
console.log(formatTraditionalNumber(123456, "ar-EG", "arab"));
// Résultat : "١٢٣٬٤٥٦"
console.log(formatTraditionalNumber(123456, "th-TH", "thai"));
// Résultat : "๑๒๓,๔๕๖"
Compatibilité des navigateurs
Les extensions Unicode fonctionnent dans tous les navigateurs modernes. Chrome, Firefox, Safari et Edge prennent en charge la syntaxe d'extension dans les identifiants de locale et les propriétés correspondantes sur les objets Intl.Locale.
La disponibilité de valeurs d'extension spécifiques dépend de l'implémentation du navigateur. Tous les navigateurs prennent en charge les valeurs courantes comme gregory pour le calendrier, latn pour le système de numération, et h12 ou h23 pour le cycle horaire. Les valeurs moins courantes comme les calendriers chinois traditionnels ou les systèmes de numération des langues minoritaires peuvent ne pas fonctionner dans tous les navigateurs.
Testez vos identifiants de locale dans les navigateurs cibles lorsque vous utilisez des valeurs d'extension moins courantes. Utilisez les propriétés Intl.Locale pour vérifier si le navigateur a reconnu vos valeurs d'extension :
const locale = new Intl.Locale("zh-CN-u-ca-chinese");
console.log(locale.calendar);
// Si le navigateur prend en charge le calendrier chinois : "chinese"
// Si le navigateur ne le prend pas en charge : undefined
Node.js prend en charge les extensions Unicode à partir de la version 12, avec une prise en charge complète de toutes les propriétés dans la version 18 et ultérieures.
Résumé
Les extensions Unicode vous permettent d'ajouter des préférences de formatage aux identifiants de locale. Au lieu de configurer chaque formateur séparément, vous encodez les préférences une seule fois dans la chaîne de locale.
Concepts clés :
- Les extensions commencent par
-u-suivi de paires clé-valeur - La clé
caspécifie le système de calendrier - La clé
nuspécifie le système de numération - La clé
hcspécifie le format du cycle horaire - La clé
cospécifie les règles de collation - La clé
kfspécifie l'ordre de priorité des majuscules - La clé
knactive la collation numérique - Vous pouvez utiliser des chaînes d'extension ou des objets d'options
- Les extensions agissent comme des valeurs par défaut que les options du formateur peuvent remplacer
- L'objet
Intl.Localeexpose les extensions sous forme de propriétés
Utilisez les extensions Unicode pour stocker les préférences des utilisateurs, respecter les calendriers culturels, afficher des chiffres traditionnels et implémenter le tri spécifique à la locale. Elles fournissent une méthode standard pour personnaliser le comportement de formatage dans le code d'internationalisation JavaScript.