JavaScript에서 로케일별 구분자로 배열을 포맷팅하는 방법은 무엇인가요?
Intl.ListFormat를 사용하여 모든 언어에 맞는 쉼표, 공백 및 구두점을 자동으로 적용하세요.
소개
배열을 읽기 쉬운 문자열로 변환할 때, 항목을 쉼표나 다른 구두점으로 구분해야 합니다. 다양한 언어는 서로 다른 구분자를 사용합니다. 영어는 쉼표와 공백을 사용하고, 일본어는 열거형 쉼표 、를 사용하며, 아랍어는 다른 구두점과 단어 순서를 사용합니다.
Intl.ListFormat API는 배열을 로케일에 적합한 구분자가 있는 문자열로 변환합니다. 이를 통해 모든 언어의 사용자에게 자연스러운 목록을 제공할 수 있습니다.
배열 구분자가 로케일에 따라 다른 이유
모든 언어가 쉼표를 사용하여 목록 항목을 구분한다고 가정할 수 있습니다. 그러나 이는 사실이 아닙니다.
영어는 쉼표와 공백으로 항목을 구분합니다.
// 영어: "red, green, blue"
일본어는 공백 없이 열거형 쉼표 、를 사용합니다.
// 일본어: "赤、緑、青"
중국어는 동일한 열거형 쉼표 、 문자를 사용합니다.
// 중국어: "红、绿、蓝"
아랍어는 다른 쉼표 문자 ،를 사용하고 오른쪽에서 왼쪽으로 읽습니다.
// 아랍어: "أحمر، أخضر، أزرق"
이러한 차이점은 Intl.ListFormat에서 자동으로 처리됩니다. 각 언어의 구두점 규칙을 알 필요가 없습니다.
join() 메서드의 문제점
Array.prototype.join() 메서드는 지정한 구분자를 사용하여 배열을 문자열로 변환합니다.
const colors = ["red", "green", "blue"];
console.log(colors.join(", "));
// "red, green, blue"
이는 영어 구두점을 하드코딩합니다. 쉼표와 공백 구분자는 다른 언어에서는 적합하지 않습니다.
const colors = ["赤", "緑", "青"];
console.log(colors.join(", "));
// "赤, 緑, 青" (잘못됨 - , 대신 、를 사용해야 함)
로케일에 따라 구분자를 수동으로 전환할 수 없습니다. 모든 언어와 해당 구두점 규칙의 매핑을 유지해야 하기 때문입니다. 이러한 매핑은 불완전하고 유지하기 어렵습니다.
로케일 인식 구분자를 위한 Intl.ListFormat 사용
Intl.ListFormat 생성자는 모든 로케일에 대해 올바른 구분자를 적용하는 포맷터를 생성합니다.
const formatter = new Intl.ListFormat("en");
const colors = ["red", "green", "blue"];
console.log(formatter.format(colors));
// "red, green, and blue"
포맷터는 지정된 로케일에 맞는 구두점을 자동으로 사용합니다. 첫 번째 인수로 로케일 코드를 전달합니다.
const enFormatter = new Intl.ListFormat("en");
const jaFormatter = new Intl.ListFormat("ja");
const arFormatter = new Intl.ListFormat("ar");
const colors = ["red", "green", "blue"];
console.log(enFormatter.format(colors));
// "red, green, and blue"
console.log(jaFormatter.format(["赤", "緑", "青"]));
// "赤、緑、青"
console.log(arFormatter.format(["أحمر", "أخضر", "أزرق"]));
// "أحمر، أخضر، أزرق"
브라우저가 구두점 규칙을 제공합니다. 로케일별 코드를 유지할 필요가 없습니다.
언어별 구분자 변화
포맷터는 로케일에 따라 다른 구분자를 적용합니다. 다음 예제는 동일한 배열이 다르게 포맷되는 방식을 보여줍니다.
영어는 쉼표, 공백 및 "and" 단어를 사용합니다.
const formatter = new Intl.ListFormat("en");
console.log(formatter.format(["apple", "orange", "banana"]));
// "apple, orange, and banana"
스페인어는 쉼표, 공백 및 "y" 단어를 사용합니다.
const formatter = new Intl.ListFormat("es");
console.log(formatter.format(["manzana", "naranja", "plátano"]));
// "manzana, naranja y plátano"
프랑스어는 쉼표, 공백 및 "et" 단어를 사용합니다.
const formatter = new Intl.ListFormat("fr");
console.log(formatter.format(["pomme", "orange", "banane"]));
// "pomme, orange et banane"
독일어는 쉼표, 공백 및 "und" 단어를 사용합니다.
const formatter = new Intl.ListFormat("de");
console.log(formatter.format(["Apfel", "Orange", "Banane"]));
// "Apfel, Orange und Banane"
일본어는 열거형 쉼표 、와 문자 、를 사용합니다.
const formatter = new Intl.ListFormat("ja");
console.log(formatter.format(["りんご", "オレンジ", "バナナ"]));
// "りんご、オレンジ、バナナ"
중국어는 열거형 쉼표 、와 단어 和를 사용합니다.
const formatter = new Intl.ListFormat("zh");
console.log(formatter.format(["苹果", "橙子", "香蕉"]));
// "苹果、橙子和香蕉"
한국어는 쉼표와 조사 및을 사용합니다.
const formatter = new Intl.ListFormat("ko");
console.log(formatter.format(["사과", "오렌지", "바나나"]));
// "사과, 오렌지 및 바나나"
포맷터는 이러한 모든 차이점을 자동으로 처리합니다. 모든 언어에 대해 동일한 코드를 작성하면 됩니다.
사용자의 로케일 사용하기
브라우저 설정에서 사용자가 선호하는 로케일을 감지하고 이를 사용하여 목록을 형식화할 수 있습니다.
const userLocale = navigator.language;
const formatter = new Intl.ListFormat(userLocale);
const items = ["first", "second", "third"];
console.log(formatter.format(items));
이렇게 하면 목록이 사용자의 기대에 맞는 구분 기호를 사용하게 됩니다. 프랑스어 브라우저 설정을 가진 사용자는 프랑스어 구두점을 보게 됩니다. 일본어 설정을 가진 사용자는 일본어 구두점을 보게 됩니다.
접속사 없이 배열 형식화하기
기본 Intl.ListFormat 동작은 마지막 항목 앞에 "그리고"와 같은 접속사를 추가합니다. 단위 유형을 사용하여 이 기능을 비활성화할 수 있습니다.
const formatter = new Intl.ListFormat("en", { type: "unit" });
console.log(formatter.format(["5 km", "12 minutes", "100 calories"]));
// "5 km, 12 minutes, 100 calories"
단위 유형은 연결 단어를 추가하지 않고 구분 기호만 사용합니다. 이는 접속사가 적절하지 않은 기술적 목록, 측정값 또는 데이터에 유용합니다.
const enFormatter = new Intl.ListFormat("en", { type: "unit" });
const jaFormatter = new Intl.ListFormat("ja", { type: "unit" });
console.log(enFormatter.format(["Item A", "Item B", "Item C"]));
// "Item A, Item B, Item C"
console.log(jaFormatter.format(["항목A", "항목B", "항목C"]));
// "항목A、항목B、항목C"
접속사가 없더라도 구분 기호 구두점은 여전히 로케일 규칙을 따릅니다.
재사용 가능한 포맷터 만들기
포맷터를 한 번 만들고 여러 배열에 재사용할 수 있습니다. 이는 각 배열마다 새 포맷터를 만드는 것보다 더 효율적입니다.
const formatter = new Intl.ListFormat("en");
console.log(formatter.format(["red", "green"]));
// "red and green"
console.log(formatter.format(["a", "b", "c", "d"]));
// "a, b, c, and d"
console.log(formatter.format(["one"]));
// "one"
동일한 포맷터는 모든 길이의 배열에 작동합니다. 배열에 있는 항목 수에 따라 올바른 구분 기호와 접속사를 적용합니다.
빈 배열 처리하기
빈 배열을 포맷팅할 때, 포맷터는 빈 문자열을 반환합니다.
const formatter = new Intl.ListFormat("en");
console.log(formatter.format([]));
// ""
다른 동작이 필요한 경우 포맷팅하기 전에 빈 배열을 확인해야 합니다.
function formatList(items, locale) {
if (items.length === 0) {
return "No items";
}
const formatter = new Intl.ListFormat(locale);
return formatter.format(items);
}
console.log(formatList([], "en"));
// "No items"
console.log(formatList(["apple"], "en"));
// "apple"
이렇게 하면 빈 배열이 사용자에게 어떻게 표시되는지 제어할 수 있습니다.
브라우저 지원
Intl.ListFormat API는 모든 최신 브라우저에서 사용할 수 있습니다. 2021년 4월부터 Chrome, Firefox, Safari 및 Edge에서 지원되고 있습니다.
사용하기 전에 API가 존재하는지 확인할 수 있습니다.
if (typeof Intl.ListFormat !== "undefined") {
const formatter = new Intl.ListFormat("en");
console.log(formatter.format(["a", "b", "c"]));
} else {
console.log("Intl.ListFormat is not supported");
}
구형 브라우저의 경우 join() 메서드로 대체할 수 있습니다. 이는 로케일별 구분자 없이 기본 포맷팅을 제공합니다.
function formatList(items, locale) {
if (typeof Intl.ListFormat !== "undefined") {
const formatter = new Intl.ListFormat(locale);
return formatter.format(items);
}
return items.join(", ");
}
console.log(formatList(["red", "green", "blue"], "en"));
// "red, green, and blue" (또는 구형 브라우저에서는 "red, green, blue")
이렇게 하면 모든 브라우저에서 코드가 작동하면서 최신 브라우저에서는 최상의 경험을 제공할 수 있습니다.