Die Lingo.dev CLI übersetzt Rails-config/locales-YAML-Dateien über eine konfigurierte Lokalisierungs-Engine. Rails bringt die i18n API bereits mit – der übersetzbare Text deiner App liegt in YAML-Dateien pro Sprache. Lingo.dev passt in deine bestehende Pipeline, ohne zusätzliche Runtime-Abhängigkeiten einzuführen.
Diese Anleitung zeigt dir die Lokalisierung einer Rails-App von Anfang bis Ende: von der CLI-Konfiguration über die Organisation sprachspezifischer YAML-Dateien und das Umschalten der Sprache pro Request bis hin zur Automatisierung mit GitHub Actions.
Demo-Repository
Klone oder fork lingodotdev/ruby-on-rails-localization-example, um direkt mitzumachen. Das Repository enthält eine funktionsfähige Rails-App mit config/locales-YAML-Dateien, eine Konfiguration für die Lingo.dev CLI und einen GitHub-Actions-Workflow.
So funktioniert Lokalisierung in Rails#
Rails liest Übersetzungen aus YAML-Dateien unter config/locales/. Jede Datei hat auf Root-Ebene einen Sprachcode und enthält verschachtelte Schlüssel, die die Lookup-Pfade widerspiegeln, die dein Code mit I18n.t verwendet.
| Ebene | Was dort liegt | Beispieldatei |
|---|---|---|
| UI-Texte | Buttons, Labels, Flash-Meldungen | config/locales/en.yml |
| Mailer-Texte | Betreffzeilen und Inhalte für ActionMailer | config/locales/mailers.en.yml |
| Modellfehler | Validierungsmeldungen und Attributnamen | config/locales/activerecord.en.yml |
Der erste Schlüssel jeder Rails-YAML-Datei ist der Sprachcode selbst – en:, es:, fr:. Der Bucket yaml-root-key der CLI versteht genau dieses Format: Er entfernt das Sprachpräfix, bevor Inhalte an deine Lokalisierungs-Engine gesendet werden, und schreibt anschließend eine parallele Datei mit dem Ziel-Sprachcode als neuem Root-Schlüssel. Verschachtelte Schlüssel, Interpolations-Tokens wie %{name} und CLDR-Pluralkategorien (zero/one/two/few/many/other) bleiben erhalten.
Voraussetzungen#
Lokalisierungs-Engine erstellen
Jeder CLI-Durchlauf schickt Inhalte durch eine Lokalisierungs-Engine – also die Konfiguration, die festlegt, welches LLM-Modell, Glossar, Markenstimme und welche Anweisungen gelten. Erstelle sie im Lingo.dev dashboard und generiere einen API-Schlüssel.
Ruby und Rails prüfen
Diese Anleitung richtet sich an Rails 7.2 oder neuer, dafür ist Ruby 3.1 oder neuer erforderlich. Prüfe deine Versionen:
ruby -v
rails -vNode.js prüfen
Die CLI benötigt Node.js 18 oder neuer:
node -vRails i18n einrichten
Diese Anleitung setzt voraus, dass deine App Übersetzungen bereits in config/locales/*.yml speichert. Wenn du noch hartcodierte Strings in Views oder Controllern hast, extrahiere sie zuerst in t()-Aufrufe. Ersetze zum Beispiel:
<h1>Welcome</h1>durch:
<h1><%= t(".welcome") %></h1>und ergänze anschließend den passenden Schlüssel in config/locales/en.yml. Die vollständigen Migrationsschritte findest du im Rails-Leitfaden zur Internationalisierung.
Übersetzungsdateien organisieren#
Rails lädt jede *.yml-Datei unter config/locales/ automatisch. Lege die Quellsprache direkt neben die übersetzten Varianten, damit das Verzeichnis als zentrale Single Source of Truth dient:
config/locales/
en.yml # Source locale
es.yml # Generated by Lingo.dev
fr.yml
de.ymlEine typische en.yml enthält eine Mischung aus einfachen Strings, verschachtelten Namespaces, %{name}-Interpolation und Pluralisierung:
en:
hello: "Hello"
home:
welcome: "Welcome, %{name}!"
cta: "Get started"
notifications:
unread:
zero: "No unread notifications"
one: "1 unread notification"
other: "%{count} unread notifications"
errors:
messages:
blank: "can't be blank"CLI konfigurieren#
Erstelle im Root-Verzeichnis deines Projekts eine i18n.json-Datei. Deklariere darin einen Bucket yaml-root-key, der auf die Sprachdateien zeigt:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de"]
},
"buckets": {
"yaml-root-key": {
"include": ["config/locales/[locale].yml"]
}
}
}Der Platzhalter [locale] wird mit jedem konfigurierten Sprachcode aufgelöst. Mit source: "en" liest die CLI config/locales/en.yml und schreibt die übersetzten Dateien nach config/locales/es.yml, config/locales/fr.yml und config/locales/de.yml.
Rails lädt problemlos mailers.en.yml, pages.en.yml und weitere Dateien neben en.yml. Füge dem Array include in deinem Bucket yaml-root-key einfach zusätzliche Muster hinzu:
{
"buckets": {
"yaml-root-key": {
"include": [
"config/locales/[locale].yml",
"config/locales/mailers.[locale].yml",
"config/locales/pages.[locale].yml"
]
}
}
}Rails für mehrere Sprachen konfigurieren#
Teile Rails mit, welche Sprachen verfügbar sind und welche standardmäßig verwendet werden soll. In config/application.rb:
module YourApp
class Application < Rails::Application
config.i18n.available_locales = [:en, :es, :fr, :de]
config.i18n.default_locale = :en
config.i18n.fallbacks = [:en]
end
endLege die Sprache pro Request in ApplicationController über einen URL-Parameter oder den Header Accept-Language fest:
class ApplicationController < ActionController::Base
around_action :switch_locale
private
def switch_locale(&action)
locale = params[:locale] || http_accept_locale || I18n.default_locale
I18n.with_locale(locale, &action)
end
def http_accept_locale
header = request.headers["Accept-Language"].to_s
header.scan(/[a-z]{2}/).find { |l| I18n.available_locales.map(&:to_s).include?(l) }
end
def default_url_options
{ locale: I18n.locale }
end
endÜbersetzungen in Views ausgeben#
Verwende die Helper t und l in ERB-Templates. Ein führender Punkt im Schlüssel wird relativ zum aktuellen View-Pfad aufgelöst, sodass die Übersetzungsschlüssel direkt bei den Templates bleiben, die sie verwenden:
<h1><%= t(".welcome", name: @user_name) %></h1>
<p><%= t("notifications.unread", count: @unread_count) %></p>
<%= link_to t(".cta"), signup_path, class: "btn-primary" %>Füge deinem Layout einen Sprachumschalter hinzu:
<nav>
<% I18n.available_locales.each do |locale| %>
<%= link_to locale.upcase, url_for(locale: locale) %>
<% end %>
</nav>Lokal übersetzen#
Setze deinen API-Schlüssel und führe die CLI aus:
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest runDie CLI liest alle Dateien, die zu deinen Bucket-Mustern passen, erkennt mit dem Lockfile unübersetzte Einträge, übersetzt nur das Delta über deine Lokalisierungs-Engine und schreibt die Ergebnisse in jede Zieldatei. Der Root-Schlüssel der Sprache, verschachtelte Namespaces, Interpolations-Tokens im Stil von %{name} und Pluralkategorien bleiben erhalten – nur der übersetzbare Text ändert sich.
So targetest du während der Entwicklung eine bestimmte Sprache:
npx lingo.dev@latest run --target-locale esStarte den Rails-Server nach dem ersten Übersetzungslauf neu, damit die neuen YAML-Dateien geladen werden:
bin/rails serverÖffne /es, um die spanische Ausgabe zu sehen.
Pluralformen#
Rails verwendet CLDR-Pluralkategorien – zero, one, two, few, many, other. Übergib ein Argument count: an I18n.t, und Rails wählt automatisch den passenden Schlüssel:
t("notifications.unread", count: 0) # => "No unread notifications"
t("notifications.unread", count: 1) # => "1 unread notification"
t("notifications.unread", count: 12) # => "12 unread notifications"Die CLI übersetzt jede Pluralvariante direkt an Ort und Stelle. Wenn deine Zielsprache mehr Kategorien als die englischen one/other braucht, definiere sie in deinem Quell-en.yml.
Mit GitHub Actions automatisieren#
Füge unter .github/workflows/translate.yml eine Workflow-Datei hinzu, damit bei jedem Push übersetzt wird:
Übersetzungen werden direkt in main committet – reibungslos und ideal für kleine Teams:
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lingo.dev
uses: lingodotdev/lingo.dev@main
with:
api-key: ${{ secrets.LINGODOTDEV_API_KEY }}Speichere deinen API-Schlüssel als LINGODOTDEV_API_KEY unter Settings > Secrets and variables > Actions in deinem GitHub-Repository.
Vor dem Deployment prüfen#
Verwende das Flag --frozen als Deployment-Gate, damit keine unübersetzten Inhalte in Produktion gehen. Wenn noch Einträge übersetzt werden müssen, beendet sich die CLI mit einem Status ungleich null:
npx lingo.dev@latest run --frozenFüge das als separaten CI-Schritt vor dem Precompile deiner Assets oder dem Container-Build hinzu:
- name: Verify translations
run: npx lingo.dev@latest run --frozen
- name: Precompile assets
run: bundle exec rails assets:precompile