Inspetor de catálogos .mo do gettext
Um arquivo .mo é o que o msgfmt deixa ao compilar um .po, e é o arquivo que de fato vai para locale/<lang>/LC_MESSAGES/. Quando o .po se perde sobra um binário que ninguém consegue ler, embora a estrutura seja pequena: um número mágico, uma revisão, e as contagens e deslocamentos de duas tabelas de cadeias, mais uma tabela hash opcional que os leitores podem ignorar. Este inspetor percorre tudo isso e mostra o que existe lá dentro. O número mágico é 0x950412de e também a sua troca de bytes, 0xde120495: é assim que o arquivo declara em que ordem de bytes estão escritas as demais palavras, de modo que um catálogo compilado para uma máquina big-endian é lido aqui igual a um little-endian. As duas coisas que se escondem num .mo são bytes NUL embutidos, invisíveis num editor de texto e fáceis de errar: uma entrada com contexto guarda msgctxt, um byte 0x04 e depois o msgid numa única cadeia, e uma entrada plural guarda msgid e msgid_plural separados por um NUL, com as formas traduzidas unidas por NUL do outro lado. Aqui as duas são separadas, então o contexto ganha a sua própria coluna e as formas plurais aparecem numeradas. A entrada de metadados, aquela cujo msgid é vazio, é analisada em Project-Id-Version, Language, Content-Type, Plural-Forms e POT-Creation-Date, e todas as outras cadeias são decodificadas com a codificação que esse cabeçalho declara, e não com um palpite. Quando o cabeçalho falta ou mente, a página diz isso em vez de produzir texto ilegível em silêncio. A expressão de plural é analisada e avaliada para n = 0 a 20, então dá para ver qual forma cada contagem escolhe, e o número de formas de cada entrada é conferido contra nplurals: uma divergência é um defeito real que devolve a cadeia errada para algumas contagens. Também aponta entradas sem tradução, traduções idênticas ao msgid, um %s ou um {} que a tradução perdeu, uma tabela de originais fora de ordem (essa ordem é a que a busca binária dos leitores escritos em C usa) e uma tabela hash com menos posições do que entradas. Ele não reconstrói o .po e não julga a qualidade de uma tradução: apenas diz se o arquivo é sólido e coerente consigo mesmo.
Como usar
- Solte um arquivo .mo na caixa: o catálogo compilado de locale/<lang>/LC_MESSAGES/, ou qualquer coisa que o msgfmt tenha produzido.
- Leia primeiro a linha do cabeçalho: ordem de bytes, revisão, número de entradas e onde ficam de fato as duas tabelas de cadeias e a tabela hash.
- Confira a codificação na entrada de metadados. Todas as cadeias abaixo são decodificadas com ela, então um Content-Type errado é a primeira coisa a corrigir.
- Veja a tabela da regra de plural para n = 0 a 20 e compare o número de formas de cada entrada plural com nplurals.
- Passe os olhos pela lista de achados e use o filtro para chegar a um msgid, uma tradução ou um contexto na tabela de entradas.
Perguntas frequentes
- Por que o número mágico aparece com dois valores diferentes?
- Existe apenas um número mágico, 0x950412de, mas um .mo guarda cada palavra de 32 bits na ordem de bytes da máquina que o compilou, e o mágico é guardado do mesmo jeito. Um leitor carrega os quatro primeiros bytes das duas formas: se lidos como little-endian resultam em 0x950412de, o arquivo inteiro é little-endian; se resultam nisso lidos como big-endian, o arquivo inteiro é big-endian. Essa é toda a declaração de ordem de bytes, não há sinalizador em nenhum outro lugar, e é por isso que um catálogo compilado num equipamento big-endian continua funcionando num little-endian. Esta página mostra os quatro bytes crus ao lado da ordem que deduziu, para você conferir a dedução em vez de confiar nela.
- O que é o byte 0x04 dentro de alguns msgid?
- É como o msgctxt é guardado. O gettext não tem um campo separado para o contexto, então o msgfmt cola o contexto, um único byte 0x04 (o EOT do ASCII) e o msgid numa só cadeia, e o pgettext procura a cadeia combinada. Por isso duas entradas podem compartilhar o msgid "Open" e ainda assim serem entradas distintas: uma é "menu\x04Open" e a outra é "state\x04Open". Num editor ou num despejo ingênuo o separador é invisível e as duas parecem duplicadas. Este inspetor divide ali e dá ao contexto uma coluna própria, então as entradas que compartilham um msgid ficam lado a lado.
- Como as formas plurais são guardadas e com o que nplurals precisa bater?
- Do lado do original, uma entrada plural é msgid, um byte NUL e depois msgid_plural. Do lado da tradução são todas as formas unidas por bytes NUL. O cabeçalho decide quantas deveriam existir: Plural-Forms traz nplurals e uma expressão em n que devolve o índice da forma a usar. Se uma entrada tem menos formas do que nplurals promete, as contagens que selecionam o índice ausente não recebem nada e o gettext volta ao msgid ou ao msgid_plural sem tradução, apenas para alguns números, que é exatamente por que o defeito sobrevive aos testes. Esta página conta as formas de cada entrada plural e marca as que discordam do cabeçalho.
- O que acontece quando o cabeçalho Content-Type falta ou está errado?
- Nada no arquivo marca a própria codificação além desse cabeçalho, então o leitor precisa confiar nele. O gettext do Python recusa o catálogo de imediato: um charset=CHARSET não preenchido gera um erro de codificação desconhecida, e bytes inválidos na codificação declarada geram um erro de decodificação. Esta página é de propósito mais tolerante: recorre ao UTF-8, decodifica o que dá e diz qual das duas coisas aconteceu, porque em geral você abriu o arquivo justamente para descobrir por que um aplicativo mostrava lixo. Um catálogo sem entrada de metadados não tem codificação, idioma nem regra de plural; o gettext então trata as cadeias como ASCII e aplica a regra germânica n != 1.
- A ordem das entradas importa?
- Importa, e é o requisito que os geradores de .mo feitos à mão mais deixam passar. A especificação do gettext diz que as cadeias originais devem estar ordenadas por bytes, porque um leitor pode achar uma entrada com uma busca binária sobre a tabela de originais. A implementação em C faz exatamente isso quando não há uma tabela hash utilizável, então um catálogo fora de ordem falha em silêncio ao procurar algumas entradas, enquanto o Python, que monta um dicionário com o arquivo inteiro, lê tudo perfeitamente. É uma classe desagradável de defeito: funciona no seu script de teste e não no aplicativo. Esta página verifica a ordenação e informa quantos pares estão invertidos.
- Para que serve a tabela hash e posso ignorá-la?
- É um acelerador de busca opcional: o msgfmt escreve uma tabela hashpjw com cerca de um terço mais posições do que entradas e usa endereçamento aberto, de modo que um leitor consiga achar um msgid sem a busca binária. Leitores podem ignorá-la por completo, como o Python faz, e um catálogo com tamanho 0 é perfeitamente válido. O que não é válido é uma tabela sem mais posições do que entradas, já que o endereçamento aberto precisa de pelo menos uma livre; essa combinação indica que o arquivo foi escrito por algo que não entendia o formato, e por isso é relatado aqui. O tamanho e o deslocamento exibidos vêm direto das palavras do cabeçalho.
Ferramentas relacionadas
Inspetor de arquivos .class do Java
Analise um .class compilado no navegador: versão do arquivo e do Java, sinalizadores de acesso, pool de constantes, campos, métodos e dependências.
Inspetor de arquivos de fonte
Abra um .ttf, .otf ou .woff e leia o nome de família real, a contagem de glifos e caracteres, a versão, o texto da licença e as permissões de incorporação.
Inspector de Arquivos WAV
Solte um .wav e veja formato, canais, sample rate, bit depth, duração, todos os chunks RIFF e tags LIST/INFO embutidas — totalmente client-side.
Inspetor de modelos STL (volume, impressão 3D)
Solte um .stl e veja contagem de triângulos, bounding box, tamanho, volume, área, verificação de estanqueidade e se cabe nas mesas de impressoras 3D.
Visualizador de arquivos mbox
Divide um arquivo .mbox no navegador: limites de mensagem, cabeçalhos decodificados, estrutura MIME, tópicos e Message-ID duplicados. Nada é enviado.
Inspetor de ZIP
Solte um ZIP e veja cada arquivo dentro — tamanhos, conteúdo e download individual — sem desempacotar localmente.