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.
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)
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)
CultureInfo cultureInfo = System.Threading.Thread.CurrentThread.CurrentUICulture;
ClientCultureInfo o = new ClientCultureInfo(cultureInfo);
SerializedCulture = ClientCultureInfo.SerializedCulture(o);
public string SerializedCulture
ViewState["kultur"] = value;
if (ViewState["kultur"] == null)
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:
// Get the name field of the CurrentCulture object
var __cultureInfo = '<%= this.SerializedCulture %>';
Sys.CultureInfo.CurrentCulture = Sys.CultureInfo._parse(__cultureInfo);
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:
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'));
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:
<globalization uiCulture="auto" culture="auto" />