Guías
Formato de mensajes
Una sintaxis pequeña, con Intl nativo por debajo: plurales, género y formato sin aprender ICU completo.
Interpolación
"Hola {name}" → t('saludo', { name: 'Aron' })Los valores se formatean solos según su tipo: números con Intl.NumberFormat, fechas con Intl.DateTimeFormat, textos tal cual. Un param que falta muestra el hueco literal y avisa una vez nombrando el mensaje, así que se ve rápido y nunca revienta.
Formatters
Agrega :formatter (con /arg opcional) a un param:
| Sintaxis | Resultado |
|---|---|
| {n:number} | Número del locale: 1,234.56 / 1234,56 |
| {n:integer} | Redondeado, sin decimales |
| {n:percent} | 0.5 → 50% |
| {n:currency/EUR} | Moneda con código ISO |
| {d:date/long} | dateStyle: short · medium · long · full |
| {d:time/short} | Variantes de timeStyle |
Los formatters custom se conectan al crear la instancia. La firma completa es (value, locale, arg?) => string, donde locale es el idioma activo y arg es lo que sigue al / en el placeholder:
createVerbaly({
formatters: { upper: (v) => String(v).toUpperCase() },
});
// "{word:upper}" → HOLATiempo relativo, listas y unidades
El formato cubre el resto del Intl moderno, siempre con cero dependencias:
"Updated {when:relative}" → Updated 2 hours ago · yesterday
"Ready {n:relative/day}" → Ready in 3 days
"Works in {langs:list}" → Works in English, Spanish, and Portuguese
"Pick {opts:list/or}" → Pick red, green, or blue
"{d:unit/kilometer}" → 3 kmrelative: pasa unDatey la unidad se elige sola contra ahora (Intl.RelativeTimeFormatconnumeric: 'auto', así obtienes ayer, no hace 1 día); pasa un número con unidad explícita (relative/hour).list: los arrays se localizan víaIntl.ListFormat, conjunción por defecto,/orpara disyunción,/unitpara listas de unidades. Cada elemento se auto-formatea por locale.unit: cualquier id de unidad CLDR (kilometer,megabyte,liter…) víaIntl.NumberFormat.- Los datos malos nunca rompen el render, y tampoco pasan de largo: un formato desconocido, una unidad inválida, un hueco al que le falta su argumento o una lista que no es lista avisan una vez, nombrando el mensaje, y caen a
String(value).
Plurales y selects: una sola sintaxis
"{count | =0: sin mensajes | one: un mensaje | other: # mensajes}"
"{gender | male: él | female: ella | other: elle}"- Los números matchean primero los valores exactos
=N, luego las categorías deIntl.PluralRules(zero one two few many other). - Los strings matchean su variante, con fallback a
other. #renderiza el número formateado al locale. Las variantes anidan placeholders libremente.- Incluye siempre
otheren un bloque plural. Es el caso comodín, así que un bloque sin él no renderiza nada para cualquier cantidad que no liste.verbaly checkrompe el build por eso, y además avisa cuando un idioma necesita formas que a tu mensaje le faltan: el polaco llega afewymanydonde el inglés solo necesitaoneyother. Si un catálogo llega a tu app sin pasar por el build, desde un loader lazy o un CMS, el runtime avisa en la consola nombrando el mensaje en vez de renderizar una cadena vacía en silencio. Un bloque de género o de rol es distinto: dejarotherfuera ahí es tu decisión, y Verbaly no lo toca.
Escape-hatch ICU
¿Tienes strings ICU MessageFormat existentes, o necesitas su sintaxis exacta? Escribe ICU y Verbaly lo detecta automáticamente y lo parsea al mismo motor, con cero dependencias extra.
"{count, plural, one {# item} other {# items}}"
"{gender, select, male {he} female {she} other {they}}"
"{n, selectordinal, one {#st} two {#nd} few {#rd} other {#th}}"- Auto-detectado por mensaje: sin config, sin marcador. Mensajes nativos e ICU conviven en el mismo catálogo.
- Soporta
plural,select,selectordinal(reglas ordinales reales),{n, number/date/time, style},#,=N, anidado y quoting con'…'. - Prefiere la sintaxis nativa por defecto; usa ICU solo cuando lo necesites.
- Solo lo pagas si lo usas. Verbaly lee tus catálogos al construir, y el parser de ICU entra en tu aplicación solo cuando alguno de tus mensajes lo necesita. Son unos 544 bytes, y no hay nada que encender. El tiempo relativo funciona igual: otros 318 bytes que solo viajan cuando un mensaje los pide.
Escapes
| Escribes | Obtienes |
|---|---|
| {{ | { literal |
| }} | } literal |
| || | | literal dentro de variantes |
| ## | # literal dentro de variantes |
En mensajes rich (data-verbaly-rich o <Trans>) la entidad numérica { también muestra una llave literal: se decodifica después del parseo, así que nunca toca la sintaxis de placeholders.