<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>meier-online &#187; Ruby</title>
	<atom:link href="http://meier-online.com/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://meier-online.com</link>
	<description>Der Blog von Karsten Meier</description>
	<lastBuildDate>Sun, 09 Oct 2011 13:27:57 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Eins plus Zwei</title>
		<link>http://meier-online.com/2010/12/one-plus_two/</link>
		<comments>http://meier-online.com/2010/12/one-plus_two/#comments</comments>
		<pubDate>Thu, 30 Dec 2010 17:42:11 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Fallen]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Typumwandlung]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=726</guid>
		<description><![CDATA[Eine Überraschung in Ruby. Selbst bei so etwas einfachen wie der Addition von Zahlen gibt es manchmal Überraschungen. Doch der Reihe nach. Wenn wir den interaktiven Ruby-Interpreter &#8220;irb&#8221; starten, können wir in als einfachen Rechner nutzen. irb&#62; 1+2 =&#62; 3 So weit so praktisch. In der Programmierpraxis liegen Zahlen häufig als String vor, z.B in [...]]]></description>
			<content:encoded><![CDATA[<h3>Eine Überraschung in Ruby.</h3>
<p>Selbst bei so etwas einfachen wie der Addition von Zahlen gibt es manchmal Überraschungen. Doch der Reihe nach. Wenn wir den interaktiven Ruby-Interpreter &#8220;irb&#8221; starten, können wir in als einfachen Rechner nutzen.</p>
<pre>irb&gt; 1+2
=&gt; 3</pre>
<p>So weit so praktisch. In der Programmierpraxis liegen Zahlen häufig als String vor, z.B in Textdateien oder als Formularparameter in Webseiten. Probieren wir also folgendes:</p>
<pre>&gt; input="1"
&gt; input+2
TypeError: can't convert Fixnum into String</pre>
<p>Richtig, wir müssen in Ruby erst explizit den String in einen Integer umwandeln. Dafür gibt es die Methode to_i</p>
<pre>&gt; input.to_i+2
=&gt; 3</pre>
<p>Ok, damit es etwas besser aussieht, fügen wir ein Leerzeichen ein</p>
<pre>&gt; input.to_i +2
=&gt; 1</pre>
<p>Huch? Was war das? Ist unsere Variable vielleicht überschrieben worden? Probieren wir es mal direkt:</p>
<pre>&gt;"1".to_i+2
=&gt; 3</pre>
<pre>&gt;"1".to_i +2
=&gt; 1</pre>
<p>Bei einen Leerzeichen vor dem Pluszeichen und keinem Leerzeichen nach dem Pluszeichen gibt es ein anderes Ergebnis. Wo kann dieses Ergebnis herkommen? Probieren wir andere Zahlen:</p>
<pre>&gt;"2".to_i +2
=&gt; 0</pre>
<p>Es wird immer rätselhafter!</p>
<pre>
&gt; "1".to_i +1
ArgumentError: illegal radix 1
</pre>
<p>Aha, es gibt eine Spur. Vielleicht schaut wir uns die Dokumentation der Methode &#8220;to_i&#8221;genauer an:</p>
<p><a title="Dokumentation Ruby String Klasse" href="http://ruby-doc.org/core/classes/String.html#M000787">http://ruby-doc.org/core/classes/String.html#M000787</a></p>
<p>Die Methode to_i hat demnach einen optionalen Parameter Namens &#8220;radix&#8221;. Der String kann als Zahl im Hexadecimal-, Decimal, Octal- oder Binärsystem interpretiert werden.</p>
<p>Weiter steht dort momentan: &#8220;This method *never* raises an exception.&#8221; Also soll die Methode, falls sie auf Grund von unerlaubten Eingaben zu Fehlern führt, immer 0 liefern, und niemals eine Exception erzeugen. Gut, wenn das so exakt dokumentiert ist. Leider ist die Aussage so nicht richtig, denn der ArgumentError ist schließlich auch eine Exception.</p>
<p>Wie hilft uns dies jetzt, das eigenartige Verhalten zu erklären? In Ruby kann man die Klammern auch bei einen Funktionsaufruf weglassen. Offenbar macht unser Rubyinterpreter aus:</p>
<pre>"1".to_i +2</pre>
<pre>"1".to_i( +2 ) =&gt; "1".to_i( 2 ) =&gt; 1</pre>
<p>Der String &#8220;1&#8243; wird als Binärzahl interpretiert, und liefert dann die Zahl 1. Eine Addition findet nicht mehr statt. So lässt sich auch erklären:</p>
<pre>"2".to_i(+2) = 0</pre>
<p>Ruby versucht den String &#8220;2&#8243; als Binärzahl zu interpretieren. Das geht nicht, weil Binärzahlen nur aus 0 und 1 bestehen. Ruby liefert dann wie dokumentiert einfach eine 0 zurück.</p>
<p>Insgesamt bleibt dabei ein ungutes Gefühl: Selbst bei einer einfachen Addition kann durch hinzufügen oder weglassen von Leerzeichen aus einen korrekten Programm ein Falsches werden. Leider der Preis, den man in Ruby  für den Verzicht auf Klammern zahlen muss. In diesen Fall ermöglicht  der optionale Parameter der Methode &#8220;to_i&#8221; diese Mehrdeutigkeiten. Optionale Klammern in Zusammenspiel mit optionalen Parametern sind leider eine gefährliche Kombination.</p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2010/12/one-plus_two/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mehrsprachige Webseiten mit Ruby on Rails (3)</title>
		<link>http://meier-online.com/2010/01/mehrsprachige-webseiten-mit-ruby-on-rails-3/</link>
		<comments>http://meier-online.com/2010/01/mehrsprachige-webseiten-mit-ruby-on-rails-3/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 10:02:16 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Mehrsprachigkeit]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=656</guid>
		<description><![CDATA[Teil 3 &#8211; Qualitätssicherung Texte gehören zu den Teilen einer Anwendung, die häufig geändert werden. Wenn dann noch externe Übersetzer im Spiel sind, kann es leicht zu fehlenden Übersetzungen kommen Wir möchten deshalb automatisch testen, dass es zu allen Texten in Sprache A auch Übersetzungen in Sprache B vorhanden sind. Ein solcher Test allein hilft [...]]]></description>
			<content:encoded><![CDATA[<p>Teil 3 &#8211; Qualitätssicherung</p>
<p>Texte gehören zu den Teilen einer Anwendung, die häufig geändert werden. Wenn dann noch externe Übersetzer im Spiel sind, kann es leicht zu fehlenden Übersetzungen kommen</p>
<p>Wir möchten deshalb automatisch testen, dass es zu allen Texten in Sprache A auch Übersetzungen in Sprache B vorhanden sind. Ein solcher Test allein hilft schon sehr, und sollte ja nicht so schwierig sein.<br />
<span id="more-656"></span></p>
<p>Leider gibt es dabei eine Überraschung: in der Internationalisierung-API findet sich zur Zeit (Rails 2.3.5) keine Möglichkeit, alle Schlüssel aufzuzählen (sprich iterieren). Man muss also offenbar die Yaml-Dateien selbst einlesen, um an die Menge aller definierten Schlüssel zu kommen. Unserer Test wird dabei leider abhängig von der konkreten Art der Datenhaltung.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">texts_hash = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">IO</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'config/locales/de.yml'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Wie haben nun einen rekursiven Hash. Um alle Schlüssel zu überprüfen, extrahieren wie sie mit einer gesonderten Funktion. Diese Funktion ist einfach rekursiv aufgebaut.<br />
<img src="http://meier-online.com/blog/uploads/rails-i18n-hash.png" alt="Extrahieren der Schlüssel aus einen verschachtelten Hash" title="rails-i18n-hash" width="400" height="240" class="alignnone size-full wp-image-670" /></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> deep_hash_key<span style="color:#006600; font-weight:bold;">&#40;</span>hash, prefix<span style="color:#006600; font-weight:bold;">&#41;</span>
  hash.<span style="color:#9900CC;">keys</span>.<span style="color:#9900CC;">sort</span>.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>key2<span style="color:#006600; font-weight:bold;">|</span>
    val = hash<span style="color:#006600; font-weight:bold;">&#91;</span>key2<span style="color:#006600; font-weight:bold;">&#93;</span>
    newprefix = prefix.<span style="color:#0000FF; font-weight:bold;">nil</span>? ? key2 : <span style="color:#996600;">&quot;#{prefix}.#{key2}&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> val.<span style="color:#9900CC;">is_a</span>? <span style="color:#CC00FF; font-weight:bold;">Hash</span>
     deep_hash_key<span style="color:#006600; font-weight:bold;">&#40;</span>val, newprefix<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      newprefix
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Wollen wir jetzt die Übersetzungen für alle Schlüssel prüfen lauert die Zweite Falle: Wenn die Übersetzung eine Variableninterpolation enthält, erhalten wir einen Fehler beim Aufrufen der translate() Methode ohne den passenden Hash. Offenbar liefert uns die API auch keinen Zugriff auf den String ohne Interpolierung. Da uns in diesen Test nur die Existenz einer Übersetzung interessiert, und nicht ihr konkreter Wert, fangen wir die Exception &#8220;MissingInterpolationArgument&#8221; einfach auf.</p>
<p>Für eine deutsche Anwendung mit Übersetzungen in Englisch und Französisch sieht dann der Test so aus:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> test_all_texts_should_exists
  texts_hash = <span style="color:#CC00FF; font-weight:bold;">YAML</span>::<span style="color:#CC0066; font-weight:bold;">load</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">IO</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'config/locales/de.yml'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  de_keys = deep_hash_key<span style="color:#006600; font-weight:bold;">&#40;</span>texts_hash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'de'</span><span style="color:#006600; font-weight:bold;">&#93;</span>, <span style="color:#0000FF; font-weight:bold;">nil</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">flatten</span>
  <span style="color:#9966CC; font-weight:bold;">for</span> lang <span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'de'</span>, <span style="color:#996600;">'fr'</span>, <span style="color:#996600;">'en'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    I18n::locale = lang
    <span style="color:#9966CC; font-weight:bold;">for</span> key <span style="color:#9966CC; font-weight:bold;">in</span> de_keys
      <span style="color:#9966CC; font-weight:bold;">begin</span>
        val = I18n.<span style="color:#9900CC;">translate</span><span style="color:#006600; font-weight:bold;">&#40;</span>key, <span style="color:#ff3333; font-weight:bold;">:default</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">nil</span>, :<span style="color:#CC0066; font-weight:bold;">raise</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#6666ff; font-weight:bold;">I18n::MissingTranslationData</span>
        val = <span style="color:#0000FF; font-weight:bold;">nil</span>
      <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#6666ff; font-weight:bold;">I18n::MissingInterpolationArgument</span>
        val = <span style="color:#0000FF; font-weight:bold;">true</span>  <span style="color:#008000; font-style:italic;"># there was a value, only an argument is missing</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
      assert_not_nil<span style="color:#006600; font-weight:bold;">&#40;</span>val, <span style="color:#996600;">&quot;key missing for locale #{lang}: #{key}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Wenn jetzt eine Übersetzung fehlt, liefert der Test eine Fehlermeldung der Art:</p>
<pre>
test_all_texts_should_exists(LocalisationTest): key missing for locale en: users.edit.title</pre>
<p>Die fehlende Übersetzung können wir dann ergänzen, bevor wir eine neue Version der Anwendung veröffentlichen. </p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2010/01/mehrsprachige-webseiten-mit-ruby-on-rails-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mehrsprachige Webseiten mit Ruby on Rails (2)</title>
		<link>http://meier-online.com/2009/05/localize-ruby-on-rails-p2/</link>
		<comments>http://meier-online.com/2009/05/localize-ruby-on-rails-p2/#comments</comments>
		<pubDate>Tue, 12 May 2009 13:51:47 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Mehrsprachigkeit]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Validierungen]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=422</guid>
		<description><![CDATA[Teil 2 &#8211; Platzhalter, Validierungen, Modellklassen [Zu Teil 1] Oft enthalten Webseiten Sätze, in denen sich ein einzelnes Wort sich dynamisch ändert. Beispielsweise &#8220;Sie sind als xxxx eingeloggt.&#8221; Zur Übersetzung können wir natürlich den Satz aus seinen Bestandteilen zusammenzubauen. Oft gibt es ein Problem: in verschiedenen Sprachen ist der Satzbau anders. Besser ist deshalb die [...]]]></description>
			<content:encoded><![CDATA[<h3>Teil 2 &#8211; Platzhalter, Validierungen, Modellklassen</h3>
<p>[<a href="/2009/04/localize-ruby-on-rails/">Zu Teil 1</a>]</p>
<p>Oft enthalten Webseiten Sätze, in denen sich ein einzelnes Wort sich dynamisch ändert. Beispielsweise &#8220;Sie sind als xxxx eingeloggt.&#8221; Zur Übersetzung können wir natürlich den Satz aus seinen Bestandteilen zusammenzubauen. Oft gibt es ein Problem: in verschiedenen Sprachen ist der Satzbau anders.</p>
<p>Besser ist deshalb die sogenannte Interpolation, wie man sie in Ruby ja kennt. Im Satz steht ein markierter Platzhalter, der zur Laufzeit ersetzt wird. Die yaml-Datei zur Spezifikation nutzt hierbei nicht die Ruby Syntax, sondern markiert die zu ersetzenden durch doppelte geschweifte Klammern. Achtung: In Rails 3 hat sich die Syntax leicht geändert.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># Definition</span>
  logmsg: <span style="color:#996600;">&quot;Sie sind als {{name}} eingeloggt.&quot;</span>
<span style="color:#008000; font-style:italic;"># Definition in Rails 3</span>
  logmsg: <span style="color:#996600;">&quot;Sie sind als %{name} eingeloggt.&quot;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Aufruf</span>
I18n.<span style="color:#9900CC;">translate</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:logmsg</span>, <span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Administrator'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#008000; font-style:italic;"># oder in kurz</span>
t <span style="color:#ff3333; font-weight:bold;">:logmsg</span>, <span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Administrator'</span></pre></div></div>

<p>Wir müssen dabei sicherstellen, das die Parameter von Definition und Aufruf übereinstimmen. Die <em>translate()</em>-Methode dabei relativ tolerant: Überflüssige Parameter werden ignoriert, fehlende Parameter werden mit einem &#8220;(???)&#8221; ersetzt.</p>
<p>:!: Achtung: die übersetzende Person muss wissen, dass sie die Variablennamen in den Klammern nicht mit übersetzen soll!<br />
Eine weitere kleine Falle lauert bei den Variablennamen: Sie dürfen nicht wie eine der anderen Parameter der <em>translate()</em>-Methode heißen. Verboten sind deshalb &#8220;default&#8221; und &#8220;scope&#8221;.</p>
<p><span id="more-422"></span></p>
<h3>Texte der Validierungen</h3>
<p>Selbst wenn wir unsere Applikation nur einsprachig auf deutsch erstellen, gibt es an einer Stelle eine Überraschung: bei den automatisch generierten Fehlermeldungen der Validierungen in den Model-Klassen. Sehr praktisch, aber dummerweise in Englisch. Außerdem setzen sie die Klassennamen und Attributnamen direkt ein. Die Namen der Klassen und Attribute wählen wir normalerweise nach den Bedürfnissen der Programmierer, für die Benutzer sind gelegentlich andere Vokabeln angebrachter.</p>
<p>Der Aufbau einer Fehlermeldung bei einer fehlgeschlagenen Validierung ist im Bild zu sehen:</p>
<p><img class="alignnone size-full wp-image-444" title="Zusammenbau der Übersetzung von Fehlermeldungen der Model-Validierunegn in Rails" src="http://meier-online.com/blog/uploads/rails-fehlermeldungen-ersetzung400.png" alt="Zusammenbau der Übersetzung von Fehlermeldungen der Model-Validierungen in Rails" width="420" height="212" /></p>
<p>Zur Anzeige auf Deutsch müssen wir die Texte nur mit den richtigen Schlüsseln in unsere yaml-Übersetzungdatei eintragen. Die Rumpfsätze sind im Bereich (scope) <em>activerecord.messages</em> definiert. Da diese Sätze für alle Anwendungen gleich sind, gibt es schon für viele Sprachen und auch für Deutsch schon Standardübersetzungen.</p>
<h4>Übersetzung des Models</h4>
<p>Die Namen der Felder und Objekte müssen wir in der yaml-Datei im Bereich <em>activerecord.models.classname</em> beziehungsweise  <em>activerecord.attributs.classname.attributname</em> definieren. Dann erkennt sie Rails und setzt sie korrekt in die automatischen Validierungsmeldungen ein.<br />
Die zentrale Übersetzung der Klassennamen und Feldernamen ist auch für die Views interessant. So brauchen wir die Labels von Eingabefeldern nicht ein zweites oder drittes mal übersetzen.</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">activerecord:
  models:
    term: &quot;Begriff&quot;
  attributes:
    term:
      name: &quot;Name&quot;
      topic: &quot;Sachgebiet&quot;</pre></div></div>

<p>Das macht für die Views nicht immer Sinn. Die Benutzerschnittstelle sollte sich nicht zu eng an das Model halten. Wichtig ist ja schliesslich der Benutzer.</p>
<h3>Validierungen mit eigenen Meldungen</h3>
<p>Ein typischer Anwendungsfall für eine eigene Meldung ist die Überprüfung einer Telefonnummer. Die Methoden zur Spezifikation der Validierungen haben einen Parameter &#8220;message&#8221;. Damit sollte eine Übersetzung ja kein Problem sein: Wir sollten einfach hier die t()-Methode aufrufen können. Leider klappt es so nicht:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;"># funktioniert so nicht! Does not work!</span>
validates_format_of<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:fax</span>,<span style="color:#006600; font-weight:bold;">&#123;</span>
    <span style="color:#ff3333; font-weight:bold;">:with</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">/</span>\A<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">9</span> \<span style="color:#006600; font-weight:bold;">+</span>\<span style="color:#006600; font-weight:bold;">-</span>\<span style="color:#006600; font-weight:bold;">/</span>\<span style="color:#006600; font-weight:bold;">&#40;</span>\<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span>\Z<span style="color:#006600; font-weight:bold;">/</span>i,
    <span style="color:#ff3333; font-weight:bold;">:message</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> t<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'activerecord.errors.messages.bad_phone'</span><span style="color:#006600; font-weight:bold;">&#41;</span>,
    <span style="color:#ff3333; font-weight:bold;">:allow_blank</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Je nach Version und des verwendeten Deployments startet Rails gar nicht erst hoch oder liefert die gewünschte Übersetzung nicht. Was läuft schief?</p>
<p>Die Sprache ist ja immer pro Request gesetzt. Bei der Definition der deklarativen Valdierungen im Model gibt es noch gar keinen Request! Es macht deshalb keinen Sinn zu diesen Zeitpunkt die translate-Methode aufzurufen.</p>
<p>Aber wie lösen wir das Problem? Typisch für Rails ist die Lösung schon eingebaut. Wenn man sie nicht kennt, kann man sich allerdings lange im Kreis drehen.<br />
Wir können dem message &#8211; Parameter nämlich auch ein Symbol statt eines Strings mitgeben: das Symbol wird erst ausgewertet, wenn die Fehlermeldung angezeigt werden soll. Das Symbol wird nacheinander in diesen speziellen Kontexten (scope) ausgewertet:</p>
<ul>
<li>activerecord.errors.models.[model_name].attributes.[attribute_name]</li>
<li>activerecord.errors.models.[model_name]</li>
<li>activerecord.errors.messages</li>
</ul>
<p>Unsere Validierung können wir demnach einfach so schreiben:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">validates_format_of<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:fax</span>,<span style="color:#006600; font-weight:bold;">&#123;</span>
    <span style="color:#ff3333; font-weight:bold;">:with</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">/</span>\A<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">9</span> \<span style="color:#006600; font-weight:bold;">+</span>\<span style="color:#006600; font-weight:bold;">-</span>\<span style="color:#006600; font-weight:bold;">/</span>\<span style="color:#006600; font-weight:bold;">&#40;</span>\<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span>\Z<span style="color:#006600; font-weight:bold;">/</span>i,
    <span style="color:#ff3333; font-weight:bold;">:message</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:bad_phone</span>,
    <span style="color:#ff3333; font-weight:bold;">:allow_blank</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<h4>Quellen:</h4>
<p>Beschreibung (Guide) der Internationalization API:<br />
<a href="http://guides.rubyonrails.org/i18n.html">guides.rubyonrails.org/i18n.html</a></p>
<p>Sprachdateien für Standardübersetzungen:<br />
<a href="http://guides.rubyonrails.org/i18n.html">github.com/svenfuchs/rails-i18n/tree/master/rails/locale</a></p>
<p><a href="/2010/01/mehrsprachige-webseiten-mit-ruby-on-rails-3/">Zu Teil 3 dieses Artikels</a></p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2009/05/localize-ruby-on-rails-p2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mehrsprachige Webseiten mit Ruby on Rails</title>
		<link>http://meier-online.com/2009/04/localize-ruby-on-rails/</link>
		<comments>http://meier-online.com/2009/04/localize-ruby-on-rails/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 21:09:44 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Mehrsprachigkeit]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Übersetzung]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=370</guid>
		<description><![CDATA[Teil 1 &#8211; Übersicht Software in mehreren Sprachen anzubieten ist eine immer wiederkehrende Aufgabenstellung. Um so erstaunlicher ist es, dass Ruby on Rails erst sehr spät hierfür ein standardisiertes Vorgehen eingeführt hat. Seit Version 2.2. ist eine &#8220;Internationalization API&#8221; Bestandteil von Ruby on Rails. Struktur des Frameworks Das Framework besteht aus einen &#8220;öffentlichen&#8221; und einen [...]]]></description>
			<content:encoded><![CDATA[<h3>Teil 1 &#8211; Übersicht</h3>
<p>Software in mehreren Sprachen anzubieten ist eine immer wiederkehrende Aufgabenstellung. Um so erstaunlicher ist es, dass Ruby on Rails erst sehr spät hierfür ein standardisiertes Vorgehen eingeführt hat. Seit Version 2.2. ist eine &#8220;Internationalization API&#8221; Bestandteil von Ruby on Rails.<img class="aligncenter size-full wp-image-374" title="Das Ruby-On-Rails Mehrsprachigkeitsmodul" src="http://meier-online.com/blog/uploads/rails-i18n.png" alt="Das Ruby-On-Rails Mehrsprachigkeitsmodul" width="480" height="300" /><span id="more-370"></span></p>
<h3>Struktur des Frameworks</h3>
<p>Das Framework besteht aus einen &#8220;öffentlichen&#8221; und einen &#8220;privaten&#8221; Teil. Das I18N Modul bildet den öffentlichen Teil mit den Methoden, die wir in unserem Quelltext aufrufen.</p>
<p>Das private Backend ist austauschbar. Die Standardversion liest die Texte aus Dateien in Yaml-Format oder aus normalen Rubydateien ein.</p>
<h3>Aufruf</h3>
<p>In unserem Quelltext ersetzen wir alle zu übersetzenden Texte durch Aufrufe der <em>I18N.translate()</em> Methode. Dank eines Alias können wir auch einfach t() schreiben. Als Parameter übergeben wir einen Schlüssel, mit dem das Backend die richtige Übersetzung nachschlägt.</p>
<p>Der Schlüssel kann einen String oder ein Symbol sein. Normalerweise ist ein Symbol als Hashkey ja geringfügig performanter. Da der Schlüssel bei der Verarbeitung in seine Bestandteile zerlegt wird, erwarte ich, dass dieser Vorteil verschwindet.</p>
<p>In einer typischen Webapplikation sind viele der zu übersetzenden Texte in den Views, also den .erb-Templates. Als Abkürzung für reinen HTML-Text gibt es folgenden Tag:</p>
<pre>&lt;%=t 'key' %&gt;</pre>
<h3 class="western">Organisation</h3>
<p>Die Symbole haben eine hierarchische Struktur. Als Organisation bietet sich an:</p>
<p>&#8220;controllername.viewname.key&#8221;, also zum Beispiel &#8216;companies.show.header&#8217;</p>
<h3>Die Sprachdateien</h3>
<p>Als Formate der Sprachdatei sind Ruby-Quelltext und Yaml vorgesehen. Die Übersetzung wird nun meistens von einer Person ohne Rubykenntnisse durchgeführt. Deshalb ist die Yaml-Datei zu empfehlen.</p>
<p>Das Format sieht so aus</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">de:
  users:
    show:
      header: &quot;Unternehmensdaten&quot;
      intro: &quot;Für dieses Unternehmen sind die folgenden Daten gespeichert:&quot;</pre></div></div>

<p style="margin-bottom: 0cm;">Die Sprache ist der erste Key, normalerweise sind dadurch die Texte der verschiedenen Sprachen räumlich getrennt. Um die Arbeit für die Übersetzer zu erleichtern, können mit einem &#8216;#&#8217; Zeichen Kommentare eingefügt werden. Und natürlich sollten die bezeichnenden Schlüsselwerte möglichst klar sein. Aber selbst dann sind die YAML-Dateien nicht optimal, wenn Entwickler und Übersetzer nicht dieselbe Person ist.</p>
<p><a href="/2009/05/localize-ruby-on-rails-p2/">Zu Teil 2 dieses Artikels</a></p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2009/04/localize-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Turing Award für Barbara Liskov</title>
		<link>http://meier-online.com/2009/03/turing-award-fur-barbara-liskov/</link>
		<comments>http://meier-online.com/2009/03/turing-award-fur-barbara-liskov/#comments</comments>
		<pubDate>Sat, 14 Mar 2009 18:52:17 +0000</pubDate>
		<dc:creator>meier</dc:creator>
				<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Abstraktion]]></category>
		<category><![CDATA[CLU]]></category>
		<category><![CDATA[Liskov]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[yield]]></category>

		<guid isPermaLink="false">http://meier-online.com/?p=272</guid>
		<description><![CDATA[Der Turing Award ist wohl die bedeutendste Auszeichnung in der Informatik. Ein guter Grund, sich mit den Errungenschaften von Frau Liskov zu beschäftigen. Ihr Team hat in den Siebzigern die Programmiersprache CLU entwicklet. In dieser Zeit war für die normalen Programmierer die heißeste Frage, ob man tatsächlich Programme ohne goto-Befehle schreiben kann. Zentrales Thema wie [...]]]></description>
			<content:encoded><![CDATA[<p>Der Turing Award ist wohl die bedeutendste Auszeichnung in der Informatik. Ein guter Grund, sich mit den Errungenschaften von Frau Liskov zu beschäftigen. Ihr Team hat in den Siebzigern die Programmiersprache <em>CLU</em> entwicklet. In dieser Zeit war für die normalen Programmierer die heißeste Frage, ob man tatsächlich Programme ohne <em>goto</em>-Befehle schreiben kann.<span id="more-272"></span></p>
<p>Zentrales Thema wie für viele Fortschritte in der Informatik ist Abstraktion. <em>CLU</em> basierte auf abstrakten Datentypen: Datentypen, deren innere Ansicht der Programmierer nicht kennen muss,<br />
den sie wurden zusammen mit Zugriffsoperationen definiert. Diese Vorgehensweise ist heute unter dem Stichwort objektorientiertes Programmieren allgemein üblich geworden.</p>
<p>Aber <em>CLU</em> bot auch Möglichkeiten, den Kontrolfluß zu abstrahieren. Ein Konzept, das offenbar der Zeit noch weiter voraus war. So kannte <em>CLU</em> das <em>yield</em>-Statement, welches erst in neuerer Zeit dank der Programmiersprache Ruby populär geworden ist. Es ist schon deshalb schwierig zu verstehen, weil auch das Wort &#8220;yield&#8221; keine so klare Bedeutung hat. Übersetzen kann man es mit abgeben, auswerfen, freisetzen. Während in Programmen klassische Prozeduren (oder auch Methoden) die Kontrolle exklusiv halten, und bestenfalls andere Prozeduren aufrufen,  gibt <em>yield</em> die Kontrolle und gegebenenfalls Objekte an ein übergebenes Codestück ab.  Auf diese Weise kann dann tatsächlich der Kontrollfluss abstrahiert werden.</p>
<p>Wie kann man sich das vorstellen? Wir schauen uns die Funktionsweise am Beispiel Ruby an:</p>
<p><img class="aligncenter size-full wp-image-276" title="Funktionsweise von yield in Ruby" src="http://meier-online.com/blog/uploads/yield.png" alt="Funktionsweise von yield in Ruby" width="461" height="201" /></p>
<p>Beim Aufruf einer Methode wird auch der in <em>do &#8230;end</em> definierte Codeblock der Methode zugänglich gemacht. Die Methode entscheidet dann, ob, wann, und wie oft sie den Codeblock aufruft. Weiterhin kann der <em>yield</em>-Befehl Parameter sozusagen auswerfen, die dann im Codeblock verfügbar sind. Umgekehrt liefert der Codeblock ein Rückgabewert, der im Methodenrumpf zur Verfügung steht.</p>
<p>Die Anwendungsfälle sind zahlreich. Man kann automatisch Resourcen ausbalancieren. Beispielsweise  kann man so dafür sorgen, das geöffnete Dateien beim verlassen eines Blockes wieder geschlossen werden. Man kann tatsächlich Kontrollstrukturen schreiben: In Ruby ist die <em>for</em>-Struktur so definiert. So kann man <em>for</em> nicht nur für Zahlen, sondern auch für Dateizeilen, Ergebnisse von Datenbankabfragen oder XML-Strukturen nutzen. Auch das Web-Framework Ruby-On-Rails macht exzessiven Gebrauch von <em>yield</em>.</p>
<p>Soweit meine Laudatio, beim ACM finden Sie die offzielle Laudatio für den <a href="http://www.acm.org/membership/turing-award2008">Turing Award für Barabara Liskov</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://meier-online.com/2009/03/turing-award-fur-barbara-liskov/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

