로케일이 사용하는 달력 또는 숫자 체계를 확인하는 방법

JavaScript로 모든 로케일의 달력 시스템 및 숫자 형식을 감지하고 검증하세요

소개

태국의 사용자가 웹 앱에서 날짜를 볼 때, 서양 국가에서 사용하는 그레고리력이 아닌 불교력으로 표시되기를 기대합니다. 마찬가지로 아랍어 사용자는 123 대신 ١٢٣으로 렌더링된 숫자를 보기를 기대합니다. 문화권마다 다른 달력 시스템과 숫자 체계를 사용하며, JavaScript는 특정 로케일에 적용되는 시스템을 감지하는 도구를 제공합니다.

Intl.Locale API는 로케일이 사용하는 달력 및 숫자 체계를 나타내는 속성과 메서드를 포함합니다. 이 정보는 다양한 문화권이 선호하는 체계에 대한 가정을 하드코딩하지 않고도 날짜와 숫자를 올바르게 형식화하는 데 도움이 됩니다.

이 가이드에서는 로케일의 달력 및 숫자 체계를 확인하는 방법, 다양한 시스템의 의미를 이해하는 방법, 그리고 이 정보를 사용하여 콘텐츠를 적절하게 형식화하는 방법을 설명합니다.

달력 시스템 이해하기

달력 시스템은 시간을 연도, 월, 일로 구성하는 방식입니다. 그레고리력이 널리 사용되지만, 많은 문화권에서는 종교적, 역사적 또는 문화적 목적으로 다른 달력 시스템을 사용합니다.

가장 일반적인 달력 시스템은 다음과 같습니다:

  • gregory: 대부분의 서구 국가에서 사용되는 그레고리력
  • buddhist: 태국, 캄보디아, 미얀마에서 사용되는 불교력
  • islamic: 이슬람 국가에서 종교적 목적으로 사용되는 이슬람 태음력
  • hebrew: 이스라엘과 유대교 종교 의식에서 사용되는 히브리력
  • japanese: 연호를 사용하는 일본력
  • chinese: 전통 명절에 사용되는 중국 태음태양력
  • persian: 이란과 아프가니스탄에서 사용되는 페르시아 태양력
  • indian: 인도 국가력
  • coptic: 이집트의 콥트 기독교인이 사용하는 콥트력

지역마다 기본으로 사용하는 달력이 다르며, 일부 지역에서는 여러 달력 체계를 일반적으로 사용합니다.

숫자 체계 이해하기

숫자 체계는 숫자를 나타내는 데 사용되는 기호 집합입니다. 서양 국가에서는 라틴 숫자(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)를 사용하지만, 다른 문화권에서는 동일한 숫자 값을 나타내기 위해 다른 기호를 사용합니다.

일반적인 숫자 체계는 다음과 같습니다:

  • latn: 라틴 숫자: 0 1 2 3 4 5 6 7 8 9
  • arab: 아랍-인도 숫자: ٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩
  • arabext: 동부 아랍-인도 숫자: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹
  • deva: 데바나가리 숫자: ० १ २ ३ ४ ⑤ ⑥ ⑦ ⑧ ⑨
  • beng: 벵골 숫자: ০ ১ ২ ৩ ৪ ৫ ৬ ৭ ৮ ৯
  • thai: 태국 숫자: ๐ ๑ ๒ ๓ ๔ ๕ ๖ ๗ ๘ ๙
  • hanidec: 중국 십진수
  • fullwide: 동아시아 타이포그래피에서 사용되는 전각 숫자

모든 숫자 체계는 동일한 숫자 값을 나타내지만 언어의 문자 체계에 따라 다른 시각적 기호를 사용합니다.

로케일의 기본 달력 확인하기

getCalendars() 메서드는 로케일에서 일반적으로 사용되는 달력 시스템의 배열을 선호도 순으로 정렬하여 반환합니다. 첫 번째 요소가 기본 달력입니다.

const locale = new Intl.Locale("th-TH");
const calendars = locale.getCalendars();
console.log(calendars);
// ["buddhist", "gregory"]

태국 로케일은 기본적으로 불교 달력을 사용하지만 그레고리력도 일반적으로 사용합니다. 이는 태국 사용자를 위해 날짜를 형식화할 때 불교 달력이 선호된다는 것을 알려줍니다.

로케일마다 다른 달력 기본 설정을 반환합니다:

const usLocale = new Intl.Locale("en-US");
console.log(usLocale.getCalendars());
// ["gregory"]

const saLocale = new Intl.Locale("ar-SA");
console.log(saLocale.getCalendars());
// ["gregory", "islamic", "islamic-civil"]

const jpLocale = new Intl.Locale("ja-JP");
console.log(jpLocale.getCalendars());
// ["gregory", "japanese"]

미국 영어는 그레고리력만 사용합니다. 사우디아라비아 아랍어는 일반적으로 그레고리력과 이슬람력을 모두 사용합니다. 일본어 로케일은 그레고리력과 일본 연호를 모두 사용합니다.

배열에는 해당 로케일에서 일반적으로 사용되는 모든 달력이 포함되어 있어, 적절한 경우 여러 달력 옵션을 제공할 수 있습니다.

로케일의 기본 숫자 체계 확인하기

getNumberingSystems() 메서드는 로케일에서 일반적으로 사용되는 숫자 체계의 배열을 반환합니다. 첫 번째 요소가 기본 숫자 체계입니다.

const locale = new Intl.Locale("ar-EG");
const numberingSystems = locale.getNumberingSystems();
console.log(numberingSystems);
// ["arab"]

이집트 아랍어는 기본적으로 아랍-인도 숫자를 사용합니다. 이집트 아랍어 사용자를 위해 숫자를 형식화할 때는 사용자가 별도로 지정하지 않는 한 아랍-인도 숫자 체계를 사용하세요.

로케일마다 다른 기본 숫자 체계를 사용합니다:

const usLocale = new Intl.Locale("en-US");
console.log(usLocale.getNumberingSystems());
// ["latn"]

const inLocale = new Intl.Locale("hi-IN");
console.log(inLocale.getNumberingSystems());
// ["latn"]

const thLocale = new Intl.Locale("th-TH");
console.log(thLocale.getNumberingSystems());
// ["latn"]

미국 영어는 라틴 숫자를 사용합니다. 인도의 힌디어도 데바나가리 숫자가 존재하지만 현대적인 맥락에서는 기본적으로 라틴 숫자를 사용합니다. 태국어는 대부분의 현대적인 맥락에서 기본적으로 라틴 숫자를 사용합니다.

많은 현대 로케일은 전통적인 숫자 체계가 존재하더라도 현재 사용 패턴을 반영하여 기본적으로 라틴 숫자를 사용합니다.

로케일에서 활성 달력 읽기

calendar 속성은 로케일에 명시적으로 설정된 달력 시스템을 반환합니다. 달력이 지정되지 않은 경우 undefined를 반환합니다.

const locale = new Intl.Locale("en-US");
console.log(locale.calendar);
// undefined

달력 확장이 없는 기본 로케일은 undefined를 반환합니다. 로케일은 날짜 형식을 지정할 때 기본 달력을 사용합니다.

유니코드 확장을 사용하여 명시적인 달력 기본 설정으로 로케일을 생성할 수 있습니다:

const locale = new Intl.Locale("en-US-u-ca-buddhist");
console.log(locale.calendar);
// "buddhist"

-u-ca-buddhist 확장은 불교 달력을 지정합니다. calendar 속성은 "buddhist"를 반환합니다.

로케일을 생성할 때 달력을 설정할 수도 있습니다:

const locale = new Intl.Locale("en-US", { calendar: "islamic" });
console.log(locale.calendar);
// "islamic"

옵션 객체는 로케일 문자열에 지정된 달력보다 우선합니다.

로케일에서 활성 숫자 체계 읽기

numberingSystem 속성은 로케일에 명시적으로 설정된 숫자 체계를 반환합니다. 숫자 체계가 지정되지 않은 경우 undefined를 반환합니다.

const locale = new Intl.Locale("en-US");
console.log(locale.numberingSystem);
// undefined

숫자 체계 확장이 없는 기본 로케일은 undefined를 반환합니다. 로케일은 숫자 형식을 지정할 때 기본 숫자 체계를 사용합니다.

명시적인 숫자 체계 기본 설정으로 로케일을 생성할 수 있습니다.

const locale = new Intl.Locale("en-US-u-nu-arab");
console.log(locale.numberingSystem);
// "arab"

-u-nu-arab 확장은 아랍-인도 숫자를 지정합니다. numberingSystem 속성은 "arab"를 반환합니다.

로케일을 생성할 때 숫자 체계를 설정할 수도 있습니다.

const locale = new Intl.Locale("ar-SA", { numberingSystem: "latn" });
console.log(locale.numberingSystem);
// "latn"

이는 기본 아랍-인도 숫자 대신 라틴 숫자를 사용하는 아랍어 로케일을 생성합니다.

로케일에 명시적 달력이 있는지 감지

로케일이 기본값을 사용하는 것이 아니라 명시적으로 설정된 달력을 가지고 있는지 확인하려면 calendar 속성이 정의되어 있는지 확인하세요.

function hasExplicitCalendar(localeString) {
  const locale = new Intl.Locale(localeString);
  return locale.calendar !== undefined;
}

console.log(hasExplicitCalendar("en-US"));
// false

console.log(hasExplicitCalendar("en-US-u-ca-buddhist"));
// true

이 구분은 사용자가 명시적으로 달력 기본 설정을 선택했는지 또는 로케일의 기본값을 사용해야 하는지 결정해야 할 때 중요합니다.

로케일에 명시적 숫자 체계가 있는지 감지

마찬가지로 numberingSystem 속성이 정의되어 있는지 확인하여 명시적인 숫자 체계 기본 설정을 감지하세요.

function hasExplicitNumberingSystem(localeString) {
  const locale = new Intl.Locale(localeString);
  return locale.numberingSystem !== undefined;
}

console.log(hasExplicitNumberingSystem("ar-EG"));
// false

console.log(hasExplicitNumberingSystem("ar-EG-u-nu-latn"));
// true

첫 번째 로케일은 이집트 아랍어의 기본 숫자 체계를 사용합니다. 두 번째 로케일은 명시적으로 라틴 숫자를 요청합니다.

달력 정보를 사용하여 날짜 형식화

로케일이 사용하는 달력을 알게 되면 Intl.DateTimeFormat로 날짜를 형식화할 때 이를 적용하세요:

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

const gregorianLocale = new Intl.Locale("en-US");
const gregorianFormatter = new Intl.DateTimeFormat(gregorianLocale, {
  year: "numeric",
  month: "long",
  day: "numeric"
});
console.log(gregorianFormatter.format(date));
// "March 15, 2025"

const buddhistLocale = new Intl.Locale("th-TH");
const buddhistFormatter = new Intl.DateTimeFormat(buddhistLocale, {
  year: "numeric",
  month: "long",
  day: "numeric"
});
console.log(buddhistFormatter.format(date));
// "15 มีนาคม 2568"

태국 불교 달력은 동일한 날짜를 그레고리력보다 543년 앞선 2568년으로 표시합니다.

달력을 명시적으로 재정의할 수도 있습니다.

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

const locale = new Intl.Locale("en-US", { calendar: "hebrew" });
const formatter = new Intl.DateTimeFormat(locale, {
  year: "numeric",
  month: "long",
  day: "numeric"
});
console.log(formatter.format(date));
// "15 Adar II 5785"

이는 히브리 달력으로 날짜를 형식화하여 해당하는 히브리 연도와 월을 표시합니다.

숫자 체계 정보를 사용하여 숫자 형식 지정

Intl.NumberFormat로 숫자를 형식화할 때 숫자 체계 정보를 적용하세요:

const number = 123456;

const latinLocale = new Intl.Locale("ar-EG", { numberingSystem: "latn" });
const latinFormatter = new Intl.NumberFormat(latinLocale);
console.log(latinFormatter.format(number));
// "123,456"

const arabicLocale = new Intl.Locale("ar-EG", { numberingSystem: "arab" });
const arabicFormatter = new Intl.NumberFormat(arabicLocale);
console.log(arabicFormatter.format(number));
// "١٢٣٬٤٥٦"

동일한 숫자가 숫자 체계에 따라 다른 숫자 기호로 렌더링됩니다.

달력 선택기 구축

달력 정보를 사용하여 사용자가 선호하는 달력을 선택할 수 있는 사용자 인터페이스를 구축합니다:

function getCalendarOptions(localeString) {
  const locale = new Intl.Locale(localeString);
  const calendars = locale.getCalendars();

  return calendars.map(calendar => ({
    value: calendar,
    label: calendar.charAt(0).toUpperCase() + calendar.slice(1)
  }));
}

const options = getCalendarOptions("ar-SA");
console.log(options);
// [
//   { value: "gregory", label: "Gregory" },
//   { value: "islamic", label: "Islamic" },
//   { value: "islamic-civil", label: "Islamic-civil" }
// ]

이는 여러 달력을 일반적으로 사용하는 사우디아라비아 아랍어 사용자에게 적합한 달력 옵션 목록을 생성합니다.

숫자 체계 선택기 구축

숫자 체계 기본 설정을 위한 사용자 인터페이스를 생성합니다:

function getNumberingSystemOptions(localeString) {
  const locale = new Intl.Locale(localeString);
  const systems = locale.getNumberingSystems();

  const labels = {
    latn: "Western (0-9)",
    arab: "Arabic-Indic (٠-٩)",
    arabext: "Eastern Arabic (۰-۹)",
    deva: "Devanagari (०-९)",
    beng: "Bengali (০-৯)"
  };

  return systems.map(system => ({
    value: system,
    label: labels[system] || system
  }));
}

const options = getNumberingSystemOptions("ar-EG");
console.log(options);
// [{ value: "arab", label: "Arabic-Indic (٠-٩)" }]

이는 숫자 체계 옵션에 대한 명확한 레이블을 제공하여 사용자에게 각 선택 항목이 어떻게 표시되는지 보여줍니다.

달력 호환성 검증

로케일에 달력을 적용하기 전에 해당 로케일이 해당 달력을 지원하는지 확인합니다:

function supportsCalendar(localeString, calendar) {
  const locale = new Intl.Locale(localeString);
  const supportedCalendars = locale.getCalendars();
  return supportedCalendars.includes(calendar);
}

console.log(supportsCalendar("th-TH", "buddhist"));
// true

console.log(supportsCalendar("en-US", "buddhist"));
// false

태국 로케일은 불교 달력을 지원하지만 미국 영어 로케일은 일반적으로 사용하지 않습니다.

숫자 체계 호환성 검증

로케일이 특정 숫자 체계를 지원하는지 확인합니다:

function supportsNumberingSystem(localeString, numberingSystem) {
  const locale = new Intl.Locale(localeString);
  const supportedSystems = locale.getNumberingSystems();
  return supportedSystems.includes(numberingSystem);
}

console.log(supportsNumberingSystem("ar-EG", "arab"));
// true

console.log(supportsNumberingSystem("en-US", "arab"));
// false

이집트 아랍어는 아랍-인도 숫자를 지원하지만 미국 영어는 사용하지 않습니다.

형식 지정을 위한 유효 달력 결정

날짜를 형식 지정할 때 실제로 사용될 달력을 결정합니다:

function getEffectiveCalendar(localeString) {
  const locale = new Intl.Locale(localeString);

  if (locale.calendar) {
    return locale.calendar;
  }

  const defaultCalendars = locale.getCalendars();
  return defaultCalendars[0];
}

console.log(getEffectiveCalendar("th-TH"));
// "buddhist"

console.log(getEffectiveCalendar("en-US-u-ca-islamic"));
// "islamic"

이 함수는 명시적으로 설정된 달력이 있으면 해당 달력을 반환하고, 그렇지 않으면 로케일의 기본 달력을 반환합니다.

형식 지정을 위한 유효 숫자 체계 결정

숫자 형식 지정 시 사용할 숫자 체계를 결정합니다:

function getEffectiveNumberingSystem(localeString) {
  const locale = new Intl.Locale(localeString);

  if (locale.numberingSystem) {
    return locale.numberingSystem;
  }

  const defaultSystems = locale.getNumberingSystems();
  return defaultSystems[0];
}

console.log(getEffectiveNumberingSystem("ar-EG"));
// "arab"

console.log(getEffectiveNumberingSystem("ar-EG-u-nu-latn"));
// "latn"

명시적으로 설정된 숫자 체계가 있으면 해당 체계를 반환하고, 없으면 로케일의 기본값을 반환합니다.

사용자 달력 기본 설정 저장

사용자가 달력 기본 설정을 선택하면 확장자가 포함된 로케일 문자열로 저장합니다:

function setUserCalendarPreference(baseLocale, calendar) {
  const locale = new Intl.Locale(baseLocale, { calendar });
  return locale.toString();
}

const preference = setUserCalendarPreference("en-US", "buddhist");
console.log(preference);
// "en-US-u-ca-buddhist"

달력 기본 설정을 보존하는 완전한 로케일 문자열이 생성됩니다. 이 문자열을 사용자 설정이나 쿠키에 저장합니다.

사용자 숫자 체계 기본 설정 저장

숫자 체계 기본 설정도 동일한 방식으로 저장합니다:

function setUserNumberingPreference(baseLocale, numberingSystem) {
  const locale = new Intl.Locale(baseLocale, { numberingSystem });
  return locale.toString();
}

const preference = setUserNumberingPreference("ar-SA", "latn");
console.log(preference);
// "ar-SA-u-nu-latn"

로케일 문자열에 숫자 체계 기본 설정이 포함되며 형식 지정 API와 직접 사용할 수 있습니다.

여러 기본 설정 동시 처리

사용자는 달력과 숫자 체계 기본 설정을 모두 가질 수 있습니다:

function createLocaleWithPreferences(baseLocale, options) {
  const locale = new Intl.Locale(baseLocale, {
    calendar: options.calendar,
    numberingSystem: options.numberingSystem
  });
  return locale.toString();
}

const preference = createLocaleWithPreferences("ar-SA", {
  calendar: "islamic",
  numberingSystem: "latn"
});
console.log(preference);
// "ar-SA-u-ca-islamic-nu-latn"

여러 형식 지정 기본 설정을 단일 로케일 문자열로 결합합니다.

확인된 형식 지정 옵션 확인

포매터를 생성한 후 사용 중인 달력과 숫자 체계를 확인합니다:

const locale = new Intl.Locale("th-TH");
const formatter = new Intl.DateTimeFormat(locale, {
  year: "numeric",
  month: "long",
  day: "numeric"
});

const options = formatter.resolvedOptions();
console.log(options.calendar);
// "buddhist"
console.log(options.numberingSystem);
// "latn"

resolvedOptions() 메서드는 기본값과 사용자 기본 설정을 해석한 후 포매터가 실제로 사용하는 달력 및 숫자 체계를 보여줍니다.

브라우저 지원

Intl.Locale API는 모든 최신 브라우저에서 지원됩니다. getCalendars()getNumberingSystems() 메서드는 최신 브라우저 버전이 필요합니다. Chrome 99, Firefox 99, Safari 15.4, Edge 99에서 이러한 메서드를 지원합니다. Node.js는 버전 18부터 이를 지원합니다.

calendarnumberingSystem 속성은 더 광범위한 지원을 제공하며, Chrome 74, Firefox 75, Safari 14, Node.js 12에서 Intl.Locale가 도입된 이후부터 사용할 수 있습니다.

사용하기 전에 메서드 지원 여부를 확인합니다:

const locale = new Intl.Locale("th-TH");

if (typeof locale.getCalendars === "function") {
  const calendars = locale.getCalendars();
  console.log(calendars);
}

이를 통해 Intl.Locale를 지원하지만 최신 메서드가 없는 환경에서도 코드가 작동하도록 보장합니다.

요약

JavaScript는 Intl.Locale API를 통해 로케일이 사용하는 달력 및 숫자 체계를 감지하는 도구를 제공합니다. 이러한 도구는 가정을 하드코딩하지 않고도 다양한 문화권에 맞게 날짜와 숫자를 올바르게 형식화하는 데 도움이 됩니다.

주요 개념:

  • getCalendars()를 사용하여 로케일에서 일반적으로 사용되는 달력 배열을 가져옵니다
  • getNumberingSystems()를 사용하여 로케일에서 일반적으로 사용되는 숫자 체계 배열을 가져옵니다
  • calendar 속성은 명시적으로 설정된 달력 또는 undefined를 반환합니다
  • numberingSystem 속성은 명시적으로 설정된 숫자 체계 또는 undefined를 반환합니다
  • 로케일마다 기본 달력 및 숫자 체계가 다릅니다
  • 포매터를 생성할 때 달력 및 숫자 체계 정보를 적용합니다
  • 사용자 기본 설정을 유니코드 확장이 포함된 로케일 문자열로 저장합니다
  • 특정 달력 및 숫자 체계를 적용하기 전에 로케일이 이를 지원하는지 검증합니다

로케일 선택기를 구축하거나, 사용자 기본 설정을 저장하거나, 형식화 옵션을 검증하거나, 날짜와 숫자에 대한 문화적 관습을 존중하는 국제화된 애플리케이션을 만들 때 이러한 메서드를 사용하십시오.