PTC

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 en count:: 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:

  1. 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.
  2. 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}.
  3. 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.
  4. 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 obtiene one / few / many / other. El japonés obtiene solo other.

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 usar I18n.l para 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: