Comment afficher les noms de scripts comme Latin, Cyrillique, Arabe ?

Utilisez Intl.DisplayNames pour convertir les codes de script en noms lisibles par l'humain pour les systèmes d'écriture dans n'importe quelle langue.

Introduction

Un script est un système d'écriture. Le latin est le script utilisé pour l'anglais, le français et l'espagnol. Le cyrillique est le script utilisé pour le russe, le bulgare et l'ukrainien. L'arabe est le script utilisé pour l'arabe, le persan et l'ourdou. Les scripts diffèrent des langues car une même langue peut être écrite dans plusieurs scripts. Le serbe utilise à la fois les scripts cyrillique et latin. Les utilisateurs en Serbie choisissent le script qu'ils préfèrent.

Lorsque vous créez des sélecteurs de langue, des sélecteurs de police ou des contrôles de saisie de texte, vous devez afficher les noms des scripts pour que les utilisateurs puissent identifier les systèmes d'écriture. L'API Intl.DisplayNames convertit les codes de script en noms localisés et lisibles par l'humain sans que vous ayez à maintenir des tables de traduction.

Comprendre les scripts et les langues

Les scripts et les langues ne sont pas la même chose. Une langue est ce que les gens parlent. Un script est la façon dont les gens l'écrivent.

L'anglais est une langue. Le latin est un script. L'anglais utilise le script latin, mais des dizaines d'autres langues l'utilisent également, notamment l'espagnol, le français, l'allemand, le vietnamien et le turc.

Le serbe est une langue qui peut être écrite dans deux scripts. Le serbe écrit en cyrillique ressemble à "Српски". Le serbe écrit en latin ressemble à "Srpski". Les deux représentent la même langue avec les mêmes mots et la même grammaire. La différence réside uniquement dans le système d'écriture.

Le chinois a deux variantes de script courantes. Le chinois simplifié utilise des caractères Han simplifiés. Le chinois traditionnel utilise des caractères Han traditionnels. La même phrase apparaît différemment selon le script que vous utilisez.

Cette distinction est importante lors de la création d'interfaces. Un utilisateur serbe pourrait préférer le texte cyrillique au texte latin. Un utilisateur chinois doit choisir entre les caractères simplifiés et traditionnels. Votre interface doit afficher les noms des scripts pour que les utilisateurs puissent faire ces choix.

Le problème avec le codage en dur des noms de scripts

Vous pouvez créer une table de correspondance qui associe les codes de script aux noms de scripts.

const scriptNames = {
  Latn: "Latin",
  Cyrl: "Cyrillic",
  Arab: "Arabic",
  Hans: "Simplified Chinese",
  Hant: "Traditional Chinese"
};

console.log(scriptNames.Latn);
// "Latin"

Cette approche ne fonctionne que pour les anglophones. Les utilisateurs qui parlent d'autres langues voient des noms de scripts en anglais qu'ils ne comprennent peut-être pas. Vous avez besoin de traductions pour chaque langue que vous prenez en charge.

const scriptNames = {
  en: {
    Latn: "Latin",
    Cyrl: "Cyrillic",
    Arab: "Arabic"
  },
  es: {
    Latn: "latino",
    Cyrl: "cirílico",
    Arab: "árabe"
  },
  fr: {
    Latn: "latin",
    Cyrl: "cyrillique",
    Arab: "arabe"
  }
};

Cela devient rapidement ingérable. Chaque nouvelle langue nécessite un ensemble complet de traductions. Chaque nouveau script nécessite des entrées dans chaque langue. Vous avez besoin d'une meilleure solution.

Utilisation d'Intl.DisplayNames pour obtenir les noms de scripts

Le constructeur Intl.DisplayNames crée un formateur qui convertit les codes de script en noms lisibles par l'humain. Vous spécifiez une locale et définissez le type sur "script".

const names = new Intl.DisplayNames(["en"], { type: "script" });
console.log(names.of("Latn"));
// "Latin"

Le premier argument est un tableau d'identifiants de locale. Le second argument est un objet d'options où type: "script" indique au formateur que vous voulez des noms de scripts. La méthode of() prend un code de script et renvoie son nom.

Les codes de script suivent la norme ISO 15924. Chaque script a un code de quatre lettres avec la première lettre en majuscule et les trois lettres restantes en minuscule. Le latin est Latn. Le cyrillique est Cyrl. L'arabe est Arab.

const names = new Intl.DisplayNames(["en"], { type: "script" });

console.log(names.of("Latn"));
// "Latin"

console.log(names.of("Cyrl"));
// "Cyrillic"

console.log(names.of("Arab"));
// "Arabic"

console.log(names.of("Hani"));
// "Han"

console.log(names.of("Hira"));
// "Hiragana"

console.log(names.of("Kana"));
// "Katakana"

Le formateur gère toute la complexité de la maintenance des traductions des noms de scripts. Vous n'avez qu'à fournir le code du script.

Codes de script courants

La norme ISO 15924 définit des codes pour plus de 160 scripts. Voici les codes les plus couramment utilisés.

const names = new Intl.DisplayNames(["en"], { type: "script" });

console.log(names.of("Latn"));
// "Latin"

console.log(names.of("Cyrl"));
// "Cyrillic"

console.log(names.of("Arab"));
// "Arabic"

console.log(names.of("Hebr"));
// "Hebrew"

console.log(names.of("Deva"));
// "Devanagari"

console.log(names.of("Thai"));
// "Thai"

console.log(names.of("Hani"));
// "Han"

console.log(names.of("Hans"));
// "Simplified Han"

console.log(names.of("Hant"));
// "Traditional Han"

console.log(names.of("Hang"));
// "Hangul"

console.log(names.of("Hira"));
// "Hiragana"

console.log(names.of("Kana"));
// "Katakana"

console.log(names.of("Beng"));
// "Bengali"

console.log(names.of("Grek"));
// "Greek"

Le latin couvre la plupart des langues d'Europe occidentale. Le cyrillique couvre le russe, le bulgare, l'ukrainien et d'autres langues slaves. L'arabe couvre l'arabe, le persan et l'ourdou. Le han couvre le chinois, avec Hans pour le chinois simplifié et Hant pour le chinois traditionnel. Le hangul couvre le coréen. L'hiragana et le katakana sont des scripts japonais.

Affichage des noms de scripts dans différentes langues

Les noms de scripts se localisent en fonction de la langue d'affichage. Créez des formateurs avec différentes langues pour voir les noms dans différentes langues.

const enNames = new Intl.DisplayNames(["en"], { type: "script" });
const esNames = new Intl.DisplayNames(["es"], { type: "script" });
const frNames = new Intl.DisplayNames(["fr"], { type: "script" });
const jaNames = new Intl.DisplayNames(["ja"], { type: "script" });

console.log(enNames.of("Latn"));
// "Latin"

console.log(esNames.of("Latn"));
// "latino"

console.log(frNames.of("Latn"));
// "latin"

console.log(jaNames.of("Latn"));
// "ラテン文字"

Chaque formateur renvoie le nom du script dans sa langue d'affichage. Cela gère toute la complexité de la maintenance des traductions des noms de scripts.

Le même modèle fonctionne pour n'importe quel code de script.

const enNames = new Intl.DisplayNames(["en"], { type: "script" });
const deNames = new Intl.DisplayNames(["de"], { type: "script" });
const zhNames = new Intl.DisplayNames(["zh"], { type: "script" });

console.log(enNames.of("Cyrl"));
// "Cyrillic"

console.log(deNames.of("Cyrl"));
// "Kyrillisch"

console.log(zhNames.of("Cyrl"));
// "西里尔文"

console.log(enNames.of("Arab"));
// "Arabic"

console.log(deNames.of("Arab"));
// "Arabisch"

console.log(zhNames.of("Arab"));
// "阿拉伯文"

Le formateur applique automatiquement les conventions linguistiques correctes pour chaque langue.

Construction d'un sélecteur de script pour les variantes linguistiques

Certaines langues offrent aux utilisateurs un choix de scripts. Le serbe peut être écrit en cyrillique ou en latin. Le chinois peut être écrit en caractères simplifiés ou traditionnels. Vous devez afficher ces options pour que les utilisateurs puissent choisir.

function getScriptOptions(language, userLocale) {
  const names = new Intl.DisplayNames([userLocale], { type: "script" });

  if (language === "sr") {
    return [
      { code: "Cyrl", name: names.of("Cyrl") },
      { code: "Latn", name: names.of("Latn") }
    ];
  }

  if (language === "zh") {
    return [
      { code: "Hans", name: names.of("Hans") },
      { code: "Hant", name: names.of("Hant") }
    ];
  }

  return [];
}

console.log(getScriptOptions("sr", "en"));
// [
//   { code: "Cyrl", name: "Cyrillic" },
//   { code: "Latn", name: "Latin" }
// ]

console.log(getScriptOptions("zh", "en"));
// [
//   { code: "Hans", name: "Simplified Han" },
//   { code: "Hant", name: "Traditional Han" }
// ]

console.log(getScriptOptions("zh", "es"));
// [
//   { code: "Hans", name: "han simplificado" },
//   { code: "Hant", name: "han tradicional" }
// ]

Cette fonction renvoie les options de script dans la langue d'interface de l'utilisateur. Les utilisateurs serbes voient des options pour les scripts cyrillique et latin. Les utilisateurs chinois voient des options pour les scripts simplifiés et traditionnels. Les noms apparaissent dans la langue que l'utilisateur comprend.

Affichage des identifiants de locale complets avec informations de script

Les identifiants de locale peuvent inclure des codes de script pour distinguer les systèmes d'écriture. Le format est langue-script-région, comme sr-Cyrl-RS pour le serbe écrit en cyrillique en Serbie ou zh-Hans-CN pour le chinois simplifié en Chine.

Lorsque vous affichez ces identifiants de locale, extrayez le code du script et convertissez-le en un nom lisible.

function parseLocaleWithScript(locale) {
  const parts = locale.split("-");

  if (parts.length < 2) {
    return null;
  }

  const [language, script] = parts;

  if (script.length === 4) {
    return {
      language,
      script: script.charAt(0).toUpperCase() + script.slice(1).toLowerCase()
    };
  }

  return null;
}

function formatLocaleWithScriptName(locale, displayLocale) {
  const parsed = parseLocaleWithScript(locale);

  if (!parsed) {
    return locale;
  }

  const languageNames = new Intl.DisplayNames([displayLocale], {
    type: "language"
  });
  const scriptNames = new Intl.DisplayNames([displayLocale], { type: "script" });

  const languageName = languageNames.of(parsed.language);
  const scriptName = scriptNames.of(parsed.script);

  return `${languageName} (${scriptName})`;
}

console.log(formatLocaleWithScriptName("sr-Cyrl", "en"));
// "Serbian (Cyrillic)"

console.log(formatLocaleWithScriptName("sr-Latn", "en"));
// "Serbian (Latin)"

console.log(formatLocaleWithScriptName("zh-Hans", "en"));
// "Chinese (Simplified Han)"

console.log(formatLocaleWithScriptName("zh-Hant", "en"));
// "Chinese (Traditional Han)"

console.log(formatLocaleWithScriptName("sr-Cyrl", "es"));
// "serbio (cirílico)"

Ce modèle rend les identifiants de locale lisibles par l'humain en combinant les noms de langues avec les noms de scripts. Les utilisateurs voient "Serbe (cyrillique)" au lieu de "sr-Cyrl".

Création d'un sélecteur de police avec noms de scripts

Les interfaces de sélection de polices regroupent souvent les polices selon les scripts qu'elles prennent en charge. Vous devez afficher les noms des scripts pour que les utilisateurs comprennent quels scripts chaque police couvre.

function createFontOptions() {
  const fonts = [
    {
      name: "Arial",
      scripts: ["Latn", "Cyrl", "Grek", "Hebr", "Arab"]
    },
    {
      name: "Noto Sans CJK",
      scripts: ["Hans", "Hant", "Hira", "Kana", "Hang"]
    },
    {
      name: "Noto Sans Devanagari",
      scripts: ["Deva"]
    }
  ];

  const names = new Intl.DisplayNames(["en"], { type: "script" });

  return fonts.map((font) => ({
    name: font.name,
    scripts: font.scripts.map((code) => names.of(code))
  }));
}

console.log(createFontOptions());
// [
//   {
//     name: "Arial",
//     scripts: ["Latin", "Cyrillic", "Greek", "Hebrew", "Arabic"]
//   },
//   {
//     name: "Noto Sans CJK",
//     scripts: ["Simplified Han", "Traditional Han", "Hiragana", "Katakana", "Hangul"]
//   },
//   {
//     name: "Noto Sans Devanagari",
//     scripts: ["Devanagari"]
//   }
// ]

Cela crée une liste de polices avec leurs scripts pris en charge sous forme lisible par l'humain. Les utilisateurs peuvent choisir des polices en fonction des systèmes d'écriture dont ils ont besoin.

Affichage des méthodes de saisie disponibles par script

Les systèmes d'exploitation et les navigateurs fournissent des méthodes de saisie pour différents scripts. Une méthode de saisie japonaise convertit les caractères latins en Hiragana, Katakana ou Kanji. Une méthode de saisie chinoise convertit le Pinyin en caractères chinois simplifiés ou traditionnels. Vous pouvez afficher les méthodes de saisie disponibles avec leurs noms de script.

function getInputMethods(userLocale) {
  const inputMethods = [
    { id: "latin-ime", script: "Latn" },
    { id: "japanese-ime", script: "Hira" },
    { id: "chinese-pinyin-simplified", script: "Hans" },
    { id: "chinese-pinyin-traditional", script: "Hant" },
    { id: "korean-ime", script: "Hang" },
    { id: "arabic-ime", script: "Arab" },
    { id: "hebrew-ime", script: "Hebr" }
  ];

  const names = new Intl.DisplayNames([userLocale], { type: "script" });

  return inputMethods.map((method) => ({
    id: method.id,
    name: names.of(method.script)
  }));
}

console.log(getInputMethods("en"));
// [
//   { id: "latin-ime", name: "Latin" },
//   { id: "japanese-ime", name: "Hiragana" },
//   { id: "chinese-pinyin-simplified", name: "Simplified Han" },
//   { id: "chinese-pinyin-traditional", name: "Traditional Han" },
//   { id: "korean-ime", name: "Hangul" },
//   { id: "arabic-ime", name: "Arabic" },
//   { id: "hebrew-ime", name: "Hebrew" }
// ]

console.log(getInputMethods("ja"));
// [
//   { id: "latin-ime", name: "ラテン文字" },
//   { id: "japanese-ime", name: "ひらがな" },
//   { id: "chinese-pinyin-simplified", name: "簡体字" },
//   { id: "chinese-pinyin-traditional", name: "繁体字" },
//   { id: "korean-ime", name: "ハングル" },
//   { id: "arabic-ime", name: "アラビア文字" },
//   { id: "hebrew-ime", name: "ヘブライ文字" }
// ]

Cela affiche les noms des méthodes de saisie dans la langue de l'utilisateur. Les utilisateurs voient "Hiragana" lorsque l'interface est en anglais et "ひらがな" lorsque l'interface est en japonais.

Comprendre la capitalisation des codes de script

Les codes de script suivent un modèle de capitalisation spécifique. La première lettre est en majuscule. Les trois lettres restantes sont en minuscule. Latn est correct. LATN, latn, et LaTn ne sont pas standard.

La méthode of() accepte les codes de script quelle que soit leur capitalisation.

const names = new Intl.DisplayNames(["en"], { type: "script" });

console.log(names.of("Latn"));
// "Latin"

console.log(names.of("LATN"));
// "Latin"

console.log(names.of("latn"));
// "Latin"

console.log(names.of("LaTn"));
// "Latin"

Le formateur gère correctement toutes les variations. Cependant, l'utilisation du modèle de capitalisation standard rend votre code plus lisible et cohérent avec la norme ISO 15924.

Gestion des locales de repli

Le constructeur Intl.DisplayNames accepte un tableau de locales. Si la première locale n'est pas disponible, le formateur se replie sur la locale suivante dans le tableau.

const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "script" });
console.log(names.of("Latn"));
// "Latin"

Le formateur essaie d'abord "xx-XX", qui n'existe pas, puis se replie sur "en". Cela garantit que votre code fonctionne même lorsque la locale demandée n'est pas disponible.

Vous pouvez vérifier quelle locale le formateur utilise réellement avec la méthode resolvedOptions().

const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "script" });
console.log(names.resolvedOptions().locale);
// "en"

Cela montre que le formateur s'est résolu à l'anglais après le repli.

Construire un système de gestion de contenu multilingue

Les systèmes de gestion de contenu qui prennent en charge plusieurs scripts doivent montrer quels scripts sont disponibles pour chaque élément de contenu. Vous pouvez afficher les noms des scripts pour aider les éditeurs de contenu à choisir la version correcte.

function getContentVersions(contentId, userLocale) {
  const versions = [
    { script: "Latn", url: `/content/${contentId}/latn` },
    { script: "Cyrl", url: `/content/${contentId}/cyrl` },
    { script: "Arab", url: `/content/${contentId}/arab` }
  ];

  const names = new Intl.DisplayNames([userLocale], { type: "script" });

  return versions.map((version) => ({
    script: version.script,
    name: names.of(version.script),
    url: version.url
  }));
}

console.log(getContentVersions("article-123", "en"));
// [
//   { script: "Latn", name: "Latin", url: "/content/article-123/latn" },
//   { script: "Cyrl", name: "Cyrillic", url: "/content/article-123/cyrl" },
//   { script: "Arab", name: "Arabic", url: "/content/article-123/arab" }
// ]

Ce modèle aide les éditeurs de contenu à voir quelles versions de script existent et à naviguer entre elles.

Compatibilité des navigateurs

L'API Intl.DisplayNames avec prise en charge du type de script est disponible dans tous les navigateurs modernes. Elle est prise en charge depuis mars 2021 dans les principaux navigateurs, notamment Chrome, Firefox, Safari et Edge.

Vous pouvez vérifier si l'API est disponible avant de l'utiliser.

if (typeof Intl.DisplayNames !== "undefined") {
  const names = new Intl.DisplayNames(["en"], { type: "script" });
  console.log(names.of("Latn"));
} else {
  console.log("Intl.DisplayNames is not supported");
}

Pour les navigateurs plus anciens, vous devez fournir une solution de repli ou utiliser un polyfill. Une solution de repli simple utilise un mappage codé en dur des codes de script vers les noms.

function getScriptName(code, locale) {
  if (typeof Intl.DisplayNames !== "undefined") {
    const names = new Intl.DisplayNames([locale], { type: "script" });
    return names.of(code);
  }

  const fallbackNames = {
    Latn: "Latin",
    Cyrl: "Cyrillic",
    Arab: "Arabic",
    Hans: "Simplified Han",
    Hant: "Traditional Han"
  };

  return fallbackNames[code] || code;
}

console.log(getScriptName("Latn", "en"));
// "Latin"

Cela garantit que votre code fonctionne même dans les navigateurs sans prise en charge d'Intl.DisplayNames, bien que vous perdiez les fonctionnalités de localisation automatique.