有没有办法在不使用外部资源的情况下将两个字母的国家代码转换为可读的对应部分?
e.g。 DE -> Germany
,AD -> Andorra
如果我可以选择目标语言或使用系统语言会很棒,因为我想用德语提供它们。
答案 0 :(得分:6)
正如@Uwe在评论中提到的,您可以使用EnumSystemGeoID
和GetGeoInfo
函数。原则是,使用EnumSystemGeoID
函数,您将枚举地理位置标识符,并通过GetGeoInfo
函数查询枚举标识符的ISO 2字母国家/地区代码(信息类型{ {3}})等于你感兴趣的一个。如果是这样,那么您可以使用相同的函数查询此标识符,无论是友好名称(信息类型GEO_ISO2
)还是官方名称(信息类型GEO_FRIENDLYNAME
),都会返回结果并停止枚举。
这是一个示例代码,可能会这样做(遗憾的是,枚举函数不支持传递自定义数据,因此我使用了全局记录变量来传递值):
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;
可能的用法:
var
S: string;
begin
if TryGetCountryNameByISO2('DE', S) then
ShowMessage(S);
end;
答案 1 :(得分:3)
您可以迭代Languages
(来自Sysutils)并检查Ext
属性。相应的Name
属性将为您提供本地化的语言名称。
for I := 0 to Languages.Count - 1 do begin
Writeln(Languages.Ext[I], '=', Languages.Name[I]);
end;
答案 2 :(得分:0)
Uwe Raabe建议的子语言元素正在帮助,但结果并不好,因为它找不到所有ISO代码,有时会返回与国家/地区名称不同的内容,例如{{1} }。
Simplified Chinese