# Tuesday, February 10, 2009

At our organization, we have to globalize our software. Making sure you've gotten all the strings globalized can be a real pain. You have to create a new language resource that looks nothing like your native language, then set the Thread.CurrentThread.CurrentUICulture to the culture of the new language resource you created.  Such a pain.

While pondering that this afternoon, I came upon something better. The .NET CultureManger looks for the most specific resource file, then works its way back to the least specific. For example, given the following resource files:

  • i18n
  • i18n.en
  • i18n.en-US

If your current culture was en-GB, the CultureManger would use the resource file for i18n.en, since there is no i18n.en-GB. But, if your current culture was da-DK, it would use i18n.

In our software, we have i18n, and i18n.da-DK resource files, plus i18n.fr-FR which is a special, internal resource file. What's so special about the fr-FR resource file you ask? The fr-FR resource file is really the i18n resource file which as been transformed to replace all the localized text with dashes.

Why did we do this? Because with all the English text replaced with dashes, it makes it very easy to see which text in the application hasn't been globalized. The down side to this, is we have to change the CurrentUICulture (and CurrentCulture) to fr-FR in order to test this.

Solution

The solution is actually quite simple, rename the fr-FR resource file to i18n.en-US (or what ever the ISO code for your culture is).  Now when your testing, the CultureManager will pick the most specific resource file, and use that. But, don't forget to remove en-US folder from the final build folder before you deploy your application, lest users get your debug language resource.

kick it on DotNetKicks.com
Tuesday, February 10, 2009 10:55:35 PM (Alaskan Standard Time, UTC-09:00)
You could also use a tool such as Babylon.NET (http://www.redpin.eu/) for making translations. It is much easier to do translations with it.
dcarapic
Thursday, February 12, 2009 3:26:12 PM (Alaskan Standard Time, UTC-09:00)
I had the same problem so I built a utility that batch generates resources where the case of each string character is inverted.
All I have to do is point it to a folder full of assemblies, specify a culture and a sub folder will be created with the mangled resources.
This is slightly better than dashes since menu items and buttons still make sense if you're not 100% familiar with the UI.
It's fairly straightforward to do using AppDomain.CurrentDomain.DefineDynamicAssembly and AssemblyBuilder.DefineResource.
Nathan Baulch
Friday, February 13, 2009 7:01:49 AM (Alaskan Standard Time, UTC-09:00)
Nathan, very interesting idea. Could you write more about your particular implementation, more specifically how you used AppDomain.CurrentDomain.DefineDynamicAssembly and AssemblyBuilder.DefineResource?
Dan Morphis
Monday, February 16, 2009 12:16:12 AM (Alaskan Standard Time, UTC-09:00)
Sure, here's a minimal example:

var assemblyName = "MyAssembly";
var cultureName = "en-AU";
var directoryName = Path.Combine(Directory.GetCurrentDirectory(), cultureName);
Directory.CreateDirectory(directoryName);
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName
{
Name = assemblyName,
CultureInfo = CultureInfo.GetCultureInfo(cultureName),
},
AssemblyBuilderAccess.Save,
directoryName);
var resourceName = "MyResource";
var resourceFileName = string.Format("{0}.{1}.resources", resourceName, cultureName);

using (var writer = assemblyBuilder.DefineResource(resourceName, null, resourceFileName))
{
writer.AddResource("MyKey", "MyValue");
writer.Generate();
}

assemblyBuilder.Save(assemblyName + ".dll");
Nathan Baulch
All comments require the approval of the site owner before being displayed.
Name
E-mail
(will show your gravatar icon)
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Live Comment Preview