From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../hjp5/html/k100118.html | 1368 ++++++++++++++++++++ 1 file changed, 1368 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100118.html (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100118.html') diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100118.html b/Master/Reference Architectures and Patterns/hjp5/html/k100118.html new file mode 100644 index 0000000..3d4c992 --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100118.html @@ -0,0 +1,1368 @@ + + + +Handbuch der Java-Programmierung, 5. Auflage + + + + + + + + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage +
 <<  +  <   +  >   + >>  + API  +Kapitel 17 - Utility-Klassen II +
+
+ + + + +

17.4 Internationalisierung und Lokalisierung +

+
+ +
+ +

+Seit dem JDK 1.1 bietet Java Unterstützung für das Internationalisieren +von Anwendungen. Auf diese Weise können Programme geschrieben +werden, die nicht nur im eigenen, sondern auch in anderen Ländern +der Erde verwendbar sind. Verschiedene Länder und Regionen unterscheiden +sich nicht nur durch die verwendete Sprache und die zugrunde liegenden +Schrift- und Zahlzeichen, sondern auch durch unterschiedliche Kalender +und Zeitzonen, abweichende Zahlen-, Zeit- und Datumsformatierungen, +eigene Währungen, unterschiedliche Telefonnummern- und Anschriftenkonventionen +und so weiter. +

+ + + + + + + + + +
+ +

+Die Begriffe Internationalisierung und Lokalisierung +werden häufig synonym gebraucht oder miteinander verwechselt. +Unter Internationalisierung wollen wir das Bündel technischer +Maßnahmen verstehen, mit denen ein Programm für die Verwendung +in verschiedenen Ländern und Sprachräumen vorbereitet wird. +Unter Lokalisierung verstehen wir dagegen die konkrete Anpassung +eines internationalisierten Programms an eine ganz bestimmte Sprache. +Ein Teil der Internationalisierung eines Programms ist es also beispielsweise, +wenn Textkonstanten nicht mehr fest im Programm enthalten sind, sondern +zur Laufzeit aus Ressourcendateien geladen werden. Die Lokalisierung +hingegen besteht darin, eben diese Textressourcen in die jeweilige +Sprache zu übersetzen. + +

+Im angelsächsischen Sprachraum werden die beiden unhandlichen +Begriffe meist abgekürzt. Statt »Internationalisierung« +wird I18N gesagt, statt »Lokalisierung« +L10N. Die Spielregel ist ganz einfach: +Zwischen den ersten und letzten Buchstaben des jeweiligen Wortes steht +die Gesamtzahl der Zeichen.

+ + + + +
 Hinweis 
+
+ +

+Internationalisierung ist ein nicht-triviales Thema, das viele Facetten +hat. Einige Beispiele dafür, in welcher Weise es von Java unterstützt +wird, sind: +

+ + + + +

17.4.1 Die Klasse Locale

+ +

+Ausgangspunkt der Lokalisierung eines Java-Programms ist die Klasse +Locale +aus dem Paket java.util. +Jede Instanz dieser Klasse identifiziert eine bestimmte geografische, +kulturelle oder politische Region auf der Erde inklusive der Sprache, +die dort üblicherweise verwendet wird. Ein Locale-Objekt +kann wie folgt erzeugt werden: +

+ + + + + +
+ +
+public Locale(String language, String country)
+
+
+
+java.util.Locale
+ +

+Das erste Argument ist ein String +mit dem Code für die Sprache, wie er im Standard ISO-639 +definiert ist. Der Sprachcode wird kleingeschrieben und lautet z.B. +»en« für englisch, »fr« für französich +oder »de« für deutsch. Das zweite Argument gibt das +Land gemäß dem Standard ISO-3166 +an, hier werden stets große Buchstaben verwendet. So stehen +beispielsweise »US« für die USA, »GB« für +England, »FR« für Frankreich und »DE« für +Deutschland. + +

+Der Länderteil ist optional. Wird an seiner Stelle ein Leerstring +übergeben, repräsentiert die Locale +lediglich eine Sprache ohne spezifisches Land. »en« alleine +steht dann beispielsweise für die englische Sprache, wie sie +nicht nur in England, sondern auch in den USA oder Kanada verständlich +wäre. Soll dagegen auf kanadische Besonderheiten abgestellt werden, +ist als Land »CA« zu ergänzen. Für den französischsprachigen +Teil von Kanada würde dagegen eine Locale +aus »fr« und »CA« gebildet werden. +

+ + + + + + + + + +
+ +

+Neben Sprach- und Länderkennung kann eine Locale +einen dritten Parameter haben. Dieser wird als Variante bezeichnet +und kann dazu verwendet werden, Betriebssysteme oder Konfigurationen +voneinander zu unterscheiden. So werden lokalisierte Hilfetexte unter +UNIX möglicherweise mit anderen Zeichensätzen oder Hilfsprogrammen +arbeiten als unter Windows oder auf dem Macintosh. Wir wollen darauf +allerdings nicht weiter eingehen.

+ + + + +
 Hinweis 
+
+ +

+Die Klasse Locale +bietet mit der statischen Methode getDefault +die Möglichkeit, eine Locale +zu beschaffen, die dem Land entspricht, in dem das laufende Programm +ausgeführt wird. Mit getCountry +kann der Länder-, mit getLanguage +der Sprachcode und mit getVariant +die Variante ermittelt werden: +

+ + + + + +
+ +
+public static Locale getDefault()
+
+public String getLanguage()
+public String getCountry()
+public String getVariant()
+
+
+
+java.util.Locale
+ +

+Mit getDefault +kann ein Programm zur Laufzeit ermitteln, in welchem Land es läuft +und welche Sprache dort gesprochen wird. Weiterhin stellt die Klasse +noch einige Konstanten mit vordefinierten Locale-Objekten +für wichtige Länder und Sprachen zur Verfügung. + +

+Das folgende Beispielprogramm ermittelt die Standard-Locale +des aktuellen Rechners und die vordefinierten Locales für Deutschland, +England und die USA und gibt sie auf der Console aus: + + +

+ + + + + +
+ +
+001 /* Listing1707.java */
+002 
+003 import java.util.*;
+004 
+005 public class Listing1707
+006 {
+007   public static void main(String[] args)
+008   {
+009     System.out.println("Default: " + Locale.getDefault());
+010     System.out.println("GERMANY: " + Locale.GERMANY);
+011     System.out.println("UK     : " + Locale.UK);
+012     System.out.println("US     : " + Locale.US);
+013   }
+014 }
+
+
+Listing1707.java
+ +Listing 17.7: Darstellung einiger Locales

+ +

+Die Ausgabe des Programm sieht hierzulande etwa so aus: + +

+Default: de_DE
+GERMANY: de_DE
+UK     : en_GB
+US     : en_US
+
+ + + + + +

17.4.2 Zahlen formatieren

+ +

+In früheren Abschnitten wurde schon gezeigt, wie Fließkommazahlen +erzeugt und verarbeitet werden können. Nach Umwandlung in einen +String +lassen sie sich mit den Methoden print +und println +auf der Console, in Dateien oder auf einer grafischen Oberfläche +ausgeben - allerdings ohne die Möglichkeit, auf die Formatierung +der Ausgabe Einfluss zu nehmen. Wir wollen uns in diesem Abschnitt +die Klasse DecimalFormat +aus dem Paket java.text +ansehen und zeigen, wie Ganz- und Fließkommazahlen mit ihrer +Hilfe formatiert werden können. + +

+DecimalFormat +ist eine Spezialisierung der Klasse NumberFormat +und dient zur Formatierung von Ganz- oder Fließkommazahlen in +Dezimaldarstellung unter Berücksichtigung länderspezifischer +Besonderheiten. Der Aufrufer legt dabei die Anzahl der Vor- oder Nachkommastellen +fest, und DecimalFormat +entscheidet, ob ein Punkt oder Komma als Dezimaltrennzeichen verwendet +werden soll. + +

+Eine Instanz der Klasse DecimalFormat +kann entweder mit new +oder durch Aufruf einer der Factory-Methoden der Klasse NumberFormat +erzeut werden: +

+ + + + + +
+ +
+public DecimalFormat(String pattern)
+
+
+
+java.text.DecimalFormat
+

+ + + + + +
+ +
+public static NumberFormat getNumberInstance()
+public static NumberFormat getNumberInstance(Locale locale)
+
+
+
+java.text.NumberFormat
+ +

+Soll ein DecimalFormat-Objekt +für die aktuelle Locale +erzeugt werden, kann es durch Übergabe eines Formatstrings direkt +instanziert werden. Wird es dagegen für eine andere Locale +benötigt, muss es mit der statischen Methode getNumberInstance +der Klasse NumberFormat +erzeugt werden. In diesem Fall muss noch die Methode applyPattern +aufgerufen werden, um den Formatstring zuzuweisen: +

+ + + + + +
+ +
+public void applyPattern(String pattern)
+
+
+
+java.text.NumberFormat
+

+ + + + + + + + + + + +
+ +

+getNumberInstance +gibt einen Wert vom Typ NumberFormat +zurück (der Basisklasse von DecimalFormat). +Das ist zwar in westlichen Ländern in der Regel eine Instanz +von DecimalFormat. +Ganz sicher kann sich ein Programm aber nur sein, wenn es den Typ +des Rückgabewerts vor der Konvertierung nach DecimalFormat +mit instanceof +überprüft.

+ + + + +
 Warnung 
+
+ +

+Der Formatstring definiert eine Maske zur Formatierung der Ausgabe. +Er besteht aus zwei Teilen, die durch ein Semikolon voneinander getrennt +sind. Der erste gibt die Formatierungsregeln für positive, der +zweite für negative Zahlen an. Der zweite Teil kann auch ausgelassen +werden. Dann werden negative Zahlen wie positive Zahlen mit vorangestelltem +Minuszeichen formatiert. Jedes Zeichen im Formatstring regelt die +Darstellung der korrespondierenden Ziffer. Der Formatstring kann folgende +Zeichen enthalten: + +

+ + + + + + + + + + + + + + + + + + + + + + + +
SymbolBedeutung
0Eine einzelne Ziffer
#Eine einzelne Ziffer. Wird ausgelassen, +falls führende Null.
.Dezimaltrennzeichen
,Tausendertrennzeichen
EAktiviert Exponentialdarstellung
%Ausgabe als Prozentwert
+

+Tabelle 17.2: Formatzeichen für DecimalFormat

+ +

+Zusätzlich können beliebige Zeichen vorangestellt oder hinten +angefügt werden; sie werden dann unverändert ausgegeben. +Ungültige Formatstrings werden mit einer IllegalArgumentException +quittiert. Falls nach einem Semikolon ein eigener Formatstring für +negative Zahlen angegeben wird, muss er mit Ausnahme eines veränderten +Prefixes und Suffixes genau dem Formatstring für positive Zahlen +entsprechen. + +

+Die Formatierung einer Zahl wird durch Aufruf von format +ausgeführt: +

+ + + + + +
+ +
+public final String format(long number)
+public final String format(double number)
+
+
+
+java.text.DecimalFormat
+ +

+Die Methode gibt es sowohl mit einem long-Parameter +zur Ausgabe von Ganzzahlen als auch mit einem double +zur Ausgabe von Fließkommazahlen. Da der Formatstring bereits +bei der Konstruktion des Objekts übergeben wurde, kann format +mehrfach aufgerufen werden, um nacheinander weitere Zahlen zu formatieren. + +

+Das folgende Programm zeigt die beispielhafte Anwendung von DecimalFormat. +Es gibt die Zahl 1768.3518 für die aktuelle Locale +in unterschiedlichen Längen und Formatierungen auf der Console +aus: + + +

+ + + + + +
+ +
+001 /* Listing1708.java */
+002 
+003 import java.text.*;
+004 
+005 public class Listing1708
+006 {
+007   public static void print(double value, String format)
+008   {
+009     DecimalFormat df = new DecimalFormat(format);
+010     System.out.println(df.format(value));
+011   }
+012   public static void main(String[] args)
+013   {
+014     double value = 1768.3518;
+015     print(value, "#0.0");
+016     print(value, "#0.000");
+017     print(value, "000000.000");
+018     print(value, "#.000000");
+019     print(value, "#,###,##0.000");
+020     print(value, "0.000E00");
+021   }
+022 }
+
+
+Listing1708.java
+ +Listing 17.8: Anwendung von DecimalFormat

+ +

+Die Ausgabe des Programms lautet: + +

+1768,4
+1768,352
+001768,352
+1768,351800
+1.768,352
+1,768E03
+
+ + +

+Sie kommt wie folgt zustande: +

+ +

+Wenn das Programm mit englischer Locale +aufgerufen worden wäre, wären in der Ausgabe Punkte und +Kommata vertauscht (denn im englischen Sprachraum werden Kommata als +Tausenderseparatoren und Punkte als Dezimaltrennzeichen verwendet). +Die Ausgabe wäre dann wie folgt gewesen: + +

+1768.4
+1768.352
+001768.352
+1768.351800
+1,768.352
+1.768E03
+12345678.909
+
+ +

+ + + + + + + + + +
+ +

+Neben der Ausgabesteuerung mit Hilfe des Formatstrings stellt DecimalFormat +noch weitere Methoden zur Konfiguration der Ausgabe zur Verfügung. +Beispiele sind etwa setGroupingSize +zur Einstellung der Größe der Tausendergruppen oder setDecimalSeparatorAlwaysShown +zur Festlegung, ob auch Ganzzahlen mit Dezimalzeichen ausgegeben werden +sollen. Zudem bietet DecimalFormat +eine Methode parse, +mit der lokalisierte Zahleneingaben eingelesen werden können. +Weitere Details zu diesen Methoden können in der API-Dokumentation +nachgelesen werden.

+ + + + +
 Hinweis 
+
+ + + + +

17.4.3 Datum und Uhrzeit formatieren +

+ +

+Neben Zahlen lassen sich mit dem Paket java.text +auch Datums- und Uhrzeitwerte unter Beachtung nationaler Besonderheiten +formatieren und in einen String +konvertieren. Die dafür vorgesehene Klasse DateFormat +wird zunächst (analog zu NumberFormat) +mit einer Factory-Methode instanziert und konfiguriert. Anschließend +wird format +aufgerufen, um den Ausgabestring zu erzeugen. + +

+Bei der Instanzierung gibt es einige Varianten zu unterscheiden: +

+ + + + + +
+ +
+public static final DateFormat getDateInstance(
+  int style,
+  Locale locale
+)
+
+public static final DateFormat getTimeInstance(
+  int style,
+  Locale locale
+)
+
+public static final DateFormat getDateTimeInstance(
+  int datestyle,
+  int timestyle,
+  Locale locale
+)
+
+public final String format(Date date)
+
+
+
+java.text.DateFormat
+ +

+Mit getDateInstance +wird eine Instanz zur Ausgabe eines Datums erzeugt, getTimeInstance +dient zur Ausgabe der Uhrzeit und getDateTimeInstance +zur kombinierten Ausgabe von Datum und Uhrzeit. Alle Methoden erwarten +ein Argument style, das mit +einer der Konstanten SHORT, +MEDIUM, +LONG, +FULL +oder DEFAULT +belegt werden muss. Es gibt an, wie lang die jeweilige Ausgabe später +sein soll und welche Daten sie enthalten soll. So werden beispielsweise +bei der kurzen Uhrzeit lediglich Stunden und Minuten ausgegeben, während +in den übrigen Stufen auch die Sekunden und andere Informationen +enthalten sind. Als zweites Argument wird die gewünschte Locale +angegeben; für die Standard-Locale +kann es auch ausgelassen werden. + +

+Das folgende Programm formatiert das aktuelle Datum und die aktuelle +Uhrzeit mit allen möglichen style-Parametern +und gibt die Ergebnisse auf der Console aus: + + +

+ + + + + +
+ +
+001 /* Listing1709.java */
+002 
+003 import java.util.*;
+004 import java.text.*;
+005 
+006 public class Listing1709
+007 {
+008   public static void print(Calendar cal, int style)
+009   {
+010     DateFormat df;
+011     df = DateFormat.getDateInstance(style);
+012     System.out.print(df.format(cal.getTime()) + " / ");
+013     df = DateFormat.getTimeInstance(style);
+014     System.out.println(df.format(cal.getTime()));
+015   }
+016 
+017   public static void main(String[] args)
+018   {
+019     GregorianCalendar cal = new GregorianCalendar();
+020     print(cal, DateFormat.SHORT);
+021     print(cal, DateFormat.MEDIUM);
+022     print(cal, DateFormat.LONG);
+023     print(cal, DateFormat.FULL);
+024     print(cal, DateFormat.DEFAULT);
+025   }
+026 }
+
+
+Listing1709.java
+ +Listing 17.9: Anwendung von DateFormat

+ +

+Die Ausgabe des Programms lautet: + +

+24.05.00 / 21:58
+24.05.2000 / 21:58:55
+24. Mai 2000 / 21:58:55 GMT+02:00
+Mittwoch, 24. Mai 2000 / 21.58 Uhr GMT+02:00
+24.05.2000 / 21:58:55
+
+ +

+ + + + + + + + + + + +
+ +

+Leider ist nicht sehr genau dokumentiert, welche Felder des Datums +bzw. der Uhrzeit in Abhängigkeit von dem style-Parameter +tatsächlich ausgegeben werden, zudem ist die Formatierung länderspezifisch. +Wenn es also auf eine präzise definierte Formatierung ankommt, +muss ausprobiert werden, welche Ergebnisse jeweils zustande kommen, +und die am besten passende Variante gewählt werden. Alternativ +kann mit Hilfe der Klasse FieldPosition +auf jedes einzelne Feld zugegriffen und so eine genauere Steuerung +der Ausgabe erreicht werden.

+ + + + +
 Warnung 
+
+ + + + +

17.4.4 Laden von Ressourcen

+ +

+Ein ausgeliefertes Java-Programm besteht in aller Regel nicht nur +aus Bytecode in Form von .class-Dateien, +sondern enthält weitere Dateien mit zusätzlichen Informationen. +Dazu zählen beispielsweise Textkonserven und Grafikdateien für +grafische Oberflächen, Sounddateien zur akustischen Untermalung +von Programmereignissen oder Hilfsdateien mit Klartextmeldungen zu +möglichen Programmfehlern. Diese zusätzlichen Informationen +werden als Ressourcen bezeichnet und müssen zusammen mit +dem Programm ausgeliefert werden. Die meisten von ihnen müssen +lokalisiert werden. + +

+Java stellt seit der Version 1.1 mit der Klasse ResourceBundle +aus dem Paket java.util +ein universelles Hilfsmittel zur Verwendung derartiger Ressourcen +zur Verfügung. Die Grundidee ist dabei einfach: Ein ResourceBundle +ist ein Java-Objekt, das eine Sammlung von Ressourcen zusammenfasst +und auf Anfrage einzeln zur Verfügung stellt. Jede Ressource +hat einen eindeutigen und für alle unterstützten Sprachvarianten +identischen Namen, mit dem auf sie zugegriffen werden kann. Ein konkretes +ResourceBundle +ist stets sprachabhängig und enthält nur die Ressourcen +für eine bestimmte Locale. + +

+Damit ist ein ResourceBundle +zunächst nicht viel mehr als eine Schlüssel-Wert-Collection +wie beispielsweise Hashtable +oder HashMap. +Der Clou liegt in der Tatsache, dass der Name des ResourceBundle +die Locale +angibt, deren Daten er enthält. Während der vordere Teil +fest und für alle lokalisierten Varianten gleich ist, ist der +hintere Teil Locale-spezifisch +und gibt Sprache, Land und gegebenenfalls Variante an. Lautet der +feste Teil beispielsweise »ImageResources«, wären »ImageResources_fr« +und »ImageResources_en_US« die Namen für die französiche +und US-englische Variante. + + + + +

Die Methode getBundle

+ +

+ResourceBundle +stellt eine statische Methode getBundle +zur Verfügung, mit der zu einem Basisnamen und einer vorgegebenen +Locale +ein ResourceBundle +beschafft werden kann. Diese gibt es in unterschiedlichen Ausprägungen: +

+ + + + + +
+ +
+public static final ResourceBundle getBundle(String baseName)
+  throws MissingResourceException
+
+public static final ResourceBundle getBundle(
+  String baseName,
+  Locale locale
+)
+
+
+
+java.util.ResourceBundle
+ +

+Die erste Variante besorgt ein ResourceBundle +für die aktuelle Default-Locale, +die zweite für die als Argument angegebene. In beiden Fällen +wird wie folgt vorgegangen: +

+ +

+Ist beispielsweise Deutschland die Default-Locale +und soll die Resource »MyTextResource« für Frankreich +beschafft werden, sucht getBundle +nacheinander nach folgenden Klassen: +

    +
  1. MyTextResource_fr_FR +
  2. MyTextResource_fr +
  3. MyTextResource_de_DE +
  4. MyTextResource_de +
  5. MyTextResource +
+ +

+Die Suche bricht ab, wenn die erste passende Klasse gefunden wurde. +Ist überhaupt keine passende Ressource vorhanden, löst getBundle +eine MissingResourceException +aus. Dies ist auch der Fall, wenn die gefundene Klasse nicht aus ResourceBundle +abgeleitet ist. + + + + +

Eigene Ressourcenklassen erstellen

+ +

+Eigene Resourcenklassen müssen aus ResourceBundle +abgeleitet werden und die beiden (in der Basisklasse abstrakten) Methoden +getKeys +und handleGetObject +überlagern: +

+ + + + + +
+ +
+public Enumeration getKeys()
+
+protected Object handleGetObject(String key)
+  throws MissingResourceException
+
+
+
+java.util.ResourceBundle
+ +

+handleGetObject +liefert eine Ressource zu einem vorgegebenen Schlüssel, getKeys +eine Aufzählung aller vorhandenen Schlüssel. Gibt es zu +einem vorgegebenen Schlüssel keine Ressource, muss handleGetObject +null +zurückgeben. + +

+Das folgende Listing zeigt eine Klasse SimpleTextResource, +die zur Internationalisierung von einfachen Texten verwendet werden +kann. Die lokalisierten Varianten können dabei sehr einfach realisiert +werden, indem sie aus SimpleTextResource +abgeleitet werden. Sie müssen dann lediglich im Konstruktor die +Hashtable +mit den gewünschten Schlüssel-/Textpaaren füllen. + + +

+ + + + + +
+ +
+001 /* SimpleTextResource.java */
+002 
+003 import java.util.*;
+004 
+005 public class SimpleTextResource
+006 extends ResourceBundle
+007 {
+008   protected Hashtable data = new Hashtable();
+009 
+010   public Enumeration getKeys()
+011   {
+012     return data.keys();
+013   }
+014 
+015   public Object handleGetObject(String key)
+016   {
+017     return data.get(key);
+018   }
+019 
+020   public ResourceBundle getParent()
+021   {
+022     return parent;
+023   }
+024 }
+
+
+SimpleTextResource.java
+ +Listing 17.10: Die Klasse SimpleTextResource

+ +

+Nun soll ein ResourceBundle +mit dem Namen »MyTextResource« erstellt werden, das Übersetzungen +zu den beiden Schlüsseln »Hi« und »To« liefert. +Dazu definieren wir zunächst eine Klasse MyTextResource, +die immer dann verwendet wird, wenn keine passende lokale Variante +gefunden wird. In unserem Fall soll sie die Texte in englischer Sprache +zur Verfügung stellen: + + +

+ + + + + +
+ +
+001 /* MyTextResource.java */
+002 
+003 public class MyTextResource
+004 extends SimpleTextResource
+005 {
+006   public MyTextResource()
+007   {
+008     data.put("Hi", "Hello");
+009     data.put("To", "World");
+010   }
+011 }
+
+
+MyTextResource.java
+ +Listing 17.11: Die Basisvariante MyTextResource

+ +

+Des weiteren wollen wir eine allgemeine deutschsprachige und eine +spezielle schweizerische Variante zur Verfügung stellen: + + +

+ + + + + +
+ +
+001 /* MyTextResource_de.java */
+002 
+003 public class MyTextResource_de
+004 extends SimpleTextResource
+005 {
+006   public MyTextResource_de()
+007   {
+008     data.put("Hi", "Hallo");
+009     data.put("To", "Welt");
+010   }
+011 }
+
+
+MyTextResource_de.java
+ +Listing 17.12: Die deutschsprachige Variante MyTextResource_de

+ + +

+ + + + + +
+ +
+001 /* MyTextResource_de_CH.java */
+002 
+003 public class MyTextResource_de_CH
+004 extends SimpleTextResource
+005 {
+006   public MyTextResource_de_CH()
+007   {
+008     data.put("Hi", "Grüezi");
+009     data.put("To", "Schweiz");
+010   }
+011 }
+
+
+MyTextResource_de_CH.java
+ +Listing 17.13: Die schweizerische Variante MyTextResource_de_CH

+ +

+Will ein Client auf eine Ressource in einem ResourceBundle +zugreifen, tut er das nicht durch direkten Aufruf von handleGetObject, +sondern verwendet dazu eine der folgenden Methoden: +

+ + + + + +
+ +
+public Object getObject(String key)
+  throws MissingResourceException
+
+public String getString(String key)
+  throws MissingResourceException
+
+public final String[] getStringArray(String key)
+  throws MissingResourceException
+
+
+
+java.util.ResourceBundle
+ +

+getObject +liefert die Ressource als Object, +getString +als String +und getStringArray +als String-Array. +Die letzten beiden Methoden dienen vornehmlich der Bequemlichkeit: +sie rufen selber getObject +auf und nehmen dem Aufrufer die anschließend erforderliche Typkonvertierung +ab. + +

+Das folgende Listing zeigt ein einfaches Testprogramm, das die Textressourcen +für verschiedene Lokalisierungen ermittelt und auf der Console +ausgibt. Das ResourceBundle +wird beschafft, indem getBundle +mit »MyTextResource« und der jeweils gewünschten Locale +als Argument aufgerufen wird. Anschließend wird auf die übersetzten +Texte mit Aufrufen von getString +zugegriffen: + + +

+ + + + + +
+ +
+001 /* Listing1714.java */
+002 
+003 import java.util.*;
+004 
+005 public class Listing1714
+006 {
+007   public static void sayHello(Locale locale)
+008   {
+009     System.out.print(locale + ": ");
+010     ResourceBundle textbundle = ResourceBundle.getBundle(
+011       "MyTextResource",
+012       locale
+013     );
+014     if (textbundle != null) {
+015       System.out.print(textbundle.getString("Hi") + ", ");
+016       System.out.println(textbundle.getString("To"));
+017     }
+018   }
+019 
+020   public static void main(String[] args)
+021   {
+022     sayHello(Locale.getDefault());
+023     sayHello(new Locale("de", "CH"));
+024     sayHello(Locale.US);
+025     sayHello(Locale.FRANCE);
+026   }
+027 }
+
+
+Listing1714.java
+ +Listing 17.14: Test von MyTextResource

+ +

+Die Ausgabe des Programms ist: + +

+de_DE: Hallo, Welt
+de_CH: Grüezi, Schweiz
+en_US: Hallo, Welt
+fr_FR: Hallo, Welt
+
+ + +

+Die Default-Locale +war beim Testen »de_DE«. Zwar wurde keine passende Klasse +MyTextResource_de_DE definiert, +aber durch den oben beschriebenen Fallback-Mechanismus liefert getBundle +eine Instanz von MyTextResource_de. +Bei der nächsten Lokalisierung wird die erforderliche Klasse +MyTextResource_de_CH direkt +gefunden, und die Ausgabe erfolgt entsprechend. Zu den letzten beiden +Lokalisierungswünschen werden keine passenden Ressourcen gefunden. +getBundle +verwendet in beiden Fällen die Datei MyTextResource_de +zur Default-Locale, und die +Ausgaben erfolgen in deutscher Sprache. +

+ + + + + + + + + + + +
+ +

+Damit die Suche nach Ressourcen und die (im nächsten Abschnitt +zu besprechende) Vaterverkettung richtig funktionieren, müssen +zu einer Ressource auch stets alle allgemeineren Ressourcen vorhanden +sein. Gibt es etwa - wie in unserem Beispiel - eine Ressource mit +der Endung »_de_CH«, so müssen auch die Ressourcen +mit der Endung »_de« und die Basisressource ohne lokale +Endung vorhanden sein.

+ + + + +
 Warnung 
+
+

+ + + + + + + + + + + +
+ +

+Um die Übersichtlichkeit zu verbessern, sollten Ressourcendateien +in eigenen Verzeichnissen gehalten werden. Da sie mit Hilfe des Classloaders +geladen werden, müssen sie in einem Verzeichnis abgelegt werden, +in dem auch eine Klasse gefunden werden würde. Man könnte +beispielsweise im Hauptpaket der Anwendung ein Unterverzeichnis resources +anlegen und alle Ressourcendateien dort platzieren. Der im Programm +zu verwendende Ressourcenname wird dann einfach vorne um »resources.« +ergänzt. Derartige Ressourcen, die über den Klassenpfad +erreichbar sind, werden auch dann gefunden, wenn das Programm in Form +einer .jar-Datei ausgeliefert wird.

+ + + + +
 Tipp 
+
+ + + + +

Die Verkettung von ResourceBundles

+ +

+Ein Aufruf von getObject +wird zunächst an die Methode handleGetObject +weitergeleitet. Ist deren Rückgabewert nicht null, +wird er an den Aufrufer übergeben. Andernfalls wird die Anfrage +an den Vater des ResourceBundles weitergereicht. Die Vaterverkettung +erfolgt bei der Instanzierung von ResourceBundle-Objekten +automatisch, indem das jeweils nächstmögliche allgemeinere +ResourceBundle +als Vater verwendet wird. So ist beispielsweise der Vater von »MyTextResource_de_DE« +die Ressource »MyTextResource_de«, und deren Vater ist »MyTextResource«. + +

+Durch diese Vaterverkettung muss ein spezielleres ResourceBundle +nur die Ressourcen zur Verfügung stellen, die sich gegenüber +dem Vater unterscheiden oder neu hinzugekommen sind. Alle unveränderten +Ressourcen brauchen dagegen nicht erneut definiert zu werden. Soll +beispielsweise eine »MyTextResource« für englischsprachige +Lokalisierungen definiert werden, die sich nur durch die Übersetzung +des Schlüssels »To« von der Basisressource unterscheidet, +muss »Hi« nicht definiert werden: + + +

+ + + + + +
+ +
+001 /* MyTextResource_en.java */
+002 
+003 public class MyTextResource_en
+004 extends SimpleTextResource
+005 {
+006   public MyTextResource_en()
+007   {
+008     data.put("To", "World of English");
+009   }
+010 }
+
+
+MyTextResource_en.java
+ +Listing 17.15: Die englische Variante MyTextResource_en

+ +

+Nach dem Anlegen und Übersetzen dieser Klasse würde ein +Aufruf von Listing 17.14 +zu folgender Ausgabe führen: + +

+de_DE: Hallo, Welt
+de_CH: Grüezi, Schweiz
+en_US: Hello, World of English
+fr_FR: Hallo, Welt
+
+ + +

+Die Übersetzung von »Hi« kommt nun aus der Vater-Ressource +MyTextResource. + + + + +

Die Klasse PropertyResourceBundle

+ +

+Die vorangegangenen Beispiele haben an Textkonserven exemplarisch +gezeigt, wie man Ressourcen lokalisieren kann. Sollen einfache Texte +übersetzt werden, gibt es aber noch einen einfacheren Weg. Das +oben beschriebene Suchschema von getBundle +war nämlich insofern unvollständig, als nach jedem einzelnen +Schritt zusätzlich eine Datei desselben Names wie die aktuelle +Klasse, aber mit der Erweiterung .properties, +gesucht wird. Wird also beispielsweise in einem beliebigen Suchschritt +die Klasse MyResource_de_DE +nicht gefunden, so sucht getBundle +vor dem Übergang zum nächsten Schritt nach einer Datei mit +dem Namen MyResource_de_DE.properties. + +

+Ist eine solche vorhanden, wird eine Instanz der Klasse PropertyResourceBundle +erzeugt und an den Aufrufer zurückgegeben. PropertyResourceBundle +liest die Eingabedatei (sie muss dasselbe Format wie die in Abschnitt 14.4.4 +beschriebenen Property-Dateien haben) und speichert alle darin gefundenen +Schlüssel-Wert-Paare ab. Anschließend können diese +als gewöhnliche Text-Ressourcen vom Programm verwendet werden. + +

+Um beispielsweise die vorigen Beispiele um eine französische +Übersetzung zu erweitern, könnten wir einfach eine Datei +MyTextResource_fr.properties anlegen +und ihr folgenden Inhalt geben: + +

+Hi=Salut
+To=monde francais
+
+ + +

+Listing 17.14 würde +nun folgende Ausgabe erzeugen: + +

+de_DE: Hallo, Welt
+de_CH: Grüezi, Schweiz
+en_US: Hello, World of English
+fr_FR: Salut, monde francais
+
+ +
+ + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 +
 <<  +  <   +  >   + >>  + API  +© 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de +
+ + + -- cgit v1.2.3