I just spent about four hours trying to solve a problem I’ll probably never actually encounter in the wild. Someone posted on the asp.net forums about script globalization using ASP.NET AJAX. This can be set up pretty easily by simply using the ScriptManager control and setting its EnableScriptGlobalization property to true. ScriptManager takes care of importing the necessary scripts and handling all the underlying code required to make things work.
What the seeker on the forums wanted to know, however, was whether this could be accomplished without the ScriptManager. In theory, all the ASP.NET AJAX framework scripts can be downloaded and used in a non-platform dependent manner.
Certain software problems are ubiquitous, and people tend to fall over themselves blogging and posting about them until Microsoft or some other vendor eventually either fixes the problem and it goes away. On the other hand, there are problems in the software bestiary that are so rare that working on them is the programming equivalent of doing cryptozoology.
This was a juicy problem of that sort. And I believe I have a solution. It basically involves redoing some of what the ScriptManager does automatically, but what the hey.
To support globalization in ecmascript, the ScriptManager basically sets a variable called __cultureInfo behind the scenes. This is then used by various ASP.NET AJAX script methods to provide formatting information. This is actually explained in the Microsoft documentation for the feature.
Behind the scenes, it seems clear, the ScriptManager is querying the CurrentUICulture of the current thread in order to determine the browser’s preferred language, and passing this to the __cultureInfo variable. The trick, then, is to determine the format of the culture data passed to __cultureInfo.
Here I had to use reflection to discover that there is an internal ClientCultureInfo type in the Sys.Web.Extensions assembly. It made sense that this was being serialized and passed to the __cultureInfo variable. With some trial and error, I finally got the serialization correct.
To make this work, you will need to download the Ajax Framework Library, which is a collection of javascript files. You will need to import the MicrosoftAjax.js file into your web project, and then reference it in your page, like this:
<script src=”MicrosoftAjax.js” type=”text/javascript”></script>
You will also need to create the ClientCultureInfo class for your project, and make sure that it is serializable. I tried DataContractJsonSerializer class to do my serializing, but had problem getting the DateTimeFormatInfo type to serialize correctly, so I finally opted to use the now obsolete JavaScriptSerializer. Here’s what the class looks like:
public class ClientCultureInfo
{
public string name;
public DateTimeFormatInfo dateTimeFormat;
public NumberFormatInfo numberFormat;
public ClientCultureInfo(CultureInfo cultureInfo)
{
this.name = cultureInfo.Name;
this.numberFormat = cultureInfo.NumberFormat;
this.dateTimeFormat = cultureInfo.DateTimeFormat;
}
public static string SerializedCulture(ClientCultureInfo info)
{
JavaScriptSerializer js = new JavaScriptSerializer();
return js.Serialize(info);
}
}
Now that we have the culture info formatted correctly, we need to be able to pass it to the client variable. We’ll create a public property in the code-behind that is accessible from the client, and set its value in the Page.Load event handler:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
CultureInfo cultureInfo = System.Threading.Thread.CurrentThread.CurrentUICulture;
ClientCultureInfo o = new ClientCultureInfo(cultureInfo);
SerializedCulture = ClientCultureInfo.SerializedCulture(o);
}
}
public string SerializedCulture
{
set
{
ViewState[“kultur”] = value;
}
get
{
if (ViewState[“kultur”] == null)
return string.Empty;
else
return ViewState[“kultur”].ToString();
}
}
Finally, we need to use this code-behind property to set __cultureInfo. Just add the following script block to your markup in order to set the current culture:
<script type="text/javascript"> // Get the name field of the CurrentCulture object var __cultureInfo = '<%= this.SerializedCulture %>'; Sys.CultureInfo.CurrentCulture = Sys.CultureInfo._parse(__cultureInfo); </script>
I added this to the bottom of the page. To test whether this works, you will need to set the language property of your browser (if you are using IE, like I am). I set mine to French for testing. Then append the following script block below the one setting the culture above:
<script type="text/javascript"> var currentCultureInfoObj = Sys.CultureInfo.CurrentCulture; var d = new Date(); alert("Current culture is " + currentCultureInfoObj.name + " and today is " + d.localeFormat('dddd, dd MMMM yyyy HH:mm:ss')); </script>
If you encounter any problems, it is possible that the web.config file is overriding the culture information from the browser. In that case, make sure the culture is set to “auto” in the config file, like this:
<system.web>
<globalization uiCulture=“auto“ culture=“auto“ />
</system.web>
I just came across some globalization problems in a non-WebForms application that uses the ASP.NET Ajax library. Sadly, the client reference says nothing about setting the culture manually. If not your post, I’d have to dig the ScriptManager down and figure out the procedure myself. It saved me a good bunch of hours. Thanks;)
Thank you very much! This article helped me a lot.
We’re using the CalenderExtender control of the AJAX Control Toolkit which uses the Culture instead of the UICulture. With your help the calendars use the UICulture instead.
Nice Post. It’s really a very good article. I noticed all your important points. Thanks
<a href="http://www.p90xworkoutus.com">P90x Workout</a>
<a href="http://www.p90xworkoutus.com">P90x Dvd</a>