Also zu Anfang. Es gibt mehr als eine Implementation von Gettext für Perl. Das wird dir noch häufiger begegnen, dass es mehrere Module gibt die alle ungefähr das selbe machen.
Neben
Gettext gibt es noch
Locale::gettext,
Locale::Messages,
Locale::Simple und noch einige mehr.
Neben dem eigentlichen Programmieren ist es auch wichtig zu wissen welche Module man am besten nutzt.
Aber zurück zu gettext.
Programme die gettext nutzen greifen auf die Umgebungsvariablen zurück um festzustellen was die Aktuelle Ausgabesprache ist.
So ist in
LANGUAGE definiert welche Sprachen generell verstanden werden.
LC_MESSAGE definiert ein welcher Sprache Texte ausgeben werden sollen. Daneben gibt es noch
LC_CTYPE und
LANG. Will man alle diese Werte auf einmal beeinflussen gibt es noch
LC_ALL
Anzumerken ist das
LC_ALL=C sämtliche Übersetzungen unterdrückt und alle Texte so ausgeben werden wie sie im Code stehen. Das gilt für alle Programme. (zumindest wenn das System POSIX Konform ist) Schreibe
LC_ALL=C programm und du bekommst die Ausgaben wie sie die Programmierer verfasst haben.
Will man unter Debian (und auch Ubuntu) die aktiven Sprachen einstellen so kann man als root
dpkg-reconfigure locales eingeben und die Sprachen einstellen, die man verwenden möchte. Danach ist ein Neustart angebracht, damit die Einstellungen in allen Ecken des Systems ankommen.
Um zu schauen welche locales zur Verfügung stehen kann man
locale -a ausführen damit werden alle verfügbaren gelistet.
Nun ein kleines Script:
test.pl:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
use strict;
use warnings;
use Locale::gettext;
use POSIX;
use FindBin '$Bin';
setlocale(LC_MESSAGES,'C') or die( "Can't set LC_MESSAGES" );
bindtextdomain("my_test","$Bin/translate");
textdomain("my_test");
print gettext("Yo man")."\n";
for(0..9)
{
printf gettext('ln: %02u')."\n",$_;
}
Das soll ein kleines Beispiel sein.
Wie zu sehen sollte im Verzeichnis des Scripts ein Ordner "translate" existieren.
Nun generieren wir aus dem Script ein Template für die Übersetzungen:
xgettext ./test.pl -d my_test -p translate Das Erzeugt im Ordner 'translate' eine Datei "my_test.po"
Grob gesagt sucht
xgettext nach
gettext(...) und nimmt den String daraus um damit das Template zu erzeugen. Darum funktionieren so Konstrukte wie
gettext( "WERT=$wert\n" ) nicht und sollten besser so geschrieben werden:
sprintf( gettext( "WERT=%s\n" ), $wert )
Die Sollte ungefähr so aussehen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-15 23:27+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: test.pl:13
msgid "Yo man"
msgstr ""
#: test.pl:16
#, perl-format
msgid "ln: %02u"
msgstr ""
Das ist das Template mit dem die einzelnen Übersetzungen erzeugt werden.
Im Verzeichnis 'translate' führt man aus:
msginit -l de -i my_test.po Damit wird eine Datei 'de.po' erzeugt. Darin macht man die Übersetzungen. Ungefähr so:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# German translations for PACKAGE package.
# Copyright (C) 2012 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# ToPeG <topeg@test.local>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-15 23:27+0200\n"
"PO-Revision-Date: 2012-06-15 23:31+0200\n"
"Last-Translator: ToPeG <topeg@test.local>\n"
"Language-Team: German\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: test.pl:13
msgid "Yo man"
msgstr "Hallo"
#: test.pl:16
#, perl-format
msgid "ln: %02u"
msgstr "Zeile %02u"
Wenn man Umlaute benutzt muss man das
charset=ASCII Ändern. Speichert man die Datei Als UTF-8 (was zu empfehlen ist) dann setzt man
charset=UTF-8 Speichert man in einer anderen Kodierung muss man das dort vermerken. Macht man da einen Fehler nörgelt gettext herum das bestimmte Zeichen nicht zur Kodierung passen, oder die Ausgabe hat seltsame Zeichen.
Das macht man nun für jede Sprache die man haben will (z.B englisch).
Der nächste Schritt ist es die Dateien zu kompilieren und an die richtige Stelle zu packen. Dazu erzeugt man zu jeder Sprache einen Ordner diesen Namens der einen Ordner 'LC_MESSAGES' enthält. Also für Deutsch:
translate/de/LC_MESSAGES/ Nun wird das ganze kompiliert:
msgfmt -o de/LC_MESSAGES/my_test.mo ./de.po Nun kann das Script auf die Übersetzung zugreifen. Dieses Prozedere wiederholst du für jede der Übersetzungen.
Mit
./test.pl bekommt man :
Yo man
ln: 00
ln: 01
ln: 02
ln: 03
ln: 04
ln: 05
ln: 06
ln: 07
ln: 08
ln: 09
Was zu erwarten ist da eine Übersetzung unterdrückt ist.
Kommentiert man
#setlocale(LC_MESSAGES,'C') aus bekommt man die Ausgabe:
Hallo
Zeile 00
Zeile 01
Zeile 02
Zeile 03
Zeile 04
Zeile 05
Zeile 06
Zeile 07
Zeile 08
Zeile 09
Wenn du Vorher für alle gewünschten Übersetzungen die locales ausgewählt hast, kannst du die Sprache ändern indem du die Zeile
setlocale(LC_MESSAGES,'...') änderst.
Die Ordnerstruktur ist bei mir nun:
test.pl
translate/my_test.po
translate/de.po
translate/en.po
translate/de/LC_MESSAGES/my_test.mo
translate/en/LC_MESSAGES/my_test.mo
Das "gettext"-Packet bietet noch weitere Programme um z.B Änderungen im Script zu erkennen und in den Übersetzungen zu ergänzen. Das solltest du dir aber selber durch lesen.
Ich hoffe das hilft dir weiter.