<?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; Plugins</title>
	<atom:link href="http://martin-grandrath.de/tags/plugins/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</title>
		<link>http://martin-grandrath.de/2008/05/wordpress-theme-internationalization/</link>
		<comments>http://martin-grandrath.de/2008/05/wordpress-theme-internationalization/#comments</comments>
		<pubDate>Wed, 14 May 2008 09:55:27 +0000</pubDate>
		<dc:creator>Martin Grandrath</dc:creator>
				<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[Internationalization]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[Themes]]></category>

		<guid isPermaLink="false">http://www.martin-grandrath.de/?p=47</guid>
		<description><![CDATA[Gestern habe ich mich damit beschäftigt ein WordPress Theme zu internationalisieren, d.h. für Übersetzungen in verschiedene Sprachen vorzubereiten.  Da die WordPress Dokumentation leider nicht sonderlich übersichtlich ist und es eine Weile gedauert hat, bis ich fündig geworden bin, hier eine kurze Zusammenfassung.
Als Internationalisierung (i18n) wird die Vorbereitung eines Programms o.ä. für die Übersetzung bezeichnet, [...]]]></description>
			<content:encoded><![CDATA[<p>Gestern habe ich mich damit beschäftigt ein WordPress Theme zu internationalisieren, d.h. für Übersetzungen in verschiedene Sprachen vorzubereiten.  Da die <a href="http://codex.wordpress.org/" rel="external">WordPress Dokumentation</a> leider nicht sonderlich übersichtlich ist und es eine Weile gedauert hat, bis ich fündig geworden bin, hier eine kurze Zusammenfassung.</p>
<p>Als <em>Internationalisierung</em> (i18n) wird die Vorbereitung eines Programms o.ä. für die Übersetzung bezeichnet, d.h. es wird eine &raquo;Infrastruktur&laquo; geschaffen, so dass die eigentliche Übersetzung auch von Nicht-Programmierern übernommen werden kann.  Das Übersetzen in andere Sprachen ist die <em>Lokalisierung</em> (l10n).</p>
<p>Grundlage für die Internationalisierung von WordPress (inkl. Themes und Plugins) ist das GNU-Tool <a href="http://www.gnu.org/software/gettext/" rel="external">Gettext</a>, das nach folgendem Prinzip funktioniert:</p>
<ol>
<li>
<p>Alle Strings, die übersetzt werden sollen, werden im Quellcode mit speziellen Funktionen <em>ausgezeichnet</em></p>
</li>
<li>
<p>Dem Programm (bzw. Plugin oder Theme) wird einmalig ein Stück <em>Code hinzugefügt</em>, das die zur eingestellten Sprache passende Übersetzung einbindet &#8212; sofern vorhanden</p>
</li>
<li>
<p>Die markierten Strings werden mit xgettext extrahiert und in einer <em>Template-Datei</em> gespeichert (Endung .pot)</p>
</li>
<li>
<p>Aus diesem Template wird für jede Sprache eine <em>Datei für die Übersetzungen</em> abgeleitet (Endung .po)</p>
</li>
<li>
<p>Die fertigen Übersetzungsdateien werden <em>kompiliert</em>, d.h. maschinenlesbar gemacht (Endung .mo)</p>
</li>
</ol>
<p><span id="more-47"></span></p>
<h3>1. Vorbereitung des Codes</h3>
<p>Die eigentliche Vorbereitung des Quelltextes wird unter <a href="http://codex.wordpress.org/Translating_WordPress" rel="external">Translating WordPress</a> ganz gut beschrieben.  Im Wesentlichen müssen sämtliche übersetzbaren Strings durch eine der folgenden beiden PHP-Funktionen ersetzt werden:</p>
<ul>
<li><strong><code>__($message, $domain)</code></strong> Für die Zeichenkette <code>$message</code> wird innerhalb von <code>$domain</code> eine passende Übersetzung gesucht und zurückgegeben.  Ist keine Übersetzung vorhanden, wird <code>$message</code> zurückgegeben.
<p>Der Parameter <code>$domain</code> ist ebenfalls ein String und stellt einen Namensraum (Namespace) dar, der verhindert, dass identische Texte mit unterschiedlichen Übersetzungen in mehreren Kontexten Konflikte auslösen.  Voraussetzung dabei ist selbstverständlich, dass die Domain einen eindeutigen Bezeichner besitzt.  Bei Plugins wählt man dafür sinnvollerweise den Namen des Plugins, der für sich ja auch bereits eindeutig sein muss.  Bei Themes ist die Wahl dieses Bezeichners insofern weniger kritisch, da nicht mehrere Themes gleichzeitig angewendet werden können.  Der Name darf sich nur nicht mit dem eines Plugins überschneiden.</p>
</li>
<li><strong><code>_e($message, $domain)</code></strong> ist eine verkürzte Schreibweise für <code>echo __($message, $domain)</code>
</li>
</ul>
<p>Zum Einbinden der Übersetzung ergänzt man noch folgenden Code:</p>
<ul>
<li><strong>Für Themes</strong> (in functions.php):
<pre class="code
php">load_theme_textdomain('your_domain');</pre>
</li>
<li><strong>Für Plugins</strong> (wenn das Plugin &raquo;foobar&laquo; heißt):
<pre class="code php">$foobar_domain = 'foobar';
$foobar_is_setup = 0;

function foobar_setup()
{
    global $foobar_domain, $foobar_is_setup;

    if ($foobar_is_setup) {
        return;
    }

    load_plugin_textdomain($foobar_domain, 'wp-content/plugins/foobar');
}</pre>
</li>
</ul>
<h3>2. Erstellung der Template-Datei (.pot)</h3>
<p>Insbesondere bei diesem Punkt habe ich lange suchen müssen.  In der WordPress-Dokumentation steht nur die lapidare Aussage</p>
<blockquote cite="http://codex.wordpress.org/Translating_WordPress#gettext_files"><p> Generally, you can download a POT file for WordPress, so you shouldn&#8217;t have to generate your own.</p></blockquote>
<p>Wirklich sehr hilfreich!  Nach einigem googlen bin ich dann noch auf diesen Hinweis gestoßen:</p>
<blockquote cite="http://codex.wordpress.org/User:Nbachiyski/I18n_for_WordPress_Developers#Generating_a_POT_file"><p> Get the <a href="http://svn.automattic.com/wordpress-i18n/tools/trunk/makepot.php">makepot.php</a> script and execute it like this:</p>
<pre class="code">php makepot.php wp-plugin your-plugin-directory</pre>
</blockquote>
<p>Hier ist der xgettext-Aufruf, den dieses Script im Wesentlichen fabriziert (auszuführen im Verzeichnis des Themes):</p>
<pre class="code">xgettext --keyword=__ --keyword=_e --keyword=_c --keyword=__ngettext:1,2 --keyword=__ngettext_noop:1,2 *.php</pre>
<p>Ruft man xgettext per Hand auf, muss man noch beachten, dass xgettext (aus <a href="http://www.gnu.org/software/gettext/manual/gettext.html#Template">historischen Gründen</a>) eine Datei mit der Endung .po erstellt, die noch umbenannt werden muss!</p>
<p>Alle notwendigen Befehle (xgettext, msginit, msgfmt und msgmerge) installiert man übrigens unter Debian bzw. Ubuntu mit</p>
<pre class="code">aptitude install gettext</pre>
<h3>3. Anlegen und Einbinden einer neuen Übersetzung (.po und .mo)</h3>
<p>Ab hier ist der Rest wieder einfach.  Der Befehl</p>
<pre class="code">msginit -l de_DE -o de_DE.po</pre>
<p>initialisiert eine neue .po-Datei (hier z.B. für die locale de_DE).  Diese kann der Übersetzer nun mit dem <a href="http://codex.wordpress.org/Translating_WordPress#Translation_Tools" rel="external">Werkzeug seiner Wahl</a> bearbeiten.</p>
<p>Das Kompilieren in ein maschinenlesbares Format erledigt anschließend die Zeile</p>
<pre class="code">msgfmt -o de_DE.mo de_DE.po</pre>
<p>Die fertige .mo-Datei muss im Theme- bzw. Plugin-Verzeichnis abgelegt werden.  Für das Plugin &raquo;foobar&laquo; muss die fertige Datei allerdings &raquo;foobar-de_DE.mo&laquo; heißen!</p>
<h3>4. Update einer vorhandenen .po-Datei</h3>
<p>Kommen nun (z.B. aufgrund einer neuen Version) weitere zu übersetzende Strings hinzu, muss man nicht wieder von vorne anfangen.  Es genügt, die Template-Datei mit dem o.g. Aufruf von xgettext neu zu erzeugen. Anschließend werden die neuen Zeilen mit</p>
<pre class="code">msgmerge -U de_DE.po messages.pot</pre>
<p>in die vorhandene .po-Datei eingefügt.  Die Übersetzung und Kompilierung erfolgen dann wieder wie gehabt.</p>
<h3>Links zum Thema</h3>
<ul>
<li><a href="http://codex.wordpress.org/Translating_WordPress" rel="external">Translating WordPress</a></li>
<li><a href="http://codex.wordpress.org/Writing_a_Plugin#Internationalizing_Your_Plugin" rel="external">Internationalizing your plugin</a> (gilt auch für Themes)</li>
<li><a href="http://codex.wordpress.org/User:Nbachiyski/I18n_for_WordPress_Developers" rel="external">I18n for WordPress developers</a></li>
<li><a href="http://www.gnu.org/software/gettext/manual/gettext.html" rel="external">Gettext Handbuch</a></li>
</ul>
<p><strong>Update:</strong> Im <a href="/2009/04/wordpress-theme-internationalization-teil-2/">2.&nbsp;Teil</a> stelle ich eine Möglichkeit vor, die Generierung und Aktualisierung der .po- und .mo-Dateien mit make zu automatisieren.</p>
]]></content:encoded>
			<wfw:commentRss>http://martin-grandrath.de/2008/05/wordpress-theme-internationalization/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

