불완전한 로케일에 가능성 높은 하위 태그를 추가하는 방법
JavaScript를 사용하여 부분 로케일 식별자를 가장 가능성 높은 문자 체계 및 지역으로 완성하기
소개
로케일 식별자를 다룰 때 불완전한 정보를 받는 경우가 있습니다. 사용자가 스크립트나 지역을 명시하지 않고 ja와 같은 언어 코드만 지정할 수 있습니다. 이러한 부분 식별자는 유효하지만, 로케일 비교나 형식 지정 규칙 결정과 같은 특정 작업에 필요한 구체성이 부족합니다.
JavaScript는 가장 가능성 높은 누락된 구성 요소를 추가하여 이러한 부분 식별자를 완성하는 방법을 제공합니다. 이 프로세스는 언어 데이터를 사용하여 해당 언어 사용자가 일반적으로 사용하는 문자 체계와 지역을 추론합니다.
이 가이드에서는 가능성 높은 하위 태그가 무엇인지, JavaScript가 이를 어떻게 결정하는지, 그리고 애플리케이션에서 이 기능을 언제 사용해야 하는지 설명합니다.
가능성 높은 하위 태그란
가능성 높은 하위 태그는 특정 언어와 가장 일반적으로 함께 나타나는 문자 체계 및 지역 코드입니다. 이러한 연관성은 유니코드 컨소시엄이 관리하는 실제 언어 사용 데이터에서 비롯됩니다.
예를 들어, 영어는 일반적으로 라틴 문자로 작성되며 미국에서 가장 많이 사용됩니다. 언어 코드 en만 있는 경우, 가능성이 높은 하위 태그는 스크립트의 경우 Latn이고 지역의 경우 US이므로, 완전한 식별자 en-Latn-US를 얻게 됩니다.
가능성은 화자 인구와 역사적 사용 패턴을 기반으로 합니다. 알고리즘은 항상 통계적으로 가장 일반적인 조합을 반환합니다.
가능성 높은 하위 태그를 추가하는 이유
부분 로케일 식별자는 대부분의 형식 지정 작업에서 작동합니다. Intl.DateTimeFormat 및 Intl.NumberFormat API는 en를 허용하며 합리적인 기본값을 적용합니다. 그러나 완전한 식별자가 필요한 상황이 있습니다.
로케일 식별자 비교
두 로케일 식별자가 동일한 언어와 지역을 참조하는지 비교할 때, 부분 식별자는 모호성을 만듭니다. en가 en-US와 같은 의미인가요, 아니면 하나는 지역을 지정하고 다른 하나는 지정하지 않기 때문에 다른가요?
가능성이 높은 하위 태그를 추가하면 이러한 모호성이 제거됩니다. en와 en-US 모두 en-Latn-US로 최대화되어 직접 비교할 수 있습니다.
const locale1 = new Intl.Locale("en");
const locale2 = new Intl.Locale("en-US");
console.log(locale1.baseName === locale2.baseName);
// false - they look different
const maximized1 = locale1.maximize();
const maximized2 = locale2.maximize();
console.log(maximized1.baseName === maximized2.baseName);
// true - both are "en-Latn-US"
정규 형식 저장
데이터베이스나 구성 파일에 로케일 식별자를 저장할 때 완전한 형식을 사용하면 일관성이 보장됩니다. 모든 프랑스어 로케일은 fr-Latn-FR가 되고, 모든 일본어 로케일은 ja-Jpan-JP가 되는 식입니다.
이러한 일관성은 로케일별 검색, 필터링, 그룹화를 더욱 안정적으로 만듭니다.
스크립트별 동작 결정
일부 언어는 여러 스크립트를 사용하며, 스크립트는 텍스트 렌더링, 글꼴 선택, 정렬에 영향을 미칩니다. 중국어는 간체 또는 번체 문자로 작성될 수 있으며, 세르비아어는 키릴 문자 또는 라틴 문자를 사용할 수 있습니다.
가능성이 높은 하위 태그를 추가하면 스크립트가 명시적으로 표시됩니다. 사용자가 스크립트를 지정하지 않고 zh를 제공하는 경우, 이를 최대화하면 zh-Hans-CN가 생성되어 간체 중국어 문자가 예상됨을 나타냅니다.
알고리즘 작동 방식
가능성 있는 하위 태그 추가 알고리즘은 언어 사용 정보 데이터베이스를 사용하여 누락된 구성 요소를 결정합니다. 이 데이터베이스는 유니코드 컨소시엄이 공통 로케일 데이터 저장소의 일부로 유지 관리합니다.
알고리즘은 제공된 정보를 검사하고 빈 부분을 채웁니다:
- 언어만 제공하면 해당 언어에 가장 일반적인 스크립트와 지역을 추가합니다
- 언어와 스크립트를 제공하면 해당 조합에 가장 일반적인 지역을 추가합니다
- 언어와 지역을 제공하면 해당 조합에 가장 일반적인 스크립트를 추가합니다
- 세 가지 구성 요소를 모두 제공하면 변경되지 않고 그대로 유지됩니다
결정은 전 세계 언어 사용에 대한 통계 데이터를 기반으로 합니다.
maximize 메서드 사용하기
maximize() 메서드는 Intl.Locale 객체에서 사용할 수 있습니다. 이 메서드는 기본 이름에 가능성 있는 하위 태그가 추가된 새로운 로케일 객체를 반환합니다.
const locale = new Intl.Locale("ja");
const maximized = locale.maximize();
console.log(locale.baseName);
// "ja"
console.log(maximized.baseName);
// "ja-Jpan-JP"
이 메서드는 원본 로케일 객체를 수정하지 않습니다. 새로운 객체를 생성하여 반환합니다.
다양한 언어의 예제
언어마다 주로 사용되는 지역과 사용하는 문자 체계에 따라 서로 다른 가능성 있는 하위 태그를 가집니다.
유럽 언어
프랑스어는 라틴 문자를 사용하는 프랑스로 최대화됩니다:
const french = new Intl.Locale("fr");
const maximized = french.maximize();
console.log(maximized.baseName);
// "fr-Latn-FR"
독일어는 라틴 문자를 사용하는 독일로 최대화됩니다:
const german = new Intl.Locale("de");
const maximized = german.maximize();
console.log(maximized.baseName);
// "de-Latn-DE"
비라틴 문자를 사용하는 언어
일본어는 일본 문자를 사용하는 일본으로 최대화됩니다:
const japanese = new Intl.Locale("ja");
const maximized = japanese.maximize();
console.log(maximized.baseName);
// "ja-Jpan-JP"
아랍어는 아랍 문자를 사용하는 이집트로 최대화됩니다:
const arabic = new Intl.Locale("ar");
const maximized = arabic.maximize();
console.log(maximized.baseName);
// "ar-Arab-EG"
문자 체계가 없는 중국어는 간체 문자와 중국으로 최대화됩니다:
const chinese = new Intl.Locale("zh");
const maximized = chinese.maximize();
console.log(maximized.baseName);
// "zh-Hans-CN"
지역이 포함된 부분 식별자
언어와 지역을 제공하지만 문자 체계를 제공하지 않으면 알고리즘이 문자 체계를 추가합니다:
const britishEnglish = new Intl.Locale("en-GB");
const maximized = britishEnglish.maximize();
console.log(maximized.baseName);
// "en-Latn-GB"
지역은 지정된 대로 유지됩니다. 누락된 문자 체계만 추가됩니다.
문자 체계가 포함된 부분 식별자
언어와 문자 체계를 제공하지만 지역을 제공하지 않으면 알고리즘이 해당 문자 체계에 가장 일반적인 지역을 추가합니다:
const traditionalChinese = new Intl.Locale("zh-Hant");
const maximized = traditionalChinese.maximize();
console.log(maximized.baseName);
// "zh-Hant-TW"
번체 중국어는 주로 대만에서 사용되므로 TW가 지역으로 추가됩니다.
확장 태그는 보존됩니다
유니코드 확장 태그는 달력 시스템, 숫자 체계, 시간 주기와 같은 형식 지정 기본 설정을 지정합니다. 이러한 태그는 로케일 식별자에서 -u- 뒤에 나타납니다.
maximize() 메서드는 확장 태그를 변경하지 않습니다. 언어, 문자 체계 및 지역 구성 요소에만 영향을 줍니다.
const locale = new Intl.Locale("fr", {
calendar: "gregory",
numberingSystem: "latn",
hourCycle: "h23"
});
console.log(locale.toString());
// "fr-u-ca-gregory-hc-h23-nu-latn"
const maximized = locale.maximize();
console.log(maximized.toString());
// "fr-Latn-FR-u-ca-gregory-hc-h23-nu-latn"
기본 이름은 fr에서 fr-Latn-FR로 변경되지만 확장 태그는 동일하게 유지됩니다.
maximize를 사용해야 하는 경우
일관성 또는 비교 목적으로 완전한 로케일 식별자가 필요한 경우 maximize() 메서드를 사용하세요.
사용자 입력 정규화
사용자는 다양한 형식으로 로케일을 입력할 수 있습니다. 일부는 en를 입력하고, 다른 사용자는 en-US를 입력하며, 또 다른 사용자는 en-Latn-US를 입력합니다. 모든 입력을 최대화하면 일관된 형식이 생성됩니다.
function normalizeLocale(input) {
try {
const locale = new Intl.Locale(input);
const maximized = locale.maximize();
return maximized.baseName;
} catch (error) {
return null;
}
}
console.log(normalizeLocale("en"));
// "en-Latn-US"
console.log(normalizeLocale("en-US"));
// "en-Latn-US"
console.log(normalizeLocale("en-Latn-US"));
// "en-Latn-US"
세 가지 입력 모두 동일한 정규화된 형식을 생성합니다.
로케일 폴백 체인 구축
특정 로케일을 사용할 수 없는 경우 애플리케이션은 보다 일반적인 로케일로 폴백합니다. 최대화는 이러한 체인을 올바르게 구축하는 데 도움이 됩니다.
function buildFallbackChain(localeString) {
const locale = new Intl.Locale(localeString);
const maximized = locale.maximize();
const chain = [maximized.toString()];
if (maximized.script && maximized.region) {
const withoutRegion = new Intl.Locale(
`${maximized.language}-${maximized.script}`
);
chain.push(withoutRegion.toString());
}
if (maximized.region) {
chain.push(maximized.language);
}
chain.push("en");
return chain;
}
console.log(buildFallbackChain("zh-TW"));
// ["zh-Hant-TW", "zh-Hant", "zh", "en"]
이렇게 하면 가장 구체적인 로케일에서 가장 일반적인 로케일로의 적절한 폴백이 생성됩니다.
사용자 기본 설정을 사용 가능한 로케일과 일치시키기
사용 가능한 번역 세트가 있고 사용자 기본 설정에 가장 적합한 항목을 찾아야 하는 경우 양쪽을 최대화하면 정확한 비교가 가능합니다.
function findBestMatch(userPreference, availableLocales) {
const userMaximized = new Intl.Locale(userPreference).maximize();
const matches = availableLocales.map(available => {
const availableMaximized = new Intl.Locale(available).maximize();
let score = 0;
if (userMaximized.language === availableMaximized.language) score += 1;
if (userMaximized.script === availableMaximized.script) score += 1;
if (userMaximized.region === availableMaximized.region) score += 1;
return { locale: available, score };
});
matches.sort((a, b) => b.score - a.score);
return matches[0].locale;
}
const available = ["en-US", "en-GB", "fr-FR", "de-DE"];
console.log(findBestMatch("en", available));
// "en-US"
이 함수는 사용자 기본 설정 en를 en-Latn-US로 확장하고 가장 가까운 일치 항목을 찾습니다.
maximize를 사용하지 않아야 하는 경우
형식 지정 API에 전달하기 전에 로케일을 최대화할 필요는 없습니다. Intl.DateTimeFormat, Intl.NumberFormat 및 기타 형식 지정 생성자는 부분 식별자를 올바르게 처리합니다.
const date = new Date("2025-03-15");
const partial = new Intl.DateTimeFormat("fr").format(date);
const maximized = new Intl.DateTimeFormat("fr-Latn-FR").format(date);
console.log(partial);
// "15/03/2025"
console.log(maximized);
// "15/03/2025"
둘 다 동일한 출력을 생성합니다. 이 경우 추가 특정성은 형식 지정 동작을 변경하지 않습니다.
기본 제공 포매터에 로케일을 전달할 때가 아니라 자체 로직에 명시적인 정보가 필요한 경우 maximize()를 사용하세요.
브라우저 지원
maximize() 메서드는 모든 최신 브라우저에서 사용할 수 있습니다. Chrome, Firefox, Safari 및 Edge는 모두 Intl.Locale API의 일부로 이를 지원합니다.
Node.js는 버전 12부터 maximize()를 지원하며, 버전 14 이상에서 완전히 지원됩니다.
요약
가능성 높은 하위 태그는 특정 언어에 대해 가장 일반적인 문자 체계와 지역을 추가하여 부분 로케일 식별자를 완성합니다. Intl.Locale.maximize() 메서드는 이러한 확장을 수행하기 위해 유니코드 Add Likely Subtags 알고리즘을 구현합니다.
주요 사항:
- 가능성 높은 하위 태그는 실제 언어 사용 데이터를 기반으로 합니다
maximize()메서드는 누락된 문자 체계 및 지역 코드를 추가합니다- 달력 및 숫자 체계에 대한 확장 태그는 변경되지 않습니다
- 사용자 입력을 정규화하고 로케일을 비교할 때 최대화를 사용하십시오
- 포맷팅 API는 최대화된 로케일을 필요로 하지 않습니다
maximize() 메서드는 애플리케이션 로직에서 명시적인 문자 체계 및 지역 정보가 필요한 경우 완전한 로케일 식별자를 사용할 수 있는 표준화된 방법을 제공합니다.