¿Cómo formateo arrays con separadores específicos del idioma en JavaScript?
Usa Intl.ListFormat para aplicar automáticamente las comas, espacios y puntuación correctos para cualquier idioma.
Introducción
Cuando conviertes un array en una cadena de texto legible, necesitas separar los elementos con comas u otros signos de puntuación. Diferentes idiomas utilizan diferentes separadores. El inglés usa comas y espacios, el japonés utiliza la coma de enumeración 、, y el árabe utiliza una puntuación y un orden de palabras diferentes.
La API Intl.ListFormat convierte arrays en cadenas de texto con separadores apropiados según la configuración regional. Esto asegura que tus listas se vean naturales para los usuarios en cada idioma.
Por qué los separadores de arrays difieren según la configuración regional
Podrías suponer que todos los idiomas utilizan comas para separar elementos de una lista. Esto no es cierto.
El inglés separa los elementos con una coma y un espacio.
// Inglés: "red, green, blue"
El japonés utiliza la coma de enumeración 、 sin espacios.
// Japonés: "赤、緑、青"
El chino utiliza el mismo carácter de coma de enumeración 、.
// Chino: "红、绿、蓝"
El árabe utiliza un carácter de coma diferente، y se lee de derecha a izquierda.
// Árabe: "أحمر، أخضر، أزرق"
Estas diferencias son automáticas en Intl.ListFormat. No necesitas conocer las reglas de puntuación para cada idioma.
El problema con join()
El método Array.prototype.join() convierte arrays en cadenas de texto utilizando un separador que especifiques.
const colors = ["red", "green", "blue"];
console.log(colors.join(", "));
// "red, green, blue"
Esto codifica de forma rígida la puntuación en inglés. El separador de coma y espacio no funciona para otros idiomas.
const colors = ["赤", "緑", "青"];
console.log(colors.join(", "));
// "赤, 緑, 青" (incorrecto - debería usar 、 en lugar de ,)
No puedes cambiar manualmente los separadores según la configuración regional porque necesitarías mantener un mapeo de cada idioma con sus reglas de puntuación. Este mapeo sería incompleto y difícil de mantener.
Uso de Intl.ListFormat para separadores adaptados al idioma
El constructor Intl.ListFormat crea un formateador que aplica los separadores correctos para cualquier idioma.
const formatter = new Intl.ListFormat("en");
const colors = ["red", "green", "blue"];
console.log(formatter.format(colors));
// "red, green, and blue"
El formateador utiliza automáticamente la puntuación adecuada para el idioma especificado. Se pasa el código de idioma como primer argumento.
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(["أحمر", "أخضر", "أزرق"]));
// "أحمر، أخضر، أزرق"
El navegador proporciona las reglas de puntuación. No es necesario mantener ningún código específico para cada idioma.
Cómo cambian los separadores entre idiomas
El formateador aplica diferentes separadores según el idioma. Estos ejemplos muestran cómo el mismo array se formatea de manera diferente.
El inglés utiliza una coma, un espacio y la palabra "and".
const formatter = new Intl.ListFormat("en");
console.log(formatter.format(["apple", "orange", "banana"]));
// "apple, orange, and banana"
El español utiliza una coma, un espacio y la palabra "y".
const formatter = new Intl.ListFormat("es");
console.log(formatter.format(["manzana", "naranja", "plátano"]));
// "manzana, naranja y plátano"
El francés utiliza una coma, un espacio y la palabra "et".
const formatter = new Intl.ListFormat("fr");
console.log(formatter.format(["pomme", "orange", "banane"]));
// "pomme, orange et banane"
El alemán utiliza una coma, un espacio y la palabra "und".
const formatter = new Intl.ListFormat("de");
console.log(formatter.format(["Apfel", "Orange", "Banane"]));
// "Apfel, Orange und Banane"
El japonés utiliza la coma de enumeración 、 y el carácter 、.
const formatter = new Intl.ListFormat("ja");
console.log(formatter.format(["りんご", "オレンジ", "バナナ"]));
// "りんご、オレンジ、バナナ"
El chino utiliza la coma de enumeración 、 y la palabra 和.
const formatter = new Intl.ListFormat("zh");
console.log(formatter.format(["苹果", "橙子", "香蕉"]));
// "苹果、橙子和香蕉"
El coreano utiliza una coma y la partícula 및.
const formatter = new Intl.ListFormat("ko");
console.log(formatter.format(["사과", "오렌지", "바나나"]));
// "사과, 오렌지 및 바나나"
El formateador maneja todas estas diferencias automáticamente. Se escribe el mismo código para todos los idiomas.
Uso de la configuración regional del usuario
Puedes detectar la configuración regional preferida del usuario desde la configuración de su navegador y utilizarla para formatear listas.
const userLocale = navigator.language;
const formatter = new Intl.ListFormat(userLocale);
const items = ["primero", "segundo", "tercero"];
console.log(formatter.format(items));
Esto asegura que la lista utilice separadores que coincidan con las expectativas del usuario. Un usuario con configuración de navegador en francés verá puntuación francesa. Un usuario con configuración japonesa verá puntuación japonesa.
Formateo de arrays sin conjunciones
El comportamiento predeterminado de Intl.ListFormat añade una conjunción como "y" antes del último elemento. Puedes desactivar esto utilizando el tipo de unidad.
const formatter = new Intl.ListFormat("en", { type: "unit" });
console.log(formatter.format(["5 km", "12 minutes", "100 calories"]));
// "5 km, 12 minutes, 100 calories"
El tipo de unidad utiliza solo separadores sin añadir palabras conectoras. Esto es útil para listas técnicas, mediciones o datos donde las conjunciones no son apropiadas.
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"
Incluso sin conjunciones, la puntuación del separador sigue las reglas de la configuración regional.
Creación de formateadores reutilizables
Puedes crear un formateador una vez y reutilizarlo para múltiples arrays. Esto es más eficiente que crear un nuevo formateador para cada array.
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"
El mismo formateador funciona para arrays de cualquier longitud. Aplica los separadores y conjunciones correctos según la cantidad de elementos que hay en el array.
Manejo de arrays vacíos
Cuando formateas un array vacío, el formateador devuelve una cadena vacía.
const formatter = new Intl.ListFormat("en");
console.log(formatter.format([]));
// ""
Debes comprobar si hay arrays vacíos antes de formatear si necesitas un comportamiento diferente.
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"
Esto te da control sobre cómo aparecen los arrays vacíos para los usuarios.
Compatibilidad con navegadores
La API Intl.ListFormat está disponible en todos los navegadores modernos. Ha sido compatible desde abril de 2021 en Chrome, Firefox, Safari y Edge.
Puedes comprobar si la API existe antes de usarla.
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");
}
Para navegadores más antiguos, puedes recurrir al método join(). Esto proporciona un formateo básico sin separadores específicos del idioma.
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" (o "red, green, blue" en navegadores más antiguos)
Esto asegura que tu código funcione en todos los navegadores mientras proporciona la mejor experiencia en los modernos.