Internacionalização do Rails (i18n): Guia completo
Configure o I18n do Rails, organize o config/locales/*.yml, automatize as traduções de YAML com IA e deixe a PTC (Private Translation Cloud) revisar o seu aplicativo Rails em execução a cada lançamento. Ao final, você terá um aplicativo Rails que responde a URLs /es/..., atende a visualizações traduzidas em 40+ idiomas e é verificado por revisão visual.
Este guia pressupõe que você tenha um aplicativo Rails 7+ existente. Os conceitos se aplicam a versões mais antigas do Rails com pequenas diferenças na API. A própria gem I18n tem se mantido estável por anos. Para a história mais ampla de localização em CI/CD em várias pilhas, consulte Localização de software por IA feita para pipelines de CI/CD.
Configure o Rails para carregar locales, reconhecer URLs e alternar por solicitação
A internacionalização do Rails exige três etapas de configuração. Defina os locales disponíveis, adicione o locale às suas URLs e faça o Rails carregar o locale correto por solicitação. Você também instala a gem rails-i18n para os dados de locale.
Declare os locales disponíveis em config/application.rb
Em config/application.rb, informe ao Rails quais idiomas o aplicativo suporta e defina um padrão:
module MyApp
class Application < Rails::Application
config.i18n.available_locales = [:en, :es, :fr, :de, :ja]
config.i18n.default_locale = :en
config.i18n.fallbacks = true
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
end
end
A linha load_path += Dir[...] é a principal. Por padrão, o Rails carrega apenas config/locales/*.yml (um nível de profundidade). Adicionar o glob recursivo permite que você organize as traduções por namespace, modelo ou recurso em subdiretórios.
Adicione :locale ao escopo da sua URL
Adicione um escopo :locale para que cada idioma tenha o seu próprio caminho, como /en/time ou /es/time:
# config/routes.rb
scope "/:locale" do
get '/time', to: 'home#index', as: :time_display
end
Alterne o locale por solicitação com I18n.with_locale
Em ApplicationController, carregue o locale certo a partir da URL e inclua-o em todos os links gerados:
class ApplicationController < ActionController::Base
around_action :switch_locale
def switch_locale(&action)
locale = params[:locale] || I18n.default_locale
I18n.with_locale(locale, &action)
end
def default_url_options
{ locale: I18n.locale }
end
end
I18n.with_locale é a forma idiomática de definir o escopo de um locale para uma solicitação. Ele define o locale, executa o bloco, restaura o locale anterior e é thread-safe. default_url_options garante que toda URL gerada pelo Rails carregue o locale atual, para que os usuários permaneçam no idioma selecionado enquanto navegam.
Instale o rails-i18n para nomes de meses traduzidos e regras de pluralização
A gem rails-i18n fornece dados de locale para dezenas de idiomas. Essa gem inclui nomes de meses traduzidos, regras de pluralização e mensagens de erro padrão do Rails. Assim, você não precisa traduzir esse boilerplate por conta própria.
# Gemfile
gem 'rails-i18n'
bundle install
O seu aplicativo Rails agora está totalmente configurado para internacionalização.
Adicione um seletor de idiomas com url_for(locale: :code)
Como default_url_options inclui automaticamente o locale em toda URL gerada, o seu seletor precisa apenas atualizar o parâmetro :locale enquanto mantém o usuário na mesma página.
<%# app/views/layouts/application.html.erb %>
<nav class="language-switcher">
<%= link_to "English", url_for(locale: :en) %> |
<%= link_to "Español", url_for(locale: :es) %> |
<%= link_to "Deutsch", url_for(locale: :de) %>
</nav>
Cada link usa url_for(locale: :code) para gerar uma URL com o locale especificado. Quando os usuários clicam, switch_locale em ApplicationController detecta a alteração e o Rails renderiza a página no novo idioma.
Substitua o texto hardcoded nas views por t(:key)
O texto hardcoded não aparecerá nos seus arquivos YAML, o que significa que ele não pode ser traduzido. Sempre use chaves de tradução para qualquer texto voltado para o usuário.
<%# Correct - uses translation keys %>
<h1><%= t(:hello) %></h1>
<p><%= t(:current_time, time: @time) %></p>
<button id="click-me"><%= t(:refresh) %></button>
<%# Incorrect - hardcoded text %>
<h1>Hello</h1>
<p>Current time: <%= @time %></p>
<button>Refresh</button>
Nos controllers (para mensagens flash):
def create
if @post.save
redirect_to @post, notice: t('flash.post.created')
else
flash.now[:alert] = t('flash.post.error')
render :new, status: :unprocessable_entity
end
end
Nos models (para mensagens de validação, use as convenções do Active Model):
# config/locales/en.yml
en:
activerecord:
attributes:
post:
title: "Title"
errors:
models:
post:
attributes:
title:
blank: "is required"
Interpole variáveis com %{name}
%{name} no YAML é substituído pelo valor que você passa para t():
current_time: "Current time: %{time}"
<%= t(:current_time, time: @time) %>
Use a busca sob demanda (.key) para traduções com escopo de view
Quando as suas chaves de tradução estiverem organizadas para corresponder à estrutura de pastas da sua view, use um ponto no início. O Rails preenche o prefixo a partir da view atual:
<%# Instead of this: %>
<%= t('home.index.hello') %>
<%# Use this: %>
<%= t('.hello') %>
O Rails vê que você está em home/index.html.erb e adiciona home.index. no início. Se você renomear ou realocar uma view, os caminhos da busca sob demanda serão atualizados automaticamente.
Organize config/locales/ por recurso em vez de um en.yml gigante
Para um aplicativo do mundo real, um en.yml gigante se torna impossível de manter. Organize por recurso:
config/locales/
en.yml # global / shared keys
models/
post.en.yml
views/
posts.en.yml
home.en.yml
flash.en.yml
Um config/locales/views/posts.en.yml de exemplo:
en:
posts:
index:
title: "All Posts"
empty: "No posts yet"
new:
title: "Create a New Post"
show:
published_at: "Published %{date}"
comments_count:
zero: "No comments yet"
one: "1 comment"
other: "%{count} comments"
Convenções:
- Chaves aninhadas agrupam strings relacionadas e habilitam a busca sob demanda.
- Interpolação de
%{name}para variáveis inline. - Chaves de pluralização
zero/one/otherpara substantivos contáveis. O Rails roteia para a chave certa com base emcount::t('posts.show.comments_count', count: 5).
Adicione strings de JavaScript ao YAML também
O Rails não extrai texto automaticamente de arquivos JavaScript. Qualquer texto do lado do cliente (alertas, tooltips, mensagens de confirmação) precisa estar no seu YAML para ser traduzido junto com todo o resto:
en:
confirm: "Are you sure?"
Quando você traduzir com a PTC na próxima seção, essas strings viajarão com o resto.
Traduza config/locales/*.en.yml com a PTC em 4 etapas
Assim que os seus arquivos de tradução estiverem no lugar, você precisará de versões para cada idioma de destino. A PTC cuida disso:
- Inicie um projeto na PTC e escolha o inglês como origem. O teste de 30 dias cobre 20.000 palavras em 2 idiomas, sem cartão de crédito.
- Faça o upload dos seus arquivos
config/locales/*.en.yml. A PTC analisa o YAML, reconhece as chaves de pluralização do Rails (zero,one,other,few,many) e preserva as interpolações de%{name}. - Adicione uma breve descrição do seu aplicativo Rails e público-alvo. A PTC usa esse contexto para traduzir com o tom e a terminologia certos.
- Escolha os idiomas de destino e confirme. A PTC produz
posts.es.yml,posts.fr.yml,posts.de.yml, estruturalmente idênticos à origem com os valores traduzidos. As formas plurais são geradas por idioma. O polonês recebeone/few/many/other. O japonês recebe apenasother.
Coloque os arquivos de volta em config/locales/views/, reinicie o seu servidor Rails, e o aplicativo servirá os novos idiomas.
Para projetos baseados em Git, aponte a PTC para o seu repositório. Novas strings em qualquer *.en.yml acionam a tradução automática. A PTC abre um merge request com os arquivos atualizados do idioma de destino. Consulte a referência da API da PTC para os endpoints subjacentes.
Use I18n.with_locale em tarefas em segundo plano, mailers e tarefas cron
O padrão I18n.with_locale(locale, &block) é fundamental para qualquer código que seja executado fora de uma solicitação normal. Isso inclui tarefas em segundo plano, tarefas cron e mailers.
# Background job: send an email in the user's preferred locale
class WelcomeEmailJob < ApplicationJob
def perform(user_id)
user = User.find(user_id)
I18n.with_locale(user.preferred_locale) do
UserMailer.welcome(user).deliver_now
end
end
end
Sem with_locale, a tarefa é executada em qualquer locale que estivesse ativo quando o worker foi iniciado. Geralmente :en, independentemente da preferência do usuário. Com ele, o e-mail é renderizado no idioma do usuário e o locale é redefinido quando o bloco termina.
Exporte traduções do Rails para JSON com i18n-js para uso do lado do cliente
As páginas renderizadas pelo Rails obtêm traduções via t() no ERB. O JavaScript executado no navegador não vê o I18n do Rails diretamente. O padrão mais limpo usa a gem i18n-js para exportar as traduções como JSON e carregá-las no lado do cliente.
# Gemfile
gem 'i18n-js'
bundle install
i18n init
Atualize a configuração gerada para exportar as traduções para public/locales.json:
# config/i18n.rb
require "i18n-js"
I18n::JS.config do |config|
config.export_i18n_js = false
config.translations_path = "public/locales.json"
end
Gere o arquivo JSON:
i18n export
Isso lê todos os seus arquivos YAML (en.yml, es.yml, de.yml) e escreve o public/locales.json com todas as traduções em um formato legível por JS.
Fixe o i18n-js com o Importmap do Rails 7+:
# config/importmap.rb
pin "i18n-js", to: "https://esm.sh/i18n-js@latest/dist/import/index.js"
pin "load_locale", to: "load_locale.js"
Crie um loader:
// app/javascript/load_locale.js
export async function loadLocale() {
const response = await fetch('/locales.json');
return await response.json();
}
Passe o locale atual para o JavaScript por meio da tag <body>:
<%# app/views/layouts/application.html.erb %>
<body data-locale="<%= I18n.locale %>">
Em seguida, use as traduções no seu JavaScript:
// app/javascript/application.js
import { I18n } from "i18n-js";
import { loadLocale } from "./load_locale";
document.addEventListener('turbo:load', async () => {
const translations = await loadLocale();
const i18n = new I18n(translations);
i18n.locale = document.body.dataset['locale'];
if (confirm(i18n.t('confirm'))) {
// User clicked OK
}
});
O i18n.t() funciona como o helper t do Rails. Quando os usuários trocam de idioma, o JavaScript usa as traduções corretas do atributo data-locale.
Traduza conteúdo do ActiveRecord com a API da PTC
O padrão acima traduz strings estáticas nos seus arquivos YAML. O conteúdo do ActiveRecord (postagens de usuários, comentários, descrições de produtos armazenadas como entrada do usuário) não aparece no YAML e precisa de uma abordagem diferente. A API REST da PTC traduz esse conteúdo sob demanda com autenticação por token Bearer, usando o mesmo glossário e voz da marca que os seus arquivos config/locales/*.yml. Faça o POST do seu conteúdo para a PTC e, em seguida, receba um callback quando as traduções estiverem prontas ou consulte o status a partir de uma tarefa em segundo plano.
Localize datas, números e moedas com os helpers do Rails
Datas e horas. Use o helper l (abreviação de localize):
<%= l Time.now, format: :long %>
A gem rails-i18n fornece formatos de data/hora padrão para muitos idiomas, incluindo nomes de meses traduzidos e formatação específica do locale. Você pode definir formatos personalizados nos seus arquivos YAML.
Números e moedas. O Rails inclui helpers sensíveis ao locale:
<%= number_to_currency(100, locale: :es) %> <!-- 100,00 € -->
<%= number_with_delimiter(1000000) %> <!-- 1,000,000 -->
Eles respeitam as convenções de locale para separadores decimais, delimitadores de milhares e símbolos de moeda.
Views localizadas por idioma. Para páginas com conteúdo significativamente diferente por locale, crie arquivos de view separados. O Rails renderiza a view apropriada com base no locale atual:
app/views/pages/
about.html.erb <!-- Default -->
about.es.html.erb <!-- Spanish version -->
about.de.html.erb <!-- German version -->
Revisão visual de tradução do seu aplicativo Rails em execução - lance sem QA manual por lançamento
Após a PTC traduzir o seu config/locales/*.yml, o aplicativo Rails renderizado ainda precisa de verificação. Um rótulo traduzido pode causar um estouro em um botão em alemão. Uma mensagem de validação em francês pode usar a forma gramatical incorreta. Uma string em inglês hardcoded em um template ERB (sem a chamada t()) será renderizada não traduzida, independentemente de quantos idiomas você lançar.
O AI Visual QA da PTC substitui o passe de QA manual. Para aplicativos Rails (baseados em navegador), instale a extensão do navegador da PTC e grave um percurso gravado das telas críticas do seu aplicativo (login, fluxos principais, páginas de administração). A partir de então, a PTC reproduz a gravação em cada idioma de destino após cada atualização de tradução, captura cada tela e relata o seguinte:
- Correções nos arquivos YAML quando a PTC os controla. A PTC retraduz uma acepção incorreta, escolhe um sinônimo mais curto, regenera uma forma plural.
- Prompts do Cursor / Claude Code quando o problema estiver no seu código Ruby ou ERB. Uma string em inglês hardcoded fora de
t(), uma mensagem flash construída por concatenação em vez de interpolação, um helper que deveria usarI18n.lpara a formatação de data.
A entrega: um aplicativo Rails multilíngue verificado por lançamento. Não apenas YAML traduzido.
Traduza notas de lançamento, mailers do Devise e páginas de marketing
As suas notas de lançamento, e-mails voltados para o cliente enviados por meio do Devise ou Action Mailer e páginas de marketing vivem fora de config/locales. O Paste to Translate da PTC lida com esse texto no mesmo projeto. Cole o texto de origem no painel da PTC, escolha os idiomas de destino, receba de volta traduções que usam o mesmo glossário e voz da marca que as suas traduções em YAML.
Traduza os seus arquivos config/locales/*.yml com a PTC
Comece o seu teste de 30 dias - 20.000 palavras em 2 idiomas, sem cartão de crédito. Faça o upload dos seus arquivos YAML, obtenha versões traduzidas em minutos e, em seguida, instale a extensão do navegador para verificar o seu aplicativo Rails em execução.
Relacionados:
- Referência da API da PTC - endpoints REST para integração de CI.
- Localização de software por IA feita para pipelines de CI/CD - visão geral do serviço para equipes de engenharia.
- Guia oficial de i18n do Rails - a referência canônica.