Designing for Internationalization

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 nameus, nameda, 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 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:

Logitech SmartCam 124

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:

publicstatic Dictionary<string, string> GetDictionary(string xml) { if (String.IsNullOrEmpty(xml)) returnnew 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:

publicstaticstring 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/

Martin H. Normark

Product and UX Hacker. Web and iOS developer.

Subscribe to Martin Normark's Blog

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!