Mega Code Archive

 
Categories / Delphi / System
 

System and User Locale vs. System and User UI Language

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;