A CLI da Lingo.dev traduz arquivos YAML do Rails config/locales por meio de um engine de localização configurado. O Rails já vem com a API i18n nativa — o texto traduzível do seu app fica em arquivos YAML por idioma. A Lingo.dev se encaixa no pipeline que você já usa, sem adicionar dependências em tempo de execução.
Este guia mostra o processo completo de localização de um app Rails: configurar a CLI, organizar arquivos YAML por idioma, alternar idiomas em tempo de requisição e automatizar traduções com GitHub Actions.
Repositório de demonstração
Faça clone ou fork de lingodotdev/ruby-on-rails-localization-example para acompanhar. O repositório traz um app Rails funcional com arquivos YAML config/locales, uma configuração da CLI da Lingo.dev e um workflow do GitHub Actions.
Como a localização funciona no Rails#
O Rails lê traduções de arquivos YAML em config/locales/. Cada arquivo usa um código de idioma na raiz e contém chaves aninhadas que espelham os caminhos de busca que seu código usa com I18n.t.
| Camada | O que fica aqui | Arquivo de exemplo |
|---|---|---|
| Strings de UI | Botões, rótulos e mensagens flash | config/locales/en.yml |
| Textos de mailer | Assuntos e corpos de ActionMailer | config/locales/mailers.en.yml |
| Erros de model | Mensagens de validação e nomes de atributos | config/locales/activerecord.en.yml |
A primeira chave de cada arquivo YAML do Rails é o próprio código do idioma — en:, es:, fr:. O bucket yaml-root-key da CLI entende esse formato: remove o prefixo do idioma antes de enviar o conteúdo para seu engine de localização e depois grava um arquivo paralelo com o código do idioma de destino como nova chave raiz. Chaves aninhadas, tokens de interpolação %{name} e categorias de plural do CLDR (zero/one/two/few/many/other) são preservados.
Pré-requisitos#
Crie um engine de localização
Cada execução da CLI envia o conteúdo por um engine de localização — a configuração que define qual modelo de LLM, glossary, voz da marca e instruções serão aplicados. Crie um no Lingo.dev dashboard e gere uma API key.
Verifique o Ruby e o Rails
Este guia é voltado para Rails 7.2 ou superior, que exige Ruby 3.1 ou superior. Verifique suas versões:
ruby -v
rails -vVerifique o Node.js
A CLI exige Node.js 18 ou superior:
node -vConfigure o i18n do Rails
Este guia parte do princípio de que seu app já armazena traduções em config/locales/*.yml. Se você ainda tem strings hardcoded em views ou controllers, extraia-as primeiro para chamadas t(). Por exemplo, substitua:
<h1>Welcome</h1>por:
<h1><%= t(".welcome") %></h1>depois, adicione a chave correspondente em config/locales/en.yml. Consulte o guia de internacionalização do Rails para ver o passo a passo completo da migração.
Organize os arquivos de tradução#
O Rails carrega automaticamente todo arquivo *.yml em config/locales/. Mantenha o idioma de origem ao lado das versões traduzidas para que o diretório funcione como fonte única da verdade:
config/locales/
en.yml # Source locale
es.yml # Generated by Lingo.dev
fr.yml
de.ymlUm arquivo en.yml típico combina strings simples, namespaces aninhados, interpolação %{name} e pluralização:
en:
hello: "Hello"
home:
welcome: "Welcome, %{name}!"
cta: "Get started"
notifications:
unread:
zero: "No unread notifications"
one: "1 unread notification"
other: "%{count} unread notifications"
errors:
messages:
blank: "can't be blank"Configure a CLI#
Crie um arquivo i18n.json na raiz do projeto. Declare um bucket yaml-root-key apontando para os arquivos de idioma:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de"]
},
"buckets": {
"yaml-root-key": {
"include": ["config/locales/[locale].yml"]
}
}
}O placeholder [locale] é resolvido para cada código de idioma configurado. Com source: "en", a CLI lê config/locales/en.yml e grava os arquivos traduzidos em config/locales/es.yml, config/locales/fr.yml e config/locales/de.yml.
O Rails carrega normalmente mailers.en.yml, pages.en.yml e assim por diante junto com en.yml. Adicione padrões extras ao array include do bucket yaml-root-key:
{
"buckets": {
"yaml-root-key": {
"include": [
"config/locales/[locale].yml",
"config/locales/mailers.[locale].yml",
"config/locales/pages.[locale].yml"
]
}
}
}Configure o Rails para vários idiomas#
Informe ao Rails quais idiomas estão disponíveis e qual deve ser usado como padrão. Em config/application.rb:
module YourApp
class Application < Rails::Application
config.i18n.available_locales = [:en, :es, :fr, :de]
config.i18n.default_locale = :en
config.i18n.fallbacks = [:en]
end
endDefina o idioma da requisição em ApplicationController com base em um parâmetro de URL ou no cabeçalho Accept-Language:
class ApplicationController < ActionController::Base
around_action :switch_locale
private
def switch_locale(&action)
locale = params[:locale] || http_accept_locale || I18n.default_locale
I18n.with_locale(locale, &action)
end
def http_accept_locale
header = request.headers["Accept-Language"].to_s
header.scan(/[a-z]{2}/).find { |l| I18n.available_locales.map(&:to_s).include?(l) }
end
def default_url_options
{ locale: I18n.locale }
end
endRenderize traduções nas views#
Use os helpers t e l em templates ERB. Um ponto no início da chave faz a resolução com base no caminho da view atual, mantendo as chaves de tradução lado a lado com os templates que as usam:
<h1><%= t(".welcome", name: @user_name) %></h1>
<p><%= t("notifications.unread", count: @unread_count) %></p>
<%= link_to t(".cta"), signup_path, class: "btn-primary" %>Adicione um alternador de idioma ao layout:
<nav>
<% I18n.available_locales.each do |locale| %>
<%= link_to locale.upcase, url_for(locale: locale) %>
<% end %>
</nav>Traduza localmente#
Defina sua API key e execute a CLI:
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest runA CLI lê cada arquivo que corresponde aos padrões do bucket, identifica entradas ainda não traduzidas usando o lockfile, traduz o delta por meio do seu engine de localização e grava os resultados em cada arquivo de idioma de destino. A chave raiz do idioma, os namespaces aninhados, os tokens de interpolação no estilo %{name} e as categorias de plural são preservados — só o texto traduzível muda.
Para segmentar um idioma específico durante o desenvolvimento:
npx lingo.dev@latest run --target-locale esReinicie o servidor Rails após a primeira execução de tradução para que os novos arquivos YAML sejam carregados:
bin/rails serverAcesse /es para ver a versão em espanhol.
Plurais#
O Rails usa categorias de plural do CLDR — zero, one, two, few, many, other. Passe um argumento count: para I18n.t e o Rails escolherá a chave correspondente:
t("notifications.unread", count: 0) # => "No unread notifications"
t("notifications.unread", count: 1) # => "1 unread notification"
t("notifications.unread", count: 12) # => "12 unread notifications"A CLI traduz cada variante de plural no lugar. Se o idioma de destino precisar de mais categorias do que one/other no inglês, defina-as no arquivo de origem en.yml.
Automatize com GitHub Actions#
Adicione um arquivo de workflow em .github/workflows/translate.yml para traduzir a cada push:
As traduções são commitadas direto na main — zero atrito, ideal para times pequenos:
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lingo.dev
uses: lingodotdev/lingo.dev@main
with:
api-key: ${{ secrets.LINGODOTDEV_API_KEY }}Armazene sua API key como LINGODOTDEV_API_KEY em Settings > Secrets and variables > Actions no seu repositório do GitHub.
Verifique antes do deploy#
Use a flag --frozen como gate de deploy para garantir que nenhum conteúdo sem tradução vá para produção. A CLI encerra com status diferente de zero se alguma entrada ainda precisar de tradução:
npx lingo.dev@latest run --frozenAdicione isso como uma etapa separada de CI antes da pré-compilação de assets ou do build do container:
- name: Verify translations
run: npx lingo.dev@latest run --frozen
- name: Precompile assets
run: bundle exec rails assets:precompile