PTC

Traduções do plugin do WordPress não estão aparecendo? Corrija traduções ausentes

Traduções ausentes após uma execução da PTC? Quatro verificações encontram quase todas as causas. Verifique se a string chegou à PTC, se o nome do arquivo .mo corresponde ao que o WordPress espera e se o text domain é consistente em todo o seu código. Este guia detalha cada verificação na ordem em que devem ser executadas.

A mesma ordem de diagnóstico funciona quer você tenha traduzido com a PTC (Private Translation Cloud), o GlotPress ou qualquer outra ferramenta baseada no gettext. Os modos de falha são inerentes ao pipeline de i18n do WordPress, não a um tradutor em particular.

Confirme se a string chegou à PTC

A primeira pergunta é se a string está no seu projeto da PTC. Se uma string não foi extraída para o seu arquivo .pot, a PTC nunca a viu. O arquivo .po não tem tradução para ela. O plugin em execução mostra o fallback do idioma de origem.

Como verificar:

  1. Abra a string afetada no plugin em execução e copie seu texto exato.
  2. Vá para o seu painel da PTC, abra a aba Translations e pesquise pela string.
  3. Se ela não estiver lá, a PTC nunca a recebeu.

A seguir estão três causas comuns.

Causa 1: a string está ausente do seu arquivo POT

O wp i18n make-pot extrai apenas strings dentro das funções de i18n reconhecidas. Isso significa __(), _e(), _n(), _x() e as variantes com escape, com o text domain correto. Strings dentro do domínio errado são ignoradas. Strings hardcoded fora de uma função de i18n são ignoradas.

Execute a extração novamente e verifique se a string agora está no .pot:

wp i18n make-pot . languages/my-plugin.pot --domain=my-plugin
grep "Save Changes" languages/my-plugin.pot

Se o grep retornar a string com um msgid, a extração está funcionando. Faça o upload do novo .pot para a PTC e traduza novamente. Se o grep não retornar nada, a string é hardcoded e não está envolvida em __(). Esse é o seu bug. Envolva a string e extraia novamente.

Causa 2: o texto não está envolvido em uma função gettext

Toda string traduzível no seu código precisa de um wrapper. Use __(), esc_html__(), _e(), _n() ou _x() com o text domain correto:

__( 'Hello, world!', 'your-plugin' );

Causa 3: as strings do JavaScript não foram marcadas como traduzíveis

Se o seu plugin incluir texto traduzível em JavaScript:

  1. No painel da PTC, vá para Configurações > Arquivos Monitorados.
  2. Edite o arquivo de recursos relevante e ative “Is this a WordPress project with localizable JavaScript?”

Isso diz à PTC para verificar os arquivos JavaScript em busca de strings traduzíveis. A PTC gera novamente as traduções e abre um novo merge request com os arquivos atualizados.

Em seguida, certifique-se de que o WordPress saiba onde carregar os arquivos de tradução .json que a PTC produziu. Chame o wp_set_script_translations() com o caminho correto:

// For plugins
wp_set_script_translations(
    'script-handle',
    'text-domain',
    plugin_dir_path( __FILE__ ) . 'languages'
);

// For themes
wp_set_script_translations(
    'script-handle',
    'text-domain',
    get_template_directory() . '/languages'
);

Isso diz ao WordPress para carregar os arquivos .json da pasta do seu plugin ou tema.

Confirme se o WordPress está carregando o seu arquivo MO

Se a string estiver na PTC e o arquivo .mo existir no diretório languages/ do seu plugin, mas o plugin renderizado ainda mostrar inglês, o WordPress está falhando ao carregar o .mo.

Diagnóstico 1: o locale do site está configurado corretamente? Vá para Configurações > Geral > Idioma do site no wp-admin e confirme se corresponde ao seu idioma de destino. Por exemplo, defina-o como “Español” para testar o espanhol. Se o site estiver em inglês, o seu .mo em espanhol nunca será carregado. Isso não é um bug.

Diagnóstico 2: o load_plugin_textdomain() está realmente em execução? Adicione uma linha de depuração temporária:

add_action( 'init', function() {
    $loaded = load_plugin_textdomain(
        'my-plugin',
        false,
        dirname( plugin_basename( __FILE__ ) ) . '/languages'
    );
    error_log( 'my-plugin textdomain loaded: ' . var_export( $loaded, true ) );
} );

Recarregue uma página e verifique o seu log de erros do PHP. loaded: true significa que o WordPress encontrou e carregou um arquivo .mo para o locale atual. loaded: false significa que não o fez. A causa geralmente é uma incompatibilidade no nome do arquivo (veja a próxima seção) ou um caminho de diretório incorreto.

Diagnóstico 3: o momento do hook está correto? O load_plugin_textdomain() deve ser executado no hook init. Esse é o hook canônico para que as traduções sejam aplicadas às strings exibidas durante o processamento normal da requisição.

Diagnóstico 4: as traduções da comunidade estão substituindo os seus arquivos empacotados? Por padrão, o WordPress prioriza os arquivos de tradução armazenados em /wp-content/languages/. Se o seu plugin ou tema tiver traduções fornecidas pela comunidade no WordPress.org, esses arquivos podem substituir os arquivos .mo empacotados com o seu projeto. Para evitar isso, use o filtro load_textdomain_mofile para forçar o carregamento do caminho do seu arquivo empacotado antes que o WordPress verifique o diretório global. Projetos com vários text domains (um plugin que incorpora outro plugin) precisam que cada domínio seja carregado separadamente. Cada domínio precisa de sua própria chamada load_plugin_textdomain() ou load_theme_textdomain().

Certifique-se de que o nome do arquivo MO corresponda ao padrão de busca do WordPress

A busca de arquivos .mo do WordPress segue uma convenção de nomenclatura estrita. Mesmo com um caractere incorreto, o WordPress fará o fallback silencioso para o inglês.

A convenção depende de onde você coloca o arquivo:

Localização Padrão Exemplo
/languages/ do plugin {text-domain}-{locale}.mo my-plugin-de_DE.mo
/languages/ do tema {locale}.mo de_DE.mo
Diretório global (/wp-content/languages/...) {text-domain}-{locale}.mo my-theme-de_DE.mo

Alguns exemplos práticos:

  • my-plugin-es_ES.mo para espanhol (Espanha)
  • my-plugin-fr_FR.mo para francês (França)
  • my-plugin-pt_BR.mo para português (Brasil)
  • my-plugin-zh_CN.mo para chinês simplificado
  • my-plugin-ja.mo para japonês (alguns locales não têm sufixo de região)

Erros comuns:

  • Prefixo de text domain incorreto. Se o cabeçalho Text Domain do seu plugin for my-plugin, mas o .mo se chamar myplugin-es_ES.mo (sem hífen), o WordPress não o encontrará. O prefixo deve corresponder exatamente ao valor Text Domain.
  • Código de locale incorreto. es.mo em vez de es_ES.mo. O WordPress usa códigos de locale regionais. es_ES, es_MX e es_AR são arquivos diferentes. Um código de idioma simples só funciona quando não existe um arquivo regional.
  • Hífen vs. sublinhado. Os códigos de locale usam sublinhado (es_ES), nunca hífen (es-ES). Isso confunde os desenvolvedores que copiam os códigos de locale de cabeçalhos Accept-Language do navegador ou fontes BCP 47, onde o hífen é o padrão.
  • Diretório incorreto. O cabeçalho Domain Path deve apontar para o diretório que contém os seus arquivos .mo. Se o Domain Path for /languages e os seus arquivos .mo estiverem em /lang/, o WordPress não os encontrará.

Verifique listando os arquivos que a PTC produziu em relação ao locale que o seu site está usando:

ls plugins/my-plugin/languages/
# my-plugin-es_ES.mo
# my-plugin-es_ES.po
# my-plugin-fr_FR.mo
# my-plugin-fr_FR.po

Se os nomes parecerem corretos, mas as traduções ainda não carregarem, execute o diagnóstico load_plugin_textdomain() acima para confirmar se o WordPress está encontrando o diretório.

Verifique se o seu text domain é consistente em todo o seu código

Este é o assassino silencioso. Cada chamada __(), _e(), _n() e _x() no seu código passa um text domain como seu último argumento. Se ao menos uma chamada passar o domínio errado, essa única string não será traduzida. Todas as outras strings no plugin funcionarão perfeitamente.

// Correct - matches the plugin's Text Domain
$correct = __( 'Save Changes', 'my-plugin' );

// Wrong - text domain typo; this string is never translated
$wrong = __( 'Save Changes', 'myplugin' );  // missing hyphen

// Wrong - copy-pasted from another plugin
$wrong = __( 'Save Changes', 'other-plugin' );

// Wrong - WordPress core domain; works for core strings but not yours
$wrong = __( 'Save Changes', 'default' );

Encontre inconsistências fazendo um grep na sua base de código:

grep -rE "__\(|_e\(|_n\(|_x\(" --include="*.php" .

Observe o último argumento de cada correspondência. Todos eles devem ser o text domain do seu plugin. Se você encontrar erros de digitação ou de copiar e colar, corrija-os e execute o wp i18n make-pot novamente para atualizar o .pot.

Para código JavaScript usando @wordpress/i18n, a mesma regra se aplica. O wp_set_script_translations() no PHP também deve passar o domínio correspondente:

wp_set_script_translations( 'my-plugin-editor', 'my-plugin', '...' );
//                                                ^^^^^^^^^^^
//                                                Must match the JS calls

Detecte os mesmos problemas antes que sejam publicados com o AI Visual QA

O ciclo de diagnóstico acima é reativo. Uma tradução está ausente, você sai em busca da causa. O AI Visual QA da PTC detecta os mesmos problemas antes que eles sejam publicados. Ele inspeciona o plugin renderizado em cada idioma de destino após cada atualização de tradução e relata o que está faltando ou errado.

Para uma string hardcoded em inglês fora de __() (Causa 1 acima), o AI Visual QA vê a string não traduzida no plugin renderizado. A PTC gera um prompt pronto para colar para o Cursor ou Claude Code para envolver a string em __(). Para uma incompatibilidade de text domain (a verificação da seção anterior), ele vê a string não traduzida quando outras strings na mesma tela estão traduzidas e relata a inconsistência.

Se você ainda não ativou o AI Visual QA, veja o tutorial de temas e plugins do WordPress para a configuração.

Quando as quatro verificações passam e as traduções ainda estão ausentes

Se você executou todas as quatro verificações e as traduções ainda não estão aparecendo, envie um e-mail para o suporte da PTC com:

  • O text domain do seu plugin.
  • Um dos nomes de arquivo .mo (por exemplo, my-plugin-es_ES.mo).
  • Uma captura de tela do painel da PTC mostrando a string afetada com a sua tradução.
  • A configuração de idioma do site em Configurações > Geral.

A maioria dos casos de “tradução ausente” se resume a uma das causas acima. Casos isolados (versões específicas do WordPress, resolução de locale do MultiSite, conflito com outro plugin de i18n) às vezes precisam de uma segunda análise.

Mantenha os lançamentos futuros sincronizados com a localização contínua

Assim que as suas traduções carregarem corretamente, configure o fluxo de trabalho de localização contínua para que os lançamentos futuros permaneçam sincronizados com as suas traduções — automaticamente, a cada push para a main.