Ir para o conteúdo

Referência

API do runtime

O core do verbaly pesa ~3 KB gzip com zero dependências, e tudo se constrói sobre Intl nativo.

createVerbaly(options)

import { createVerbaly } from 'verbaly';

const v = createVerbaly({
  locale: 'es',
  fallback: ['en'],
  messages: { es: { home: { title: 'Inicio' } } },
});
OpçãoTipoDescrição
localestringIdioma inicial; por padrão navigator.language no navegador
fallbackstring | string[]Cadeia de fallback após o narrowing BCP-47 (es-MXes)
messagesobjectIdioma → árvore; as chaves aninhadas achatam com pontos (home.title). Uma string vazia conta como não traduzida e segue o fallback, a mesma regra do check
loadersobjectCatálogos lazy: locale → () => import('./es.json'), carregados a pedido. O do locale com que arrancas é pedido logo, e a UI atualiza quando chega
formattersobjectFormatters custom {v:name}
onMissingfunction(key, locale): retorne uma string para substituir; silencia o warn-once padrão
onResolvefunction(info) em cada t(): key, locale, value e status (hit / fallback / miss). Alimenta os devtools

Instância

MembroDescrição
t(key, params?)Traduz; as chaves e os params são verificados contra as tuas mensagens. Dados maus de catálogo nunca quebram o render e também não passam ao lado: um param que falta, um bloco plural sem caso geral, um marcador sem o seu argumento, um valor que nem sequer é texto, cada um avisa uma vez na consola nomeando a mensagem ou o caminho de onde veio
t`...`Tagged template: interpola texto fonte; o compilador o melhora
t.id(key)`...`Chaves legíveis opt-in: formata o texto inline; o compilador o reescreve para uma chamada com chave
setLocale(locale)Troca o idioma e notifica os assinantes, auto-carrega um catálogo lazy pendente
loadLocale(locale)Carrega um catálogo lazy (narrowing BCP-47, deduplicado): faça await antes de setLocale para trocar sem flash
addMessages(locale, tree)Mescla mensagens em runtime: a primitiva do lazy-loading
subscribe(fn)Listener de mudanças; retorna unsubscribe
has(key)A chave existe na cadeia atual
inspect(key)Locale de origem (from) + texto fonte de uma key (devtools/ferramentas)
localeIdioma atual (readonly)
localesIdiomas carregados + carregáveis (readonly): alimenta um switcher a partir de uma única fonte de verdade
versionContador de mudanças que impulsiona os adapters de frameworks

Helpers de idioma

import { localeDirection, localeFromPath, localeName, localePath, negotiateLocale, persistLocale, resolveLocale, resolveRequestLocale, switchLocale } from 'verbaly';

// which language is this page? a fact of the url, undefined when it carries no prefix
localeFromPath({ supported: ['en', 'es', 'pt'] }) ?? 'en';

// which language does this visitor want? url prefix → storage → navigator → fallback
resolveLocale({ supported: ['en', 'es', 'pt'] });
persistLocale('es');                             // localStorage + <html lang> + <html dir>

// server-side: match an Accept-Language header
negotiateLocale('es-PE,en;q=0.8', ['en', 'es']);   // → 'es'

// per-request: cookie value → header → fallback
resolveRequestLocale({ supported: ['en', 'es'], cookie, header });

// client switch for SSR setups: catalog → locale → cookie + <html lang> + <html dir>
await switchLocale(instance, 'es');

// language switchers: names and direction from Intl, no tables
localeName('es');        // → 'español'
localeName('de', 'en');  // → 'German'
localeDirection('ar');   // → 'rtl'

// pre-rendered sites: the same page in another language, for a switcher that navigates
localePath('pt', { supported: ['en', 'es', 'pt'], sourceLocale: 'en' });  // /es/docs → /pt/docs

localeFromPath e resolveLocale respondem a duas perguntas diferentes, e escolher a errada é o erro clássico. localeFromPath(options) pergunta em que idioma está esta página: lê o prefixo /{locale}/ e devolve undefined quando o url não leva nenhum, por isso num site com uma árvore por idioma escreves localeFromPath(...) ?? sourceLocale e nada pode contradizer o url. resolveLocale(options) pergunta que idioma quer este visitante: prefixo do url, depois a escolha guardada, depois navigator.languages com narrowing BCP-47, depois fallback (path: false desliga o url). Usa-a para decidir para onde mandar alguém, nunca para decidir o que uma página já diz. persistLocale lembra uma mudança. As três são seguras em SSR, as duas primeiras aceitam um base para um site servido a partir de uma subpasta, e as de armazenamento aceitam um storageKey próprio (false desativa-o). Vê HTML puro → Bootstrap de idioma para o padrão completo.

negotiateLocale(header, supported, fallback?) é a contraparte do lado do servidor: entregue a ela um header Accept-Language e seus locales e ela devolve a melhor correspondência (respeita os q-values, es-PE corresponde a es, sem diferenciar maiúsculas). Funciona com qualquer servidor; as integrações do SvelteKit, do Nuxt e do Next.js a usam por baixo.

resolveRequestLocale(options) toma a decisão inteira por request em uma só chamada: primeiro o valor de um cookie salvo, depois o header Accept-Language, depois seu fallback. LOCALE_STORAGE_KEY exporta o nome compartilhado (verbaly-locale) usado pelo storage do browser e pelo cookie SSR.

switchLocale(instance, locale, options?) é a troca de idioma do lado do cliente compartilhada pelas integrações SSR: carrega o catálogo primeiro, depois troca o locale, grava o cookie verbaly-locale e atualiza os atributos lang e dir. É seguro chamá-la no servidor (lá ela não faz nada); o @verbaly/sveltekit a re-exporta.

localeName(locale, displayIn?) e localeDirection(locale) alimentam um seletor de idioma sem tabelas fixas: nomes de idioma reais via Intl.DisplayNames (por padrão o nome no próprio idioma) e a direção de escrita de qualquer locale. Idiomas da direita para a esquerda não pedem trabalho extra: switchLocale, persistLocale, as integrações SSR e o verbaly render já mantêm o dir correto por conta própria.

Segurança em nível de tipos

editor
v.t('home.title');            
v.t('home.title', { x: 1 });  ✗ no params declared
v.t('nope');                  ✗ unknown key

O TypeScript parseia suas mensagens: FlatKeys achata árvores aninhadas, ParamNames lê as ocorrências de {param}, e TArgs exige os params exatamente quando a mensagem os declara.

Exports de baixo nível

Construindo ferramentas sobre o Verbaly? O pacote também exporta parse(message) (a AST da mensagem), parseTags(text) com RICH_TAGS (o tokenizador de texto rico e sua whitelist de tags, o que um renderer próprio precisa), flatten(tree) (árvore aninhada → keys com pontos), safeHref(href) e safeAttribute(name, value) (as proteções de URL e de atributos), e normalizeLink(link), o único normalizador de links que todos os adapters compartilham, mais o tipo RichLink. São as mesmas peças que o compilador usa.

Copiado para a área de transferência