Formatierung von Daten Nachdem die grundsätzliche Funktionsweise der Internationalisierung und die Isolierung von Daten betrachtet wurden, wird in diesem Abschnitt erklärt, wie Zahlen, Währungen, Datumsangaben, Zeitangaben und Text formatiert werden kann. Da derartige Datenelemente vom Endbenutzer verwendet werden, muss das jeweilige Format mit den verschiedenen kulturellen Konventionen konform sein. Zahlen und Währungen Programme operieren auf Zahlen in einer Art und Weise, die grundsätzlich unabhängig von einer Localen ist. Vor der Ausgabe einer Zahl muss daher ein Programmteil durchlaufen werden, der eine Zahl in einen String konvertiert, so dass ein Locale-sensitives Format erzeugt wird. Während bspw. im amerikanischen Raum das Zahlenformat mit Punkt (1234.56) verwendet wird, wird in Deutschland meist das Format mit Komma (1234,56) benutzt. Indem man die Methoden aufruft, die von der Klasse NumberFormat zur Verfügung gestellt werden, können Zahlen, Währungen und Prozentangaben entsprechend einer Localen formatiert werden. Problematisch ist allerdings, dass das NumberFormat unter Umständen die selbst spezifizierte Locale nicht unterstützt. Es kann aber leicht festgestellt werden, welche Definition der Localen von der Klasse NumberFormat unterstützt wird, indem die Methode getAvailableLocales folgendermaßen aufgerufen wird: Locale[] locales = NumberFormat.getAvailableLocales(); Wenn NumberFormat die jeweils benötigte Locale nicht unterstützt, kann ein eigenes Format definiert werden. Dies wird im Folgenden detailliert erläutert. Die NumberFormat-Methoden können weiterhin dazu verwendet werden, primitive Zahlentypen, wie bspw. float oder double und ihre entsprechenden Objekttypen (Float und Double), zu formatieren. Das folgende Beispiel formatiert eine Double-Zahl entsprechend einer Localen. Indem die getNumberInstance-Methode aufgerufen wird, kann eine Locale-spezifische Instanz des NumberFormats erzeugt werden. Die Formatierungsmethode akzeptiert hierbei Double als Argument und gibt einen String zurück, der die formatierte Zahl enthält: Double Preis = new Double(12.99); NumberFormat zahlenFormatierer; String PreisText; zahlenFormatierer = NumberFormat.getNumberInstance(derzeitigeLocale); PreisText = zahlenFormatierer.format(Preis); System.out.println(PreisText + " " + derzeitigeLocale.toString()); Die Ausgabe dieses Beispiels illustriert, wie das Format mit der jeweiligen Localen variiert: 12,99 de_DE 12.99 en_US Die Formatierung von Währungen erfolgt in ähnlicher Weise wie die von Zahlen. Hierzu ist die Methode getCurrencyInstance zu verwenden, die einen String zurückliefert, der die formatierte Zahl und eine Währungsangabe enthält. Das folgende Beispiel illustriert dies: Double waehrung = new Double(12.99); NumberFormat waehrungsFormatierer; String waehrungsText; waehrungsFormatierer = NumberFormat.getCurrencyInstance(derzeitigeLocale); waehrungsText = waehrungsFormatierer.format(waehrung); System.out.println(waehrungsText + " " + derzeitigeLocale.toString()); Nach dem Aufruf ergibt sich die folgende Ausgabe: 12,99 DM de_DE $12.99 en_US Die Formatierung von Prozentangaben erfolgt analog mittels der Methode getPercentInstance. Selbstdefinierte Formate Zur Formatierung von Dezimalzahlen und damit zu deren Umsetzung in Locale-spezifische Strings kann die Klasse DecimalFormat verwendet werden. Diese Klasse ermöglicht die Kontrolle der Anzeige führender und folgender Nullen, von Präfixen und Suffixen, von Gruppentrennzeichen (bspw. Punkt oder Komma in Tausenderangaben) und von Dezimaltrennzeichen. Wenn derartige Formatierungssymbole verändert werden sollen, muss DecimalFormatSymbols zusammen mit der Klasse DecimalFormat verwendet werden. Diese beiden Klassen bieten eine erhebliche Flexibilität hinsichtlich der Formatierung von Zahlen an, können aber Programme auch sehr komplex machen. Es empfiehlt sich daher, anstelle von DecimalFormat und DecimalFormatSymbols die Klasse NumberFormat so oft wie möglich einzusetzen. Die Formateigenschaften von DecimalFormat werden stets mit einem Muster-String angegeben. Das Muster bestimmt hierbei, wie die formatierte Zahl aussehen soll. Das folgende Beispiel generiert eine Formatierung, indem ein Muster-String nach dem DecimalFormat-Konstruktor durchsucht wird. Die Methode erwartet einen Wert vom Typ double als Argument und erzeugt eine formatierte Zahl, die als String zurückgegeben wird. Mögliche Ausgaben dieses Beispiels sind in Tab. 6-3 dargestellt. DecimalFormat formatierer= new DecimalFormat(muster); String output = formatierer.format(wert); System.out.println(wert + " " + muster + " " + output);
Wert | Muster | Ausgabe | Erläuterung
111111.111 | ###,###.### | 111,111.111 | Das Doppelkreuz repräsentiert jeweils eine Stelle der Zahl, das Komma repräsentiert den Gruppenseparator und der Punkt den Dezimalseparator.
111111.111 | ###.## | 111111.11 | Ein Abschneiden von Nachkommastellen wird durch eine Rundung durchgeführt.
111.11 | 000000.000 | 000111.110 | Dieses Muster spezifiziert die Anzahl führender und folgender Nullen, da anstelle des Doppelkreuzes das Null-Symbol verwendet wird.
111111.111 | $###,###.### | $111,111.111 | Das erste Zeichen des Musters ist das Dollarzeichen. Dieses muss der ersten Ziffer unmittelbar vorangehen.
Tab. 6.3: Selbstdefinierte Zahlenmuster Ziel des vorangegangenen Beispiels ist die Generierung eines DecimalFormat-Objekts für eine Standard-Locale. Soll ein derartiges Objekt für eine Locale generiert werden, die keine Standard-Locale ist, so muss das Objekt als NumberFormat instantiiert und anschließend in den Typ DecimalFormat umgewandelt werden. Das so entstandene Objekt formatiert dann die Muster in einer Locale-sensitiven Art und Weise: NumberFormat nf = NumberFormat.getNumberInstance(l); DecimalFormat df = (DecimalFormat) nf; df.applyPattern(muster); String output = df.format(wert); System.out.println(muster + " " + output + " " + l.toString()); Bisher wurden solche Muster betrachtet, die der US-amerikanischen Konvention folgten. Symbole, wie bspw. das Dezimaltrennzeichen, der Gruppenseparator und das Minuszeichen können mit der Klasse DecimalFormatSymbols verändert werden. Im nächsten Beispiel wird mittels DecimalFormatSymbols einer Zahl ein ungewöhnliches Format zugewiesen. Hierzu werden Aufrufe der Methoden setDecimalSeparator, setGroupingSeparator und setGroupingSize verwendet. DecimalFormatSymbols neueSymbole= new DecimalFormatSymbols(derzeitigeLocale); neueSymbole.setDecimalSeparator('*'); neueSymbole.setGroupingSeparator('#'); String muster = "#.#[],###"; DecimalFormat neuerFormatierer = new DecimalFormat(muster,neueSymbole); neuerFormatierer.setGroupingSize(4); String komisch= neuerFormatierer.format(11111.111); System.out.println(komisch); Als Ausgabe ergibt sich in diesem Fall 1#1111*111. Formatierung von Datum und Zeit Date-Objekte werden in Java dazu verwendet, Datums- und Zeitangaben zu repräsentieren. Wie in den vorangegangenen Beispielen muss ein Datumsobjekt vor der Ausgabe in einen String konvertiert werden. Die Formatierung ist hierbei in großem Maße kulturabhängig. In Java wird die DateFormat-Klasse dazu verwendet, Datums- und Zeitangaben in einer Locale-sensitiven Art und Weise zu formatieren. Wie bisher auch unterstützt DateFormat nicht alle Locale-Definitionen. Zur Feststellung, welche Localen unterstützt werden, kann die bereits beschriebene Methode getAvailableLocales verwendet werden. Die Formatierung von Datumsangaben mittels der Klasse DateFormat erfolgt in zwei Schritten. Zuerst wird ein Formatierer mittels der Methode getDateInstance generiert. Anschließend wird die Formatierungsmethode aufgerufen, die einen String mit dem formatierten Datum zurückliefert. Das folgende Beispiel illustriert dieses Vorgehen: Date heutigesDatum; String datumText; DateFormat datumsFormatierer; datumsFormatierer = DateFormat.getDateInstance(DateFormat.DEFAULT, derzeitigeLocale); heutigesDatum= new Date(); datumText = datumsFormatierer.format(heutigesDatum); System.out.println(datumText + " " + derzeitigeLocale.toString()); Die Ausgabe, die hier erzeugt wird, variiert mit der Localen: 1.2.1999 de_DE 01-Feb-99 en_US Dieses Beispiel wurde mit dem DEFAULT-Formatierungsstil ausgeführt, der einer der Stile ist, die in der Klasse DateFormat vordefiniert sind. Weitere Stile sind SHORT, MEDIUM, LONG und FULL. Tab. 6-4 zeigt, wie sich die Datumsangaben in Abhängigkeit vom gewählten Stil verändern.
Stil | Deutsche Locale | US-Locale
DEFAULT | 10. Feb 99 | 10-Feb-99
SHORT | 10/02/99 | 02/10/99
MEDIUM | 10. Feb 99 | 10-Feb-99
LONG | 10. Februar 1999 | February 10, 1999
FULL | Mittwoch, 10. Februar 1999 | Wednesday, February 10, 1999
Tab. 6.4: Datumsstile in Java Da Date-Objekte sowohl Datums- als auch Zeitangaben repräsentieren, ist die Formatierung von Zeitangaben analog. Es muss allerdings die Methode getTimeInstance verwendet werden. Tab. 6-5 zeigt die Stile, die in Java für Zeitangaben zur Verfügung stehen.
Stil | Deutsche Locale | US-Locale
DEFAULT | 15:58:45 | 3:58:45 PM
SHORT | 15:58 | 3:58 PM
MEDIUM | 15:58:45 | 3:58:45 PM
LONG | 3:58:45 GMT+02:00 | 3:58:45 PM PDT
FULL | 15.58 Uhr GMT+02:00 | 3:58:45 o'clock PM PDT
Tab. 6.5: Zeitangaben in Java Zur simultanen Darstellung von Datum und Zeit in einem String kann wie folgt vorgegangen werden: DateFormat formatierer = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, derzeitigeLocale); Meist reichen die in Java vordefinierten Formate für Datums- und Zeitangaben aus. Soll dennoch eine Veränderung erfolgen, so kann mit Hilfe von SimpleDateFormat wie folgt vorgegangen werden: Zur Formatierung muss ein SimpleDateFormat-Objekt generiert werden, indem ein Muster-String angegeben wird. Dieses Vorgehen ist analog zur Formatierung von Zahlen und Währungen. Der Inhalt des Muster-Strings bestimmt dann das Format von Datum und Zeit. Das folgende Beispiel formatiert eine Datums- und eine Zeitangabe mit Hilfe eines Muster-Strings, der an den SimpleDateFormat-Konstruktor übergeben wird. Der zurückgegebene String enthält dann Datum und Zeit im gewünschten Format. Date heute; String output; SimpleDateFormat formatierer; formatierer = new SimpleDateFormat(muster, derzeitigeLocale); heute = new Date(); output = formatierer.format(heute); System.out.println(muster + " " + output);

Muster | Ausgabe
dd.MM.yy | 10.02.99
yyyy.MM.dd G 'at' hh:mm:ss z | 1999.02.10 AD at 06:15:55 PDT
EEE, MMM d, ''yy | Wed, Feb 10, '99
h:mm a | 6:15 PM

Tab. 6.6: Datums- und Zeitformatierung in Java Tab. 6-6 zeigt verschiedene Formatierungsarten, die vom Benutzer als Muster spezifiziert wurden. Die Klasse SimpleDateFormat ist Locale-sensitiv. Wird SimpleDateFormat ohne einen Locale-Parameter instantiiert, so werden Datum und Zeit nach der Standard-Localen formatiert. Aus diesem Grund bestimmen sowohl Muster als auch Locale das Ausgabeformat. Für dasselbe Muster kann daher SimpleDateFormat verschiedene Formatierungen erzeugen, wenn sich die Locale ändert. Die format-Methode der Klasse SimpleDateFormat gibt einen String zurück, der aus Zahlen und Symbolen besteht. Wenn die in der Klasse SimpleDateFormat gekapselten Symbole den Anforderungen des Entwicklers nicht entsprechen, können sie mit Hilfe der Klasse DateFormatSymbols verändert werden. Derart können neue Namen für Monate, Wochentage und Zeitzonen festgelegt werden.Tab. 6-7 zählt die Methoden der Klasse DateFormatSymbols auf, mit deren Hilfe die Symbole verändert werden können.

Methode | Beispiel
setAmPmStrings | PM
setEras | AD
setMonths | Dezember
setShortWeekdays | Die
setWeekdays | Dienstag
setZoneStrings | PST

Tab. 6.7: Methoden der Klasse DateFormatSymbols Das folgende Beispiel ruft die Methode setWeekdays auf, um alle Wochentage von Kleinschreibung in Großschreibung umzuändern. Das erste Element des Array-Arguments von setWeekdays ist ein Null-String. Hierdurch enthält der Array ein Element anstatt leer initialisiert zu werden. Der Konstruktor der Klasse SimpleDateFormat akzeptiert das so modifizierte DateFormatSymbols-Objekt als Argument. Date heute; String resultat; SimpleDateFormat formatierer; DateFormatSymbols symbole; String[] standardTage; String[] geaenderteTage; symbole = new DateFormatSymbols(new Locale("de","DE")); standardTage = symbole.getWeekdays(); for (int i = 0; i < standardTage.length; i++) { System.out.print(standardTage[i] + " "); } System.out.println(); String[] grosseTage = {"", "SONNTAG", "MONTAG", "DIENSTAG", "MITTWOCH", "DONNERSTAG", "FREITAG", "SAMSTAG"}; symbole.setWeekdays(grosseTage); geaenderteTage = symbole.getWeekdays(); for (int i = 0; i < geaenderteTage.length; i++) { System.out.print(geaenderteTage[i] + " "); } System.out.println(); System.out.println(); formatierer = new SimpleDateFormat("E", symbols); heute = new Date(); resultat = formatierer.format(heute); System.out.println(resultat); Textinhalte Ein wichtiges Anwendungsgebiet der Internationalisierung ist das Angebot von Statusnachrichten in der jeweiligen Landessprache. Es wurden bereits die Mechanismen diskutiert, die übersetzbare Texte Locale-spezifisch isolieren. Üblicherweise ist dazu ein Text-String an ein ResourceBundle-Objekt zu übergeben. Wenn diese Daten allerdings variabel sind, müssen vor der Übersetzung einige weitere Schritte ausgeführt werden. Unter einer Verbundnachricht versteht man Daten, die variable Komponenten enthalten. Soll bspw. der Satz „Unsere Datenbank Adressdatenbank enthält derzeit 400 Einträge" internationalisiert werden, so ist sowohl die Anzahl der Einträge als auch der Name der Datenbank variabel, wenn mehrere Datenbanken verwendet werden. Eine mögliche Umsetzung dieses Satzes könnte darin bestehen, Satzelemente mit Variablen zu kombinieren: int anzahlEintraege; String datenbankName; ResourceBundle textBundle; String nachricht = textBundle.getString("einleitung") + textBundle.getString("datenbankName") + textBundle.getString("zwischentext")+ anzahlEintraege.toString() + textBundle.getString("endText"); Problematisch ist allerdings, dass dieser Satzaufbau zwar im Deutschen, nicht aber in vielen anderen Sprachen anwendbar ist. Der eigentliche Satzaufbau ist in diesem Beispiel fest vorgegeben und daher schlecht internationalisierbar. Zur Vermeidung dieses Problems sind in Java spezielle Mechanismen zu verwenden, die Verbundnachrichten mit Hilfe der Klasse MessageFormat verarbeiten. Es sei aber darauf hingewiesen, dass in Verbundnachrichten der eigentliche Text fragmentiert wird. Derartige Texte sind schwierig zu übersetzen und damit auch mit Kosten verbunden. Verbundnachrichten sollten daher nur eingesetzt werden, wenn es nicht zu vermeiden ist. Zur Internationalisierung einer Verbundnachricht müssen folgende Schritte durchlaufen werden, in denen die Klasse MessageFormat verwendet wird: Identifikation der Variablen, die in der Verbundnachricht verwendet werden Im oben betrachteten Beispiel werden der Name einer Datenbank sowie die Zahl ihrer Einträge als Variablen verwendet. Isolierung des Textmusters in einem ResourceBundle-Objekt Die Verbundnachricht sollte folgendermaßen in einem ResourceBundle-Objekt namens TextBundle gespeichert werden: ResourceBundle texte = ResourceBundle.getBundle("TextBundle",derzeitigeLocale); Dieses ResourceBundle-Objekt wird für jede Locale in einem Properties File gespeichert. Da das ResourceBundle-Objekt TextBundle heißt, muss das Properties File für die deutsche Locale TextBundle_de_DE.properties heißen. Der Inhalt dieser Datei sieht folgendermaßen aus: muster = Unsere Datenbank {0} enthält derzeit {1,number, integer} Einträge. Datenbank= Adressdatenbank Die erste Zeile des Properties Files enthält das Textmuster. Hierbei wird jede Variable der Nachricht durch ein Argument ersetzt, das in geschweiften Klammern steht. Jedes Argument beginnt mit einer Zahl, die auch als Argumentnummer bezeichnet wird, und die dem Elementindex entspricht, mit dem in einer Objektliste auf das Argument zugegriffen werden kann. Die Argumentnummern müssen dabei in keiner speziellen Reihenfolge vorliegen. Die einzige Bedingung ist, dass die Argumentnummer ein Gegenstück in der Liste der Argumentwerte findet. In diesem Fall wird durch den Wert 0 ein String angegeben, der den Namen der Datenbank enthält und durch den Wert 1 ein number-Objekt, das durch die Angabe des Typs integer weiter festgelegt wird. Setzen der Nachrichtenargumente Im Folgenden muss jedem Argument, das Teil des Musters ist, ein Wert zugewiesen werden. Die Indizes der Elemente im Array texteArgumente entsprechen hierbei der Argumentnummer des Musters. Das ganzzahlige Element mit Index 1 entspricht bspw. dem Argument {1,number,integer} im angegebenen Muster. Da das String-Objekt übersetzt werden muss, wird es als Element 0 mittels der getString-Methode aus dem ResourceBundle-Objekt geladen: Object[] texteArgumente = { texte.getString("Datenbank"), new Integer(7) }; Erzeugung der Formatierung Im vierten Schritt wird ein MessageFormat-Objekt erzeugt. Hierzu ist die Locale zu setzen, da die Nachricht ein Number-Objekt enthält, das in einer Locale-sensitiven Art und Weise formatiert werden muss: MessageFormat formatierer = new MessageFormat(""); formatierer.setLocale(derzeitigeLocale); Formatierung der Nachricht gemäß Nachrichtenmuster und Argumente Im fünften Schritt wird ersichtlich, wie Muster, Nachrichtenargumente und Formatierer zusammenarbeiten. Zuerst wird mittels der getString-Metode der Muster-String aus dem ResourceBundle-Objekt geladen. Schlüssel dieses Musters ist muster. Der Muster-String wird anschließend mittels der applyPattern-Methode an den Formatierer übergeben. Daraufhin wird die Nachricht formatiert, indem der Nachrichten-Array mit der Methode format formatiert wird. Der von format zurückgegebene String kann dann angezeigt werden: formatierer.applyPattern(texte.getString("muster")); String ausgabe = formatierer.format(texteArgumente); Das gesamte Programm sieht wie folgt aus: import java.util.*; import java.text.*; public class MessageFormatBeispiel { static void anzeige(Locale derzeitigeLocale) { ResourceBundle texte = ResourceBundle.getBundle("texteBundle", derzeitigeLocale); Object[] texteArgumente = { texte.getString("Datenbank"),new Integer(7) } MessageFormat formatierer = new MessageFormat(""); formatierer.setLocale(derzeitigeLocale); formatierer.applyPattern(texte.getString("muster ")); String ausgabe = formatierer.format(texteArgumente); System.out.println(ausgabe); } static public void main(String[] args) { anzeige(new Locale("de", "DE")); System.out.println(); anzeige(new Locale("en", "US")); } } In vielen Sprachen sind Singular und Plural eines Wortes verschieden. Dies wirft dann Probleme auf, wenn Verbundtexte verwendet werden, die Textvariablen enthalten. Ein Beispiel hierfür ist der Satz „2 Angestellte arbeiten in unserer Firma", wobei der Satzteil „2 Angestellte arbeiten" variabel sei. Zur Verarbeitung derartiger Textkomponenten kann die Klasse ChoiceFormat verwendet werden, die wiederum auf die Klasse MessageFormat zurückgreift, die im letzten Abschnitt eingeführt wurde. Zur Verarbeitung variabler Textelemente sind die folgenden Schritte auszuführen, die stark denjenigen ähneln, die im letzten Abschnitt besprochen wurden: Definition eines Nachrichtenmusters Zuerst werden wiederum die Variablen des Textes identifiziert, im Beispiel also „2 Angestellte arbeiten." Anschließend werden die Textvariablen durch Argumente ersetzt, indem ein Muster erzeugt wird, das das MessageFormat-Objekt verwenden kann: {0} in unserer Firma. Die Verarbeitung des Arguments {0} ist komplex, da dieses Argument mit der Anzahl der Beschäftigen variiert. Um den Satz zur Laufzeit zu generieren, muss die Anzahl der Beschäftigten auf einen String abgebildet werden. Wird nur ein Angestellter beschäftigt, so muss der String "Ein Angestellter arbeitet" lauten. Diese Art der Abbildung wird durch die Klasse ChoiceFormat realisiert. Wenn in der Firma mehrere Angestellte arbeiten, so beinhaltet der Satz eine Zahl, anderenfalls das Wort "Ein". Mittels der Klasse MessageFormat ist es möglich, eine Zahl in einen Satz einzufügen. Erzeugung eines ResourceBundles Zur Übersetzungsfähigkeit muss der Text in einem ResourceBundle-Objekt isoliert werden: ResourceBundle bundle = ResourceBundle.getBundle("AuswahlBundle",derzeitigeLocale ) ; Im Beispiel werden die Werte des ResourceBundle-Objekts in Properties Files gespeichert. Die Datei AuswahlBundle_de_DE.properties enthält daher die folgenden Zeilen: muster = {} in unserer Firma. einAngestellter = Ein Angestellter arbeitet mehrAngestellte = {1} Angestellte arbeiten Der Inhalt dieses Properties Files zeigt bereits, wie der Text erzeugt und formatiert werden wird. Die erste Zeile enthält gemäß Schritt 1 das Muster für MessageFormat. Die anderen Zeilen enthalten Satzteile, die das Argument {0} des Musters ersetzen. Der Satzteil mit dem Schlüssel mehrAngestellte enthält das Argument {1}, das durch die entsprechende Zahl der Angestellten ersetzt wird. Erzeugung der Textformatierung. Im dritten Schritt wird MessageFormat instantiiert und die Locale gesetzt: MessageFormat textForm = new MessageFormat(""); textForm.setLocale(derzeitigeLocale); Generierung einer Auswahlformatierung Das ChoiceFormat-Objekt erlaubt die Auswahl eines bestimmten Strings in Abhängigkeit von einer Zahl des Typs double. Der Wertebereich dieser Zahl und die String-Objekte, auf die sie abgebildet werden kann, werden in Arrays spezifiziert: double[] angestellteWerte = {0,1}; String [] angestellteStrings= { bundle.getString("einAngestellter"), bundle.getString("mehrAngestellte") }; ChoiceFormat bildet jedes Element des Arrays auf das Element des String-Arrays ab, das denselben Index hat. Im Beispiel wird der Wert 0 auf den String abgebildet, der zurückgegeben wird, wenn die Methode bundle.getString("einAngestellter") aufgerufen wird. Der double-Wert und der String-Array werden angegeben, wenn ChoiceFormat instantiiert wird: ChoiceFormat auswahlForm = new ChoiceFormat(angestellteWerte, angestellteStrings); Anwendung des Musters Im ersten Schritt wurde bereits ein Muster erzeugt. Dieses wird nun aus dem ResourceBundle-Objekt eingeladen und auf das MessageFormat-Objekt angewendet: String muster = bundle.getString("muster"); textForm.applyPattern(muster); Zuweisung der Formate Im sechsten Schritt wird das in Schritt vier erzeugte ChoiceFormat-Objekt dem MessageFormat-Objekt zugewiesen: Format[] formate = {auswahlForm, NumberFormat.getInstance()}; textForm.setFormats(formate); Die setFormats-Methode weist den Argumenten des Nachrichtenmusters Format-Objekte zu. Vor dem Aufruf der setFormats-Methode muss die Methode applyPattern aufgerufen werden. Argumente des Format-Objekts sind auswahlForm, das auf das Element {0} abgebildet wird und die Methode NumberFormat.getInstance(), die auf das Element {1} abgebildet wird. Setzen der Argumente und Formatierung der Nachricht Zur Laufzeit weist das Programm die Variablen dem Array von Argumenten zu, der an das MessageFormat-Objekt übergeben wird. Die Elemente des Arrays entsprechen hierbei den Argumenten des Musters. Der Eintrag textArgument[1] entspricht daher dem Musterargument {1}, das eine Zahl enthält, die die Anzahl der Beschäftigten wiedergibt. Im sechsten Schritt wurde dem Argument {0} des Musters ein ChoiceFormat-Objekt zugewiesen. Die Zahl, die textArgument[0] zugewiesen wird, bestimmt daher, welcher String vom ChoiceFormat-Objekt ausgewählt wird. Object[] textArgumente = {null, null}; for (int angestellteZahl = 0; angestellteZahl < 3; angestellteZahl++) { textArgumente[0] = new Integer(angestellteZahl); textArgumente[1] = new Integer(angestellteZahl); String resultat = textForm.format(textArgumente); System.out.println(resultat); } Das vollständige Programm lautet wie folgt: import java.util.*; import java.text.*; public class ChoiceFormatBeispiel { static void anzeige (Locale derzeitigeLocale) { ResourceBundle bundle = ResourceBundle.getBundle("AuswahlBundle", derzeitigeLocale); MessageFormat textForm = new MessageFormat(""); textForm.setLocale(derzeitigeLocale); double[] angestellteWerte = {0,1}; String [] angestellte = { bundle.getString("einAngestellter"), bundle.getString("mehrAngestellte") } ChoiceFormat auswahlForm = new ChoiceFormat(angestellteWerte, angestellte); String muster = bundle.getString("muster"); Format[] formate= {auswahlForm, NumberFormat.getInstance()}; textForm.applyPattern(muster); textForm.setFormats(formate); Object[] textArguments = {null, null}; for (int angestellteZahl = 0; angestellteZahl < 4; angestellteZahl++) { textArguments[0] = new Integer(angestellteZahl); textArguments[1] = new Integer(angestellteZahl); String resultat = textForm.format(textArgumente); System.out.println(resultat); } } static public void main(String[] args) { anzeige(new Locale("de", "DE")); System.out.println(); anzeige(new Locale("en", "US")); } }