Framework

HTML puro

Sem framework? O Verbaly trata HTML puro como cidadão de primeira, algo que nenhuma outra ferramenta i18n com compilador faz. Marque elementos, chame bindDom, pronto.

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-verbalyChave cuja tradução vira o texto do elemento
data-verbaly-argsParams JSON compartilhados pelas traduções de texto e atributos
data-verbaly-attrMapa JSON de atributo → chave, ex. placeholder, title, aria-label. Desde 0.17.0: atributos URL (href, src…) são sanitizados contra esquemas inseguros; on*, style e srcdoc são bloqueados, então um catálogo não pode injetar scripts
data-verbaly-richOpt-in: renderiza os tags da mensagem como elementos reais (ver Rich text)
data-verbaly-linksMapa JSON de nome do link → href para links nomeados (ver Links nomeados)

Rich text

Por padrão as traduções renderizam via textContent, então os tags ficam literais. Marque o elemento com data-verbaly-rich e as mensagens com tags viram elementos reais:

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> -->

Uma chave por frase, então o tradutor vê a mensagem inteira e cada idioma mantém sua própria ordem de palavras. O modelo de segurança:

Links ficam fora da whitelist de propósito: um <a> sem atributos é inútil, e atributos nunca vêm das mensagens. Desde 0.11.0 você nomeia o link na mensagem e fornece o href pelo 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

Dois helpers cobrem o boilerplate que todo app repete, escolher o idioma inicial e lembrar a escolha do usuário:

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') },
});
bindDom(v);

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

Comportamento

Copiado para a área de transferência