This article is currently in the process of being translated into German (~99% done).
The CultureInfo class
In den letzten Artikeln haben wir darüber gesprochen, wie nützlich die CultureInfo-Klasse ist, wenn Sie die volle Kontrolle darüber benötigen, wie Zahlen und Daten in Ihrer Anwendung angezeigt werden. Wir haben auch darüber gesprochen, wie Sie überprüfen und ändern können, welche Kultur Ihre Anwendung als Fallback verwenden soll. Mit all dem ist es an der Zeit, tiefer in die eigentliche CultureInfo-Klasse einzutauchen, um zu sehen, wie wir sie voll ausnutzen können.
Eine kurze Erinnerung, bevor wir anfangen: Die CultureInfo-Klasse ist Teil des System.Globalization-Namensraums, also importieren Sie sie, wenn Sie die Beispiele ausprobieren:
using System.Globalization;
Neutrale und spezifische Kulturen
In den vorherigen Beispielen in diesem Kapitel haben wir nur bestimmte Kulturen verwendet, d.h. eine Kultur, die sowohl eine Sprache als auch ein Land/eine Region spezifiziert. Ein Beispiel dafür ist die en-US-Kultur, die eindeutig besagt, dass die gewünschte Sprache Englisch und die Region die USA sein sollten. Eine Alternative dazu ist die en-GB-Kultur, die die gleiche Sprache (Englisch), aber mit Großbritannien als Region anstelle der USA ist.
Es wird Zeiten geben, in denen diese Unterschiede wichtig sind. In diesem Fall sollten diese regionsspezifischen Versionen der CultureInfo-Klasse verwendet werden. Andererseits wird es auch Situationen geben, in denen Englisch nur eine Sprache ist und Sie diese Sprache nicht an ein bestimmtes Land oder eine bestimmte Region binden wollen. Dazu definiert das .NET-Framework sogenannte neutrale Kulturen, die nur eine Sprache angeben. Tatsächlich erben sowohl en-US als auch en-GB von einer solchen neutralen Kultur (was vollkommen sinnvoll ist, da sie dieselbe Sprache verwenden!) und Sie können von der Parent-Eigenschaft darauf zugreifen. Lassen Sie mich das an einem Beispiel verdeutlichen:
CultureInfo enGb = new CultureInfo("en-GB");
CultureInfo enUs = new CultureInfo("en-US");
Console.WriteLine(enGb.DisplayName);
Console.WriteLine(enUs.DisplayName);
Console.WriteLine(enGb.Parent.DisplayName);
Console.WriteLine(enUs.Parent.DisplayName);
Kein sehr nützliches Beispiel, aber es soll einen besseren Einblick in die interne Struktur der CultureInfo-Klasse geben. Die Ausgabe sollte so aussehen:
English (United Kingdom)
English (United States)
English
English
Die richtige CultureInfo
Aus unseren vorherigen Beispielen haben wir gesehen, dass wir die gewünschte CultureInfo-Klasse holen können, indem wir die Sprach-Land/Region-Kennung an den Konstruktor der Klasse übergeben. Da man aber, wie oben beschrieben, nach einer neutralen Kultur sucht, kann man auch einfach eine Sprachkennung eingeben:
CultureInfo en = new CultureInfo("en");
Das .NET-Framework gibt dann eine englische, regionenneutrale CultureInfo-Instanz zurück. Eine vollständige Liste der möglichen Sprach- und/oder Sprach-Land/Regionskennzeichen finden Sie in der MSDN-Dokumentation.
Eine weitere Möglichkeit, eine bestimmte Kultur zu identifizieren, ist die sogenannte LCID (LoCale ID). Man findet sie als Eigenschaft auf bestehenden CultureInfo-Instanzen, aber wenn man die ID kennt, kann man sie auch verwenden, um ein CultureInfo-Objekt zu instanziieren. Zum Beispiel ist die LCID für en-US 1033:
CultureInfo enUs = new CultureInfo(1033);
In den meisten Fällen ist es jedoch viel einfacher, den Bezeichner für die Sprache-Land/die Region zu verwenden, wie bereits gezeigt.
Eine Liste der verfügbaren Kulturen
Wir können nun eine bestimmte Kultur erhalten und für verschiedene Zwecke verwenden, aber vielleicht benötigen Sie eine Liste der verfügbaren Kulturen, z.B. um dem Benutzer die Auswahl einer Sprache und/oder eines Landes/Region zu ermöglichen. Glücklicherweise macht das .NET-Framework das auch für uns einfach - hier ein Beispiel:
CultureInfo[] specificCultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
foreach (CultureInfo ci in specificCultures)
Console.WriteLine(ci.DisplayName);
Console.WriteLine("Total: " + specificCultures.Length);
Wie Sie an der ersten Zeile des Codes erkennen können, verwende ich die statische Methode GetCultures der CultureInfo-Klasse, um eine Liste der Kulturen zu erhalten. Sie benötigt den CultureTypes-Parameter, der angibt, nach welcher Art von Kulturen Sie suchen. In diesem Fall habe ich nach den spezifischen Kulturen gefragt, die, wie bereits erwähnt, sowohl an eine Sprache als auch an ein Land/eine Region gebunden sind. Das ist übrigens eine ziemlich lange Liste - auf diesem Computer bekomme ich insgesamt 563 verfügbare Kulturen!
Aber vielleicht interessieren Sie sich mehr für die neutralen Kulturen? Das wäre beispielsweise sinnvoll, wenn Sie eine Liste der verfügbaren Sprachen erstellen würden, ohne sich darum zu kümmern, zu welchem Land oder welcher Region sie gehören. Dies ist so einfach wie das Ändern des CultureTypes-Parameters:
CultureInfo[] neutralCultures = CultureInfo.GetCultures(CultureTypes.NeutralCultures);
foreach (CultureInfo ci in neutralCultures)
Console.WriteLine(ci.DisplayName);
Console.WriteLine("Total: " + neutralCultures.Length);
Dabei werden Sie auch sehen, dass es nicht ganz so viele neutrale Kulturen gibt, wie es spezifische Kulturen gibt - auf meiner Computer/.NET Framework-Version sind es insgesamt 280 neutrale Kulturen.
Wichtige Eigenschaften & Methoden von CultureInfo
Sobald Sie eine Instanz der CultureInfo-Klasse haben, erhalten Sie sofort Zugriff auf eine sehr breite Palette von verwendbaren Eigenschaften und Methoden. Diese Mitglieder können Ihnen helfen, viele nützliche Dinge in Bezug auf die Kultur zu erreichen - lassen Sie uns einen Blick auf einige von ihnen werfen!
DateTimeFormat
Mit der DateTimeFormat-Eigenschaft erhalten Sie Zugriff auf Informationen darüber, wie Datum und Uhrzeit formatiert werden sollen, sowie viele nützliche Informationen über den Kalender für die jeweilige Kultur. Ein schönes Beispiel dafür sind die Eigenschaften FirstDayOfWeek und CalendarWeekRule - sie können Ihnen sagen, an welchem Tag eine Woche beginnt (normalerweise Sonntag oder Montag) und wie die erste Kalenderwoche des Jahres entschieden wird (z.B. nur der erste Tag oder die erste volle Woche):
CultureInfo enUs = new CultureInfo("en-US");
Console.WriteLine("First day of the: " + enUs.DateTimeFormat.FirstDayOfWeek.ToString());
Console.WriteLine("First calendar week starts with: " + enUs.DateTimeFormat.CalendarWeekRule.ToString());
Ändern Sie die CultureInfo-Instanz auf Ihre eigene Kultur oder eine andere Kultur, um zu sehen, wie diese Eigenschaften variieren!
Interessante ist auch, dass man mit Hilfe von Eigenschaften wie MonthNames und Methoden wie GetMonthName() Informationen über die Monats- und Tagesnamen für die jeweilige Kultur erhalten kann. Hier ist ein kurzes Beispiel:
CultureInfo enUs = new CultureInfo("en-US");
foreach (string monthName in enUs.DateTimeFormat.MonthNames)
Console.WriteLine(monthName);
Console.WriteLine("Current month: " + enUs.DateTimeFormat.GetMonthName(DateTime.Now.Month));
Und genau dasselbe kann für Tage mit der DayNames-Eigenschaft und der GetDayName()-Methode erreicht werden:
CultureInfo enUs = new CultureInfo("en-US");
foreach (string dayName in enUs.DateTimeFormat.DayNames)
Console.WriteLine(dayName);
Console.WriteLine("Today is: " + enUs.DateTimeFormat.GetDayName(DateTime.Now.DayOfWeek));
Es gibt viele weitere nützliche Eigenschaften und Methoden in der Eigenschaft DateTimeFormat, z.B. DateSeparator, YearMonthPattern und so weiter. Schauen Sie selbst - es könnte sehr wohl eine Lösung für Ihr Datum/Uhrzeit-Problem darin versteckt sein: DateTimeFormatInfo-Dokumentation.
NumberFormat
Genauso wie das DateTimeFormat Informationen über Daten enthält, können Sie über die NumberFormat-Eigenschaft auf Informationen darüber zugreifen, wie die jeweilige Kultur mit Zahlen umgeht. Diese Informationen werden jedes Mal verwendet, wenn Sie nach einer visuellen Darstellung einer Zahl fragen, z.B. wenn Sie sie in einen String konvertieren und in die Konsole schreiben, aber Sie können auch selbst auf die Informationen zugreifen, indem Sie die Eigenschaften und Methoden der NumberFormat-Eigenschaft verwenden - hier ist ein Beispiel:
CultureInfo enUs = new CultureInfo("en-US");
Console.WriteLine(enUs.DisplayName + ":");
Console.WriteLine("NumberGroupSeparator: " + enUs.NumberFormat.NumberGroupSeparator);
Console.WriteLine("NumberDecimalSeparator: " + enUs.NumberFormat.NumberDecimalSeparator);
CultureInfo deDe = new CultureInfo("de-DE");
Console.WriteLine(deDe.DisplayName + ":");
Console.WriteLine("NumberGroupSeparator: " + deDe.NumberFormat.NumberGroupSeparator);
Console.WriteLine("NumberDecimalSeparator: " + deDe.NumberFormat.NumberDecimalSeparator);
Wir verwenden die Eigenschaften NumberGroupSeparator und NumberDecimalSeparator, um Informationen darüber zu erhalten, wie eine Zahl angezeigt wird (z.B. 1,000.00 oder 1.000,00) für die englische und deutsche Kultur. Wenn Sie schauen, finden Sie passende Eigenschaften für Währungen (CurrencyGroupSeparator und CurrencyDecimalSeparator) sowie Prozentangaben (PercentGroupSeparator und PercentDecimalSeparator).
Apropos Währung, die NumberFormat-Eigenschaft kann Ihnen auch sagen, welches Symbol eine bestimmte Kultur verwendet, um einen Geldbetrag anzuzeigen - verwenden Sie einfach die CurrencySymbol-Eigenschaft:
CultureInfo enUs = new CultureInfo("en-US");
Console.WriteLine(enUs.DisplayName + " - currency symbol: " + enUs.NumberFormat.CurrencySymbol);
CultureInfo deDe = new CultureInfo("de-DE");
Console.WriteLine(deDe.DisplayName + " - currency symbol: " + deDe.NumberFormat.CurrencySymbol);
CultureInfo ruRu = new CultureInfo("ru-RU");
Console.WriteLine(ruRu.DisplayName + " - currency symbol: " + ruRu.NumberFormat.CurrencySymbol);
Alle diese Eigenschaften sind schön zu wissen, aber in den meisten Situationen, werden Sie nichts damit zu tun haben, da C# stillschweigend die Informationen verwenden wird, um Zahlen, Prozentsätze und Währungen für Sie zu formatieren, solange Sie den richtigen Format-String angeben, wenn Sie die Zahl in eine Zeichenfolge umwandeln.
Namen & Bezeichnungen
Zum Schluss noch ein Blick auf die Eigenschaften, die die CultureInfo-Instanz repräsentieren. Wir haben bereits einige davon verwendet, z.B. Name und DisplayName, aber wie funktionieren sie eigentlich? Zuerst ist hier eine Liste der verfügbaren Eigenschaften, die verwendet werden, um eine CultureInfo zu identifizieren:
- Name identifiziert eine CultureInfo im Sprachcode-Land/Regionalcode Format, z.B. "en-US" für Englisch in den USA, en-GB für Englisch in Großbritannien und so weiter. Wird kein Land/Region angegeben, wird nur der erste Teil zurückgegeben, z.B. "en" für Englisch.
- TwoLetterISOLanguageName macht so ziemlich dasselbe wie Name, gibt aber nur den Sprachcode zurück, unabhängig davon, ob ein Land/eine Region angegeben wurde oder nicht. Beispielsweise wird "en" sowohl für "en-US" als auch für "en-GB" zurückgegeben. Die zurückgegebenen Buchstaben sind in der Norm ISO 639-1 spezifiziert.
- ThreeLetterISOLanguageName funktioniert ähnlich wie TwoLetterISOLanguageName, gibt aber drei statt zwei Buchstaben zurück, wie von der Norm ISO 639-2 vorgegeben.
- EnglishName gibt den Namen der Sprache zurück (in Englisch). Wenn ein Land/eine Region angegeben wurde, wird diese in Klammern an das Ergebnis angehängt.
- NativeName gibt den Namen der Sprache zurück (in der von der CultureInfo-Instanz angegebenen Sprache). Wenn ein Land/eine Region angegeben wurde, wird diese in Klammern an das Ergebnis angehängt.
Zusammenfassung
Wie Sie der Länge dieses Artikels entnehmen können, ist der Umgang mit Kultur im Allgemeinen keine einfache Aufgabe. Zum Glück für uns macht es das .NET-Framework mit der CultureInfo-Klasse viel einfacher. Es wird in Ihrer gesamten Anwendung verwendet, wenn Sie Zahlen und Daten formatieren, aber es ist gut für Sie zu wissen, wie es funktioniert, so dass Sie das Verhalten bei Bedarf ändern können. Hoffentlich hat Ihnen dieser Artikel alles beigebracht, was Sie über die CultureInfo-Klasse wissen müssen.