Thursday, May 11, 2006

Fixing Globalization Problem

Few days ago i received a strange error on our project which deals with numbers and decimals (floating points). It displays a negative number when it should always be a positive number. I couldn't reproduce the error on my laptop and also in my friend's laptop, but my project leader can reproduce it on his laptop. That's weird, since we have the same program. Later, i found out that i used English regional settings while they use Indonesian and Dutch for their regional settings and this was the main problem. English uses dot to separate between number and decimal, meanwhile Indonesian and Dutch uses comma. It will affect how the number are calculated. Yesterday i tried to fix it but i couldn't find the best solution. If i fix in English, it will occur in Indonesian/Dutch and vice versa.

Today i finally find the solution. By using CultureInfo class, i grabbed the local CultureInfo from the computer that was running the program and use the setting (NumberDecimalSeparator) to determine what symbol is being used as a separator between number and decimal. So it will work for any regional settings, because it will follow the computer's regional settings. Yesterday, i tried to use English as the base and do some convertion, but it didn't work. Also, i put the wrong index. I put the index 0 which was the index for Saudi Arabia, so i always got a wrong result. I'm using this code to get the local culture info:
// get local culture information
CultureInfo ciLocal = CultureInfo.CurrentCulture;

Next, i can get the separator for number and decimal by using:

// get the number-decimal separator
ciLocal.NumberFormat.NumberDecimalSeparator.ToString()


So for English, it will return "." and for Indonesian/Dutch, it will return ",". Problem fixed and everybody is happy :D

One note using this solution is that this setting will be saved when the program started, and it will persists until the program ended, so if at runtime you changed your regional setting, you will get the old settings. The reason is because the setting is only valid for current thread, so if we want to change the setting, there are 2 approach that we can use, restart the program or check the setting and overwrite it. I'm taking the first option, since it's not common to change the regional setting while you are playing the game (mostly the users are students). Well anyway it's fixed.

Here are the remarks from Microsoft's MSDN about CultureInfo.CurrentCulture property :

The culture is a property of the executing thread. This read-only property returns Thread.CurrentCulture. When a thread is started, its culture is initially determined by using GetUserDefaultLCID from the Windows API. To change the culture used by a thread, set Thread.CurrentCulture to the new culture. Changing the culture of Thread.CurrentThread requires a SecurityPermission with the ControlThread flag set. Manipulating threads is dangerous because of the security state associated with threads. Therefore, this permission should be given only to trustworthy code, and then only as necessary. You cannot change a thread's culture in semi-trusted code.