Como automatizei a Internacionalização (i18n) no Next.js manipulando AST e usando LLMs (Open Source)
Fala, pessoal.
Durante o desenvolvimento de alguns projetos pessoais, bati de frente com uma das tarefas mais ingratas do desenvolvimento Front-end: Internacionalização (i18n).
O processo manual é um assassino de produtividade:
- Parar de codar a feature.
- Recortar a string hardcoded (
<p>Olá</p>). - Criar uma chave no arquivo
pt.json. - Criar a chave no
en.jsone traduzir (ou ir no Google Translate). - Voltar no código e substituir por
{t('chave')}.
Fazer isso para 5 telas é chato. Fazer para um sistema inteiro é simplesmente MORTE.
Como eu sou dev solo, eu simplesmente tinha preguiça para essa burocracia.
Decidi que a engenharia deveria trabalhar para mim. Publiquei o código de uma ferramenta que resolve isso: o @scopeact/autoi18n.
O Abismo entre o Regex e a AST (Abstract Syntax Tree)
A primeira ideia de todo mundo é: "Ah, faz um Regex que busca o que está entre as tags e troca".
Não faça isso.
Regex para manipular HTML/JSX é o caminho mais rápido para corromper seu código fonte. O Regex não entende contexto. Ele não sabe se aquele texto está dentro de um comentário, se é uma variável ou se é um conteúdo renderizável. (Para quem não conhece, vale ler a clássica resposta do StackOverflow sobre isso).
Para criar algo realmente confiável, eu precisei mergulhar na AST (Abstract Syntax Tree) do TypeScript usando a biblioteca ts-morph.
Como a mágica acontece:
- Scanner Sintático: O CLI mapeia o projeto e "enxerga" o código como uma árvore de objetos. Eu instruí o scanner a buscar especificamente nós do tipo
JsxText. Isso é cirúrgico: eu ignoro imports, lógicas deif/elsee atributos internos, pegando apenas o que o usuário realmente vê na tela. - O Agente de Extração (IA): Aqui está o diferencial. Em vez de gerar um hash (como
a7b2c), eu envio os textos para uma LLM (GPT-4o, Gemini, DeepSeek, etc). O prompt é desenhado para agir como um engenheiro de localização. Ele lê "Bem-vindo de volta, finalize seu cadastro" e sugere uma chave semântica:welcome_back_complete_registration. Isso mantém o código legível. - Tradução em Batch (LLM Agnostic): Enviar string por string seria lento e caro. Eu implementei uma lógica de lotes (chunks). A ferramenta é agnóstica a provedores; usei o padrão de API da OpenAI para suportar inclusive modelos locais via Ollama, o que é excelente para quem não quer gastar com API no começo.
- Reescrita In-place: O
ts-morphvolta na árvore sintática e substitui o nó de texto original por um{t('chave')}. Como estamos mexendo na estrutura da árvore e não no arquivo de texto bruto, o risco de quebrar a sintaxe do React é praticamente zero.
Por que usar IA para as Chaves?
Talvez você se pergunte: "Por que não usar a própria string como chave?".
O problema é que strings não seguem padrão. Se você tiver um parágrafo de 12 linhas, sua chave vira um demogorgon feio e imenso. Usando um agente de IA para gerar chaves semânticas baseadas no sentido da frase, o código fica muito mais legível.
Resultados e Open Source
O resultado final foi que consegui traduzir um projeto inteiro em cerca de 40 segundos. O custo? Zero usando Ollama.
Publiquei o código como um monorepo (CLI + Core) no GitHub. Ainda é uma v1, focada em extrair textos entre tags (JsxText), mas os próximos passos incluem extrair atributos (placeholders, alt-texts) e strings literais em funções de erro.
Se você quiser testar ou contribuir:
- NPM:
npx @scopeact/autoi18n init|npx @scopeact/autoi18n run - Repo: github.com/felipevetter/auto-i18n
Se alguém tiver experiência com manipulação de AST ou quiser dar uma força melhorando os prompts de sistema para evitar alucinações das LLMs, os PRs estão abertos.
O que acham dessa abordagem? IA no fluxo de build é o futuro ou estamos criando ferramentas demais?
Abs!