PTC

Internationalisation Rails (i18n) : guide complet

Configurez Rails I18n, organisez config/locales/*.yml, automatisez les traductions YAML avec l'IA et laissez PTC (Private Translation Cloud) relire votre application Rails en fonctionnement à chaque nouvelle version. À la fin, vous obtiendrez une application Rails qui répond aux URL /es/..., sert des vues traduites dans 40+ langues et est vérifiée par une révision visuelle.

Ce guide part du principe que vous disposez d'une application Rails 7+ existante. Les concepts s'appliquent aux anciennes versions de Rails avec des différences d'API mineures. La gem I18n elle-même est stable depuis des années. Pour en savoir plus sur la localisation CI/CD sur l'ensemble des stacks techniques, consultez Localisation de logiciels par IA conçue pour les pipelines CI/CD.

Configurer Rails pour charger les locales, reconnaître les URL et basculer à chaque requête

L'internationalisation de Rails nécessite trois étapes de configuration. Définissez les locales disponibles, ajoutez la locale à vos URL et configurez Rails pour charger la bonne locale à chaque requête. Vous installez également la gem rails-i18n pour les données de locale.

Déclarer les locales disponibles dans config/application.rb

Dans config/application.rb, indiquez à Rails quelles langues l'application prend en charge et définissez une langue par défaut :

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 ligne load_path += Dir[...] est la plus importante. Par défaut, Rails ne charge que config/locales/*.yml (un seul niveau de profondeur). L'ajout du motif global récursif vous permet d'organiser les traductions par espace de noms, par modèle ou par fonctionnalité dans des sous-répertoires.

Ajouter :locale à votre scope d'URL

Ajoutez un scope :locale pour que chaque langue ait son propre chemin, comme /en/time ou /es/time :

# config/routes.rb
scope "/:locale" do
  get '/time', to: 'home#index', as: :time_display
end

Basculer de locale à chaque requête avec I18n.with_locale

Dans ApplicationController, chargez la bonne locale depuis l'URL et incluez-la dans tous les liens générés :

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 est la manière idiomatique de limiter une locale à une requête. Cette méthode définit la locale, exécute le bloc, restaure la locale précédente et est thread-safe. default_url_options garantit que chaque URL générée par Rails inclut la locale actuelle, afin que les utilisateurs restent dans la langue sélectionnée pendant leur navigation.

Installer rails-i18n pour les noms de mois traduits et les règles de pluralisation

La gem rails-i18n fournit des données de locale pour des dizaines de langues. Cette gem inclut les noms de mois traduits, les règles de pluralisation et les messages d'erreur Rails par défaut. Ainsi, vous n'avez pas à traduire ce boilerplate vous-même.

# Gemfile
gem 'rails-i18n'
bundle install

Votre application Rails est désormais entièrement configurée pour l'internationalisation.

Ajouter un sélecteur de langue avec url_for(locale: :code)

Puisque default_url_options inclut automatiquement la locale dans chaque URL générée, votre sélecteur n'a besoin de mettre à jour que le paramètre :locale tout en maintenant l'utilisateur sur la même page.

<%# 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>

Chaque lien utilise url_for(locale: :code) pour générer une URL avec la locale spécifiée. Lorsque les utilisateurs cliquent, switch_locale dans ApplicationController détecte le changement et Rails affiche la page dans la nouvelle langue.

Remplacer le texte en dur dans les vues par t(:key)

Le texte en dur n'apparaîtra pas dans vos fichiers YAML, ce qui signifie qu'il ne peut pas être traduit. Utilisez toujours des clés de traduction pour tout texte visible par l'utilisateur.

<%# 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>

Dans les contrôleurs (pour les flash messages) :

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

Dans les modèles (pour les messages de validation, utilisez les conventions Active Model) :

# config/locales/en.yml
en:
  activerecord:
    attributes:
      post:
        title: "Title"
    errors:
      models:
        post:
          attributes:
            title:
              blank: "is required"

Interpoler des variables avec %{name}

%{name} dans le YAML est remplacé par la valeur que vous passez à t() :

current_time: "Current time: %{time}"
<%= t(:current_time, time: @time) %>

Utiliser le lazy lookup (.key) pour les view-scoped translations

Lorsque vos clés de traduction sont organisées pour correspondre à la structure de vos dossiers de vues, utilisez un point initial. Rails remplit le préfixe à partir de la vue actuelle :

<%# Instead of this: %>
<%= t('home.index.hello') %>

<%# Use this: %>
<%= t('.hello') %>

Rails voit que vous êtes dans home/index.html.erb et ajoute le préfixe home.index.. Si vous renommez ou déplacez une vue, les chemins du lazy lookup se mettent à jour automatiquement.

Organiser config/locales/ par fonctionnalité au lieu d'un seul gros en.yml

Pour une application en conditions réelles, un seul gros en.yml devient impossible à maintenir. Organisez par fonctionnalité :

config/locales/
  en.yml                       # global / shared keys
  models/
    post.en.yml
  views/
    posts.en.yml
    home.en.yml
  flash.en.yml

Un exemple 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"

Conventions :

  • Clés imbriquées : regroupent les chaînes associées et permettent le lazy lookup.
  • Interpolation %{name} : pour les variables en ligne.
  • Clés de pluralisation zero / one / other : pour les noms dénombrables. Rails route vers la bonne clé en fonction de count: : t('posts.show.comments_count', count: 5).

Ajouter également les chaînes JavaScript au YAML

Rails n'extrait pas automatiquement le texte des fichiers JavaScript. Tout texte côté client (alertes, infobulles, messages de confirmation) doit se trouver dans votre YAML pour être traduit avec le reste :

en:
  confirm: "Are you sure?"

Lorsque vous traduirez avec PTC dans la section suivante, ces chaînes voyageront avec le reste.

Traduire config/locales/*.en.yml avec PTC en 4 étapes

Une fois vos fichiers de traduction en place, vous avez besoin de versions pour chaque langue cible. PTC s'en charge :

  1. Démarrez un projet PTC et choisissez l'anglais comme source. L'essai couvre 20 000 mots vers 2 langues, sans carte bancaire.
  2. Téléversez vos fichiers config/locales/*.en.yml. PTC analyse le YAML, reconnaît les clés de pluralisation Rails (zero, one, other, few, many) et préserve les interpolations %{name}.
  3. Ajoutez une brève description de votre application Rails et de son public. PTC utilise ce contexte pour traduire avec le bon ton et la bonne terminologie.
  4. Choisissez les langues cibles et confirmez. PTC produit posts.es.yml, posts.fr.yml, posts.de.yml, structurellement identiques à la source avec les valeurs traduites. Les formes plurielles sont générées par langue. Le polonais obtient one / few / many / other. Le japonais obtient uniquement other.

Replacez les fichiers dans config/locales/views/, redémarrez votre serveur Rails, et l'application sert les nouvelles langues.

Pour les projets basés sur Git, connectez PTC à votre dépôt. Les nouvelles chaînes dans n'importe quel *.en.yml déclenchent la traduction automatique. PTC ouvre une merge request avec les fichiers de langue cible mis à jour. Consultez la référence de l'API PTC pour les points de terminaison sous-jacents.

Utiliser I18n.with_locale dans les tâches d'arrière-plan, les mailers et les tâches cron

Le motif I18n.with_locale(locale, &block) est essentiel pour tout code qui s'exécute en dehors d'une requête normale. Cela inclut les tâches d'arrière-plan, les tâches cron et les 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

Sans with_locale, la tâche s'exécute dans la locale qui était active au démarrage du worker. Généralement :en, quelle que soit la préférence de l'utilisateur. Avec, l'e-mail est affiché dans la langue de l'utilisateur et la locale est réinitialisée lorsque le bloc se termine.

Exporter les traductions Rails vers JSON avec i18n-js pour une utilisation côté client

Les pages rendues par Rails obtiennent les traductions via t() dans ERB. Le JavaScript qui s'exécute dans le navigateur ne voit pas directement l'I18n de Rails. Le motif le plus propre utilise la gem i18n-js pour exporter les traductions au format JSON et les charger côté client.

# Gemfile
gem 'i18n-js'
bundle install
i18n init

Mettez à jour la configuration générée pour exporter les traductions vers 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

Générez le fichier JSON :

i18n export

Ceci lit tous vos fichiers YAML (en.yml, es.yml, de.yml) et écrit public/locales.json avec chaque traduction dans un format lisible par JS.

Épinglez i18n-js avec 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"

Créez un chargeur :

// app/javascript/load_locale.js
export async function loadLocale() {
  const response = await fetch('/locales.json');
  return await response.json();
}

Passez la locale actuelle au JavaScript via la balise <body> :

<%# app/views/layouts/application.html.erb %>
<body data-locale="<%= I18n.locale %>">

Ensuite, utilisez les traductions dans votre 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() fonctionne comme le helper t de Rails. Lorsque les utilisateurs changent de langue, le JavaScript utilise les bonnes traductions à partir de l'attribut data-locale.

Traduire le contenu ActiveRecord avec l'API PTC

Le motif ci-dessus traduit les chaînes statiques dans vos fichiers YAML. Le contenu ActiveRecord (publications d'utilisateurs, commentaires, descriptions de produits stockées en tant que saisie utilisateur) n'apparaît pas dans le YAML et nécessite une approche différente. L'API REST PTC traduit ce contenu à la demande avec une authentification par jeton Bearer, en utilisant le même glossaire et la même voix de marque que vos fichiers config/locales/*.yml. Envoyez votre contenu en POST à PTC, puis recevez un callback lorsque les traductions sont prêtes ou interrogez périodiquement le statut depuis une tâche d'arrière-plan.

Localiser les dates, les nombres et les devises avec les helpers Rails

Dates et heures. Utilisez le helper l (raccourci pour localize) :

<%= l Time.now, format: :long %>

La gem rails-i18n fournit des formats de date/heure par défaut pour de nombreuses langues, y compris les noms de mois traduits et le formatage spécifique à la locale. Vous pouvez définir des formats personnalisés dans vos fichiers YAML.

Nombres et devises. Rails inclut des helpers sensibles à la locale :

<%= number_to_currency(100, locale: :es) %>   <!-- 100,00 € -->
<%= number_with_delimiter(1000000) %>          <!-- 1,000,000 -->

Ceux-ci respectent les conventions de la locale pour les séparateurs décimaux, les séparateurs de milliers et les symboles monétaires.

Vues localisées par langue. Pour les pages dont le contenu diffère considérablement d'une locale à l'autre, créez des fichiers de vue séparés. Rails affiche la vue appropriée en fonction de la locale actuelle :

app/views/pages/
  about.html.erb       <!-- Default -->
  about.es.html.erb    <!-- Spanish version -->
  about.de.html.erb    <!-- German version -->

Révision visuelle de la traduction de votre application Rails en fonctionnement - passez en production sans contrôle qualité manuel à chaque version

Une fois que PTC a traduit vos config/locales/*.yml, l'application Rails rendue nécessite toujours une vérification. Une étiquette traduite peut déborder d'un bouton en allemand. Un message de validation en français peut utiliser la mauvaise forme grammaticale. Une chaîne en dur en anglais dans un modèle ERB (sans appel à t()) sera affichée non traduite, quel que soit le nombre de langues que vous déployez.

L'AI Visual QA de PTC remplace la passe de contrôle qualité manuel. Pour les applications Rails (basées sur le navigateur), installez l'extension de navigateur PTC et enregistrez un parcours guidé des écrans critiques de votre application (connexion, parcours principaux, pages d'administration). Dès lors, PTC rejoue l'enregistrement dans chaque langue cible après chaque mise à jour de traduction, capture chaque écran et fait un rapport :

  • Corrections dans les fichiers YAML lorsque PTC les contrôle. PTC retraduit un sens erroné, choisit un synonyme plus court, régénère une forme plurielle.
  • Prompts Cursor / Claude Code lorsque le problème se trouve dans votre code Ruby ou ERB. Une chaîne en dur en anglais en dehors de t(), un flash message construit par concaténation au lieu d'une interpolation, un helper qui devrait utiliser I18n.l pour le formatage des dates.

Le livrable : une application Rails multilingue vérifiée à chaque version. Pas seulement du YAML traduit.

Traduire les notes de version, les mailers Devise et les pages marketing

Vos notes de version, les e-mails destinés aux clients envoyés via Devise ou Action Mailer, et les pages marketing se trouvent en dehors de config/locales. La fonctionnalité Paste to Translate de PTC gère ce texte dans le même projet. Collez le texte source dans le tableau de bord PTC, choisissez les langues cibles, et récupérez des traductions qui utilisent le même glossaire et la même voix de marque que vos traductions YAML.

Traduire vos fichiers config/locales/*.yml avec PTC

Commencez votre essai de 30 jours - 20 000 mots vers 2 langues, sans carte bancaire. Téléversez vos fichiers YAML, obtenez les versions traduites en quelques minutes, puis installez l'extension de navigateur pour vérifier votre application Rails en fonctionnement.

Sur le même sujet :