1
0
Fork 0

Improved locale detection on Mac.

Respect the user's language selection in the system settings, and try those languages in turn. If a language is explicitly specified, try that first regardless.
This commit is contained in:
James Turner 2013-03-27 22:48:16 +00:00
parent db5a39e305
commit 67f2147f3d
2 changed files with 70 additions and 27 deletions

View file

@ -26,6 +26,8 @@
#include <windows.h>
#endif
#include <boost/foreach.hpp>
#include <simgear/props/props_io.hxx>
#include <simgear/structure/exception.hxx>
@ -57,9 +59,10 @@ FGLocale::~FGLocale()
*
* This software comes with no warranty. Use at your own risk.
*/
const char*
string_list
FGLocale::getUserLanguage()
{
string_list result;
static char locale[100] = {0};
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
@ -72,23 +75,55 @@ FGLocale::getUserLanguage()
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_SISO3166CTRYNAME,
locale+i, (int)(sizeof(locale)-i)))
return locale;
{
result.push_back(locale);
return result;
}
locale[--i] = 0;
SG_LOG(SG_GENERAL, SG_WARN, "Failed to detected locale's country setting.");
return locale;
result.push_back(locale);
return result;
}
return NULL;
return result;
}
#else
/**
* Determine locale/language settings on Linux (and Mac?).
*/
const char*
#elif __APPLE__
// determine locale / langauge on Mac
#include <CoreFoundation/CoreFoundation.h>
string_list
FGLocale::getUserLanguage()
{
return ::getenv("LANG");
string_list result;
CFArrayRef langs = CFLocaleCopyPreferredLanguages();
char buffer[64];
for (int i=0; i<CFArrayGetCount(langs); ++i) {
CFStringRef s = (CFStringRef) CFArrayGetValueAtIndex(langs, i);
CFStringGetCString(s, buffer, 64, kCFStringEncodingASCII);
result.push_back(buffer);
}
CFRelease(langs);
return result;
}
#else
/**
* Determine locale/language settings on Linux/Unix.
*/
string_list
FGLocale::getUserLanguage()
{
string_list result;
const char* langEnv = ::getenv("LANG");
if (langEnv) {
result.push_back(langEnv);
}
return result;
}
#endif
@ -142,21 +177,27 @@ FGLocale::findLocaleNode(const string& language)
bool
FGLocale::selectLanguage(const char *language)
{
// Use system setting when no language is given.
if ((language == NULL)||(language[0]==0))
{
language = getUserLanguage();
SG_LOG(SG_GENERAL, SG_INFO, "System language: " << ((language) ? language : "<unavailable>"));
}
// Use plain C locale if nothing is available.
if ((language == NULL)||(language[0]==0))
{
string_list languages = getUserLanguage();
if (languages.empty()) {
// Use plain C locale if nothing is available.
SG_LOG(SG_GENERAL, SG_WARN, "Unable to detect system language" );
language = "C";
languages.push_back("C");
}
// if we were passed a language option, try it first
if ((language != NULL) && (strlen(language) > 0)) {
languages.insert(languages.begin(), string(language));
}
SGPropertyNode *locale = findLocaleNode(language);
SGPropertyNode *locale = NULL;
BOOST_FOREACH(string lang, languages) {
locale = findLocaleNode(lang);
if (locale) {
break;
}
}
if (!locale)
{
SG_LOG(SG_GENERAL, SG_ALERT,

View file

@ -72,10 +72,7 @@ public:
*/
static void utf8toLatin1 (std::string& s);
/**
* Obtain user's default language setting.
*/
const char* getUserLanguage();
protected:
/**
@ -98,6 +95,11 @@ protected:
*/
simgear::PropertyList getLocalizedStrings(SGPropertyNode *localeNode, const char* id, const char* context);
/**
* Obtain user's default language setting.
*/
string_list getUserLanguage();
SGPropertyNode_ptr _intl;
SGPropertyNode_ptr _currentLocale;
SGPropertyNode_ptr _defaultLocale;