No dictionaries were preselected for en_US langpack
...as gm_Langpack_r_en_US was explicitly excluded from langs[] in SelectLanguage, so addMatchingDictionaries was never called for it. (This was only evident in installation sets conaining only few langpacks, as the "official" multi-lang installation set also contains en_GB etc., so appropriate dictionaries were selected through those.) Reworked the logic of chosing which langpacks to preselect (see the comment in SelectLanguage); hope it still works as intended for the various cases (of which the "official" multi-lang installation set is the only truly relevant one, for now). Change-Id: I31f531194c79e49c9c09e33454a7b0a82d9ff02f
This commit is contained in:
parent
d83de4b1a9
commit
8cb7464130
1 changed files with 71 additions and 91 deletions
162
setup_native/source/win32/customactions/sellang/sellang.cxx
Normal file → Executable file
162
setup_native/source/win32/customactions/sellang/sellang.cxx
Normal file → Executable file
|
@ -172,7 +172,7 @@ langid_to_string( LANGID langid )
|
|||
CASE(sh, SERBIAN, SERBIAN_LATIN);
|
||||
CASE(sr, SERBIAN, SERBIAN_CYRILLIC);
|
||||
#undef CASE
|
||||
default: return "";
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,14 +183,20 @@ langid_to_string( LANGID langid )
|
|||
static const char *ui_langs[MAX_LANGUAGES];
|
||||
static int num_ui_langs = 0;
|
||||
|
||||
void add_ui_lang(char const * lang)
|
||||
{
|
||||
if (lang != 0 && num_ui_langs != SAL_N_ELEMENTS(ui_langs)) {
|
||||
ui_langs[num_ui_langs++] = lang;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CALLBACK
|
||||
enum_ui_lang_proc (LPTSTR language, LONG_PTR /* unused_lParam */)
|
||||
{
|
||||
long langid = strtol(language, NULL, 16);
|
||||
if (langid > 0xFFFF)
|
||||
return TRUE;
|
||||
ui_langs[num_ui_langs] = langid_to_string((LANGID) langid);
|
||||
num_ui_langs++;
|
||||
add_ui_lang(langid_to_string((LANGID) langid));
|
||||
if (num_ui_langs == SAL_N_ELEMENTS(ui_langs) )
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
|
@ -207,12 +213,13 @@ present_in_ui_langs(const char *lang)
|
|||
|
||||
namespace {
|
||||
|
||||
struct Dictionary {
|
||||
struct InstallLocalized {
|
||||
char lang[sizeof("xx_XX")];
|
||||
bool install;
|
||||
};
|
||||
|
||||
void addMatchingDictionaries(char const * lang, Dictionary * dicts, int ndicts)
|
||||
void addMatchingDictionaries(
|
||||
char const * lang, InstallLocalized * dicts, int ndicts)
|
||||
{
|
||||
for (int i = 0; i != SAL_N_ELEMENTS(setup_native::languageDictionaries);
|
||||
++i)
|
||||
|
@ -242,9 +249,9 @@ extern "C" UINT __stdcall SelectLanguage( MSIHANDLE handle )
|
|||
MSIHANDLE database, view, record;
|
||||
DWORD length;
|
||||
int nlangs = 0;
|
||||
char langs[MAX_LANGUAGES][6];
|
||||
InstallLocalized langs[MAX_LANGUAGES];
|
||||
int ndicts = 0;
|
||||
Dictionary dicts[MAX_LANGUAGES];
|
||||
InstallLocalized dicts[MAX_LANGUAGES];
|
||||
|
||||
database = MsiGetActiveDatabase(handle);
|
||||
|
||||
|
@ -269,11 +276,11 @@ extern "C" UINT __stdcall SelectLanguage( MSIHANDLE handle )
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Keep track of what languages are included in this installer, if
|
||||
* it is a multilanguage one.
|
||||
/* Keep track of what langpacks are included in this installer.
|
||||
*/
|
||||
if (strcmp(feature, "gm_Langpack_r_en_US") != 0)
|
||||
strcpy(langs[nlangs++], feature + strlen("gm_Langpack_r_"));
|
||||
strcpy(langs[nlangs].lang, feature + strlen("gm_Langpack_r_"));
|
||||
langs[nlangs].install = false;
|
||||
++nlangs;
|
||||
|
||||
MsiCloseHandle(record);
|
||||
}
|
||||
|
@ -315,92 +322,65 @@ extern "C" UINT __stdcall SelectLanguage( MSIHANDLE handle )
|
|||
MsiCloseHandle(view);
|
||||
}
|
||||
|
||||
if (nlangs > 0) {
|
||||
int i;
|
||||
char* pVal = NULL;
|
||||
if ( (GetMsiProp( handle, "UI_LANGS", &pVal )) && pVal ) {
|
||||
/* user gave UI languages explicitely with UI_LANGS property */
|
||||
int sel_ui_lang = 0;
|
||||
strcpy(langs[nlangs++], "en_US");
|
||||
char *str_ptr;
|
||||
str_ptr = strtok(pVal, ",");
|
||||
for(; str_ptr != NULL ;) {
|
||||
ui_langs[num_ui_langs] = str_ptr;
|
||||
num_ui_langs++;
|
||||
str_ptr = strtok(NULL, ",");
|
||||
}
|
||||
for (i = 0; i < nlangs; i++) {
|
||||
if (!present_in_ui_langs(langs[i])) {
|
||||
UINT rc;
|
||||
sprintf(feature, "gm_Langpack_r_%s", langs[i]);
|
||||
rc = MsiSetFeatureStateA(handle, feature, INSTALLSTATE_ABSENT);
|
||||
}
|
||||
else {
|
||||
addMatchingDictionaries(langs[i], dicts, ndicts);
|
||||
sel_ui_lang++;
|
||||
}
|
||||
}
|
||||
if ( sel_ui_lang == 0 ) {
|
||||
/* When UI_LANG property contains only languages that are not present
|
||||
* in the installer, install at least en_US localization.
|
||||
*/
|
||||
MsiSetFeatureStateA(handle, "gm_Langpack_r_en_US", INSTALLSTATE_LOCAL);
|
||||
addMatchingDictionaries("en_US", dicts, ndicts);
|
||||
/* Keep track of what UI languages are relevant, either the ones explicitly
|
||||
* requested with the UI_LANGS property, or all available on the system:
|
||||
*/
|
||||
char* pVal = NULL;
|
||||
if ( (GetMsiProp( handle, "UI_LANGS", &pVal )) && pVal ) {
|
||||
char *str_ptr;
|
||||
str_ptr = strtok(pVal, ",");
|
||||
for(; str_ptr != NULL ;) {
|
||||
add_ui_lang(str_ptr);
|
||||
str_ptr = strtok(NULL, ",");
|
||||
}
|
||||
} else {
|
||||
add_ui_lang(langid_to_string(GetSystemDefaultUILanguage()));
|
||||
add_ui_lang(langid_to_string(LANGIDFROMLCID(GetThreadLocale())));
|
||||
//TODO: are the above two explicit additions necessary, or will
|
||||
// those values always be included in the below EnumUILanguages
|
||||
// anyway?
|
||||
EnumUILanguagesA(enum_ui_lang_proc, 0, 0);
|
||||
}
|
||||
|
||||
// If the set of langpacks that match any of the relevant UI languages is
|
||||
// non-empty, select just those matching langpacks; otherwise, if an en_US
|
||||
// langpack is included, select just that langpack (this happens if, e.g.,
|
||||
// a multi-language en-US,de,es,fr,it,pt-BR installation set is installed on
|
||||
// a Finnish Windows); otherwise, select all langpacks (this happens if,
|
||||
// e.g., a single-language de installation set is installed on a Finnish
|
||||
// Windows):
|
||||
bool matches = false;
|
||||
for (int i = 0; i < nlangs; i++) {
|
||||
if (present_in_ui_langs(langs[i].lang)) {
|
||||
langs[i].install = true;
|
||||
matches = true;
|
||||
}
|
||||
}
|
||||
if (!matches) {
|
||||
for (int i = 0; i < nlangs; i++) {
|
||||
if (strcmp(langs[nlangs].lang, "en_US") == 0) {
|
||||
langs[i].install = true;
|
||||
matches = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Deselect those languages that don't match any of the UI languages
|
||||
* available on the system.
|
||||
*/
|
||||
|
||||
const char *system_default_lang = langid_to_string(GetSystemDefaultUILanguage());
|
||||
const char *user_locale_lang = langid_to_string(LANGIDFROMLCID(GetThreadLocale()));
|
||||
|
||||
EnumUILanguagesA(enum_ui_lang_proc, 0, 0);
|
||||
|
||||
/* If one of the alternative languages in a multi-language installer
|
||||
* is the system default UI language, deselect those languages that
|
||||
* aren't among the UI languages available on the system.
|
||||
* (On most Windows installations, just one UI language is present,
|
||||
* which obviously is the same as the default UI language. But
|
||||
* we want to be generic.)
|
||||
* If none of the languages in a multi-language installer is the
|
||||
* system default UI language (this happens now in 2.4.0 where we
|
||||
* cannot put as many UI languages into the installer as we would
|
||||
* like, but only half a dozen: en-US,de,es,fr,it,pt-BR), pretend
|
||||
* that English is the system default UI language,
|
||||
* so that we will by default deselect everything except
|
||||
* English. We don't want to by default install all half dozen
|
||||
* languages for an unsuspecting user of a Finnish Windows, for
|
||||
* instance. Sigh.
|
||||
*/
|
||||
bool have_system_default_lang = false;
|
||||
if (system_default_lang[0]) {
|
||||
for (i = 0; i < nlangs; i++) {
|
||||
if (memcmp (system_default_lang, langs[i], 2) == 0) {
|
||||
have_system_default_lang = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!have_system_default_lang) {
|
||||
system_default_lang = "en";
|
||||
}
|
||||
|
||||
for (i = 0; i < nlangs; i++) {
|
||||
if (memcmp(system_default_lang, langs[i], 2) != 0 &&
|
||||
memcmp(user_locale_lang, langs[i], 2) != 0 &&
|
||||
!present_in_ui_langs(langs[i])) {
|
||||
UINT rc;
|
||||
sprintf(feature, "gm_Langpack_r_%s", langs[i]);
|
||||
rc = MsiSetFeatureStateA(handle, feature, INSTALLSTATE_ABSENT);
|
||||
} else {
|
||||
addMatchingDictionaries(langs[i], dicts, ndicts);
|
||||
}
|
||||
if (!matches) {
|
||||
for (int i = 0; i < nlangs; i++) {
|
||||
langs[i].install = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < nlangs; i++) {
|
||||
if (langs[i].install) {
|
||||
addMatchingDictionaries(langs[i].lang, dicts, ndicts);
|
||||
} else {
|
||||
sprintf(feature, "gm_Langpack_r_%s", langs[i].lang);
|
||||
MsiSetFeatureStateA(handle, feature, INSTALLSTATE_ABSENT);
|
||||
}
|
||||
}
|
||||
|
||||
// Select just those dictionaries that match any of the selected langpacks:
|
||||
for (int i = 0; i != ndicts; ++i) {
|
||||
if (!dicts[i].install) {
|
||||
sprintf(feature, "gm_r_ex_Dictionary_%s", dicts[i].lang);
|
||||
|
|
Loading…
Reference in a new issue