0

Guys I'm developing an application that will run across multiple machines. I've recently introduced Cultures in it to support all currencies.

I have 2 main development PCs and I move code between them. One is a Windows 8 laptop, while the other is a Windows 7 PC.

It seems that the list of SpecificCultures in these two machines is NOT the same. When the executable runs on Windows 8, a few more SpecificCultures are returned, and some existing ones are also renamed.

I used the following code to text file dump all Specific Cultures:

StringBuilder sb = new StringBuilder();

foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
{
    sb.Append(ci.Name + "\t" + new RegionInfo(ci.LCID).CurrencyEnglishName);
    sb.AppendLine();
}

StreamWriter f = new StreamWriter(@"specificCulturesFound.txt");
f.Write(sb);
f.Close();

The SpecificCultures returned from my Windows 8 Laptop is this: http://pastebin.com/cznLRG62 The SpecificCultures returned from my Windows 7 PC is this: http://pastebin.com/MwMXwSdb

If you compare them in Notepad++ or something, you'll see differences.

For Example: For example, the et-EE Estonian Kroon entry is only available on my Windows 7 PC, while ku-Arab-IQ Iraqi Dinar is only available on Windows 8 Laptop

Question is, how can I deal with this situation ? Once the application is released, it will be run on different machines with different .NET framework versions.

Is there a way to maybe export all collected CultureInfo data with the application, so that can be used instead of getting it from the installed .NET framework ?

Ahmad
  • 12,886
  • 30
  • 93
  • 146
  • You can always fall back on [`CultureInfo.InvariantCulture`](http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.invariantculture.aspx) – Wim Ombelets Apr 12 '13 at 09:35

1 Answers1

0

It's not an easy situation, in normal conditions your application shouldn't not be aware of differences between cultures, what it should be aware is just that differences exist.

This is usually done saving everything in a neutral culture (let's say, for example, en-US locale) then converting back to the specific locale of the user where application runs. For example if user enters a list of date values what you do to save them is to convert each date to its neutral representation and to concatenate them using the list separator (both using the neutral culture, you can do it because you can get the current locale of the user and you know the neutral one). Later, in another machine with a different locale, someone else will read that file, your application knows that that dates are in neutral culture then it can read them and to present them to the user with required formatting. Example:

  • User with it-IT locale enters two dates: 01/01/1960;25/12/2013.
  • Application stores it in a neutral en-US format: 01/01/1977,12/25/2013.
  • Another user with jp-JP locale will read it, application will read the neutral locale and will show it to the user as 1977/01/01・2013/12/25.

Things become more complicated when this data aren't fixed, for example currencies. In this case you can't simply convert to a neutral value, let's imagine this (values are pretty random):

  • User enters a value in, let's say, 1000 YEN.
  • You convert YEN to DOLLARS (imagine 100 YEN = 1 DOLLAR): 10 DOLLARS and you save it.
  • Data will be read in another country in Europe where EURO is in use, application read 10 DOLLARS then it'll convert it to 10 EURO.

This is wrong of course because:

  • Change YEN <-> DOLLARS may be changed from the day you wrote it and the day it'll be read in EURO.
  • Change YEN <-> EURO is not equivalent to YEN <-> DOLLARS <-> EURO.

This is not an easy solving problem, you simply can't rely on "automatic" conversions via CultureInfo but you have to implement this by your own (in the way that best suits your requirements). For example (very naive, of course) implementation may store currencies like this:

struct CurrencyValue
{
    public decimal Value;
    public string Currency;
}

This may be complicated as needed (using a class hierarchy instead of currencies instead of a string, for example) but just keep in mind that this kind of conversion is absolutely not trivial.

To summarize

Don't care about this conversions, just store everything using a neutral locale and conversion (to and from) will happen in the user machine (where you don't need to care about which locale is in use).

If you have to manage special types like currencies then you have to implement your own library to handle them in the proper way. What "proper way" is depends on your full application requirements so it can't be answered here.

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • Thanks for the reply! The issue is that my application has a lot of money-related stuff in it. One particular use is that the user needs to specify a price. This is done by first selecting a Currency from a drop-down (e.g. `US Dollar`), and then specifying the numeric value in a textbox. I actually store the locale selected by the user in DB with the numeric value. Now suppose a user selects a currency which *IS* available in one machine, and *IS NOT* available in another. In such a case, when the application reads that currency's locale on the Database, it won't know which currency is it. – Ahmad Apr 12 '13 at 10:17
  • Names can vary and you shouldn't rely on them, LCIDs are more stable so you should store/use them instead (but a newer version can support locales that doesn't exist in an older version). To get ALL cultures you should use CultureTypes.AllCultures and to get back the CultureInfo you may use CultureInfo.GetCultureInfo() with the LCID you need. Of course the case that LCID is unknown must be handled (but using IDs not so probable). – Adriano Repetti Apr 12 '13 at 10:58
  • Yeah I guess LCID would be a safer thing to store than `ku-Arab-IQ`. But still how would I handle the unknown LCID case ? I don't think using LCID instead of something like `ku-Arab-IQ` would really help me with this problem. Or am I missing something out ? – Ahmad Apr 12 '13 at 13:33
  • Well, name may change (for example because a political definition of a country changes) but its LCID would remain the same). Moreover the same name is sometimes assigned to different locale because it's the same country (India, for example). Anyway yes, you have to handle the case that an ID doesn't exist (it may not be probable but it's at least possible). How? You may deploy with your application a list of known cultures with basic needed informations, when you have an unkown ID you create a custom CultureInfo and you fill it with that informations. – Adriano Repetti Apr 12 '13 at 14:08
  • This won't limit your users to that list and it'll give you a chance to handle this kind of changes between Windows versions (at least as **ultimate fallback before you prompt an error**). – Adriano Repetti Apr 12 '13 at 14:09