![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||||||||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
|||||||
![]() |
|||||||
![]() |
|
||||||
![]() |
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 Perl-Skript 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.
Listing 1: trans |
01 #!/usr/bin/perl -w 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 } |
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 weiß, 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.
Die unterstützten Sprachen stehen in den Zeilen 10 und 11 im Array @languages. Der praktische Operator qw zur Listendefinition trennt den eingeschlossenen 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 aussehen 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 %i2full 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!
INFOS |
[1]Zum Thema Babelfisch: Douglas Adams, Per Anhalter durch die Galaxis, Heyne, ISBN 3453146972 |
Der Autor |
Michael Schilli arbeitet als Web-Engineer für AOL/Netscape in Mountain View, Kalifornien. Er ist Autor des 1998 bei Addison-Wesley erschienenen (und 1999 für den englischsprachigen Markt als "Perl Power" herausgekommenen) Buches "GoTo Perl 5". zu erreichen. |
Copyright © 2000 Linux New Media AG