Guias

Migrar do i18next

As duas ferramentas falam JSON, então é mais fácil do que parece: suas keys e traduções portam quase direto, os sufixos de plural se fundem em uma única mensagem e a troca de runtime é quase buscar-e-substituir. De quebra você solta ~20 KB de runtime.

O que mapeia com o quê

O modelo mental se transfere um a um, e a única coisa que muda é a sintaxe:

i18nextVerbaly
i18next.init({ … })npx verbaly init + one build plugin
t('inbox.title')t('inbox.title'): same call, keys now typed
{{name}}{name}
messages_one / messages_other{count | one: … | other: # …}
format: 'currency' (interpolation){price:currency/EUR} (native Intl)
i18next-browser-languagedetectorresolveLocale() + persistLocale()
i18next-http-backend (lazy load)per-locale code-splitting, built into the plugin
useTranslation() (react-i18next)useT() (@verbaly/react)
Trans componentTrans component: values / components map over
i18next.changeLanguage('es')await setLocale('es')
saveMissing, runtime fallbacksnpx verbaly check: the build fails instead

Mantenha suas keys: os catálogos portam quase direto

Os catálogos do Verbaly são JSON plano sem formato proprietário. Achate os grupos aninhados em keys com pontos e funda os sufixos _one/_other em uma única mensagem com variantes, e cada tradução existente sobrevive:

locales/en.json (i18next)
{
  "inbox": { "title": "Inbox" },
  "messages_one": "one message",
  "messages_other": "{{count}} messages"
}
locales/en.json (Verbaly)
{
  "inbox.title": "Inbox",
  "messages": "{count | one: one message | other: # messages}"
}

Namespaces (ns:key) viram parte da key com pontos (ns.key). O # dentro de uma variante renderiza o count já localizado, sem interpolação formattedCount à parte.

Troque o runtime

As keys existentes continuam funcionando via t('key', params), então os componentes migrados quase não mudam. Em React:

before (react-i18next)
import { useTranslation } from 'react-i18next';

const { t } = useTranslation();
t('inbox.title');
t('messages', { count });
after (@verbaly/react)
import { useT } from '@verbaly/react';

const t = useT();
t('inbox.title');
t('messages', { count });  // params now typed

O texto novo pula a cerimônia de keys: escreva como tagged template e deixe o compilador extrair, ou mantenha ids legíveis com t.id. Os adapters de Vue e Svelte seguem o mesmo padrão, e páginas de HTML puro podem fazer bind com data-verbaly.

src/app.tsx
t`Hola ${name}`;                    // key + types generated
t.id('inbox.title')`Inbox`;      // readable id, i18next-style

Detecção de idioma e carga lazy

O plugin detector e o backend HTTP desaparecem. resolveLocale lê o storage → navigator.languages → fallback (SSR-safe, com narrowing BCP-47), persistLocale guarda a escolha e sincroniza <html lang>, e setLocale carrega o chunk daquele idioma sob demanda:

src/main.ts
import { resolveLocale, persistLocale } from 'verbaly';
import { setLocale, getLocale } from 'virtual:verbaly';

await setLocale(resolveLocale({ supported: ['en', 'es', 'pt'] }));
persistLocale(getLocale());

Migre incrementalmente

Não precisa de big-bang: o runtime do Verbaly pesa ~3 KB, então as duas bibliotecas podem conviver enquanto você migra uma página ou namespace por vez. Uma ordem pragmática:

  1. npx verbaly init + o plugin de build, então o toolchain roda ao lado do i18next desde o dia um.
  2. Porte os catálogos: achate as keys, funda os sufixos de plural e reduza as chaves de interpolação de quatro para duas.
  3. Troque os hooks página por página (useTranslationuseT) e apague cada namespace do i18next quando esvaziar.
  4. Ligue o gate: npx verbaly check no CI, npx verbaly pseudo para caçar strings hardcoded que a migração deixou passar.
Copiado para a área de transferência