0%

When your software doesn't work in China

I had an interesting bug submitted by a user, he wrote that our product was crashing in his Visual Studio 2010, which was a Traditional Chinese edition.

Typemock Isolator, being a Visual Studio add-in, adds a menu next to the Tools menu in Visual Studio. It does so by looking for an index of the Tools menu in the main menu bar, and simply adding the Typemock menu after it. However, the Tools menu is only called that in the English locale. In other languages, the menu might be called differently. In French, for instance, it’s called Outils.

When creating a new Visual Studio 2008 Add-in (under Other Project Types - Extensibility), if selected the Yes, create a Tools menu item in page 4 of the wizard, the following code is generated in OnConnect method after completing the wizard:

...
string resourceName;
ResourceManager resourceManager = new ResourceManager("MyAddin.CommandBar", Assembly.GetExecutingAssembly());
CultureInfo cultureInfo = new CultureInfo(_applicationObject.LocaleID);

if (cultureInfo.TwoLetterISOLanguageName == "zh")
{
System.Globalization.CultureInfo parentCultureInfo = cultureInfo.Parent;
resourceName = String.Concat(parentCultureInfo.Name, "Tools");
}
else
{
resourceName = String.Concat(cultureInfo.TwoLetterISOLanguageName, "Tools");
}
toolsMenuName = resourceManager.GetString(resourceName);
...

Unfortunately, this auto-generated code violates almost every known good coding practice. In particular, it gives no clues as to why zh is different, and why it’s handled separately.

Visual Studio menus are localized in the following way: a resource file, CommandBar.resx, is added to the project. This resource file contains translations of all common menus in Visual Studio, and each entry is defined by appending the two-letter ISO language code to the menu name, so that the entry for Debug in Spanish, for example, is esDebug.

There are two separate entries for both Traditional and Simplified Chinese in the resource file, and the entries are prefixed with zh-CHS and zh-CHT (zh is a short for Zhōngwén). Those identifiers refer to the old culture names. Since Windows Vista, the new zh-Hans and zh-Hant names are used, and the older names are kept for backwards compatibility. They can be found in the Parent property of the CultureInfo, specifying the current Visual Studio Locale ID (LCID).

Now that I had an understanding why zh was different, I was able to solve the bug by simply checking for the Chinese culture, and returning the correct identifier:

private string GetCurrentLocaleName(CultureInfo cultureInfo)
{
// Chinese (Traditional and Simplified) use "old" locale code,
// zh-CHT and zh-CHS, which is the name of the parent culture
if (cultureInfo.TwoLetterISOLanguageName == ChineseTwoLetterISOLanguageName)
{
return cultureInfo.Parent.Name;
}

return cultureInfo.TwoLetterISOLanguageName;
}