System Delphi

Title: System and User Locale vs. System and User UI Language
Question: This sorts out the business of Language IDs and UI Language IDs. Why they are different and how to access them.
Answer:
System and User Locale vs. System and User UI Language
I became quite confused (easy for me) on the subject of Language IDs. It turns out, that what I failed to realize is that there is really two, potentially different, languages IDs on a system. Sure, I knew that there is both a default system ID and a user ID for each defined user on the system but what I didnt know, was that there is also a system and user UI Language ID.
It goes like this.
Windows 32 bit operating systems have a System Locale, which can be retrieved with GetSystemDefaultLangID. System This ID determines which bitmap fonts, and OEM, ANSI and MAC code pages are defaults for the system.
Complementing the system locale default is the user locale default that determines which settings are used for dates, times, currency, numbers, and sort order as a default for each user. The GetUserDefaultLangID retrieves the default value for the current user.
Threads can also have a default locale. New threads default to the default user locale but can be changed with SetThreadLocale and retrieved with GetThreadLocale. The thread locale determines which settings are used for formatting dates, times, currency, numbers, and sort order for the thread.
Eventually, I realized that there is also separate default User Interface (UI) language IDs. These determine the language of menus, dialogs, messages, INF files and help files. The System UI Language is retrieved using GetSystemDefaultUILanguage, while the user UI language is retrieved using GetUseDefaultUILanguage.
Once I finally came to terms with this, not so subtle, distinction between locals and UI languages I realized that what I needed was the user UI language ID unfortunately none of my copies of Delphi (including Delphi 6) support either GetSystemDefaultUILanguage or GetUseDefaultUILanguage. Even worse, these are relatively new API calls and only first appeared with Windows ME and 2000.
Here is a GetUseDefaultUILanguage I pieced together from various MSDN documents, samples, and factoids. This was written with Delphi 6 and supports OSs from Win95 on up. Ive only tested it on Windows 2000 so please let me know if it hiccups on Win9x and NT.
Send comments to alecb@o2a.com.
// Helper
function HrFromWin32(dwErr: DWord) : HResult;
begin
result := HResultFromWin32(dwErr);
end;
// Helper
function HrFromLastWin32Error: HResult;
var
dw : DWord;
begin
dw := GetLastError;
if dw = 0 then
result := E_Fail
else
result := HrFromWin32(dw);
end;
// Helper
function MAKELANGID(p, s: word) : word;
begin
result := (s shl 10) or p;
end;
// The good stuff
function GetUserDefaultUILanguage: LANGID;
type
TGetLang = function: LangID;
THandle = Integer;
var
GetLang: TGetLang;
wUILang: LANGID;
Osv : OSVERSIONINFO;
Reg: TRegistry;
Handle: THandle;
begin
wUILang := 0;
Osv.dwOSVersionInfoSize := sizeof(Osv);

if not GetVersionEx(Osv) then
begin
OleError(HrFromLastWin32Error);
end
// Get the UI language by one of three methods, depending on OS
else if Osv.dwPlatformId VER_PLATFORM_WIN32_NT then
begin
// Case 1: Running on Windows 9x. Get the system UI language from registry:
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_USERS;
if Reg.OpenKey('.Default\Control Panel\desktop\ResourceLocale', False) then
begin
wUILang := LangID(Reg.ReadInteger(''));
Reg.CloseKey;
end;
finally
Reg.Free;
end;
end
else if (Osv.dwMajorVersion = 5.0) then
begin
// Case 2: Running on Windows 2000 or later. Use GetUserDefaultUILanguage
// to find the user's prefered UI language
Handle := LoadLibrary('kernel32.dll');
if Handle 0 then
begin
@GetLang := GetProcAddress(Handle, 'GetUserDefaultUILanguage');
if @GetLang nil then
wUILang := GetLang;
FreeLibrary(Handle);
end;
end
else
begin
// Case 3: Running on Windows NT 4.0 or earlier. Get UI language
// from locale of .default user in registry:
// HKEY_USERS\.DEFAULT\Control Panel\International\Locale
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_USERS;
if Reg.OpenKey('.Default\Control Panel\desktop\International', False) then
begin
wUILang := LangID(Reg.ReadInteger('Locale'));
Reg.CloseKey;
// Special case these to the English UI.
// These versions of Windows NT 4.0 were enabled only, i.e., the
// UI was English. However, the registry setting
// HKEY_USERS\.DEFAULT\Control Panel\International\Locale was set
// to the respective locale for application compatibility.
if ($0401 = wUILang) or // Arabic
($040d = wUILang) or // Hebrew
($041e = wUILang) then // Thai
begin
wUILang := MakeLangID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
end;

end;
finally
Reg.Free;
end;
end;
result := wUILang;
end;