<?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>toscho.design</title>
	<atom:link href="http://toscho.de/feed/" rel="self" type="application/rss+xml" />
	<link>http://toscho.de</link>
	<description>Redaktion, Druck- und Webdesign aus Halle (Saale)</description>
	<lastBuildDate>Sun, 28 Feb 2010 17:17:13 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>de</language>
	<sy:updatePeriod>daily</sy:updatePeriod>
	<sy:updateFrequency>4</sy:updateFrequency>
			<item>
		<title>WordPress-Tutorial: Ein Framebreaker-Plugin schreiben</title>
		<link>http://toscho.de/2010/wordpress-tutorial-ein-framebreaker-plugin-schreiben/</link>
		<comments>http://toscho.de/2010/wordpress-tutorial-ein-framebreaker-plugin-schreiben/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 17:17:13 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1633</guid>
		<description><![CDATA[Anleitung zum Schreiben eines handwerklich sauberen WordPress-Plugins.]]></description>
			<content:encoded><![CDATA[<p><!--TOC--></p>
<p>Ein Framebreaker ist ein kleines Javascript, das die Website in den Vordergrund hebt, wenn jemand versucht, sie in seinen Frame einzubetten.</p>
<p>In der einfachsten Variante steht das Script im <code>head</code>:</p>
<pre class="notranslate" style="max-width:30em;clear:none">&lt;head&gt;
&lt;script type=&quot;<code class="string">text/javascript</code>&quot;&gt;
if (<var>self</var> != <var>top</var>)
{
    <var>top</var>.location.replace(<var>self</var>.location.href);
}
&lt;/script&gt;
&lt;/head&gt;</pre>
<p>So wird die URL im Verlauf ersetzt und der Zurückbutton funktioniert weiterhin normal.</p>
<p>Nun kann nicht jeder WordPress-Benutzer frei an seinem Theme herumschrauben. Oft wird es aus anderen Quellen aktualisiert, und dann würde der Code überschrieben werden. Ein Plugin löst das Problem, indem es diese Funktionalität vom Theme trennt.</p>
<h2>Dateien anlegen</h2>
<p>Zuerst erstellen wir ein Verzeichnis <samp>framebreaker</samp> im Pluginverzeichnis; da legen wir eine PHP-Datei hinein, die wir passenderweise auch <samp>framebreaker.php</samp> nennen.<br />
Der Dateiname spielt übrigens keine Rolle; er muß nur auf <code>.php</code> enden. Wir achten aber darauf, daß er von anderen leicht als ›Hauptdatei‹ erkannt wird, damit sich jeder schnell zurechtfindet. <samp>main.php</samp> wäre also auch ein passender Name, <samp>code.php</samp> eher nicht.<br />
Es ist üblich, bei Datei- und Verzeichnisnamen nur Kleinbuchstaben, Zahlen und Bindestriche zu verwenden.</p>
<p>Wenn das Plugin aus nur einer Datei besteht, braucht es kein eigenes Verzeichnis. Für den Anwender ist es aber übersichtlicher, wenn jedem Plugin ein Verzeichnis entspricht, weil er dann im FTP-Programm nur den Baum aufklappen muß, um alle Plugins zu sehen.<br />
Wollen wir bei einem späteren Update doch weitere Dateien hinzufügen – Icons, Sprachdateien oder eine Optionsseite – müssen wir ohnehin ›umziehen‹.</p>
<h2>Metadaten</h2>
<p>Der Kopf der Datei sollte so aussehen:</p>
<pre class="notranslate">&lt;?php
<i>/*
Plugin Name: Framebreaker
Plugin URI:  http://toscho.de/2010/wordpress-tutorial-framebreaker-plugin/
Description: Baut ein Javascript in den HTML-Kopf, das die Website vor dem Einframen schützt.
Version:     0.1
Author:      Thomas Scholz
Author URI:  http://toscho.de
*/</i></pre>
<p>WordPress genügt der Name; den Rest können wir technisch gesehen weglassen. Aber davon rate ich ab. Die Angaben helfen dem Nutzer, sich für oder gegen das Plugin zu entscheiden. Fehlen sie, sieht es schnell ›verdächtig‹ aus.</p>
<p><a href="http://toscho.de/wp-content/uploads/2010/02/framebreaker-01.png"><img src="http://toscho.de/wp-content/uploads/2010/02/framebreaker-01-300x56.png" alt="Screenshot" title="Screenshot: Framebreaker in der Pluginliste" width="300" height="56" class="alignnone size-medium wp-image-1634" /></a></p>
<p>Falls wir unser fantastisches Plugin irgendwann auf wordpress.org veröffentlichen wollen, sollten wir jetzt schon nachsehen, ob eines mit diesem Namen existiert.<br />
Die <a href="http://wordpress.org/extend/plugins/search.php?q=Framebreaker">Suche nach ›Framebreaker‹</a> liefert bis jetzt noch keine Ergebnisse; wir können also weitermachen.</p>
<p>Der Name sollte eher beschreiben als unterhalten, die Hauptfunktion also klar wiedergeben. Wäre ›Framebreaker‹ schon weg, das bestehende Plugin dazu aber nicht so gut, daß wir unsere Arbeit fallen oder dort einfließen lassen wollen, könnten wir noch ›Break Frames‹ oder ›Frame Escape‹ versuchen. ›Luftjucker‹ klänge zwar deutlich amüsanter und ist sicher noch frei, aber <em>danach sucht niemand</em>.</p>
<p>Real gibt es natürlich schon eine Menge Framebreaker (in sehr unterschiedlicher Qualität); unser Plugin brauchen wir dort also nicht anzumelden.</p>
<p>Beim Auslesen der Metadaten wird noch kein Plugin-Code ausgeführt; wir können aber in der Beschreibung ein paar HTML-Elemente verwenden:</p>
<ul class="notranslate">
<li><code>a[href][title]</code>,</li>
<li><code>abbr[title]</code>,</li>
<li><code>acronym[title]</code>,</li>
<li><code>code</code>,</li>
<li><code>em</code> und</li>
<li><code>strong</code></li>
</ul>
<p>Die Beschreibung selbst sollte kurz und knackig sein, kein Roman. Zeilenumbrüche sind nicht erlaubt.</p>
<p>Alle Metadaten zusammen dürfen nicht mehr als 8 <abbr title="Kilobyte">KiB</abbr> beanspruchen.</p>
<h2>Guter Stil</h2>
<p>Benutze immer <code>&lt;?php</code>, um PHP zu öffnen, niemals <a lang="en" href='http://www.php.net/manual/de/ini.core.php'>Short Open Tags</a> wie <code>&lt;?</code> oder <code>&lt;?=</code>. In manchen Installationen funktioniert nur die ausführliche Schreibweise.</p>
<p>Laß das schließende <code>?&gt;</code> am Ende der PHP-Datei weg, damit sich keine Leerzeilen oder -zeichen einschleichen, die das berüchtigte <a href='http://www.php-faq.de/q-fehler-header.html' lang="en">Headers already sent</a> auslösen.</p>
<p>Benenne deine Klassen und Funktionen stets so, daß sie wahrscheinlich nicht mit anderen Plugins oder gar dem Core kollidieren. Benutze im Zweifel <a href='http://www.php.net/manual/de/function.function-exists.php'>function_exists()</a> und <a href='http://www.php.net/manual/de/function.class-exists.php'>class_exists()</a>.</p>
<p>Stelle niemals, wirklich nie, Variablen in den globalen Namensraum!</p>
<p>Schreib alles in <a href='http://toscho.de/2010/warum-utf-8/'>UTF-8</a>. Mit jeder anderen <a href='http://toscho.de/2008/grundlagen-zeichenkodierung/'>Zeichenkodierung</a> wirst du ganz sicher Probleme bekommen.</p>
<p>Kommentiere ausführlich und benutze <a href='http://codex.wordpress.org/Inline_Documentation' hreflang='en' title='WordPress Codex: Inline Documentation'>PHPDoc</a>, aus dem man automatisch eine ordentliche Dokumentation erstellen kann.</p>
<h2>Grundfunktion</h2>
<p>Bisher kann man das Plugin nur aktivieren; es tut noch nichts.<br />
Also brauchen wir zwei weitere Abschnitte: Eine Funktion, die den Javascriptcode ausgibt, und eine Angabe dazu, wo und wann sie ausgeführt werden soll.</p>
<p>Die Funktion ist einfach:</p>
<pre class="notranslate">if ( ! function_exists('<code class="string">toscho_write_framebreaker</code>') )
{
    <i lang="en">/**
     * Inserts a javascript frame buster.
     * @return void
     */</i>
    function toscho_write_framebreaker()
    {
?&gt;
&lt;script type="<code class="string">text/javascript</code>"&gt;
if (<var>self</var> != <var>top</var>)
{
    <var>top</var>.location.replace(<var>self</var>.location.href);
}
&lt;/script&gt;
&lt;?php
        return;
    }
}</pre>
<p>Wir wollen das Script in den Kopf des HTML-Codes schreiben; dort wartet in WordPress schon die Funktion <a href="http://codex.wordpress.org/Plugin_API/Action_Reference/wp_head"><code>wp_head()</code></a> auf uns. Die steht in jedem ordentlichen Theme, meistens in der Datei <code>header.php</code>:</p>
<pre class="notranslate">&lt;head&gt;
<i>&lt;!-- allerhand Code --&gt;</i>
&lt;?php
wp_head();
?&gt;
&lt;/head&gt;</pre>
<p>Wir finden die Funktion in der Datei <code><a href='http://core.trac.wordpress.org/browser/trunk/wp-includes/general-template.php#L1544'>wp-includes/general-template.php</a></code>:</p>
<pre class="notranslate"><i lang="en">/**
 * Fire the wp_head action
 *
 * @since 1.2.0
 * @uses do_action() Calls 'wp_head' hook.
 */</i>
function wp_head() {
    do_action('<code class="string">wp_head</code>');
}</pre>
<p>Zu Deutsch: Die Funktion löst einfach die gleichnamige Aktion aus. </p>
<h2>Filter und Aktionen</h2>
<p>Hier kommen wir zu den beiden einfachsten <a href='http://codex.wordpress.org/Plugin_API'>Schnittstellen</a> (<i lang="en">Hooks</i>) für Pluginautoren. Eine Aktion (<i lang="en">action</i>) wird zu einem bestimmten Zeitpunkt in der Verarbeitung ausgelöst, ähnlich dem Onclick-Event in Javascript. Manchmal, aber nicht immer, werden noch Variablen übergeben.</p>
<p>Ein Filter (<i lang="en">filter</i>) übergibt <em>immer</em> mindestens eine Variable – und er erwartet, daß die Filterfunktion sie nach dem Bearbeiten wieder zurückliefert.</p>
<p>Weit mehr als 1000 solcher <i lang="en">Hooks</i> bietet WordPress derzeit an; Adam R. Brown hält eine aktuelle Liste vor: <a href='http://adambrown.info/p/wp_hooks' hreflang="en">WordPress Hook Database</a>.</p>
<p>Wir können auch eigene Filter und Aktionen bereitstellen, damit andere Autoren in ihren Plugins und Themes unserem Code nicht hilflos ausgeliefert sind.<br />
Wenn wir etwas direkt ausgeben, dann sollten wir <em>immer</em> einen Filter anbieten. Deshalb schreiben wir unsere Funktion jetzt ein bißchen um:</p>
<pre class="notranslate">if ( ! function_exists('<code class="string">toscho_write_framebreaker</code>') )
{
    <i lang="en">/**
     * Inserts a javascript frame buster.
     * @return void
     */</i>
    function toscho_write_framebreaker()
    {
        <var>$script</var> = '<code class="string">
&lt;script type="text/javascript"&gt;
if (<var>self</var> != <var>top</var>)
{
    <var>top</var>.location.replace(<var>self</var>.location.href);
}
&lt;/script&gt;</code>';
        <i lang="en">/**
         * To alter the script output just use
         * add_filter('toscho_write_framebreaker', 'your_function');
         */</i>
        <strong>apply_filters</strong>('<code class="string">toscho_write_framebreaker</code>', <var>$script</var>);

        echo <var>$script</var>;

        return;
    }
}</pre>
<p>Beim Aufruf der Funktion <code>apply_filters()</code> sieht WordPress nach, ob jemand einen Filter für den ersten Parameter definiert hat. Wenn ja, dann wird er ausgeführt, ehe wir weiterarbeiten. Dieses elegante und mächtige Werkzeug ermöglicht eine reibungsarme Kommunikation zwischen Themes, Plugins und dem Core.</p>
<h2>Den Framebreaker an eine Aktion binden</h2>
<p>Jetzt bringen wir unser Plugin zum Arbeiten, mit nur einer Zeile nach der Funktion:</p>
<pre class="notranslate">add_action('<code class="string">wp_head</code>', '<code class="string">toscho_write_framebreaker</code>');</pre>
<p>Wenn die Funktion <code>do_action()</code> mit einem Parameter aufgerufen wird, sieht WordPress wiederum nach, ob für diesen Parameter Aktionen angeboten werden. Wir könnten unser Plugin noch um eine eigene Aktion erweitern:</p>
<pre class="notranslate">add_action('<code class="string">framebreak</code>', '<code class="string">toscho_write_framebreaker</code>');</pre>
<p>Dann könnte ein Theme-Autor in seine Vorlage schreiben:</p>
<pre class="notranslate">do_action('<code class="string">framebreak</code>');</pre>
<p>Wird das Plugin deaktiviert, passiert dann einfach nichts. Ist es aber aktiv, wird der Javascript-Code ausgegeben.</p>
<p>Manche Plugin-Autoren stellen Ausgaben zur Verfügung, die man an beliebiger Stelle im Theme aufrufen kann. Genau dafür existieren eigene Aktionen.<br />
<em>Schlampig</em> hingegen wäre dies:</p>
<pre class="notranslate">if ( function_exists('<code class="string">meine_plugin_funktion</code>')
{
    meine_plugin_funktion();
}</pre>
<h2>Das komplette Plugin</h2>
<p>Im Ganzen sieht das Plugin – ergänzt um eine Lizenzangabe – jetzt so aus:</p>
<pre class="notranslate">&lt;?php
<i>/*
Plugin Name: Framebreaker
Plugin URI:  http://toscho.de/2010/wordpress-tutorial-framebreaker-plugin/
Description: Baut ein Javascript in den HTML-Kopf, das die Website vor dem Einframen schützt.
Version:     0.1
Author:      Thomas Scholz
Author URI:  http://toscho.de
License:     GPL
*/</i>

<i lang="en">/*
Copyright 2010  Thomas Scholz  (email: info@toscho.de)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License,
version 2, as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
MA  02110-1301  USA
*/</i>

if ( ! function_exists('<code class="string">toscho_write_framebreaker</code>') )
{
    <i lang="en">/**
     * Inserts a javascript frame buster.
     * @return void
     */</i>
    function toscho_write_framebreaker()
    {
        <var>$script</var> = '<code class="string">
&lt;script type="text/javascript"&gt;
if (<var>self</var> != <var>top</var>)
{
    <var>top</var>.location.replace(<var>self</var>.location.href);
}
&lt;/script&gt;</code>';
        <i lang="en">/**
         * To alter the script output just use
         * add_filter('toscho_write_framebreaker', 'your_function');
         */</i>
        apply_filters('<code class="string">toscho_write_framebreaker</code>', <var>$script</var>);

        echo <var>$script</var>;

        return;
    }
}

add_action('<code class="string">wp_head</code>', '<code class="string">toscho_write_framebreaker</code>');
</pre>
<h2>Testen</h2>
<p>Jetzt aktivieren wir das Plugin. Wenn sich ein Fehler eingeschlichen hat, verweigert WordPress die Aktivierung, und wir sehen (meistens) die passende PHP-Fehlermeldung am Anfang der Plugin-Verwaltungsseite.</p>
<p>Wenn kein Fehler auftritt, laden wir jetzt unsere Startseite neu und sehen in den Quellcode: Richtig, da steht der Framebreaker.</p>
<p>Unser erstes Plugin ist fertig.</p>
<p>Naja … Software ist niemals ›fertig‹. Wir könnten beispielsweise noch Ausnahmen einbauen, die bestimmte Frames zulassen. Dank des Filters kann das zwar jetzt schon jeder tun, aber eine kleine Optionsseite dafür wäre handlicher. Vielleicht im nächsten Teil?</p>
<h2>Lektüre</h2>
<ul>
<li><a href='http://codex.wordpress.org/Writing_a_Plugin' hreflang="en">Writing a Plugin</a> und <a href='http://codex.wordpress.org/Plugin_Resources' hreflang="en">Plugin Resources</a> im Codex.</li>
<li>Olivier ›Ozh‹ Richard: <a href='http://planetozh.com/blog/2009/09/top-10-most-common-coding-mistakes-in-wordpress-plugins/' lang="en" hreflang="en">Top 10 Most Common Coding Mistakes in WordPress Plugins</a>.</li>
<li>Frank Bültge: <a href="http://bueltge.de/wp-tutorial-wir-schreiben-ein-simples-wp-plugin-teil-0/211/">WP - Tutorial, wir schreiben ein simples WP-Plugin - Teil 0</a> – von 2006, aber immer noch gute Lektüre.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/wordpress-tutorial-ein-framebreaker-plugin-schreiben/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>WordPress: Länge der Artikelliste im Backend anpassen</title>
		<link>http://toscho.de/2010/wordpress-laenge-artikelliste-backend-anpassen/</link>
		<comments>http://toscho.de/2010/wordpress-laenge-artikelliste-backend-anpassen/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 18:02:39 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Trickkiste]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1631</guid>
		<description><![CDATA[Wie man die Zahl der angezeigten Artikel unter ›Artikel/Bearbeiten‹ beeinflußt.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.im-tal.net/">Markus</a> gab heute im WP-Forum mal wieder einen <a href="http://forum.wordpress-deutschland.org/allgemeines/66168-artikel-pro-seite-800-im-backend.html">guten Tipp</a>: Die Menge der Artikel pro Seite im Backend wird über den Meta-Key <code>edit_per_page</code> in der Tabelle <code>wp_usermeta</code> gesteuert.<br />
Abgefragt wird sie in der Datei <code>/wp-admin/includes/post.php</code> mit:</p>
<pre class="notranslate"><var>$posts_per_page</var> = (int) get_user_option( '<code class="string">edit_per_page</code>', 0, false );</pre>
<p>Die Funktion <code>get_user_option()</code> wiederum bietet einen Filter an:</p>
<pre class="notranslate">apply_filters("<code class="string">get_user_option_{<var>$option</var>}</code>", <var>$result</var>, <var>$option</var>, <var>$user</var>);</pre>
<p>Und <em>daraus</em> folgt dieser kleine Eintrag in der <code>functions.php</code>, mit dem ich künftig 100 Artikel sehe, ohne die Datenbank anzufassen:</p>
<pre class="notranslate">add_filter('<code class="string">get_user_option_edit_per_page</code>',
    create_function('','<code class="string">return 100;</code>'));</pre>
<p>Das kann man noch an eine <a href="http://codex.wordpress.org/Roles_and_Capabilities" hreflang="en" title="Roles and Capabilities">Abfrage des Userlevels</a> binden, wenn man möchte. Mir reicht es so.</p>
<p>Strenggenommen gehört so eine Modifikation natürlich nicht ins Theme, sondern in ein Plugin. Andererseits möchte ich dafür nicht extra ein zusätzliches Plugin laden. Kompromisse, wohin man sieht …</p>
<p>Und noch strenger gesehen ist diese Option bereits vorhanden: In den Optionen der Artikelansicht. Dort findet sie aber kaum jemand, deshalb setze ich sie global.</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/wordpress-laenge-artikelliste-backend-anpassen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress-Dashboard: ›Approved‹ nicht ›Genehmigt‹</title>
		<link>http://toscho.de/2010/wordpress-dashboard-approved-nicht-genehmigt/</link>
		<comments>http://toscho.de/2010/wordpress-dashboard-approved-nicht-genehmigt/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 12:34:03 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Sprache]]></category>
		<category><![CDATA[Trickkiste]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1628</guid>
		<description><![CDATA[Wie man nicht übersetzte Zeichenketten per <code>functions.php</code> repariert.]]></description>
			<content:encoded><![CDATA[<p>Dank einer <a href="http://forum.wordpress-deutschland.org/sprachdatei/63073-sprachdatei-fuer-2-9-1-zum-testen.html#post293301">kleinen Schlamperei</a> seitens der WordPress-Entwickler kann das <i lang="en">Approved</i> im Dashboard derzeit nicht per Sprachdatei ins Deutsche übersetzt werden.</p>
<p>Mich stört es nicht, einige Kunden aber schon.</p>
<p>Bis das behoben ist, kann man sich mit einem kleinen Workaround in der <code>functions.php</code> des Themes aushelfen:</p>
<pre class="notranslate">add_filter(
    '<code class="string">ngettext</code>',
    create_function(
        '<code class="string"><var>$t</var>,<var>$s</var>,<var>$p</var></code>',
        '<code class="string">return "Approved"== <var>$p</var>?"Genehmigte":<var>$t</var>;</code>'),
    10, 3);</pre>
<p>Keine Schlamperei, sondern <a href="http://forum.wordpress-deutschland.org/sprachdatei/31178-anmerkung-zum-tellerrand.html">Absicht</a>: <i lang="en">Dashboard</i> wird weiterhin nicht ins Deutsche übersetzt. Auch diesen <i lang="en">Bug</i> kann man leicht reparieren, ohne die Sprachdatei anzufassen, wie auch das <i lang="en">Submitted on</i>:</p>
<pre class="notranslate">if ( ! function_exists('<code class="string">toscho_translations</code>') )
{
    function toscho_translations(<var>$str</var>)
    {
        <i>// Diesen Array bei Bedarf um weitere Übersetzungen erweitern.</i>
        <var>$trans</var> = array (
            '<code class="string">Dashboard</code>'     =&gt; '<code class="string">Übersicht</code>',
            '<code class="string">Submitted on</code>'  =&gt; '<code class="string">Eingereicht am</code>'
        );

        foreach ( <var>$trans</var> as <var>$original</var> =&gt; <var>$translation</var> )
        {
            <var>$str</var> = str_replace(<var>$original</var>, <var>$translation</var>, <var>$str</var>);
        }

        return <var>$str</var>;
    }
    add_filter('<code class="string">gettext</code>', '<code class="string">toscho_translations</code>');
}</pre>
<p>Und so sieht das Ergebnis aus:</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/02/dashboard-uebersetzt.png" alt="Dashboard übersetzt" width="529" height="229" class="alignnone size-full wp-image-1629 border" /></p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/wordpress-dashboard-approved-nicht-genehmigt/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Webdesign fürs iPad</title>
		<link>http://toscho.de/2010/webdesign-fuers-ipad/</link>
		<comments>http://toscho.de/2010/webdesign-fuers-ipad/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 13:43:33 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Browser]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Webdesign]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1625</guid>
		<description><![CDATA[Wie man sein Layout iPad-tauglich gestaltet.]]></description>
			<content:encoded><![CDATA[<p>Der Bettvorleger ist <a href="http://www.heise.de/mobil/meldung/iPad-Apple-praesentiert-das-erwartete-Tablet-2-Update-915500.html">gelandet</a>. Apple hat am Mittwoch das iPad vorgestellt, ein Gerät, das die Nachteile eines Notebooks mit denen des iPhones kombiniert: Kein USB-Anschluß, kein DVD- oder BlueRay-Laufwerk, kein UMTS. Multitasking, das Ausführen parallel laufender Programme, geht auch nicht. Das einzige, das glänzt, ist das Display in einer Auflösung von 768×1024 Pixeln.</p>
<p><object width="480" height="295"><param name="movie" value="http://www.youtube.com/v/1ZS8HqOGTbA&#038;hl=de_DE&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/1ZS8HqOGTbA&#038;hl=de_DE&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="295"></embed></object></p>
<p>Viele <a title="Christian Reber: iPad - Aber auch nur beinahe perfekt" href="http://www.christianreber.com/ipad-aber-auch-nur-beinahe-perfekt">Beobachter</a> geben sich jetzt <a href="http://al3x.net/2010/01/28/ipad.html" hreflang="en" title="Alex Payne: On the iPad">enttäuscht</a>. So ein Wirbel um ein so <em>langweiliges</em> Spielzeug? Mich hat das nicht überrascht oder gar enttäuscht. Ich mache mit Apple ohnehin keine Geschäfte.<br />
Aber für den Markt freue ich mich: Die Geräteklasse wird durch Apple eingeführt und bekannt gemacht, und jeder Konkurrent kann den Pionier leicht ausstechen. Es genügt ein USB-Anschluß und die Option, daß der Kunde im Gegensatz zum iPad seine Akkus <em>selber wechseln</em> kann, wenn er möchte. Packt man noch ein richtiges, <em>mattes</em> Display drauf und eine UMTS-Verbindung, dann kommt sogar ein mobiles Gerät dabei heraus.</p>
<p>Als Designer freue ich mich auch: Die Bildschirmbreite von maximal 1024 Pixeln wird all jenen auf die Füße fallen, die bisher Festbreiten gemeißelt und damit das Web verschmutzt haben. Real werden die Benutzer dieses Spielzeugs lieber hochkant lesen, also nur 768 Pixel bereitstellen. Gute Layouts passen sich dem an, schlechte werden einfach nicht mehr benutzt.</p>
<p>Wer jetzt erst auf ein modernes Layout umstellt, mag dies bedenken:</p>
<ul>
<li>Auf einem <i lang="en">Touchscreen</i> sollten <strong>Links</strong> nicht zu dicht beieinander liegen. Finger treffen schlechter als eine Maus. Peter-Paul Koch hat dazu gerade ein bißchen geforscht: <a href="http://www.quirksmode.org/blog/archives/2010/02/the_touch_actio.html" hreflang="en" lang="en">The touch action</a>.<br />
Das interessante Problem hierbei: Wer mit solchen Bildschirmmaßen kommt und <em>doch</em> eine Maus benutzt, der möchte keinen Platz für zusätzlichen Leeraum vergeuden. Vielleicht wird sich der iPad-Safari ja per Javascript zu erkennen geben, damit man den gezielt ansprechen kann.<br />
Die Pseudo-Klasse <code>:hover</code> oder <code>onmouse*</code>-Events werden nicht angesprochen.</li>
<li>Eine horizontale Navigation sollte am Seitenrand <strong>umbrechen</strong>, sonst verschwinden vielleicht wichtige Elemente rechts hinter dem Bildschirmrand.</li>
<li>Bei Tageslicht liefert ein Spiegeldisplay schlechte <strong>Kontraste</strong>. Orangefarbene Links auf weißem Hintergrund beispielsweise dürften kaum noch zu erkennen sein.<br />
Sehr lange Texte möchte sicher niemand auf weißem Hintergrund lesen. Hier kann man einen Styleswitcher anbieten, wenn das iPad keinen eigenen Regler mitbringt.</li>
<li>
<p>Safari, der Webbrowser auf dem iPad, unterstützt <strong><a href='http://www.w3.org/TR/css3-mediaqueries/' hreflang="en" lang="en">Media Queries</a></strong> ein bißchen. Das kann man so ansprechen:</p>
<pre class="notranslate">@media screen and (max-device-width: 1024px)
{
    <em>/* Horizontal */</em>
}
@media screen and (max-device-width: 768px)
{
    <em>/* Vertikal */</em>
}
@media screen and (max-device-width: 480px)
{
    <em>/* iPhone. Findet @media handheld nicht. */</em>
}</pre>
<p>Opera und Firefox verstehen das natürlich auch, im Gegensatz zu Safari sogar nach einer <a hreflang="en" href="http://msdn.microsoft.com/en-us/library/ms537634(VS.85).aspx">IE-Expression</a>.</p>
<pre class="notranslate">* html textarea
    {
        border:             expression(
            this.onfocus = function()
                {
                    this.style.borderColor = '<code class="string">#27b</code>';
                },
            this.onblur = function()
                {
                    this.style.borderColor = '<code class="string">#888</code>';
                }
            );
    }

@media screen and (max-device-width: 768px)
{
    <em>/* Das liest Safari nicht. */</em>
}</pre>
</li>
<li>Auf dem iPad gibt es <strong>kein Flash</strong>. Dafür sollte normalerweise schon längst eine Alternative bereitstehen, aber oft sieht die <a href="http://www.google.com/search?q=ihr+browser+unterst%C3%BCtzt+kein+flash&#038;num=50&#038;ie=utf-8&#038;oe=utf-8">eher peinlich</a> aus. Safari versteht Javascript und <a href="http://www.peterkroener.de/eine-kleine-canvas-einfuehrung/">Canvas</a>; wer das nutzt, kann auf Flash oft verzichten.</li>
<li>Wenn der Safari als Mobilvariante installiert ist, dann kann er vielleicht <a href="http://doctyper.com/archives/200808/fixed-positioning-on-mobile-safari/">kein <code>position:fixed</code></a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/webdesign-fuers-ipad/feed/</wfw:commentRss>
		<slash:comments>42</slash:comments>
		</item>
		<item>
		<title>WordPress: WP-Cron begrenzen</title>
		<link>http://toscho.de/2010/wordpress-wp-cron-begrenzen/</link>
		<comments>http://toscho.de/2010/wordpress-wp-cron-begrenzen/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 16:49:28 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1622</guid>
		<description><![CDATA[Wie man die vielen Requests innerhalb WordPress’ auf ein vernünftiges Maß reduziert.]]></description>
			<content:encoded><![CDATA[<p>So sehr ich WordPress auch <a href="http://toscho.de/2010/wordpress-cms/">schätze</a> – einige Macken gehen mir tüchtig auf die Nerven. Dazu gehören auch die vielen Requests auf <code>wp-cron.php?doing_wp_cron</code>.<br />
Solch ein Request wird bei (fast?) jedem Aufruf einer Seite oder eines Artikels angestoßen. Zwar werden dabei kaum Daten übertragen, aber ein bißchen Zeit kostet es eben doch, und das <a href="http://toscho.de/2010/logfiles-analysieren/">Logfile</a> wächst ohne Not.</p>
<p>Ich habe mir deshalb in die Konfigurationsdatei <code>wp-config.php</code> diese kleine Einschränkung eingetragen:</p>
<pre class="notranslate">if ( 0 < (time() % 10) )
{
    define('<code class="string">DISABLE_WP_CRON</code>', TRUE);
}</pre>
<p>Zu Deutsch: Wenn sich der aktuelle, in Sekunden gemessene UNIX-Timestamp nicht genau durch 10 teilen läßt, verzichte ich auf WP-Cron.</p>
<p>Damit funktionieren noch die Kontrollen auf neue Plugin- oder WordPress-Versionen, doch die Menge der Requests schrumpft dramatisch. Wer noch weniger Aufrufe haben möchte, der erhöhe einfach den Teiler.</p>
<p>Natürlich könnte man die Pseudo-Cronjobs auch einfach komplett abschalten und einen <a href="http://linux.die.net/man/8/cron" hreflang="en">richtigen Cron</a> benutzen. WordPress sendet aber einen POST-Request, dessen Zusammensetzung ich nach jedem Update neu überprüfen müßte, um den echten Cron entsprechend anzupassen. Das ist mir zu umständlich.</p>
<p>Einen guten Überblick über die anstehenden Cronjobs bekommt man mit dem <a href="http://wordpress.org/extend/plugins/cron-view/installation/" lang="en" hreflang="en">Plugin Cron View</a>. Das sieht dann ungefähr so aus:</p>
<p><img src="http://toscho.de/wp-content/uploads/2010/01/cron-view.png" alt="Cron View" width="500" height="198" class="alignnone size-full wp-image-1623 border" /></p>
<p>Wer gerne Plugins ausprobiert, sollte sich das unbedingt mal ansehen, denn nicht jeder Autor schreibt eine saubere Deinstallation.</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/wordpress-wp-cron-begrenzen/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>WordPress: Grundeinstellungen per Plugin setzen</title>
		<link>http://toscho.de/2010/wordpress-grundeinstellungen-per-plugin-setzen/</link>
		<comments>http://toscho.de/2010/wordpress-grundeinstellungen-per-plugin-setzen/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 19:23:06 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Trickkiste]]></category>
		<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1621</guid>
		<description><![CDATA[Wie man den Weg durch die vielen Einstellungsseiten abkürzt. Code zur Ansicht und ein Plugin zum Download.]]></description>
			<content:encoded><![CDATA[<p>Wer öfter mal ein WordPress-Blog installiert, weiß die vielen Einstellungsseiten nicht unbedingt zu goutieren. Ich habe mir dafür ein kleines Plugin geschrieben, das die wichtigsten Optionen auf einen Schlag setzt, die Blogroll (Linkliste) leert und die Dummytexte löscht:</p>
<p class="downloadlink"><a class='piwik_download' lang="en" href="http://f.toscho.de/php-skripte/toscho_basic_settings.zip">Download Toschos Basic Settings</a>.</p>
<pre class="notranslate">&lt;?php
<i>/*
Plugin Name: Toscho's basic settings
Plugin URI: http://toscho.de/2010/wordpress-grundeinstellungen-per-plugin-setzen/
Description: Some useful default configuration settings. See 'wp-admin/options.php' for more options.
Version: 0.3
Author: Thomas Scholz
Author URI: <a href="http://toscho.de/">http://toscho.de</a>
*/</i>

function set_toscho_defaults()
{
    global <var>$wpdb</var>;
    <var>$o</var> = array(
        '<code class="string">avatar_default</code>'            =&gt; '<code class="string">blank</code>',
        '<code class="string">avatar_rating</code>'             =&gt; '<code class="string">G</code>',
        '<code class="string">category_base</code>'             =&gt; '<code class="string">/thema</code>',
        '<code class="string">comment_max_links</code>'         =&gt; 0,
        '<code class="string">comments_per_page</code>'         =&gt; 0,
        '<code class="string">date_format</code>'               =&gt; '<code class="string">d.m.Y</code>',
        '<code class="string">default_ping_status</code>'       =&gt; '<code class="string">closed</code>',
        '<code class="string">default_post_edit_rows</code>'    =&gt; 30,
        '<code class="string">links_updated_date_format</code>' =&gt; '<code class="string">j. F Y, H:i</code>',
        '<code class="string">permalink_structure</code>'       =&gt; '<code class="string">/%year%/%postname%/</code>',
        '<code class="string">rss_language</code>'              =&gt; '<code class="string">de</code>',
        '<code class="string">timezone_string</code>'           =&gt; '<code class="string">Etc/GMT-1</code>',
        '<code class="string">use_smilies</code>'               =&gt; 0,
        '<code class="string">start_of_week</code>'             =&gt; 1
    );

    foreach ( <var>$o</var> as <var>$k</var> =&gt; <var>$v</var> )
    {
        update_option(<var>$k</var>, <var>$v</var>);
    }

    <i>// Delete dummy post and comment.</i>
    wp_delete_post(1, TRUE);
    wp_delete_comment(1);

    <i>// empty blogroll</i>
    <var>$wpdb</var>->query("<code class="string">DELETE FROM <var>$wpdb</var>->links WHERE link_id != ''</code>");

    return;
}
register_activation_hook(__FILE__, '<code class="string">set_toscho_defaults</code>');</pre>
<p>Dieses Plugin aktivieren, deaktivieren und löschen. Fertig.</p>
<p><strong>Nachtrag:</strong> Dieses kleine Plugin hat jetzt auch seine eigene GitHub-Adresse: <a href="http://github.com/toscho/WordPress-Basic-Settings">http://github.com/toscho/WordPress-Basic-Settings</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/wordpress-grundeinstellungen-per-plugin-setzen/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>CSS: Mit ::selection markierten Text hervorheben</title>
		<link>http://toscho.de/2010/css-mit-selection-markierten-text-hervorheben/</link>
		<comments>http://toscho.de/2010/css-mit-selection-markierten-text-hervorheben/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 22:58:53 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Webdesign]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1619</guid>
		<description><![CDATA[Wie man per CSS die Auswahl färbt.]]></description>
			<content:encoded><![CDATA[<p>Das Pseudo-Element <code>::selection</code> stand lange im Entwurf für die <a hreflang='en' href="http://www.w3.org/TR/css3-selectors/">CSS3-Selektoren</a>. Das ursprüngliche Ziel war: Die normale Gestaltung des Browsers für markierte Elemente sollte mit CSS ausgedrückt und überschrieben werden können.<br />
Seit dem 10. März 2009 jedoch fehlt es, <a href='http://lists.w3.org/Archives/Public/www-style/2009Oct/0277.html' hreflang='en'>weil</a> es zu schlecht definiert war und es zu aufwendig gewesen wäre, den Text konsensfähig zu verbessern.</p>
<p>Der <a href='http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#UIfragments' hreflang='en' class='notranslate'>alte Text</a> im Wortlaut:</p>
<blockquote lang='en'><p>The <code>::selection</code> pseudo-element applies to the portion of a document that has been highlighted by the user. This also applies, for example, to selected text within an editable text field. This pseudo-element should not be confused with the <code>:checked</code> pseudo-class (which used to be named <code>:selected</code>) </p>
<p>Although the <code>::selection</code> pseudo-element is dynamic in nature, and is altered by user action, it is reasonable to expect that when a UA re-renders to a static medium (such as a printed page, see CSS21) which was originally rendered to a dynamic medium (like screen), the UA may wish to transfer the current <code>::selection</code> state to that other medium, and have all the appropriate formatting and rendering take effect as well. This is not required — UAs may omit the <code>::selection</code> pseudo-element for static media. </p>
<p>These are the CSS properties that apply to <code>::selection</code> pseudo-elements: <code>color</code>, <code>background</code>, <code>cursor</code> (optional), <code>outline</code> (optional). The computed value of the '<code>background-image</code>' property on <code>::selection</code> may be ignored.</p>
</blockquote>
<p>Ein paar Lücken springen sofort ins Auge:</p>
<ul>
<li>Was soll eine <i lang='en'>»portion of a document«</i> sein? Wenn ich beispielsweise im Zitat den unteren Teil des ersten Absatzes markiere und den oberen des zweiten: Wie sieht dann die Box des Pseudo-Elements aus? Oder sind es zwei Boxen? Was erwischt <a hreflang='en' href='http://www.w3.org/Style/CSS/Tracker/issues/67'>p::selection</a>?</li>
<li>Wenn im markierten Text <i lang='en'>Generated Content</i> auftaucht: Ist der dann Teil des Dokuments?</li>
<li>Kann der Selektor <code>::selection + ::before</code> zutreffen? Und <code>::selection + ::selection</code>?</li>
</ul>
<p>Dennoch haben Opera und Webkit den Selektor implementiert, und Mozilla immerhin eine <a href='https://bugzilla.mozilla.org/show_bug.cgi?id=176170' hreflang='en'>Variante</a> mit dem <code>-moz-</code>Präfix.</p>
<p>Ich empfehle den Einsatz immer dann, wenn heller Text auf dunklem Hintergrund steht. Die normale Markierung kann der Leser sonst vielleicht schlecht oder gar nicht erkennen.</p>
<p>Beispiel:</p>
<pre class="notranslate">.dark ::selection
    {
        color:      #000;
        background: #ff9;
    }
.dark ::-moz-selection
    {
        color:      #000;
        background: #ff9;
    }</pre>
<p>Wir können die beiden Varianten leider nicht bündeln, denn der Browser muß eine Regel ignorieren, wenn er einen Selektor nicht erkennt. Mehr als Vorder- und Hintergrundfarbe kann man derzeit in keinem Browser ändern. Reicht ja auch.</p>
<p>Einen kurzen Test auf die oben genannten Lücken sollte man sich schon gönnen, aber im Groben kann nichts <em>richtig</em> schiefgehen.</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/css-mit-selection-markierten-text-hervorheben/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Lächeln 0.9</title>
		<link>http://toscho.de/2010/laecheln-0-9/</link>
		<comments>http://toscho.de/2010/laecheln-0-9/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 22:59:57 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Kunterlei]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1618</guid>
		<description><![CDATA[Das Wichtigste fehlt: der Spaß. Warum?]]></description>
			<content:encoded><![CDATA[<p>An vielen <i lang="en">Social Networks</i> des Web 2.0 – Twitter mal ausgenommen – irritiert mich immer wieder, wie wenig Humor man dort findet. </p>
<ul>
<li>Bei Facebook entsteht er <a href="http://toscho.de/2009/automatisch-makaber/">eher unfreiwillig</a> oder als Twitterimport.</li>
<li>delicious.com füttert gerade mal meinen Zynismus: 10435 Nutzer haben <a href="http://delicious.com/url/c513827c6d646a8f2ec682f0be63d6ff">delicious.com als Lesezeichen</a> gespeichert und <a href="http://delicious.com/url/ff90821feeb2b02a33a6f9fc8e5f3fcd">44136 sogar Google</a>.</li>
<li>youtube.com glänzt mit <a href="http://stupid-youtube-comments.blogspot.com/">dummen Kommentaren</a>.</li>
<li>Bei Xing.com treten sich die Leute gegenseitig auf die Krawatten.</li>
<li>Und auf Google Wave kann man nur <a href="http://toscho.de/2010/goodbye-google-wave/">über Google Wave lachen</a>.</li>
</ul>
<p>Woran liegt das? Übersehe ich etwas? Fehlt mir der Humor?<br />
Das Usenet habe ich <a href="http://best-of-netdigest.jendryschik.de/">lustiger in Erinnerung</a>, ebenso <a href="http://german-bash.org/">IRC</a>.<br />
›Alte‹ Netzwerke, deren Teilnehmer vielleicht auch ob dieses Mangels nicht in die ›neuen‹ wechseln mögen …</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/laecheln-0-9/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Goodbye Google Wave</title>
		<link>http://toscho.de/2010/goodbye-google-wave/</link>
		<comments>http://toscho.de/2010/goodbye-google-wave/#comments</comments>
		<pubDate>Sun, 24 Jan 2010 18:28:06 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Kunterlei]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1615</guid>
		<description><![CDATA[Epitaph auf die angebliche Zukunft. Ohne Bedauern.]]></description>
			<content:encoded><![CDATA[<p>Vor ein paar Tagen habe ich mich mal wieder bei Google Wave eingeloggt. Das kann ich jedem nur <a href='http://toscho.de/2009/google-wave-einladungen/' title="Einladung abholen">empfehlen</a>, der sich von Twitter erholen will, von überquellenden Feedreadern und Todo-Listen, für deren Ausdruck man einen ganzen Wald niedermähen müßte.</p>
<p title="Simon &amp; Garfunkel: The Sound of Silence"><object width="300" height="30"><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed type="application/x-shockwave-flash" src="http://soundzit.net/szplayer/player.swf" quality="high" allowfullscreen="false" allowscriptaccess="always" flashvars="file=http://www.youtube.com/watch?v=VflKiZzb4h4&#038;feature=youtube_gdata&#038;skin=http://soundzit.net/szplayer/skinout.swf&#038;backcolor=#000000&#038;lightcolor=#FF6600&#038;frontcolor=#FFFFFF&#038;abouttext=Go to Soundzit.com&#038;aboutlink=http://soundzit.com" width="300" height="30"></embed></object></p>
<p>Denn Google Wave ist der OBI des Internets: Zwischen Regalen voller Technik hört der Forschungsreisende allein das Echo seiner Schritte. Hier und da tappt noch ein <a href='http://docs.google.com/View?docid=0AWgfoS9Tf_CWZGQ0anhndHFfMjgzZ2o0aHc3Z3Q&#038;hgd=1'>Zombie</a> durch die Gänge oder ein <a href='https://twitter.com/sir_pepe/status/7800539976'>braver Ritter</a> auf der Suche nach dem heiligen Blip.<br />
Macht nix: Denen kann man leicht ausweichen, sie sind langsam. In Google Wave ist <em>alles</em> langsam, deshalb heißt es ja ›Echtzeitweb‹.</p>
<div id="attachment_1616" class="wp-caption alignnone" style="width: 510px"><img src="http://toscho.de/wp-content/uploads/2010/01/lonely-monkey-ape-epsos-2.jpg" alt="Foto: Einsamer Affe" width="500" height="375" class="size-full wp-image-1616" /><p class="wp-caption-text">Foto: <a lang='en' href='http://www.flickr.com/photos/epsos/3697643787/'>Lonely Monkey Ape at the Zoo</a> von <a href='http://www.flickr.com/photos/epsos/'>epSos.de</a></p></div>
<p>Wenn man doch mal jemandem begegnet, dann entfaltet Google Wave freilich seine ganze Pracht: </p>
<ul>
<li>Man kann einander beim Vertippen zusehen, sofern man in dieser Fitzelschriftwüste überhaupt etwas zu lesen vermag. </li>
<li>Man kann »kollaborieren«, was ganz vermutlich etwas anderes ist als »kollabieren«. </li>
<li>Man kann, das ist wirklich neu, miteinander chatten.</li>
<li>Und gemeinsam Dokumente erstellen kann man auch. Wenn man möchte – und auf einen brauchbaren Export ebenso verzichtet wie auf eine Versionsverwaltung. Aber die gibt es im »richtigen« Leben doch auch nicht. Nur im richtigen Internet. Dem von heute, von <a href="http://toscho.de/2010/willkommen-im-alten-jahrzehnt/">2010</a>.
<p>Florian bringt es auf den Punkt:</p>
<p><a href="http://twitter.com/Elchi3/status/7300662181"><img src="http://toscho.de/wp-content/uploads/2010/01/elchi3-wave-2009.png" alt="Google Wave ist so 2009" width="381" height="191" class="size-full wp-image-1617 border" /></a></li>
</ul>
<p>Und auf welches Grab spucken wir nächstes Jahr?</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/goodbye-google-wave/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Warum UTF-8?</title>
		<link>http://toscho.de/2010/warum-utf-8/</link>
		<comments>http://toscho.de/2010/warum-utf-8/#comments</comments>
		<pubDate>Sat, 23 Jan 2010 22:13:51 +0000</pubDate>
		<dc:creator>Thomas Scholz</dc:creator>
				<category><![CDATA[Webdesign]]></category>
		<category><![CDATA[Zeichen]]></category>

		<guid isPermaLink="false">http://toscho.de/?p=1614</guid>
		<description><![CDATA[Gründe für den Umstieg. Vorteile der Zeichenkodierung UTF-8.]]></description>
			<content:encoded><![CDATA[<p>Manche Leute halten <a hreflang="en" href="http://www.ietf.org/rfc/rfc2279.txt"><abbr title="Unicode transformation format" lang="en">UTF</abbr>-8</a> immer noch für Voodoo. Schade. Wer Textformate produziert, <em>muß</em> irgendwann 20 Minuten aufwenden, um die <a href="http://toscho.de/2008/grundlagen-zeichenkodierung/">Grundlagen der Zeichenkodierung</a> zu verstehen, und er <em>sollte</em> UTF-8 benutzen – und dabei wissen, was er tut. Warum?</p>
<p>UTF-8 ist eine Zeichenkodierung für <a hreflang="en" lang="en" class="notranslate" href="http://www.unicode.org/standard/standard.html">Unicode</a>. Damit können wir alle Zeichen aus Unicode benutzen, ohne sie zu <a href="http://toscho.de/2008/zeichenkodierung-begriffe/#toc-maskierung-entity-und-zeichenreferenz">maskieren</a>: das deutsche Alphabet und das chinesische, Währungszeichen, Musiknoten, Pfeile und Schachfiguren.</p>
<p>In E-Mails mag UTF-8 <a title="UTF-8-Unterstützung deutscher Webmail-Anbieter" href="http://www.walkingsmall.de/2009/04/07/email-clients-freemailer-und-utf-8/">noch nicht</a> immer angebracht sein; im <a href="http://toscho.de/thema/markup/" title="Meine Artikel zum Thema ›Markup‹">Markup</a> jedoch können wir nicht mehr darauf verzichten:</p>
<ul>
<li>In unseren <strong>Formularen</strong> wollen wir jedes Zeichen verarbeiten können. Wenn wir kein UTF benutzen, riskieren wir, wichtige Daten zu verlieren.</li>
<li>Alle <strong>XML-Parser</strong> <em>müssen</em> UTF-8 verstehen (und UTF-16). Newsfeeds, SVG, XSLT, RDF – all diese Formate sollten wir nur in UTF-8 oder UTF-16 schreiben, damit jeder sie gewiß verarbeiten kann.</li>
<li>Alle wichtigen <strong>APIs der großen Webdienste</strong> liefern UTF-8 aus: Flickr, Twitter, Youtube oder Delicious. Wenn wir diese Daten verarbeiten wollen, sollten wir uns nicht den Umweg einer Konvertierung zumuten.</li>
<li>UTF-8 ist im Unterschied zu UTF-16 bedingt <strong>kompatibel zu US-ASCII</strong>, denn alle ASCII-Zeichen werden deckungsgleich kodiert. Zeichen oberhalb des Dezimalwerts 127 freilich brauchen zwei Bytes. Deshalb ist es in allen Sprachen, die eine Variante des lateinischen Alphabets verwenden, sehr <strong>kompakt</strong>.</li>
<li>Die meisten Browser <a href="http://www.w3.org/International/articles/idn-and-iri/" title="An Introduction to Multilingual Web Addresses" hreflang="en">verwenden</a> für <strong>Nicht-ASCII-Zeichen in URLs</strong> UTF-8. Wenn wir das nicht erwarten, werden wir unsere Besucher sicher bald frustrieren.</li>
<li>UTF-8 können wir <strong>validieren</strong>: So <a href="http://toscho.de/2009/utf-8-erzwingen/">finden und reparieren</a> wir falsch kodierte Zeichen, ehe der Leser sie sieht.</li>
<li>UTF-8 braucht <strong>kein <abbr title="Byte Order Mark" lang="en">BOM</abbr></strong>. Auch ein Vorteil gegenüber UTF-16 und UTF-32. Anleitung: <a href="http://toscho.de/2009/bom-entfernen/">Bom entfernen</a>.</li>
</ul>
<p>In einigen Programmiersprachen – <a href="http://techblog.notify.me/post/59407777/perl-utf-8-hell-and-how-to-find-your-way-out">Perl</a> oder <a href="http://www.phpwact.org/php/i18n/utf-8">PHP</a> beispielsweise – hängt die Implementierung der Multibytekodierungen noch ein bißchen. Aber mit ein wenig Lektüre können wir auch diese Probleme meistens lösen. Nie entschuldigen <em>sie allein</em> den Verzicht auf UTF-8.</p>
<p>Zu diesem Artikel wurde ich durch zwei Diskussionsbeiträge inspiriert: einen <a href="http://forum.ecombiz.de/seo-nature/4203-doctype-und-zeichenkodierung.html#post26337">schlechten</a> und einen <a href="http://groups.google.com/group/de.comm.infosystems.www.authoring.misc/msg/0e782543d0e11096">guten</a>. Der gute stammt von <a href="http://www.bjoernsworld.de/" class="notranslate">Björn Höhrmann</a>, dem ich deshalb ausdrücklich danken will.</p>
]]></content:encoded>
			<wfw:commentRss>http://toscho.de/2010/warum-utf-8/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>
