Internationalisierung mit Rails

In diesem Tutorial lernen Sie, wie man einsprachige und mehrsprachige Webapplikationen in Ruby on Rails ab Version 2.2/2.3 erstellt.

Grundlagen

Es hat mehr als 5 Jahre gedauert, bis die Internationlisierung (kurz i18n) einzug in Ruby on Rails gefunden hat. Das wichtigste Feature von Rails 2.2 ist für die meisten Entwickler die Internationalisierung (I18n) von Rails.

Es gibt zwar zahlreiche Plugins, wie z.B. Globalize und Globalite (im Buch beschrieben), mit der die Internationalisierung auch möglich ist, jedoch haben diese grundsätzlich folgende Probleme:

  • Die PlugIns müssen immer bei neuen Updates von Rails angepasst werden
  • Keine einheitliche “Technik” für die Entwickler

Mit der neuen Funktion ist es nicht nur möglich mehrsprachige Applikationen zu entwickeln, sondern es ist nun auch einfacher, einsprachige (nicht engl.) Applikationen zu entwickeln, bei der u.a. die Datumsformate, Währungsbeträge und Fehlermeldungen in Formularen lokalsiert werden.

Wir zeigen als erstes, wie man eine einsprachige, deutschsprachige Applikation in Rails entwickelt.

Entwickeln einer einsprachigen (deutschen) Applikation

Englisch ist in Rails die Standardsprache. In der Einstellungsdatei config/environment.rb kann man die Sprache einstellen. Das schöne ist, dass Rails in dieser Datei bereits einen Eintrag für die deutsche Sprache enthält. Sie müssen lediglich das Kommentarzeichen (#) entfernen:

  config.i18n.default_locale = :de 

Als nächstes muss eine Sprachdatei angelegt werden, in der die Übersetzungen für die (deutsche) Sprache festgelegt werden. Die Sprachdateien werden im Verzeichnis config/locales angelegt. Für die deutsche Sprache wird die Datei de.yml verwendet. Diese Datei ist wie z.B. die database.yml eine YAML-Datei, die sich sehr gut für Konfigurations-Dateien eignet. In dieser Sprachdatei wird u.a. folgendes festgelegt:

  • Datumsformatierung
  • Zeitformatierung
  • Zahlen und Währungsformatierung
  • Fehlermeldungen für ActiveRecord

Sven Fuchs hat auf GitHub alle Sprachdateien gesammelt, die Sie einfach übernehmen können. Um eine Sprachdatei zu laden gehen Sie wie folgt vor:

  1. Öffnen Sie http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale
  2. Es werden dann über 40 Sprachdateien gelistet. Öffnen Sie die Datei de.yml für die deutsche Sprache und klicken auf den Link “raw” oberhalb des Listings im grauen Balken.
  3. Kopieren Sie den Inhalte über die Zwischenablage in Ihr Railsprojekt config/locales/de.yml
  4. Fügen Sie eine leere Zeile am Ende der Datei ein.

Wenn eine neue Rails Version erscheint, ist es ratsam erneut die Sprachdatei zu laden, da es zu Ergänzungen kommen kann. (was z.B. der Fall bei Rails 2.3 ist)

Auszug aus der Datei config/locales/de.yml:

de:
  date:
    formats:
      default: "%d.%m.%Y"
      short: "%e. %b"
      long: "%e. %B %Y"
      only_day: "%e"
 
    day_names: [Sonntag, Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag]
    abbr_day_names: [So, Mo, Di, Mi, Do, Fr, Sa]
    month_names: [~, Januar, Februar, März, April, Mai, Juni, Juli, August, September, Oktober, November, Dezember]
    abbr_month_names: [~, Jan, Feb, Mär, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez]
    order: [ :day, :month, :year ]
  
  time:
    formats:
      default: "%A, %e. %B %Y, %H:%M Uhr"
      short: "%e. %B, %H:%M Uhr"
      long: "%A, %e. %B %Y, %H:%M Uhr"
      time: "%H:%M"
 
    am: "vormittags"
    pm: "nachmittags"
      
  datetime:
...      
  number:
    format:
      precision: 2
      separator: ','
      delimiter: '.'
    currency:
      format:
        unit: '€'
        format: '%n%u'
        separator: 
        delimiter: 
        precision: 
...

  support:
    array:
      sentence_connector: "und"
      skip_last_comma: true
        
  activerecord:
    errors:
      template:
        header:
          one:    "Konnte dieses {{model}} Objekt nicht speichern: 1 Fehler."
          other:  "Konnte dieses {{model}} Objekt nicht speichern: {{count}} Fehler."
        body: "Bitte überprüfen Sie die folgenden Felder:"
 
      messages:
        inclusion: "ist kein gültiger Wert"
 ...
        less_than_or_equal_to: "muss kleiner oder gleich {{count}} sein"
        odd: "muss ungerade sein"
        even: "muss gerade sein"
      models:

Zur Übung werden wir nun eine einfache Ressource zum Verwalten von Büchern mit den Feldern title, price und published_at für das Veröffentlichungsdatum anlegen. Geben Sie dazu in der Konsole folgendes ein:

script/generate scaffold book title:string price:decimal published_at:date

Starten Sie anschließend den lokalen Server mit script/server und öffnen die URL http://localhost:3000/books und legen ein paar Beispielbücher an.

Was als erstes auffällt ist, dass die Auswahlfelder für das Datum bereits lokalisiert sind:

Jedoch wird das Datum sowohl in der Liste (index), also auch auf der Detailseite (show) nicht lokilisiert angezeigt:

Ändern Sie folgende Zeile in der Datei app/views/books/show.html.erb:

  <%=h @book.published_at %>

ab in

 <%= l @book.published_at %>                             

l ist ein abkürzung für I18n.localize
Das Datum wird im deutschen Format dann wie folgt angezeigt: 24.12.2009.
Es ist aber auch möglich, das Datum in folgenden Formaten darzustellen:

  • <%= l @book.published_at, :format => :short %> wird ausgeben als 24. Dez.
  • <%= l @book.published_at, :format => :only_day %> wird ausgeben als 24
  • <%= l @book.published_at, :format => :long %> wird ausgeben als 24. Dezember 2009
  • <%= l @book.published_at, :format => :standard %> wird ausgeben als 24.12.2009

Sie können, die Formate auch anpassen oder sogar ergänzen, wenn Sie die Datei config/locales/de.yml im Abschnitt date anpassen. Angenommen wir möchten das Datum wie folgt ausgeben: “Donnerstag, der 24. Dezember 2009”.
Dazu ändern wir das Format long wie folgt ab:

de:
  date:
    formats:
      default: "%d.%m.%Y"
      short: "%e. %b"
      long: "%A, der %d %B %Y"
      only_day: "%e"

Eine Tabelle mit den möglichen Format-Kürzeln findet sich z.B. hier

Mit der Option :locale => :en ist es möglich, die Sprache nur für diesen Aufruf abweichend von der Standardsprache einzustellen.
Im folgenden Beispiel wird das Veröffentlichungsdatum im englischen Format ausgegeben:

  <%= l @book.published_at, :locale => :en %> 

Datum-Zeitformatierung

Die Datum-Uhrzeit-Formatierung, funktioniert im Prinzip genauso wie bei der Datumsformatierung.

Um z.B. das Erstellungs-Datum-Uhrzeit des Datensatzes auszugeben fügen wir in der Datei app/views/books/show.html.erb folgendes ein:

<p>
  <b>Created at:</b>
  <%=l @book.created_at %>
</p>

Das Datum wird dann z.B. wie folgt angezeigt: Samstag, 14. März 2009, 10:03 Uhr
Analog zu den Datumsformaten, gibt es auch für die Zeit eigene Formate:

  • <%= l @book.created_at, :format => :time %> wird ausgegeben als 10:03
  • <%= l @book.created_at, :format => :short %> wird ausgegeben als 14. März 10:03 Uhr
  • <%= l @book.created_at, :format => :long %> wird ausgegeben als Samstag, 14. März 2009, 10:03 Uhr
  • <%= l @book.created_at, :format => :standard %> wird ausgegeben als Samstag, 14. März 2009, 10:03 Uhr

Die letzten beiden Formate sind gleich.

Währungen

Damit die Währung lokalisiert angezeigt wird, verwenden Sie den Helper number_to_currency. Ändern Sie dazu in der Datei app/views/books/show.html.erb von

  <%= h @book.price %>

in


<%= number_to_currency @book.price %>

Sie können die Datei an Ihre Bedürfnisse anpassen. Um z.B. Währungsangaben statt mit 12,94€ als EUR 12,94 zu formatieren, ändern Sie die Datei config/locales/de.yml wie folgt ab:


currency:
format:
unit: ‘EUR
format: ‘%u %n’

%u% steht für die Währungseinheit (u=Unit) und %n% steht für die Zahl (n=number).

Dezimalzahlen

Um Dezimalzahlen (z.B. 24.95) zu formatieren (ohne Währungszeichen), kann einfach der Helper number_with_precision verwendet werden:

    <%= number_with_precision 12.9543 %>

Wird bei deutscher Loklisierung als “12,95” dargestellt. Die Anzahl der Stellen wird entweder zentral in der Lokalisierungsdatei config/locales/de.yml eingestellt oder über die Option :precision des Helpers number_with_precision übergeben. Wenn Sie immer 3 Stellen nach dem Komma anzeigen möchten, sollten Sie die Einstellung der Sprachdatei vornehmen:

  number:
    format:
      precision: 3
      separator: ','
      delimiter: '.'  

Für die Formatierung von großen Zahlen (über 1000) kann auch der Helper number_with_delimiter verwendet werden.

    <%= method number_with_delimiter 1234567.5 %>

wird in der deutschen Lokalisierung, wie folgt ausgegeben: 1.234.567,5

Prozentwerte

Zur Formatierung von Prozentwerten kann der Helper number_to_percentage verwendet werden:

  <%= number_to_percentage 23.5 %>

wird in der deutschen Lokalisierung wie folgt ausgegeben: 23,50%

Entwickeln einer mehrsprachigen (deutsch und englisch) Applikation

Im folgenden werden wir die Texte lokalisieren.

Es gibt folgende Möglichkeiten die Übersetzungen im View aufzurufen:

  • I18n.t "common.hello_world"
  • I18n.translate "common.hello_world"
  • t "common.hello_world"
  • translate "common.hello_world"

Die letzten beiden Varianten funktionieren nur in Controllers und Views. Um z.B. eine Übersetzung in der Console zu verwenden, sollte I18n.t oder I18n.translate verwendet werden. Die Sprache kann manuell z.B. mit I18n.locale = "de" auf deutsch gesetzt werden.

Das I18n-Modul lädt alle .rb und .yml – Dateien innerhalb des Verzeichnisses config/locales. Wie Sie die Dateien benennen ist egal, Hauptsache die Endung ist .yml oder .rb.

Sie können die Texte Ihrer Applikation auch innerhalb der Datei config/locales/de.yml, in der die Formatierungen hinterlegt sind, anlegen oder eine eigene Datei z.B. config/locales/de_txt.yml dafür anlegen. In unserem Beispiel, enthält die Sprachdatei config/locales/de_txt.yml folgenden Inhalt:

de:
  common:
    hello_world: Hallo Welt

Das bedeutet, dass der Key common.hello_world die Zeichenkette “Hallo Welt” zurückliefert, wenn locale = de ist. Damit ein englischer Text ausgegeben wird, wenn locale = en ist, muss eine englische Sprachdatei config/locales/en_txt.yml angelegt werden:

en:
  common:
    hello_world: hello world

Um in unserer Beispielapplikation, zum Verwalten von Büchern, die Detailseite (show.html.erb) zu übersetzen, ergänzen wir die Sprachdateien wie folgt:

de:
  common:
    hello_world: Hallo Welt
    title: Titel
    price: Preis
    published_at: Erschienen am
    created_at: Angelegt am
    edit: Bearbeiten
    back: Zurück

Es ist üblich, die Keys in den Sprachdateien auf Englisch anzulegen, deshalb haben wir uns daran angepasst, aber es ist natürlich möglich, die Keys auch in einer anderen Sprache z.B. deutsch anzulegen.

In der show.html.erb können wir die Texte dann wie folgt übersetzen:

  <p>
    <b><%= t "common.title" %>:</b>
    <%=h @book.title %>
  </p>

  <p>
    <b><%= t "common.price" %>:</b>
    <%=  number_to_currency @book.price %><br />
  </p>

  <p>
    <b><%= t "common.published_at" %>:</b>
    <%=l @book.published_at, :format => :long %>
  </p>

  <p>
    <b><%= t "common.created_at" %>:</b>
    <%=l @book.created_at, :format => :long %>
  </p>


  <%= link_to t('common.edit'), edit_book_path(@book) %> |
  <%= link_to t('common.back'), books_path %>

Da in unserer Detailseite keine Texte übersetzt wurden, die nur auf dieser Seite existieren, sondern die verwendeten Begriffe auch an anderer Stelle nochmal benötigt werden könnten, haben wir uns in der Sprachdatei für den Namespace “common”, innerhalb dem wir unsere Keys definiert haben, entschieden.

Ab Rails 2.3 ist es möglich in den Sprachdateien den Pfad zu einer Ressource in den Namespaces abzubilden und dann eine Kurzform für den Aufruf der Übersetzung zu nutzen. In unserem Fall wäre also folgendes auch möglich gewesen:

de:
  books:
    show:
      title: Titel
      price: Preis
      ...
<pre>

In dem View zur Detailseite (show.html.erb), hätten wir dann die Übersetzungen wie folgt aufrufen können:

<pre>
  <p>
    <b><%= t ".title" %>:</b>
    <%=h @book.title %>
  </p>

  <p>
    <b><%= t ".price" %>:</b>
    <%=  number_to_currency @book.price %><br />
  </p>
  ...

Diese Vorgehensweise macht aber nur Sinn, wenn es sich um Texte handelt, die nur in diesem einen View vorkommen, da Sie nur für diesen View die Kurzschreibweise nutzen können. Beispielsweise könnte das eine Überschrift für die Seite sein.

Beim Anlegen der Sprachdateien müssen Sie unbedingt darauf achten, dass Sie nicht Namespaces verwenden, die bereits von Rails benutzt werden, da Sie diese sonst überschreiben. Dazu gehören z.B. “date”, “time” und “activerecord”. Einige Entwickler umgehen dies, indem sie zuerst einen Namespace “txt” oder “common” setzen, innerhalb derer sie dann die weiteren Namespaces definieren.

Existiert für eine Sprache der Applikation die zugehörige Sprachdatei oder der geforderte Eintrag nicht, wird beim Wechsel der Sprache eine Fehlermeldung, mit dem Pfad zu dem gesuchten Eintrag in der Übersetzungsdatei angegeben, z.B. translation missing en, common, hello_world

Nach jeder Änderung an einer der Übersetzungsdateien, muss der Server neu gestartet werden (dies wird sich in Rails 2.3 vermutlich ändern.)

Mehrzeilig

[folgt noch]

Pluralisierung

[folgt noch]

Seiten in einer Sprache (ab reils 2.3.)

Bei statischen Seiten, wie z.B. die Impressumsseite oder bei den AGBs ist es am einfachsten, wenn die Seiten vollständig in einer Sprach vorliegen.

[folgt noch]

Links

Sorry, comments are closed for this article.