added support for GUI localization at runtime

pull/1/head
Heiko Hund 2009-02-02 17:27:09 +00:00
parent 41be82f81c
commit 6f37fd999f
13 changed files with 174 additions and 4 deletions

View File

@ -24,15 +24,20 @@
#define WINVER Windows2000
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <stdio.h>
#include <stdarg.h>
#include "main.h"
#include "localization.h"
#include "openvpn-gui-res.h"
#include "options.h"
#include "registry.h"
extern struct options o;
static const LANGID defaultLangId = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
static const LANGID fallbackLangId = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
static LANGID gui_language;
static HRSRC
FindResourceLang(PTSTR resType, PTSTR resId, LANGID langId)
@ -45,7 +50,7 @@ FindResourceLang(PTSTR resType, PTSTR resId, LANGID langId)
return res;
/* try to find the resource in the default language */
res = FindResourceEx(o.hInstance, resType, resId, defaultLangId);
res = FindResourceEx(o.hInstance, resType, resId, fallbackLangId);
if (res)
return res;
@ -57,7 +62,33 @@ FindResourceLang(PTSTR resType, PTSTR resId, LANGID langId)
static LANGID
GetGUILanguage(void)
{
return GetUserDefaultUILanguage();
if (gui_language == 0)
{
HKEY regkey;
DWORD value = 0;
LONG status = RegOpenKeyEx(HKEY_CURRENT_USER, GUI_REGKEY_HKCU, 0, KEY_READ, &regkey);
if (status != ERROR_SUCCESS)
ShowLocalizedMsg(GUI_NAME, ERR_CREATE_REG_HKCU_KEY, GUI_REGKEY_HKCU);
GetRegistryValueNumeric(regkey, "ui_language", &value);
gui_language = ( value != 0 ? value : LANGIDFROMLCID(GetThreadLocale()) );
}
return gui_language;
}
static void
SetGUILanguage(LANGID langId)
{
HKEY regkey;
if (RegCreateKeyEx(HKEY_CURRENT_USER, GUI_REGKEY_HKCU, 0, NULL, 0,
KEY_WRITE, NULL, &regkey, NULL) != ERROR_SUCCESS )
ShowLocalizedMsg(GUI_NAME, ERR_CREATE_REG_HKCU_KEY, GUI_REGKEY_HKCU);
SetRegistryValueNumeric(regkey, "ui_language", langId);
gui_language = langId;
}
@ -235,3 +266,86 @@ CreateLocalizedDialog(const UINT dialogId, DLGPROC dialogFunc)
return CreateDialogIndirect(o.hInstance, resInfo, NULL, dialogFunc);
}
static PTSTR
LangListEntry(const UINT stringId, const LANGID langId, ...)
{
static TCHAR str[128];
va_list args;
va_start(args, langId);
LoadStringLang(stringId, langId, str, sizeof(str)/sizeof(*str), args);
va_end(args);
return str;
}
typedef struct {
HWND languages;
LANGID language;
} langProcData;
static BOOL
FillLangListProc(HANDLE module, PTSTR type, PTSTR stringId, WORD langId, LONG lParam)
{
langProcData *data = (langProcData*) lParam;
int index = ComboBox_AddString(data->languages, LangListEntry(IDS_LANGUAGE_NAME, langId));
ComboBox_SetItemData(data->languages, index, langId);
/* Select this item if it is the currently displayed language */
if (langId == data->language
|| (PRIMARYLANGID(langId) == PRIMARYLANGID(data->language)
&& ComboBox_GetCurSel(data->languages) == CB_ERR) )
ComboBox_SetCurSel(data->languages, index);
return TRUE;
}
BOOL CALLBACK
LanguageSettingsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
LPPSHNOTIFY psn;
langProcData langData = {
.languages = GetDlgItem(hwndDlg, CB_LANGUAGES),
.language = GetGUILanguage()
};
switch(msg) {
case WM_INITDIALOG:
/* Populate UI language selection combo box */
EnumResourceLanguages( NULL, RT_STRING, MAKEINTRESOURCE(IDS_LANGUAGE_NAME / 16 + 1),
(ENUMRESLANGPROC) FillLangListProc, (LONG) &langData );
/* If none of the available languages matched, select the fallback */
if (ComboBox_GetCurSel(langData.languages) == CB_ERR)
ComboBox_SelectString(langData.languages, -1,
LangListEntry(IDS_LANGUAGE_NAME, fallbackLangId));
/* Clear language id data for the selected item */
ComboBox_SetItemData(langData.languages, ComboBox_GetCurSel(langData.languages), 0);
break;
case WM_NOTIFY:
psn = (LPPSHNOTIFY) lParam;
if (psn->hdr.code == (UINT) PSN_APPLY)
{
LANGID langId = (LANGID) ComboBox_GetItemData(langData.languages,
ComboBox_GetCurSel(langData.languages));
if (langId != 0)
SetGUILanguage(langId);
SetWindowLong(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR);
return TRUE;
}
break;
}
return FALSE;
}

View File

@ -30,5 +30,6 @@ LPCDLGTEMPLATE LocalizedDialogResource(const UINT);
INT_PTR LocalizedDialogBoxParam(const UINT, DLGPROC, const LPARAM);
INT_PTR LocalizedDialogBox(const UINT, DLGPROC);
HWND CreateLocalizedDialog(const UINT, DLGPROC);
BOOL CALLBACK LanguageSettingsDlgProc(HWND, UINT, WPARAM, LPARAM);
#endif

9
main.c
View File

@ -359,7 +359,7 @@ BOOL CALLBACK AboutDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, UNUSED LPA
static void
ShowSettingsDialog()
{
PROPSHEETPAGE psp[1];
PROPSHEETPAGE psp[2];
psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = PSP_DLGINDIRECT;
psp[0].hInstance = o.hInstance;
@ -367,6 +367,13 @@ ShowSettingsDialog()
psp[0].pfnDlgProc = ProxySettingsDialogFunc;
psp[0].lParam = 0;
psp[0].pfnCallback = NULL;
psp[1].dwSize = sizeof(PROPSHEETPAGE);
psp[1].dwFlags = PSP_DLGINDIRECT;
psp[1].hInstance = o.hInstance;
psp[1].pResource = LocalizedDialogResource(IDD_LANGUAGE);
psp[1].pfnDlgProc = LanguageSettingsDlgProc;
psp[1].lParam = 0;
psp[1].pfnCallback = NULL;
PROPSHEETHEADER psh;
psh.dwSize = sizeof(PROPSHEETHEADER);

View File

@ -130,6 +130,18 @@ BEGIN
AUTOCHECKBOX "Beim Verbinden nach Benutzername/Passwort fragen", CHECKB_PROXY_AUTH, 13, 103, 183, 10
END
/* General Settings Dialog */
IDD_LANGUAGE DIALOGEX 6, 18, 249, 124
STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_CENTER
CAPTION "Allgemein"
FONT 8, "Microsoft Sans Serif"
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
BEGIN
GROUPBOX "Benutzeroberfläche", 201, 6, 6, 235, 30
LTEXT "Sprache:", TEXT_LANGUAGES, 17, 19, 29, 12
COMBOBOX CB_LANGUAGES, 51, 17, 177, 85, CBS_DROPDOWNLIST | WS_TABSTOP
END
/* Proxy Authentication Dialog */
IDD_PROXY_AUTH DIALOG 29, 23, 154, 65
STYLE DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | DS_CENTER
@ -147,6 +159,8 @@ END
STRINGTABLE
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
BEGIN
IDS_LANGUAGE_NAME "Deutsch - German"
/* About Dialog */
TEXT_ABOUT_OPENVPNGUI "OpenVPN GUI v%s - Eine grafische Oberfläche für OpenVPN"

View File

@ -125,6 +125,18 @@ BEGIN
AUTOCHECKBOX "Prompt for username/password when connecting.", CHECKB_PROXY_AUTH, 13, 103, 183, 10
END
/* General Settings Dialog */
IDD_LANGUAGE DIALOGEX 6, 18, 249, 124
STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_CENTER
CAPTION "General"
FONT 8, "Microsoft Sans Serif"
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
BEGIN
GROUPBOX "User Interface", 201, 6, 6, 235, 30
LTEXT "Language:", TEXT_LANGUAGES, 17, 19, 52, 12
COMBOBOX CB_LANGUAGES, 57, 17, 171, 85, CBS_DROPDOWNLIST | WS_TABSTOP
END
/* Proxy Authentication Dialog */
IDD_PROXY_AUTH DIALOG 29, 23, 154, 65
STYLE DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | DS_CENTER
@ -142,6 +154,8 @@ END
STRINGTABLE
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
BEGIN
IDS_LANGUAGE_NAME "English"
/* About Dialog */
TEXT_ABOUT_OPENVPNGUI "OpenVPN GUI v%s - A Windows GUI for OpenVPN"

View File

@ -141,6 +141,8 @@ END
STRINGTABLE
LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL
BEGIN
IDS_LANGUAGE_NAME "Español - Spanish"
/* About Dialog */
TEXT_ABOUT_OPENVPNGUI "OpenVPN GUI v%s - Un frontend de Windows para OpenVPN"

View File

@ -140,6 +140,8 @@ END
STRINGTABLE
LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
BEGIN
IDS_LANGUAGE_NAME "Français - French"
/* About Dialog */
TEXT_ABOUT_OPENVPNGUI "OpenVPN GUI v%s - A Windows GUI for OpenVPN"

View File

@ -140,6 +140,8 @@ END
STRINGTABLE
LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
BEGIN
IDS_LANGUAGE_NAME "Italiano - Italian"
/* About Dialog */
TEXT_ABOUT_OPENVPNGUI "OpenVPN GUI v%s - Interfaccia per Windows di OpenVPN"

View File

@ -140,6 +140,8 @@ END
STRINGTABLE
LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL
BEGIN
IDS_LANGUAGE_NAME "Nederlands - Dutch"
/* About Dialog */
TEXT_ABOUT_OPENVPNGUI "OpenVPN GUI v%s - Een Windows GUI voor OpenVPN"

View File

@ -145,6 +145,8 @@ END
STRINGTABLE
LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL
BEGIN
IDS_LANGUAGE_NAME "Norsk - Norwegian"
/* About Dialog */
TEXT_ABOUT_OPENVPNGUI "OpenVPN GUI v%s - Ett Windows-Grensesnitt mot OpenVPN"

View File

@ -141,6 +141,8 @@ END
STRINGTABLE
LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL
BEGIN
IDS_LANGUAGE_NAME "Português - Portuguese"
/* About Dialog */
TEXT_ABOUT_OPENVPNGUI "OpenVPN GUI v%s - Uma GUI Windows para OpenVPN"

View File

@ -146,6 +146,8 @@ END
STRINGTABLE
LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL
BEGIN
IDS_LANGUAGE_NAME "Svenska - Swedish"
/* About Dialog */
TEXT_ABOUT_OPENVPNGUI "OpenVPN GUI v%s - Ett Windows GUI för OpenVPN"

View File

@ -76,6 +76,12 @@
#define TEXT_PROXY_PORT 217
#define CHECKB_PROXY_AUTH 218
/* Language Settings Dialog */
#define IDD_LANGUAGE 230
#define IDS_LANGUAGE_NAME 231
#define CB_LANGUAGES 232
#define TEXT_LANGUAGES 233
/* Proxy Auth Dialog */
#define IDD_PROXY_AUTH 250
#define EDIT_PROXY_USERNAME 251