Lokalisierung mit ASP .NET

Veröffentlicht: 23. Feb 2002 | Aktualisiert: 16. Jun 2004
Von Dariusz Parys

Gerade im Internet sollte eine Anwendung verschiedene Sprachen anbieten. Internationalisierung tut Not. Mehrsprachigkeit, Verarbeitung von unterschiedlichen Währungen und Datumsformaten – all dies sind Herausforderungen, denen man sich bei der Entwicklung einer globalen Anwendung stellen muss. Das Microsoft .NET Framework bietet in seiner Basis-Klassenbibliothek (BCL) eine Vielzahl von Klassen, die die Lokalisierung einer .NET-Anwendung unterstützen.

Auf dieser Seite

 Die Klasse CultureInfo
 Neutraler und regionaler Kulturcode
 Resource-Verwaltung
 Die Klasse ResourceManager
 Satellite Assemblies
 Design und eigene Web Controls
 Zusammenfassung

Die Klasse CultureInfo

Einige dieser Basisklassen nehmen in ihren Konstruktoren einen zusätzlichen Parameter vom Typ CultureInfo entgegen. CultureInfo enthält alle notwendigen Informationen wie etwa Sprache, Länder- beziehungsweise regionale Infos wie Zahlen- und Datumsformate.

Um eine Instanz von CultureInfo zu erzeugen, übergibt man dem Konstruktor als Parameter einen Kulturcode. Als Beispiel dient folgender Code:

... 
CultureInfo ci = new CultureInfo( "fr" ); 
... 

Die Zeile hat nun ein CultureInfo-Objekt erzeugt, das den Kulturcode "fr" als Parameter erhalten hat. Dieser Parameter gibt lediglich den sprachlichen Code an, enthält aber noch keine regionalen Informationen. Sprachlich weiß dieses Objekt, dass wir französisch sprechen, aber welche Zahlen- und Datumsformate benutzt werden sollen, ist dem Objekt noch nicht bekannt. Es handelt sich hier um einen neutralen Kulturcode.

Wollen wir nun für den ausführenden Thread das Datum im gültigen Format für den Raum Frankreich ausgeben, so müssen wir ein CultureInfo-Objekt mit dem Kulturcode "fr-FR" erstellen. In einer simplen Konsolenanwendung eingesetzt, sieht es wie folgt aus:

    static void Main(string[] args) 
    { 
      Thread.CurrentThread.CurrentCulture = new CultureInfo( "fr-FR" ); 
      Console.WriteLine( DateTime.Now.ToString() ); 
Console.WriteLine( DateTime.Now.ToString( "f" ) ); 
    } 

Die Ausgabe in der Konsole lautet:

Bild01









Ändern wir nun im oberen Quellcode den Kulturcode auf "fr-CA" für den französisch sprechenden Teil in Kanada, erhalten wir folgende Ausgabe:

Bild02









Neutraler und regionaler Kulturcode

Wozu braucht man den neutralen Kulturcode? Würde man nicht immer mit regionalen Kulturcodes arbeiten?

Um diese Frage zu beantworten, muss man erläutern, wie die Ressourcenverwaltung im .NET Framework funktioniert und dass es eine Trennung bezüglich Verarbeitung und Anzeige gibt.

Hierzu gibt es im Thread-Objekt zwei Eigenschaften: CurrentCulture und CurrentUICulture. CurrentCulture enthält ein CultureInfo-Objekt, das für die Verarbeitung von Daten zuständig ist, während die CurrentUICulture für die Ausgabe dieser Daten in der jeweiligen Sprache zuständig ist.

Möchte man nun in ASP .NET die Verarbeitung für den Raum Großbritannien setzen, jedoch die Ausgabe für den gesamt englischsprachigen Raum zur Verfügung stellen, kann man den ausführenden Thread mit den folgenden Informationen füttern:

    private void Page_Load(object sender, System.EventArgs e) 
    { 
      Thread.CurrentThread.CurrentCulture = new CultureInfo( "en-GB" ); 
      Thread.CurrentThread.CurrentUICulture = new CultureInfo( "en" ); 
    } 

In ASP .NET kann man dies mit den Attributen culture und uiCulture außerdem noch über die Seitendirektive deklarieren:

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" 
Inherits="LocalizationDemo.WebForm1"  
Culture="en-GB" uiCulture="en"%> 

Resource-Verwaltung

Culture definiert also die Verarbeitung der Daten für die jeweilige Region. Wie wird nun aber mit Ressourcen gearbeitet, die über UICulture gesetzt werden können? Wie werden diese Ressourcen abgelegt? Und welche Formate stehen zur Verfügung?

Strings, die man in seinen Anwendungen lokalisieren möchte, steckt man in so genannte Resource-Dateien. Das .NET Framework bietet hier mehrere Formate an:

  1. .txt – eine einfache Textdatei, die nur zum Speichern von Texten geeignet ist

  2. .resx – eine XML-basierte Resource-Datei, die auch Objekte speichern kann

  3. .resources – eine kompilierte Form von .txt- oder .resx-Dateien, die direkt in ein Assembly gebunden werden kann.

Für jede Sprachversion der Anwendung muss es eine Resource-Datei geben.

Das folgende Beispiel verdeutlicht die Verwendung von Resource-Dateien im .NET Framework. Über die Beispielanwendung in ASP .NET kann der Surfer Mailinglisten bestellen. Dabei soll die Anwendung auf den deutsch- (Deutschland, Österreich und Schweiz) und englischsprachigen Raum zugeschnitten sein.

Bild03


































Die Abbildung zeigt die Beispiel-Anwendung. Die rot umrahmten Bereiche sind die Texte, die in verschiedenen Sprachen verfügbar sein sollen.

Der zugehörige ASP-.NET-Sourcecode sieht folgendermaßen aus:

<%@ Page language="c#" Codebehind="order.aspx.cs" AutoEventWireup="false" 
Inherits="LocalizationDemo.order" %> 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > 
<HTML> 
  <HEAD> 
    <title>order</title> 
    <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0"> 
    <meta name="CODE_LANGUAGE" Content="C#"> 
    <meta name="vs_defaultClientScript" content="JavaScript"> 
    <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> 
  </HEAD> 
  <body MS_POSITIONING="GridLayout"> 
    <form id="order" method="post" runat="server"> 
      <asp:Label id="Label1" style="Z-INDEX: 101; LEFT: 45px; POSITION: absolute; 
TOP: 41px" runat="server"> 
  Welche Mailinglisten möchten Sie bestellen?</asp:Label> 
      <asp:Label id="Label2" style="Z-INDEX: 102; LEFT: 45px; POSITION: absolute; 
TOP: 178px" runat="server"> 
  Ihre E-Mail-Adresse</asp:Label> 
      <asp:TextBox id="TextBox1" style="Z-INDEX: 103; LEFT: 45px; POSITION: absolute; 
TOP: 198px" runat="server"></asp:TextBox> 
      <asp:ListBox id="ListBox1" style="Z-INDEX: 104; LEFT: 45px; POSITION: absolute; 
TOP: 96px" runat="server"> 
        <asp:ListItem Value="MSDN Newsflash">MSDN Newsflash</asp:ListItem> 
        <asp:ListItem Value="XBox Newsletter">XBox Newsletter</asp:ListItem> 
        <asp:ListItem Value="Office Flash">Office Flash</asp:ListItem> 
      </asp:ListBox> 
      <asp:Button id="Button1" style="Z-INDEX: 105; LEFT: 45px; POSITION: absolute;  
  TOP: 232px" runat="server" Text="Bestellen"></asp:Button> 
      <asp:Label id="Label3" style="Z-INDEX: 106; LEFT: 45px; POSITION: absolute;  
  TOP: 73px" runat="server">Mailinglisten</asp:Label> 
      <asp:Label id="Label4" style="Z-INDEX: 107; LEFT: 49px; POSITION: absolute;  
  TOP: 270px" runat="server" Width="309px" Height="141px"></asp:Label> 
    </form> 
  </body> 
</HTML> 

Bisher ist noch nichts lokalisiert. Die Texte sind fest den jeweiligen WebControls zugeordnet. Um den Lokalisierungsprozess zu starten, legen wir nun in der Anwendung eine Resource-Datei an. Dazu fügen wir eine Assembly-Resource-Datei zu unserem Projekt hinzu und nennen diese Strings.resx.

Bild04


























Wer will, kann direkt im XML in der Datei editieren, oder er nutzt den Tabellen-Modus, in dem er bequem die Bezeichner und Werte einträgt. In diesem Fall kommen die folgenden Bezeichner und Werte hinzu:

Bild05


























Die Eigenschaften der Resource-Datei zeigen, dass bei "Build Action" der Eintrag "Embedded Resource" ausgewählt ist. Durch diese Definition wird beim Kompilieren des Projektes eine .resources-Datei angelegt. Dies geschieht nach dem folgenden Muster: Projektname.ResourceDatei.resources. In diesem Beispiel heißt das Projekt "LocalizationDemo" und die Resources-Datei "Strings.resx".

Beim Kompilieren des Projektes enthält unser Assembly dann eine Resource-Datei mit dem Namen "LocalizationDemo.Strings.resources". Es ist wichtig, diesen Aufbau zu kennen, denn um die Ressourcen benutzen zu können, muss der ResourceManager durch den Bezeichner darauf zugreifen.

Die Klasse ResourceManager

Der ResourceManager ist unter dem Namensbereich System.Resources zu finden und ist dafür verantwortlich, Ressourcen aus Resource-Dateien zu laden. Hierbei ist es egal, ob diese Dateien einzeln auf der Platte liegen oder in Assemblies eingebunden sind. Letzteres ist in unserem Beispiel der Fall.

Für unser Beispiel langt es vollkommen, wenn die Ressourcen im Page_Load Event ausgelesen und den Controls zugewiesen werden. Es folgt ein Auszug aus dem Page_Load Event:

private void Page_Load(object sender, System.EventArgs e) 
{ 
  ResourceManager mgr = new ResourceManager( "LocalizationDemo.Strings",   
Assembly.GetExecutingAssembly() ); 
... 

Der erste Parameter des ResourceManger-Konstruktors ist der Name der Resource-Datei. Die Endung .resources wird weggelassen. Als zweiter Parameter wird das Assembly angegeben, in welchem sich diese Datei befindet. Es existieren noch weitere Konstruktoren, die direkt aus Verzeichnissen oder anhand von Typangaben Resource-Dateien suchen und diese an den ResourceManager übergeben.

Der ResourceManager ist nur für die Ressourcen "LocalizationDemo.Strings" zuständig, allerdings für alle Dateien mit dem gleichen Bezeichner, die unterschiedliche Sprachinformationen zur Verfügung stellen.

Eine kleine Grafik soll dies veranschaulichen:

Bild06




















Der Zugriff auf einen String in einer solchen Resource-Datei erfolgt nun mittels des ResourceManager. In unserem Beispiel sähe die Zuweisung für das Label1 dann wie folgt aus:

      Label1.Text = mgr.GetString( "Label1" ); 

Die Funktion GetString verfügt noch über eine überladene Version, die zusätzlich eine CultureInfo als Parameter erwartet. Wird die erste Variante wie eben gezeigt gewählt, so wird die CurrentUICulture vom ausführenden Thread herangezogen.

Wie erreicht man nun, dass eine weitere Sprache als Ressource zur Verfügung steht? Hier hat das .NET Framework sich der RFC1766 bedient. Der Aufbau von Mehrsprachigkeit wird über ein hierarchisches Prinzip gelöst.

default 
             de 
                    de-DE 
                    de-CH 
             en 
                    en-GB 
                    en-US
...


Es gibt allgemeine, neutrale sprachbezogene und spezifizierte regionale Ressourcen. Ist eine Ressource für eine bestimmte CultureInfo-Instanz nicht verfügbar zum Beispiel für en-GB, so wird ein Fallback auf den neutralen Kulturcode gemacht, also "en", und dort nach der entsprechenden Ressource gesucht. Ist diese dort ebenfalls nicht zu finden, versucht man es letztendlich in der allgemeinen Resource-Datei.

Dieser Fallback-Mechanismus ermöglicht es, Ressourcen effektiv zu lokalisieren, allgemeine Informationen zentral an einem Ort zu speichern und nur die wenigen notwendigen kulturspezifischen Informationen in den jeweiligen regionalen Resource-Dateien zu speichern.

In der gleichen Art und Weise handhabt dies der Windows Forms Resource Designer, der in Visual Studio .NET integriert ist. Er speichert nur die Delta-Informationen, die sich in den einzelnen Kulturen unterscheiden, um so über möglichst viele Gemeinsamkeiten an einer zentralen Stelle zu verfügen.

Um nun für unsere ASP-.NET-Anwendung eine englischsprachige Resource-Datei anbieten zu können, legen wir einfach eine zweite Assembly Resource-Datei in unserem Projekt an und nennen diese Strings.en.resx. "en" steht hier für den neutralen Kulturcode Englisch. Wir legen hier nun folgende Inhalte ab:

Bild07

























Ändern wir nun die UICulture-Eigenschaft unserer ASP .NET WebForm auf "en" für Englisch und starten die Anwendung, erhalten wir statt deutsche, englische Texte.

Bild08





































Wir legen noch eine dritte Resource-Datei an und nennen diese Strings.de-CH.resx. Gefüllt wird sie mit den folgenden Werten:

Bild09


























Wenn wir nun die UICulture auf de-CH (Schweiz) setzen, sehen wir, dass die Ausgabe den Willkommenstext aus unserer Schweizer Resource-Datei bekommt, alle weiteren Ressourcen jedoch aus der allgemeinen Resource-Datei. An dieser Stelle ist ein Fallback passiert. Der ResourceManager hat lediglich das eine Label gefunden und musste die anderen Ressourcen den Pfad hochiterierend herausziehen.

Bild10

































Satellite Assemblies

Bei unserer bisherigen Vorgehensweise hat Visual Studio .NET uns eine ganze Menge Arbeit abgenommen. Wir haben die drei Resource-Dateien LocalizationDemo.Strings.resx, LocalizationDemo.Strings.de-CH.resx und LocalizationDemo.Strings.en.resx angelegt. Während des Kompiliervorgangs hat Visual Studio diese Dateien zuerst in ihr binäres Format umgewandelt, also in .resources-Dateien. Danach hat VS .NET unsere Datei LocalizationDemo.Strings.resources in unser Main-Assembly eingebunden.

Für die zwei weiteren Dateien hat Visual Studio .NET zwei neue Assemblies erzeugt und zwar jeweils mit dem gleichen Namen: LocalizationDemo.resources.dll. Es handelt sich hierbei um so genannte Satellite Assemblies; in diesem Projekt enthalten sie nur die binäre Resourcen-Datei für die jeweilige Sprache.

Damit das Ganze aber keinen Namenskonflikt auslöst, erstellt Visual Studio .NET für jeden Kulturcode ein Unterverzeichnis und zwar unter dem /bin-Verzeichnis der ASP .NET-Anwendung.

In unserem Fall sieht das Anwendungsverzeichnis nun wie folgt aus:

Bild11





































Diese Struktur hat einen gravierenden Vorteil: Zur Laufzeit lassen sich weitere Sprachen hinzufügen: Einfach ein neues Verzeichnis mit dem jeweiligen Kulturcode anlegen und ein neues Satellite Assembly mit der entsprechend eingebundenen Resource-Datei hineinkopieren.

Was Visual Studio .NET uns abgenommen hat, können wir natürlich auch manuell erzeugen.

Dies geschieht in zwei Schritten:

1. Kompilieren der Resource-Dateien
Die .resx-Dateien sind noch im Source-Format. Um diese in ein Binärformat umzuwandeln, werden diese mittels des Tools resgen.exe kompiliert.

Resgen /compile Strings.en.resx Strings.en.resources 

2. Erzeugen eines Satellite Assemblies
Um ein Satellite Assembly zu erzeugen, gibt es ein Tool namens "Assembly Linker" (al.exe). Eine kompilierte Resource-Datei kann auf diese Weise in ein Assembly eingebunden werden. Existiert noch keines, so kann es vom Assembly Linker erzeugt werden. Die Kommandozeile sähe dann wie folgt aus:

Al /t:lib /embed:Strings.en.resources /culture:en /out:LocalizationDemo.resources.dll 

Design und eigene Web Controls

Nachdem unsere ASP-.NET-Anwendung nun lokalisiert ist, stellt sich die Frage, ob wir den Resourcemanager jedes Mal neu instanzieren und den Code für das Auslesen der Ressourcen schreiben müssen. Wie sähe dies dann erst bei eigenen benutzerdefinierten Web-Controls aus? Gibt es nicht eine elegantere Methode, Ressourcen auszulesen und anzuzeigen? Und zwar ausgehend von der eingestellten UICulture?

Um mehrsprachige Web-Controls anzubieten, kann man sich eines einfachen Tricks bedienen: Jedes Control hat eine Render-Methode. Würde man von diesem Control ableiten, die Render-Funktion überschreiben und dort den entsprechenden Code implementieren, der für die Anzeige der jeweiligen Sprachinhalte verantwortlich ist, so hätten wir mit recht wenig Aufwand Web-Controls, die sich mehrsprachig verhalten und für den ASP-.NET-Designer keinen zusätzlichen Arbeitsaufwand bedeuten. Lediglich der ResourceManager müsste einmalig instanziert werden um von den einzelnen Controls angesprochen werden zu können.

Anhand eines einfachen Label-Web-Controls setzen wir dies in die Praxis um: Zuerst erzeugen wir ein neues C#-Projekt vom Typ Klassenbibliothek und eine neue Klasse, die sich von System.Web.UI.WebControls.Label ableitet. Der nachfolgende Sourcecode zeigt eine solche Implementierung:

using System; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Reflection; 
using System.Resources; 
namespace LocalizedControls 
{ 
  /// <summary> 
  /// Summary description for Class1. 
  /// </summary> 
  public class LocalizedLabel : System.Web.UI.WebControls.Label 
  { 
    public LocalizedLabel() 
    { 
    } 
    protected override void Render( HtmlTextWriter writer ) 
    { 
      ResourceManager rm = new ResourceManager( "LocalizationDemo.String", 
      Assembly.GetExecutingAssembly() ); 
      this.Text = rm.GetString( this.ID ); 
      base.Render( writer ); 
    } 
  } 
} 

Wir kompilieren das Projekt und binden das Assembly in unser ASP-.NET-Projekt ein. Über "Customizing Toolbox" können wir nun das neue Control in die Toolbox mit aufnehmen, um es Designern so einfach zu machen, mit unserer lokalisierten Variante zu arbeiten.

Bild12




























Was aber macht das Control? In der Render-Methode instanziert es einen ResourceManager und holt sich dann über diesen mit seiner eigenen ID die entsprechende lokalisierte Ressource. Danach ruft es die Render-Methode der Basisklasse auf und schon erhält man auf der ASP-.NET-Seite lokalisierte Anzeigen.

Es gibt jedoch bei dieser Lösung noch einen kleinen Haken: Es fehlt ein kleines Framework, in dem die Ressourcen-Herkunft von außen gesteuert werden kann.

Zu diesem Zweck erzeugen wir eine Klasse RMManager, die nur für die Verwaltung eines ResourceManagers verantwortlich ist. Diese kann in unserem Beispiel auch nur ein Objekt enthalten, was für unser simples Szenario ausreicht, und wird über eine statische Methode instanziert (wir benutzen hierfür ein Singleton Pattern).

Der Sourcecode für die Klasse sieht wie folgt aus:

using System; 
using System.Collections; 
using System.Resources; 
using System.Reflection; 
namespace LocalizedControls 
{ 
  /// <summary> 
  /// Summary description for RMManager. 
  /// </summary> 
  public class RMManager 
  { 
    private static RMManager manager = null; 
    private ResourceManager rm = null; 
    private bool init = false; 
    private RMManager() 
    { 
    } 
    public static RMManager Instance() 
    { 
      if( manager == null ) 
      {  
        manager = new RMManager(); 
      } 
      return manager; 
    } 
    public ResourceManager CreateResourceManager( string name, Assembly assembly ) 
    {                            
      if( init ) 
      { 
        throw new ApplicationException
       ( "ResourceManager object already exists! First remove this one" ); 
      } 
      rm = new ResourceManager( name, assembly ); 
      if( rm != null ) 
      { 
        init = true; 
        return rm; 
      } 
      else 
      { 
        throw new ApplicationException( "Could not create ResourceManager!" ); 
      } 
    } 
    public ResourceManager CurrentResourceManager 
    { 
      get 
      { 
        if( !init || rm == null ) 
        { 
          throw new ApplicationException( "No ResourceManager was created so far!" ); 
        } 
        return rm;         
      }      
    } 
    public void RemoveResourceManager() 
    { 
      rm = null; 
      init = false; 
    } 
  } 
} 

Wie wendet man nun den RMManager an? Zunächst stellen wir fest, dass es eine CreateResourceManager-Methode gibt, die 1:1 die gleichen Parameter bekommt wie das originale ResourceManager-Objekt. Am besten erzeugen wir am Anfang unserer Anwendung eine Verbindung zum RMManager und der Resourcen-Datei, die er handhaben soll. Für unser Beispiel machen wir dies in der Application_Start-Methode der Global.asax-Datei:

    protected void Application_Start(Object sender, EventArgs e) 
    { 
      LocalizedControls.RMManager.Instance().CreateResourceManager
      ( "LocalizationDemo.Strings", Assembly.GetExecutingAssembly() ); 
    } 

Nachdem wir nun die Verbindung zu der Ressource hergestellt haben und unser RMManager damit umgehen kann, müssen wir noch den Code unseres lokalisierten Label-Controls anpassen:

using System; 
using System.Web.UI; 
using System.Web.UI.WebControls; 
using System.Reflection; 
using System.Resources; 
namespace LocalizedControls 
{ 
  /// <summary> 
  /// Summary description for Class1. 
  /// </summary> 
  public class LocalizedLabel : System.Web.UI.WebControls.Label 
  { 
    public LocalizedLabel() 
    { 
    } 
    protected override void Render( HtmlTextWriter writer ) 
    { 
      try 
      { 
        ResourceManager rm = RMManager.Instance().CurrentResourceManager; 
        this.Text = rm.GetString( this.ID ); 
      } 
      catch 
      { 
      } 
      finally 
      { 
        base.Render( writer ); 
      } 
    } 
  } 
} 

Wir sehen, dass wir nun einfach einen ResourceManager über unser RMManager-Objekt holen können. Sollte keiner vorhanden sein, wird der Content, der in der ASP-.NET-Seite direkt eingegeben wurde, gerendert. Die Exception, die auftreten kann, wird sauber abgefangen.
Setzen von Culture und UICulture
Nachdem wir nun ein kleines Framework für unser eigenes ASP-.NET-User-Control zusammengestellt haben, sollten wir noch wissen, wie ASP .NET an die gewünschte Sprachinformation herankommt, die der Benutzer von der Anwendung erwartet.

Es gibt zwei Ansätze in einer ASP-.NET-Anwendung, die Sprache abhängig vom Benutzer zu setzen. Die erste ist folgende: Der Benutzer meldet sich an, die entsprechende Kulturinformation ist in seinem Profil vorhanden und wird dementsprechend ausgelesen und aktiv gesetzt.

Diese Methode eignet sich aber nicht für ASP-.NET-Anwendungen, die von vielen anonymen Benutzern angesprochen werden und denen der Inhalt lokalisiert dargestellt werden soll.

Elegant wäre es, die eingestellten Sprachen aus dem Webbrowser herauszulesen und entsprechend die Culture-Informationen zu setzen. Der Code sähe dann folgendermaßen aus:

private void Page_Load(object sender, System.EventArgs e) 
{ 
   Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture
   ( Request.UserLanguages[ 0 ] ); 
   Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; 
} 

Das Request-Objekt enthält eine Collection aller eingestellten Browser-Sprachen, die der Benutzer eingestellt hat.

Da es sich bei solchen Sprachen auch um einen neutralen Kulturcode handeln kann, müssen wir eine statische Funktion von CultureInfo nutzen, um ein Mapping auf eine kulturspezifische Sprache zu machen. Ansonsten können wir CurrentCulture für den momentanen Thread nicht setzen, da – wie wir bereits wissen – nur spezifische Kulturcodes zur Verarbeitung verwendet werden können. Diese Funktion heißt CreateSpecificCulture und mappt beispielsweise de -> de-DE.

Zusammenfassung

Wir haben in diesem Artikel über die Unterschiede von Culture und UICulture gesprochen und veranschaulicht wozu diese dienen. Desweiteren sind wir auf die spezifischen Besonderheiten von Visual Studio .NET eingegangen im Umgang mit Resourcen-Dateien und wie diese in das fertige Assembly mit eingepflegt werden.

Um mit ASP-.NET-Anwendungen Mehrsprachigkeit abzubilden, haben wir ein sehr einfaches Modell implementiert um eigene ASP-.NET-User-Controls die Fähigkeit zu verleihen, Resourcen auszulesen und darzustellen.

Alles in allem haben wir festgestellt, dass das Microsoft .NET Framework eine Vielfalt von Klassen zur Verfügung stellt, um Anwendungen für den internationalen Markt zu schreiben und diese mit einfachen Mitteln an die jeweiligen Landesgewohnheiten anzupassen.

Wir konnten lediglich einen kleinen Teil der Klassen in den Namensbereichen System.Globalization, System.Resources, etc. vorstellen und es sind noch eine Reihe weiterer interessanter Klassen enthalten, wie zum Beispiel verschiedene Kalender-Implementierungen.

Wichtig ist aber, mit dem Prinzip der Globalisierung im Framework vertraut zu werden und die ganze Vielfalt durch experimentieren zu entdecken, zu welchem Sie dieser Beitrag ein wenig motivieren soll.


Anzeigen: