Der Übersetzungscomputer Babel Fish ist zwar kein Sprachgenie, hilft aber den Inhalt fremdsprachiger Dateien zu verstehen. Das heute vorgestellte Kommandozeilentool dockt an ihn an.
Wer auf altavista.com
auf den Translate-Knopf drückt, erhält das
Web-Formular zu Babel Fish, einem Programm, das ein halbes Dutzend
Sprachen versteht und ganze Sätze übersetzen kann. Nun steckt die
maschinelle Übersetzungskunst seit Jahrzehnten in den Kinderschuhen und
es ist noch kein Durchbruch in Sicht, also ist das Ganze nicht ganz
ernstzunehmen. Dennoch: In Sprachen, in denen man nur ``Guten Tag'' und
``Ein Bier bitte'' sagen kann, kann der Babel Fish helfen.
Das Webformular auf babel.altavista.com
versteht in eine Eingabebox
getippten Text sowie Links auf zu übersetzende Webdokumente. Statt jedes
Mal den Browser hochzufahren und den zu übersetzenden Text als URL oder
mittels Cut-and-Paste in das Eingabefeld zu transferieren geht es heute
darum, mittels eines Perl Skripts über das Internet bei Babel Fish
anzudocken, den Inhalt lokaler Dateien zu übersetzen und anschließend
auszugeben.
Das vorgestellte Perlskript trans
tut genau dies. Wie fast immer
stellt sich nach kurzem Nachforschen auf dem CPAN heraus, dass
es dort schon ein passendes Perl-Modul gibt, in diesem Fall ist es
WWW::Babelfish
von Dan Urist, das die Arbeit an trans
auf ein Minimum reduziert.
Das Modul WWW::Babelfish
arbeitet mit einem Babelfish-Objekt, dessen
translate()
-Methode neben einigen Übersetzungsparametern auch
den zu übersetzenden Text als String entgegennimmt.
Der faule Babel Fish auf dem Web
schneidet Texte rigoros nach 1000 Zeichen ab,
WWW::Babelfish
umgeht dies aber geschickt, indem es Texte
in Teile mit weniger als 1000 Buchstaben zerlegt und sie
einzeln an Babel Fish schickt.
Babelfish unterstützt derzeit beidseitige Konvertierungen zwischen den Sprachen Deutsch-Englisch und Deutsch-Französisch. Im Zusammenhang mit Englisch arbeitet er außerdem mit Italienisch, Portugiesisch, Spanisch und Russisch.
Ein Aufruf von trans
ganz ohne Parameter zeigt an, welche
Parameter es normalerweise erwartet:
usage: trans \ [efgpirs]2[efgpirs] file ... e: English f: French g: German i: Italian p: Portuguese r: Russian s: Spanish
Damit das vorgestellte Skript trans
auch weiss, aus welcher und in
welche Sprache es übersetzen soll, gibt der erste Kommandozeilenparameter die
Richtung an: g2e
(German-English) ist Deutsch-Englisch,
f2g
(French-German) ist Französisch-Deutsch.
Der zu übersetzende Text steht in einer oder mehreren Dateien, deren
Namen als Parameter nachfolgen. Der folgende Aufruf übersetzt
zum Beispiel den französischen
Inhalt der Datei /tmp/french.txt
ins Deutsche und
gibt das Ergebnis auf der Standardausgabe aus:
$ trans f2d /tmp/french.txt
In alter Unix-Tradition geht es auch,
den Dateinamen wegzulassen, dann nimmt trans
die Daten aus
der Standardeingabe entgegen:
$ echo "Der Ball ist rund" | \ trans g2e The ball is round
Das Skript in Listing trans
zieht in Zeile 3 das Modul
WWW::Babelfish
herein, das vorher entsprechend den Anweisungen
im Abschnitt Installation vom CPAN geholt und installiert werden
muss.
01 #!/usr/bin/perl 02 03 use WWW::Babelfish; 04 05 # Vorgegaukelter User-Agent 06 use constant AGENT => 07 'Mozilla/4.73 [en] (X11; U; Linux)'; 08 09 # Unterstützte Sprachen 10 my @languages = qw(English French German Italian 11 Portuguese Russian Spanish); 12 13 # Hash aufbauen, der Sprachkürzel der 14 # Sprache zuordnet (g=>German, e=>English, ..) 15 foreach my $language (@languages) { 16 my $initial = substr($language, 0, 1); 17 $i2full{lc($initial)} = $language; 18 } 19 20 # Alle Kürzel in einem String (efgpirs) 21 my $chars = join '', keys %i2full; 22 23 # Umwandlungsrichtung von der 24 # Kommandozeile (g2e, e2f, ...) 25 my $way = shift; 26 27 usage() unless defined $way; 28 29 usage("Scheme $way not supported") unless 30 ($from, $to) = $way =~ /^([$chars])2([$chars])$/; 31 32 # Zu übersetzenden Text einlesen 33 my $data = join '', <>; 34 35 # Verbindung zu Babelfish aufnehmen 36 my $babel = WWW::Babelfish->new(agent => AGENT); 37 usage("Cannot connect to Babelfish") unless 38 defined $babel; 39 40 # Übersetzen lassen 41 my $transtext = $babel->translate( 42 source => $i2full{$from}, 43 destination => $i2full{$to}, 44 text => $data 45 ); 46 47 die("Error: " . $babel->error) unless 48 defined($transtext); 49 50 print $transtext, "\n"; 51 52 ################################################## 53 sub usage { 54 ################################################## 55 my $msg = shift; 56 my $prog = $0; 57 58 print "usage: $prog ", 59 "[${chars}]2[${chars}] file ...\n"; 60 foreach $c (sort split //, $chars) { 61 print " $c: $i2full{$c}\n"; 62 } 63 exit(1); 64 }
Die unterstützten Sprachen stehen in den Zeilen 10 und 11 im
Array @languages
. Der praktische Operator qw
zur Listendefinition
trennt den eingschlossenen String an den Wortgrenzen
(Leerzeichen und Umbrüche) und liefert eine Liste zurück, die jedes
Wort als Element enthält.
Um später elegant über die Kürzel (z.B. g
) auf die vollständigen
Sprachnamen (z.B. German
) zugreifen zu können, bauen die Zeilen
15 bis 18 einen Hash %i2full
auf, der die Kürzel als Schlüssel
und die Sprachnamen als Werte enthält. Hierzu greift sich die
substr
-Funktion jeweils das erste Zeichen des Sprachnamens und die
lc
-Funktion konvertiert es in einen Kleinbuchstaben.
Zeile 21 baut für später alle verfügbaren Kürzel zu einem String
$chars
zusammen, der mit my
auf das gegenwärtige Package beschränkt
wird, aber auch in der Unterfunktion usage
zur Verfügung steht.
$way
holt sich in Zeile 25 mit shift
den ersten
Kommandozeilenparameter, der
die Richtung der Übersetzung angibt. Falls keiner vorliegt, hat der
Benutzer offensichtlich die Syntax von trans
nicht begriffen und
die usage
-Funktion gibt eine Bedienungsanleitung aus und bricht das
Programm ab.
Der reguläre Ausdruck in Zeile 30 /^([$chars])2([$chars])$/;
interpoliert zu /^([efgpirs])2([efgpirs])$/;
und
prüft, ob der Richtungsanzeiger dem Format x2y
entspricht, wobei
x
und y
einen der Werte
e
,
f
,
g
,
p
,
i
,
r
oder
s
annehmen. Da der Ausdruck im Listen-Kontext steht und auf
der linken Seite eine Liste mit den Elementen $from
und $to
steht, liegen dort bei einem erfolgreichen Match anschließend die
in den Klammern des regulären Ausdrucks eingefangenen Werte. Bei
g2e
wäre dies g
in $from
und e
in $to
.
Schlägt der Match hingegen fehl, ist das Resultat eine leere Liste, die
im boolschen Kontext von unless
als falsch interpretiert wird.
Zeile 33 liest den zu übersetzenden Text ein -- entweder von Dateien,
deren Namen auf der Kommandozeile stehen oder von der Standardeingabe,
falls keine Dateinamen vorliegen. Die join
-Funktion verbindet die
Zeilen zu einem langen String, unter Beibehaltung der Zeilenumbrüche,
versteht sich.
Zeile 36 erzeugt ein neues WWW:Babelfish
-Objekt und weist es mit
dem agent
-Parameterpaar an, sich als Netscape-Browser auszugeben. Hierzu
dient die in Zeile 6 mit Perls use constant
-Pragma angegebene Konstante.
So definiert man Funktionen, die Ausssehen wie Makros und von Perl so
optimiert werden, dass sie konstanten Skalaren in nichts nachstehen.
Laut Dokumentation liefert der WWW:Babelfish
-Konstruktor den
Wert undef
zurück, falls etwas schief ging, was Zeile 37 zum
Abbruch nutzen würde.
Zeile 41 schließlich sendet alle Daten an den Babel Fish auf dem
Web. Die translate
-Methode nimmt die vollen
(englischen)
Namen für Ausgangs- und Zielsprache (Parameternamen
source
und destination
)
entgegen, sowie den zu übersetzenden Text als Stringwert für den Parameter
text
.
Das Objekt
schickt die Daten an das Formular,
interpretiert das zurückkommende HTML und extrahiert daraus wieder
das Ergebnis -- alles ohne unser Zutun. In $transtext
liegt anschließend
das Ergebnis. Ein Wert von undef
deutet einen Fehler an, den Zeile
47 abfängt und mittels der error
-Methode des WWW::Babelfish
-Objekts
als Meldung anzeigt.
Zeile 50 gibt das Ergebnis schließlich auf der Standardausgabe
aus.
Damit neue Benutzer die Bedienung von trans
leicht erlernen, gibt
die ab Zeile 53 definierte usage
-Funktion eine ihr übergebene
Nachricht und anschließend eine kurze Bedienungsanleitung aus.
Anschließend bricht sie mit exit(1)
das Programm ab.
Das oben schon einmal abgedruckte Kurz-Manual generiert usage
dynamisch aus dem Inhalt der Variablen $chars
und %short
,
die erlaubte Kürzel und eine Kürzel-zu-Sprachname-Tabelle enthalten.
Die Perlfunktion split
in Zeile 60
spaltet mit //
als Pattern einen String
in seine Einzelzeichen auf und liefert einen Array zurück, der jedes
Zeichen als Element enthält. Die sort
-Funktion bringt den
Array mit Kleinbuchstaben in alphabetische Reihenfolge und
der Hash %short
liefert die dazugehörigen Sprachnamen.
Die Reihe der unterstützten Sprachen könnte man übrigens auch
mit der Methode languages()
des WWW::Babelfish
-Objektes
abfragen, die einen Array mit allen aktuellen Sprachen zurückliefert.
trans tut dies nicht, da die Auswahl relativ statisch ist.
WWW::Babelfish
gibt's auf dem CPAN unter
WWW-Babelfish-0.09.tar.gz
und setzt das libwww
-Bundle sowie das Modul IO::String
voraus.
Installiert wird, wie immer mit der CPAN-Shell und
perl -MCPAN -eshell cpan> install libwww cpan> install IO::String cpan> install WWW::Babelfish
Ein paar Beispiele, um die Funktion von Babelfish zu testen: Hierzu
rufen wir trans
nur mit dem Sprachrichtungsparameter auf,
geben den zu übersetzenden Text anschließend über die Standardeingabe
ein und schließen mit ^D
(Control+D) ab:
$ trans g2e Einen Radi und eine Mass Bier, aber schnell! ^D
A Radi and measure beer, but fast!
Na ja, nicht schlecht, aber halt nicht perfekt. Auch von Englisch nach Französisch gibt's eine Schnittstelle:
$ trans e2f waiter, where the hell are my frog legs? ^D
le serveur, oł l'enfer sont mes cuisses de grenouille?
Oder von Englisch nach Deutsch:
$ trans e2g waiter, this american beer tastes terrible! ^D
Kellner, dieses Amerikanerbier schmeckt schrecklich!
Na bitte, sogar Humor hat das Teil. Viel Spaß damit!
Michael Schilliarbeitet als Software-Engineer bei Yahoo! in Sunnyvale, Kalifornien. Er hat "Goto Perl 5" (deutsch) und "Perl Power" (englisch) für Addison-Wesley geschrieben und ist unter mschilli@perlmeister.com zu erreichen. Seine Homepage: http://perlmeister.com. |