Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load different RESX files based on some parameter

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.

like image 703
Francesco Gallarotti Avatar asked Sep 03 '10 11:09

Francesco Gallarotti


People also ask

How do I sort a RESX file?

Right click a resx file in Solution Explorer, and choose "Sort resx". Select any number of resx files (or any other files), right click and choose "Sort resx".

How do I add files to Resx?

Double click (select) Resource. resx. Select Add Resource > Add Existing File. Select the 'icon.

How do I read a RESX file?

To start with, you need to create a web application. Here, I am using Visual Studio 2012 and C# as the language. Once you created the application, you need to create a RESX file by clicking the “New Item”. Now you can see a new file in your solution explorer named Resource1.

Are RESX files compiled?

resx file is compiled into a . resource file, which in turn is linked into a . resource. dll satellite file, referred to as a satellite DLL or Language Assembly.


1 Answers

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.
like image 121
Jakub Januszkiewicz Avatar answered Oct 05 '22 19:10

Jakub Januszkiewicz