Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: php-Skript per Gettext übersetzen

1 view
Skip to first unread message
Message has been deleted

Michael Fesser

unread,
Jan 27, 2010, 10:46:39 AM1/27/10
to
.oO(Chris Leick)

>Ich m�chte meine Website zweisprachig machen und dazu gettext verwenden:
>
> $lang=substr($_SERVER["HTTP_ACCEPT_LANGUAGE"],0,2);
> // echo "<br>".$lang."<br>";
> // $lang ist z.B. "de" oder "fr", je nach Browser-Spracheinstellung

Das korrekte Parsen des HTTP_ACCEPT_LANGUAGE-Headers ist nicht trivial.
Ein typischer Header sieht z.B. so aus:

de-DE,de;q=0.9,en;q=0.8

Aber die tats�chlich bevorzugte Sprache k�nnte bei Verwendung der q-
Parameter auch durchaus am Ende stehen! F�r korrekte Ergebnisse m�ssen
diese mit ausgewertet werden. Auch halte ich es zumindest f�r frag-
w�rdig, einfach nur blind die ersten beiden Zeichen auszuwerten.

> setlocale(LC_MESSAGES, $lang);
> bindtextdomain("progr", "./locale");
> bind_textdomain_codeset("progr", "UTF-8");
> textdomain("progr");
>
>Im Pfad .locale/ habe ich die Verzeichnisse "de/" und "fr/", die jeweils in
>LC_MESSAGES/ die �bersetzten und komplierten Dateien progr.mo enthalten.
>
>Leider werden auf der Website die englischen Originalstrings angezeigt.

Die entsprechenden Locales m�ssen auf dem Server auch installiert sein.
Bei "de" z.B. hab ich meine Zweifel, �blich sind "de_DE", "de_DE.utf8"
und dergleichen. Wenn das ein *nix-Server ist, pr�fe mal die Ausgabe von
"locale -a", welche Locales tats�chlich verf�gbar sind.

Abgesehen davon - ber�cksichtigst Du auch die M�glichkeit, da� ein
Besucher m�glicherweise unabh�ngig von den Browsereinstellungen eine
andere Sprache w�hlen m�chte? Diese M�glichkeit zu verbauen und stets
einzig auf den HTTP_ACCEPT_LANGUAGE-Header zu setzen ist problematisch.

Mein pers�nlicher Ansatz f�r Mehrsprachigkeit (bislang mangels Notwen-
digkeit in meinen Scripten nicht implementiert, nur vorbereitet und das
Prinzip mal kurz getestet) sieht ein Sprachk�rzel als Teil der URL vor,
entweder als Subdomain oder im Pfad. HTTP_ACCEPT_LANGUAGE w�rde nur auf
der Homepage f�r eine erste automatische Entscheidung herangezogen und
der Benutzer dann entsprechend weitergeleitet. F�r diesen Test brauche
ich nicht mal selbst am Header rumzufummeln, das kann der Apache bereits
von Haus aus weitaus besser auswerten (Content-Negotiation, MultiViews).

Micha

Message has been deleted

Stefan Froehlich

unread,
Jan 27, 2010, 1:34:16 PM1/27/10
to
On Wed, 27 Jan 2010 17:13:00 Chris Leick wrote:
> > Die entsprechenden Locales müssen auf dem Server auch installiert sein.

> Das heißt, der komplette Linux-Server muss komplett alle Sprachpakete für
> alle verwendeten Sprachen enthalten, obwohl ich nur ein oder zwei PHP-
> Skripte übersetzen möchte?

Ja. Im Prinzip reicht es aus, wenn das gewuenschte locale supported wird,
d.h. beispielsweise - je nach Distribution - in /usr/share/i18n/locales/
auftaucht. In der Praxis werden aber wohl die meisten Distributionen die
Sprachpakete fuer alle installierten Programme entsprechend nachziehen.
Wobei das bei weitem nicht so tragisch ist, wie es sich vielleicht fuer
Dich anhoert.

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - mit der geschmierten Idee gezierter Nachbarn.
(Sloganizer)

Message has been deleted

Michael Fesser

unread,
Jan 28, 2010, 9:24:02 AM1/28/10
to
.oO(Chris Leick)

>Michael Fesser wrote:
>>
>> Die entsprechenden Locales m�ssen auf dem Server auch installiert sein.
>

>Das hei�t, der komplette Linux-Server muss komplett alle Sprachpakete f�r
>alle verwendeten Sprachen enthalten, ...

Jein. Eigentlich nur das System selbst, tut also nicht weh. Die ganzen
installierten Anwendungen interessieren hier nicht, zumal die meisten
Programme ohnehin nur in einer oder maximal einer Handvoll Sprachen
daherkommen und deren Sprachdateien i.d.R. eh alle installiert werden,
auch wenn dem System das jeweilige Locale nicht bekannt sein sollte.

Mein /usr/share/locale-Verzeichnis ist jedenfalls gut gef�llt mit 112 MB
und zahlreichen Sprachen, die eigentlich gar nicht installiert sind. Nur
Klingonisch fehlt da noch ...

Gut, auf Debian g�be es localepurge, aber die paar MB tun auch nicht
wirklich weh.

>... obwohl ich nur ein oder zwei PHP-
>Skripte �bersetzen m�chte?

Ich hab hier auf meinem Debian-Server schon �fter einzelne fehlende
Locales einfach nachinstalliert bzw. das Locale-Paket neu konfiguriert
("dpkg-reconfigure locales"). Alles Ben�tigte ausw�hlen, mit Ok be-
st�tigen, dann r�delt er 'n bi�chen ("Generating locales") und fertig.

Alternativ geht's auch mit locale-gen und vorherigem Editieren der
locale.gen. Wie gesagt - Debian. Auf anderen Distris mags Unterschiede
geben.

>> Bei "de" z.B. hab ich meine Zweifel, �blich sind "de_DE", "de_DE.utf8"
>> und dergleichen. Wenn das ein *nix-Server ist, pr�fe mal die Ausgabe von
>> "locale -a", welche Locales tats�chlich verf�gbar sind.
>

>Es sind nur "de_*"-locales verf�gbar.

Ein paar en_* sollten schon auch noch da sein. M�sstest Dir nur
�berlegen, ob en_GB oder en_US. Oder beide ...

>> Abgesehen davon - ber�cksichtigst Du auch die M�glichkeit, da� ein
>> Besucher m�glicherweise unabh�ngig von den Browsereinstellungen eine
>> andere Sprache w�hlen m�chte? Diese M�glichkeit zu verbauen und stets
>> einzig auf den HTTP_ACCEPT_LANGUAGE-Header zu setzen ist problematisch.
>

>Ok. Aber selbst wenn ich den Anwender nun ausw�hlen lasse, welche Sprache er
>haben mag, so will ich nat�rlich nicht die komplette Seite redundant f�r
>jede Sprache pflegen.

Mu� ja nicht. Wenn die Seiten ohnehin per Script ausgegeben werden, dann
kann doch trotz unterschiedlicher URL dasselbe Script aufgerufen werden
und jeweils die gew�nschte Sprachversion ausspucken. Das Script mu� nur
irgendwie aus der URL ermitteln k�nnen, welche Sprache es sein soll.

Ganz primitiv kann man's so machen:

http://example.com/foo/bar.php?lang=de
http://example.com/foo/bar.php?lang=en

Gleiches Script, nur anderer Sprachparameter. Allerdings w�rden in
meinen Scripten die URLs etwas angepa�t, z.B. so:

http://example.com/de/foo/bar
http://example.com/en/foo/bar

Oder halt per Subdomain, aber intern liefe alles genauso ab wie oben
mittels 'lang'-Parameter.

mod_rewrite kann hierbei sehr hilfreich sein, um die "h�bscheren" URLs
in die erste Variante mit Parameter zu �berf�hren. Aber da gibt es noch
mehr M�glichkeiten, z.B. k�nnte auf dem Server /en nur ein symbolischer
Link auf /de sein und das Script sich die angeforderte Sprache einfach
aus PHP_SELF o.�. ziehen. Auch verschieden Subdomains k�nnten auf das-
selbe Verzeichnis verweisen, die Sprachwahl steckt dann im HTTP_HOST.

M�glichkeiten ohne Redundanz gibt's also einige. Und betreibt man noch
etwas mehr Script-Aufwand, dann sind sogar komplett sprachabh�ngige URLs
m�glich:

http://example.com/de/produkte/musik
http://example.com/en/products/music

Aber das ist ein Kapitel f�r sich.

HTH
Micha

Message has been deleted

Werner Flamme

unread,
Jan 29, 2010, 6:27:21 AM1/29/10
to
Chris Leick [29.01.2010 12:19]:

> Michael Fesser wrote:
>
>> Ganz primitiv kann man's so machen:
>>
>> http://example.com/foo/bar.php?lang=de
>> http://example.com/foo/bar.php?lang=en
>
> Und dann innerhalb von bar.php
>
> if ($lang=="de") { echo "deutsch"; }
> elseif ($lang=="fr" { echo "francais"; }
> elseif ...

Oder
$spruch['txt1']['de'] = 'deutsch';
$spruch['txt1']['fr'] = 'français';

Ggf. die Texte nach Sprache in unterschiedliche .php-Dateien schreiben
und abhängig von der Sprache includen.

Viele Wege führen nach Rom.

>
> Das ist viel Mehrarbeit. Vor allem muss ich dann etwas programmieren, was es
> schon gibt (Gettext).

Nur erhältst Du dann etwas, was auch - im Gegensatz zu Deinem Gettext -
auch funktioniert. Ist vielleicht die Arbeit wert.

>
>> Gleiches Script, nur anderer Sprachparameter. Allerdings würden in
>> meinen Scripten die URLs etwas angepaßt, z.B. so:
>>
>> http://example.com/de/foo/bar
>> http://example.com/en/foo/bar
>
> Dann habe ich wieder Doubletten der Skripte, und muss bei der Änderung eines
> Skriptes alle Skripte ändern, auch wenn die Änderung gar keine
> sprachspezifische Ausgabe hat.

Kwarg. Du kannst den Webserver durchaus dazu überreden, eine beliebige
URL an ein beliebiges Script durchzureichen. Rewrite Rules, virtuelle
Webseiten habe ich da als Stichwörter in Erinnerung.

HTH
Werner

Message has been deleted

Stefan Froehlich

unread,
Jan 29, 2010, 11:42:13 AM1/29/10
to
On Fri, 29 Jan 2010 12:19:20 Chris Leick wrote:
> Ich habe dies nun mal zum Testen getan und fr_FR installiert. Das Problem
> löst es nicht. Die Sprachdateien werden nicht berücksichtigt.

Dann hat's noch irgendwo irgendetwas.

> Selbst wenn ich die Sprache fix reinschreibe - das Problem ist, dass die
> übersetzten Strings einfach nicht von Gettext genommen werden.
> Möglicherweise sucht Gettext an der falschen Stelle. Kann man irgendwie
> herausfinden, wo es die Übersetzung sucht?

Es ist jetzt schon einige Zeit her, dass ich mich theoretisch mit der
Materie auseinandergesetzt habe - seitdem funktioniert einfach alles auf
Knopfdruck. Es kann daher gut sein, dass nicht alles vom folgenden
notwendig ist.

Sprachumschaltung passiert hier so (teilweise manuell vereinfacht,
Tippfehler sind daher moeglich):

| $locale = 'de_DE.UTF-8';
| putenv($locale);
| setlocale(LC_COLLATE, $locale);
| setlocale(LC_CTYPE, $locale);
| setlocale(LC_MESSAGES, $locale); # das ist fuer gettext relevant
| setlocale(LC_TIME, $locale);
| setlocale(LC_NUMERIC, '0');
|
| bindtextdomain('messages', $localedir);
| textdomain('messages');

Die beiden letzten Befehle sind wichtig, damit gettext die richtige
Uebersetzungsdatei findet, das locale ist (klarerweise) wichtig, um die
Sprache auszuwaehlen.

Wenn Du Herr auf Deinem Server bist, kannst Du auch einfach einmal
strace(1) an den passenden Prozess attachen, um zu sehen, nach welchen
Dateien ueberhaupt gesucht wird. Das ist manchmal sehr erhellend.

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - waschen!? Aber krachen ist unglaublicher.
(Sloganizer)

Michael Fesser

unread,
Jan 29, 2010, 8:08:35 PM1/29/10
to
(mit leichter Versp�tung ... hatte Netzprobleme ...)

.oO(Chris Leick)

>Stefan Froehlich wrote:
>
>> On Wed, 27 Jan 2010 17:13:00 Chris Leick wrote:

>>> > Die entsprechenden Locales m�ssen auf dem Server auch installiert sein.
>>
>>> Das hei�t, der komplette Linux-Server muss komplett alle Sprachpakete f�r


>>> alle verwendeten Sprachen enthalten, obwohl ich nur ein oder zwei PHP-

>>> Skripte �bersetzen m�chte?


>>
>> Ja. Im Prinzip reicht es aus, wenn das gewuenschte locale supported wird,
>> d.h. beispielsweise - je nach Distribution - in /usr/share/i18n/locales/
>> auftaucht. In der Praxis werden aber wohl die meisten Distributionen die
>> Sprachpakete fuer alle installierten Programme entsprechend nachziehen.
>> Wobei das bei weitem nicht so tragisch ist, wie es sich vielleicht fuer
>> Dich anhoert.
>

>Doch. Auf meinem Webserver sind sehr viele Programme und da m�chte ich nicht
>mit Kanonen auf Spatzen schie�en und f�r alle die locales installieren.

Bei mehrsprachigen Applikationen, die von Gettext Gebrauch machen, sind
die i.d.R. eh schon alle da. Schau einfach mal in /usr/share/locales
oder wie auch immer der Pfad bei Deiner Distri hei�t. Da liegt �blicher-
weise eine Menge Kram rum, z.T. auch Sprachen, von denen man nicht mal
den Namen kennt.

>Gibt es eine brauchbare Alternative zu Gettext?

Gettext ist schon recht brauchbar und elegant (IMHO).

Kleine Stolperfalle kann z.B. UTF-8 bzw. Unicode allgemein sein, aber
irgendwie kriegt man das auch alles hin (ich brauchte damals irgendeinen
speziellen Parameter f�r's Auslesen der Strings aus dem Quelltext IIRC).

>Falls nicht, schreibe ich
>mir eine kleine Funktion, die die Strings anhand eines Indexes aus einer DB
>ausliest.

Gettext hat den Vorteil, da� es bereits zahlreiche Tools mitbringt zum
Auslesen der zu �bersetzenden Strings aus den Quellen und deren weiterer
Verarbeitung bis hin zur fertigen Sprachdatei.

Micha

Michael Fesser

unread,
Jan 29, 2010, 8:27:10 PM1/29/10
to
.oO(Chris Leick)

>Michael Fesser wrote:
>>
>> Ich hab hier auf meinem Debian-Server schon �fter einzelne fehlende
>> Locales einfach nachinstalliert bzw. das Locale-Paket neu konfiguriert
>> ("dpkg-reconfigure locales"). Alles Ben�tigte ausw�hlen, mit Ok be-
>> st�tigen, dann r�delt er 'n bi�chen ("Generating locales") und fertig.
>

>Ich habe dies nun mal zum Testen getan und fr_FR installiert. Das Problem

>l�st es nicht. Die Sprachdateien werden nicht ber�cksichtigt.

In PHP dann auch 'fr_FR' und nicht nur 'fr' ausgew�hlt? Die Schreibweise
ist wichtig. setlocale() erlaubt aber auch Alternativen. Ggf. R�ckgabe-
wert pr�fen.

>Und dann innerhalb von bar.php
>
> if ($lang=="de") { echo "deutsch"; }
> elseif ($lang=="fr" { echo "francais"; }
> elseif ...
>

>Das ist viel Mehrarbeit. Vor allem muss ich dann etwas programmieren, was es
>schon gibt (Gettext).

So war das nicht gemeint. Ich greif mir den Parameter und leite den an
setlocale() weiter, ggf. mit geringf�giger Anpassung (z.B. de => de_DE).
Mein Beispiel war schon auf Gettext und nicht auf was eigenes bezogen.

Ganz extrem vereinfacht also:

setlocale(LC_MESSAGES, $_GET['lang']);

Das ist so nat�rlich nicht praxistauglich, zeigt aber die Idee.

>> Gleiches Script, nur anderer Sprachparameter. Allerdings w�rden in
>> meinen Scripten die URLs etwas angepa�t, z.B. so:
>>
>> http://example.com/de/foo/bar
>> http://example.com/en/foo/bar
>

>Dann habe ich wieder Doubletten der Skripte, und muss bei der �nderung eines
>Skriptes alle Skripte �ndern, auch wenn die �nderung gar keine
>sprachspezifische Ausgabe hat.

Nee, keine Doubletten. Ich hab doch verschiedene M�glichkeiten gepostet,
wie man sowas realisieren k�nnte, n�mlich:

>> mod_rewrite kann hierbei sehr hilfreich sein, um die "h�bscheren" URLs
>> in die erste Variante mit Parameter zu �berf�hren. Aber da gibt es noch
>> mehr M�glichkeiten, z.B. k�nnte auf dem Server /en nur ein symbolischer
>> Link auf /de sein und das Script sich die angeforderte Sprache einfach
>> aus PHP_SELF o.�. ziehen. Auch verschieden Subdomains k�nnten auf das-
>> selbe Verzeichnis verweisen, die Sprachwahl steckt dann im HTTP_HOST.

Micha

Message has been deleted
Message has been deleted

Stefan Froehlich

unread,
Feb 2, 2010, 8:34:41 AM2/2/10
to
On Tue, 02 Feb 2010 10:47:11 Chris Leick wrote:
> > Wenn Du Herr auf Deinem Server bist, kannst Du auch einfach einmal
> > strace(1) an den passenden Prozess attachen, um zu sehen, nach welchen
> > Dateien ueberhaupt gesucht wird. Das ist manchmal sehr erhellend.

> Herr auf dem Server bin ich, allerdings habe ich keine Ahnung, wie ich
> den Prozess finden kann. Apache ruft PHP auf und das wiederum Gettext.
> Richtig?

Genau. Am einfachsten ist es, die Konfiguration des Apache so anzupassen,
dass zu Testzwecken nur eine Instanz davon vorhanden ist (StartServers,
MinSpareServers, MaxSpareServers) und sich danach mit "strace -f -p PID"
auf die entsprechende PID zu haengen.

Ein einzelner Seitenaufruf hat bei mir gerade satte 1,5 MB Ausgabe erzeugt,
aber die passende Stelle ist ueber den Verzeichnisnamen relativ leicht zu
finden. Hier sieht das so aus:

| 25081 open("[application path]/locale/de_DE.UTF-8/LC_MESSAGES/messages.mo", O_RDONLY) = 19

Aehnliches leistet auch "ltrace -f -S -p PID".

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - buchen!? Aber knutschen ist wundervoller.
(Sloganizer)

Message has been deleted

Stefan Froehlich

unread,
Feb 2, 2010, 2:10:55 PM2/2/10
to
On Tue, 02 Feb 2010 16:06:16 Chris Leick wrote:
> > | 25081 open("[application path]/locale/de_DE.UTF-8/LC_MESSAGES/messages.mo", O_RDONLY) = 19

> Leider habe ich in dem Trace keine entsprechende Zeile entdeckt. Das
> einzige, was ich endecken konnte war folgendes:

> lstat("/var/www/progr/locale", {st_mode=S_IFDIR|0755, st_size=4096, ...})

So weit, so gut - den gibt es bei mir auch und das gehoert sich ja auch
so. Existiert das Verzeichnis denn und ist fuer den Prozess lesbar?

> Den Aufruf der mo-Datei konnte ich nirgendwo im Trace entdecken.

Trivialer Ansatz waere: weil lstat nicht das gewuenschte Ergebnis liefert.
Andernfalls gehen mir langsam die Ideen aus. Kannst Du das Problem denn
irgendwie auf ein Trivialbeispiel mit 10 Zeilen reduzieren?

Interessant ist, dass zwischen den beiden Aufrufen einiges an Abstand
liegt. lstat() scheint direkt beim Aufruf von bindtextdomain() angesprungen
zu werden, waehrend das Lesen der Sprachdateien erst spaeter, bei Bedarf
erfolgt.

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - die edelste Potenz von banal!
(Sloganizer)

Message has been deleted
0 new messages