Comment travailler avec des balises de langue comme en-US et fr-CA

Comprendre la structure et la signification des balises de langue BCP 47 pour prendre de meilleures décisions d'internationalisation

Introduction

Les balises de langue sont des codes standardisés qui identifient des langues spécifiques et leurs variations régionales. Ces balises apparaissent dans tout le travail d'internationalisation. Lorsque vous détectez la langue préférée d'un utilisateur, le navigateur renvoie des balises de langue. Lorsque vous formatez des dates ou des nombres, vous transmettez des balises de langue à l'API Intl. Lorsque vous chargez des traductions, vous utilisez des balises de langue pour déterminer quel contenu afficher.

Comprendre comment ces balises fonctionnent vous aide à prendre de meilleures décisions concernant la sélection de la langue, le comportement de repli et l'organisation du contenu. Cette leçon explique la structure des balises de langue et vous montre comment les utiliser en JavaScript.

Ce que sont les balises de langue

Une balise de langue est une chaîne comme en, en-US, ou zh-Hans-CN qui identifie une langue et spécifie éventuellement le script et la région. Ces balises suivent la norme BCP 47, qui est maintenue par l'Internet Engineering Task Force et l'Internet Assigned Numbers Authority.

BCP 47 signifie Best Current Practice 47. La norme définit comment construire des balises de langue à partir de composants plus petits appelés sous-balises. Chaque sous-balise représente un aspect spécifique de la langue, comme la langue utilisée, le système d'écriture qu'elle utilise, ou le pays auquel elle est associée.

Chaque langage de programmation et bibliothèque d'internationalisation utilise les balises BCP 47. Cette cohérence signifie que vous pouvez utiliser les mêmes identificateurs de langue dans toute votre application, de la détection par le navigateur au formatage côté serveur en passant par les noms de fichiers de traduction.

Structure des balises de langue

Les balises de langue sont composées de sous-balises séparées par des traits d'union. Les trois sous-balises les plus courantes sont la langue, le script et la région. Ces sous-balises apparaissent toujours dans cet ordre spécifique lorsqu'elles sont présentes.

La sous-balise de langue vient en premier et est le seul composant requis. Elle utilise un code de deux ou trois lettres issu de l'ISO 639. Par exemple, en représente l'anglais, fr représente le français, et zh représente le chinois.

La sous-balise de script vient en deuxième position lorsqu'elle est présente. Elle utilise un code de quatre lettres issu de l'ISO 15924 qui identifie le système d'écriture. Par exemple, Latn représente l'alphabet latin, Cyrl représente le cyrillique, et Hans représente les caractères chinois simplifiés.

La sous-balise de région vient en dernier lorsqu'elle est présente. Elle utilise un code de deux lettres issu de l'ISO 3166-1 qui représente généralement un pays. Par exemple, US représente les États-Unis, CA représente le Canada, et CN représente la Chine.

Exemples de balises de langue courantes

Voici des exemples qui démontrent les différents niveaux de spécificité que vous pouvez exprimer avec les balises de langue.

Balises simples avec uniquement une langue :

  • en - Anglais (sans région ou script spécifique)
  • fr - Français (sans région ou script spécifique)
  • es - Espagnol (sans région ou script spécifique)

Balises avec langue et région :

  • en-US - Anglais tel qu'utilisé aux États-Unis
  • en-GB - Anglais tel qu'utilisé en Grande-Bretagne
  • fr-CA - Français tel qu'utilisé au Canada
  • es-MX - Espagnol tel qu'utilisé au Mexique

Balises avec langue, script et région :

  • zh-Hans-CN - Chinois utilisant les caractères simplifiés en Chine
  • zh-Hant-TW - Chinois utilisant les caractères traditionnels à Taïwan
  • sr-Latn-RS - Serbe utilisant l'alphabet latin en Serbie
  • sr-Cyrl-RS - Serbe utilisant l'alphabet cyrillique en Serbie

Le niveau de spécificité dont vous avez besoin dépend de votre application. Si vous traduisez uniquement du texte, vous pourriez n'avoir besoin que de la langue et de la région. Si vous travaillez avec des langues qui utilisent plusieurs systèmes d'écriture, vous aurez besoin de sous-balises de script.

Conventions de casse pour les balises de langue

Les balises de langue ne sont pas sensibles à la casse. Les balises en-US, EN-US, en-us et En-Us représentent toutes la même langue. Cependant, il existe des modèles de capitalisation conventionnels qui rendent les balises plus lisibles.

Les sous-balises de langue utilisent conventionnellement des lettres minuscules. Écrivez en, pas EN ou En.

Les sous-balises de script utilisent conventionnellement la casse titre avec la première lettre en majuscule. Écrivez Latn, pas latn ou LATN.

Les sous-balises de région utilisent conventionnellement des lettres majuscules. Écrivez US, pas us ou Us.

Suivre ces conventions rend vos balises plus faciles à lire et correspond au format utilisé dans la documentation et les spécifications. Cependant, votre code devrait accepter les balises de langue quelle que soit la capitalisation, car le format est officiellement insensible à la casse.

Analyse des balises de langue avec JavaScript

JavaScript fournit le constructeur Intl.Locale pour analyser les balises de langue et extraire leurs composants. Ce constructeur accepte une chaîne de caractères représentant une balise de langue et renvoie un objet avec des propriétés pour chaque sous-balise.

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

console.log(locale.language);
// Résultat: "en"

console.log(locale.region);
// Résultat: "US"

L'objet Intl.Locale possède des propriétés pour chaque composant de la balise de langue. Ces propriétés renvoient undefined si la sous-balise correspondante n'est pas présente dans la balise d'origine.

const simple = new Intl.Locale("fr");
console.log(simple.language);
// Résultat: "fr"

console.log(simple.region);
// Résultat: undefined

Vous pouvez analyser les balises avec des sous-balises de script de la même manière.

const complex = new Intl.Locale("zh-Hans-CN");

console.log(complex.language);
// Résultat: "zh"

console.log(complex.script);
// Résultat: "Hans"

console.log(complex.region);
// Résultat: "CN"

Cette capacité d'analyse est utile lorsque vous devez prendre des décisions basées sur des composants spécifiques d'une balise de langue. Par exemple, vous pourriez vouloir charger différentes polices en fonction du script, ou afficher différents contenus en fonction de la région.

Quand utiliser des balises spécifiques ou générales

Le choix du niveau de spécificité pour les balises de langue dépend des aspects linguistiques et culturels que votre application doit gérer.

Utilisez des balises de langue uniquement comme en ou fr lorsque vous disposez d'une seule traduction qui fonctionne pour tous les locuteurs de cette langue. Cela est courant pour les applications avec des budgets de localisation limités ou des langues présentant peu de variations régionales.

Utilisez des balises de langue et de région comme en-US ou fr-CA lorsque vous devez tenir compte des différences régionales dans le vocabulaire, l'orthographe ou les conventions culturelles. L'anglais britannique et l'anglais américain utilisent des orthographes différentes pour de nombreux mots. Le français canadien et le français européen ont un vocabulaire et des expressions différents.

Utilisez des balises de langue, de script et de région comme zh-Hans-CN lorsque vous travaillez avec des langues qui utilisent plusieurs systèmes d'écriture. Le chinois peut être écrit avec des caractères simplifiés ou traditionnels. Le serbe peut être écrit avec des alphabets latins ou cyrilliques. La sous-balise de script permet de distinguer ces variantes.

Extraction des codes de langue pour les fichiers de traduction

De nombreux systèmes de traduction organisent les fichiers par code de langue. Vous pouvez extraire uniquement la langue et la région d'une balise de langue complète pour déterminer quel fichier de traduction charger.

const userLanguage = "zh-Hans-CN";
const locale = new Intl.Locale(userLanguage);

const translationKey = `${locale.language}-${locale.region}`;
console.log(translationKey);
// Résultat: "zh-CN"

Cette approche fonctionne même si la balise de langue de l'utilisateur inclut des composants dont vous n'avez pas besoin pour la sélection de fichiers.

Certaines applications utilisent uniquement le code de langue sans la région.

const userLanguage = "fr-CA";
const locale = new Intl.Locale(userLanguage);

const translationKey = locale.language;
console.log(translationKey);
// Résultat: "fr"

La structure que vous choisissez pour les noms de fichiers de traduction doit correspondre à la façon dont vous extrayez les composants des balises de langue.

Utilisation des balises de langue avec l'API Intl

L'API Intl accepte directement les balises de langue dans tous ses constructeurs. Vous n'avez pas besoin d'analyser la balise vous-même, sauf si vous devez examiner des composants spécifiques.

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

const usFormat = new Intl.DateTimeFormat("en-US").format(date);
console.log(usFormat);
// Résultat: "3/15/2025"

const gbFormat = new Intl.DateTimeFormat("en-GB").format(date);
console.log(gbFormat);
// Résultat: "15/03/2025"

L'API Intl utilise la balise de langue pour déterminer quelles conventions de formatage appliquer. Les différentes régions formatent les dates, les nombres et les devises différemment, même lorsqu'elles parlent la même langue.

Vous pouvez passer directement la balise de langue que vous obtenez du navigateur aux constructeurs Intl.

const userLanguage = navigator.language;
const formatter = new Intl.NumberFormat(userLanguage);

console.log(formatter.format(1234.5));
// Le résultat varie selon la langue
// Pour "en-US": "1,234.5"
// Pour "de-DE": "1.234,5"

C'est le modèle le plus courant dans l'internationalisation côté client. Détectez la langue de l'utilisateur, puis utilisez cette balise de langue dans toute votre application pour formater le contenu de manière appropriée.

Gestion des balises de langue invalides

Le constructeur Intl.Locale lance une erreur RangeError si vous passez une balise de langue invalide. Vous devriez gérer cette erreur lorsque vous travaillez avec des balises de langue provenant de sources non fiables.

try {
  const locale = new Intl.Locale("invalid-tag-format");
} catch (error) {
  console.log(error.name);
  // Output: "RangeError"

  console.log(error.message);
  // Output: "invalid language tag: invalid-tag-format"
}

La plupart des balises de langue provenant des navigateurs sont valides, mais les entrées utilisateur ou les sources de données externes peuvent contenir des balises mal formées. Encapsuler le constructeur dans une gestion d'erreur empêche ces balises invalides de faire planter votre application.