영어, 스페인어, 일본어와 같은 언어 이름을 어떻게 표시하나요?
언어 선택기 및 국제화된 인터페이스에서 원어 스크립트로 언어 이름을 표시하려면 Intl.DisplayNames를 사용하세요.
소개
언어 선택기를 구축하거나 사용 가능한 언어 목록을 표시할 때, 사용자가 인식할 수 있는 방식으로 각 언어 이름을 표시해야 합니다. 프랑스어 사용자는 "Français"를 찾고, 스페인어 사용자는 "Español"을, 일본어 사용자는 "日本語"를 찾습니다. 사용자는 자신의 언어를 해당 언어의 원래 문자와 철자로 식별합니다.
이러한 번역을 하드코딩하는 것은 확장성이 없습니다. 모든 언어 이름을 다른 모든 언어로 번역하여 유지 관리해야 합니다. Intl.DisplayNames API는 언어, 국가, 스크립트 및 통화에 대한 표준화되고 로케일을 인식하는 이름을 제공함으로써 이 문제를 해결합니다.
언어 이름 하드코딩의 문제점
객체에 언어 이름을 하드코딩하여 언어 선택기를 만들 수 있습니다.
const languageNames = {
en: "English",
es: "Spanish",
fr: "French",
de: "German",
ja: "Japanese"
};
console.log(languageNames.en);
// "English"
이 접근 방식에는 세 가지 문제가 있습니다. 첫째, 이러한 이름은 영어 사용자에게만 작동합니다. 둘째, 사용자는 영어로 표시될 때 자신의 언어를 인식할 수 없습니다. 일본어 사용자가 자신의 언어를 찾을 때는 "Japanese"라는 단어가 아닌 일본어 문자를 찾습니다. 셋째, 모든 언어를 다른 모든 언어로 번역하는 작업을 수동으로 유지 관리해야 합니다.
const languageNames = {
en: {
en: "English",
es: "Spanish",
fr: "French",
de: "German",
ja: "Japanese"
},
es: {
en: "Inglés",
es: "Español",
fr: "Francés",
de: "Alemán",
ja: "Japonés"
}
// ... 더 많은 언어
};
이는 빠르게 유지 관리가 불가능해집니다. 더 나은 해결책이 필요합니다.
Intl.DisplayNames를 사용하여 언어 이름 가져오기
Intl.DisplayNames 생성자는 언어 코드를 사람이 읽을 수 있는 이름으로 변환하는 포맷터를 생성합니다. 로케일과 표시하려는 이름의 유형을 지정합니다.
const names = new Intl.DisplayNames(["en"], { type: "language" });
console.log(names.of("en"));
// "English"
첫 번째 인수는 로케일 식별자 배열입니다. 두 번째 인수는 type: "language"로 포맷터에게 언어 이름을 원한다고 알려주는 옵션 객체입니다. of() 메서드는 언어 코드를 받아 해당 이름을 반환합니다.
로케일을 변경하여 어떤 언어로든 이름을 얻을 수 있습니다.
const enNames = new Intl.DisplayNames(["en"], { type: "language" });
const esNames = new Intl.DisplayNames(["es"], { type: "language" });
const frNames = new Intl.DisplayNames(["fr"], { type: "language" });
console.log(enNames.of("es"));
// "Spanish"
console.log(esNames.of("es"));
// "español"
console.log(frNames.of("es"));
// "espagnol"
각 포맷터는 표시 로케일에 맞는 언어 이름을 반환합니다. 이는 언어 이름 번역을 유지 관리하는 모든 복잡성을 처리합니다.
언어 이름을 원어 형태로 표시하기
언어 선택기에서 가장 좋은 방법은 각 언어를 해당 언어의 고유 문자로 표시하는 것입니다. 사용자는 익숙한 문자로 작성된 언어를 더 빠르게 인식합니다.
const names = new Intl.DisplayNames(["ja"], { type: "language" });
console.log(names.of("ja"));
// "日本語"
각 언어의 원어 이름을 얻으려면 대상 언어를 표시 로케일로 사용하여 포맷터를 생성하세요.
function getNativeName(languageCode) {
const names = new Intl.DisplayNames([languageCode], { type: "language" });
return names.of(languageCode);
}
console.log(getNativeName("en"));
// "English"
console.log(getNativeName("es"));
// "español"
console.log(getNativeName("fr"));
// "français"
console.log(getNativeName("de"));
// "Deutsch"
console.log(getNativeName("ja"));
// "日本語"
console.log(getNativeName("ar"));
// "العربية"
console.log(getNativeName("zh"));
// "中文"
이 패턴은 모든 언어 코드에 적용됩니다. 포맷터는 원어민이 사용하는 문자와 형태로 이름을 반환합니다.
언어 코드 형식 이해하기
of() 메서드는 여러 형식의 언어 코드를 허용합니다. "en"과 같은 기본 언어 코드나 "en-US"와 같은 전체 로케일 식별자를 사용할 수 있습니다.
const names = new Intl.DisplayNames(["en"], { type: "language" });
console.log(names.of("en"));
// "English"
console.log(names.of("en-US"));
// "American English"
console.log(names.of("en-GB"));
// "British English"
console.log(names.of("zh"));
// "Chinese"
console.log(names.of("zh-Hans"));
// "Simplified Chinese"
console.log(names.of("zh-Hant"));
// "Traditional Chinese"
포맷터는 짧은 코드와 지역 또는 스크립트 서브태그가 있는 확장 식별자를 모두 인식합니다. 이를 통해 언어 변형을 구분할 수 있습니다.
언어 이름 표시 방식 제어하기
languageDisplay 옵션은 반환된 이름의 세부 정보 수준을 제어합니다. 두 가지 값을 허용합니다.
"standard" 값은 방언 정보를 포함한 전체 이름을 반환합니다. 이것이 기본값입니다.
const names = new Intl.DisplayNames(["en"], {
type: "language",
languageDisplay: "standard"
});
console.log(names.of("en-US"));
// "American English"
console.log(names.of("en-GB"));
// "British English"
console.log(names.of("pt-BR"));
// "Brazilian Portuguese"
console.log(names.of("pt-PT"));
// "European Portuguese"
"dialect" 값도 방언 정보가 포함된 전체 이름을 반환합니다. 대부분의 경우 "standard"와 동일한 출력을 생성합니다.
const names = new Intl.DisplayNames(["en"], {
type: "language",
languageDisplay: "dialect"
});
console.log(names.of("en-US"));
// "American English"
console.log(names.of("pt-BR"));
// "Brazilian Portuguese"
언어 선택기의 경우, 표준 형식은 여러 방언이 제공될 때 사용자가 올바른 변형을 선택하는 데 도움이 됩니다.
사용자 인터페이스를 위한 언어 이름 현지화하기
설정 페이지나 언어 선택기를 구축할 때, 사용자의 현재 인터페이스 언어로 언어 이름을 표시해야 합니다. 사용자의 로케일을 사용하여 포맷터를 생성하세요.
function getLocalizedLanguageName(languageCode, userLocale) {
const names = new Intl.DisplayNames([userLocale], { type: "language" });
return names.of(languageCode);
}
// 사용자 인터페이스가 영어인 경우
console.log(getLocalizedLanguageName("ja", "en"));
// "Japanese"
// 사용자 인터페이스가 프랑스어인 경우
console.log(getLocalizedLanguageName("ja", "fr"));
// "japonais"
// 사용자 인터페이스가 스페인어인 경우
console.log(getLocalizedLanguageName("ja", "es"));
// "japonés"
이 접근 방식은 사용자가 이해하는 언어로 설명적인 이름을 보여줍니다. 이를 원어 이름과 결합하여 "日本語 (Japanese)"와 같은 하이브리드 레이블을 만들면 원어민과 그 외 사용자 모두에게 효과적입니다.
원어 이름을 사용한 언어 선택기 구축하기
일반적인 사용 사례는 사용자가 선호하는 언어를 선택할 수 있는 드롭다운이나 목록을 구축하는 것입니다. 각 언어를 원어 형태로 표시하여 사용자가 자신의 옵션을 빠르게 찾을 수 있도록 합니다.
const supportedLanguages = ["en", "es", "fr", "de", "ja", "ar", "zh"];
function createLanguageOptions() {
return supportedLanguages.map((code) => {
const names = new Intl.DisplayNames([code], { type: "language" });
const nativeName = names.of(code);
return { code, name: nativeName };
});
}
const options = createLanguageOptions();
console.log(options);
이는 원어 이름이 포함된 언어 옵션 배열을 생성합니다.
[
{ code: "en", name: "English" },
{ code: "es", name: "español" },
{ code: "fr", name: "français" },
{ code: "de", name: "Deutsch" },
{ code: "ja", name: "日本語" },
{ code: "ar", name: "العربية" },
{ code: "zh", name: "中文" }
]
이러한 옵션을 HTML로 렌더링하여 언어 선택기를 만들 수 있습니다.
function renderLanguageSelector() {
const options = createLanguageOptions();
const select = document.createElement("select");
select.id = "language-selector";
options.forEach((option) => {
const optionElement = document.createElement("option");
optionElement.value = option.code;
optionElement.textContent = option.name;
select.appendChild(optionElement);
});
return select;
}
const selector = renderLanguageSelector();
document.body.appendChild(selector);
이렇게 하면 각 언어가 원어 스크립트로 표시되는 드롭다운이 생성되어 사용자가 자신의 언어를 쉽게 식별할 수 있습니다.
하이브리드 언어 레이블 생성하기
일부 인터페이스는 원어 이름과 사용자 언어로 된 번역을 함께 표시합니다. 이는 모든 문자를 인식하지 못하는 사용자를 돕고 인터페이스를 더 접근하기 쉽게 만듭니다.
function createHybridLabel(languageCode, userLocale) {
const nativeNames = new Intl.DisplayNames([languageCode], {
type: "language"
});
const localizedNames = new Intl.DisplayNames([userLocale], {
type: "language"
});
const nativeName = nativeNames.of(languageCode);
const localizedName = localizedNames.of(languageCode);
if (nativeName === localizedName) {
return nativeName;
}
return `${nativeName} (${localizedName})`;
}
// 사용자 인터페이스가 영어인 경우
console.log(createHybridLabel("ja", "en"));
// "日本語 (Japanese)"
console.log(createHybridLabel("ar", "en"));
// "العربية (Arabic)"
console.log(createHybridLabel("en", "en"));
// "English"
// 사용자 인터페이스가 스페인어인 경우
console.log(createHybridLabel("ja", "es"));
// "日本語 (japonés)"
이 패턴은 원어 이름의 인식 이점과 현지화된 번역의 명확성을 결합합니다.
대체 로케일 처리하기
Intl.DisplayNames 생성자는 로케일 배열을 받습니다. 첫 번째 로케일을 사용할 수 없는 경우, 포맷터는 배열의 다음 로케일로 대체합니다.
const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "language" });
console.log(names.of("fr"));
// "French"
포맷터는 먼저 존재하지 않는 "xx-XX"를 시도한 다음 "en"으로 대체합니다. 이는 요청된 로케일을 사용할 수 없는 경우에도 코드가 작동하도록 보장합니다.
resolvedOptions() 메서드를 사용하여 포맷터가 실제로 어떤 로케일을 사용하는지 확인할 수 있습니다.
const names = new Intl.DisplayNames(["xx-XX", "en"], { type: "language" });
console.log(names.resolvedOptions().locale);
// "en"
이는 포맷터가 대체 후 영어로 해결되었음을 보여줍니다.
다양한 로케일이 언어 이름을 포맷하는 방법
각 로케일은 언어 이름에 대한 고유한 규칙을 가지고 있습니다. 포맷터는 이러한 규칙을 자동으로 적용합니다.
const supportedLanguages = ["en", "es", "fr", "de", "ja"];
function showLanguageNamesInLocale(locale) {
const names = new Intl.DisplayNames([locale], { type: "language" });
return supportedLanguages.map((code) => ({
code,
name: names.of(code)
}));
}
console.log(showLanguageNamesInLocale("en"));
// [
// { code: "en", name: "English" },
// { code: "es", name: "Spanish" },
// { code: "fr", name: "French" },
// { code: "de", name: "German" },
// { code: "ja", name: "Japanese" }
// ]
console.log(showLanguageNamesInLocale("es"));
// [
// { code: "en", name: "inglés" },
// { code: "es", name: "español" },
// { code: "fr", name: "francés" },
// { code: "de", name: "alemán" },
// { code: "ja", name: "japonés" }
// ]
console.log(showLanguageNamesInLocale("ja"));
// [
// { code: "en", name: "英語" },
// { code: "es", name: "スペイン語" },
// { code: "fr", name: "フランス語" },
// { code: "de", name: "ドイツ語" },
// { code: "ja", name: "日本語" }
// ]
포맷터는 각 언어에 대한 대소문자, 문자 체계 및 언어적 규칙을 자동으로 처리합니다.
브라우저 지원
Intl.DisplayNames API는 모든 최신 브라우저에서 사용할 수 있습니다. 2021년 3월부터 Chrome, Firefox, Safari, Edge 등 주요 브라우저에서 지원되고 있습니다.
사용하기 전에 API의 가용성을 확인할 수 있습니다.
if (typeof Intl.DisplayNames !== "undefined") {
const names = new Intl.DisplayNames(["en"], { type: "language" });
console.log(names.of("fr"));
} else {
console.log("Intl.DisplayNames is not supported");
}
구형 브라우저의 경우 대체 방안을 제공하거나 폴리필을 사용해야 합니다. 간단한 대체 방안으로는 언어 코드와 이름의 하드코딩된 매핑을 사용합니다.
function getLanguageName(code, locale) {
if (typeof Intl.DisplayNames !== "undefined") {
const names = new Intl.DisplayNames([locale], { type: "language" });
return names.of(code);
}
// 구형 브라우저를 위한 대체 방안
const fallbackNames = {
en: "English",
es: "español",
fr: "français",
de: "Deutsch",
ja: "日本語"
};
return fallbackNames[code] || code;
}
console.log(getLanguageName("es", "en"));
// "español" (또는 지역화를 위해 대체 방안을 조정하면 "Spanish")
이렇게 하면 Intl.DisplayNames를 지원하지 않는 브라우저에서도 코드가 작동하지만, 자동 지역화 기능은 사용할 수 없게 됩니다.