Los plurales y las formas select cubren los casos en que una sola cadena fuente no alcanza: la traducción depende de un número o de una categoría. @lingo.dev/react ofrece dos helpers prácticos (l.plural y l.select) que se compilan internamente a ICU MessageFormat, así que los traductores ven la sintaxis estándar y el runtime sigue siendo el mismo.
Plurales#
l.plural(count, forms, { context }) elige la forma correcta según count y las reglas de pluralización de CLDR para el idioma.
const l = useLingo();
l.plural(items.length, {
one: "1 item",
other: "{count} items",
}, { context: "Cart summary" });
// → "1 item" (en, count=1) / "5 items" (en, count=5)
// → "1 Eintrag" / "5 Einträge" (de, after translation)Formas por idioma#
El mapa de formas acepta todas las categorías plurales de CLDR: zero, one, two, few, many, other. Cada idioma usa las que necesita:
- El inglés usa
one+other(1 vs. todo lo demás) - El ruso usa
one+few+many+other(1; 2-4; 5-20; 21, 31, ...) - El árabe usa las seis
- El japonés usa solo
other(sin distinción de plural)
Solo necesitas proporcionar las formas que usa el idioma fuente; los traductores agregan el resto según el idioma de destino.
{count} se interpola automáticamente dentro de cualquier forma plural. No lo pasas por values; viene del primer argumento.
Combinar con otros placeholders#
En oraciones con una cantidad y otras variables, escribe esas variables dentro de las cadenas de cada forma; se pasarán a ICU.
l.plural(notifications.length, {
one: "1 message from {sender}",
other: "{count} messages from {sender}",
}, { context: "Inbox header" });Luego pasa los valores al hacer la llamada; pero ojo, la firma de l.plural solo incluye { context }. Para casos mixtos, usa l.text directamente con la sintaxis plural de ICU:
l.text(`{count, plural, one {1 message from {sender}} other {# messages from {sender}}}`, {
values: { count: notifications.length, sender: user.name },
context: "Inbox header",
});El token # se reemplaza por el valor de la cantidad tal cual, lo que resulta útil cuando lo quieres sin la interpolación entre llaves.
Select#
l.select(value, forms, { context }) elige una forma según una clave de texto (género, rol, tipo de contenido o cualquier otra categoría).
l.select(user.gender, {
male: "He uploaded a photo",
female: "She uploaded a photo",
other: "They uploaded a photo",
}, { context: "Activity feed" });other es obligatorio como fallback. La coincidencia es exacta: no hay coincidencias difusas ni insensibles a mayúsculas y minúsculas.
Selectordinal#
Para números ordinales (1.º, 2.º, 3.º), usa ICU selectordinal directamente a través de l.text:
l.text(`You finished in {place, selectordinal, one {#st} two {#nd} few {#rd} other {#th}} place`, {
values: { place: rank },
context: "Leaderboard",
});
// → "You finished in 1st place" / "2nd" / "3rd" / "4th, 5th, ..."En qué se compila#
Tanto l.plural como l.select construyen una cadena en ICU MessageFormat y se la pasan a l.text. La forma compilada es lo que extrae lingo extract y se guarda en tus archivos de idioma; los traductores editan la sintaxis de ICU directamente, no el literal del objeto de JS.
Ejemplo: l.plural(n, { one: "1 item", other: "{count} items" }, { context: "Cart" }) se extrae así:
{count, plural, one {1 item} other {{count} items}}Esto significa que los traductores pueden adaptar las categorías según el idioma, incluso las que no existen en la fuente. El ruso pasa a ser {count, plural, one {...} few {...} many {...} other {...}} sin ningún cambio de código.
Cuándo no conviene usar esto#
- Un simple booleano de "1 o muchos". Dos llamadas a
l.textdentro de uniffuncionan bien y son más fáciles de detectar para los traductores. - Un enum programático que no ve el usuario. Plural / select son para la traducción de mensajes categóricos, no para controlar la lógica de la app.
Qué sigue#
- useLingo — semántica base de
l.textyl.rich. - Formatting — formato de números, moneda, fechas y listas con Intl nativo.
