Sorry, my Hyphenation class only works with German language, thus this page is not translated.
Die Klasse Silbentrennung kann eingesetzt werden, um in einem Text lange Wörter automatisch zu trennen und somit Layoutprobleme zu vermeiden. Lücken wegen zu langer Wörter können vor allem Blocksatz unlesbar machen, aber auch wenn rechtsbündiger Fließtext in der Breite wenig Platz hat, können unschöne, den Lesefluss behindernde Effekte auftreten:
Hier hätte eine automatische Silbentrennung einen guten Dienst getan – optimalerweise nur auf den bebilderten Einleitungsabsatz angewandt, da die restlichen Absätze in der Regel breiter sind.
An dieser Stelle sei aber angemerkt, dass “automatisch” in diesem Fall eher halb- als vollautomatisch bedeutet. Das Verfahren ist konzeptbedingt nicht perfekt, wie spätere Beispiele zeigen werden. Und ein falsch getrenntes Wort ist nicht weniger peinlich als eines, das für eine schmale Spalte zu breit ist. Ein guter Kompromiss ist es, den Text beim Veröffentlichungsprozess vom Autor oder Lektor gegengelesen zu lassen (was ja in der Regel sowieso passiert – oder passieren sollte), sodass dieser nebenbei die Trennung kontrollieren kann. Im Gegenzug spart man sich, wenn ein Wort mal wieder das Layout sprengt, die Suche nach einem alternativen Begriff oder das manuelle Trennen mit - , was ebenfalls fehleranfällig ist:
Requires: Preprocess
<?php
/**
* class Silbentrennung
* Zum Erkennen von Silben und Trennen von Wörtern in deutschsprachigen Texten.
* Copyright (C) 2006 Dao Gottwald <dao at design-noir.de>
*
* Licensed under the terms of the GNU Lesser General Public License:
* http://www.opensource.org/licenses/lgpl-license.php
*
* Die Trennregeln wurden mithilfe folgender Seiten erstellt:
* http://www.ruediger-weingarten.de/Orthographie/Silbentrennung.htm
* http://www.ifi.unizh.ch/CL/volk/LexMorphVorl/Lexikon12.Gener.html
* http://www.schneid9.de/pdf/ling07.pdf
*
* @version 1.2.6
*/
require_once 'Preprocess.php';
class Silbentrennung extends Preprocess {
private
$zeichen, $rZeichen, /* Trennzeichen */
$min_wortlaenge, /* minimale Länge zu trennender Wörter */
$min_silbenlaenge, /* minimale Länge einer Silbe */
$offset; /* Anzahl der Buchstaben, die am Wortanfang/-ende nicht abgetrennt werden sollen */
private static
$a = '[a-zßäÄüÜöÖ]', /* alle Buchstaben */
$v = 'aeiouäÄüÜöÖy', /* Vokalbuchstaben */
$pattern = array();
public function __construct ($min_wortlaenge = 16, $min_silbenlaenge = 3, $offset = 4, $zeichen = '­') {
$this->min_wortlaenge = (int) $min_wortlaenge;
$this->min_silbenlaenge = (int) $min_silbenlaenge;
$this->offset = (int) $offset;
$this->zeichen = (string) $zeichen;
$this->rZeichen = preg_quote ($this->zeichen, '~');
if (empty (self::$pattern)) {
/* Konsonantenbuchstaben */
$k = 'bcdfghklmnpqrßtvwxz';
/* besondere Konsonanten */
$_k = 's';
/* Vokale */
$v = self::$v;
/* Digraphen und Konsonanten */
$d = "(?:s?ch|s[tp]|[$k]|s(?!ch))";
self::$pattern[] = "ß(?![$v])";
/* Prefixe */
self::$pattern[] = "(?:durch|hinter|hinaus|miss|[üÜ]ber)";
self::$pattern[] = "\B(?=durch|hinter|hinaus|miss|[üÜ]ber)";
self::$pattern[] = "(?>\b)(?:a[nb](?![$v])|au[fs]|be|ent|emp|er|ge|[vz]er|fehl|um|unter|voll|wie?der|ex)";
self::$pattern[] = "(?:au[fs]|be|ein|ent|emp|er|ge|[vz]er|fehl|um|unter|voll|wie?der|ex)(?![$v])";
/* Suffixe */
self::$pattern[] = "(?:igen?|lichen?|schafts?|[$k$_k]ungs?|[hk]eits?)";
self::$pattern[] = "\B(?=igen?|lichen?|schaft|[$k$_k]ung|[hk]eit)";
/* bei mindestens einem Konsonanten zwischen zwei Vokalen wird vor dem letzten Konsonant getrennt */
self::$pattern[] = "[$v]$d{1,3}?(?={$d}h?[$v])";
self::$pattern = implode ('|', self::$pattern);
}
}
public function run ($text) {
if (is_array ($text)) {
$text = $text[0];
}
if (strpos ($text, '<') !== false && strpos ($text, '<') < strpos ($text, '>')) {
$this->text =& $text;
$this->_escape_init();
$this->_escape_comments_cdata();
$this->_escape_content ('head', 'pre', 'code', 'blockcode', 'textarea');
$text = '>'. $text. '<';
$text = preg_replace_callback ('~>[^<]+<~s', array ($this,'run'), $text);
$this->_escape_fin();
return substr ($text, 1, -1);
}
if ($this->min_wortlaenge > 1) {
$text = preg_replace_callback ('~'.self::$a.'{'.$this->min_wortlaenge.',}~i', array ($this,'_worttrenn'), $text);
} else {
$text = preg_replace_callback ('~'.self::$a.'+~i', array ($this,'_worttrenn'), $text);
}
return $text;
}
private function _worttrenn (array $wort) {
$wort = $wort[0];
$a = self::$a;
$v = self::$v;
$z = $this->rZeichen;
$wort = preg_replace ('~'.self::$pattern.'~i', '\\0'.$this->zeichen, $wort);
$wort = preg_replace ("~$z\$~", '', $wort);
$wort = preg_replace ("~$z([^$v]+)\$~i", '\\1', $wort);
if ($this->offset) {
$o = $this->offset;
$wort = preg_replace ("~^($a{1,$o})$z~i", '\\1', $wort);
$wort = preg_replace ("~$z($a{1,$o})\$~i", '\\1', $wort);
}
if ($this->min_silbenlaenge) {
$m = $this->min_silbenlaenge;
$wort = preg_replace ("~(?<=$z)($a{1,$m})$z~i", '\\1', $wort);
}
return $wort;
}
}
?>
Dem Konstruktor können folgende optionale Argumente übergeben werden:
Nach einer Instanziierung kann die Methode run() aufgerufen werden. Sie erwartet den zu behandelnden Text als Argument und gibt diesen nach der vollzogenen Silbentrennung zurück. Der Text darf HTML-Code enthalten. HTML-Tags werden dabei nicht behandelt, außerdem wird der gesamte Inhalt von <!--...-->, <![CDATA[...]]>, <head>...</head>, <pre>...</pre>, <code>...</code> und <textarea>...</textarea> ignoriert.
Es folgt ein Beispiel mit einigen zusammengesetzten Wörtern. Zur Anschaulichkeit wird ein immer sichtbares Trennzeichen und keine minimale Wort- und Silbenlänge verwendet.
<?php
ob_start (array (new Silbentrennung (0, 0, 0, '-'), 'run'));
?>Ehre + Tribüne
Ehrentribüne
Moskau + treu
moskautreu
Widerstand + Gruppe
Widerstandsgruppe
selbst + verständlich
selbstverständlich
Unterhaltung + Software
Unterhaltungssoftware
Bildung + Ministerien
Bildungsministerien
national + Sozialismus
Nationalsozialismus
Geschwindigkeit + Begrenzer
Geschwindigkeitsbegrenzer
Geschwindigkeit + Überschreitung
Geschwindigkeitsüberschreitung
Krieg + Gedenken + Tag
Kriegsgedenktag
mehr + Spieler + Namen
Mehrspielernamen
Licht + Spiel + Theater
Lichtspieltheater
Wie man sieht, arbeitet die automatische Trennung in einzelnen Wörtern recht zuverlässig. Doch wenn zwei Wörter zusammentreffen, hat der Algorithmus in ungünstigen Fällen keine Chance, die Konsonanten einer Silbe zuzuordnen. Treffen mehr als drei Konsonanten aufeinander, wird daher nicht getrennt.
Zwar werden auf diese Weise einige Wortgrenzen sowie Silben (die im Deutschen bis zu fünf Konsonanten hintereinander enthalten können) übersehen, aber Ziel war es auch nicht, alle Silben zu finden. Und für die Praxis ist eine übersehene Silbe besser als eine falsche. Dennoch ist es ein offensichtlicher Nachteil, dass gerade einige der besten Stellen zum Trennen nicht gefunden werden (nämlich Wortgrenzen). Um dieses Manko zu beheben, müsste man mindestens auf eine Datenbank von Wortstämmen zurückgreifen.
Ebenfalls um potenzielle Fehlerquellen zu dezimieren, werden die meisten Silben, die mit einem Vokal enden und eigentlich korrekt erkannt werden könnten, übergangen. Auch diese Einschränkung sollte in Kauf genommen werden, da sie tatsächlich keinen Nachteil darstellt – in den interessanten, überlangen Wörtern finden sich noch genügend Möglichkeiten für eine Trennung.
Nicht abgefangen werden kann der Fall, dass bei zusammengesetzten Wörtern eines mit einem Konsonanten endet und das folgende mit zwei Konsonanten beginnt. Hier schlägt die wichtigste Trennregel unweigerlich zu: “Bei mindestens einem Konsonanten zwischen zwei Vokalen wird vor dem letzten Konsonant getrennt.”
Hier werden noch einmal gezielt lange Wörter betrachtet. Diesmal mit praxistauglichen Parametern, abgesehen vom Trennzeichen.
<?php
ob_start (array (new Silbentrennung (12, 3, 4, '-'), 'run'));
?>mehrere
Unterprivilegierter
auseinanderzusetzen
Ehrentribüne
moskautreu
Widerstandsgruppe
selbstverständlich
Unterhaltungssoftware
Bildungsministerien
Nationalsozialismus
Geschwindigkeitsbegrenzer
Geschwindigkeitsüberschreitung
Kriegsgedenktag
Mehrspielernamen
Lichtspieltheater
Es folgt eine Anwendung, wie sie in der Praxis aussehen könnte. Die Klasse wird sinnvoll instanziiert und die Silbentrennung auf die gesamte Ausgabe angewandt:
<?php
ob_start (array (new Silbentrennung (14), 'run'));
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
<title>Silbentrennung</title>
<style type="text/css"><!--
p {
border: 1px solid red;
width: 10em;
}
--></style>
</head>
<body>
<p>
Der moskautreue tschetschenische Präsident Achmad Kadyrow ist tot: Attentäter hatten während der Feiern zum
Kriegsgedenktag mit einer Mine die voll besetzte Ehrentribüne des Stadions in Grosny gesprengt. Die Explosion
tötete mehrere Menschen und verletzte Dutzende. Russlands Präsident Putin kündigte Vergeltung an.
</p>
</body>
</html>
Abschließend noch eine kürzere, auf Geschwindigkeit optimierte Implementierung der Klasse:
<?php
/**
* class Silbentrennung
* Zum Erkennen von Silben und Trennen von Wörtern in deutschsprachigen Texten.
* Copyright (C) 2006 Dao Gottwald <dao at design-noir.de>
*
* Licensed under the terms of the GNU Lesser General Public License:
* http://www.opensource.org/licenses/lgpl-license.php
*
* Die Trennregeln wurden mithilfe folgender Seiten erstellt:
* http://www.ruediger-weingarten.de/Orthographie/Silbentrennung.htm
* http://www.ifi.unizh.ch/CL/volk/LexMorphVorl/Lexikon12.Gener.html
* http://www.schneid9.de/pdf/ling07.pdf
*
* @version 1.2.6_opt
*/
require_once 'Preprocess.php';
class Silbentrennung extends Preprocess {
private
$zeichen, $rZeichen, /* Trennzeichen */
$min_wortlaenge, /* minimale Länge zu trennender Wörter */
$min_silbenlaenge, /* minimale Länge einer Silbe */
$offset; /* Anzahl der Buchstaben, die am Wortanfang/-ende nicht abgetrennt werden sollen */
public function __construct ($min_wortlaenge = 16, $min_silbenlaenge = 3, $offset = 4, $zeichen = '­') {
$this->min_wortlaenge = (int) $min_wortlaenge;
$this->min_silbenlaenge = (int) $min_silbenlaenge;
$this->offset = (int) $offset;
$this->zeichen = (string) $zeichen;
$this->rZeichen = preg_quote ($this->zeichen, '~');
}
public function run ($text) {
if (is_array ($text)) {
$text = $text[0];
}
if (strpos ($text, '<') !== false && strpos ($text, '<') < strpos ($text, '>')) {
$this->text =& $text;
$this->_escape_init();
$this->_escape_comments_cdata();
$this->_escape_content ('head', 'pre', 'code', 'blockcode', 'textarea');
$text = '>'. $text. '<';
$text = preg_replace_callback ('~>[^<]+<~s', array ($this,'run'), $text);
$this->_escape_fin();
return substr ($text, 1, -1);
}
if ($this->min_wortlaenge > 1) {
$text = preg_replace_callback ('~[a-zßäÄüÜöÖ]{'.$this->min_wortlaenge.',}~i', array ($this,'_worttrenn'), $text);
} else {
$text = preg_replace_callback ('~[a-zßäÄüÜöÖ]+~i', array ($this,'_worttrenn'), $text);
}
return $text;
}
private function _worttrenn (array $wort) {
$wort = $wort[0];
$wort = preg_replace ('~ß(?![aeiouäÄüÜöÖy])|(?:durch|hinter|hinaus|miss|[üÜ]ber)|\B(?=durch|hinter|hinaus|miss|[üÜ]ber)|(?>\b)(?:a[nb](?![aeiouäÄüÜöÖy])|au[fs]|be|ent|emp|er|ge|[vz]er|fehl|um|unter|voll|wie?der|ex)|(?:au[fs]|be|ein|ent|emp|er|ge|[vz]er|fehl|um|unter|voll|wie?der|ex)(?![aeiouäÄüÜöÖy])|(?:igen?|lichen?|schafts?|[bcdfghklmnpqrßtvwxzs]ungs?|[hk]eits?)|\B(?=igen?|lichen?|schaft|[bcdfghklmnpqrßtvwxzs]ung|[hk]eit)|[aeiouäÄüÜöÖy](?:s?ch|s[tp]|[bcdfghklmnpqrßtvwxz]|s(?!ch)){1,3}?(?=(?:s?ch|s[tp]|[bcdfghklmnpqrßtvwxz]|s(?!ch))h?[aeiouäÄüÜöÖy])~i', '\\0'.$this->zeichen, $wort);
$wort = preg_replace ('~'.$this->rZeichen.'$~', '', $wort);
$wort = preg_replace ('~'.$this->rZeichen.'([^aeiouäÄüÜöÖy]+)$~i', '\\1', $wort);
if ($this->offset) {
$wort = preg_replace ('~^([a-zßäÄüÜöÖ]{1,'.$this->offset.'})'.$this->rZeichen.'~i', '\\1', $wort);
$wort = preg_replace ('~'.$this->rZeichen.'([a-zßäÄüÜöÖ]{1,'.$this->offset.'})$~i', '\\1', $wort);
}
if ($this->min_silbenlaenge) {
$wort = preg_replace ('~'.$this->rZeichen.'([a-zßäÄüÜöÖ]{1,'.$this->min_silbenlaenge.'})(?='.$this->rZeichen.')~i', '\\1', $wort);
}
return $wort;
}
}
?>
array| aus |private function _worttrenn (array $wort) {| entfernst.
$sb = new Silbentrennung(); echo $sb->run($titel);