Rails 5.1 Consulting und Schulung vom Autor:
www.wintermeyer-consulting.de/rails/

10.3. Mehrsprachige Rails-Applikation

Die Vorgehensweise bei mehrsprachigen Rails-Applikationen ähnelt sehr der in Abschnitt 10.2, „Eine einsprachig deutsche Rails-Applikation“ gezeigten rein deutschen Rails-Applikation. Allerdings müssen wir YAML-Sprachdateien für alle benötigten Sprachen definieren und der Rails-Applikation sagen, welche Sprache gerade benutzt werden soll. Dazu verwenden wir I18n.locale.

I18n.locale zum Definieren der gewünschten Sprache benutzen

Natürlich muss eine Rails-Applikation wissen, in welcher Sprache eine Webseite dargestellt werden soll. I18n.locale speichert die aktuelle Sprache ab und kann von der Applikation ausgelesen werden. Ich zeige Ihnen das mit einem Mini-Webshop-Beispiel:
MacBook:~ xyz$ rails new webshop
[...]
MacBook:~ xyz$ cd webshop
MacBook:webshop xyz$ 
Dieser bekommt eine Homepage:
MacBook:webshop xyz$ rails generate controller Page index
[...]
MacBook:webshop xyz$ rm public/index.html 
MacBook:webshop xyz$
Diese müssen wir noch in der config/routes.rb als Root-Seite eintragen:
Webshop::Application.routes.draw do

  root :to => 'page#index'
  get "page/index"

end
Die app/views/page/index.html.erb füllen wir mit folgendem Beispiel:
<h1>Example Webshop</h1>
<p>Welcome to this webshop.</p>

<p><b>I18n.locale:</b> 
<%= I18n.locale %>
</p>
Wenn wir den Rails-Server mit rails server starten und im Browser http://0.0.0.0:3000/ aufrufen, dann sehen wir folgende Webseite:
Index-Seite page#index
Sie sehen, dass "en" für Englisch als Default eingestellt ist. Stoppen Sie den Rails-Server mit CTRL-C und ändern Sie in der Datei config/application.rb die Einstellung für die Default-Sprache auf:
    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]

    config.i18n.default_locale = :de
Wenn Sie danach rails server starten und mit dem Webbrowser http://0.0.0.0:3000/ wieder aufrufen, dann sehen Sie folgende Webseite:
Index-Seite page#index mit config.i18n.default_locale = :de
Die Webseite hat sich nicht verändert, aber als Ausgabe von <%= I18n.locale %> bekommen Sie jetzt 'de' für Deutsch und nicht mehr 'en' für Englisch angezeigt.
Bitte stoppen Sie den Rails-Server mit CTRL-C und ändern Sie in der Datei config/application.rb die Einstellung für die Default-Sprache auf en für Englisch:
    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]

    config.i18n.default_locale = :en
Wir wissen jetzt, wie der Default für I18n.locale in der gesamten Applikation gesetzt wird, aber das ist ja nur die halbe Miete. Ein User möchte sich seine Sprache selber aussuchen. Dafür gibt es verschiedene Ansätze. Zum Veranschaulichen dieser Ansätze brauchen wir eine zweite Seite, die einen deutschen Text anzeigt. Bitte legen Sie die Datei app/views/page/index.de.html.erb mit diesem Inhalt an:
<h1>Beispiel Webshop</h1>
<p>Willkommen in diesem Webshop.</p>

<p><b>I18n.locale:</b> 
<%= I18n.locale %>
</p>

I18n.locale per URL Path-Prefix setzen

Der charmante Weg, die Sprache zu setzen, ist sie als Prefix mit in die URL aufzunehmen. So können Suchmaschinen besser verschiedene Sprachversionen verwalten. http://0.0.0.0:3000/de soll die deutsche Version der Homepage und http://0.0.0.0:3000/en die englische Version der Homepage anzeigen. Der erste Schritt dafür ist eine Anpassung der config/routes.rb:
Webshop::Application.routes.draw do

  scope "(:locale)", :locale => /en|de/ do
    root :to => 'page#index'
    get "page/index"
  end

end
Als Nächstes müssen wir in der app/controllers/application_controller.rb einen before_filter setzen, der den von der Route gesetzten Parameter locale als I18n.locale setzt:
class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :set_locale
 
  private
  def set_locale
    I18n.locale = params[:locale] || I18n.default_locale
  end
end
Zum Testen Rails mit rails server starten und die URL http://0.0.0.0:3000/de aufrufen.
http://0.0.0.0:3000/de
Natürlich können wir auch http://0.0.0.0:3000/de/page/index aufrufen:
http://0.0.0.0:3000/de/page/index
Beim Aufruf von http://0.0.0.0:3000/en und http://0.0.0.0:3000/en/page/index bekommen wir die jeweils englischen Seiten angezeigt.
Jetzt haben wir aber ein Problem: Zwar kommen wir initial mit dem Prefix auf eine Seite mit der richtigen Sprache, aber was ist, wenn wir von dieser Seite auf eine andere Seite in unserem Rails-Projekt verlinken wollen? Dann müssten wir den Prefix manuell in den Link einbauen. Das will keiner. Deshalb gibt es eine Lösung in Form von Rails.application.routes.default_url_options. Wir müssen nur unsere set_locale-Methode in app/controllers/application_controller.rb entsprechend erweitern:
class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :set_locale
 
  private
  def set_locale
    I18n.locale = params[:locale] || I18n.default_locale
    Rails.application.routes.default_url_options[:locale]= I18n.locale 
  end
end
Damit werden alle mit link_to und url_for (auf das link_to aufsetzt) erzeugten Links automatisch um den Parameter locale erweitert. Sie müssen nichts weiter tun. Alle mit dem Scaffold Generator generierten Links werden automatisch entsprechend verändert.
Navigationsbeispiel
Um dem User die Möglichkeit zu geben, einfach zwischen den Sprachversionen hin- und herzuschalten, bieten sich am Kopf der Webseite zwei Links an. Dabei sollte die aktuelle Sprache nicht als aktiver Link angezeigt werden. Dies kann man in der app/views/layouts/application.html.erb-Datei für alle Views wie folgt realisieren:
<!DOCTYPE html>
<html>
<head>
  <title>Webshop</title>
  <%= stylesheet_link_tag    "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>
</head>
<body>

<p>
<%= link_to_unless I18n.locale == :en, "English", locale: :en %>
|
<%= link_to_unless I18n.locale == :de, "Deutsch", locale: :de %>
</p>

<%= yield %>

</body>
</html>
Die Navigation wird dann am Kopf der Seite angezeigt.
Sprachauswahl in der Kopfzeile

I18n.locale per Accept-Language HTTP Header des Browsers setzen

Wenn ein User Ihre Webseite zum ersten Mal aufruft, möchten Sie ihm im Idealfall direkt die Webseite in der richtigen Sprache anzeigen. Dafür können Sie das Accept-Language Feld im HTTP Header auslesen. In jedem Webbrowser kann der Benutzer der Software seine bevorzugte Sprache einstellen (siehe http://www.w3.org/International/questions/qa-lang-priorities). Dieser Wert wird dem Webserver und damit Rails automatisch vom Browser mitgeteilt.
Bitte verändern Sie app/controllers/application_controller.rb wie folgt ab:
class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :set_locale
 
  private
  def extract_locale_from_accept_language_header
    request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
  end

  def set_locale
    I18n.locale = extract_locale_from_accept_language_header || I18n.default_locale
  end
end
Und vergessen Sie bitte nicht, die config/routes.rb von den Einstellungen in „I18n.locale per URL Path-Prefix setzen“ zu bereinigen:
Webshop::Application.routes.draw do

  get "page/index"
  root :to => 'page#index'

end
Jetzt bekommen Sie immer die im Webbrowser definierte Sprache ausgeliefert. Dabei ist zu beachten, dass request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first nicht alle Fälle abfängt. So sollten Sie überprüfen, ob Sie in Ihrer Rails-Applikation die angegebene Sprache überhaupt unterstützen. Es gibt einige fertige Gems, die Ihnen diese Arbeit einfach abnehmen. Die Suchmaschine Ihrer Wahl wird Ihnen bei der Suche helfen.

I18n.locale in einer Session abspeichern

Oft soll der Wert von I18n.locale in einer Session (siehe Abschnitt 8.2, „Sessions“) gespeichert werden.

Tipp

Der hier mit Sessions beschriebene Weg funktioniert natürlich genau so gut mit Cookies. Siehe Abschnitt 8.1, „Cookies“.
Legen wir zum Setzen des Wertes als Beispiel in unserem Webshop einen Controller SetLanguage mit den beiden Actions english und german an:
MacBook:webshop xyz$ rails generate controller SetLanguage english german
[...]
MacBook:webshop xyz$ 
In der app/controllers/set_language_controller.rb-Datei füllen wir die beiden Actions wie folgt:
class SetLanguageController < ApplicationController
  def english
    I18n.locale = :en
    set_session_and_redirect
  end

  def german
    I18n.locale = :de
    set_session_and_redirect
  end

  private
  def set_session_and_redirect
    session[:locale] = I18n.locale
    redirect_to :back
    rescue ActionController::RedirectBackError
      redirect_to :root
  end
end
Zum Schluss müssen wir noch in der Datei app/controllers/application_controller.rb die set_locale-Methode anpassen:
class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :set_locale
 
  private
  def set_locale
    I18n.locale = session[:locale] || I18n.default_locale
    session[:locale] = I18n.locale
  end
end
Jetzt können Sie nach dem Starten von Rails mit rails server mit dem Aufruf der URL http://0.0.0.0:3000/set_language/german die Sprache auf Deutsch und mit dem Aufruf von http://0.0.0.0:3000/set_language/english die Sprache auf Englisch stellen.
Navigationsbeispiel
Um dem User die Möglichkeit zu geben, einfach zwischen den Sprachversionen hin- und herzuschalten, bieten sich am Kopf der Webseite zwei Links an. Dabei sollte die aktuelle Sprache nicht als aktiver Link angezeigt werden. Dies kann man in der app/views/layouts/application.html.erb-Datei für alle Views wie folgt realisieren:
<!DOCTYPE html>
<html>
<head>
  <title>Webshop</title>
  <%= stylesheet_link_tag    "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>
</head>
<body>

<p>
<%= link_to_unless I18n.locale == :en, "English", set_language_english_path %>
|
<%= link_to_unless I18n.locale == :de, "Deutsch", set_language_german_path %>
</p>

<%= yield %>

</body>
</html>
Die Navigation wird dann am Kopf der Seite angezeigt.
Sprachauswahl in der Kopfzeile

I18n.locale per Domain-Endung setzen

Wenn Sie mehrere Domains mit den für die entsprechenden Sprachen typischen Domain-Endungen haben, dann können Sie natürlich darüber auch die Sprache setzen. So würde ein Besucher von http://www.example.com die englische Version und ein Besucher von http://www.example.de die deutsche Version angezeigt bekommen.
Dazu müssen wir in der app/controllers/application_controller.rb einen before_filter setzen, der die aufgerufene Domain analysiert und I18n.locale setzt:
class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :set_locale
 
  private
  def set_locale
    case request.host.split('.').last
    when 'de'
      I18n.locale = :de
    when 'com'
      I18n.locale = :en
    else
      I18n.locale = I18n.default_locale
    end 
  end
 
end

Tipp

Zum Testen dieser Funktionalität können Sie auf Ihrem Linux- oder Mac OS X-Entwicklungssystem in der Datei /etc/hosts die folgenden Einträge hinzufügen:
0.0.0.0 www.example.com
0.0.0.0 www.example.de
Danach können Sie die URLs http://www.example.com:3000 und http://www.example.de:3000 aufrufen und bekommen die entsprechenden Sprachversionen angezeigt.

Welcher Weg ist der beste?

Meiner Meinung nach führt eine Kombination der vorgestellten Wege zum besten Ergebnis. Als Erst-Besucher einer Webseite freue ich mich, wenn der Accept-Language HTTP Header meines Browsers korrekt gelesen und umgesetzt wird. Es ist aber auch schön, die Sprache später in der User-Konfiguration ändern zu können (gerade bei schlecht übersetzten Seite ist oft Englisch besser). Und zum Schluss muss man sagen, dass eine gute Abbildbarkeit der Seite inklusive der Sprachen für eine Suchmaschine sehr viel wert ist. Rails gibt Ihnen die Möglichkeit, alle Varianten leicht zu benutzen und sogar zu verknüpfen.

Mehrsprachige Scaffolds

Als Beispiel benutzen wir einen Mini-Webshop, in dem wir einen Product Scaffold übersetzen. Das Ziel ist, die Applikation in Deutsch und Englisch zur Verfügung zu stellen. Die Rails-Applikation:
MacBook:~ xyz$ rails new webshop
[...]
MacBook:~ xyz$ cd webshop
MacBook:webshop xyz$ rails generate scaffold Product name description 'price:decimal{7,2}'
[...]
MacBook:webshop xyz$ rake db:migrate
[...]
MacBook:webshop xyz$ 
Das Product-Model definieren wir in der app/models/product.rb:
class Product < ActiveRecord::Base
  attr_accessible :description, :name, :price

  validates :name,
            :presence => true,
            :uniqueness => true,
            :length => { :within => 2..255 }

  validates :price,
            :presence => true,
            :numericality => { :greater_than => 0 }
end
Bei der Sprachauswahl für den User nehmen wir die URL-Prefix-Variante, die in „I18n.locale per URL Path-Prefix setzen“ beschrieben wird. Dazu verwenden wir folgende app/controllers/application_controller.rb:
class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :set_locale
 
  private
  def set_locale
    I18n.locale = params[:locale] || I18n.default_locale
    Rails.application.routes.default_url_options[:locale]= I18n.locale
  end
end
Diese config/routes.rb:
Webshop::Application.routes.draw do

  scope "(:locale)", :locale => /en|de/ do
    root :to => 'products#index'
    resources :products
  end

end
Fügen Sie in der app/views/layouts/application.html.erb noch die Links für die Navigation ein:
<!DOCTYPE html>
<html>
<head>
  <title>Webshop</title>
  <%= stylesheet_link_tag    "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>
</head>
<body>

<p>
<%= link_to_unless I18n.locale == :en, "English", locale: :en %>
|
<%= link_to_unless I18n.locale == :de, "Deutsch", locale: :de %>
</p>

<%= yield %>

</body>
</html>
Und vor dem Starten von Rails mit rails server löschen wir noch die public/index.html-Datei, damit wir als Root-Seite die Liste aller Produkte angezeigt bekommen.
MacBook:webshop xyz$ rm public/index.html 
MacBook:webshop xyz$ rails server
=> Booting WEBrick
=> Rails 3.2.3 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2012-06-01 10:43:06] INFO  WEBrick 1.3.1
[2012-06-01 10:43:06] INFO  ruby 1.9.3 (2012-04-20) [x86_64-darwin11.3.0]
[2012-06-01 10:43:06] INFO  WEBrick::HTTPServer#start: pid=51412 port=3000
Beim Aufruf von http://0.0.0.0:3000 bekommen wir die normale englische Seite angezeigt.
Grundversion
Wenn wir auf Deutsch klicken, verändert sich bis auf die Sprachnavigation ganz oben nichts auf der Seite.
Grundversion de
Bei beiden Sprachen haben wir die Datei app/views/products/index.html.erb gerendet. Sie enthält folgenden Code:
<h1>Listing products</h1>

<table>
  <tr>
    <th>Name</th>
    <th>Description</th>
    <th>Price</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @products.each do |product| %>
  <tr>
    <td><%= product.name %></td>
    <td><%= product.description %></td>
    <td><%= product.price %></td>
    <td><%= link_to 'Show', product %></td>
    <td><%= link_to 'Edit', edit_product_path(product) %></td>
    <td><%= link_to 'Destroy', product, confirm: 'Are you sure?', method: :delete %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New Product', new_product_path %>
Jetzt müssen wir nur noch einen Weg finden, die einzelnen Elemente dieser Seite sinnvoll und möglichst generisch zu übersetzen.

Textbausteine im YAML-Format

Jetzt müssen wir für I18n.t die einzelnen Textbausteine definieren. Die entsprechenden Verzeichnisse müssen dazu noch angelegt werden:
MacBook:webshop xyz$ mkdir -p config/locales/models/product
MacBook:webshop xyz$ mkdir -p config/locales/views/product
MacBook:webshop xyz$
Damit die dort angelegten YAML-Dateien auch automatisch eingelesen werden, müssen Sie die folgenden Zeilen in der Datei config/application.rb einfügen:
    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', 'models', '*', '*.yml').to_s]
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', 'views', '*', '*.yml').to_s]
    config.i18n.default_locale = :en
Deutsch
Bitte legen Sie die Datei config/locales/models/product/de.yml mit folgendem Inhalt an.
# ruby encoding: utf-8

de:
  activerecord:
    models:
      product: 'Produkt'
    attributes:
      product:
        name: 'Name'
        description: 'Beschreibung'
        price: 'Preis'
In der Datei config/locales/views/product/de.yml fügen wir ein paar Werte für die Scaffold Views ein:
# ruby encoding: utf-8

de:
  views:
    show: Anzeigen
    edit: Editieren
    destroy: Löschen
    are_your_sure: Sind Sie sicher?
    back: Zurück
    edit: Editieren
    product:
      index:
        title: Liste aller Produkte
        new_product: Neues Produkt
      edit:
        title: Produkt editieren
      new:
        title: Neues Produkt
      flash_messages:
        product_was_successfully_created: 'Das Produkt wurde erfolgreich angelegt.'
        product_was_successfully_updated: 'Das Produkt wurde erfolgreich aktualisiert.'
Zum Schluss kopieren wir noch eine fertige Standard-Übersetzung von Sven Fuchs aus seinem Github-Repository https://github.com/svenfuchs/rails-i18n:
MacBook:webshop xyz$ cd config/locales
MacBook:locales xyz$ curl -O https://raw.github.com/svenfuchs/rails-i18n/master/rails/locale/de.yml
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  4940  100  4940    0     0   9574      0 --:--:-- --:--:-- --:--:-- 11932
MacBook:locales xyz$ cd ../..
MacBook:webshop xyz$ 

Anmerkung

Wenn Sie wissen, wie Bundler funktioniert, können Sie auch die Zeile gem 'rails-i18n' in die Datei Gemfile einfügen und danach bundle ausführen. Damit bekommen Sie alle Sprachdateien aus dem Repository eingespielt.
In der config/locales/de.yml-Datei sind die benötigten Formate und generischen Formulierungen für Deutsch enthalten, die wir für eine normale Rails-Applikation benötigen (z. B. die Wochentage, Währungssymbol usw.). Schauen Sie einmal mit Ihrem Lieblingseditor rein, um einen Überblick zu bekommen.
Englisch
Da für Englisch die meisten Sachen schon im System vorhanden sind, müssen wir nur in der Datei config/locales/views/product/en.yml ein paar Werte für die Scaffold Views einfügen:
en:
  views:
    show: Show
    edit: Edit
    destroy: Delete
    are_you_sure: Are you sure?
    back: Back
    edit: Edit
    product:
      index:
        title: List of all products
        new_product: New product
      edit:
        title: Edit Product
      new:
        title: New product
      flash_messages:
        product_was_successfully_created: 'Product was successfully created.'
        product_was_successfully_updated: 'Product was successfully updated.'

Views mit I18n.t ausstatten

Bitte verändern Sie die aufgeführten View-Dateien wie angegeben.
_form.html.erb
In der Datei app/views/products/_form.html.erb müssen wir im oberen Teil die Anzeige der Validierungsfehler auf I18n.t umstellen. Die Namen der Formularfehler werden automatisch aus activerecord.attributes.product eingelesen:
<%= form_for(@product) do |f| %>
  <% if @product.errors.any? %>
    <div id="error_explanation">
      <h2><%= t 'activerecord.errors.template.header', :model => Product.model_name.human, :count => @product.errors.count %></h2>

      <ul>
      <% @product.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :description %><br />
    <%= f.text_field :description %>
  </div>
  <div class="field">
    <%= f.label :price %><br />
    <%= f.text_field :price %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>
edit.html.erb
In der Datei app/views/products/edit.html.erb müssen wir die Überschrift und die Links am Fuß der Seite mit I18n.t einbauen:
<h1><%= t 'views.product.edit.title' %></h1>

<%= render 'form' %>

<%= link_to I18n.t('views.show'), @product %> |
<%= link_to I18n.t('views.back'), products_path %>
index.html.erb
In der Datei app/views/products/index.html.erb müssen wir so gut wie jede Zeile verändern. Im Tabellenkopf benutze ich dafür human_attribute_name(), das könnte aber auch direkt mit I18n.t gemacht werden. Der Preis des Produktes wird mit dem Helper number_to_currency angegeben. In einer realen Applikation müssen wir an dieser Stelle noch eine definierte Währung angeben.
<h1><%= t 'views.product.index.listing_products' %></h1>

<table>
  <tr>
    <th><%= Product.human_attribute_name(:name) %></th>
    <th><%= Product.human_attribute_name(:description) %></th>
    <th><%= Product.human_attribute_name(:price) %></th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @products.each do |product| %>
  <tr>
    <td><%= product.name %></td>
    <td><%= product.description %></td>
    <td><%= number_to_currency(product.price) %></td>
    <td><%= link_to I18n.t('views.show'), product %></td>
    <td><%= link_to I18n.t('views.edit'), edit_product_path(product) %></td>
    <td><%= link_to I18n.t('views.destroy'), product, confirm: I18n.t('views.are_you_sure'), method: :delete %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to I18n.t('views.product.index.new_product'), new_product_path %>
new.html.erb
In der app/views/products/new.html.erb müssen die Überschrift und der Link angepasst werden:
<h1><%= t 'views.product.new.title' %></h1>

<%= render 'form' %>

<%= link_to I18n.t('views.back'), products_path %>
show.html.erb
In der app/views/products/show.html.erb benutzen wir wieder human_attribute_name() für die Attribute. Zusätzlich müssen noch die Links mit I18n.t übersetzt werden. Wie beim index View benutzen wir auch number_to_currency(), um den Preis formatiert anzuzeigen:
<p id="notice"><%= notice %></p>

<p>
  <b><%= Product.human_attribute_name(:name) %>:</b>
  <%= @product.name %>
</p>

<p>
  <b><%= Product.human_attribute_name(:description) %>:</b>
  <%= @product.description %>
</p>

<p>
  <b><%= Product.human_attribute_name(:price) %>:</b>
  <%= number_to_currency(@product.price) %>
</p>

<%= link_to I18n.t('views.edit'), edit_product_path(@product) %> |
<%= link_to I18n.t('views.back'), products_path %>

Flash-Messages im Controller übersetzen

Zum Schluss müssen wir in der app/controllers/products_controller.rb die zwei Flash-Nachrichten beim Erstellen (create) und Updaten (update) von Datensätzen mit I18n.t übersetzen:
class ProductsController < ApplicationController
  # GET /products
  # GET /products.json
  def index
    @products = Product.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @products }
    end
  end

  # GET /products/1
  # GET /products/1.json
  def show
    @product = Product.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @product }
    end
  end

  # GET /products/new
  # GET /products/new.json
  def new
    @product = Product.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @product }
    end
  end

  # GET /products/1/edit
  def edit
    @product = Product.find(params[:id])
  end

  # POST /products
  # POST /products.json
  def create
    @product = Product.new(params[:product])

    respond_to do |format|
      if @product.save
        format.html { redirect_to @product, notice: I18n.t('views.product.flash_messages.product_was_successfully_created') }
        format.json { render json: @product, status: :created, location: @product }
      else
        format.html { render action: "new" }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

  # PUT /products/1
  # PUT /products/1.json
  def update
    @product = Product.find(params[:id])

    respond_to do |format|
      if @product.update_attributes(params[:product])
        format.html { redirect_to @product, notice: I18n.t('views.product.flash_messages.product_was_successfully_updated') }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /products/1
  # DELETE /products/1.json
  def destroy
    @product = Product.find(params[:id])
    @product.destroy

    respond_to do |format|
      format.html { redirect_to products_url }
      format.json { head :no_content }
    end
  end
end

Das Ergebnis

Jetzt können Sie das Scaffold products sowohl in Deutsch als auch in Englisch bedienen. Die Umschaltung der Sprache erfolgt über den Link am Kopf der Seite.

Autor

Stefan Wintermeyer