Convert ISO 3166-1 alpha-2 Country Code to a Localized Country Name

Is there a way to convert two-letter country codes into readable copies without using external resources?

eg. DE -> Germany , AD -> Andorra

It would be great if I could choose the target language or use the system language, because I would like to have them in German.

+6
source share
3 answers

As @Uwe mentioned in his comment, you can use the EnumSystemGeoID and GetGeoInfo functions. The principle is that using the EnumSystemGeoID function EnumSystemGeoID you list the geographic location identifiers and GetGeoInfo if the requested ISO country / region code of the 2-letter ISO identifier ( GEO_ISO2 information GEO_ISO2 ) corresponds to one of your interests. If so, you can request for this identifier with the same function either a friendly name (information type GEO_FRIENDLYNAME ) or an official name (information type GEO_OFFICIALNAME ), return the result and stop the listing.

Here is an example of code that can do this (unfortunately, the enumeration function does not support the transfer of user data, so I used a global write variable to pass values):

 type TEnumData = record GeoCode: string; GeoName: string; Success: Boolean; end; GEOID = type LONG; GEOTYPE = type DWORD; GEOCLASS = type DWORD; SYSGEOTYPE = ( GEO_NATION = $0001, GEO_LATITUDE = $0002, GEO_LONGITUDE = $0003, GEO_ISO2 = $0004, GEO_ISO3 = $0005, GEO_RFC1766 = $0006, GEO_LCID = $0007, GEO_FRIENDLYNAME= $0008, GEO_OFFICIALNAME= $0009, GEO_TIMEZONES = $000A, GEO_OFFICIALLANGUAGES = $000B, GEO_ISO_UN_NUMBER = $000C, GEO_PARENT = $000D ); SYSGEOCLASS = ( GEOCLASS_NATION = 16, GEOCLASS_REGION = 14, GEOCLASS_ALL = 0 ); GEO_ENUMPROC = function(GeoId: GEOID): BOOL; stdcall; function EnumSystemGeoID(GeoClass: GEOCLASS; ParentGeoId: GEOID; lpGeoEnumProc: GEO_ENUMPROC): BOOL; stdcall; external kernel32 name 'EnumSystemGeoID'; function GetGeoInfo(Location: GEOID; GeoType: GEOTYPE; lpGeoData: LPTSTR; cchData: Integer; LangId: LANGID): Integer; stdcall; external kernel32 name {$IFDEF UNICODE}'GetGeoInfoW'{$ELSE}'GetGeoInfoA'{$ENDIF}; implementation var // I have used this global variable due to a lack of user data parameter for the callback function EnumData: TEnumData; function TryGetGeoInfo(GeoId: GEOID; GeoType: GEOTYPE; out Value: string): Boolean; var Buffer: string; BufferLen: Integer; begin Result := False; BufferLen := GetGeoInfo(GeoId, GeoType, LPTSTR(Buffer), 0, 0); if BufferLen <> 0 then begin SetLength(Buffer, BufferLen); Result := GetGeoInfo(GeoId, GeoType, LPTSTR(Buffer), BufferLen, 0) <> 0; if Result then Value := Trim(Buffer); end; end; function EnumGeoInfoProc(GeoId: GEOID): BOOL; stdcall; var S: string; begin Result := TryGetGeoInfo(GeoId, GEOTYPE(GEO_ISO2), S); if Result and (S = EnumData.GeoCode) then begin // stop the enumeration since we've found the country by its ISO code Result := False; // return the success flag and try to return the friendly name of the country to the // EnumData.GeoName record field; you can optionally query the GEO_OFFICIALNAME EnumData.Success := TryGetGeoInfo(GeoId, GEOTYPE(GEO_FRIENDLYNAME), EnumData.GeoName); end; end; function TryGetCountryNameByISO2(const Code: string; out Name: string): Boolean; begin // here is the brainless part using global record variable (because the function used // here with its callback does not support passing user data); no, you cannot tune it // up by making the callback function nested EnumData.GeoCode := Code; EnumData.Success := False; if not EnumSystemGeoID(GEOCLASS(GEOCLASS_NATION), 0, EnumGeoInfoProc) then RaiseLastOSError; Result := EnumData.Success; if Result then Name := EnumData.GeoName; end; 

And possible use:

 var S: string; begin if TryGetCountryNameByISO2('DE', S) then ShowMessage(S); end; 
+6
source

You can iterate over Languages (from Sysutils) and check the Ext property. The corresponding Name property will give you a localized language name.

  for I := 0 to Languages.Count - 1 do begin Writeln(Languages.Ext[I], '=', Languages.Name[I]); end; 
+3
source

The sublingual element suggested by Uwe Raabe helps, but the results are not so good, because it will not find all ISO codes and sometimes returns something else by the name of the country, for example Simplified Chinese .

 function _GetCountryFromISO(const aISO: string): string; const cStatement1 = '-(.*)'; cStatement2 = '\((.*?)\)'; var i: Integer; match: TMatch; begin Result := aISO; // default result if not found for i := 0 to Languages.Count - 1 do begin match := TRegEx.Match(Languages.LocaleName[i], cStatement1); if not match.Success then Assert(False, ''); if (aISO.Equals(match.Groups[1].Value)) then begin match := TRegEx.Match(Languages.Name[i], cStatement2); if not match.Success then Assert(False, ''); Exit(match.Groups[1].Value); end; end; end; 
0
source

Source: https://habr.com/ru/post/973800/


All Articles