10.2. Eine einsprachig deutsche
Rails-Applikation
Es reicht bei einer nur für deutsche User ausgerichteten
Rails-Applikation leider nicht aus, einfach alle Views ins Deutsche zu
übersetzen. Die Vorgehensweise ähnelt in vielen Punkten der einer
mehrsprachigen Rails-Applikation (siehe
Abschnitt 10.3, „Mehrsprachige
Rails-Applikation“). Entsprechend wird es
einige Wiederholungen geben. Anhand einer einfachen Applikation zeige ich
Ihnen, welche Schritte beachtet werden müssen. Gehen wir alle diese
Änderung an folgender Literaturverzeichnis-Applikation durch:
MacBook:~ xyz$ rails new bibliography
[...]
MacBook:~ xyz$ cd bibliography
MacBook:bibliography xyz$ rails generate scaffold book title number_of_pages:integer 'price:decimal{7,2}'
[...]
MacBook:bibliography xyz$ rake db:migrate
[...]
MacBook:bibliography xyz$
Um Beispiele für Validierungsfehler zu bekommen, fügen Sie bitte in
der
app/models/book.rb
folgende Validierungen
ein:
class Book < ActiveRecord::Base
attr_accessible :number_of_pages, :price, :title
validates :title,
:presence => true,
:uniqueness => true,
:length => { :within => 2..255 }
validates :price,
:presence => true,
:numericality => { :greater_than => 0 }
end
Bitte suchen Sie in der Konfigurations-Datei
config/application.rb
nach dem Wert
config.i18n.default_locale
und setzen Sie ihn auf
:de
für deutsch. Im gleichen Zusammenhang fügen wir dann auch
in der Zeile darüber noch zwei weitere Verzeichnisse für Übersetzungen der
Models und der Views ein. Diese Verzeichnisstruktur ist nicht technisch
notwendig, verschafft aber bei größeren Applikationen einen besseren
Überblick:
# 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 = :de
Die entsprechenden Verzeichnisse müssen dann noch angelegt
werden:
MacBook:bibliography xyz$ mkdir -p config/locales/models/book
MacBook:bibliography xyz$ mkdir -p config/locales/views/book
MacBook:bibliography xyz$
Jetzt müssen Sie eine Sprachkonfigurationsdatei für Deutsch
generieren oder einfacher eine fertige von Sven Fuchs aus seinem
Github-Repository
https://github.com/svenfuchs/rails-i18n
downloaden:
MacBook:bibliography 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$
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.
Als Nächstes müssen wir Rails erklären, dass in Deutsch ein Model
'book' nicht 'book', sondern 'Buch' heißt. Das Gleiche gilt für alle
Attribute. Dafür legen wir die Datei
config/locales/models/book/de.yml
mit folgender
Struktur an. Als Nebeneffekt bekommen wir die Methoden
Model.model_name.human
und
Model.human_attribute_name(attribute)
, mit denen
wir die Model- und Attributnamen im View einfügen können.
# ruby encoding: utf-8
de:
activerecord:
models:
book: 'Buch'
attributes:
book:
title: 'Titel'
number_of_pages: 'Seitenanzahl'
price: 'Preis'
In der Datei
config/locales/views/book/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_you_sure: Sind Sie sicher?
back: Zurück
edit: Editieren
book:
index:
title: Bücherliste
new: Neues Buch
edit:
title: Buch editieren
new:
title: Neues Buch
flash_messages:
book_was_successfully_created: 'Das Buch wurde erfolgreich angelegt.'
book_was_successfully_updated: 'Das Buch wurde erfolgreich aktualisiert.'
Jetzt müssen wir noch "ein paar" Veränderungen in den Views
einbauen. Wir benutzen dabei den
I18n.t
Helper,
der im View auch mit
t
abgekürzt werden kann.
I18n.t
ließt aus der YAML-Datei den
entsprechenden Eintrag aus. Wir könnten bei einer rein deutschsprachigen
Applikation auch direkt den deutschen Text in den View schreiben, aber so
können wir im Fall des Falles leichter auf Mehrsprachigkeit umstellen.
Mehr Informationen zu I18n.t finden Sie unter
„I18n.t“.
app/views/books/_form.html.erb
<%= form_for(@book) do |f| %>
<% if @book.errors.any? %>
<div id="error_explanation">
<h2><%= t 'activerecord.errors.template.header', :model => Book.model_name.human, :count => @book.errors.count %></h2>
<ul>
<% @book.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :number_of_pages %><br />
<%= f.number_field :number_of_pages %>
</div>
<div class="field">
<%= f.label :price %><br />
<%= f.text_field :price %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
app/views/books/edit.html.erb
<h1><%= t 'views.book.edit.title' %></h1>
<%= render 'form' %>
<%= link_to I18n.t('views.show'), @book %> |
<%= link_to I18n.t('views.back'), books_path %>
app/views/books/index.html.erb
<h1><%= t 'views.book.index.title' %></h1>
<table>
<tr>
<th><%= Book.human_attribute_name(:title) %></th>
<th><%= Book.human_attribute_name(:number_of_pages) %></th>
<th><%= Book.human_attribute_name(:price) %></th>
<th></th>
<th></th>
<th></th>
</tr>
<% @books.each do |book| %>
<tr>
<td><%= book.title %></td>
<td><%= number_with_delimiter(book.number_of_pages) %></td>
<td><%= number_to_currency(book.price) %></td>
<td><%= link_to I18n.t('views.show'), book %></td>
<td><%= link_to I18n.t('views.edit'), edit_book_path(book) %></td>
<td><%= link_to I18n.t('views.destroy'), book, confirm: I18n.t('views.are_you_sure'), method: :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to I18n.t('views.book.index.new'), new_book_path %>
app/views/books/new.html.erb
<h1><%= t 'views.book.new.title' %></h1>
<%= render 'form' %>
<%= link_to I18n.t('views.back'), books_path %>
app/views/books/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<b><%= Book.human_attribute_name(:title) %>:</b>
<%= @book.title %>
</p>
<p>
<b><%= Book.human_attribute_name(:number_of_pages) %>:</b>
<%= number_with_delimiter(@book.number_of_pages) %>
</p>
<p>
<b><%= Book.human_attribute_name(:price) %>:</b>
<%= number_to_currency(@book.price) %>
</p>
<%= link_to I18n.t('views.edit'), edit_book_path(@book) %> |
<%= link_to I18n.t('views.back'), books_path %>
Anmerkung
Im show- und index-View habe ich die Helper
number_with_delimiter
und
number_to_currency
eingebaut, damit die Zahlen
für den End-User schöner dargestellt werden.
Ganz zum Schluss müssen wir im Controller
app/controllers/books_controller.rb
noch ein paar
Flash-Messages anpassen:
class BooksController < ApplicationController
# GET /books
# GET /books.json
def index
@books = Book.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @books }
end
end
# GET /books/1
# GET /books/1.json
def show
@book = Book.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @book }
end
end
# GET /books/new
# GET /books/new.json
def new
@book = Book.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @book }
end
end
# GET /books/1/edit
def edit
@book = Book.find(params[:id])
end
# POST /books
# POST /books.json
def create
@book = Book.new(params[:book])
respond_to do |format|
if @book.save
format.html { redirect_to @book, notice: I18n.t('views.book.flash_messages.book_was_successfully_created') }
format.json { render json: @book, status: :created, location: @book }
else
format.html { render action: "new" }
format.json { render json: @book.errors, status: :unprocessable_entity }
end
end
end
# PUT /books/1
# PUT /books/1.json
def update
@book = Book.find(params[:id])
respond_to do |format|
if @book.update_attributes(params[:book])
format.html { redirect_to @book, notice: I18n.t('views.book.flash_messages.book_was_successfully_updated') }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @book.errors, status: :unprocessable_entity }
end
end
end
# DELETE /books/1
# DELETE /books/1.json
def destroy
@book = Book.find(params[:id])
@book.destroy
respond_to do |format|
format.html { redirect_to books_url }
format.json { head :no_content }
end
end
end
Jetzt können Sie die vom Scaffold Generator angelegten Views
komplett auf Deutsch benutzen. Die hier gezeigte Struktur der YAML-Dateien
lässt sich natürlich nach eigenem Geschmack anpassen. Die Texte in den
Views und im Controller werden mit I18n.t
angezeigt. An dieser Stelle könnte man natürlich bei einer
rein deutschen Anwendung auch direkt den deutschen Text einbauen.
Unsere Bücherliste ist komplett deutsch, aber die aufzurufenden
URLs sind alle noch in Englisch. Wenn wir alle Bücher unter der URL
http://0.0.0.0:3000/buecher
und nicht unter
http://0.0.0.0:3000/books
abrufbar machen möchten, so müssen wir in der
config/routes.rb
folgenden Eintrag
machen:
Bibliography::Application.routes.draw do
scope(:path_names => { :new => "neu", :edit => "bearbeiten" }) do
resources :books, :path => "buecher"
end
end
Damit ergeben sich folgende neue Pfade:
MacBook:bibliography xyz$ rake routes
books GET /buecher(.:format) books#index
POST /buecher(.:format) books#create
new_book GET /buecher/neu(.:format) books#new
edit_book GET /buecher/:id/bearbeiten(.:format) books#edit
book GET /buecher/:id(.:format) books#show
PUT /buecher/:id(.:format) books#update
DELETE /buecher/:id(.:format) books#destroy
MacBook:bibliography xyz$
Das Schöne an den Rails-Routen ist, dass Sie nicht mehr machen
müssen. Der Rest wird transparent von den Routen verwaltet.