diff --git a/code/nel/include/nel/misc/i18n.h b/code/nel/include/nel/misc/i18n.h index 5f98c5f34..1102a8907 100644 --- a/code/nel/include/nel/misc/i18n.h +++ b/code/nel/include/nel/misc/i18n.h @@ -104,6 +104,11 @@ public: */ static const std::vector &getLanguageCodes(); + /** Check if a language code is supported. + * Code are ISO 639-2 compliant. + */ + static bool isLanguageCodeSupported(const std::string &lang); + /// Load a language file depending of the language code("en", "fr", ...). Code are ISO 639-2 compliant. static void load (const std::string &languageCode, const std::string &fallbackLanguageCode=""); @@ -119,6 +124,9 @@ public: /// Returns the code of the language ("fr", "en", ...) static std::string getCurrentLanguageCode (); + /// Returns the code of the language ("fr", "en", ...) defined on system + static std::string getSystemLanguageCode (); + /// Find a string in the selected language and return his association. static const ucstring &get (const std::string &label); diff --git a/code/nel/src/misc/i18n.cpp b/code/nel/src/misc/i18n.cpp index e53750af7..99e9c68a0 100644 --- a/code/nel/src/misc/i18n.cpp +++ b/code/nel/src/misc/i18n.cpp @@ -20,6 +20,12 @@ #include "nel/misc/path.h" #include "nel/misc/i18n.h" +#include + +#ifdef NL_OS_MAC +#include +#endif + using namespace std; #ifdef DEBUG_NEW @@ -52,11 +58,13 @@ void CI18N::initLanguages() _LanguageCodes.push_back("fr"); _LanguageCodes.push_back("de"); _LanguageCodes.push_back("ru"); + _LanguageCodes.push_back("es"); _LanguageNames.push_back(ucstring("English")); _LanguageNames.push_back(ucstring("French")); _LanguageNames.push_back(ucstring("German")); _LanguageNames.push_back(ucstring("Russian")); + _LanguageNames.push_back(ucstring("Spanish")); _LanguagesNamesLoaded = true; } @@ -226,6 +234,108 @@ string CI18N::getCurrentLanguageCode () return _SelectedLanguageCode; } +bool CI18N::isLanguageCodeSupported(const std::string &lang) +{ + initLanguages(); + + for (sint i = 0, ilen = _LanguageCodes.size(); i < ilen; ++i) + { + if (lang == _LanguageCodes[i]) return true; + } + + return false; +} + +std::string CI18N::getSystemLanguageCode () +{ + static std::string s_cachedSystemLanguage; + + if (!s_cachedSystemLanguage.empty()) + return s_cachedSystemLanguage; + +#ifdef NL_OS_MAC + // under OS X, locale is only defined in console, not in UI + // so we need to use CoreFoundation API to retrieve it + + // get an array with all preferred languages + CFArrayRef langs = CFLocaleCopyPreferredLanguages(); + + if (langs) + { + // get languages count + sint languagesCount = CFArrayGetCount(langs); + + // process each language + for (sint i = 0; i < languagesCount; ++i) + { + std::string lang; + + // get language CFString + CFStringRef langCF = (CFStringRef)CFArrayGetValueAtIndex(langs, i); + + if (langCF) + { + // get a C string from CFString + const char *langStr = CFStringGetCStringPtr(langCF, kCFStringEncodingASCII); + + if (!langStr) + { + // get length of the CFString + CFIndex length = CFStringGetLength(langCF); + + // allocate a temporary buffer to hold converted string + char *tmp = new char[length+1]; + + // use alternative function to get a C string from CFString + if (CFStringGetCString(langCF, tmp, length+1, kCFStringEncodingASCII)) + { + lang = std::string(tmp, length); + } + else + { + nlerror("Unable to convert CFStringRef to string"); + } + + delete [] tmp; + } + else + { + lang = std::string(langStr); + } + + CFRelease(langCF); + } + + // only keep language code if supported by NeL + if (!lang.empty() && isLanguageCodeSupported(lang)) + { + s_cachedSystemLanguage = lang; + break; + } + } + + // don't need languages array anymore + CFRelease(langs); + } +#endif + + // use system locale (works under Linux and Windows) + if (s_cachedSystemLanguage.empty()) + { + std::string lang = NLMISC::toLower(std::string(setlocale(LC_CTYPE, ""))); + + // only keep 2 first characters + if (lang.size() > 1) + s_cachedSystemLanguage = lang.substr(0, 2); + } + + // english is default language + if (s_cachedSystemLanguage.empty()) + s_cachedSystemLanguage = "en"; + + return s_cachedSystemLanguage; +} + void CI18N::removeCComment(ucstring &commentedString) { ucstring temp; diff --git a/code/ryzom/client/src/app_bundle_utils.cpp b/code/ryzom/client/src/app_bundle_utils.cpp index b42b00b98..42d1b61bc 100644 --- a/code/ryzom/client/src/app_bundle_utils.cpp +++ b/code/ryzom/client/src/app_bundle_utils.cpp @@ -17,53 +17,57 @@ #include "stdpch.h" #include "app_bundle_utils.h" -#if defined(NL_OS_MAC) +#ifdef NL_OS_MAC #include #endif std::string getAppBundlePath() { - static std::string cachedPathToBundle; + static std::string s_cachedPathToBundle; - if(cachedPathToBundle.size()) - return cachedPathToBundle; + if (!s_cachedPathToBundle.empty()) + return s_cachedPathToBundle; #if defined(NL_OS_MAC) // get the bundle CFBundleRef bundle = CFBundleGetMainBundle(); - if(bundle) + if (bundle) { // get the url to the bundles root CFURLRef url = CFBundleCopyBundleURL(bundle); - if(url) + if (url) { // get the file system path CFStringRef str; - str = CFURLCopyFileSystemPath( - CFURLCopyAbsoluteURL(url), kCFURLPOSIXPathStyle); + str = CFURLCopyFileSystemPath(CFURLCopyAbsoluteURL(url), kCFURLPOSIXPathStyle); CFRelease(url); - if(str) + if (str) { - cachedPathToBundle = CFStringGetCStringPtr( - str, CFStringGetSmallestEncoding(str)); + s_cachedPathToBundle = CFStringGetCStringPtr(str, CFStringGetSmallestEncoding(str)); CFRelease(str); } else + { nlerror("CFStringGetCStringPtr"); + } } else + { nlerror("CFBundleCopyBundleURL"); + } } else + { nlerror("CFBundleGetMainBundle"); + } #elif defined(NL_OS_WINDOWS) char buffer[MAX_PATH+1]; if (GetModuleFileNameA(NULL, buffer, MAX_PATH)) - cachedPathToBundle = NLMISC::CPath::standardizePath(NLMISC::CFile::getPath(buffer), false); + s_cachedPathToBundle = NLMISC::CPath::standardizePath(NLMISC::CFile::getPath(buffer), false); #endif // defined(NL_OS_MAC) - return cachedPathToBundle; + return s_cachedPathToBundle; } diff --git a/code/ryzom/client/src/client_cfg.cpp b/code/ryzom/client/src/client_cfg.cpp index 3ccdde651..bfce130f3 100644 --- a/code/ryzom/client/src/client_cfg.cpp +++ b/code/ryzom/client/src/client_cfg.cpp @@ -49,8 +49,6 @@ #include "app_bundle_utils.h" #endif // NL_OS_MAC -#include - /////////// // MACRO // /////////// @@ -1919,8 +1917,7 @@ void CClientConfig::init(const string &configFileName) nlwarning("CFG::init: creating '%s' with default values", configFileName.c_str ()); // get current locale - std::string lang = toLower(std::string(setlocale(LC_CTYPE, ""))); - lang = lang.substr(0, 2); + std::string lang = CI18N::getSystemLanguageCode(); const std::vector &languages = CI18N::getLanguageCodes(); diff --git a/code/ryzom/client/src/main_loop.cpp b/code/ryzom/client/src/main_loop.cpp index 8a900f381..c0beba4c1 100644 --- a/code/ryzom/client/src/main_loop.cpp +++ b/code/ryzom/client/src/main_loop.cpp @@ -2015,7 +2015,7 @@ bool mainLoop() } // Temp for weather test - if (ClientCfg.ManualWeatherSetup && ContinentMngr.cur() && ContinentMngr.cur()->WeatherFunction) + if (ClientCfg.ManualWeatherSetup) { H_AUTO_USE ( RZ_Client_Main_Loop_Debug ) static float displayHourDelta = 0.04f; // static for edition during debug..