Einführung
Zend_Locale ist die Antwort des Frameworks auf die Frage "Wie kann
die selbe Anwendung auf der ganzen Welt verwendet werden?". Die meisten Leute werden sagen
"Das ist einfach. Lasst uns alle Ausgaben in die unterschiedlichsten Sprachen übersetzen".
Aber, eine einfache Übersetzungstabelle die Phrasen von einer Sprache in die andere
übersetzt ist nicht genug. Verschiedene Regionen haben auch unterschiedliche Regeln für
Vornamen, Nachnamen, Titel, Format von Nummern, Daten, Zeiten, Währungen usw.
Was wir benötigen ist Lokalisierung
und die vergleichbare Internationalisierung. Beide werden oft
abgekürzt zu L10n und I18n. Internationalisierung bezeichnet mehr
die Benutzung von Systemen für die spezielle Benutzung durch eindeutige Gruppen wie zum
Beispiel Sprachübersetzung, Unterstützung von lokalen Konventionen für Plurale, Daten,
Zeiten, Währungen, Namen, Symbolen, Sortierungen, Reihungen und viele mehr.
L10n und I18n sind einander sehr ähnlich. Zend Framework bietet
Unterstützung für diese Konventionen durch eine Kombination von Komponenten wie
Zend_Locale, Zend_Date,
Zend_Measure, Zend_Translate,
Zend_Currency und Zend_TimeSync.
Zend_Locale und setLocale()
Die Dokumentation von PHP sagt das
setlocale() nicht Threadsicher ist weil es pro Prozess
behandelt wird und nicht pro Thread. Das bedeutet das man in multithreaded Umgebungen
das Problem bekommen kann, das sich das Gebietsschema (Locale) ändert wärend das Skript
diese Änderung nie selbst durchgeführt hat. Deswegen kann es zu unerwarteten Ergebnissen
kommen wenn man setLocale() in seinen Skripts verwendet.
Wenn Zend_Locale verwendet wird hat man diese Einschränkungen
nicht, da Zend_Locale weder von PHP's
setlocale() abhängig ist, noch irgendwie mit Ihr gekoppelt ist.
Was ist Lokalisierung
Lokalisierung bedeutet das eine Anwendung (oder Homepage) von verschiedenen Benutzer
verwendet werden kann die unterschiedliche Sprachen sprechen. Aber wie bereits
angedeutet heißt Lokalisierung mehr als nur die Übersetzung von Zeichenketten. Es
beinhaltet
Zend_Locale - Unterstützung für Gebietsschemata welche
Unterstützung für Lokalisierungen von anderen Zend Framework Komponenten
bieten.
Zend_Translate - Übersetzung von Zeichenketten.
Zend_Date - Lokalisierung von Daten und Zeiten.
Zend_Calendar - Lokalisierung von Kalendern
(Unterstützung für nicht Gregorianische Kalendersysteme)
Zend_Currency - Lokalisierung von Währungen.
Zend_Locale_Format - Erkennen und erzeugen von
lokalisierten Zahlen.
Zend_Locale_Data - Empfangen von lokalisierten Standard
Übersetzungen für Länder, Sprachen und mehr aus der CLDR.
TODO - Lokalisierung von Sammlungen
Was ist ein Gebietsschema?
Jeder Computer benutzt Gebietsschemata, selbst wenn Sie es nicht wissen. Anwendungen
welche keine Unterstützung für Lokalisierung bieten, unterstützen zumindest genau ein
Gebietsschema (das Gebietsschema des Authors). Wenn eine Klasse oder Funktion
Lokalisierung verwendet sagen wir sie ist Lokalisierbar. Aber wie weiß der
Code welches Gebietsschema ein Benutzer erwartet ?
Eine Gebietsschema Zeichenkette oder Objekt welches ein unterstütztes Gebietsschema
identifiziert, gibt Zend_Locale und dessen Unterklassen Zugriff
auf Informationen über die Sprache und Region welche der Benutzer erwartet.
Formatierungen, Normalisierungen und Konvertierungen werden anhand dieser Informationen
durchgeführt.
Wodurch werden Gebietsschemata repräsentiert?
Eine Gebietsschema Zeichenkette besteht aus Informationen über die Sprache des Benutzers
und die bevorzugte/primäre geographische Region (z.B. Staat oder Region von seinem
Zuhause oder Arbeitsplatz). Die Gebietsschema Zeichenkette welche im Zend Framework
benutzt werden sind international definierte Standard Abkürzungen von Sprachen und
Regionen. Sie werden geschrieben als sprache_REGION. Beide Teile, sowohl
Sprache als auch Region, werden mit Buchstaben, ASCII Zeichen,
abgekürzt.
Man muß darauf achten das nicht nur Gebietsschemata mit 2 Zeichen existieren wie die
meisten Leute denken. Es gibt auch Sprachen und Regionen die nicht nur mit 2 Zeichen
abgekürzt werden. Deswegen sollte man die Region und Sprache NICHT selbst trennen,
sondern Zend_Locale verwenden um die Sprache oder Region von
einem Gebietsschema String zu trennen. Andernfalls kann es zu unerwartetem Verhalten
im eigenen Code kommen wenn man versucht das selbst zu machen.
Ein Benutzer von den USA würde die Sprache Englisch und die Region
USA erwarten, beschrieben durch das Gebietsschema "en_US". Ein
Benutzer von Deutschland würde die Sprache Deutsch und die Region
Deutschland erwarten, beschrieben durch das Gebietsschema "de_DE". Hier
findest Du eine Liste
von vordefinierten Sprachen und Kombinationen von Regionen wenn ein
bestimmtes Gebietsschema im Zend Framework ausgewählt werden muß.
Auswählen eines speziellen Gebietsschemas
Ein deutscher Benutzer in Amerika würde die Sprache Deutsch und die region
USA erwarten, aber diese nicht-standardmäßigen Mischungen werden
nicht als direkt als "Gebietsschema" unterstützt und erkannt. Wird stattdessen eine
ungültige Kombination benutzt, dann wird Sie automatisch gekürzt, indem die Region
entfernt wird. Zum Beispiel würde "de_IS" zu "de" gekürzt werden, und "xh_RU" würde zu
"xh" gekürzt werden, weil keiner dieser Kombinationen gültig ist. Zusätzlich, wenn die
Sprache nicht unterstützt wird (z.B. "zz_US") oder diese nicht existiert, dann wird ein
Standard "root" Gebietsschema benutzt. Dieses "root" Gebietsschema hat
Standarddefinitionen für international bekannte Repräsentationen von Daten, Zeiten,
Nummern, Währungen usw. Der Prozess der Kürzung hängt von der gewünschten Information
ab, weil einige Kombinationen von Sprache und Region für eine gewisse Art von
Informationen gültig sind (z.B. Daten) aber für andere nicht (z.B. Währungs Formate).
Achtung vor historischen Änderungen oder dem Versuch die verschiedenen Änderungen der
Zeitzonen die im Laufe der langen Zeit in den vielen Regionen gemacht wurden, da Zend
Framework Komponenten darüber nichts wissen. Zum Beispiel kann hier eine historische Liste mit
dutzenden Änderungen von Regierungen angesehen werden und ob eine Region
DST (Sommer-/Winterzeit) unterstützt und sogar in welche Zeitzone
eine bestimmte geographische Region gehört. Das bedeutet, wenn Datumsberechnungen
gemacht werden, wird die Berechnung welche durch die Zend Framework Komponenten
durchgeführt wird, nicht an diese Änderungen angepasst. Stattdessen wird die korrekte
Uhrzeit benutzt, welche für die aktuell benutzte Zeitzone angegeben wurde, wobei moderne
Regeln für Sommer-/Winterzeit und Zeitzonen Zuordnung anhand von geographischen Regionen
verwendet werden.
Auswahl des richtigen Gebietsschemas
In den meisten Situationen wird new Zend_Locale() automatisch das richtige
Gebietsschema auswählen, wobei die Informationen benutzt werden welche der Webbrowser
des Benutzers zur Verfügung stellt. Wenn statt dessen
new Zend_Locale(Zend_Locale::ENVIRONMENT benutzt wird, dann werden die
Informationen vom Betriebsystem des hostenden Servers, wie anbei beschrieben, dafür
genommen.
Automatische Auswahl des Gebietsschemas
Der Suchalgorithmus, welcher von Zend_Locale für die automatische
Auswahl des Gebietsschemas verwendet wird beherrscht drei Informationsquellen:
const Zend_Locale::BROWSER - Der Webbrowser des
Benutzer welcher die Informationen mit jeder Anfrage schickt. Diese wird von
PHP durch die globale Variable
HTTP_ACCEPT_LANGUAGE veröffentlicht. Wenn kein
passendes Gebietsschema gefunden wurde, dann wird mit
ENVIRONMENT gesucht und als letztes mit
FRAMEWORK gesucht.
const Zend_Locale::ENVIRONMENT -
PHP veröffentlicht das Gebietsschema des hostenden
Servers über die interne PHP Funktion
setlocale(). Wenn kein passendes Gebietsschema
gefunden wurde, dann wird mit FRAMEWORK und als letztes
mit BROWSER gesucht.
const Zend_Locale::FRAMEWORK - Wenn Zend Framework
einen standartisierten Weg zur Verfügung stellt um für Komponenten
Standardwerte zu definieren (das ist geplant aber noch nicht realisiert),
dann wird die Verwendung dieser Konstante das Gebietsschema anhand dieser
Standardwerte auswählen. Wenn kein passendes Gebietsschema gefunden wurde,
dann wird mit ENVIRONMENT und als letztes mit
BROWSER gesucht.
Verwenden automatischer Gebietsschemata
Zend_Locale bietet drei zusätzliche Gebietsschemata. Diese
Gebietsschemata gehören nicht zu irgendeiner Sprache oder Region. Es sind "automatische"
Gebietsschemata was bedeutet das Sie den gleichen Effekt wie die Methode
getDefault() haben, aber ohne die negativen Effekte wie die
Erstellung einer Instanz. Diese "automatischen" gebietsschemata können überall verwendet
werden, wo auch standard Gebietsschemata verwendet werden können, und für die Definition
eines Gebietsschemas, kann auch die String Repräsentation verwendet werden. Das bietet
Einfachheit für Situationen wo mit Gebietsschemas gearbeitet wird die vom Browser
geliefert werden.
Es gibt drei Gebietsschemata mit leicht unterschiedlichem Verhalten:
'browser' - Zend_Locale soll mit den
Informationen arbeiten die durch den Web Browser des Benutzers geliefert
werden. Sie werden von PHP in der globalen Variable
HTTP_ACCEPT_LANGUAGE veröffentlicht.
Wenn ein Benutzer mehr als ein Gebietsschema in seinem Browser anbietet,
wird Zend_Locale das erste gefundene Gebietsschema
verwenden. Wenn der Benutzer kein Gebietsschema liefert oder das Skript von
der Kommandozeile aufgerufen wird, wird automatisch das Gebietsschema
'environment' verwendet und zurückgegeben.
'environment' - Zend_Locale soll mit den
Informationen arbeiten welche vom Host Server geliefert werden. Sie werden
vom PHP über die interne Funktion
setlocale() veröffentlicht.
Wenn eine Umgebung mehr als ein Gebietsschema anbietet, wird
Zend_Locale das erste gefundene Gebietsschema
verwenden. Wenn der Host kein Gebietsschema anbietet wird automatisch das
Gebietsschema 'browser' verwendet und zurückgegeben.
'auto' - Zend_Locale soll automatisch
jedes beliebige Gebietsschema erkennen mit dem gearbeitet werden kann.
Zuerst wird nach dem Gebietsschema des Benutzers gesucht und anschließend,
wenn das nicht erfolgreich war, nach dem Gebietsschema des Hosts.
Wenn kein Gebietsschema gefunden werden konnte, wird eine Ausnahme geworfen
und bekanntgeben das die automatische Erkennung fehlgeschlagen ist.
Verwenden automatischer Gebietsschemata
Verwenden eines Standard Gebietsschemas
In einigen Umgebungen ist es nicht möglich automatisch ein Gebietsschema zu erkennen.
Man kann dieses Verhalten zum Beispiel sehen wenn eine Anfrage von der Kommandozeile
kommt, oder der anfragende Browser kein Sprachtag gesetzt hat und zusätzlich der Server
das Standardgebietsschema 'C' gesetzt hat oder ein anderes propäritäres Gebietsschema.
In solchen Fällen wirft Zend_Locale normalerweise eine Ausnahme
mit einer Nachricht, das die automatische Erkennung des Gebietsschemas nicht erfolgreich
war. Es gibt zwei Optionen um diese Situation handzuhaben. Entweder durch das Setzen
eines neuen Gebietsschemas per Hand, oder der Definition eines Standardgebietsschemas.
Handhabung von Ausnahmen für Gebietsschemas
Aber das hat einen großen negativen Effekt. Man muß das Gebietsschema-Objekt in jeder
Klasse setzen die Zend_Locale verwendet. Das kann sehr unhandlch
sein wenn mehrere Klassen verwendet werden.
Seit Zend Framework Release 1.5 gibt es einen viel besseren Weg um das handzuhaben. Man
kann ein Standard Gebietsschema mit der statischen setDefault()
Methode setzen. Natürlich wird jedes unbekannte oder nicht voll qualifizierte
Gebietsschema eine Ausnahme werden. setDefault() sollte der
erste Aufruf sein bevor irgendeine Klasse initiiert wird die
Zend_Locale verwendet. Siehe das folgende Beispiel für Details:
Setzen eines Standardgebietsschemas
Im Fall das kein Gebietsschema erkannt wird, wird automatisch das Gebietsschema
de verwendet. Andernfalls wird das erkannte Gebietsschema
verwendet.
ZF lokalisierbare Klassen
Im Zend Framework sind lokalisierbare Klassen von Zend_Locale
abhängig um ein Gebietsschema automatisch auszuwählen, wie im oberen Abschnitt
geschrieben. Das Erstellen eines Datums durch Verwendung von
Zend_Date ohne die Angabe eines Gebietsschemas führt als
Ergebnis zu einem Objekt mit einem Gebietsschema, basierend auf den Informationen
welche durch den Webbrowser des Benutzers zur Verfügung gestellt werden.
Daten verwenden das aktuelle Gebietsschema des Web Benutzers
Um dieses Standardverhalten zu übergehen, und die eine lokalisierbare Zend Framework
Komponente dazu zu bringen ein spezielles Gebietsschema zu benutzen welches unabhängig
vom Gebietsschema des Besucher der Webseite ist, muß als dritter Parameter im
Konstruktor das Gebietsschema angegeben werden.
Übergehen der Auswahl des standardmäßigen Gebietsschemas
Wenn viele Objekte benutzt werden die alle das gleiche Gebietsschema verwenden, sollte
das Gebietsschema explizit definiert werden, um die zusätzliche Arbeit des Objekts durch
die Eruierung des Standardmäßigen Gebietsschemas zu verringern.
Optimierung der Geschwindigkeit durch Benutzung eines Standard Gebietsschemas
Anwendungsweites Gebietsschema
Zend Framework erlaubt die Verwendung eines Anwendungsweiten Gebietsschemas. Man kann
einfach eine Instanz von Zend_Locale in der Registry mit dem
Schüssel 'Zend_Locale' setzen. Dann wird diese Instanz in allen Klassen vom Zend
Framework die Gebietsschemata verwenden selbst verwendet. Auf diesem Weg wird eine
Instanz in der Registry gesetzt und dann kann man das weitere Setzen vergessen. Sie wird
automatisch in allen anderen Klassen verwendet. Siehe das folgende Beispiel für die
richtige Verwendung:
Verwendung eines anwendungsweiten Gebietsschemas
getLocale();
echo $date->getDate();
]]>
Zend_Locale_Format::setOptions(array $options)
Die Option 'precision' wird benutzt um einen Wert zu verkürzen oder mit extra Ziffern zu
strecken. Ein Wert von '-1' verhindert die Veränderung der Anzahl an Ziffern im
Nachkomma-Teil des Wertes. Die 'locale' Option hilft wenn Nummern und Daten analysiert
werden und hierbei Trennzeichen oder Monatsnamen verwendet werden. Die Datumsformat
Option 'format_type' wählt zwischen CLDR/ISO Datumsdefinitionen und
PHP's date() Definitionen. Die Option 'fix_date' erlaubt oder
verhindert eine Automatik welche versucht falsche Daten zu korrigieren. Die Option
'number_format' definiert ein Standard Format für Nummern bei Verwendung der Funktion
toNumber(). (siehe
).
Die Option 'date_format' kann verwendet werden um ein Standard Datumsformat zu
definieren. Aber Achtung bei der Verwendung von getDate(), checkDateFormat() und
getTime() nach der Verwendung von setOptions() mit einem 'date_format'. Um diese vier
Methoden mit einem Standard Datumsformat für ein Gebietsschema zu benutzen, muß
array('date_format' => null, 'locale' => $locale) in deren Optionen angegeben werden.
Daten die das richtige Gebietsschema des Web Benutzers verwenden
'en_US',
'fix_date' => true,
'format_type' => 'php'));
]]>
Um mit den Standarddefinitionen eines Gebietsschemas zu arbeiten kann die Konstante
Zend_Locale_Format::STANDARD verwendet werden. Das Setzen der
Konstante Zend_Locale_Format::STANDARD für
'date_format' benutzt die Standarddefinition des aktuellen Gebietsschemas.
Das Setzen für 'number_format' benutzt das Standard Nummernformat dieses Gebietsschemas.
Und das Setzen für 'locale' verwendet das Standard Gebietsschema des Servers oder
Browsers.
Verwendung von STANDARD Definitionen für setOptions()
'en_US',
'date_format' => 'dd.MMMM.YYYY'));
// Überladen des global gesetzten Datumsformats
$date = Zend_Locale_Format::getDate('2007-04-20',
array('date_format' =>
Zend_Locale_Format::STANDARD);
// Überladen des global gesetzten Standard Gebietsschemas
Zend_Locale_Format::setOptions(array('locale' => Zend_Locale_Format::STANDARD,
'date_format' => 'dd.MMMM.YYYY'));
]]>
Zend_Locale und dessen Subklassen schneller machen
Zend_Locale und dessen Subklassen können durch die Verwendung von
Zend_Cache schneller gemacht werden. Man sollte die statische
Methode Zend_Locale::setCache($cache) verwenden wenn man
Zend_Locale benutzt. Zend_Locale_Format
kann schneller gemacht werden indem die Option cache innerhalb von
Zend_Locale_Format::setOptions(array('cache' => $adapter));
aufgerufen wird. Wenn beide Klassen verwendet werden sollte nur für
Zend_Locale ein Cache gesetzt werden, da der zuletzt gesetzte
Cache den vorher gesetzten Cache überschreibt. Der Bequemlichkeit halber gibt es auch
die statischen Methoden getCache(),
hasCache(), clearCache() und
removeCache().
Wenn kein Cache gesetzt wird, dann setzt Zend_Locale automatisch
von selbst einen Cache. Manchmal ist es gewünscht zu verhindern das ein Cache gesetzt
wird, selbst wenn das die Performance verringert. In diesem Fall sollte die statische
disableCache(true) Methode verwendet werden. Sie schaltet
nicht nur den aktuell gesetzten Cache aus, ohne Ihn zu löschen, sondern verhindert auch
das ein Cache automatisch erstellt wird, wenn kein Cache gesetzt ist.