Guía completa de internacionalización (i18n) en Rails
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 lanzamiento. Al finalizar, tendrá una aplicación Rails que responde a las URL /es/..., sirve vistas traducidas en más de 40 idiomas y está verificada mediante revisión visual.
Esta guía asume que usted tiene una aplicación Rails 7+ existente. Los conceptos se aplican a versiones anteriores de Rails con pequeñas diferencias en la API. La gema I18n en sí ha sido estable durante años. Para conocer la historia completa de localización en CI/CD en diferentes entornos tecnológicos, consulte Localización de software con IA diseñada para pipelines de CI/CD.
Configure Rails para cargar locales, reconocer URL y cambiar según la solicitud
La internacionalización de Rails requiere tres pasos de configuración. Establezca los locales disponibles, añada el locale a sus URL y haga que Rails cargue el locale correcto en cada solicitud. También debe instalar 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. Por defecto, Rails solo carga config/locales/*.yml (un nivel de profundidad). Añadir el glob recursivo le permite organizar las traducciones por espacio de nombres, modelo o funcionalidad en subdirectorios.
Añada :locale a su alcance de URL
Añada un alcance :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 (thread-safe). default_url_options garantiza que cada URL que Rails genere lleve el locale actual, para que los usuarios permanezcan en el idioma seleccionado mientras navegan.
Instale rails-i18n para nombres de meses traducidos y reglas de pluralización
La gema rails-i18n proporciona datos de locales para docenas de idiomas. Esa gema incluye nombres de meses traducidos, reglas de pluralización y mensajes de error predeterminados de Rails. Así no tendrá que traducir usted mismo ese contenido genérico.
# 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)
Dado que default_url_options incluye automáticamente el locale en cada URL generada, su selector solo necesita actualizar el parámetro :locale manteniendo 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 "Español", url_for(locale: :es) %> |
<%= link_to "Deutsch", url_for(locale: :de) %>
</nav>
Cada enlace utiliza 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.
Sustituya el texto codificado en las vistas por t(:key)
El texto codificado directamente (hardcoded) no aparecerá en sus archivos YAML, lo que significa que no se podrá traducir. Utilice siempre claves de traducción para cualquier texto orientado al 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, utilice 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 el YAML se sustituye por el valor que pase a t():
current_time: "Current time: %{time}"
<%= t(:current_time, time: @time) %>
Utilice la búsqueda diferida (.key) para traducciones con alcance de vista
Cuando sus claves de traducción estén organizadas para coincidir con la estructura de carpetas de sus vistas, utilice un punto inicial. Rails rellena el prefijo a partir de la vista actual:
<%# Instead of this: %>
<%= t('home.index.hello') %>
<%# Use this: %>
<%= t('.hello') %>
Rails detecta que se encuentra en home/index.html.erb y antepone home.index.. Si cambia el nombre o la ubicación de una vista, las rutas de búsqueda diferida se actualizan automáticamente.
Organice config/locales/ por funcionalidad en lugar de un único archivo en.yml gigante
Para una aplicación real, un solo archivo en.yml gigante se vuelve inmanejable. Organice por funcionalidad:
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:
- Claves anidadas: agrupan cadenas relacionadas y permiten la búsqueda diferida.
- Interpolación
%{name}: para variables en línea. - Pluralización
zero/one/other: claves para sustantivos contables. Rails dirige a la clave correcta basándose encount::t('posts.show.comments_count', count: 5).
Añada también las cadenas de JavaScript al 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, estas cadenas viajarán con el resto.
Traduzca config/locales/*.en.yml con PTC en 4 pasos
Una vez que sus archivos de traducción estén listos, necesitará versiones para cada idioma de destino. PTC se encarga de esto:
- Inicie un proyecto en PTC y elija el inglés como origen. La prueba gratuita cubre 20.000 palabras en 2 idiomas, sin tarjeta de crédito.
- Suba sus archivos
config/locales/*.en.yml. PTC analiza el YAML, reconoce las claves de pluralización de Rails (zero,one,other,few,many) y preserva las interpolaciones%{name}. - Añada una breve descripción de su aplicación Rails y su audiencia. PTC utiliza este contexto para traducir con el tono y la terminología adecuados.
- Elija los idiomas de destino y confirme. PTC genera
posts.es.yml,posts.fr.yml,posts.de.yml, estructuralmente idénticos al origen 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 gestionados con Git, apunte PTC a su repositorio. Las nuevas cadenas en cualquier *.en.yml activan la traducción automática. PTC abre un pull request con los archivos de los idiomas de destino actualizados. Consulte la referencia de la API de PTC para el flujo de sincronización.
Utilice I18n.with_locale en tareas 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. Esto incluye tareas en segundo plano, tareas cron y 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, la tarea se ejecuta en cualquier locale que estuviera activo cuando se inició el worker. Generalmente :en, independientemente de la preferencia del usuario. Con él, el correo electrónico se renderiza en el idioma del usuario y el locale se restablece cuando termina el bloque.
Exporte las traducciones de Rails a JSON con i18n-js para uso en el 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 consiste en utilizar la gema i18n-js para exportar las traducciones como JSON y cargarlas en el 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.
Ancle i18n-js con Rails 7+ Importmap:
# 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 %>">
A continuación, utilice 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 ayudante t de Rails. Cuando los usuarios cambian de idioma, JavaScript utiliza las traducciones correctas del atributo data-locale.
Traduzca contenido de ActiveRecord con la API de PTC
El patrón anterior traduce cadenas estáticas en sus archivos YAML. El contenido de ActiveRecord (publicaciones de usuarios, comentarios, descripciones de productos almacenadas como entrada de usuario) no aparece en el YAML y requiere un enfoque diferente. La API REST de PTC traduce este contenido bajo demanda con autenticación mediante token Bearer, utilizando el mismo glosario y voz de marca que sus archivos config/locales/*.yml. Envíe su contenido a PTC mediante POST y, a continuación, reciba un callback cuando las traducciones estén listas o consulte el estado desde una tarea en segundo plano.
Localice fechas, números y moneda con los ayudantes de Rails
Fechas y horas. Utilice el ayudante l (abreviatura de localize):
<%= l Time.now, format: :long %>
La gema rails-i18n proporciona formatos de fecha/hora predeterminados para muchos idiomas, incluyendo nombres de meses traducidos y formatos específicos de cada locale. Puede definir formatos personalizados en sus archivos YAML.
Números y moneda. Rails incluye ayudantes que tienen en cuenta el locale:
<%= number_to_currency(100, locale: :es) %> <!-- 100,00 € -->
<%= number_with_delimiter(1000000) %> <!-- 1,000,000 -->
Estos respetan las convenciones del locale para separadores decimales, delimitadores de miles y símbolos de moneda.
Vistas localizadas por idioma. Para páginas con contenido significativamente diferente por locale, cree archivos de vista separados. Rails renderiza la vista adecuada basándose en 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: publique sin control de calidad manual en cada lanzamiento
Después de que PTC traduzca sus archivos config/locales/*.yml, la aplicación Rails renderizada aún necesita verificación. Una etiqueta traducida puede desbordar un botón en alemán. Un mensaje de validación en francés puede utilizar una forma gramatical incorrecta. Una cadena en inglés codificada directamente en una plantilla ERB (sin llamada a t()) se renderizará sin traducir, independientemente de cuántos idiomas publique.
El AI Visual QA de PTC sustituye al paso de control de calidad 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 ese momento, PTC reproduce la grabación en cada idioma de destino después de cada actualización de traducción, captura cada pantalla e informa de los resultados:
- Correcciones en los archivos YAML cuando PTC los controla. PTC vuelve a traducir los términos incorrectos, elige un sinónimo más corto o regenera una forma plural.
- Prompts para Cursor / Claude Code cuando el problema reside en su código Ruby o ERB. Una cadena en inglés codificada directamente fuera de
t(), un mensaje flash construido por concatenación en lugar de interpolación o un ayudante que debería usarI18n.lpara el formato de fecha.
El resultado: una aplicación Rails multilingüe verificada en cada lanzamiento. No solo archivos YAML traducidos.
Traduzca notas de lanzamiento, mailers de Devise y páginas de marketing
Sus notas de lanzamiento, los correos electrónicos orientados al cliente 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 gestiona esos textos en el mismo proyecto. Pegue el texto de origen en el panel de control de PTC, elija los idiomas de destino y obtenga traducciones que utilicen el mismo glosario y voz de marca que sus traducciones de YAML.
Traduzca sus archivos config/locales/*.yml con PTC
Comience su prueba gratuita de 30 días: 20.000 palabras en 2 idiomas, sin tarjeta de crédito. Suba sus archivos YAML, obtenga las versiones traducidas en minutos e 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 general del servicio para equipos de ingeniería.
- Guía oficial de Rails i18n: la referencia canónica.