Internacionalización de Rails (i18n): guía completa
Configure Rails I18n, organice config/locales/*.yml, automatice las traducciones de YAML con IA y deje que PTC (Private Translation Cloud) revise su aplicación Rails en ejecución en cada versión. Al terminar tendrá una aplicación Rails que responde a URL /es/..., sirve vistas traducidas en más de 40 idiomas y queda verificada mediante revisión visual.
Esta guía asume que ya tiene una aplicación Rails 7+. Los conceptos se aplican a versiones anteriores de Rails con diferencias menores en la API. La propia gema I18n lleva años siendo estable. Para conocer el panorama más amplio de la localización con CI/CD en distintos stacks, consulte Localización de software con IA diseñada para pipelines de CI/CD.
Configure Rails para cargar locales, reconocer URL y cambiar por solicitud
La internacionalización de Rails requiere tres pasos de configuración. Defina los locales disponibles, añada el locale a sus URL y haga que Rails cargue el locale correcto en cada solicitud. Además, instale la gema rails-i18n para los datos de los locales.
Declare los locales disponibles en config/application.rb
En config/application.rb, indique a Rails qué idiomas admite la aplicación y establezca uno por defecto:
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
La línea load_path += Dir[...] es la clave. De forma predeterminada, Rails carga únicamente config/locales/*.yml (un nivel de profundidad). Añadir el glob recursivo le permite organizar las traducciones por namespace, modelo o función en subdirectorios.
Añada :locale a su scope de URL
Añada un scope :locale para que cada idioma tenga su propia ruta, como /en/time o /es/time:
# config/routes.rb
scope "/:locale" do
get '/time', to: 'home#index', as: :time_display
end
Cambie el locale por solicitud con I18n.with_locale
En ApplicationController, cargue el locale correcto desde la URL e inclúyalo en todos los enlaces generados:
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 es la forma idiomática de limitar un locale a una solicitud. Establece el locale, ejecuta el bloque, restaura el locale anterior y es seguro para hilos. default_url_options garantiza que cada URL que genera Rails lleve el locale actual, de modo que los usuarios permanezcan en el idioma seleccionado mientras navegan.
Instale rails-i18n para obtener nombres de meses traducidos y reglas de pluralización
La gema rails-i18n proporciona datos de locales para decenas de idiomas. Nombres de meses traducidos, reglas de pluralización, mensajes de error predeterminados de Rails. Así no tiene que traducir usted mismo ese código repetitivo.
# Gemfile
gem 'rails-i18n'
bundle install
Su aplicación Rails ya está totalmente configurada para la internacionalización.
Añada un selector de idioma con url_for(locale: :code)
Como default_url_options incluye automáticamente el locale en cada URL generada, su selector solo necesita actualizar el parámetro :locale y mantener al usuario en la misma página.
<%# app/views/layouts/application.html.erb %>
<nav class="language-switcher">
<%= link_to "English", url_for(locale: :en) %> |
<%= link_to "Espanol", url_for(locale: :es) %> |
<%= link_to "Deutsch", url_for(locale: :de) %>
</nav>
Cada enlace usa url_for(locale: :code) para generar una URL con el locale especificado. Cuando los usuarios hacen clic, switch_locale en ApplicationController detecta el cambio y Rails renderiza la página en el nuevo idioma.
Reemplace el texto codificado en las vistas con t(:key)
El texto codificado no aparecerá en sus archivos YAML, lo que significa que no se puede traducir. Use siempre claves de traducción para cualquier texto visible para el usuario.
<%# 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>
En los controladores (para mensajes 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
En los modelos (para mensajes de validación, use las convenciones de Active Model):
# config/locales/en.yml
en:
activerecord:
attributes:
post:
title: "Title"
errors:
models:
post:
attributes:
title:
blank: "is required"
Interpole variables con %{name}
%{name} en la YAML se sustituye por el valor que pasa a t():
current_time: "Current time: %{time}"
<%= t(:current_time, time: @time) %>
Use la búsqueda perezosa (.key) para traducciones acotadas a la vista
Cuando sus claves de traducción están organizadas para coincidir con la estructura de carpetas de sus vistas, use un punto inicial. Rails completa el prefijo a partir de la vista actual:
<%# Instead of this: %>
<%= t('home.index.hello') %>
<%# Use this: %>
<%= t('.hello') %>
Rails ve que está en home/index.html.erb y antepone home.index.. Si renombra o reubica una vista, las rutas de búsqueda perezosa se actualizan automáticamente.
Organice config/locales/ por función en lugar de un único en.yml gigante
Para una aplicación real, un único en.yml gigante se vuelve inmanejable. Organícelo por función:
config/locales/
en.yml # global / shared keys
models/
post.en.yml
views/
posts.en.yml
home.en.yml
flash.en.yml
Un ejemplo de config/locales/views/posts.en.yml:
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"
Convenciones:
- Las claves anidadas agrupan strings relacionados y habilitan la búsqueda perezosa.
- La interpolación
%{name}para variables en línea. - Las claves de pluralización
zero/one/otherpara sustantivos contables. Rails enruta a la clave correcta segúncount::t('posts.show.comments_count', count: 5).
Añada también los strings de JavaScript a la YAML
Rails no extrae automáticamente el texto de los archivos JavaScript. Cualquier texto del lado del cliente (alertas, tooltips, mensajes de confirmación) debe residir en su YAML para que se traduzca junto con todo lo demás:
en:
confirm: "Are you sure?"
Cuando traduzca con PTC en la siguiente sección, estos strings viajan con el resto.
Traduzca config/locales/*.en.yml con PTC en 4 pasos
Una vez que sus archivos de traducción están en su sitio, necesita versiones para cada idioma de destino. PTC se encarga de ello:
- Inicie un proyecto en PTC y elija inglés como origen. La prueba gratuita incluye 20.000 palabras a 2 idiomas, sin tarjeta de crédito.
- Suba sus archivos
config/locales/*.en.yml. PTC analiza la YAML, reconoce las claves de pluralización de Rails (zero,one,other,few,many) y conserva las interpolaciones%{name}. - Añada una breve descripción de su aplicación Rails y su audiencia. PTC usa este contexto para traducir con el tono y la terminología adecuados.
- Elija los idiomas de destino y confirme. PTC produce
posts.es.yml,posts.fr.yml,posts.de.yml, estructuralmente idénticos al origen pero con los valores traducidos. Las formas plurales se generan por idioma. El polaco obtieneone/few/many/other. El japonés obtiene soloother.
Vuelva a colocar los archivos en config/locales/views/, reinicie su servidor Rails y la aplicación servirá los nuevos idiomas.
Para proyectos basados en Git, conecte PTC a su repositorio. Los nuevos strings en cualquier *.en.yml activan una traducción automática. PTC abre un PR con los archivos de idioma de destino actualizados. Consulte la referencia de la API de PTC para conocer el flujo de sincronización.
Use I18n.with_locale en trabajos en segundo plano, mailers y tareas cron
El patrón I18n.with_locale(locale, &block) es fundamental para cualquier código que se ejecute fuera de una solicitud normal. Trabajos en segundo plano, tareas cron, 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
Sin with_locale, el trabajo se ejecuta en el locale que estaba activo cuando se inició el worker. Normalmente :en, independientemente de la preferencia del usuario. Con él, el correo se renderiza en el idioma del usuario y el locale se restablece cuando finaliza el bloque.
Exporte las traducciones de Rails a JSON con i18n-js para su uso del lado del cliente
Las páginas renderizadas por Rails obtienen las traducciones mediante t() en ERB. El JavaScript que se ejecuta en el navegador no ve directamente el I18n de Rails. El patrón más limpio usa la gema i18n-js para exportar las traducciones como JSON y cargarlas del lado del cliente.
# Gemfile
gem 'i18n-js'
bundle install
i18n init
Actualice la configuración generada para exportar las traducciones a 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
Genere el archivo JSON:
i18n export
Esto lee todos sus archivos YAML (en.yml, es.yml, de.yml) y escribe public/locales.json con cada traducción en un formato legible por JS.
Fije i18n-js con Importmap de 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"
Cree un cargador:
// app/javascript/load_locale.js
export async function loadLocale() {
const response = await fetch('/locales.json');
return await response.json();
}
Pase el locale actual a JavaScript a través de la etiqueta <body>:
<%# app/views/layouts/application.html.erb %>
<body data-locale="<%= I18n.locale %>">
Después, use las traducciones en su 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
}
});
i18n.t() funciona como el helper t de Rails. Cuando los usuarios cambian de idioma, JavaScript usa las traducciones correctas a partir del atributo data-locale.
Traduzca contenido de ActiveRecord con la API de PTC
El patrón anterior traduce strings estáticos en sus archivos YAML. El contenido de ActiveRecord (publicaciones de usuarios, comentarios, descripciones de productos almacenados como entrada del usuario) no aparece en la YAML y requiere un enfoque distinto. La API REST de PTC traduce este contenido bajo demanda con autenticación mediante token Bearer, usando el mismo glosario y la misma voz de marca que sus archivos config/locales/*.yml. Envíe su contenido por POST a PTC y luego reciba un callback cuando las traducciones estén listas o consulte el estado desde un trabajo en segundo plano.
Localice fechas, números y monedas con los helpers de Rails
Fechas y horas. Use el helper l (abreviatura de localize):
<%= l Time.now, format: :long %>
La gema rails-i18n proporciona formatos de fecha y hora predeterminados para muchos idiomas, incluidos nombres de meses traducidos y formato específico de cada locale. Puede definir formatos personalizados en sus archivos YAML.
Números y monedas. Rails incluye helpers que reconocen el locale:
<%= number_to_currency(100, locale: :es) %> <!-- 100,00 EUR -->
<%= number_with_delimiter(1000000) %> <!-- 1,000,000 -->
Estos respetan las convenciones del locale para separadores decimales, separadores de miles y símbolos de moneda.
Vistas localizadas por idioma. Para páginas con contenido considerablemente distinto según el locale, cree archivos de vista separados. Rails renderiza la vista adecuada según el locale actual:
app/views/pages/
about.html.erb <!-- Default -->
about.es.html.erb <!-- Spanish version -->
about.de.html.erb <!-- German version -->
Revisión visual de la traducción de su aplicación Rails en ejecución - lance sin QA manual por versión
Después de que PTC traduce sus config/locales/*.yml, la aplicación Rails renderizada todavía necesita verificación. Una etiqueta traducida puede desbordar un botón en alemán. Un mensaje de validación en francés puede usar la forma gramatical incorrecta. Un string en inglés codificado en una plantilla ERB (sin llamada a t()) se renderizará sin traducir por muchos idiomas que despliegue.
La revisión visual con IA de PTC reemplaza la pasada de QA manual. Para aplicaciones Rails (basadas en navegador), instale la extensión de navegador de PTC y grabe un recorrido por las pantallas críticas de su aplicación (inicio de sesión, flujos principales, páginas de administración). A partir de entonces, PTC reproduce la grabación en cada idioma de destino tras cada actualización de traducción, captura cada pantalla e informa:
- Correcciones en los archivos YAML cuando PTC los controla. PTC retraduce un sentido erróneo, elige un sinónimo más corto, regenera una forma plural.
- Indicaciones para Cursor / Claude Code cuando el problema reside en su código Ruby o ERB. Un string en inglés codificado fuera de
t(), un mensaje flash creado por concatenación en lugar de interpolación, un helper que debería usarI18n.lpara el formato de fechas.
El resultado: una aplicación Rails multilingüe verificada por versión. No solo YAML traducida.
Traduzca notas de versión, mailers de Devise y páginas de marketing
Sus notas de versión, los correos para clientes enviados a través de Devise o Action Mailer y las páginas de marketing residen fuera de config/locales. La función Paste to Translate de PTC se encarga de ese texto en el mismo proyecto. Pegue el texto de origen en el panel de PTC, elija los idiomas de destino y reciba traducciones que usan el mismo glosario y la misma voz de marca que sus traducciones de YAML.
Traduzca sus archivos config/locales/*.yml con PTC
Inicie su prueba gratuita de 30 días - 20.000 palabras a 2 idiomas, sin tarjeta de crédito. Suba sus archivos YAML, obtenga versiones traducidas en minutos y luego instale la extensión de navegador para verificar su aplicación Rails en ejecución.
Relacionado:
- Referencia de la API de PTC - endpoints REST para la integración con CI.
- Localización de software con IA diseñada para pipelines de CI/CD - descripción del servicio para equipos de ingeniería.
- Guía oficial de i18n de Rails - la referencia canónica.