mirror of https://github.com/OpenVPN/openvpn-gui
added support for GUI localization at runtime
parent
41be82f81c
commit
6f37fd999f
120
localization.c
120
localization.c
|
@ -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, ®key);
|
||||
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, ®key, 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;
|
||||
}
|
||||
|
|
|
@ -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
9
main.c
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue