Rails-Internationalisierung (i18n): Der vollständige Leitfaden
Konfigurieren Sie Rails I18n, organisieren Sie config/locales/*.yml, automatisieren Sie YAML-Übersetzungen mit KI und lassen Sie die PTC (Private Translation Cloud) Ihre laufende Rails-App bei jedem Release prüfen. Am Ende werden Sie eine Rails-App haben, die auf /es/...-URLs reagiert, übersetzte Views in 40+ Sprachen ausliefert und durch eine visuelle Prüfung verifiziert ist.
Dieser Leitfaden setzt voraus, dass Sie eine bestehende Rails 7+-App haben. Die Konzepte gelten mit geringfügigen API-Unterschieden auch für ältere Rails-Versionen. Das I18n-Gem selbst ist seit Jahren stabil. Für den umfassenderen Ansatz zur CI/CD-Lokalisierung über verschiedene Stacks hinweg, lesen Sie KI-Software-Lokalisierung für CI/CD-Pipelines entwickelt.
Rails konfigurieren, um Locales zu laden, URLs zu erkennen und pro Request zu wechseln
Die Rails-Internationalisierung erfordert drei Konfigurationsschritte. Legen Sie verfügbare Locales fest, fügen Sie das Locale zu Ihren URLs hinzu und sorgen Sie dafür, dass Rails das richtige Locale pro Request lädt. Außerdem installieren Sie das rails-i18n-Gem für Locale-Daten.
Verfügbare Locales in config/application.rb deklarieren
Teilen Sie Rails in config/application.rb mit, welche Sprachen die App unterstützt, und legen Sie einen Standard fest:
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
Die Zeile load_path += Dir[...] ist entscheidend. Standardmäßig lädt Rails nur config/locales/*.yml (eine Ebene tief). Durch das Hinzufügen des rekursiven Globs können Sie Übersetzungen nach Namespace, Modell oder Funktion in Unterverzeichnissen organisieren.
:locale zu Ihrem URL-Scope hinzufügen
Fügen Sie einen :locale-Scope hinzu, damit jede Sprache ihren eigenen Pfad hat, wie /en/time oder /es/time:
# config/routes.rb
scope "/:locale" do
get '/time', to: 'home#index', as: :time_display
end
Locale pro Request mit I18n.with_locale wechseln
Laden Sie in ApplicationController das richtige Locale aus der URL und fügen Sie es in alle generierten Links ein:
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 ist der idiomatische Weg, um ein Locale auf einen Request zu beschränken (scoping). Es setzt das Locale, führt den Block aus, stellt das vorherige Locale wieder her und ist threadsicher. default_url_options stellt sicher, dass jede von Rails generierte URL das aktuelle Locale enthält, sodass Benutzer beim Navigieren in der von ihnen ausgewählten Sprache bleiben.
rails-i18n für übersetzte Monatsnamen und Pluralisierungsregeln installieren
Das rails-i18n-Gem bietet Locale-Daten für Dutzende von Sprachen. Dieses Gem liefert übersetzte Monatsnamen, Pluralisierungsregeln und Standard-Rails-Fehlermeldungen aus. So müssen Sie diesen Standardtext (Boilerplate) nicht selbst übersetzen.
# Gemfile
gem 'rails-i18n'
bundle install
Ihre Rails-App ist nun vollständig für die Internationalisierung konfiguriert.
Einen Sprachumschalter mit url_for(locale: :code) hinzufügen
Da default_url_options das Locale automatisch in jede generierte URL aufnimmt, muss Ihr Sprachumschalter nur den :locale-Parameter aktualisieren und den Benutzer auf derselben Seite belassen.
<%# 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>
Jeder Link verwendet url_for(locale: :code), um eine URL mit dem angegebenen Locale zu generieren. Wenn Benutzer klicken, erkennt switch_locale in ApplicationController die Änderung und Rails rendert die Seite in der neuen Sprache.
Hardcodierten Text in Views durch t(:key) ersetzen
Hardcodierter Text taucht nicht in Ihren YAML-Dateien auf, was bedeutet, dass er nicht übersetzt werden kann. Verwenden Sie für jeden benutzerseitigen Text immer Übersetzungs-Keys.
<%# 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>
In Controllern (für 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
In Modellen (verwenden Sie für Validierungsmeldungen die Active Model-Konventionen):
# config/locales/en.yml
en:
activerecord:
attributes:
post:
title: "Title"
errors:
models:
post:
attributes:
title:
blank: "is required"
Variablen mit %{name} einsetzen
%{name} im YAML wird durch den Wert ersetzt, den Sie an t() übergeben:
current_time: "Current time: %{time}"
<%= t(:current_time, time: @time) %>
Lazy Lookup (.key) für View-bezogene Übersetzungen verwenden
Wenn Ihre Übersetzungs-Keys so organisiert sind, dass sie Ihrer View-Ordnerstruktur entsprechen, verwenden Sie einen führenden Punkt. Rails füllt das Präfix aus der aktuellen View aus:
<%# Instead of this: %>
<%= t('home.index.hello') %>
<%# Use this: %>
<%= t('.hello') %>
Rails erkennt, dass Sie sich in home/index.html.erb befinden, und stellt home.index. voran. Wenn Sie eine View umbenennen oder verschieben, werden die Lazy-Lookup-Pfade automatisch aktualisiert.
config/locales/ nach Funktion statt in einer riesigen en.yml organisieren
Für eine reale App wird eine einzige riesige en.yml unwartbar. Organisieren Sie nach Funktion:
config/locales/
en.yml # global / shared keys
models/
post.en.yml
views/
posts.en.yml
home.en.yml
flash.en.yml
Eine beispielhafte 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"
Konventionen:
- Verschachtelte Keys gruppieren verwandte Strings und ermöglichen den Lazy Lookup.
%{name}-Einsetzung (Interpolation) für Inline-Variablen.zero- /one- /other-Pluralisierungs-Keys für zählbare Substantive. Rails leitet basierend aufcount:an den richtigen Key weiter:t('posts.show.comments_count', count: 5).
JavaScript-Strings ebenfalls zu YAML hinzufügen
Rails extrahiert Text nicht automatisch aus JavaScript-Dateien. Jeder clientseitige Text (Warnungen, Tooltips, Bestätigungsmeldungen) muss in Ihrem YAML liegen, damit er zusammen mit allem anderen übersetzt wird:
en:
confirm: "Are you sure?"
Wenn Sie im nächsten Abschnitt mit der PTC übersetzen, werden diese Strings mit dem Rest verarbeitet.
config/locales/*.en.yml mit der PTC in 4 Schritten übersetzen
Sobald Ihre Übersetzungsdateien bereitstehen, benötigen Sie Versionen für jede Zielsprache. Die PTC übernimmt das:
- Starten Sie ein PTC-Projekt und wählen Sie Englisch als Quelle. Die Testphase deckt 20.000 Wörter in 2 Sprachen ab, ohne Kreditkarte.
- Laden Sie Ihre
config/locales/*.en.yml-Dateien hoch. Die PTC parst das YAML, erkennt Rails-Pluralisierungs-Keys (zero,one,other,few,many) und behält%{name}-Einsetzungen bei. - Fügen Sie eine kurze Beschreibung Ihrer Rails-App und der Zielgruppe hinzu. Die PTC nutzt diesen Kontext, um mit der richtigen Tonalität und Terminologie zu übersetzen.
- Wählen Sie die Zielsprachen aus und bestätigen Sie. Die PTC erzeugt
posts.es.yml,posts.fr.yml,posts.de.yml, strukturell identisch mit der Quelle, jedoch mit übersetzten Werten. Pluralformen werden pro Sprache generiert. Polnisch erhältone/few/many/other. Japanisch erhält nurother.
Legen Sie die Dateien zurück in config/locales/views/, starten Sie Ihren Rails-Server neu, und die App liefert die neuen Sprachen aus.
Bei Git-gesteuerten Projekten verknüpfen Sie die PTC mit Ihrem Repo. Neue Strings in einer beliebigen *.en.yml lösen eine automatische Übersetzung aus. Die PTC öffnet einen Merge Request mit den aktualisierten Zielsprachen-Dateien. Siehe die PTC-API-Referenz für die zugrunde liegenden Endpunkte.
I18n.with_locale in Hintergrund-Jobs, Mailern und Cron-Tasks verwenden
Das I18n.with_locale(locale, &block)-Muster ist entscheidend für jeden Code, der außerhalb eines normalen Requests ausgeführt wird. Das schließt Hintergrund-Jobs, Cron-Tasks und Mailer ein.
# 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
Ohne with_locale läuft der Job in dem Locale, das aktiv war, als der Worker gestartet wurde. Normalerweise :en, unabhängig von der Präferenz des Benutzers. Mit dieser Methode wird die E-Mail in der Sprache des Benutzers gerendert und das Locale zurückgesetzt, wenn der Block endet.
Rails-Übersetzungen mit i18n-js für die clientseitige Nutzung in JSON exportieren
Von Rails gerenderte Seiten erhalten Übersetzungen über t() in ERB. JavaScript, das im Browser ausgeführt wird, sieht das I18n von Rails nicht direkt. Das sauberste Muster verwendet das i18n-js-Gem, um Übersetzungen als JSON zu exportieren und sie clientseitig zu laden.
# Gemfile
gem 'i18n-js'
bundle install
i18n init
Aktualisieren Sie die generierte Konfiguration, um Übersetzungen nach public/locales.json zu exportieren:
# config/i18n.rb
require "i18n-js"
I18n::JS.config do |config|
config.export_i18n_js = false
config.translations_path = "public/locales.json"
end
Generieren Sie die JSON-Datei:
i18n export
Dies liest alle Ihre YAML-Dateien (en.yml, es.yml, de.yml) und schreibt public/locales.json mit jeder Übersetzung in einem JS-lesbaren Format.
Pinnen Sie i18n-js mit der 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"
Erstellen Sie einen Loader:
// app/javascript/load_locale.js
export async function loadLocale() {
const response = await fetch('/locales.json');
return await response.json();
}
Übergeben Sie das aktuelle Locale über das <body>-Tag an JavaScript:
<%# app/views/layouts/application.html.erb %>
<body data-locale="<%= I18n.locale %>">
Verwenden Sie dann die Übersetzungen in Ihrem 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() funktioniert wie der t-Helper von Rails. Wenn Benutzer die Sprache wechseln, verwendet JavaScript die korrekten Übersetzungen aus dem data-locale-Attribut.
ActiveRecord-Inhalte mit der PTC-API übersetzen
Das obige Muster übersetzt statische Strings in Ihren YAML-Dateien. ActiveRecord-Inhalte (Benutzerbeiträge, Kommentare, Produktbeschreibungen, die als Benutzereingaben gespeichert werden) tauchen nicht im YAML auf und erfordern einen anderen Ansatz. Die PTC-REST-API übersetzt diese Inhalte bei Bedarf mit Bearer-Token-Authentifizierung und verwendet dabei dasselbe Glossar und dieselbe Markenstimme wie Ihre config/locales/*.yml-Dateien. Senden Sie Ihre Inhalte per POST an die PTC und empfangen Sie dann entweder einen Callback, wenn die Übersetzungen fertig sind, oder fragen Sie den Status aus einem Hintergrund-Job ab.
Daten, Zahlen und Währungen mit Rails-Helpern lokalisieren
Datum und Uhrzeit. Verwenden Sie den l-Helper (kurz für localize):
<%= l Time.now, format: :long %>
Das rails-i18n-Gem bietet Standard-Datums-/Uhrzeitformate für viele Sprachen, einschließlich übersetzter Monatsnamen und locale-spezifischer Formatierung. Sie können benutzerdefinierte Formate in Ihren YAML-Dateien definieren.
Zahlen und Währungen. Rails enthält locale-abhängige Helper:
<%= number_to_currency(100, locale: :es) %> <!-- 100,00 € -->
<%= number_with_delimiter(1000000) %> <!-- 1,000,000 -->
Diese respektieren Locale-Konventionen für Dezimaltrennzeichen, Tausendertrennzeichen und Währungssymbole.
Lokalisierte Views pro Sprache. Erstellen Sie für Seiten mit deutlich unterschiedlichen Inhalten pro Locale separate View-Dateien. Rails rendert die entsprechende View basierend auf dem aktuellen Locale:
app/views/pages/
about.html.erb <!-- Default -->
about.es.html.erb <!-- Spanish version -->
about.de.html.erb <!-- German version -->
Visuelle Übersetzungsprüfung Ihrer laufenden Rails-App – ohne manuelle QA pro Release veröffentlichen
Nachdem die PTC Ihre config/locales/*.yml übersetzt hat, muss die gerenderte Rails-App noch verifiziert werden. Ein übersetztes Label könnte im Deutschen über den Button hinausragen. Eine französische Validierungsmeldung verwendet möglicherweise die falsche grammatikalische Form. Ein hardcodierter englischer String in einem ERB-Template (ohne t()-Aufruf) wird unübersetzt gerendert, unabhängig davon, wie viele Sprachen Sie veröffentlichen.
Die AI Visual QA der PTC ersetzt den manuellen QA-Durchlauf. Installieren Sie für Rails-Apps (browserbasiert) die PTC-Browser-Erweiterung und zeichnen Sie einen Rundgang durch die kritischen Bildschirme Ihrer App auf (Anmeldung, Hauptabläufe, Admin-Seiten). Von da an spielt die PTC die Aufzeichnung nach jedem Übersetzungsupdate in jeder Zielsprache ab, erfasst jeden Bildschirm und meldet Folgendes zurück:
- Korrekturen in den YAML-Dateien, wenn die PTC diese kontrolliert. Die PTC übersetzt eine falsche Bedeutung neu, wählt ein kürzeres Synonym und generiert eine Pluralform neu.
- Cursor- / Claude Code-Prompts, wenn der Fehler in Ihrem Ruby- oder ERB-Code liegt. Ein hardcodierter englischer String außerhalb von
t(), eine Flash-Message, die durch Verkettung statt durch Einsetzung erstellt wurde, oder ein Helper, derI18n.lfür die Datumsformatierung verwenden sollte.
Das Ergebnis: eine verifizierte mehrsprachige Rails-App pro Release. Nicht nur übersetztes YAML.
Release Notes, Devise-Mailer und Marketingseiten übersetzen
Ihre Release Notes, kundenorientierten E-Mails, die über Devise oder Action Mailer gesendet werden, und Marketingseiten leben außerhalb von config/locales. Das Paste to Translate der PTC verarbeitet diesen Text im selben Projekt. Fügen Sie den Ausgangstext im PTC-Dashboard ein, wählen Sie die Zielsprachen und erhalten Sie Übersetzungen zurück, die dasselbe Glossar und dieselbe Markenstimme wie Ihre YAML-Übersetzungen verwenden.
Ihre config/locales/*.yml-Dateien mit der PTC übersetzen
Starten Sie Ihre 30-Tage-Testphase – 20.000 Wörter in 2 Sprachen, keine Kreditkarte. Laden Sie Ihre YAML-Dateien hoch, erhalten Sie in wenigen Minuten übersetzte Versionen und installieren Sie dann die Browser-Erweiterung, um Ihre laufende Rails-App zu verifizieren.
Verwandte Themen:
- PTC-API-Referenz – REST-Endpunkte für die CI-Integration.
- KI-Software-Lokalisierung für CI/CD-Pipelines entwickelt – Service-Übersicht für Entwicklerteams.
- Offizieller Rails-i18n-Leitfaden – die kanonische Referenz.