diff --git a/configure.ac b/configure.ac index f99f001f..18e0baee 100644 --- a/configure.ac +++ b/configure.ac @@ -81,6 +81,7 @@ CXXFLAGS="$save_CXXFLAGS" # Checks for header files. dnl AC_CHECK_HEADERS([]) +gt_LC_MESSAGES # Checks for typedefs, structures, and compiler characteristics. AC_CANONICAL_HOST @@ -95,7 +96,7 @@ AC_TYPE_UINT64_T AC_TYPE_UINT8_T # Checks for library functions. -AC_CHECK_FUNCS([_NSGetExecutablePath]) +AC_CHECK_FUNCS_ONCE([_NSGetExecutablePath setenv]) AX_STRING_STRCASECMP if test x"$ac_cv_string_strcasecmp" = "xno" ; then diff --git a/include/LocaleRes.h b/include/LocaleRes.h index 6f659778..ebedb45b 100644 --- a/include/LocaleRes.h +++ b/include/LocaleRes.h @@ -64,11 +64,13 @@ class LocaleRes void init(); void deinit(); - void load(); + void load(const char *locale); #ifdef ENABLE_NLS const char *conv_str(iconv_t cd, const char *s); #endif + const char *get_locale_dir(); + const char *get_messages_locale(); }; extern LocaleRes locale_res; diff --git a/m4/lcmessage.m4 b/m4/lcmessage.m4 new file mode 100644 index 00000000..2e56de66 --- /dev/null +++ b/m4/lcmessage.m4 @@ -0,0 +1,35 @@ +# lcmessage.m4 serial 8 +dnl Copyright (C) 1995-2002, 2004-2005, 2008-2014, 2016, 2019-2023 Free +dnl Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Lesser General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Lesser General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995. + +# Check whether LC_MESSAGES is available in . + +AC_DEFUN([gt_LC_MESSAGES], +[ + AC_CACHE_CHECK([for LC_MESSAGES], [gt_cv_val_LC_MESSAGES], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[return LC_MESSAGES]])], + [gt_cv_val_LC_MESSAGES=yes], + [gt_cv_val_LC_MESSAGES=no])]) + if test $gt_cv_val_LC_MESSAGES = yes; then + AC_DEFINE([HAVE_LC_MESSAGES], [1], + [Define if your file defines LC_MESSAGES.]) + fi +]) diff --git a/src/AM.cpp b/src/AM.cpp index c520e0e6..a201230c 100644 --- a/src/AM.cpp +++ b/src/AM.cpp @@ -312,7 +312,7 @@ int main(int argc, char **argv) } config_adv.init(); if( config_adv.locale[0] ) - locale_res.load(); + locale_res.load(config_adv.locale); //----- read command line arguments -----// diff --git a/src/LocaleRes.cpp b/src/LocaleRes.cpp index 2ad79f20..8ffe191a 100644 --- a/src/LocaleRes.cpp +++ b/src/LocaleRes.cpp @@ -21,6 +21,7 @@ //Filename : LocaleRes.cpp //Description : Locale Resources +#include #ifdef ENABLE_NLS #include #include @@ -28,9 +29,24 @@ #include #include -#include #include + +#ifndef HAVE_SETENV +static String lc_all_str; +int setenv(const char *name, const char *value, int overwrite) +{ + if( !value ) + return putenv(name); + + lc_all_str = name; + lc_all_str += "="; + lc_all_str += value; + return putenv(lc_all_str); +} +#endif + + //------------- End of function Constructor -------// // LocaleRes::LocaleRes() @@ -65,16 +81,15 @@ LocaleRes::~LocaleRes() void LocaleRes::init() { #ifdef ENABLE_NLS - const char *env_locale_dir; - if( misc.is_file_exist("locale") ) - bindtextdomain(PACKAGE, "locale"); - else if( env_locale_dir = getenv("SKLOCALE") ) - bindtextdomain(PACKAGE, env_locale_dir); - else - bindtextdomain(PACKAGE, LOCALE_DIR); + const char *locale_dir; + locale_dir = get_locale_dir(); + if( locale_dir ) + { + bindtextdomain(PACKAGE, locale_dir); + } textdomain(PACKAGE); - - load(); + setlocale(LC_ALL, ""); + load(getenv("SKMESSAGES")); in_buf = mem_add(INIT_BUF_SIZE+1); in_buf_size = INIT_BUF_SIZE; @@ -110,24 +125,37 @@ void LocaleRes::deinit() //------------- End of function LocaleRes::deinit ---------// -//----------- Start of function LocaleRes::change_locale ---------// +//----------- Start of function LocaleRes::load ---------// +// +// Performs setlocale and initializes codeset conversion. // -void LocaleRes::load() +void LocaleRes::load(const char *locale) { #ifdef ENABLE_NLS - const char *ctype; - if( config_adv.locale[0] ) + if( locale && locale[0] ) { - if( !setlocale(LC_ALL, config_adv.locale) ) - return; - ctype = config_adv.locale; + setlocale(LC_MESSAGES, locale); + setlocale(LC_CTYPE, locale); +#ifndef HAVE_LC_MESSAGES + // Gettext fakes the setlocale for LC_MESSAGES above via a + // wrapper, set the env var the same way since the var is + // actually used by gettext instead of the real setlocale. + setenv("LC_MESSAGES", locale, 1); +#endif } - else + locale = get_messages_locale(); + + if( !locale || !locale[0] ) { - setlocale(LC_ALL, ""); - ctype = setlocale(LC_CTYPE, NULL); - if( !ctype ) - return; + // The platform doesn't have full POSIX localization, and the + // user did not specify a locale in the game config. Default to + // English. The reason why to do this is if gettext does end up + // mapping the locale internally, we don't know what font to + // use. English is a safe choice. + locale = "en_US"; + setlocale(LC_MESSAGES, locale); + setlocale(LC_CTYPE, locale); + setenv("LC_MESSAGES", locale, 1); } LocaleRec *localeRec; @@ -147,7 +175,7 @@ void LocaleRes::load() localeRec = (LocaleRec*) dbLocale->read(i+1); misc.rtrim_fld( lang, localeRec->lang, localeRec->LANG_LEN ); - if( !misc.str_icmpx(ctype, lang) ) + if( !misc.str_icmpx(locale, lang) ) continue; misc.rtrim_fld( fontset, localeRec->fontset, localeRec->FONTSET_LEN ); @@ -173,7 +201,7 @@ void LocaleRes::load() cd_from_sdl = iconv_open("ISO-8859-1//TRANSLIT//IGNORE", "UTF-8"); #endif } -//------------- End of function LocaleRes::change_locale ---------// +//------------- End of function LocaleRes::load ---------// #ifdef ENABLE_NLS @@ -216,3 +244,54 @@ const char *LocaleRes::conv_str(iconv_t cd, const char *s) return out_buf; } #endif + + +//-------- Begin of function LocaleRes::get_locale_dir -----------// +// +const char *LocaleRes::get_locale_dir() +{ + if( misc.is_file_exist("locale") ) + return "locale"; + if( misc.is_file_exist(getenv("SKLOCALE")) ) + return getenv("SKLOCALE"); +#ifdef LOCALE_DIR + if( misc.is_file_exist(LOCALE_DIR) ) + return LOCALE_DIR; +#endif + return NULL; +} +//---------- End of function LocaleRes::get_locale_dir ----------// + + +//-------- Begin of function LocaleRes::get_messages_locale -----------// +// +const char *LocaleRes::get_messages_locale() +{ + const char *locale; + +#ifdef HAVE_LC_MESSAGES + /* setlocale(LC_ALL, "") has been done previously */ + locale = setlocale(LC_MESSAGES, NULL); + if( locale && locale[0] ) + return locale; +#else /* Missing LC_MESSAGES */ + // gettext uses the env vars on this platform + locale = getenv("LC_ALL"); + if( locale && locale[0] ) + return locale; + + locale = getenv("LC_MESSAGES"); + if( locale && locale[0] ) + return locale; + + locale = getenv("LANG"); + if( locale && locale[0] ) + return locale; +#endif + // We don't spend the time to map what Windows uses for locales. And + // some platforms don't have a POSIX setlocale, so if the user does not + // manually set an option in this case, we don't know the locale. + + return NULL; +} +//---------- End of function LocaleRes::get_messages_locale ----------//