1st, 2nd, 3rd와 같은 서수 형식 지정 방법
JavaScript를 사용하여 로케일에 적합한 접미사와 형식으로 서수를 표시하세요
소개
서수는 순서에서 위치나 순위를 나타냅니다. 영어에서는 경주에서의 순위나 목록의 항목을 설명하기 위해 1st, 2nd, 3rd, 4th와 같이 작성합니다. 이러한 접미사는 서수를 일반 기수와 구별하는 데 도움이 됩니다.
언어마다 서수에 대해 완전히 다른 규칙을 사용합니다. 영어는 st, nd, rd, th와 같은 접미사를 추가합니다. 프랑스어는 1er, 2e와 같은 위첨자 문자를 사용합니다. 독일어는 1., 2.와 같이 숫자 뒤에 마침표를 추가합니다. 일본어는 숫자 앞에 第 문자를 붙입니다. 영어 서수 접미사를 하드코딩하면 모든 사용자가 동일한 규칙을 따른다고 가정하게 됩니다.
JavaScript는 이러한 차이를 자동으로 처리하기 위해 Intl.PluralRules API를 서수 타입과 함께 제공합니다. 이 레슨에서는 서수가 무엇인지, 언어마다 형식이 왜 다른지, 그리고 모든 로케일에 대해 올바르게 형식을 지정하는 방법을 설명합니다.
서수란 무엇인가
서수는 순서에서 위치, 순위 또는 순서를 나타냅니다. "몇 개"가 아니라 "어느 것"이라는 질문에 답합니다. 1st, 2nd, 3rd는 경주에서의 위치를 설명합니다. 첫 번째, 두 번째, 세 번째는 목록의 항목을 설명합니다.
기수는 수량이나 양을 나타냅니다. "몇 개"라는 질문에 답합니다. 1, 2, 3은 객체의 개수를 설명합니다. 하나, 둘, 셋은 양을 설명합니다.
동일한 숫자 값이 문맥에 따라 두 가지 목적으로 사용됩니다. 숫자 5는 "사과 5개"에서는 기수이지만 "5위"에서는 서수입니다. 많은 언어에서 서수를 기수와 다르게 형식 지정하기 때문에 이러한 구분이 중요합니다.
영어에서 10 미만의 서수는 고유한 단어 형태를 가집니다. First, second, third, fourth, fifth는 각각 구별되는 단어입니다. 10 이상에서는 영어가 접미사를 추가하여 서수를 형성합니다. Eleventh, twelfth, twentieth, twenty-first는 패턴을 따르지만 접미사가 필요합니다.
서수를 단어가 아닌 숫자로 표기할 때, 영어는 st, nd, rd 또는 th 접미사를 추가합니다. 이러한 접미사는 숫자의 마지막 자릿수에 따라 특정 규칙을 따릅니다.
서수 형식이 로케일에 따라 다른 이유
각 언어는 서수를 표현하는 서로 다른 체계를 발전시켰습니다. 이러한 관례는 각 언어 고유의 문법 규칙, 표기 체계 및 문화적 관행을 반영합니다.
영어에서 서수는 네 가지 접미사를 사용합니다. 1로 끝나는 숫자는 st를, 2로 끝나는 숫자는 nd를, 3으로 끝나는 숫자는 rd를, 그 외 모든 숫자는 th를 사용합니다. 그러나 11, 12, 13으로 끝나는 숫자는 모두 th를 사용합니다. 따라서 1st, 2nd, 3rd, 4th, 11th, 12th, 13th, 21st, 22nd, 23rd가 됩니다.
프랑스어에서 서수는 위첨자 약어를 사용합니다. 첫 번째 항목은 남성형의 경우 1er, 여성형의 경우 1re를 사용합니다. 그 외 모든 서수는 2e, 3e, 4e와 같이 위첨자로 e를 사용합니다. 형식에는 단순한 접미사 문자가 아닌 위첨자 타이포그래피가 포함됩니다.
독일어에서 서수는 숫자 뒤에 마침표를 사용합니다. 1., 2., 3. 표기는 첫 번째, 두 번째, 세 번째를 나타냅니다. 이 마침표는 독자가 소리 내어 읽을 때 적절한 문법적 어미를 추가해야 함을 나타냅니다.
스페인어에서 서수는 성별에 따른 위첨자 표시를 사용합니다. 남성형 서수는 1.º, 2.º, 3.º를 사용하고 여성형 서수는 1.ª, 2.ª, 3.ª를 사용합니다. 마침표는 숫자와 표시를 구분합니다.
일본어에서 서수는 숫자 앞에 접두사 第를 추가합니다. 첫 번째, 두 번째, 세 번째는 第一, 第二, 第三으로 표시됩니다. 이 접두사는 의미를 기수에서 서수로 변경합니다.
하드코딩된 접미사와 숫자를 연결하여 서수 문자열을 구성하면 모든 사용자가 영어 규칙을 해석하도록 강제하게 됩니다. 이는 다른 형식을 기대하는 사람들이 애플리케이션을 사용하기 어렵게 만듭니다.
ordinal 타입의 Intl.PluralRules 이해하기
Intl.PluralRules API는 주어진 로케일에 대해 숫자가 어떤 복수 범주에 속하는지 결정합니다. 이 API는 일반적으로 단수형과 복수형 단어 형태를 선택하는 데 사용되지만, 서수도 처리합니다.
생성자는 로케일 식별자와 옵션 객체를 받습니다. 기수 대신 서수를 사용하려면 type 옵션을 "ordinal"로 설정하세요.
const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });
이렇게 하면 영어 서수 패턴을 이해하는 규칙 객체가 생성됩니다. select() 메서드는 전달한 숫자에 대한 범주 이름을 반환합니다.
const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });
console.log(rules.select(1));
// Output: "one"
console.log(rules.select(2));
// Output: "two"
console.log(rules.select(3));
// Output: "few"
console.log(rules.select(4));
// Output: "other"
반환되는 범주는 실제 접미사가 아닌 언어학적 용어입니다. "one" 범주는 영어에서 st 접미사를 사용하는 숫자에 해당합니다. "two" 범주는 nd 접미사에 해당합니다. "few" 범주는 rd 접미사에 해당합니다. "other" 범주는 th 접미사에 해당합니다.
이러한 범주 이름을 로케일에 적합한 접미사에 매핑합니다. API는 각 숫자가 속하는 범주를 결정하는 복잡한 규칙을 처리합니다.
서수 포매터 함수 구축하기
서수를 형식화하려면 Intl.PluralRules를 복수 범주에서 접미사로의 매핑과 결합합니다. 숫자를 받아 형식화된 문자열을 반환하는 포맷터 함수를 만드세요.
function formatOrdinal(number, locale) {
const rules = new Intl.PluralRules(locale, { type: 'ordinal' });
const category = rules.select(number);
const suffixes = {
one: 'st',
two: 'nd',
few: 'rd',
other: 'th'
};
const suffix = suffixes[category];
return `${number}${suffix}`;
}
console.log(formatOrdinal(1, 'en-US'));
// Output: "1st"
console.log(formatOrdinal(2, 'en-US'));
// Output: "2nd"
console.log(formatOrdinal(3, 'en-US'));
// Output: "3rd"
console.log(formatOrdinal(4, 'en-US'));
// Output: "4th"
이 함수는 실행될 때마다 새로운 PluralRules 인스턴스를 생성합니다. 더 나은 성능을 위해 규칙 객체를 한 번 생성하고 여러 숫자에 재사용하세요.
const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });
const suffixes = {
one: 'st',
two: 'nd',
few: 'rd',
other: 'th'
};
function formatOrdinal(number) {
const category = rules.select(number);
const suffix = suffixes[category];
return `${number}${suffix}`;
}
console.log(formatOrdinal(1));
// Output: "1st"
console.log(formatOrdinal(21));
// Output: "21st"
console.log(formatOrdinal(22));
// Output: "22nd"
console.log(formatOrdinal(23));
// Output: "23rd"
API는 11, 12, 13과 같은 숫자를 올바르게 처리하며, 이들은 마지막 자릿수와 관계없이 모두 th를 사용합니다.
console.log(formatOrdinal(11));
// Output: "11th"
console.log(formatOrdinal(12));
// Output: "12th"
console.log(formatOrdinal(13));
// Output: "13th"
복수형 규칙은 로케일의 모든 특수 사례와 예외를 인코딩합니다. 이러한 엣지 케이스를 처리하기 위해 조건부 로직을 작성할 필요가 없습니다.
다양한 로케일에 대한 서수 형식 지정
복수형 카테고리와 그 의미는 로케일마다 다릅니다. 일부 언어는 영어보다 적은 카테고리를 가지고 있습니다. 다른 언어는 각 카테고리에 속하는 숫자에 대해 다른 규칙을 가지고 있습니다.
웨일스어는 다른 분류 체계를 사용합니다. 규칙은 더 많은 카테고리를 식별하며, 각각은 웨일스어의 다른 서수 형태에 해당합니다.
const enRules = new Intl.PluralRules('en-US', { type: 'ordinal' });
const cyRules = new Intl.PluralRules('cy', { type: 'ordinal' });
console.log(enRules.select(1));
// Output: "one"
console.log(cyRules.select(1));
// Output: "one"
console.log(enRules.select(2));
// Output: "two"
console.log(cyRules.select(2));
// Output: "two"
console.log(enRules.select(5));
// Output: "other"
console.log(cyRules.select(5));
// Output: "many"
여러 로케일을 지원하려면 각 로케일에 대해 다른 접미사 매핑이 필요합니다. 카테고리는 동일하게 유지되지만 접미사는 변경됩니다.
const ordinalSuffixes = {
'en-US': {
one: 'st',
two: 'nd',
few: 'rd',
other: 'th'
},
'fr-FR': {
one: 'er',
other: 'e'
}
};
function formatOrdinal(number, locale) {
const rules = new Intl.PluralRules(locale, { type: 'ordinal' });
const category = rules.select(number);
const suffixes = ordinalSuffixes[locale];
const suffix = suffixes[category] || suffixes.other;
return `${number}${suffix}`;
}
console.log(formatOrdinal(1, 'en-US'));
// Output: "1st"
console.log(formatOrdinal(1, 'fr-FR'));
// Output: "1er"
console.log(formatOrdinal(2, 'en-US'));
// Output: "2nd"
console.log(formatOrdinal(2, 'fr-FR'));
// Output: "2e"
이 접근 방식은 각 로케일에 대한 접미사 문자열을 제어할 때 잘 작동합니다. 그러나 지원하는 모든 로케일에 대해 접미사 데이터를 유지 관리해야 합니다.
서수 복수형 카테고리 이해하기
Intl.PluralRules API는 6개의 가능한 범주 이름을 사용합니다. 로케일마다 이러한 범주의 다른 하위 집합을 사용합니다.
카테고리는 zero, one, two, few, many, other입니다. 모든 언어가 6개 카테고리를 모두 구분하는 것은 아닙니다. 영어 서수는 one, two, few, other의 4개만 사용합니다.
카테고리 이름은 숫자 값과 직접적으로 대응하지 않습니다. "one" 카테고리에는 11을 제외하고 1, 21, 31, 41 및 1로 끝나는 모든 숫자가 포함됩니다. "two" 카테고리에는 12를 제외하고 2, 22, 32, 42 및 2로 끝나는 모든 숫자가 포함됩니다.
로케일이 사용하는 범주를 확인하려면 resolvedOptions() 메서드를 호출하고 pluralCategories 속성을 검사하세요.
const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });
const options = rules.resolvedOptions();
console.log(options.pluralCategories);
// Output: ["one", "two", "few", "other"]
이는 영어 서수가 네 가지 범주를 사용함을 보여줍니다. 다른 로케일은 서로 다른 범주 집합을 사용합니다.
const rules = new Intl.PluralRules('fr-FR', { type: 'ordinal' });
const options = rules.resolvedOptions();
console.log(options.pluralCategories);
// Output: ["one", "other"]
프랑스어 서수는 one과 other만 구분합니다. 이러한 단순한 분류는 프랑스어의 더 간단한 접미사 규칙을 반영합니다.
사용자 로케일에 맞게 서수 형식 지정하기
특정 로케일을 하드코딩하는 대신 브라우저에서 사용자가 선호하는 언어를 사용할 수 있습니다. navigator.language 속성은 사용자의 최우선 언어 기본 설정을 반환합니다.
const userLocale = navigator.language;
const rules = new Intl.PluralRules(userLocale, { type: 'ordinal' });
const suffixes = {
one: 'st',
two: 'nd',
few: 'rd',
other: 'th'
};
function formatOrdinal(number) {
const category = rules.select(number);
const suffix = suffixes[category] || suffixes.other;
return `${number}${suffix}`;
}
console.log(formatOrdinal(1));
// Output varies by user's locale
이 접근 방식은 사용자의 언어 기본 설정에 자동으로 적응합니다. 그러나 애플리케이션이 지원하는 각 로케일에 대해 적절한 접미사 매핑을 제공해야 합니다.
특정 접미사 매핑이 없는 로케일의 경우, 기본 동작으로 대체하거나 접미사 없이 숫자를 표시할 수 있습니다.
function formatOrdinal(number, locale = navigator.language) {
const rules = new Intl.PluralRules(locale, { type: 'ordinal' });
const category = rules.select(number);
const localeMapping = ordinalSuffixes[locale];
if (!localeMapping) {
return String(number);
}
const suffix = localeMapping[category] || localeMapping.other || '';
return `${number}${suffix}`;
}
이 함수는 로케일에 대한 접미사 매핑이 없을 때 숫자만 반환합니다.
서수의 일반적인 사용 사례
서수는 사용자 인터페이스의 여러 일반적인 맥락에서 나타납니다. 이러한 사용 사례를 이해하면 숫자를 서수로 형식 지정할 시기를 결정하는 데 도움이 됩니다.
순위 및 리더보드는 사용자 위치를 표시합니다. 게임 애플리케이션은 "place 1", "place 2", "place 3" 대신 "1st place", "2nd place", "3rd place"를 표시합니다.
function formatRanking(position) {
const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });
const category = rules.select(position);
const suffixes = {
one: 'st',
two: 'nd',
few: 'rd',
other: 'th'
};
const suffix = suffixes[category];
return `${position}${suffix} place`;
}
console.log(formatRanking(1));
// Output: "1st place"
console.log(formatRanking(42));
// Output: "42nd place"
날짜 형식 지정은 때때로 월의 일자에 서수를 사용합니다. 일부 로케일은 "January 1" 대신 "January 1st"로 표기합니다.
단계별 지침은 각 단계를 번호 매기기 위해 서수를 사용합니다. 튜토리얼은 "1st step: Install the software", "2nd step: Configure settings", "3rd step: Start the application"을 표시합니다.
긴 시퀀스의 목록 항목은 단순한 열거보다 위치를 강조하는 것이 중요할 때 서수 형식 지정의 이점을 얻습니다.
성능을 위한 규칙 객체 재사용
새로운 Intl.PluralRules 인스턴스를 생성하려면 로케일 데이터를 로드하고 옵션을 처리해야 합니다. 동일한 로케일로 여러 서수를 형식화할 때는 규칙 객체를 한 번 생성하여 재사용하세요.
const rules = new Intl.PluralRules('en-US', { type: 'ordinal' });
const suffixes = {
one: 'st',
two: 'nd',
few: 'rd',
other: 'th'
};
function formatOrdinal(number) {
const category = rules.select(number);
const suffix = suffixes[category];
return `${number}${suffix}`;
}
const positions = [1, 2, 3, 4, 5];
positions.forEach(position => {
console.log(formatOrdinal(position));
});
// Output:
// "1st"
// "2nd"
// "3rd"
// "4th"
// "5th"
이 접근 방식은 각 숫자마다 새로운 규칙 객체를 생성하는 것보다 더 효율적입니다. 수백 또는 수천 개의 값을 가진 배열을 포맷할 때 성능 차이가 두드러집니다.
특정 로케일에 대해 구성된 함수를 반환하는 포매터 팩토리를 생성할 수도 있습니다.
function createOrdinalFormatter(locale, suffixMapping) {
const rules = new Intl.PluralRules(locale, { type: 'ordinal' });
return function(number) {
const category = rules.select(number);
const suffix = suffixMapping[category] || suffixMapping.other || '';
return `${number}${suffix}`;
};
}
const formatEnglishOrdinal = createOrdinalFormatter('en-US', {
one: 'st',
two: 'nd',
few: 'rd',
other: 'th'
});
console.log(formatEnglishOrdinal(1));
// Output: "1st"
console.log(formatEnglishOrdinal(2));
// Output: "2nd"
이 패턴은 규칙 객체와 접미사 매핑을 함께 캡슐화하여 애플리케이션 전체에서 포매터를 쉽게 재사용할 수 있도록 합니다.