4

I need to localize my C# DateTime object based on a two letter ISO-3166 country code

https://en.wikipedia.org/wiki/ISO_3166-2

Is there a way to do it?

I'm only able to apply a given culture using the 5 character country representation (en-US, nl-NL and so on..)

System.Globalization.CultureInfo cultureinfo =
        new System.Globalization.CultureInfo("nl-NL");
DateTime dt = DateTime.Parse(date, cultureinfo);

Even a surjective mapping would be ok (i.e. more than one country code map to a single C# culture)

Gianluca Ghettini
  • 11,129
  • 19
  • 93
  • 159
  • I'm not clearly understand your question. Can't you use `CultureInfo("NL")` as well? Looks like this constructor uses [National Language Support (NLS) API Reference](https://msdn.microsoft.com/en-us/goglobal/bb896001.aspx) which I'm not %100 sure which ISO standard it has. – Soner Gönül Jan 13 '16 at 11:18
  • so basically CultureInfo accepts natively ISO-3166 country codes?. If I run var cultureinfo = new System.Globalization.CultureInfo("US"); I get a "not supported" exception – Gianluca Ghettini Jan 13 '16 at 11:19
  • ++ (or maybe it has own standard?) BTW, both `NL` and `nl-NL` has the same `TwoLetterISOLanguageName` and `ThreeLetterISOLanguageName` properties. But this is not true for all cases like `EE` as ISO 3166-1 alpha-2 code. – Soner Gönül Jan 13 '16 at 11:26

4 Answers4

5

From CultureInfo(string) constructor documentation;

For a list of predefined culture names, see the National Language Support (NLS) API Reference

Also from CultureInfo.TwoLetterISOLanguageName Property

The ISO 639-1 two-letter code for the language of the current CultureInfo.

There is no US defined but there is en (if you really have to use two letter name) which you can use it. All of them defined in that standard.

var cultureInfo = new CultureInfo("en");

All of that two-letter codes are valid except iv which is for InvariantCulture so we can ignore it. I wrote a simple code to check it.

foreach (var culture in CultureInfo.GetCultures(CultureTypes.AllCultures))
{
     try
     {
          var c = new CultureInfo(culture.TwoLetterISOLanguageName);
     }
     catch (Exception)
     {
          Console.WriteLine(culture.TwoLetterISOLanguageName); // Only prints "iv"
     }
}

How to create your own mapping? I suggest to follow these steps;

  • Find the different two-letter codes in ISO-3166 and ISO 639-1 standards.
  • Create your own KeyValuePair<string, string> structure which contains ISO-3166 two-letter codes as the first one and ISO 639-1 two-letter codes as the second one.
  • If your two-letter ISO-3166 two-letter code fails in this constructor, check it's mapped two-letter code and try to create your CultureInfo using that two-letter code.
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
1

You should be able to use an invariant culture, if it's supported by .net.

E.g. This works:

var culture = new CultureInfo("EN");

As you've noted, there doesn't appear to be full support for all country codes, this is because the two characters it takes are a Neutral Culture.

You can get a list of all supported cultures via:

CultureInfo.GetCultures(CultureTypes.AllCultures);

And specifically Neutral ones with:

CultureInfo.GetCultures(CultureTypes.NeutralCultures);

The reason that var culture = new CultureInfo("US"); doesn't work is because the neutral culture for US is EN. (the specific culture being en-US).

There are other high voted answers on converting Country Codes to Cultures, which I'm not going to dupe here.

Community
  • 1
  • 1
NikolaiDante
  • 18,469
  • 14
  • 77
  • 117
1

The last part of CultureInfo.Name is country's ISO-3166 code, so this is how I ended up my solution,

public static CultureInfo GetCultureFromTwoLetterCountryCode(string twoLetterISOCountryCode)
{
    try
    {
        return CultureInfo.GetCultures(CultureTypes.AllCultures 
                                           & ~CultureTypes.NeutralCultures)
                  .Where(m => m.Name.EndsWith("-"+twoLetterISOCountryCode))
                  .FirstOrDefault();
     }
     catch
     {
         return null;
     }
}

The only problem is some countries have more than one culture like GB, so you can't select the right culture just with ISO-3166 code,

cy-GB Welsh (United Kingdom)

en-GB English (United Kingdom)

gd-GB Scottish Gaelic (United Kingdom)

So GetCultureFromTwoLetterCountryCode("GB") will return "cy-GB" culture which may be ok for Wales but not for Scotland.

You can ignore these kind of exceptions or create your own cultureinfo database and store only one culture for each country. That will be the best solution.

Okan Kocyigit
  • 13,203
  • 18
  • 70
  • 129
0

I think you're confusing regions with cultures?

RegionInfo r = new RegionInfo("US");
MessageBox.Show(r.DisplayName);

This will return "United States"

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
David Homer
  • 396
  • 2
  • 8