ASP.NET Ressourcen clientseitig mit JavaScript nutzen
In einer ASP.NET Anwendung in der relativ viel JavaScript genutzt wird, bekommt man spätestens dann Probleme, wenn man auch Meldungen und Texte die per JavaScript erzeugt werden, mehrsprachig ausgeben möchte.
Man könnte jetzt einfach alle Scripts serverseitig erzeugen und auf das WebForm rendern, bei vielen JavaScripts macht das allerdings keinen Sinn mehr. Selbst alle Scripts dynamisch über einen HttpHandler ausgeben zu lassen ist nicht sinnvoll, da dann alle Scripts nur als String im .NET Code vorliegen und nur schwer zu Ändern sind (fehlendes Syntax Highlighting, kein IntelliSense, etc).
Das Problem ist jetzt, wie stelle ich alle Resource Strings meiner Webanwendung clientseitig zur Verfügung? Wichtig ist, dass ich die bei einer neuen Ressource nicht wieder Änderungen an zwei Stellen vornehmen muss.
Einen HttpHandler zu benutzen steht außer Frage. Was ich aber nicht möchte, ist jeden Resource String einzeln in den Handler zu schreiben. Bis jetzt kannte ich keine Möglichkeit, eine Collection mit allen Werten aus den Ressourcen zu lesen. Die Beschreibung der ResXResourceReader in der MSDN brachte mich dann auf die annähernd optimale Lösung:
context.Response.ContentType = "text/javascript";
string resourceFilePath = context.Server.MapPath("~/App_GlobalResources/General.resx");
string resourceValue;
string resourceString;
context.Response.Write("var Resources = {\n"); // Start Namespace "Resources"
context.Response.Write("\"General\" : {\n"); // Start Class "General"
using (ResXResourceReader reader = new ResXResourceReader(resourceFilePath))
{
IDictionaryEnumerator en = reader.GetEnumerator();
while (en.MoveNext())
{
resourceValue = en.Value.ToString();
resourceValue = resourceValue.Replace("\"", "\\\"");
resourceValue = resourceValue.Replace("\r\n", "\\n");
resourceString = string.Format("\"{0}\" : \"{1}\",\n",
en.Key,
resourceValue);
context.Response.Write(resourceString);
}
}
context.Response.Write("}\n"); // End Class "General"
context.Response.Write("};\n"); // End Namespace "Resources"
Dieser Handler erzeugt dann z. B: folgende Ausgabe:
var Resources = {
"General" : {
"Add" : "Hinzufügen",
"AllFields" : "Alle Felder",
"Apply" : "Übernehmen",
"AskDelete" : "Aktuellen Datensatz wirklich löschen?",
"Back" : "Zur letzten Seite",
"Cancel" : "Abbrechen",
"Change" : "Bearbeiten",
"CloseModalWindow" : "Schließen",
}
}
Der Handler kann dann ganz normal wie eine JavaScript Datei im WebForm eingebunden werden:
<script src="common/scripts/resources.ashx" type="text/javascript"> </script>
Das schöne an dieser Variante ist, das ich die Ressourcen wie im C# Code nutzen kann:
<asp:Button ID="btnDelete" runat="server" Text="Löschen"
onclick="if(confirm(Resources.Genaral.AskDelete))return false;" />
Nachteil an dieser Variante, bzw. eigentlich nur an dem Code des HttpHandlers oben, ist dass die Resource Datei hart reingeschrieben ist. Um das ganz zu optimieren, könnte man alle .RESX Dateien durchgehen, die z. B. unter „App_GlobalResources“ angelegt sind.
Des Weiteren ist die Internationalisierung noch nicht berücksichtigt. Das heißt bei der Ermittlung des Pfades zur Resource Datei muss die aktuelle Culture noch berücksichtigt werden, damit je nach Einstellung die richtigen Dateien gefunden werden. Z. B: („General.de-DE.resx“ für die Deutsche Ausgabe oder „General.en-US.resx“ für die US Amerikanische Ausgabe).