In .NET is there any way to convert from three letter country codes (defined in ISO 3166-1 alpha-3) to two letter language codes (defined in ISO 3166-1 alpha-2) eg. convert
Looks like there is no built-in way to do that. You can use the approach from the GenericTypeTea's answer. But if you need to convert many country codes you can avoid Cultures enumeration and pre-compute a mapping dictionary for country codes conversion.
That's how such generator looks like:
namespace ISOCountryCodes
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
class Program
{
public static void Main(string[] args)
{
var countryCodesMapping = new Dictionary<string, RegionInfo>();
CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
foreach (var culture in cultures)
{
try
{
var region = new RegionInfo(culture.LCID);
countryCodesMapping[region.ThreeLetterISORegionName] = region;
}
catch (CultureNotFoundException)
{
var consoleColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Culture not found: " + culture.Name);
Console.ForegroundColor = consoleColor;
}
}
Console.WriteLine("var countryCodesMapping = new Dictionary<string, string>() {");
foreach (var mapping in countryCodesMapping.OrderBy(mapping => mapping.Key))
{
Console.WriteLine(" {{ \"{0}\", \"{1}\" }}, // {2}", mapping.Key, mapping.Value.TwoLetterISORegionName, mapping.Value.EnglishName);
}
Console.WriteLine("};");
}
}
}
Run this generator to get a country codes mapping dictionary like this:
var countryCodesMapping = new Dictionary<string, string>() {
{ "AFG", "AF" }, // Afghanistan
{ "ALB", "AL" }, // Albania
{ "ARE", "AE" }, // U.A.E.
{ "ARG", "AR" }, // Argentina
{ "ARM", "AM" }, // Armenia
{ "AUS", "AU" }, // Australia
{ "AUT", "AT" }, // Austria
{ "AZE", "AZ" }, // Azerbaijan
{ "BEL", "BE" }, // Belgium
{ "BGD", "BD" }, // Bangladesh
{ "BGR", "BG" }, // Bulgaria
{ "BHR", "BH" }, // Bahrain
{ "BIH", "BA" }, // Bosnia and Herzegovina
{ "BLR", "BY" }, // Belarus
{ "BLZ", "BZ" }, // Belize
{ "BOL", "BO" }, // Bolivia
{ "BRA", "BR" }, // Brazil
{ "BRN", "BN" }, // Brunei Darussalam
{ "CAN", "CA" }, // Canada
{ "CHE", "CH" }, // Switzerland
{ "CHL", "CL" }, // Chile
{ "CHN", "CN" }, // People's Republic of China
{ "COL", "CO" }, // Colombia
{ "CRI", "CR" }, // Costa Rica
{ "CZE", "CZ" }, // Czech Republic
{ "DEU", "DE" }, // Germany
{ "DNK", "DK" }, // Denmark
{ "DOM", "DO" }, // Dominican Republic
{ "DZA", "DZ" }, // Algeria
{ "ECU", "EC" }, // Ecuador
{ "EGY", "EG" }, // Egypt
{ "ESP", "ES" }, // Spain
{ "EST", "EE" }, // Estonia
{ "ETH", "ET" }, // Ethiopia
{ "FIN", "FI" }, // Finland
{ "FRA", "FR" }, // France
{ "FRO", "FO" }, // Faroe Islands
{ "GBR", "GB" }, // United Kingdom
{ "GEO", "GE" }, // Georgia
{ "GRC", "GR" }, // Greece
{ "GRL", "GL" }, // Greenland
{ "GTM", "GT" }, // Guatemala
{ "HKG", "HK" }, // Hong Kong S.A.R.
{ "HND", "HN" }, // Honduras
{ "HRV", "HR" }, // Croatia
{ "HUN", "HU" }, // Hungary
{ "IDN", "ID" }, // Indonesia
{ "IND", "IN" }, // India
{ "IRL", "IE" }, // Ireland
{ "IRN", "IR" }, // Iran
{ "IRQ", "IQ" }, // Iraq
{ "ISL", "IS" }, // Iceland
{ "ISR", "IL" }, // Israel
{ "ITA", "IT" }, // Italy
{ "JAM", "JM" }, // Jamaica
{ "JOR", "JO" }, // Jordan
{ "JPN", "JP" }, // Japan
{ "KAZ", "KZ" }, // Kazakhstan
{ "KEN", "KE" }, // Kenya
{ "KGZ", "KG" }, // Kyrgyzstan
{ "KHM", "KH" }, // Cambodia
{ "KOR", "KR" }, // Korea
{ "KWT", "KW" }, // Kuwait
{ "LAO", "LA" }, // Lao P.D.R.
{ "LBN", "LB" }, // Lebanon
{ "LBY", "LY" }, // Libya
{ "LIE", "LI" }, // Liechtenstein
{ "LKA", "LK" }, // Sri Lanka
{ "LTU", "LT" }, // Lithuania
{ "LUX", "LU" }, // Luxembourg
{ "LVA", "LV" }, // Latvia
{ "MAC", "MO" }, // Macao S.A.R.
{ "MAR", "MA" }, // Morocco
{ "MCO", "MC" }, // Principality of Monaco
{ "MDV", "MV" }, // Maldives
{ "MEX", "MX" }, // Mexico
{ "MKD", "MK" }, // Macedonia (FYROM)
{ "MLT", "MT" }, // Malta
{ "MNE", "ME" }, // Montenegro
{ "MNG", "MN" }, // Mongolia
{ "MYS", "MY" }, // Malaysia
{ "NGA", "NG" }, // Nigeria
{ "NIC", "NI" }, // Nicaragua
{ "NLD", "NL" }, // Netherlands
{ "NOR", "NO" }, // Norway
{ "NPL", "NP" }, // Nepal
{ "NZL", "NZ" }, // New Zealand
{ "OMN", "OM" }, // Oman
{ "PAK", "PK" }, // Islamic Republic of Pakistan
{ "PAN", "PA" }, // Panama
{ "PER", "PE" }, // Peru
{ "PHL", "PH" }, // Republic of the Philippines
{ "POL", "PL" }, // Poland
{ "PRI", "PR" }, // Puerto Rico
{ "PRT", "PT" }, // Portugal
{ "PRY", "PY" }, // Paraguay
{ "QAT", "QA" }, // Qatar
{ "ROU", "RO" }, // Romania
{ "RUS", "RU" }, // Russia
{ "RWA", "RW" }, // Rwanda
{ "SAU", "SA" }, // Saudi Arabia
{ "SCG", "CS" }, // Serbia and Montenegro (Former)
{ "SEN", "SN" }, // Senegal
{ "SGP", "SG" }, // Singapore
{ "SLV", "SV" }, // El Salvador
{ "SRB", "RS" }, // Serbia
{ "SVK", "SK" }, // Slovakia
{ "SVN", "SI" }, // Slovenia
{ "SWE", "SE" }, // Sweden
{ "SYR", "SY" }, // Syria
{ "TAJ", "TJ" }, // Tajikistan
{ "THA", "TH" }, // Thailand
{ "TKM", "TM" }, // Turkmenistan
{ "TTO", "TT" }, // Trinidad and Tobago
{ "TUN", "TN" }, // Tunisia
{ "TUR", "TR" }, // Turkey
{ "TWN", "TW" }, // Taiwan
{ "UKR", "UA" }, // Ukraine
{ "URY", "UY" }, // Uruguay
{ "USA", "US" }, // United States
{ "UZB", "UZ" }, // Uzbekistan
{ "VEN", "VE" }, // Bolivarian Republic of Venezuela
{ "VNM", "VN" }, // Vietnam
{ "YEM", "YE" }, // Yemen
{ "ZAF", "ZA" }, // South Africa
{ "ZWE", "ZW" }, // Zimbabwe
};
To the fellow lurker: if what you want is just to derive "default" country for a given two letter language name in .NET world (for example "en" => "US", "ja" => "JP"), this does the trick
// Can be read from CultureInfo.Name (or CultureInfo.Parent.Name if using non-generic culture)
var language = "ja"; // Japanese
// Creates "ja-JP" culture
var defaultCulture = CultureInfo.CreateSpecificCulture(language);
// After this, just take the split[1] (careful, check index) to get country code
var split = defaultCulture.Name.Split('-');
I've this working with a JS library that accepts only ISO3166 codes, and for 25 languages our website supports this works flawlessly. Always test your scenario
The RegionInfo
class does know the three-letter code (in the ThreeLetterISORegionName property), but I don’t think there is a way to get RegionInfo
based on this code, you would need to enumerate all regions and add them to your own dictionary, with the three-letter code as a key.
However, I think the .NET Framework uses RegionInfo
to work with cultures, not countries in the ISO 3166-1 sense. Therefore, many countries from the ISO 3166-1 standard are not available (try e.g. SX
). I guess you should create your own country codebook.
Edit: From 246 countries in my current country codebook, RegionInfo
is available for 125 of them, the rest (121) are not supported. Conclusion: This is not a good way to get a country codebook.
You can try using .NET RegionInfo as it is described HERE:
using System;
using System.Globalization;
public class SamplesRegionInfo {
public static void Main() {
// Displays the property values of the RegionInfo for "US".
RegionInfo myRI1 = new RegionInfo( "US" );
Console.WriteLine( " Name: {0}", myRI1.Name );
Console.WriteLine( " DisplayName: {0}", myRI1.DisplayName );
Console.WriteLine( " EnglishName: {0}", myRI1.EnglishName );
Console.WriteLine( " IsMetric: {0}", myRI1.IsMetric );
Console.WriteLine( " ThreeLetterISORegionName: {0}", myRI1.ThreeLetterISORegionName );
Console.WriteLine( " ThreeLetterWindowsRegionName: {0}", myRI1.ThreeLetterWindowsRegionName );
Console.WriteLine( " TwoLetterISORegionName: {0}", myRI1.TwoLetterISORegionName );
Console.WriteLine( " CurrencySymbol: {0}", myRI1.CurrencySymbol );
Console.WriteLine( " ISOCurrencySymbol: {0}", myRI1.ISOCurrencySymbol );
}
}
/*
This code produces the following output.
Name: US
DisplayName: United States
EnglishName: United States
IsMetric: False
ThreeLetterISORegionName: USA
ThreeLetterWindowsRegionName: USA
TwoLetterISORegionName: US
CurrencySymbol: $
ISOCurrencySymbol: USD
*/
There's ISO3166
Nuget package that provides list of ISO3166 countries that include name, 2 and 3 letter code, and numberic code.
Some of the above answers are O(N) for lookups, which is fine if you're only doing it once, but generally you'll want to call this more than once per process in which case you'll probably want something more efficient.
var Iso3ToIso2Mapping = CultureInfo.GetCultures(CultureTypes.SpecificCultures)
.Select(ci => new RegionInfo(ci.LCID))
.GroupBy(ri => ri.ThreeLetterISORegionName)
.ToDictionary(g => g.Key, g => g.First().TwoLetterISORegionName);
Then you can just do a lookup with:
var iso2CountryCode = Iso3ToIso2Mapping["AUS"];
Console.WriteLine(iso2CountryCode);
Prints:
AU