A CLI da Lingo.dev traduz ficheiros YAML do Rails config/locales através de um motor de localização configurado. O Rails já inclui a API i18n de raiz — o texto traduzível da sua app fica em ficheiros YAML por idioma. A Lingo.dev encaixa no pipeline existente sem acrescentar uma dependência em runtime.
Este guia mostra-lhe como localizar uma aplicação Rails de ponta a ponta: configurar o CLI, organizar ficheiros YAML por idioma, mudar de idioma no momento do pedido e automatizar traduções em CI.
Repositório de demonstração
Faça clone ou fork de lingodotdev/ruby-on-rails-localization-example para acompanhar. É uma aplicação Rails funcional com ficheiros YAML config/locales, um .lingo/config.json em commit e traduções já preparadas, para que possa ver a configuração lado a lado com o resultado que ela gerou.
Como Funciona a Localização no Rails#
O Rails lê traduções de ficheiros YAML em config/locales/. Cada ficheiro usa um código de idioma como chave na raiz e contém chaves aninhadas que refletem os caminhos de procura que o seu código usa com I18n.t.
| Camada | O que contém | Ficheiro de exemplo |
|---|---|---|
| Strings da interface | Botões, etiquetas, mensagens flash | config/locales/en.yml |
| Conteúdo de mailer | Assuntos e corpos para ActionMailer | config/locales/mailers.en.yml |
| Erros do modelo | Mensagens de validação e nomes de atributos | config/locales/activerecord.en.yml |
A primeira chave de cada ficheiro YAML do Rails é o próprio código do idioma – en:, es:, fr:. O Rails indexa as traduções por essa chave raiz, e não pelo nome do ficheiro: carrega todos os ficheiros em config/locales/ e guarda o conteúdo de cada um sob a raiz que este declarar. Por isso, um es.yml que continue com a raiz em en: não é ignorado – é agregado ao namespace en. O espanhol acaba sem traduções nenhumas, e as em inglês são substituídas silenciosamente.
Traduzir este formato significa, por isso, reescrever essa chave, não apenas os valores. O formato yaml-root-key faz exatamente isso: percorre a árvore abaixo da chave raiz, traduz apenas os valores de texto e escreve o ficheiro de destino com a raiz no idioma de destino. Chaves aninhadas, tokens de interpolação %{name} e categorias de plural do CLDR (zero/one/two/few/many/other) fazem parte da estrutura, por isso passam intactos – tal como os comentários e as âncoras YAML.
Pré-requisitos#
Criar um motor de localização
Sempre que executar a CLI, o conteúdo é enviado através de um motor de localização — a configuração que define que modelo de LLM, glossário, voz da marca e regras são aplicados. Crie um no painel do Lingo.dev e gere uma chave de API.
Verificar Ruby e Rails
Este guia foi pensado para Rails 7.2 ou superior, que requer Ruby 3.1 ou superior. Verifique as versões:
ruby -v
rails -vVerificar Node.js
O CLI requer Node.js 22 ou superior:
node -vConfigurar o i18n do Rails
Este guia parte do princípio de que a sua app já armazena traduções em config/locales/*.yml. Se tiver strings hardcoded em views ou controllers, extraia-as primeiro para chamadas t(). Por exemplo, substitua:
<h1>Welcome</h1>por:
<h1><%= t(".welcome") %></h1>e depois adicione a chave correspondente a config/locales/en.yml. Consulte o guia de internacionalização do Rails para ver todos os passos da migração.
Organizar os Ficheiros de Tradução#
O Rails carrega automaticamente todos os ficheiros *.yml em config/locales/. Mantenha o idioma de origem ao lado das respetivas versões traduzidas, para que a diretoria funcione como a única fonte de verdade:
config/locales/
en.yml # Source locale
es.yml # Generated by Lingo.dev
fr.yml
de.ymlUm ficheiro 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"Configurar a CLI#
Instale o CLI, autentique-se e ligue o projeto ao seu motor:
npm install -g @lingo.dev/cli
lingo login
lingo init
lingo linklingo init e lingo link criam .lingo/config.json com os seus idiomas e o orgId e engineId do seu motor. Faça commit desse ficheiro, juntamente com .lingo/lock.json, para que todas as máquinas e todas as execuções de CI partilhem o mesmo estado.
Aponte uma entrada files[] para o ficheiro do idioma de origem e defina explicitamente o formato:
{
"orgId": "org_...",
"engineId": "eng_...",
"sourceLocale": "en",
"targetLocales": ["es", "fr", "de"],
"files": [{ "pattern": "config/locales/en.yml", "format": "yaml-root-key" }]
}"format": "yaml-root-key" é obrigatório aqui, não opcional. Um caminho .yml não permite perceber se a chave raiz corresponde a um idioma ou a uma configuração normal, por isso o CLI não tenta adivinhar: se omitir format, o ficheiro é tratado como yaml genérico, o que traduz os valores e mantém a raiz em en: – a falha silenciosa descrita acima.
Os ficheiros de destino são derivados do caminho de origem, por isso config/locales/en.yml produz config/locales/es.yml, config/locales/fr.yml e config/locales/de.yml.
O Rails também carrega ficheiros por contexto juntamente com en.yml – devise.en.yml, mailers.en.yml, activerecord.en.yml. Adicione uma segunda entrada com um glob para os abranger:
{
"files": [
{ "pattern": "config/locales/en.yml", "format": "yaml-root-key" },
{ "pattern": "config/locales/*.en.yml", "format": "yaml-root-key" }
]
}Os dois padrões não se sobrepõem: o primeiro corresponde apenas a en.yml e o segundo apenas a ficheiros que terminam em .en.yml, por isso ficheiros já traduzidos, como es.yml e devise.es.yml, nunca são apanhados como origem. devise.en.yml produz devise.es.yml.
Configurar o Rails para Vários Idiomas#
Diga ao Rails que idiomas estão disponíveis e qual deve ser usado por defeito. 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 do pedido em ApplicationController a partir de um parâmetro na URL ou do 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
endRenderizar Traduções nas Views#
Use os helpers t e l em templates ERB. Um ponto no início da chave resolve em relação ao caminho da view atual, mantendo as chaves de tradução junto dos 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 seletor de idioma ao layout:
<nav>
<% I18n.available_locales.each do |locale| %>
<%= link_to locale.upcase, url_for(locale: locale) %>
<% end %>
</nav>Traduzir Localmente#
lingo push --waitpush carrega os ficheiros de origem, processa-os através do seu motor de localização e volta a escrever os ficheiros traduzidos. --wait mantém o comando bloqueado até os resultados ficarem disponíveis – vale a pena passá-lo explicitamente, porque uma alteração prevista vai mudar o comportamento predefinido, pelo que push submete a execução e regressa de imediato, deixando a recolha dos resultados para lingo pull.
As execuções seguintes traduzem apenas o delta: push gera um hash da origem e compara-o com lingo/lock.json, por isso as entradas inalteradas não têm qualquer custo. A primeira execução num projeto – ou depois de adicionar um idioma – precisa do corpus completo:
lingo push --backfill-missingRestrinja uma execução a um subconjunto de ficheiros, passando um glob:
lingo push "config/locales/**"Para obter resultados gerados noutro local – noutra máquina ou em CI – execute lingo pull.
Reinicie o servidor Rails após a primeira execução da tradução para que os novos ficheiros YAML sejam carregados:
bin/rails serverVisite /es para ver o resultado em espanhol.
Plurais#
O Rails usa categorias de plural CLDR — zero, one, two, few, many, other. Passe um argumento count: a I18n.t e o Rails escolhe 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 mesmo local. Se o seu idioma de destino precisar de mais categorias do que one/other em inglês, defina-as no en.yml de origem.
Automatize em CI#
A GitHub App da Lingo.dev traduz em cada push e pull request, do lado do servidor – sem runner nem chave de API guardada no seu repositório. Resolve o motor a partir do .lingo/config.json em commit, por isso orgId e engineId têm de estar presentes no ficheiro que colocar em commit.
Se preferir executar o CLI no seu próprio pipeline – GitHub Actions, GitLab CI, Bitbucket Pipelines – consulte CI/CD Workflows. Forneça LINGO_API_KEY como segredo e invoque lingo push --wait como qualquer outro passo de build.
Verificar Antes de Fazer Deploy#
Use lingo check como bloqueio de deployment para garantir que nenhum conteúdo por traduzir chega à produção. Termina com um estado diferente de zero se ainda houver entradas por traduzir, e não escreve nada:
lingo checkAdicione-o como um passo de CI separado antes da pré-compilação de assets ou da build do contentor:
- name: Verify translations
run: lingo check
- name: Precompile assets
run: bundle exec rails assets:precompile