How to load different RESX files based on some parameter
Asked Answered
J

2

15

I have an ASP.NET3.5 (C#) ASPX page that is internationalized in 10 different languages.

The page is very complex in its structured with dozens of nested views driven by a state machine pattern.

EDIT: I am using the meta:resourcekey syntax in every asp control, which allows to use declarative syntax for Implicit Resource expressions.

I have been asked to "brand" the page based on some query string parameter. Branding will mean not just loading different CSS files, but also having different text blurbs (in all languages).

Is there an easy way to "swap" resx files without having to get resources manually for each of the hundreds of literals and images that I have on this page?

In other words, let's say I have the following RESX files:

brand1_myPage.aspx.en-US.resx
brand1_myPage.aspx.de-DE.resx
brand1_myPage.aspx.fr-FR.resx

brand2_myPage.aspx.en-US.resx
brand2_myPage.aspx.de-DE.resx
brand2_myPage.aspx.fr-FR.resx

myPage.aspx will be looking for resx files named myPage.xx-XX.resx.

Is there a way to load instead either the brand1xxx.resx files or the brand2xxx.resx based on some value?

Thanks in advance.

Jeuz answered 3/9, 2010 at 11:47 Comment(0)
M
12

You can use custom cultures to achieve this effect.

First, create and register custom cultures in the system, for example:

CultureAndRegionInfoBuilder builder = new CultureAndRegionInfoBuilder("en-US-brand1", CultureAndRegionModifiers.None);
CultureInfo parentCI = new CultureInfo("en-US");
RegionInfo parentRI = new RegionInfo("en-US");
builder.LoadDataFromCultureInfo(parentCI);
builder.LoadDataFromRegionInfo(parentRI);
builder.Parent = parentCI;
// set other properties of the custom culture (CultureEnglishName, CultureNativeName, possibly other ones)
// ...
builder.Register();

Note that you might want to build a simple tool to automate this, since those cultures need to be installed on every system where your aplication will be compiled or executed. Administrative rights are needed to be able to register the cultures.

Once you have the cultures installed, create resx files like you would normally do, but use the custom culture names (myPage.aspx.en-US-brand1.resx etc).

Now all that's left to do is to set System.Threading.Thread.CurrentThread.CurrentUICulture based on some parameter (the sooner the better, BeginRequest is a good place; or Page_PreInit if you want this only for some pages):

CultureInfo ci = new CultureInfo(Request.QueryString["paramname"]);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;

(setting CurrentCulture is not really necessary, as resources work in terms of CurrentUICulture, but setting both allows you to further customize the page for each brand, e.g. use different date/time format settings for each custom culture/brand)

Some notes:

  • this solution gives you great flexibility, since normal culture fallback is in effect - if an entry is not found for en-US-brandX, the runtime will fall back to en-US and so on; this can greatly reduce duplicate resx entries if the brands are mostly similar, as you can put some entries only in the parent (en-US) resx file,
  • you can create more levels of inherited cultures, eg en-US-brandX-variantY,
  • all methods for accessing resources work as expected,
  • changing the culture of the worker thread means you will get localized exception messages if you set the culture to, say, de-DE-brandX and you have de-DE localization installed in the OS,
  • for the above reason, you might want to reset the current (UI) culture to CultureInfo.InvariantCulture in Application_Error, or even better also as soon as you catch an exception which you know will lead to Application_Error; this will prevent localization of the standard yellow page of death and at least part of the exception stack,
  • you might consider building a service tool which will register/unregister/update the cultures, especially if you anticipate frequent changes,
  • this solution might be problematic if you use client-based culture detection.
Montespan answered 21/3, 2011 at 22:54 Comment(0)
I
0

If you reference resources in your code like this: Resources.brand1_myPage.WelcomeMessage then it may be difficult.

But you can also retrieve resources programmatically: GetGlobalResourceObject ("brand1_myPage", "WelcomeMessage"). Here you have some room for manipulation with the resource file name.

Intercommunicate answered 3/9, 2010 at 12:21 Comment(1)
I am not using neither GetGlobalResourceObject nor GetLocalResourceObject. Every ASP control has a built in meta:resource property that automatically loads from the associated RESX file. As an example, if I have the following ASP tag: <asp:Literal ID="someLit" runat="server" meta:resourceKey="someLitResource"> and then in my 10 different RESX files I have someLitResource.Text defined, the content in the current language is automatically loaded already.Jeuz

© 2022 - 2024 — McMap. All rights reserved.