Localization in ASP.NET hasn’t changed much since the days of WebForms and ASP.NET 1.0 with some minor updates (for WebForms) in ASP.NET 2.0. Since then things have been rather quiet in regards to new localization features.
One of the things that just about any localized ASP.NET app needs to do is set the user’s locale, often based on the active browser language setting. There’s some limited support for auto-local switching built into .NET but this often doesn’t hit all the needs of a typical application scenario where more is required.
This post describes what’s ‘in the box’, and how you can create a simple custom solution that provides a bit more flexibility along with some discussion on how to best set the culture depending on your application requirements, whether its automatic culture detection and setting, or explicitly assigning cultures based on user preferences.
ASP.NET Native Support for Auto Locale Switching
ASP.NET has some native support for automatic locale switching via the <globalization> web.config section. The following setting can be made in web.config:
<globalization culture="auto:en-US" uiCulture="fr" />
This setting automatically switches the ASP.NET request to the browser client’s language if a match can be found. If the browser doesn’t provide a language or the language can’t be matched to one of the .NET installed cultures, the fallback value is used – in this case en-US.
This setting applies the ASP.NET request thread’s CurrentCulture and UICulture. The culture is switched very early in the ASP.NET HttpApplication lifecycle, so you see the selected culture applied and available even in Application_BeginRequest and then throughout the rest of the request cycle.
Culture and UICulture
As a refresher, recall that a .NET Culture drives things like number and date formats, currency symbols, sort order, casing etc. – ie. it’s primarily geared towards formatting and converting things. UICulture on the other hand is what .NET uses for resource localization – if you’re using Resx resources or a custom ResourceManager or ResourceProvider (in ASP.NET) the UICulture is what affects which resources are selected for display.
In addition to the global web.config settings that apply globally to all ASP.NET requests, WebForms Page objects can also apply Culture and UI culture on a per page basis, and use the same auto-culture detections. For example:
<%@ Page Language="C#" Culture="auto:en-us" UICulture="auto:en-us" %>
WebForms Pages also include an InitializeCulture() handler that can be overridden. It fires very early in the page cycle as a pre-init event that allows you to hook into the process of assigning a new culture before other code in the page runs and before the initial page tree and the controls within it are constructed.. InitializeCulture() can be used to override culture values set with the above attributes, or completely create a custom culture switching routine based on application logic.
Don’t use Page level Settings
Generally I’d advise against using Page level localization settings, to avoid missing non-Page resources in your application that might also need to be localized. For example, you might have a module that also produces localized output or error messages and if you use only page level localization only pages that have the attributes set localize properly. It’s better to use localization globally and ensure your entire application uses the same settings.
Auto-detecting and setting the Culture with Code
Today a lot of new ASP.NET applications don’t use WebForms so the above solution clearly doesn’t work for everything. Even if it did, the solution is very generic with very little control over the process if you need to customize how localization is applied in any way. In real-world applications the requirements for locale switching tend to be a bit more complex, involving switching only to certain supported languages and locales as well as overriding some of the common culture settings. I’ll come back to this in a minute, but first lets look at a routine that I use to switch my .NET Culture and UICulture in Web applications.
To make this work you need to:
- Sniff the Browser’s language via Accept-Header using Request.UserLanguages in ASP.NET
- Determine the locale to select
- Set the Thread’s CurrentCulture and CurrentUICulture to the chosen locale
The HTTP Accept-Language Header
The Accept-Language header is sent by most browsers and looks something like this:
The header includes a list of languages that are defined in the browser’s language settings. Typically you’re only interested in the first one for setting the language as that’s the primary language. Although browsers send this automatically, keep in mind that non-browser HTTP clients typically don’t so if you’re checking for Accept-Language always assume it’s not present first, before using it.
In ASP.NET you can use the Request.UserLanguages property to retrieve the list of languages supported. You can check the UserLanguages, ensure that it’s available and then read the first item:
culture = CultureInfo.InstalledUICulture.IetfLanguageTag;
if (HttpContext.Current != null && HttpContext.Current.Request.UserLanguages != null)
culture = Request.UserLanguages;
You can use different values for Culture and UI culture. But typically you use the same values for both or specify a specific culture for the Culture and a generic non-specific culture for the UICulture – ie. en-US for culture, and en for UICulture – as generally the differences between regional versions of a given language are relatively minor and not worth customizing for (color vs. colour type of issues).
Cultures are applied on the thread level in .NET and ASP.NET assigns these culture settings on the active request thread which remains active for the lifetime of a typical ASP.NET request. The culture is accessible and can also be assigned manually like this:
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture); // de-DE
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(culture);
Other Posts you might also like