라틴 문자, 키릴 문자, 아랍 문자와 같은 문자 체계 이름을 표시하는 방법
Intl.DisplayNames를 사용하여 문자 체계 코드를 모든 언어로 사람이 읽을 수 있는 문자 체계 이름으로 변환하세요.
소개
문자 체계는 표기 시스템입니다. 라틴 문자는 영어, 프랑스어, 스페인어에 사용됩니다. 키릴 문자는 러시아어, 불가리아어, 우크라이나어에 사용됩니다. 아랍 문자는 아랍어, 페르시아어, 우르두어에 사용됩니다. 문자 체계는 언어와 다릅니다. 동일한 언어가 여러 문자 체계로 작성될 수 있기 때문입니다. 세르비아어는 키릴 문자와 라틴 문자를 모두 사용합니다. 세르비아 사용자는 선호하는 문자 체계를 선택합니다.
언어 선택기, 글꼴 선택기 또는 텍스트 입력 컨트롤을 구축할 때 사용자가 문자 체계를 식별할 수 있도록 스크립트 이름을 표시해야 합니다. Intl.DisplayNames API는 번역 테이블을 유지 관리할 필요 없이 스크립트 코드를 현지화된 사람이 읽을 수 있는 이름으로 변환합니다.
문자 체계와 언어 이해하기
문자 체계와 언어는 같은 것이 아닙니다. 언어는 사람들이 말하는 것입니다. 문자 체계는 사람들이 그것을 쓰는 방법입니다.
영어는 언어입니다. 라틴 문자는 문자 체계입니다. 영어는 라틴 문자를 사용하지만 스페인어, 프랑스어, 독일어, 베트남어, 터키어를 포함한 수십 개의 다른 언어도 라틴 문자를 사용합니다.
세르비아어는 두 가지 문자 체계로 작성될 수 있는 언어입니다. 키릴 문자로 작성된 세르비아어는 "Српски"처럼 보입니다. 라틴 문자로 작성된 세르비아어는 "Srpski"처럼 보입니다. 둘 다 동일한 단어와 문법을 가진 동일한 언어를 나타냅니다. 차이점은 표기 시스템뿐입니다.
중국어에는 두 가지 일반적인 문자 체계 변형이 있습니다. 간체 중국어는 간체 한자를 사용합니다. 번체 중국어는 번체 한자를 사용합니다. 동일한 문장이 사용하는 문자 체계에 따라 다르게 표시됩니다.
인터페이스를 구축할 때 이러한 구분이 중요합니다. 세르비아어 사용자는 라틴 문자보다 키릴 문자를 선호할 수 있습니다. 중국어 사용자는 간체와 번체 중에서 선택해야 합니다. 사용자가 이러한 선택을 할 수 있도록 인터페이스에 문자 체계 이름을 표시해야 합니다.
문자 체계 이름 하드코딩의 문제점
문자 체계 코드를 문자 체계 이름에 매핑하는 조회 테이블을 만들 수 있습니다.
const scriptNames = {
Latn: "Latin",
Cyrl: "Cyrillic",
Arab: "Arabic",
Hans: "Simplified Chinese",
Hant: "Traditional Chinese"
};
console.log(scriptNames.Latn);
// "Latin"
이 방식은 영어 사용자에게만 작동합니다. 다른 언어를 사용하는 사용자는 이해하지 못할 수 있는 영어 문자 체계 이름을 보게 됩니다. 지원하는 모든 언어에 대한 번역이 필요합니다.
const scriptNames = {
en: {
Latn: "Latin",
Cyrl: "Cyrillic",
Arab: "Arabic"
},
es: {
Latn: "latino",
Cyrl: "cirílico",
Arab: "árabe"
},
fr: {
Latn: "latin",
Cyrl: "cyrillique",
Arab: "arabe"
}
};
이는 빠르게 유지 관리가 불가능해집니다. 새로운 언어마다 완전한 번역 세트가 필요합니다. 새로운 문자 체계마다 모든 언어에 항목이 필요합니다. 더 나은 솔루션이 필요합니다.
Intl.DisplayNames를 사용하여 문자 체계 이름 가져오기
Intl.DisplayNames 생성자는 스크립트 코드를 사람이 읽을 수 있는 이름으로 변환하는 포매터를 생성합니다. 로케일을 지정하고 타입을 "script"로 설정합니다.
const names = new Intl.DisplayNames(["en"], { type: "script" });
console.log(names.of("Latn"));
// "Latin"
첫 번째 인수는 로케일 식별자 배열입니다. 두 번째 인수는 옵션 객체이며, 여기서 type: "script"는 포매터에 스크립트 이름을 원한다고 알려줍니다. of() 메서드는 스크립트 코드를 받아 해당 이름을 반환합니다.
스크립트 코드는 ISO 15924 표준을 따릅니다. 각 스크립트는 첫 글자는 대문자이고 나머지 세 글자는 소문자인 네 글자 코드를 가집니다. 라틴 문자는 Latn입니다. 키릴 문자는 Cyrl입니다. 아랍 문자는 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"
포매터는 문자 체계 이름 번역을 유지 관리하는 모든 복잡성을 처리합니다. 문자 체계 코드만 제공하면 됩니다.
일반적인 문자 체계 코드
ISO 15924 표준은 160개 이상의 문자 체계에 대한 코드를 정의합니다. 다음은 가장 일반적으로 사용되는 코드입니다.
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"
라틴 문자는 대부분의 서유럽 언어를 포함합니다. 키릴 문자는 러시아어, 불가리아어, 우크라이나어 및 기타 슬라브어를 포함합니다. 아랍 문자는 아랍어, 페르시아어, 우르두어를 포함합니다. 한자는 중국어를 포함하며, 간체 중국어는 Hans, 번체 중국어는 Hant로 표시됩니다. 한글은 한국어를 포함합니다. 히라가나와 가타카나는 일본어 문자입니다.
다양한 로케일에서 문자 체계 이름 표시하기
문자 체계 이름은 표시 로케일에 따라 현지화됩니다. 다양한 로케일로 포매터를 생성하여 여러 언어로 이름을 확인할 수 있습니다.
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"));
// "ラテン文字"
각 포매터는 해당 표시 로케일로 문자 체계 이름을 반환합니다. 이는 문자 체계 이름 번역을 유지하는 모든 복잡성을 처리합니다.
동일한 패턴이 모든 문자 체계 코드에 적용됩니다.
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"));
// "阿拉伯文"
포매터는 각 언어에 대한 올바른 언어적 규칙을 자동으로 적용합니다.
언어 변형을 위한 문자 체계 선택기 구축하기
일부 언어는 사용자에게 문자 체계 선택권을 제공합니다. 세르비아어는 키릴 문자 또는 라틴 문자로 작성할 수 있습니다. 중국어는 간체 또는 번체 문자로 작성할 수 있습니다. 사용자가 선택할 수 있도록 이러한 옵션을 표시해야 합니다.
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" }
// ]
이 함수는 사용자의 인터페이스 언어로 문자 체계 옵션을 반환합니다. 세르비아어 사용자는 키릴 문자와 라틴 문자 옵션을 볼 수 있습니다. 중국어 사용자는 간체 및 번체 문자 옵션을 볼 수 있습니다. 이름은 사용자가 이해하는 언어로 표시됩니다.
문자 체계 정보가 포함된 전체 로케일 식별자 표시하기
로케일 식별자는 문자 체계를 구분하기 위해 스크립트 코드를 포함할 수 있습니다. 형식은 language-script-region이며, 세르비아의 키릴 문자로 작성된 세르비아어의 경우 sr-Cyrl-RS, 중국의 간체 중국어의 경우 zh-Hans-CN와 같습니다.
이러한 로케일 식별자를 표시할 때 문자 체계 코드를 추출하여 읽을 수 있는 이름으로 변환합니다.
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)"
이 패턴은 언어 이름과 문자 체계 이름을 결합하여 로케일 식별자를 사람이 읽을 수 있게 만듭니다. 사용자는 "sr-Cyrl" 대신 "세르비아어(키릴 문자)"를 볼 수 있습니다.
스크립트 이름으로 글꼴 선택기 만들기
글꼴 선택 인터페이스는 지원하는 스크립트별로 글꼴을 그룹화하는 경우가 많습니다. 사용자가 각 글꼴이 지원하는 스크립트를 이해할 수 있도록 스크립트 이름을 표시해야 합니다.
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"]
// }
// ]
이렇게 하면 지원되는 스크립트가 사람이 읽을 수 있는 형식으로 표시된 글꼴 목록이 생성됩니다. 사용자는 필요한 문자 체계를 기반으로 글꼴을 선택할 수 있습니다.
스크립트별 사용 가능한 입력 방법 표시
운영 체제와 브라우저는 다양한 스크립트에 대한 입력 방법을 제공합니다. 일본어 입력 방법은 라틴 문자를 히라가나, 가타카나 또는 한자로 변환합니다. 중국어 입력 방법은 병음을 간체 또는 번체 중국어 문자로 변환합니다. 스크립트 이름과 함께 사용 가능한 입력 방법을 표시할 수 있습니다.
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: "ヘブライ文字" }
// ]
이렇게 하면 사용자의 언어로 입력 방법 이름이 표시됩니다. 사용자는 인터페이스가 영어일 때 "Hiragana"를 보고 인터페이스가 일본어일 때 "ひらがな"를 봅니다.
스크립트 코드 대문자 표기 이해하기
스크립트 코드는 특정 대소문자 패턴을 따릅니다. 첫 글자는 대문자입니다. 나머지 세 글자는 소문자입니다. Latn가 올바릅니다. LATN, latn, LaTn는 표준이 아닙니다.
of() 메서드는 대소문자에 관계없이 스크립트 코드를 허용합니다.
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"
포매터는 모든 변형을 올바르게 처리합니다. 그러나 표준 대문자 표기 패턴을 사용하면 코드를 더 읽기 쉽게 만들고 ISO 15924 표준과 일관성을 유지할 수 있습니다.
대체 로케일 처리
Intl.DisplayNames 생성자는 로케일 배열을 허용합니다. 첫 번째 로케일을 사용할 수 없는 경우, 포매터는 배열의 다음 로케일로 폴백합니다.
const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "script" });
console.log(names.of("Latn"));
// "Latin"
포매터는 먼저 존재하지 않는 "xx-XX"를 시도한 다음 "en"로 폴백합니다. 이를 통해 요청한 로케일을 사용할 수 없는 경우에도 코드가 작동하도록 보장합니다.
resolvedOptions() 메서드를 사용하여 포매터가 실제로 사용하는 로케일을 확인할 수 있습니다.
const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "script" });
console.log(names.resolvedOptions().locale);
// "en"
이는 폴백 후 포매터가 영어로 해석되었음을 보여줍니다.
다국어 콘텐츠 관리 시스템 구축
여러 문자 체계를 지원하는 콘텐츠 관리 시스템은 각 콘텐츠에 사용 가능한 문자 체계를 표시해야 합니다. 문자 체계 이름을 표시하여 콘텐츠 편집자가 올바른 버전을 선택할 수 있도록 도울 수 있습니다.
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" }
// ]
이 패턴은 콘텐츠 편집자가 어떤 문자 체계 버전이 존재하는지 확인하고 그 사이를 탐색하는 데 도움이 됩니다.
브라우저 지원
스크립트 타입을 지원하는 Intl.DisplayNames API는 모든 최신 브라우저에서 사용할 수 있습니다. Chrome, Firefox, Safari, Edge를 포함한 주요 브라우저에서 2021년 3월부터 지원되었습니다.
API를 사용하기 전에 사용 가능한지 확인할 수 있습니다.
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");
}
이전 브라우저의 경우 폴백을 제공하거나 폴리필을 사용해야 합니다. 간단한 폴백은 문자 체계 코드를 이름에 하드코딩된 매핑을 사용합니다.
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"
이를 통해 Intl.DisplayNames를 지원하지 않는 브라우저에서도 코드가 작동하도록 보장하지만, 자동 로컬라이제이션 기능은 사용할 수 없습니다.