Referencia
API del runtime
El core de verbaly pesa ~3 KB gzip con cero dependencias, y todo se construye sobre Intl nativo.
createVerbaly(options)
import { createVerbaly } from 'verbaly';
const v = createVerbaly({
locale: 'es',
fallback: ['en'],
messages: { es: { home: { title: 'Inicio' } } },
});| Opción | Tipo | Descripción |
|---|---|---|
| locale | string | Idioma inicial; por defecto navigator.language en el navegador |
| fallback | string | string[] | Cadena de fallback tras el narrowing BCP-47 (es-MX → es) |
| messages | object | Idioma → árbol; las claves anidadas se aplanan con puntos (home.title). Un string vacío cuenta como sin traducir y sigue el fallback, la misma regla que check |
| loaders | object | Catálogos lazy: idioma → () => import('./es.json'), cargados bajo demanda |
| formatters | object | Formatters custom {v:name} |
| onMissing | function | (key, locale): devuelve un string para sustituir; silencia el warn-once por defecto |
| onResolve | function | (info) en cada t(): key, locale, value y status (hit / fallback / miss). Alimenta los devtools |
Instancia
| Miembro | Descripción |
|---|---|
| t(key, params?) | Traduce; claves y params se verifican en tipos desde tus mensajes |
| t`...` | Tagged template: interpola texto fuente; el compilador lo mejora |
| t.id(key)`...` | Claves legibles opt-in: formatea el texto inline; el compilador lo reescribe a una llamada con clave |
| setLocale(locale) | Cambia el idioma y notifica a los suscriptores, auto-carga un catálogo lazy pendiente |
| loadLocale(locale) | Carga un catálogo lazy (narrowing BCP-47, deduplicado): haz await antes de setLocale para cambiar sin flash |
| addMessages(locale, tree) | Fusiona mensajes en runtime: la primitiva del lazy-loading |
| subscribe(fn) | Listener de cambios; devuelve unsubscribe |
| has(key) | La clave existe en la cadena actual |
| inspect(key) | Locale de origen (from) + texto fuente de una key (devtools/herramientas). El campo se renombró de locale en 0.17.0 (breaking) para alinearse con ResolveInfo.from |
| locale | Idioma actual (readonly) |
| locales | Idiomas cargados + cargables (readonly): alimenta un switcher desde una sola fuente de verdad |
| version | Contador de cambios que impulsa los adapters de frameworks |
Helpers de idioma
import { negotiateLocale, persistLocale, resolveLocale, resolveRequestLocale, switchLocale } from 'verbaly';
resolveLocale({ supported: ['en', 'es', 'pt'] }); // storage → navigator → fallback
persistLocale('es'); // localStorage + <html lang>
// server-side (0.16.0): match an Accept-Language header
negotiateLocale('es-PE,en;q=0.8', ['en', 'es']); // → 'es'
// per-request (0.17.0): cookie value → header → fallback
resolveRequestLocale({ supported: ['en', 'es'], cookie, header });
// client switch for SSR setups (0.18.0): catalog → locale → cookie + <html lang>
await switchLocale(instance, 'es');resolveLocale elige el idioma inicial (elección guardada, luego navigator.languages con narrowing BCP-47, luego fallback); persistLocale recuerda un cambio. Ambos son SSR-safe y aceptan un storageKey custom (false desactiva el storage). Ver HTML plano → Bootstrap de idioma para el patrón completo.
negotiateLocale(header, supported, fallback?) (0.16.0) es la contraparte del lado servidor: dale un header Accept-Language y tus locales y devuelve la mejor coincidencia (respeta los q-values, es-PE coincide con es, sin distinguir mayúsculas). Funciona con cualquier servidor; las integraciones de SvelteKit, Nuxt y Next.js la usan por debajo.
resolveRequestLocale(options) (0.17.0) toma toda la decisión por request en una sola llamada: primero el valor de una cookie guardada, luego el header Accept-Language, luego tu fallback. LOCALE_STORAGE_KEY exporta el nombre compartido (verbaly-locale) que usan el storage del browser y la cookie SSR.
switchLocale(instance, locale, options?) (0.18.0) es el cambio de idioma del lado cliente que comparten las integraciones SSR: carga el catálogo primero, luego cambia el locale, escribe la cookie verbaly-locale y actualiza el atributo lang. Es seguro llamarlo en el servidor (ahí no hace nada); @verbaly/sveltekit lo re-exporta.
Seguridad a nivel de tipos
v.t('home.title'); ✓
v.t('home.title', { x: 1 }); ✗ no params declared
v.t('nope'); ✗ unknown keyTypeScript parsea tus mensajes: FlatKeys aplana árboles anidados, ParamNames lee las apariciones de {param}, y TArgs exige los params exactamente cuando el mensaje los declara.
Exports de bajo nivel
¿Construyes herramientas sobre Verbaly? El paquete también exporta parse(message) (el AST del mensaje), flatten(tree) (árbol anidado → dot-keys), safeHref(href) (el guardián de esquemas inseguros detrás de los named links) y, desde 0.17.0, normalizeLink(link), el normalizador de links único que comparten todos los adapters, más el tipo RichLink. Son las mismas piezas que usa el compilador.