Quando pensamos em internacionalização (i18n) em projetos Rails, a abordagem mais comum é utilizar a API nativa do framework com chaves de tradução. No entanto, recentemente descobri uma alternativa que torna esse processo mais direto e com maior visibilidade do conteúdo traduzido: o uso do GetText.
GetText é um framework utilizado no ecossistema Linux, que oferece um conjunto de ferramentas para facilitar a tradução de textos em aplicações. Integrado ao Rails, ele permite uma forma mais automática de localizar strings, sem a necessidade de criar e gerenciar nomes de chaves.
No modelo tradicional com I18n
, criamos chaves de tradução e mapeamos seus conteúdos em arquivos YML. Nas views, essas chaves são utilizadas da seguinte forma:
t(".empty_state_message")
# => Nenhum resultado encontrado
Já com GetText
, podemos escrever diretamente o texto original:
_("Nenhum resultado encontrado")
# => Nenhum resultado encontrado
Essa abordagem destaca imediatamente o conteúdo que será traduzido, tornando o código mais legível e intuitivo.
Setup
Instalação das Gems
Para integrar o GetText ao Rails, instalei as gems gettext_i18n_rails e gettext. Apesar de gettext
ser uma dependência opcional da gettext_i18n_rails
, vale a pena incluí-la no projeto, pois ela oferece rake tasks bastante úteis:
- Para adicionar suporte a um novo idioma:
LANGUAGE=xx rake gettext:add_language
Substitua xx
pelo código do idioma desejado, por exemplo, en
para inglês. A lista completa dos idiomas suportados está disponível aqui.
- Para buscar traduções ausentes e adicioná-las aos arquivos
.po
:
rake gettext:find
Configurações iniciais
Depois da instalação, é necessário criar um initializer para definir os domínios de tradução e os idiomas disponíveis. Para isso, usamos classes da gem fast_gettext, já que gettext_i18n_rails
atua como um wrapper para facilitar a integração do GetText com projetos Rails.
# config/initializers/gettext_i18n_rails.rb
FastGettext.add_text_domain "app", path: "locale", type: :po
FastGettext.default_available_locales = ["pt_BR", "en", "es"]
FastGettext.default_text_domain = "app"
Essa configuração permite organizar as traduções por domínio. No exemplo acima, usei apenas o domínio app
para fins de demonstração, mas é possível definir domínios separados por módulos da aplicação, evitando centralizar todas as traduções em um único arquivo.
Além disso, ajuste o before_action
responsável por definir o idioma da aplicação para também atualizar o locale do GetText:
def set_locale
locale = params[:locale] || I18n.default_locale
+ FastGettext.set_locale(locale)
I18n.locale = locale
end
Por fim, como a aplicação já estava usando I18n
para mensagens de erro do ActiveRecord (e alterar isso demandaria mais esforço), desativei esse comportamento do GetText:
# config/initializers/gettext_i18n_rails.rb
Rails.application.config.gettext_i18n_rails.use_for_active_record_attributes = false
Processo de tradução
Para iniciar o processo de tradução, adicionei um texto usando o método do GetText:
<%= _("Nenhum resultado encontrado") %>
Em seguida, executei a rake task:
rake gettext:find
Essa rake task escaneia o projeto e adiciona as novas strings aos arquivos .po
.
Depois, incluí a tradução correspondente no campo msgstr
de cada arquivo .po
:
# locale/en/app.po
msgid "Nenhum resultado encontrado"
-msgstr ""
+msgstr "No result found"
Após atualizar as traduções, é importante rodar a rake task novamente. Isso garante que os arquivos edit.po
sejam atualizados corretamente. Caso contrário, as alterações podem se misturar com novas strings adicionadas posteriormente, o que dificulta o controle de versões e a revisão das mudanças.
Features
Fallback automático
Se uma string não tiver tradução, ou se você esquecer de adicionar, o GetText retorna o valor original por padrão:
_("Nenhuma categoria encontrada")
# => Nenhuma categoria encontrada
Também é possível fornecer um bloco. Se esse bloco for passado, seu conteúdo será retornado como valor padrão, o que permite definir um fallback mais explícito:
_("Não foi encontrada uma tradução") { "Texto alternativo" }
# => Texto alternativo
Pluralização
A pluralização no GetText é semelhante à do I18n do Rails. Para que funcione corretamente, é necessário configurar a regra de plural de cada idioma nos arquivos .po
.
No meu caso, os idiomas configurados ficaram assim:
# locale/en/app.po
- "Plural-Forms: nplurals=; plural=;\n"
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
# locale/es/app.po
- "Plural-Forms: nplurals=; plural=;\n"
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
# locale/pt_BR/app.po
- "Plural-Forms: nplurals=; plural=;\n"
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
Depois disso, basta usar o método n_
passando o singular, o plural e o número.
n_("tarefa pendente", "tarefas pendentes", @total)
Após rodar a rake task gettext:find
, serão geradas as entradas necessárias nos arquivos .po
. Com as chaves criadas, é só adicionar as traduções correspondentes.
Traduções dinâmicas
É possível interpolar variáveis dentro das strings normalmente. O conteúdo será exibido dinamicamente:
_("Publicado por %{username}") % { username: @user.username }
Conclusão
Se você busca uma forma mais simples e direta de gerenciar traduções, vale a pena experimentar o GetText no seu projeto Rails. A integração é tranquila, o ganho em produtividade é real e você ainda pode manter o I18n do Rails para casos onde preferir.
Top comments (1)
Ótima explicação sobre o uso do GetText no Rails, ficou bem claro! Só senti falta de uma comparação mais direta sobre eventuais desvantagens, como possíveis desafios na manutenção das traduções ou na colaboração com equipes maiores. Fora isso, o post está excelente!