如何将ISO 639-1代码转换为语言ID

时间:2011-05-17 10:25:07

标签: delphi winapi localization

有没有办法使用Windows API从语言ISO代码中获取主要语言ID?我想将它用于我的GetDateFormatInt函数,我很好奇是否有一种不使用常量的方法。虽然该函数不使用英语的默认子语言,但我只对主语言ID感兴趣。

function GetDateFormatInt(const aLanguageISOCode: string): string;
const
  C_ISO_CODES: array[0..3] of string = (
    'nl', 'en', 'de', 'fr'
  );
  C_LCIDS: array[0..3] of Cardinal = (
    ((SUBLANG_DUTCH shl 10) or LANG_DUTCH) or (SORT_DEFAULT shl 16),
    ((SUBLANG_ENGLISH_UK shl 10) or LANG_ENGLISH) or (SORT_DEFAULT shl 16),
    ((SUBLANG_GERMAN shl 10) or LANG_GERMAN) or (SORT_DEFAULT shl 16),
    ((SUBLANG_FRENCH shl 10) or LANG_FRENCH) or (SORT_DEFAULT shl 16)
  );
var
  i: Integer;
  lLCID: Cardinal;
  lBuffer: array[0..512] of Char;
begin
  i := AnsiIndexText(aLanguageISOCode, C_ISO_CODES);
  if i > -1 then
    lLCID := C_LCIDS[i]
  else
    lLCID := LOCALE_USER_DEFAULT;

  i := GetDateFormat(lLCID, DATE_LONGDATE, nil, nil, lBuffer, 512);
  SetString(Result, lBuffer, i - 1);
end;

1 个答案:

答案 0 :(得分:6)

免责声明:我仅基于LOCALE_SISO639LANGNAME常量的存在而编写以下内容。我不知道它是否真的有效或以任何方式有用。我根本没有测试过它。

unit Iso639;

interface

uses
  Windows;

function Iso639ToPrimaryLangID(const S: string): LANGID;

implementation

uses
  SysUtils, Classes;

var
  Iso639Languages: TStringList = nil;

function GetLocaleDataW(ID: LCID; Flag: DWORD): WideString;
var
  Buffer: array[0..1023] of WideChar;
begin
  Buffer[0] := #0;
  SetString(Result, Buffer, GetLocaleInfoW(ID, Flag, Buffer, SizeOf(Buffer) div 2));
end;

function LangIDFromLcID(ID: LCID): LANGID;
begin
  Result := LANGID(ID);
end;

function PrimaryLangID(LangID: LANGID): LANGID;
begin
  Result := LangID and $3FF;
end;

procedure InitializeIso639Languages;
var
  I: Integer;
  ALocaleID: LCID;
  ALangID: LANGID;
  S: string;
begin
  Iso639Languages := TStringList.Create;
  try
    Iso639Languages.Sorted := True;
    for I := 0 to Languages.Count - 1 do
    begin
      ALocaleID := Languages.LocaleID[I];
      ALangID := PrimaryLangID(LangIDFromLcID(ALocaleID));
      if Iso639Languages.IndexOfObject(TObject(ALangID)) = -1 then
      begin
        S := GetLocaleDataW(ALocaleID, LOCALE_SISO639LANGNAME);
        Iso639Languages.AddObject(S, TObject(ALangID));
      end;
    end;
  except
    FreeAndNil(Iso639Languages);
    raise;
  end;
end;

function Iso639ToPrimaryLangID(const S: string): LANGID;
var
  I: Integer;
begin
  Result := 0;

  if not Assigned(Iso639Languages) then
    InitializeIso639Languages;

  I := Iso639Languages.IndexOf(S);
  if I <> -1 then
    Result := LANGID(Iso639Languages.Objects[I]);
end;

initialization

finalization
  FreeAndNil(Iso639Languages);

end.

Delphi 7用户警告:

TLanguages.Create具有an issue with DEP并在启用DEP时抛出访问冲突。所以不要使用Languages[I].LocaleID并自己获取LocaleID:

function EnumLocalesProc(aLocaleString: PChar): Integer; stdcall;
var
  lLocaleID: LCID;
begin
  lLocaleID := StrToInt('$' + Copy(aLocaleString, 5, 4));
  Result := 1;
end;

EnumSystemLocales(@EnumLocalesProc, LCID_SUPPORTED);