PTC

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

  1. 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.
  2. 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.
  3. 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.
  4. 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ält one / few / many / other. Japanisch erhält nur other.

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, der I18n.l fü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: