Desenvolvimento

28 jun, 2011

Implementando suporte a tradução com GetText + Google Translate API

Publicidade

Veremos como dar suporte a tradução de um software escrito em python com GNUGetText.

Explicação sobre o Gettext e requerimentos

O GNUGettext, é uma biblioteca disponível em várias linguagens que
permite a tradução de programas a partir de arquivos binários. Sua
utilização é muito simples e ao longo deste artigo, criaremos um script
para tradução com a Google Translate API, agilizando a tradução.

Para maiores informações sobre o Gettext, visite a página do projeto:

Requerimentos:

  • gettext – (isso pode variar de acordo com a linguagem, no python vem por padrão)
  • pygettext – (um utilitário para vasculhar o código Python e encontrar as strings isoladas)
  • msgfmt – (converte os arquivos gerados pelo pygettext para binários)

Com tudo certo, vamos ao código

Isolando strings no código:

Para que o gettext funcione, é preciso isolar as strings no código python:

#!/usr/bin/python
# importing the gettext library
import gettext

# Defining the translate file
SOURCE_FILE_TRADUCTION='messages'

# Defining the translate directory
LOCALE_DIR='locale'

# Start gettext
language = gettext.translation(SOURCE_FILE_TRADUCTION,LOCALE_DIR,languages=["pt-br"])
language.install()

# Alias the underscore to translate
_ = language.gettext

# Code
print _("Hello World")

Aqui isolamos as strings com _(), e agora iremos gerar o arquivo .po com o pygettext:

user@localhost:~> pygettext -o test.po test.py

Eis o arquivo de tradução:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR , YEAR.
#

msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSIONn"
"POT-Creation-Date: 2011-05-10 09:18+BRTn"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONEn"
"Last-Translator: FULL NAME n"
"Language-Team: LANGUAGE n"
"MIME-Version: 1.0n"
"Content-Type: text/plain; charset=CHARSETn"
"Content-Transfer-Encoding: ENCODINGn"
"Generated-By: pygettext.py 1.5n"

#: test.py:10
msgid "Hello World"
msgstr ""

Obs.: É essencial preencher o cabeçalho, pois a frente teremos problemas na conversão para binário.

Enfim, agora podemos traduzir, mas porque não usar o Google?.

Google Translate API + Gettext

Agora creio que é a parte mais legal, automatizar a tradução.

Sinceramente, confesso que o script pode conter alguns erros,
principalmente se a string isolada contem caracteres especiais, como %,<,>, entre outros.Esse script funcionou bem para traduções de texto puro.

Aceito sugestões de melhorias 🙂


#!/bin/bash

#############
# Author: Ramon Medeiros @ Viva o Linux
##############

# Line break

ORI_IFS=$IFS
IFS=
n'

# Set the language to be translated
LANG_FROM=en
LANG_TO=pt

# Google Translate API Key
KEY=

# Translated dir
mkdir TRANSLATED_FILES

for FILE in `ls *.po`; do
# Start translation for .po files
for LINE in `cat $FILE`; do

if ! [ "$(echo $LINE | grep -o '^msgstr')" = "msgstr" -o "$(echo $LINE | grep -o '^msgid')" = "msgid" ]; then
echo "$LINE" >> TRANSLATED_FILES/$FILE
fi

if [ "$(echo $LINE | grep -o '^msgid')" = "msgid" ]; then
echo $LINE >> TRANSLATED_FILES/$FILE

# Blank space and % treatment

TEXT=$(echo $LINE | cut -d'"' -f 2)
TEXT=$(echo $TEXT | sed 's/%/%25/g')
TEXT=$(echo $TEXT | sed 's/ /%20/g')

# Using the Google Translate API
OUTPUT=$(GET "https://www.googleapis.com/language/translate/v2?key=$KEY&source=$LANG_FROM&target=$LANG_TO&q=$TEXT" |
grep translatedText |
sed 's/translatedText": "//g' |
sed 's/"//g' |
sed 's/^ //g' |
sed 's/% / %/g'
)
echo -e "msgstr "$OUTPUT"n" >> TRANSLATED_FILES/$FILE
fi
done
done

# Line break treatment
IFS=$ORI_IFS

Para pegar sua key, vá em

Apenas uma coisa, o limite diário de caracteres é de 100.000 =/

Com esse script, que deve ser rodado na mesma pasta onde ficam os
arquivos .po, a pasta TRANSLATED_FILES, será criada com os arquivos
traduzidos.

Finalizando a tradução

Com os arquivos traduzidos, vamos convertê-los em binários!

user@localhost:~> msgfmt -o test.mo test.po

Caso você tenha especificado apenas locale no código, terá de criar as seguintes pastas:

user@localhost:~> mkdir -p locale/$LANG/LC_MESSAGES

Agora, basta colocar o arquivo .mo na pasta LC_MESSAGES, criar a pasta
$LANG com a língua passada no código e pronto. Seja feliz com seu
programa traduzido. 🙂

Agradecimentos especiais ao dono do tópico:

n'\u003Cbr \u002F\u003E\u003Cbr \u002F\u003E# Set the language to be translated\u003Cbr \u002F\u003ELANG_FROM=en\u003Cbr \u002F\u003ELANG_TO=pt\u003Cbr \u002F\u003E\u003Cbr \u002F\u003E# Google Translate API Key\u003Cbr \u002F\u003EKEY=\u003Cbr \u002F\u003E\u003Cbr \u002F\u003E# Translated dir\u003Cbr \u002F\u003Emkdir TRANSLATED_FILES\u003Cbr \u002F\u003E\u003Cbr \u002F\u003Efor FILE in `ls *.po`; do\u003Cbr \u002F\u003E # Start translation for .po files\u003Cbr \u002F\u003E for LINE in `cat $FILE`; do\u003Cbr \u002F\u003E\u003Cbr \u002F\u003E if ! [ \"$(echo $LINE | grep -o '^msgstr')\" = \"msgstr\" -o \"$(echo $LINE | grep -o '^msgid')\" = \"msgid\" ]; then\u003Cbr \u002F\u003E echo \"$LINE\" >> TRANSLATED_FILES\u002F$FILE\u003Cbr \u002F\u003E fi\u003Cbr \u002F\u003E\u003Cbr \u002F\u003E if [ \"$(echo $LINE | grep -o '^msgid')\" = \"msgid\" ]; then\u003Cbr \u002F\u003E echo $LINE >> TRANSLATED_FILES\u002F$FILE\u003Cbr \u002F\u003E\u003Cbr \u002F\u003E # Blank space and % treatment\u003Cbr \u002F\u003E\u003Cbr \u002F\u003E TEXT=$(echo $LINE | cut -d'\"' -f 2)\u003Cbr \u002F\u003E TEXT=$(echo $TEXT | sed 's\u002F%\u002F%25\u002Fg')\u003Cbr \u002F\u003E TEXT=$(echo $TEXT | sed 's\u002F \u002F%20\u002Fg')\u003Cbr \u002F\u003E\u003Cbr \u002F\u003E # Using the Google Translate API\u003Cbr \u002F\u003E OUTPUT=$(GET \"https:\u002F\u002Fwww.googleapis.com\u002Flanguage\u002Ftranslate\u002Fv2?key=$KEY&source=$LANG_FROM&target=$LANG_TO&q=$TEXT\" |\u003Cbr \u002F\u003E grep translatedText |\u003Cbr \u002F\u003E sed 's\u002FtranslatedText\": \"\u002F\u002Fg' |\u003Cbr \u002F\u003E sed 's\u002F\"\u002F\u002Fg' |\u003Cbr \u002F\u003E sed 's\u002F^ \u002F\u002Fg' |\u003Cbr \u002F\u003E sed 's\u002F% \u002F %\u002Fg'\u003Cbr \u002F\u003E )\u003Cbr \u002F\u003E echo -e \"msgstr \"$OUTPUT\"n\" >> TRANSLATED_FILES\u002F$FILE\u003Cbr \u002F\u003E fi\u003Cbr \u002F\u003E done\u003Cbr \u002F\u003Edone\u003Cbr \u002F\u003E\u003Cbr \u002F\u003E# Line break treatment\u003Cbr \u002F\u003EIFS=$ORI_IFS\u003C\u002Fspan\u003E \u003C\u002Fpre\u003E\n\u003Cp\u003E\nPara pegar sua key, vá em\u003C\u002Fp\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\"https:\u002F\u002Fcode.google.com\u002Fapis\u002Fconsole\u002F\"\u003Ehttps:\u002F\u002Fcode.google.com\u002Fapis\u002Fconsole\u002F\u003C\u002Fa\u003E\u003C\u002Fli\u003E\n\u003C\u002Ful\u003E\n\u003Cp\u003E\nApenas uma coisa, o limite diário de caracteres é de 100.000 =\u002F\u003C\u002Fp\u003E\n\u003Cp\u003E\nCom esse script, que deve ser rodado na mesma pasta onde ficam os\u003Cbr \u002F\u003E\narquivos .po, a pasta TRANSLATED_FILES, será criada com os arquivos\u003Cbr \u002F\u003E\ntraduzidos.\u003C\u002Fp\u003E\n\u003Ch4\u003EFinalizando a tradução\u003C\u002Fh4\u003E\n\u003Cp\u003E\nCom os arquivos traduzidos, vamos convertê-los em binários!\u003C\u002Fp\u003E\n\u003Cp\u003E\u003Cstrong\u003Euser@localhost:~> msgfmt -o test.mo test.po\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\n\u003Cp\u003E\nCaso você tenha especificado apenas locale no código, terá de criar as seguintes pastas:\u003C\u002Fp\u003E\n\u003Cp\u003E\u003Cstrong\u003Euser@localhost:~> mkdir -p locale\u002F$LANG\u002FLC_MESSAGES\u003C\u002Fstrong\u003E\u003C\u002Fp\u003E\n\u003Cp\u003E\nAgora, basta colocar o arquivo .mo na pasta LC_MESSAGES, criar a pasta\u003Cbr \u002F\u003E\n$LANG com a língua passada no código e pronto. Seja feliz com seu\u003Cbr \u002F\u003E\nprograma traduzido. 🙂\u003C\u002Fp\u003E\n\u003Cp\u003E\nAgradecimentos especiais ao dono do tópico:\u003C\u002Fp\u003E\n\u003Cul\u003E\n\u003Cli\u003E\n\u003Ca href=\"http:\u002F\u002Fwww.vivaolinux.com.br\u002Fdica\u002FInternacionalizacao-dos-programas-em-Python\"\u003E\u003Cbr \u002F\u003E\nInternacionalização dos programas em Python\u003C\u002Fa\u003E\n\u003C\u002Fli\u003E\n\u003C\u002Ful\u003E\n","excerpt":"","link":"https:\u002F\u002Fimasters.com.br\u002Fdesenvolvimento\u002Fimplementando-suporte-a-traducao-com-gettext-google-translate-api","date":"28 jun, 2011","thumbnail":"","externalMention":null,"author":{"id":8543,"thumbnail":"https:\u002F\u002Fsecure.gravatar.com\u002Favatar\u002F18964e9a56348e4001a9f2db0ecfd80b?s=96&d=mm&r=g","name":"Ramon Medeiros","description":"cursa Segurança de Informação na FATEC de Americana (SP). É técnico em informática pelo Centro Municipal Osmar Passareli Silveira, em Paulinia (SP). Primeiro colocado nas Olimpíadas de Algorítimos, em São Paulo, em 2008 e 2009. É estagiário no Linux Technology Center da IBM. Como programador em python, atua em um projeto que cria Ferramentas para instalação de distribuições Linux na arquitetura PowerPC.","slug":"ramon_nunes_medeiros","url":"https:\u002F\u002Fimasters.com.br\u002Fperfil\u002Framon_nunes_medeiros","registered":"2011-06-21 19:23:44","social":{"linkedin":null,"youtube":null,"facebook":"","twitter":"","instagram":null,"github":null,"url":"","mail":"ramon.rnm@gmail.com"},"articles_count":1,"views_count":100,"certifications":null,"conquests":null,"office":null,"articles":[]},"categories":[{"title":"Desenvolvimento","slug":"desenvolvimento","id":7234,"link":"https:\u002F\u002Fimasters.com.br\u002Fdesenvolvimento"},{"title":"DevSecOps","slug":"devsecops","id":1,"link":"https:\u002F\u002Fimasters.com.br\u002Fdevsecops"}],"tags":[{"title":"Linux","slug":"linux","id":7237,"link":"https:\u002F\u002Fimasters.com.br\u002Flinux"}],"seo":{"open_graph":{"title":"Implementando suporte a tradução com GetText + Google Translate API - iMasters - We are Developers","description":"","type":"article","locale":"pt_BR","site_name":"iMasters - We are Developers","image":false,"modified_time":"2018-05-24T01:35:09-03:00","published_time":"2011-06-28T10:00:00-03:00"},"twitter":{"title":"Implementando suporte a tradução com GetText + Google Translate API - iMasters - We are Developers","description":"","type":"summary_large_image","image":false}},"articleSocial":{"facebook":"https:\u002F\u002Fwww.facebook.com\u002Fsharer?u=https:\u002F\u002Fimasters.com.br\u002Fdesenvolvimento\u002Fimplementando-suporte-a-traducao-com-gettext-google-translate-api","twitter":"https:\u002F\u002Ftwitter.com\u002Fshare?url=https:\u002F\u002Fimasters.com.br\u002Fdesenvolvimento\u002Fimplementando-suporte-a-traducao-com-gettext-google-translate-api","linkedin":"https:\u002F\u002Fwww.linkedin.com\u002FshareArticle?url=https:\u002F\u002Fimasters.com.br\u002Fdesenvolvimento\u002Fimplementando-suporte-a-traducao-com-gettext-google-translate-api"},"type":"post","articleViews":100}},"author":{"success":false,"isFetchingPagination":false,"maxPages":0,"page":1,"data":{}},"category":{"success":false,"data":{}},"categoryArticles":{"success":false,"isFetchingPagination":false,"maxPages":0,"page":1,"data":{}},"categoryMostRead":{"success":false,"data":{}},"home":{"success":false,"featured":[],"options":{"homeProducts":[]},"allCategories":{},"featuredArticles":{},"magazines":{"data":[]},"tv":{},"forums":[],"authorsRanking":{},"events":{},"certificatedUsers":[],"news":[]},"page":{"success":false,"data":{}},"magazine":{"success":false,"magazines":[]},"schedule":{"success":false,"data":{}},"searchResult":{"success":false,"totalPosts":0,"totalPage":0,"currentPage":1,"posts":[],"term":"","orderBy":"recents","currentFilter":"articles","isLoading":true,"isLoadingPagination":false},"singleNews":{"success":false,"data":{}},"listNews":{"success":false,"isFetchingPagination":false,"maxPages":0,"page":1,"data":[]},"sponsors":{"success":true,"data":[]},"header":{"success":true,"menus":{"main":[{"ID":138755,"order":1,"parent":0,"title":"Back-End","url":"https:\u002F\u002Fimasters.com.br\u002Fback-end","attr":"package","target":"","classes":"package","xfn":"","description":"Tecnologias utilizadas no backend da aplicação","object_id":7158,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":138756,"order":2,"parent":0,"title":"Mobile","url":"https:\u002F\u002Fimasters.com.br\u002Fmobile","attr":"package","target":"","classes":"package","xfn":"","description":"Conteúdos sobre Desenvolvimento Mobile nas plataformas iOS (iPhone e iPad) e Android.","object_id":4255,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":139476,"order":3,"parent":0,"title":"Front End","url":"https:\u002F\u002Fimasters.com.br\u002Ffront-end","attr":"package","target":"","classes":"package","xfn":"","description":"Conteúdos sobre HTML5, CSS3, Javascript, JQuery, Web Standards e SEO.","object_id":7304,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":138764,"order":4,"parent":0,"title":"DevSecOps","url":"https:\u002F\u002Fimasters.com.br\u002Fdevsecops","attr":"package","target":"","classes":"package","xfn":"","description":"","object_id":1,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":139204,"order":5,"parent":0,"title":"Design & UX","url":"https:\u002F\u002Fimasters.com.br\u002Fdesign-ux","attr":"package","target":"","classes":"package","xfn":"","description":"Conteúdos sobre User Experience, Arquitetura de Informação, Usabilidade, Acessibilidade, Design Responsivo, Teoria do Design e Photoshop.","object_id":7252,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":138759,"order":6,"parent":0,"title":"Data","url":"https:\u002F\u002Fimasters.com.br\u002Fdata","attr":"package","target":"","classes":"package","xfn":"","description":"Conteúdos sobre Banco de Dados Oracle, MySQL, SQL Server, MongoDB, DB2 e Postgre SQL, sobre BI e análise de dados.","object_id":16,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":138758,"order":7,"parent":0,"title":"APIs e Microsserviços","url":"https:\u002F\u002Fimasters.com.br\u002Fapis-microsservicos","attr":"package","target":"","classes":"package","xfn":"","description":"Dicas e tutoriais sobre APIs públicas como Facebook, Twitter, PayPal, Buscapé, Google, etc e arquitetura de microsserviços, com códigos de exemplo, vídeos, cursos.","object_id":4257,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]}],"secondary":[{"ID":138752,"order":1,"parent":0,"title":"Fórum iMasters","url":"https:\u002F\u002Fforum.imasters.com.br\u002F","attr":"","target":"_blank","classes":"","xfn":"","description":"","object_id":138752,"object":"custom","type":"custom","type_label":"Link personalizado","children":[]},{"ID":139067,"order":2,"parent":0,"title":"Portal E-Commerce Brasil","url":"http:\u002F\u002Fwww.ecommercebrasil.com.br","attr":"","target":"","classes":"","xfn":"","description":"","object_id":139067,"object":"custom","type":"custom","type_label":"Link personalizado","children":[]},{"ID":156289,"order":3,"parent":0,"title":"iMasters Business","url":"http:\u002F\u002Fbusiness.imasters.com.br","attr":"","target":"","classes":"","xfn":"","description":"","object_id":156289,"object":"custom","type":"custom","type_label":"Link personalizado","children":[]}]}},"webinar":{"success":false,"data":{}},"webinars":{"success":false,"isFetchingPagination":false,"maxPages":0,"page":1,"data":{"next":[],"prev":[]}},"tv":{"sectionNameLeft":{"small":"Vídeos","large":"iMasters TV"},"itemsLeft":[{"text":"Em Destaque","slug":"recents"},{"text":"Mais Vistos","slug":"most-viewed"}],"sectionNameRight":{"small":"","large":""},"itemsRight":[{"text":"Mais Recentes","slug":"recents"},{"text":"7Masters","slug":"7-masters"},{"text":"PHP Experience","slug":"php-experience"},{"text":"Android DevConference","slug":"android-devconference"},{"text":"Busca","slug":"search"}],"currentVideo":"recents","currentListVideo":"recents"}} window.__SERVER_VARS__ = {"applicationRestUrl":"https:\u002F\u002Fadmin.imasters.com.br\u002Fwp-json","applicationBaseUrl":"https:\u002F\u002Fadmin.imasters.com.br"}n'

# Set the language to be translated
LANG_FROM=en
LANG_TO=pt

# Google Translate API Key
KEY=

# Translated dir
mkdir TRANSLATED_FILES

for FILE in `ls *.po`; do
# Start translation for .po files
for LINE in `cat $FILE`; do

if ! [ "$(echo $LINE | grep -o '^msgstr')" = "msgstr" -o "$(echo $LINE | grep -o '^msgid')" = "msgid" ]; then
echo "$LINE" >> TRANSLATED_FILES/$FILE
fi

if [ "$(echo $LINE | grep -o '^msgid')" = "msgid" ]; then
echo $LINE >> TRANSLATED_FILES/$FILE

# Blank space and % treatment

TEXT=$(echo $LINE | cut -d'"' -f 2)
TEXT=$(echo $TEXT | sed 's/%/%25/g')
TEXT=$(echo $TEXT | sed 's/ /%20/g')

# Using the Google Translate API
OUTPUT=$(GET "https://www.googleapis.com/language/translate/v2?key=$KEY&source=$LANG_FROM&target=$LANG_TO&q=$TEXT" |
grep translatedText |
sed 's/translatedText": "//g' |
sed 's/"//g' |
sed 's/^ //g' |
sed 's/% / %/g'
)
echo -e "msgstr "$OUTPUT"n" >> TRANSLATED_FILES/$FILE
fi
done
done

# Line break treatment
IFS=$ORI_IFS

Para pegar sua key, vá em

Apenas uma coisa, o limite diário de caracteres é de 100.000 =/

Com esse script, que deve ser rodado na mesma pasta onde ficam os
arquivos .po, a pasta TRANSLATED_FILES, será criada com os arquivos
traduzidos.

Finalizando a tradução

Com os arquivos traduzidos, vamos convertê-los em binários!

user@localhost:~> msgfmt -o test.mo test.po

Caso você tenha especificado apenas locale no código, terá de criar as seguintes pastas:

user@localhost:~> mkdir -p locale/$LANG/LC_MESSAGES

Agora, basta colocar o arquivo .mo na pasta LC_MESSAGES, criar a pasta
$LANG com a língua passada no código e pronto. Seja feliz com seu
programa traduzido. 🙂

Agradecimentos especiais ao dono do tópico:

De 0 a 10, o quanto você recomendaria este artigo para um amigo?

Ramon Medeiros

edit1 Artigo(s)

cursa Segurança de Informação na FATEC de Americana (SP). É técnico em informática pelo Centro Municipal Osmar Passareli Silveira, em Paulinia (SP). Primeiro colocado nas Olimpíadas de Algorítimos, em São Paulo, em 2008 e 2009. É estagiário no Linux Technology Center da IBM. Como programador em python, atua em um projeto que cria Ferramentas para instalação de distribuições Linux na arquitetura PowerPC.