Web sites and Web Applications today, are very often exposed beyond the borders of your home country, and therefore users speak different languages, and has a different currency, date- and time formats etc. ASP.NET provides you with an entire namespace for handling things like this. That is the System.Globalization namespace, where you will find a lot of classes for handling your every day globalization tasks. I’m not going to cover anything in this namespace now, if you want to get your hands dirty take a look at this video: http://asp.net/learn/videos/video-40.aspx where you will see how to use local and global resources for your application.

Using a global resource file for a place to store display text on buttons, labels, validation controls etc. is fine. But if you have an e-commerce site, selling products in multiple regions with different languages, you need an extra level. That level is a way to globalize e.g. the name and description of your product. When a user changes language, the name and description of your “display product details page” should change accordingly.

For me, the ideal solution should not result in extra database columns like name_us, name_da, name_es. This would be a very static solution, as you would have to change your database whenever a new language is added to your application. Nor should it require extra tables, so you need to join like hell, when you need to select a product.

I’ve decided to store e.g. the Name values as XML in the database, and parse that XML into a Dictionary<string, string> property on my Product object, with the key of the Dictionary being the language code (en-US for US English). To me this seems to work just fine. My database design is not getting more complex, and I can get and set values quite easily.

The XML string that goes into my ProductName column in the database table, looks like this:

<cultures><culture code=”en-us”>Logitech SmartCam 124</culture></cultures>

On my Product object, the Name property is a Dictionary:

private Dictionary<string, string> _Name;

public Dictionary<string, string> Name
{
  get { return _Name; }
  set
  {
    if (_Name != value) MarkDirty("Name");
    _Name = value;
  }
}

When I need to get the US English value of the Product.Name property, I call:

p.Name["en-us"]

To get a Dictionary from my XML, I use this helper method:

public static Dictionary<string, string> GetDictionary(string xml)
{
  if (String.IsNullOrEmpty(xml))
    return new Dictionary<string, string>(owner);

  XmlDocument doc = new XmlDocument();
  doc.LoadXml(xml);

  Dictionary<string, string> dic = new Dictionary<string, string>();

  foreach (XmlNode node in doc.DocumentElement)
  {
    dic.Add(node.Attributes["code"].Value, node.InnerText);
  }

  return dic;
}

And when I want to update my database, after I change the Name of the Product, I convert to Dictionary to an XML string using this helper method:

public static string GetXmlDocument(Dictionary<string, string> dic)
{
  XmlDocument doc = new XmlDocument();
  XmlNode docElement = doc.CreateNode(XmlNodeType.Element, "cultures", "");

  foreach (string key in dic.Keys)
  {
    XmlNode node = doc.CreateNode(XmlNodeType.Element, "culture", "");
    XmlAttribute att = doc.CreateAttribute("code");
    att.Value = key;
    node.Attributes.Append(att);

    node.InnerText = dic[key];

    docElement.AppendChild(node);
  }

  doc.AppendChild(docElement);

  return doc.OuterXml;
}

If you need more information on this huge topic, take a look at the ASP.NET Wiki: http://wiki.asp.net/page.aspx/55/internationalization/

« »