forked from organicmaps/organicmaps
[platform] Cache system languages.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
This commit is contained in:
parent
0d6cfcbfe1
commit
36e006ec63
1 changed files with 82 additions and 76 deletions
|
@ -1,14 +1,13 @@
|
|||
#include "platform/preferred_languages.hpp"
|
||||
|
||||
#include "base/buffer_vector.hpp"
|
||||
#include "base/string_utils.hpp"
|
||||
#include "base/macros.hpp"
|
||||
|
||||
#include "std/target_os.hpp"
|
||||
|
||||
#include <cstdlib> // getenv
|
||||
#include <cstring> // strlen
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE)
|
||||
#include <CoreFoundation/CFLocale.h>
|
||||
|
@ -39,113 +38,120 @@ static const MSLocale gLocales[] = {{0x1,"ar"},{0x2,"bg"},{0x3,"ca"},{0x4,"zh-Ha
|
|||
|
||||
namespace languages
|
||||
{
|
||||
void GetSystemPreferred(std::vector<std::string> & languages)
|
||||
struct SystemLanguages
|
||||
{
|
||||
/// @DebugNote
|
||||
// Hardcode draw text language.
|
||||
//languages.push_back("hi");
|
||||
//return;
|
||||
buffer_vector<std::string, 4> m_langs;
|
||||
|
||||
SystemLanguages()
|
||||
{
|
||||
/// @DebugNote
|
||||
// Hardcode draw text language.
|
||||
//m_langs.push_back("hi");
|
||||
//return;
|
||||
|
||||
#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE) || defined(OMIM_OS_LINUX)
|
||||
// check environment variables
|
||||
char const * p = std::getenv("LANGUAGE");
|
||||
if (p && strlen(p)) // LANGUAGE can contain several values divided by ':'
|
||||
languages = strings::Tokenize<std::string>(p, ":");
|
||||
else if ((p = getenv("LC_ALL")))
|
||||
languages.push_back(p);
|
||||
else if ((p = getenv("LC_MESSAGES")))
|
||||
languages.push_back(p);
|
||||
else if ((p = getenv("LANG")))
|
||||
languages.push_back(p);
|
||||
// check environment variables
|
||||
char const * p = std::getenv("LANGUAGE");
|
||||
if (p && strlen(p)) // LANGUAGE can contain several values divided by ':'
|
||||
strings::Tokenize(p, ":", [this](std::string_view s) { m_langs.push_back(std::string(s)); });
|
||||
else if ((p = getenv("LC_ALL")))
|
||||
m_langs.push_back(p);
|
||||
else if ((p = getenv("LC_MESSAGES")))
|
||||
m_langs.push_back(p);
|
||||
else if ((p = getenv("LANG")))
|
||||
m_langs.push_back(p);
|
||||
|
||||
#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE)
|
||||
else
|
||||
{
|
||||
// Mac and iOS implementation
|
||||
CFArrayRef langs = CFLocaleCopyPreferredLanguages();
|
||||
char buf[30];
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(langs); ++i)
|
||||
#if defined(OMIM_OS_MAC) || defined(OMIM_OS_IPHONE)
|
||||
else
|
||||
{
|
||||
CFStringRef strRef = (CFStringRef)CFArrayGetValueAtIndex(langs, i);
|
||||
CFStringGetCString(strRef, buf, 30, kCFStringEncodingUTF8);
|
||||
languages.push_back(buf);
|
||||
// Mac and iOS implementation
|
||||
CFArrayRef langs = CFLocaleCopyPreferredLanguages();
|
||||
char buf[30];
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(langs); ++i)
|
||||
{
|
||||
CFStringRef strRef = (CFStringRef)CFArrayGetValueAtIndex(langs, i);
|
||||
CFStringGetCString(strRef, buf, 30, kCFStringEncodingUTF8);
|
||||
m_langs.push_back(buf);
|
||||
}
|
||||
CFRelease(langs);
|
||||
}
|
||||
CFRelease(langs);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined(OMIM_OS_WINDOWS)
|
||||
// if we're on Vista or above, take list of preferred languages
|
||||
typedef BOOL (WINAPI *PGETUSERPREFERREDUILANGUAGES)(DWORD, PULONG, PWCHAR, PULONG);
|
||||
PGETUSERPREFERREDUILANGUAGES p =
|
||||
reinterpret_cast<PGETUSERPREFERREDUILANGUAGES>(
|
||||
GetProcAddress(GetModuleHandleA("Kernel32.dll"), "GetUserPreferredUILanguages"));
|
||||
if (p)
|
||||
{
|
||||
// Vista or above, get buffer size first
|
||||
ULONG numLangs;
|
||||
WCHAR * buf = NULL;
|
||||
ULONG bufSize = 0;
|
||||
CHECK_EQUAL(TRUE, p(MUI_LANGUAGE_NAME, &numLangs, buf, &bufSize), ());
|
||||
CHECK_GREATER(bufSize, 0U, ("GetUserPreferredUILanguages failed"));
|
||||
buf = new WCHAR[++bufSize];
|
||||
p(MUI_LANGUAGE_NAME, &numLangs, buf, &bufSize);
|
||||
size_t len;
|
||||
WCHAR * pCurr = buf;
|
||||
while ((len = wcslen(pCurr)))
|
||||
// if we're on Vista or above, take list of preferred languages
|
||||
typedef BOOL (WINAPI *PGETUSERPREFERREDUILANGUAGES)(DWORD, PULONG, PWCHAR, PULONG);
|
||||
PGETUSERPREFERREDUILANGUAGES p =
|
||||
reinterpret_cast<PGETUSERPREFERREDUILANGUAGES>(
|
||||
GetProcAddress(GetModuleHandleA("Kernel32.dll"), "GetUserPreferredUILanguages"));
|
||||
if (p)
|
||||
{
|
||||
char * utf8Buf = new char[len*2];
|
||||
CHECK_NOT_EQUAL(WideCharToMultiByte(CP_UTF8, 0, pCurr, -1, utf8Buf, len*2, NULL, NULL), 0, ());
|
||||
languages.push_back(utf8Buf);
|
||||
delete[] utf8Buf;
|
||||
pCurr += len + 1;
|
||||
}
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
if (languages.empty())
|
||||
{
|
||||
// used mostly on WinXP
|
||||
LANGID langId = GetUserDefaultLangID();
|
||||
for (size_t i = 0; i < ARRAY_SIZE(gLocales); ++i)
|
||||
if (gLocales[i].m_code == langId)
|
||||
// Vista or above, get buffer size first
|
||||
ULONG numLangs;
|
||||
WCHAR * buf = NULL;
|
||||
ULONG bufSize = 0;
|
||||
CHECK_EQUAL(TRUE, p(MUI_LANGUAGE_NAME, &numLangs, buf, &bufSize), ());
|
||||
CHECK_GREATER(bufSize, 0U, ("GetUserPreferredUILanguages failed"));
|
||||
buf = new WCHAR[++bufSize];
|
||||
p(MUI_LANGUAGE_NAME, &numLangs, buf, &bufSize);
|
||||
size_t len;
|
||||
WCHAR * pCurr = buf;
|
||||
while ((len = wcslen(pCurr)))
|
||||
{
|
||||
languages.push_back(gLocales[i].m_name);
|
||||
break;
|
||||
char * utf8Buf = new char[len*2];
|
||||
CHECK_NOT_EQUAL(WideCharToMultiByte(CP_UTF8, 0, pCurr, -1, utf8Buf, len*2, NULL, NULL), 0, ());
|
||||
m_langs.push_back(utf8Buf);
|
||||
delete[] utf8Buf;
|
||||
pCurr += len + 1;
|
||||
}
|
||||
}
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
if (m_langs.empty())
|
||||
{
|
||||
// used mostly on WinXP
|
||||
LANGID langId = GetUserDefaultLangID();
|
||||
for (size_t i = 0; i < ARRAY_SIZE(gLocales); ++i)
|
||||
if (gLocales[i].m_code == langId)
|
||||
{
|
||||
m_langs.push_back(gLocales[i].m_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(OMIM_OS_ANDROID)
|
||||
languages.push_back(GetAndroidSystemLanguage());
|
||||
m_langs.push_back(GetAndroidSystemLanguage());
|
||||
#else
|
||||
#error "Define language preferences for your platform"
|
||||
#error "Define language preferences for your platform"
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
buffer_vector<std::string, 4> const & GetSystemPreferred()
|
||||
{
|
||||
static SystemLanguages const langs;
|
||||
return langs.m_langs;
|
||||
}
|
||||
|
||||
std::string GetPreferred()
|
||||
{
|
||||
std::vector<std::string> arr;
|
||||
GetSystemPreferred(arr);
|
||||
|
||||
// generate output string
|
||||
std::string result;
|
||||
for (size_t i = 0; i < arr.size(); ++i)
|
||||
for (auto const & e : GetSystemPreferred())
|
||||
{
|
||||
result.append(arr[i]);
|
||||
result.append(e);
|
||||
result.push_back('|');
|
||||
}
|
||||
|
||||
if (result.empty())
|
||||
result = "default";
|
||||
else
|
||||
result.resize(result.size() - 1);
|
||||
result.pop_back();
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string GetCurrentOrig()
|
||||
{
|
||||
std::vector<std::string> arr;
|
||||
GetSystemPreferred(arr);
|
||||
auto const & arr = GetSystemPreferred();
|
||||
if (arr.empty())
|
||||
return "en";
|
||||
else
|
||||
|
|
Loading…
Add table
Reference in a new issue