Introduction
A while ago, I needed to implement localization depending also on the gender of the registered user, something obviously more relevant to languages other than English (for example, mine - Hebrew). After playing around a bit with writing my own custom ResourceManager/Provider classes, I decided to follow a suggestion I received for a much simpler way - create my own custom cultures for each required language.
Step 1 - Create your own custom culture
For each language required, create a custom "female" culture as a clone of the original culture. For example, the following code creates a custom culture named 'he-IL-f' which is a clone of 'he-IL'. Install the culture on your machine. You can verify the installation was successful by viewing your “C:\Windows\Globalization” folder after running the exe.
CultureAndRegionInfoBuilder cib =
new CultureAndRegionInfoBuilder("he-IL-f", CultureAndRegionModifiers.None);
CultureInfo ci = new CultureInfo("he-IL");
cib.LoadDataFromCultureInfo(ci);
RegionInfo ri = new RegionInfo("IL");
cib.LoadDataFromRegionInfo(ri);
cib.Parent = ci;
cib.Register();
* The above code needs admin rights to execute, so if in Vista, run the exe “as admin”.
The fallback culture of the new culture will be the original one – this is why we have this line:
cib.Parent = ci;
This enables us to only enter the strings that need changing in the "female" RESX files.
Step 2 - Create the correspondingly names RESX files
Notice that in the “female” RESX files, you only need to insert those strings which differ from their “male” version.
Step 3 - Set the thread's UICulture property
protected override void InitializeCulture()
{
string culture = "";
if (Request.Form["DropDownListCulture"] != null)
{
string gender = Request.Form["DropDownListGender"];
bool isFemale = (gender == "Female");
culture = Request.Form["DropDownListCulture"];
dir = (culture == "he-IL") ? "rtl" : "ltr";
if (isFemale)
{
culture += "-f";
}
}
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(culture);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
base.InitializeCulture();
}
In my example I used the InitializeCulture
event of the page to perform the logic. In more complex systems, we’d probably want to move this logic to a more centralized location (perhaps some event in the Application level). I receive two parameters from the form – language and gender. Of course, in a real application, we would have this information per user and use it automatically upon login.
Using the code / Points of interest
- In the source code supplied, we register three custom cultures: en-US-f, he-IL-f, and fr-FR-f.
You can verify this by checking your “C:\Windows\Globalization” folder after running the exe.
- Note that the French culture was registered without this line of code:
cib.Parent = ci;
.
This means that instead of falling back to fr-FR, it falls back to the default culture (en-US, in our case).
This is demonstrated when using the global resource ‘Talya’ (at the bottom of the page): its default in English is ‘talya’, and it is overridden in the he-IL and fr-FR cultures, but not in their female versions.
When viewed with the he-IL-f culture, it falls back to the Hebrew resource ‘טליה’. However, when viewed with the fr-FR-f culture instead of falling back to ‘talya (French)’, it falls back to the English ‘talya’. This is because we didn’t set the French female culture’s parent to the French culture.