Get user's ISO 3166-1 alpha-2 country code

I’d like to know a reliable way to get the user’s ISO 3166-1 alpha-2 (2-letter code, ex : US, CA) with c# in unity3d ?

I’ve tried RegionInfo.TwoLetterISORegionName but it returns an empty string.

Are they not implemented ?

How do I do this ?

The main error I’m getting here is that the TwoLetterISORegionName is empty when I try and get it. The CultureInfo and RegionInfo are always returning United States as the culture unless I use this workaround :


RegionInfo regionInfo = newRegionInfo(GetSystemDefaultLCID());
CultureInfo cultureInfo = newCultureInfo(GetSystemDefaultLCID());

However, the TwoLetterISORegionName is empty and the ThreeLetterWindowsRegionName returns something like “Canada”, which is no good for me.


Here’s the Debug information I get using the code above :

	Debug.Log("----- REGION INFO -----"); // Empty
	Debug.Log("CurrencyEnglishName : " + regionInfo.CurrencyEnglishName); // Empty
	Debug.Log("CurrencyNativeName : " + regionInfo.CurrencyNativeName); // Not implemented exception
	Debug.Log("CurrencySymbol : " + regionInfo.CurrencySymbol); // CAD
	Debug.Log("DisplayName : " + regionInfo.DisplayName); // Empty
	Debug.Log("EnglishName : " + regionInfo.EnglishName); // Empty
	Debug.Log("GeoId : " + regionInfo.GeoId); // 959515600
	Debug.Log("IsMetric : " + regionInfo.IsMetric); // True
	Debug.Log("ISOCurrencySymbol : " + regionInfo.ISOCurrencySymbol); // Canadian Dollar
	Debug.Log("Name : " + regionInfo.Name); // Empty
	Debug.Log("NativeName : " + regionInfo.NativeName); // Empty
	Debug.Log("ThreeLetterISORegionName : " + regionInfo.ThreeLetterISORegionName); // Empty
	Debug.Log("ThreeLetterWindowsRegionName : " + regionInfo.ThreeLetterWindowsRegionName); // Canada
	Debug.Log("TwoLetterISORegionName : " + regionInfo.TwoLetterISORegionName); // Empty

Obviously those are wrong values (well it’s right, I’m in Canada and all, but the 3 letter code isn’t “Canada”, and the geoid can’t be that big a number last I checked), or I’m missing something !

Quick update : The GeoID returned is always different, which makes no sense at all, as if it was randomly generated. Also, my Unity version is 4.3.4f, so I believe I’m pretty much up to date.

Finally ended up finding a solution… and I’m not liking it, but hell it works. Opened up Visual Express 2008 (important that it is 2008, because you can’t change target .NET platform on later versions, I believe) and created a .dll using the exact same class (RegionInfo) that I would have used in Unity C#.

So in C++/CLR : Create a .dll with a function that takes a char* as a parameter, assign the 2 characters from the System::String you get from the TwoLetterISORegionName and thats it. Copy the .dll in the plugins folder in Unity.

In C#/Unity : Link the .dll using DllImport and your method name (the method will not take a char* here but a IntPtr). Allocate the bytes to the IntPtr here, then call the C++ function, then Read the bytes, (cast them as chars for every index), and finally don’t forget to release the memory. Allocate, Read and Release were used with the Marshal class.

This wouldn’t work very well with a ton of characters but since I have only 2 it’s not too bad. I realize this is a sketchy solution at best and demands a lot of work but since the RegionInfo class doesn’t work well in Unity this is what I came up with. Hope I might help someone out !