<?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; Validierungen</title>
	<atom:link href="http://meier-online.com/tag/validierungen/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>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>
	</channel>
</rss>

