Como traduzir temas e plugins?
Tweet |
Nas próximas linhas vamos tentar mostrar como “internacionalizar” um tema ou plugin – usarei daqui em diante o termo genérico “addon” para ambos.
O modo grosseiro
Se o addon que deseja traduzir tem suporte a tradução…
… as strings serão tratadas com as funções_e()
e __()
. Ou seja, o que você esperava que fosse assim:<h2>Plugin title</h2>
<h2><?php _e("Plugin title", "text_domain"); ?></h2>
text_domain"
é uma string definida pelo desenvolvedor para identificar o plugin no sistema de tradução e é definida pelas funções load_theme_textdomain()
e load_plugin_textdomain()
que associam o textdomain ao arquivo .mo, que é gerado a partir do catálogo PO.Deve haver um ou mais arquivos com extensão .PO incluídos no pacote ou, de preferência, um arquivo .POT – que nada mais é que um .PO apenas com as strings originais, sem tradução, para servir de base para criação dos arquivos .PO. Para editar esses catálogos (PO ou POT), você pode usar o poEdit que é grátis e simples de usar.
Nesse caso, você não deve modificar os arquivos do addon – a tradução acontecerá apenas no catálogo, que deverá ser salvo seguindo o padrão definido pelo WP:
textdomain + ‘-’ + código da linguagem + ‘.po’ -> no nosso exemplo seria assim -> text_domain-pt_BR.po
Ao finalizar a tradução, salve o catálogo. Neste momento o poEdit gera automaticamente um arquivo de mesmo nome com extensão .MO – esse é que será usado pelo WordPress, o .PO é apenas para nós, humanos, conseguirmos ler e editar as strings.
Se o arquivo text_domain-pt_BR.mo estiver presente no diretório informado ao declarar o textdomain, basta configurar a constante WP_LANG (em wp-config.php) para “pt_BR” e pronto, se tudo deu certo, o sistema aparecerá em português.
Mas você pode querer internacionalizar um addon que não oferece suporte à tradução…
Nesse caso teremos que fazer o que o desenvolvedor não fez, editando o código – portanto só é recomendado para quem tem alguma intimidade com o PHP.A primeira coisa é declarar o textdomain e informar a localização dos arquivos .MO, usando uma das funções citada acima. A linha abaixo pode ser inserida em qualquer parte do arquivo principal do plugin, ou do arquivo functions.php, se estamos traduzindo um tema
// para plugins: load_plugin_textdomain("mytextdomain", dirname(__FILE__)."/languages"); // para temas: load_theme_textdomain("mytextdomain", dirname(__FILE__)."/languages");
<?php _e('string', 'textdomain'); ?>
a função _e() imprime a string traduzida na tela
<?php $str = __('string', 'textdomain'); ?>
a função __() retorna a string traduzida sem imprimir
Vamos ver um trecho de código a ser traduzido, como exemplo:
<?php if(!empty($_POST['act'])) { ?><div class="updated fade"><p><?php if($_POST['act'] = 'remove') print deleteThing($_POST['mythings']) // função imaginária... ? "Your '{$_POST['mythings']}' was successfully removed." : "Your '{$_POST['mythings']}' could not be removed!"; if($_POST['act'] = 'edit') print editThing($_POST['mythings'])// função imaginária... ? "Your '{$_POST['mythings']}' was successfully edited." : "Your '{$_POST['mythings']}' could not be edited!"; } ?></p></div><?php ?> <h2>My things</h2> <div class="wrap"> <form action="<?php print $PHP_SELF; ?>" method="post"> <label>Your cool things: <select name="mythings"> <?php foreach($coolthings as $things) { ?> <option value="<?php print sanitize_title($things['thing_title']); ?>"><?php print $things['thing_title']; ?></option> <?php } ?> </select> </label> <p class="butts"> <input type="button" class="button auto"<?php if(count($coolthings) == 0) print ' disabled="disabled"'; ?> value="Edit" onclick=" this.form.act.value = 'edit'; this.form.submit();" /> <input class="auto button delete"<?php if(count($coolthings) == 0) print ' disabled="disabled"'; ?> value="<?php _e("Edit", "mythings"); ?>"type="button" value="Delete" onclick="if(!confirm('Do you really want to delete this thing?')) return; this.form.act.value = 'remove'; this.form.submit();" /> </p> <input type="hidden" name="act" /> </form> </div>
Veja abaixo o mesmo código, já com o suporte à internacionalização:
<?php// essa linha deve aparecer apenas uma vez, em qualquer lugar - fora // de funções (ou não, se você sabe quando executá-la) load_plugin_text_domain("mythings", dirname(__FILE__).'/languages'); // começamos usando __(), pois o valor está sendo atribuído à variável $msg, não impresso if(!empty($_POST['act'])) { if($_POST['act'] = 'remove') $msg = deleteThing($_POST['mythings']) // função imaginária... ? sprintf(__("Your '%s' was successfully removed.", "mythings"), $_POST['mythings']) : sprintf(__("Your '%s' could not be removed!", "mythings"), $_POST['mythings']); if($_POST['act'] = 'edit') $msg = editThing($_POST['mythings'])// função imaginária... ? sprintf(__("Your '%s' was successfully edited.", "mythings"), $_POST['mythings']) : sprintf(__("Your '%s' could not be edited!", "mythings"), $_POST['mythings']); ?> <div class="updated fade"> <p><?php print $msg; ?></p> </div> <?php } ?> <?php // para os valores que estavam escritos diretamente na parte HTML do documento, // usamos a função _e(), que imprime a tradução, sem precisar de echos ou prints ?> <h2><?php _e("My things", "mythings"); ?></h2> <div class="wrap"> <form action="<?php print $PHP_SELF; ?>" method="post"> <label><?php _e("Your cool things:", "mythings"); ?> <select name="mythings"> <?php foreach($coolthings as $things) { ?> <option value="<?php print sanitize_title($things['thing_title']); ?>"><?php print $things['thing_title']; ?></option> <?php } ?> </select> </label> <p class="butts"> <input type="button" class="button auto"<?php if(count($coolthings) == 0) print ' disabled="disabled"'; ?> value="<?php _e("Edit", "mythings"); ?>" onclick=" this.form.act.value = 'edit'; this.form.submit();" /> <input class="auto button delete"<?php if(count($coolthings) == 0) print ' disabled="disabled"'; ?> type="button" value="<?php _e("Delete", "mythings"); ?>" onclick="if(!confirm('<?php _e("Do you really want to delete this thing?", "mythings"); ?>')) return; this.form.act.value = 'remove'; this.form.submit();" /> </p> <input type="hidden" name="act" /> </form> </div>
Não esqueça coisas que podem parecer detalhes, como rótulos dos botões, texto de alerts e conffirms Javascript, etc.
Bem, se não havia suporte… não existe nenhum arquivo .POT ou .PO…
Você pode usar o já citado poEdit para criá-lo ou copiar o texto abaixo para um arquivo de texto:msgid "" msgstr "" "Project-Id-Version: n" "Report-Msgid-Bugs-To: n" "POT-Creation-Date: n" "PO-Revision-Date: n" "Last-Translator: seu nome <seu@email.com>n" "Language-Team: n" "MIME-Version: 1.0n" "Content-Type: text/plain; charset=UTF-8n" "Content-Transfer-Encoding: 8bitn" "X-Poedit-KeywordsList: __;_en" "X-Poedit-Basepath: .n" "X-Poedit-SearchPath-0: .n"
Clique em Ok e inicie sua tradução. Ao terminar, salve o arquivo e saia. Você verá que o arquivo mythings-pt_BR.mo foi gerado. Coloque este arquivo no diretório que associamos ao nosso textdomain (./languages). Pronto!
Postar um comentário