<?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>martin-grandrath.de &#187; gettext</title>
	<atom:link href="http://martin-grandrath.de/tags/gettext/feed/" rel="self" type="application/rss+xml" />
	<link>http://martin-grandrath.de</link>
	<description>Ein neues WordPress-Weblog</description>
	<lastBuildDate>Fri, 23 Oct 2009 22:35:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>WordPress Theme internationalization (Teil 2)</title>
		<link>http://martin-grandrath.de/2009/04/wordpress-theme-internationalization-teil-2/</link>
		<comments>http://martin-grandrath.de/2009/04/wordpress-theme-internationalization-teil-2/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 20:14:52 +0000</pubDate>
		<dc:creator>Martin Grandrath</dc:creator>
				<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[gettext]]></category>
		<category><![CDATA[Internationalization]]></category>
		<category><![CDATA[Make]]></category>
		<category><![CDATA[Themes]]></category>

		<guid isPermaLink="false">http://martin-grandrath.de/?p=117</guid>
		<description><![CDATA[Vor etwa einem Jahr habe ich bereits einen Artikel über WordPress Theme internationalization geschrieben und das grundlegende Vorgehen zum Erzeugen von Sprachdateien skizziert.  Ich möchte diesen im Folgenden durch meinen persönlichen Workflow anhand eines einfachen Beispiels ergänzen.
Vorbereitung
Wie bereits im ersten Teil dargestellt, muss zunächst in der Datei functions.php die &#187;Textdomain&#171; eingebunden werden.  Seit [...]]]></description>
			<content:encoded><![CDATA[<p>Vor etwa einem Jahr habe ich bereits einen Artikel über <a href="/2008/05/wordpress-theme-internationalization/">WordPress Theme internationalization</a> geschrieben und das grundlegende Vorgehen zum Erzeugen von Sprachdateien skizziert.  Ich möchte diesen im Folgenden durch meinen persönlichen Workflow anhand eines einfachen Beispiels ergänzen.</p>
<h3>Vorbereitung</h3>
<p>Wie bereits im ersten Teil dargestellt, muss zunächst in der Datei <strong><code>functions.php</code></strong> die &raquo;Textdomain&laquo; eingebunden werden.  Seit WordPress&nbsp;2.7 ist es möglich, zusätzlich zum Namen der Domain ein Verzeichnis anzugeben, in dem nach den Übersetzungen gesucht wird (in diesem Fall das Verzeichnis <code>messages/</code> unterhalb des Template-Verzeichnisses):</p>
<pre class="code code-php">
load_theme_textdomain('mydomain', get_template_directory().'/messages');
</pre>
<p>Anschließend müssen in den Templatedateien sämtliche Strings ausgezeichnet werden, die übersetzt werden sollen.  Wenn man ein neues Theme von Grund auf gestaltet, tut man gut daran, das von Anfang an zu tun.  Andernfalls ist das eine recht mühselige Arbeit.</p>
<h4>Ein paar Beispiele</h4>
<p>In der Datei <strong><code>index.php</code></strong> befindet sich innerhalb &raquo;Der Schleife&laquo; (The Loop) diese Zeile zur Ausgabe des Inhalts eines Artikels:</p>
<pre class="code code-php">
the_content('Read the rest of this entry');
</pre>
<p>Dies wird zu</p>
<pre class="code code-php">
the_content( __('Read the rest of this entry', 'mydomain') );
</pre>
<p>Die Funktion <code>__($message, $domain)</code> sucht innerhalb der Domain <code>$domain</code> (hier: &#8216;mydomain&#8217;) nach einer Übersetzung für den String <code>$message</code> (hier: &#8216;Read the rest of this entry&#8217;) und gibt diese zurück.  Oder, falls keine Übersetzung gefunden wurde, den ursprünglichen String.</p>
<p>In der Datei <strong><code>comments.php</code></strong> findet sich das Label für das Formularfeld &raquo;author&laquo;:</p>
<pre class="code code-php">
&lt;label for="author"&gt;Your name&lt;/label&gt;
</pre>
<p>Dies wird zu</p>
<pre class="code code-php">
&lt;label for="author"&gt;&lt;?php _e('Your name', 'mydomain'); ?&gt;&lt;/label&gt;
</pre>
<p>Die Funktion <code>_e(...)</code> ist äquivalent zu <code>echo __(...)</code></p>
<h3>Automatisierung mit GNU make</h3>
<p>Nun geht es darum, diese Strings zu extrahieren und in separaten Dateien zu speichern, die dann jeweils die Übersetzung in eine weitere Sprache ermöglichen.  Um das Hantieren mit den .po- und .mo-Dateien (siehe <a href="/2008/05/wordpress-theme-internationalization/">Teil&nbsp;1</a>) etwas einfacher zu gestalten, habe ich folgendes Makefile geschrieben:</p>
<pre class="code code-gnumake">
# List of locales to generate (space separated)
LOCALES = de_DE

# List of source files
SRC_FILES = ../*.php

# .pot file to create
POT_FILE = messages.pot

$(POT_FILE): $(SRC_FILES)
        xgettext --keyword=__ --keyword=_e --keyword=_c --keyword=__ngettext:1,2 --keyword=__ngettext_noop:1,2 $(SRC_FILES) &#038;&#038; \
        mv messages.po $(POT_FILE)

po_files: $(patsubst %,%.po,$(LOCALES))

mo_files: $(patsubst %,%.mo,$(LOCALES))

%.po: $(POT_FILE)
        [ -f $@ ] &#038;&#038; \
        msgmerge -U $@ $&lt; &#038;&#038; touch $@ || \
        msginit -l $* -o $@

%.mo: %.po
        msgfmt -o $@ $&lt;
</pre>
<p><strong>Wichtig:</strong> die eingerückten Zeilen müssen mit einem Tab und <em>nicht</em> mit Leerzeichen eingerückt werden!</p>
<p>Diese Datei wird unter dem Namen <code>Makefile</code> (Groß-/Kleinschreibung beachten) im Verzeichnis <code>messages/</code> abgelegt, das unterhalb des Template-Verzeichnisses angelegt wird:</p>
<pre>
mytheme/
|-- footer.php
|-- functions.php
|-- header.php
|-- index.php
|-- messages/
|   `-- Makefile
|-- screenshot.png
|-- searchform.php
|-- sidebar.php
|-- single.php
`-- style.css
</pre>
<p>Damit das Folgende funktioniert, müssen die GNU-Tools make und gettext installiert sein, was unter Debian der Befehl <kbd>aptitude install gettext make</kbd> erledigt.</p>
<h4>.po-Files generieren</h4>
<p>Zunächst wechseln wir in das neu angelegte Verzeichnis:</p>
<pre class="code">
$ cd messages/
$ ls
Makefile
</pre>
<p>Jetzt legen wir die .po-Datei an, in der die deutschen Übersetzungen gespeichert werden:</p>
<pre class="code">
$ make de_DE.po
</pre>
<h4>Übersetzen</h4>
<p>Nun wird die eigentliche Übersetzungsarbeit fällig.  Es bietet sich an, für das Bearbeiten der .po-Dateien eines der <a href="http://codex.wordpress.org/Translating_WordPress#Translation_Tools" rel="external">zahlreichen Tools</a> zu verwenden, die es einem erleichtern, sich ganz auf die Texte zu konzentrieren, ohne dass man Gefahr läuft die Syntax der Datei kaputt zu machen.</p>
<p>Vorab sollte man in der .po-Datei noch die Zeichenkodierung auf UTF-8 ändern, um sich Probleme mit Umlauten zu ersparen:</p>
<pre class="code">
"Content-Type: text/plain; charset=UTF-8\n"
</pre>
<h4>.mo-Files generieren</h4>
<p>Ist die Übersetzung abgeschlossen, kann die .po-Datei compiliert, d.h. die .mo-Datei erzeugt werden.  Das passiert durch den Aufruf von</p>
<pre class="code">
$ make de_DE.mo
</pre>
<p>Jetzt sollten die übersetzten Texte im Theme erscheinen.  Falls das nicht klappt, sollte als erstes geprüft werden, ob in der <code>wp-config.php</code> die Konstante <code>WPLANG</code> auf den Wert &#8216;de_DE&#8217; gesetzt ist.</p>
<h4>.po-Files aktualisieren</h4>
<p>Wird nun weiter am Template gearbeitet, kann es natürlich passieren, dass neue Strings definiert werden, die übersetzt werden wollen.  In diesem Fall aktualisiert der Aufruf von <kbd>make de_DE.po</kbd> die .po-Datei &ndash; alle bisher gemachten Übersetzungen bleiben dabei erhalten.  Die Erzeugung der .mo-Datei erfolgt wie gehabt.</p>
<h4>Übersetzungen in weitere Sprachen</h4>
<p>Wer sich mit Makefiles auskennt, hat vermutlich schon bemerkt, dass sich mit meinem Makefile eine ganze Liste von Sprachdateien in einem Rutsch aktualisieren lassen.  Dazu werden in der 2.&nbsp;Zeile alle Locales, die erzeugt werden sollen, durch Leerzeichen getrennt hintereinander aufgelistet (hier z.B. für Deutsch, Französisch, Spanisch und Italienisch):</p>
<pre class="code code-gnumake">
LOCALES = de_DE fr_FR es_ES it_IT
</pre>
<p>Nun können alle .po-Dateien mit <code>make po_files</code> bzw. alle .mo-Dateien mit <code>make mo_files</code> auf den neuesten Stand gebracht werden.  Es ist übrigens auch möglich, weitere Sprachen im Nachhinein zu ergänzen.  Make erzeugt bzw. aktualisiert immer nur die Dateien, die notwendig sind.</p>
]]></content:encoded>
			<wfw:commentRss>http://martin-grandrath.de/2009/04/wordpress-theme-internationalization-teil-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

