Changed: Implement CI18N::setSystemLanguageCode, if we must force it

Fixed: CI18N::getSystemLanguageCode under Windows (use 2 different methods)
This commit is contained in:
kervala 2016-03-18 15:07:49 +01:00
parent 23e93ad89e
commit d72a59f5ea
2 changed files with 114 additions and 14 deletions

View file

@ -127,6 +127,9 @@ public:
/// Returns the code of the language ("fr", "en", ...) defined on system /// Returns the code of the language ("fr", "en", ...) defined on system
static std::string getSystemLanguageCode (); static std::string getSystemLanguageCode ();
/// Define the code of the language ("fr", "en", ...) defined on system
static bool setSystemLanguageCode (const std::string &languageCode);
/// Find a string in the selected language and return his association. /// Find a string in the selected language and return his association.
static const ucstring &get (const std::string &label); static const ucstring &get (const std::string &label);
@ -230,6 +233,7 @@ private:
static std::vector<std::string> _LanguageCodes; static std::vector<std::string> _LanguageCodes;
static std::vector<ucstring> _LanguageNames; static std::vector<ucstring> _LanguageNames;
static std::string _SystemLanguageCode;
static bool _LanguagesNamesLoaded; static bool _LanguagesNamesLoaded;

View file

@ -43,6 +43,7 @@ string CI18N::_SelectedLanguageCode;
CI18N::ILoadProxy *CI18N::_LoadProxy = 0; CI18N::ILoadProxy *CI18N::_LoadProxy = 0;
vector<string> CI18N::_LanguageCodes; vector<string> CI18N::_LanguageCodes;
vector<ucstring> CI18N::_LanguageNames; vector<ucstring> CI18N::_LanguageNames;
std::string CI18N::_SystemLanguageCode;
bool CI18N::noResolution = false; bool CI18N::noResolution = false;
void CI18N::setLoadProxy(ILoadProxy *loadProxy) void CI18N::setLoadProxy(ILoadProxy *loadProxy)
@ -248,10 +249,8 @@ bool CI18N::isLanguageCodeSupported(const std::string &lang)
std::string CI18N::getSystemLanguageCode () std::string CI18N::getSystemLanguageCode ()
{ {
static std::string s_cachedSystemLanguage; if (!_SystemLanguageCode.empty())
return _SystemLanguageCode;
if (!s_cachedSystemLanguage.empty())
return s_cachedSystemLanguage;
#ifdef NL_OS_MAC #ifdef NL_OS_MAC
// under OS X, locale is only defined in console, not in UI // under OS X, locale is only defined in console, not in UI
@ -317,7 +316,7 @@ std::string CI18N::getSystemLanguageCode ()
// only keep language code if supported by NeL // only keep language code if supported by NeL
if (isLanguageCodeSupported(lang)) if (isLanguageCodeSupported(lang))
{ {
s_cachedSystemLanguage = lang; _SystemLanguageCode = lang;
break; break;
} }
} }
@ -328,21 +327,118 @@ std::string CI18N::getSystemLanguageCode ()
} }
#endif #endif
// use system locale (works under Linux and Windows) #ifdef NL_OS_WINDOWS
if (s_cachedSystemLanguage.empty()) // use user locale under Windows (since Vista)
if (_SystemLanguageCode.empty() && false)
{ {
std::string lang = NLMISC::toLower(std::string(setlocale(LC_CTYPE, ""))); // GetUserDefaultLocaleName prototype
typedef int (WINAPI* GetUserDefaultLocaleNamePtr)(LPWSTR lpLocaleName, int cchLocaleName);
// only keep 2 first characters // get pointer on GetUserDefaultLocaleName, kernel32.dll is always in memory so no need to call LoadLibrary
if (lang.size() > 1) GetUserDefaultLocaleNamePtr nlGetUserDefaultLocaleName = (GetUserDefaultLocaleNamePtr)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetUserDefaultLocaleName");
s_cachedSystemLanguage = lang.substr(0, 2);
// only use it if found
if (nlGetUserDefaultLocaleName)
{
// get user locale
wchar_t buffer[LOCALE_NAME_MAX_LENGTH];
sint res = nlGetUserDefaultLocaleName(buffer, LOCALE_NAME_MAX_LENGTH);
// convert wide string to std::string
std::string lang = wideToUtf8(buffer);
// only keep 2 first characters
if (lang.size() > 1)
_SystemLanguageCode = lang.substr(0, 2);
}
}
#endif
// use system locale (works under OS X, Linux and Windows)
if (_SystemLanguageCode.empty())
{
// get default locale
char *locale = setlocale(LC_CTYPE, "");
if (locale)
{
std::string lang(locale);
#ifdef NL_OS_WINDOWS
// be sure supported languages are initialized
initLanguages();
// locales names are different under Windows, for example: French_France.1252
for(uint i = 0; i < _LanguageNames.size(); ++i)
{
std::string name = _LanguageNames[i].toUtf8();
// so we compare the language name with the supported ones
if (lang.compare(0, name.length(), name) == 0)
{
// found, so use its code
_SystemLanguageCode = _LanguageCodes[i];
break;
}
}
#else
std::string lang = NLMISC::toLower(lang);
// only keep 2 first characters
if (lang.size() > 1)
_SystemLanguageCode = lang.substr(0, 2);
#endif
}
} }
// english is default language // english is default language
if (s_cachedSystemLanguage.empty()) if (_SystemLanguageCode.empty())
s_cachedSystemLanguage = "en"; _SystemLanguageCode = "en";
return s_cachedSystemLanguage; return _SystemLanguageCode;
}
bool CI18N::setSystemLanguageCode (const std::string &languageCode)
{
// be sure supported languages are initialized
initLanguages();
std::string lang = NLMISC::toLower(languageCode);
// specified language is really a code (2 characters)
if (lang.length() == 2)
{
// check if language code is supported
for(uint i = 0; i < _LanguageCodes.size(); ++i)
{
std::string code = NLMISC::toLower(_LanguageCodes[i]);
if (lang == code)
{
// found, so use it
_SystemLanguageCode = lang;
return true;
}
}
}
// specified language is something else
else
{
// check if language name is supported
for(uint i = 0; i < _LanguageNames.size(); ++i)
{
std::string name = NLMISC::toLower(_LanguageNames[i].toUtf8());
if (name == lang)
{
// found, so use its code
_SystemLanguageCode = _LanguageCodes[i];
return true;
}
}
}
return false;
} }
void CI18N::removeCComment(ucstring &commentedString) void CI18N::removeCComment(ucstring &commentedString)