Custom Cultures, Vista and the IetfLanguageTag

One of the great features in the .NET Framework 2.0 is the ability to define new or replacement cultures, known as custom cultures. One of the benefits of this feature is that it allows you to export cultures from newer operating systems to older operating systems. This allows you to reap the rewards of the new culture without having to upgrade. The exported cultures are not always an exact replica of the original (for example the target operating system may not support the sort orders required by the exported culture) but it is often better than forcing your users to upgrade. I cover the subject of Custom Cultures in depth in one of the free sample chapters for .NET Internationalization.

The purpose of this post, however, is to explain why it is not so straight forwards exporting cultures from Vista as it is for other operating systems and what you can do to overcome this difference.

The problem lies in the ieftLanguageTag. The ietfLanguageTag is the culture name formatted according to the RFC 3066 standard. It is relevant because the CultureAndRegionInfoBuilder (i.e. the class that builds custom cultures and can ’export’ them) does not save the ietfLanguageTag when it runs on Vista. If you export the English (United States) ("en-US") from Windows XP SP2 and look through the generated LDML file you will find the following line:-

msLocale:ietfLanguageTag type="en-US"

If you do the same from Vista the line won’t be there. This is a problem because if you try to load the resulting LDML file in an older operating system an exception will be thrown and the culture will not be imported. Now naturaly there is no value in exporting the English (United States) culture because all operating systems include this culture but you can see that this is a problem if the whole reason for doing this is to export a Vista culture to Windows XP SP 2.

So the solution to the problem is to add the ietfLanguageTag element back into the LDML file:-

public static void SetIetfLanguageTag(string ldmlFilename, string ietfLanguageTag)
{
const string msLocaleNamespace = "http://schemas.microsoft.com/globalization/2004/08/carib/ldml";

// Vista is version 6
if (System.Environment.OSVersion.Version.Major >= 6)
{
XmlDocument xmlDocument = new XmlDocument();
using (FileStream fileStream = new FileStream(ldmlFilename, FileMode.Open))
{
xmlDocument.Load(fileStream);

XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
xmlNamespaceManager.AddNamespace("msLocale", msLocaleNamespace);

// Check to see if the LDML file is missing the IETF Language Tag.
XmlNode ietfLanguageTagXmlNode = xmlDocument.SelectSingleNode(
"//identity/special/msLocale:ietfLanguageTag", xmlNamespaceManager);
if (ietfLanguageTagXmlNode == null)
{
// the IEFT Language Tag is missing - add it back
XmlNode msLocaleXmlNode = xmlDocument.SelectSingleNode(
"//identity/special", xmlNamespaceManager);
if (msLocaleXmlNode is XmlElement)
{
XmlElement ietfLanguageTagXmlElement =
xmlDocument.CreateElement("msLocale", "ietfLanguageTag", msLocaleNamespace);
ietfLanguageTagXmlElement.SetAttribute("type", ietfLanguageTag);
msLocaleXmlNode.AppendChild(ietfLanguageTagXmlElement);
}
}
}
xmlDocument.Save(ldmlFilename);
}
}

Call this me

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: Guy Smith-Ferrier
Posted on: Friday, March 09, 2007 at 9:26 PM
Categories: Internationalization
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (4) | Post RSSRSS comment feed

Related posts

Comments

Guy Smith-Ferrier

Sunday, March 11, 2007 12:26 AM

guy[at]guysmithferrier[dot]com

G,

Glad you liked the chapter.

I’m not sure I understand the problem exactly. Could you elaborate on what you mean by "it defaults to the default culture" ?

Thanks.

Guy

G Rojas

Sunday, March 11, 2007 12:26 AM

G Rojas

The chapter on Custom Cultures is very well layed out, the only issue I see is that when creating a custom culture and trying to use a resource file for it, it defaults to the default culture. It does not read the values from my specific custom culture resource file (i.e. en-US-XX ) where XX is client specific.

Guy Smith-Ferrier

Sunday, March 11, 2007 12:26 AM

guy[at]guysmithferrier[dot]com

G,

I’m not sure what is going wrong in your app but this works fine for me. I am assuming that your app is a Windows Forms app (because you are explicitly creating a ResourceManager object). I have reproduced a very simplistic example that uses a custom culture and the resource string in ResourceStrings.en-US-Sirius.resx is loaded and used correctly at runtime. I am using the "en-US (Sirius)" custom culture from the downloadable source code for the book (http://www.dotneti18n.com/Downloads.aspx).

Guy

G Rojas

Sunday, March 11, 2007 12:26 AM

G Rojas

I have created a custom culture "en-US-SR". It basically inherets all traits from the "en-US" culture. I create and register it on the pc, the en-US-SR.nlp file gets created and the registry entry also gets created. I then created a resource file "ResourceStrings.en-US-SR.resx" in my project. In this file I have a single key defined (key=Msg1, value="Client Name"). I then set the cutlure to be my custom culture. I have debugged my application to verify that the custom culture is set correctly, but when I call the ResourceManger LocRM.GetString( "Msg1", cultureInfo ) it does not return "Client Name" it returns "Hello World", which is defined in the default resource file ResourceStrings.resx. I also noticed that in the bin directory I don’t get a folder for "en-US-SR" and there is no dll also. I created another resource file "ResourceStrings.fr-FR.resx". This does create the sub-folder in the bin directory named "fr-FR"? How do we basically use a custom culture to do company or client specific verbiage?