Tutorial¶
Esta página vai de um diretório vazio a um programa que cumprimenta em japonês. Cinco passos, sem pressupor experiência com gettext, e cada comando é mostrado com a saída que ele realmente produz — assim, a cada passo você sabe se está no caminho certo.
Você precisa do Python 3.14 ou mais recente, porque t-strings são sintaxe nova
no 3.14. O japonês é o idioma-alvo de exemplo desta página, mas nada depende
dessa escolha. Para usar outro idioma, troque o ja no passo 4 — esse código
de localidade é a única coisa que o nomeia.
1. Instale¶
O extra [babel] traz o Babel, a ferramenta que coleta suas mensagens em
arquivos de catálogo no passo 3. É uma ferramenta de desenvolvimento: o código
em produção renderiza apenas com a biblioteca padrão.
2. Marque uma mensagem no seu código¶
Crie app.py:
t"Hello {name}" parece uma f-string, mas o prefixo t mantém o texto e o
valor separados em vez de fundi-los na hora. É essa separação que permite a
tr() buscar uma tradução para a frase inteira Hello {name} e inserir o
valor depois.
Execute agora:
Nenhuma tradução foi instalada ainda, então o texto de origem é renderizado como está. Um programa que usa esta biblioteca nunca exige um catálogo para rodar — o inglês (ou qualquer que seja seu idioma de origem) é o fallback embutido.
3. Extraia as mensagens¶
Quem traduz costuma trabalhar a partir de catálogos, e não do código-fonte, então um pequeno arquivo chamado catálogo viaja entre vocês. O primeiro passo em direção a ele é coletar do código todas as mensagens marcadas.
Diga ao Babel como encontrar suas mensagens criando babel.cfg:
Depois extraia para um arquivo de template (.pot):
$ mkdir -p locales
$ pybabel extract -F babel.cfg -c "Translators:" -o locales/messages.pot .
extracting messages from app.py (encoding="utf-8")
writing PO template file to locales/messages.pot
locales/messages.pot agora contém uma entrada por mensagem:
msgid é a chave que seu código vai consultar. O msgstr vazio é onde entra
uma tradução — mas não neste arquivo: um .pot é um template, e o próximo
passo o copia uma vez por idioma.
4. Traduza e compile¶
Crie o catálogo japonês a partir do template:
$ pybabel init -i locales/messages.pot -d locales -l ja
creating catalog locales/ja/LC_MESSAGES/messages.po based on locales/messages.pot
Abra locales/ja/LC_MESSAGES/messages.po e preencha o msgstr:
Mantenha {name} exatamente como está — o marcador é como o valor encontra
seu lugar dentro da frase traduzida, e a tradução é livre para movê-lo para
onde o idioma de destino precisar. Em um projeto real, este arquivo .po é o
que você entrega a quem traduz ou envia a uma plataforma de tradução; o
formato é o mesmo nos dois casos.
Catálogos são editados como texto, mas carregados em forma binária (.mo),
então compile:
$ pybabel compile -d locales
compiling catalog locales/ja/LC_MESSAGES/messages.po to locales/ja/LC_MESSAGES/messages.mo
Este comando também é uma rede de segurança. Se a tradução tivesse danificado o
marcador — {nome} em vez de {name}, por exemplo —, ele se recusaria a
passar:
$ pybabel compile -d locales
error: locales/ja/LC_MESSAGES/messages.po:24: translation does not match the
source placeholders: {name} is missing; {nome} is not in the source message
1 errors encountered.
Uma ressalva que já vale conhecer: ele reporta o erro e sai com código
diferente de zero, mas escreve o .mo assim mesmo. Em um projeto real, é a CI
que precisa parar diante desse código de saída — a página
Em produção monta isso.
5. Execute¶
Os passos 2 a 4 usaram tr(), que procura um catálogo e não encontra nenhum.
Agora que existe um, carregue-o e vincule-o uma vez: o Translator guarda um
catálogo para que os pontos de chamada não precisem nomeá-lo, e _ é o nome
convencional do gettext para o resultado.
Aponte app.py para o catálogo compilado. Clique nos marcadores para ver o
que cada linha está fazendo:
import gettext
from gettext_tstrings import Translator
_ = Translator(gettext.translation("messages", localedir="locales", languages=["ja"])) # (1)!
name = "Ada"
print(_(t"Hello {name}")) # (2)!
- A biblioteca padrão carrega o
.mocompilado, e oTranslatoro vincula a uma função chamável._é o nome convencional do gettext para "traduza isto" — curto porque aparece em toda string exibida a quem usa o programa. Ele faz a mesma tradução quetr, vinculado a um catálogo. - Na chamada: o texto da t-string vira a chave de busca
Hello {name}, o catálogo respondeこんにちは {name}, a resposta é verificada contra os marcadores de origem, e só então o valor é inserido.
Esse é o ciclo completo, e vale a pena vê-lo como uma única imagem:
flowchart LR
mark["1–2 marcar<br>t-strings no código"] --> extract["3 extrair<br>messages.pot"]
extract --> translate["4 traduzir<br>ja/…/messages.po"]
translate --> compile["4 compilar<br>ja/…/messages.mo"]
compile --> run["5 executar<br>こんにちは Ada"]
Marcar → extrair → traduzir → compilar → executar. Todo o restante deste site é um refinamento de um desses cinco passos.
Próximos passos¶
- Por que t-strings — do que este design protege você, em
comparação com
%(name)s,.format()e strings$. - Guia — plurais, idioma por requisição, strings preguiçosas e o que acontece em tempo de execução quando, mesmo assim, um catálogo está errado.
- Em produção — este mesmo ciclo como uma equipe o executa, semana após semana: atualização de catálogos, portões de CI e plataformas de tradução.
- Extração — a referência completa do
pybabel: nomes de função personalizados, modo estrito para CI e as verificações que protegem seus catálogos. - Migração — se o projeto em que você realmente quer fazer isso já tem catálogos gettext.
- Para quem traduz — a página única para entregar a quem
preenche aquelas linhas
msgstr.