Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2018年08月24日] [更新 2018年08月24日] Delphi 一般・その他
   
ロケールの言語と国コードの取得
動作確認等 Windows 7 U64(SP1) + Delphi XE5(UP2) Pro VCL-32
[整理番号 - 0460]







ロケールの言語と国コードの取得


ロケールの ja あるいは ja-JP という言語コードと国コードの値を取得するサンプルです.

以下のコマンドを実行すると下図の [地域と言語] のダイアログが現れます.これがロケール各種の設定内容です.ただし,このダイアログには ja や ja-JP の表示はありません.


%SystemRoot%\System32\control.exe /name Microsoft.RegionalAndLanguageOptions /page


図1
[地域と言語] のダイアログ
  • ロケール関係の設定内容





01_GetLocaleInfo 関数を使用した言語コードの取得


上の図で表示されているロケールの値は,GetLocaleInfo 関数を使用して取得することができます.また,SetLocaleInfo 関数を使用すると設定もできます.ロケールの種類によっては専用の取得あるいは設定用の関数が用意されていることがあります.


GetLocaleInfo 関数の第 1 引数には以下の値が指定できます.
LOCALE_INVARIANT, LOCALE_CUSTOM_XXX については以下の記事で確認してください.


LOCALE_SYSTEM_DEFAULT システムの既定ロケール
LOCALE_USER_DEFAULT ユーザの既定ロケール
LOCALE_INVARIANT -
LOCALE_CUSTOM_DEFAULT -
LOCALE_CUSTOM_UI_DEFAULT -
LOCALE_CUSTOM_UNSPECIFIED -


下図は GetLocaleInfo 関数の第 2 引数に,言語コードと国コードに関係ありそうな値を指定して,それらの値を表示した結果です.


図2
言語コードと国コード関係の値
  • LOCALE_IXXX は Identify の意味
  • LOCALE_SXXX は Signature の意味
  • ISO639 の言語コードが ja になっている 

リスト1
implementation

uses
  AnsiStrings;

{$R *.dfm}

//=============================================================================
//  ロケールの言語関係の値を取得
//  usesにAnsiStringsが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LStrList  : TStringList;
  LIndex    : Integer;
  LCData    : Cardinal;
  LpcLCA    : array[0..LOCALE_NAME_MAX_LENGTH - 1] of Char;
  LDataText : AnsiString;
  LFlagText : AnsiString;
  LRetText  : AnsiString;
begin
  Memo1.Font.Name  := 'Courier New';
  Memo1.Font.Pitch := fpFixed;
  Memo1.Font.Size  := 10;
  Memo1.Lines.Clear;

  LStrList := TStringList.Create;
  try
    //取得する情報の種類のリストを作成
    LStrList.AddObject('LOCALE_ILANGUAGE',        TObject(LOCALE_ILANGUAGE));
    LStrList.AddObject('LOCALE_SLANGUAGE',        TObject(LOCALE_SLANGUAGE));
    LStrList.AddObject('LOCALE_SENGLANGUAGE',     TObject(LOCALE_SENGLANGUAGE));
    LStrList.AddObject('LOCALE_SABBREVLANGNAME',  TObject(LOCALE_SABBREVLANGNAME));
    LStrList.AddObject('LOCALE_SNATIVELANGNAME',  TObject(LOCALE_SNATIVELANGNAME));
    LStrList.AddObject('LOCALE_ICOUNTRY',         TObject(LOCALE_ICOUNTRY));
    LStrList.AddObject('LOCALE_SCOUNTRY',         TObject(LOCALE_SCOUNTRY));
    LStrList.AddObject('LOCALE_SENGCOUNTRY',      TObject(LOCALE_SENGCOUNTRY));
    LStrList.AddObject('LOCALE_SABBREVCTRYNAME',  TObject(LOCALE_SABBREVCTRYNAME));
    LStrList.AddObject('LOCALE_SNATIVECTRYNAME',  TObject(LOCALE_SNATIVECTRYNAME));
    LStrList.AddObject('LOCALE_IDEFAULTLANGUAGE', TObject(LOCALE_IDEFAULTLANGUAGE));
    LStrList.AddObject('LOCALE_IDEFAULTCOUNTRY',  TObject(LOCALE_IDEFAULTCOUNTRY));
    LStrList.AddObject('LOCALE_SISO639LANGNAME',  TObject(LOCALE_SISO639LANGNAME));
    LStrList.AddObject('LOCALE_SISO3166CTRYNAME', TObject(LOCALE_SISO3166CTRYNAME));


    //情報に応じた値を順番に取得
    for LIndex := 0 to LStrList.Count - 1 do begin
      FillChar(LpcLCA, SizeOf(LpcLCA), #0);
      LCData := Cardinal(LStrList.Objects[LIndex]);

      GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LCData, LpcLCA, Length(LpcLCA));

      //取得した値を表示
      //桁位置を揃えたいのでAnsiStringを使用
      //欧文フォントの場合,等倍フォントでも位置がづれることがある
      LDataText := AnsiString(LpcLCA);
      LFlagText := AnsiString(LStrList[LIndex]);
      LRetText  := AnsiStrings.Format('%-16s%-25s%', [LDataText, LFlagText]);
      Memo1.Lines.Add(String(LRetText));
    end;
  finally
    FreeAndNil(LStrList);
  end;
end;

上のサンプルの実行結果から,言語コードである ja の値を取得するには GetLocaleInfo 関数の第 2 引数に LOCALE_SISO639LANGNAME を指定すればいいことが分かります.以下は言語コードだけを取得するサンプルです.
これは ISO639-1 の言語コードの値です.


図3
言語コードを取得するサンプルの実行結果

リスト2
//=============================================================================
//  ロケールの言語コードを取得
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LpcLCA   : array[0..LOCALE_NAME_MAX_LENGTH - 1] of Char;
  LRetText : string;
begin
  Memo1.Lines.Clear;

  FillChar(LpcLCA, SizeOf(LpcLCA), #0);
  GetLocaleInfo(LOCALE_SYSTEM_DEFAULT,
                LOCALE_SISO639LANGNAME,
                LpcLCA,
                Length(LpcLCA));

  LRetText := LpcLCA;
  Memo1.Lines.Add(LRetText);
end;




02_GetSystemDefaultLocaleName 関数を使用したロケール名取得


GetSystemDefaultLocaleName 関数,あるいは GetUserDefaultLocaleName 関数を使用すると,ja-JP のような [言語コード] と [国コード] を組み合わせたロケール名が取得できます.その例です.
これらの関数は Windows Vista 以降で使用可能です.
結果の JP は ISO3166-1 の国コードの値です.



[備考]
Delphi XE7 以降には,GetSystemDefaultLocaleName 関数と GetUserDefaultLocaleName 関数が実装されています.下のコードのこれらの関数の定義コードは必要ありません.



図4
言語コードと国コードの組み合わせを取得
  • 筆者の環境では,[Button1] クリックの実行結果も [Button2] クリックの実行結果も同じ

リスト3
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics,Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

  function GetSystemDefaultLocaleName(
    lpLocaleName : LPWSTR;
    cchLocaleName : Integer) : Integer; stdcall; external 'Kernel32.dll';

  function GetUserDefaultLocaleName(
    lpLocaleName : LPWSTR;
    cchLocaleName : Integer) : Integer; stdcall; external 'Kernel32.dll';

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  システムの既定ロケールの言語を取得
//  [言語コード]-[国コード] の組み合わせの値を取得
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LCharArr : array [0..LOCALE_NAME_MAX_LENGTH - 1] of Char;
begin
  Memo1.Lines.Clear;

  FillChar(LCharArr, SizeOf(LCharArr), #0);
  GetSystemDefaultLocaleName(LCharArr, Length(LCharArr));

  Memo1.Lines.Add(LCharArr);
end;

//=============================================================================
//  ユーザの既定ロケールの言語を取得
//  [言語コード]-[国コード] の組み合わせの値を取得
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  LCharArr : array [0..LOCALE_NAME_MAX_LENGTH - 1] of Char;
begin
  Memo1.Lines.Clear;

  FillChar(LCharArr, SizeOf(LCharArr), #0);
  GetUserDefaultLocaleName(LCharArr, Length(LCharArr));

  Memo1.Lines.Add(LCharArr);
end;

end.


関数の実行結果を String 型の文字列変数で取得するには,String 型の文字列変数のサイズを設定してから関数を実行します.
関数の実行結果を PChar 型の文字列変数で取得するには,PChar 型の文字列変数の領域を確保してから関数を実行します.



リスト4
procedure TForm1.Button1Click(Sender: TObject);
var
  LText : string;
begin
  Memo1.Lines.Clear;

  SetLength(LText, LOCALE_NAME_MAX_LENGTH);
  GetSystemDefaultLocaleName(PChar(LText), Length(LText));

  Memo1.Lines.Add(LText);
end;


リスト5
procedure TForm1.Button1Click(Sender: TObject);
var
  LCharCnt : Integer;
  LPChar   : PChar;
begin
  Memo1.Lines.Clear;

  LCharCnt := (LOCALE_NAME_MAX_LENGTH + 1);
  LPChar   := StrAlloc(LCharCnt);
  try
    GetSystemDefaultLocaleName(LPChar, LCharCnt);
    Memo1.Lines.Add(LPChar);
  finally
    StrDispose(LPChar);
  end;
end;