I have been posting a lot about the product – Coded UI Test and Microsoft Test Manager.  This is my first post probably on the dev topic.  The post is copy\paste of the internal email that I sent to our dev team.  You will find this useful if you do Globalization\Localization of your code.

 

Based on code reviews, I have observed some common coding confusion among devs.  The #1 coding confusion is mix up between CultureInfo.InvariantCulture and CultureInfo.CurrentCulture.  You will find lots on this on web but none with good examples.  Below is my attempt -

What is CultureInfo?

Provides information about a specific culture (called a "locale" for unmanaged code development). The information includes the names for the culture, the writing system, the calendar used, and formatting for dates and sort strings.

This means a date of 27th November 2010, when converted to string could be “11/27/10” or “27/11/2010” or “27-NOV-2010” or something else depending on the culture.  Similarly parsing back a string “3.3” as double might succeed (e.g. in en-US) or fail (e.g. Fr-fr as comma ‘,’ and not dot ‘.’ is the decimal separator).  So it is important to use right CultureInfo any time you are converting any rich .NET object to string or are parsing string to construct the object.

For example, use CultureInfo in string.Format, XXX.ToString (like DateTime.ToString), XXX.Parse (like int.Parse), XXX.TryParse (like double.TryParse) etc.

What are various CultureInfo’s?

The CultureInfo class has four static CultureInfo properties –

Property

Description

When to use?

InvariantCulture

A fixed (i.e. invariant) culture info which is based on English and is independent of any region or country or other settings & cannot be changed by the user. (Note that this is not same as en-US.)  All objects will give the same string when ToString(CultureInfo.InvariantCulture) is called irrespective of the language, culture, region, country or the customization done by the user. 

1.       To store, retrieve and manipulate data in non-UI layer like storing\retrieving options from registry\configuration files.

2.       To trace\debug or other messages that are for non-end users (like product devs).

CurrentCulture

Culture information of the current thread based on user’s current culture.  This includes the standard culture chosen by the user plus any customization done on top of that (at OS level or within the thread).  Because this includes customization done by the user, even for two people having same en-US culture, the data could be different.

1.       To parse data coming from the user

2.       To show data to the user on the UI or console or data going into the files meant for user.

CurrentUICulture

The user’s culture as represented by standards excluding any customization by user.

There are rare scenarios where one will need these two cultures.  It is best to forget them to avoid confusion.

InstalledUICulture

The culture installed with the OS.

Some Examples!

Use Case

Culture to use

Reason

Take a double as input from the user

CurrentCulture

Data coming as an input from the user. Refer example above – in Fr-fr, “,” and not “.” is decimal point separator.

Take a date time filter from the user via a Text Box (like WIT Query) and parse it into date time object

CurrentCulture

Data coming as an input from the user – she will prefer to give it in her culture.

Show a date time to the user in the UI

CurrentCulture

Data being shown to the user – makes it easy for the user to understand

Show an error message to the user

CurrentCulture

Same as above

Trace a message for debugging

InvariantCulture

Data meant for developer and not the user.  You don’t want to wonder what “12/6/2010” means – 6th Dec or 12th June.

Save users last time filter to registry

InvariantCulture

So that even if user changes her culture, the last time filter option saved in registry works as expected.

Serialize an object into XML to save it on the server (like UITest object)

InvariantCulture

The client and server culture could be different and the same data could be consumed by another user in different culture.

Mixed Scenario –

 

Consider WIT like query where the user gives “Created Date < 12/6/2010” in the query and saves it on the server (assume it saves it as XML). Later she opens the same query.

-          While saving

  • Use CurrentCulture to parse “12/6/2010” into date time object.
  • Use InvariantCulture to serialize the date time object into XML.

-          While opening

  • Use InvariantCulture to deserialize the XML data into the date time object.
  • Use CurrentCulture to convert the date time object into string for the user.

The above might seem cumbersome – why not store and retrieve the data all along in CurrentCulture? The reason is as mentioned above – a) the client & server cultures could be different & b) there may be multiple users having different culture consuming this data.  In fact the same user may have changed her culture between saving and reopening.

Summary

  • Use InvariantCulture when the data is not meant for end-user like trace messages or storing\retrieving configuration options in registry.
  • Use CurrentCulture when the data is meant for the user like taking inputs in a UI or showing it in UI.
  • You will probably never need CurrentUICulture and InstalledUICulture.  Best is to forget those exists.