Localizing ASP.Net web applications is pretty straightforward. You can use global and/or local resources and use them in your pages as you like. Via configuration you can set the default culture of your site or you can set it to auto. All very well. There’s just one thing about the whole localization system that bothers me: Override the default (UI)Culture at runtime.
While overriding the new InitializeCulture member of the Page class is considered best practice, I think it has some unfortunate flaws. The main issue I have is that you have to override a member on page level. Since it is very likely that you’ll have more than just one Page, you’ll have to start using a common base class. This could have been fine with the pageBaseType setting, but it just doesn’t work if you have pages with code-behinds. So you’ll have to start changing your base class manually in each code-behind file. Not very useful.
Additionally, for this kind of requirement, I just prefer a more loosely coupled approach. ASP.Net makes it so easy to do this, so why don’t?
Basically what I’ve done is created an HttpModule that injects code in the PreRequestHandlerExecute event of the HttpApplication. During this event the Session and Profile data is available and the HttpHandler (the page, in this case) initialized and about to execute. Essentially, it occurs just before the execution of the InitializeCulture method (via FrameworkInitialize and __BuildControlTree), so it can’t get any closer than this. (You just have to be careful not to use resources in your page constructor for example, since that code has already executed.)
In my (simplistic) example the default culture is fixed to en-US via the Web.config:
<globalization culture="en-US" uiCulture="en-US" />
This means all pages will, by default, render en-US resources. The registered HttpModule
<httpModules> <add name="localization" type="LocalizationModule"/> </httpModules>
checks the use Request’s QueryString to see if the user wishes to override the default Culture. If so, it stores this requested culture in the user’s current profile. The current thread’s culture is only changed if the profile has a culture specified. (we know that if we don’t touch it, it’s set to en-US thanks to the web.config)
Switching the culture by the means of a QueryString parameter is merely for convenience. Plus, the query string parameter is only required to perform the culture-switch, afterwards it is no longer required.
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(GetQueryStringString("c")))
{
HttpContext.Current.Profile["c"] = GetQueryStringString("c");
}
if (HttpContext.Current.Profile["c"] != null)
{
//retrieve culture
string culture = HttpContext.Current.Profile["c"].ToString();
//set culture
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(culture);
Thread.CurrentThread.CurrentUICulture = new
CultureInfo(culture);
}
}
As you can see, no rocket science at all. I just don’t understand why the ASP.Net designers chose the InitializeCulture approach.