Mojibake Resolvido: Corrija Acentos Quebrados de Vez
Feito com Master Rules Claude v8.6
Leitura: ~9 min
TL;DR
- Mojibake acontece quando um texto certo em UTF-8 é lido com o charset errado (geralmente Windows-1252 ou ISO-8859-1) — é aí que "ç" vira "ç" e "ã" vira "ã".
- Sem agente ou LLM, dá pra resolver reabrindo o arquivo com o encoding certo no editor, importando CSV com UTF-8 explícito, ou rodando um script de duas linhas que reverte o dano.
- Com agente/LLM, a correção que não volta depois é uma regra fixa de projeto (ou global) proibindo charset implícito, com uma checagem automática rodando antes de qualquer entrega.
Nota Técnica: Scripts e comandos deste post têm fins exclusivamente educacionais. Teste sempre em uma cópia dos dados antes de aplicar qualquer correção de encoding em produção. O @CanalQb não se responsabiliza por perdas decorrentes do uso indevido.
Um app pode estar 100% em UTF-8 e ainda exibir "Configuração" na tela.
Isso é mojibake — texto certo sendo lido com o charset errado em algum ponto entre o arquivo, o banco e a tela.
No fim deste post tem o comando exato pra reverter o estrago já feito, e a regra que impede ele de voltar — mesmo trabalhando com IA.
O que é mojibake e por que ele acontece?
Mojibake é o nome técnico pra texto corrompido quando uma sequência de bytes codificada em um padrão — quase sempre UTF-8 — é decodificada usando outro padrão, quase sempre Windows-1252 ou ISO-8859-1. Cada caractere acentuado ocupa mais de um byte em UTF-8; lido byte a byte como Latin-1, ele vira dois ou três caracteres visíveis errados.
Em português, isso aparece o tempo todo porque quase toda palavra tem acento. O "ç" em UTF-8 é gravado como dois bytes: C3 A7. Se algum ponto do sistema lê esses dois bytes como se fossem dois caracteres separados de Windows-1252, o resultado na tela é "Ã" seguido de "§" — dois símbolos onde deveria ter um só. O mesmo vale pra "ã" (C3 A3, vira "ã"), "é" (C3 A9, vira "é"), e assim por diante pra cada letra acentuada do idioma.
O problema não é o texto em si — ele está certo, salvo como UTF-8 de verdade. O problema é que, em algum lugar do caminho entre onde o texto foi escrito e onde ele aparece na tela, alguém trocou o mapa de leitura. Aqui no @CanalQb, validamos isso em mais de uma dezena de apps: declarar UTF-8 no manifesto do Android ou no meta charset do HTML documenta a intenção, mas não obriga nada — se o código que lê o arquivo, o banco ou a resposta de rede não especificar o charset explicitamente, ele usa o padrão da plataforma, e aí o estrago já está feito.
Esse tipo de erro aparece com frequência em apps Android que leem strings.xml, JSON ou banco sem forçar o charset; sites PHP/MySQL com a conexão configurada em latin1; planilhas CSV importadas no Excel sem escolher UTF-8 manualmente; e arquivos editados uma vez num editor com encoding errado e salvos de novo por cima.
Como eu descubro se um texto está com mojibake?
Mojibake tem uma assinatura visual bem reconhecível: os caracteres "Ã", "â€" e "Â" aparecem em sequência com símbolos estranhos logo depois, exatamente onde deveria estar um acento comum. Uma tabela rápida de comparação resolve a maior parte das dúvidas na hora de diagnosticar.
| Caractere original | Aparece corrompido como |
|---|---|
| á | á |
| â | â |
| ã | ã |
| à | Ã |
| ç | ç |
| é | é |
| ê | ê |
| í | Ã |
| ó | ó |
| ô | ô |
| õ | õ |
| ú | ú |
| — (travessão) | â€" |
| " " (aspas curvas) | “ †|
Guarda essa tabela — ela sozinha resolve a maior parte dos diagnósticos sem precisar abrir nenhum debugger. Se o texto que você está vendo bate com algum desses padrões, o problema é encoding, não é "erro de digitação" nem "fonte quebrada".
Como resolver mojibake sem agente ou LLM?
Pra quem não trabalha com um agente de código, a correção mais rápida depende de onde o texto mora: em editor de texto, reabra o arquivo forçando o encoding UTF-8 e salve de novo sem BOM; em planilha, escolha UTF-8 manualmente na importação do CSV; e pra texto já salvo em outro lugar, um script de duas linhas reverte o dano na maioria dos casos.
- Editor de texto (VS Code, Notepad++, Sublime): use "Reopen with Encoding" → UTF-8 e confira se os acentos aparecem certos. Depois use "Save with Encoding" → UTF-8 (sem BOM) — salvar sem reabrir corretamente primeiro só reforça o erro.
- Planilha (Excel, Google Sheets): ao importar CSV, escolha explicitamente "UTF-8" no campo de codificação. Nunca deixe em "Detecção automática" ou "Ocidental (Windows-1252)" — essa dupla é a causa mais comum de mojibake em relatório financeiro e planilha de controle.
- Terminal (Mac/Linux, ou WSL no Windows): o comando iconv reconverte arquivos em lote sem precisar abrir nenhum editor. Veja o exemplo logo abaixo.
- Texto avulso já corrompido: um script curto reverte o dano pegando os bytes como Latin-1 e decodificando de novo como UTF-8. Funciona sem precisar reprocessar o arquivo inteiro.
# reconverte um arquivo de Windows-1252 para UTF-8 real
iconv -f WINDOWS-1252 -t UTF-8 arquivo.txt -o arquivo_corrigido.txt
texto_corrompido = "Configuração"
texto_corrigido = texto_corrompido.encode("windows-1252").decode("utf-8")
print(texto_corrigido) # Configuração
E o melhor: você não precisa escrever nada além dessas três linhas pra resolver o caso mais comum. Mas tem um porém — esse truque só funciona quando o dano foi de uma passada só. Se o texto passou pelo processo errado duas vezes (mojibake em cima de mojibake), a reversão simples não fecha; nesse caso, o caminho é ir na origem dos dados e corrigir a fonte, não o sintoma.
Como resolver mojibake usando um agente ou LLM?
A instrução mais comum — "aplica UTF-8" — não funciona porque não diz ao agente ONDE o charset está errado. O pedido certo mapeia o pipeline inteiro: arquivo de origem, ponto de leitura no código, e qualquer banco ou armazenamento pelo meio, pedindo confirmação com um exemplo real antes/depois.
Quando o agente responde "já resolvi, apliquei UTF-8" e o problema continua, geralmente ele mexeu numa camada só — trocou o encoding do arquivo fonte, por exemplo, sem tocar no ponto do código que lê esse arquivo em runtime, ou vice-versa. É preciso pedir uma varredura estruturada, não uma correção genérica.
Diagnostique mojibake (UTF-8 lido como Windows-1252) nesta ordem:
1. Confirme o encoding real dos arquivos-fonte em disco.
2. Liste todo ponto que converte bytes em texto sem charset explícito.
3. Verifique se o dado já foi salvo corrompido em banco/cache/preferências.
4. Prove a correção com uma string real, antes e depois.
Essa é a diferença entre um agente que "aplica UTF-8" no ar e um que resolve de verdade: ele mostra o byte, mostra o ponto exato do código, e prova com um exemplo real — não com a palavra dele.
Como transformar isso numa regra de projeto (ou regra global) para o agente nunca mais gerar mojibake?
A maioria dos agentes de código aceita um arquivo de regras persistente — CLAUDE.md, .cursorrules, AGENTS.md, ou o próprio system prompt — que vale pra todo o projeto ou pra toda sessão. Colar uma regra explícita de encoding ali evita que o mesmo erro volte em cada nova conversa.
REGRA DE ENCODING — NUNCA VIOLAR
1. Toda leitura ou escrita de texto (arquivo, banco, rede, clipboard) deve declarar
explicitamente UTF-8. Proibido usar charset padrão da plataforma/JVM/SO.
2. Nunca usar String(bytes) sem charset — sempre String(bytes, Charsets.UTF_8)
(ou equivalente na linguagem do projeto).
3. Todo arquivo de texto (.xml, .json, .csv, .properties) deve ser salvo como
UTF-8 sem BOM. Configurar o editor/IDE do projeto pra isso ser o padrão.
4. Antes de considerar uma tarefa concluída, rodar a checagem de mojibake
(ver regra de validação) em qualquer texto novo ou alterado.
5. Se um texto exibido contiver os padrões Ã, â€,  seguidos de caractere estranho,
tratar como bug de encoding, não como "acento errado" — a causa é sempre um
charset errado em algum ponto do pipeline.
Se a regra ficar dentro do repositório — em um CLAUDE.md na raiz do projeto, por exemplo — ela vale só pra esse projeto, ideal quando só um sistema específico tem histórico de mojibake. Se ficar nas instruções globais do seu agente, no perfil ou na configuração da conta, ela passa a valer pra qualquer projeto novo, o que faz mais sentido se você já bateu nesse problema mais de uma vez em contextos diferentes.
Como validar automaticamente que a regra está sendo seguida?
Regra escrita sem checagem é regra que se esquece. A validação eficiente é um padrão de busca simples — os pares de caracteres que só aparecem quando há mojibake — rodado antes de qualquer entrega de código ou commit, travando a entrega se encontrar uma correspondência.
import re
PADRAO_MOJIBAKE = re.compile(r'(Ã[€-¿]|â€[”"\x9d]|Â[€-¿])')
def tem_mojibake(texto: str) -> bool:
return bool(PADRAO_MOJIBAKE.search(texto))
Peça pro agente rodar esse tipo de checagem como último passo, sempre, e tratar qualquer resultado positivo como bloqueador — não como aviso. Em times com pipeline de CI, o mesmo padrão vira um pre-commit hook, barrando qualquer commit que introduza mojibake antes mesmo de chegar em revisão.
Aplicando o diagnóstico certo, a regra fixa e a checagem automática, o mojibake para de ser um problema recorrente e vira só mais um item no checklist de qualidade do projeto — resolvido uma vez, do jeito certo, na origem, não sempre no sintoma. Se você trabalha com encoding com frequência, vale manter esse post nos favoritos como referência rápida da tabela de assinaturas.
Perguntas Frequentes
O que causa o mojibake na prática?
Mojibake e problema de fonte tipográfica são a mesma coisa?
UTF-8 sem BOM é realmente necessário?
Dá pra corrigir mojibake sem saber programar?
Meu agente de IA diz que já aplicou UTF-8, mas o erro continua — o que fazer?
Mojibake pode corromper dados de forma irreversível?
Existe diferença entre mojibake e o caractere de substituição (�)?
Fontes e Referências
Bateu esse erro no seu projeto? Confira mais dicas de automação no canal @CanalQb no YouTube.