Guides
Message format
One small syntax, powered by native Intl underneath: plurals, gender and formatting without learning full ICU.
Interpolation
"Hola {name}" → t('saludo', { name: 'Aron' })Values format themselves by type: numbers via Intl.NumberFormat, dates via Intl.DateTimeFormat, strings as-is. A missing param shows the placeholder literally, so it's easy to spot and never a crash.
Formatters
Append :formatter (with optional /arg) to a param:
| Syntax | Result |
|---|---|
| {n:number} | Locale number: 1,234.56 / 1234,56 |
| {n:integer} | Rounded, no decimals |
| {n:percent} | 0.5 → 50% |
| {n:currency/EUR} | Currency with ISO code |
| {d:date/long} | dateStyle: short · medium · long · full |
| {d:time/short} | timeStyle variants |
Custom formatters plug in at instance creation. The full signature is (value, locale, arg?) => string, where locale is the active locale and arg is whatever follows the / in the placeholder:
createVerbaly({
formatters: { upper: (v) => String(v).toUpperCase() },
});
// "{word:upper}" → HOLARelative time, lists & units
Since 0.11.0 the format surface covers the rest of modern Intl, still with zero dependencies:
"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: pass aDateand the unit picks itself against now (Intl.RelativeTimeFormatwithnumeric: 'auto', so you get yesterday, not 1 day ago); pass a number with an explicit unit (relative/hour).list: arrays localize viaIntl.ListFormat, conjunction by default,/orfor disjunction,/unitfor unit lists. Each item auto-formats per locale.unit: any CLDR unit id (kilometer,megabyte,liter…) throughIntl.NumberFormat.- Unknown formats and invalid units warn once and fall back to
String(value), so nothing crashes at render time.
Plurals and selects: one syntax
"{count | =0: sin mensajes | one: un mensaje | other: # mensajes}"
"{gender | male: él | female: ella | other: elle}"- Numbers match
=Nexact values first, thenIntl.PluralRulescategories (zero one two few many other). - Strings match their variant key, falling back to
other. #renders the number, locale-formatted. Variants nest placeholders freely.
ICU escape-hatch
Have existing ICU MessageFormat strings, or need its exact syntax? Write ICU and Verbaly detects it automatically and parses it into the same engine, with zero extra dependencies.
"{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-detected per message: no config, no marker. Native and ICU messages coexist in the same catalog.
- Supports
plural,select,selectordinal(real ordinal rules),{n, number/date/time, style},#,=N, nesting and'…'quoting. - Prefer the native syntax by default; reach for ICU only when you need it.
Escapes
| Write | Get |
|---|---|
| {{ | Literal { |
| }} | Literal } |
| || | Literal | inside variants |
| ## | Literal # inside variants |