Saltar al contenido

Integraciones

HTML plano

¿Sin framework? Verbaly trata el HTML plano como ciudadano de primera, algo que ninguna otra herramienta i18n con compilador hace. Marca elementos, llama bindDom, listo.

Uso

index.html
<h1 data-verbaly="home.title"></h1>
<p  data-verbaly="inbox" data-verbaly-args='{"count":3}'></p>
<input data-verbaly-attr='{"placeholder":"search.hint"}' />
main.ts
import { bindDom, createVerbaly } from 'verbaly';

const v = createVerbaly({ locale: 'es', messages });
const unbind = bindDom(v);   // render + observe

v.setLocale('en');            // every bound node re-renders

Atributos

AtributoPropósito
data-verbalyClave cuya traducción se vuelve el texto del elemento
data-verbaly-argsParams JSON compartidos por las traducciones de texto y atributos
data-verbaly-attrMapa JSON de atributo → clave, p. ej. placeholder, title, aria-label. Los atributos URL (href, src…) se sanitizan contra esquemas inseguros; on*, style y srcdoc se bloquean, así que un catálogo no puede inyectar scripts
data-verbaly-richOpt-in: renderiza los tags del mensaje como elementos reales (ver Rich text)
data-verbaly-linksMapa JSON de nombre de link → href para links nombrados (ver Links nombrados)

Rich text

Por defecto las traducciones renderizan vía textContent, así que los tags quedan literales. Marca el elemento con data-verbaly-rich y los mensajes con tags se vuelven elementos reales:

locales/en.json
{ "gate.title": "The build <em>gate</em>" }
index.html
<h3 data-verbaly="gate.title" data-verbaly-rich></h3>
<!-- renders: The build <em>gate</em> -->

Una clave por frase, así que el traductor ve el mensaje completo y cada idioma mantiene su propio orden de palabras. El modelo de seguridad:

Los links quedan fuera de la whitelist a propósito: un <a> sin atributos no sirve, y los atributos nunca salen de los mensajes. En su lugar nombras el link en el mensaje y provees el href desde el código:

locales/en.json
{ "cta": "Read the <docs>guide</docs> now" }
main.ts
bindDom(v, {
  richLinks: { docs: { href: '/docs', target: '_blank', rel: 'noopener' } },
});
// renders: Read the <a href="/docs" target="_blank" rel="noopener">guide</a> now
index.html: per-element override
<p data-verbaly="cta" data-verbaly-rich data-verbaly-links='{"docs":"/es/docs"}'></p>

Bootstrap de idioma

Dos helpers cubren el boilerplate que toda app repite, elegir el idioma inicial y recordar la elección del usuario:

main.ts
import { bindDom, createVerbaly, persistLocale, resolveLocale } from 'verbaly';

const v = createVerbaly({
  locale: resolveLocale({ supported: ['en', 'es', 'pt'] }),  // storage → navigator → fallback
  messages: { en },  // bundle only the source
  loaders: { es: () => import('./locales/es.json'), pt: () => import('./locales/pt.json') },
});  // the chosen locale's catalog is fetched for you
bindDom(v);

// on user switch:
await v.loadLocale('es');  // flash-free (setLocale alone also auto-loads)
v.setLocale('es');
persistLocale('es');  // localStorage + <html lang> + <html dir>

Comportamiento

Copiado en el portapapeles