Fix locale verification to also allow ICU locales without data, but still don't allow bogus locales. Patch by Yves. Fixes #2533.

This was SVN commit r15122.
This commit is contained in:
sanderd17 2014-05-07 08:14:57 +00:00
parent c5b184744c
commit 19ca1e3ebf
6 changed files with 114 additions and 59 deletions

View File

@ -5,16 +5,13 @@ function init()
languageList.list_data = Engine.GetSupportedLocaleBaseNames();
var currentLocale = Engine.GetCurrentLocale();
var currentLocaleBaseName = Engine.GetLocaleBaseName(currentLocale);
var currentLocaleLanguage = Engine.GetLocaleLanguage(currentLocale);
var currentLocaleDictName = Engine.GetFallbackToAvailableDictLocale(currentLocale);
var useLongStrings = Engine.UseLongStrings();
var index = -1;
if (useLongStrings)
index = languageList.list_data.indexOf("long");
if (index == -1)
index = languageList.list_data.indexOf(currentLocaleBaseName);
if (index == -1)
index = languageList.list_data.indexOf(currentLocaleLanguage);
index = languageList.list_data.indexOf(currentLocaleDictName);
if (index != -1)
languageList.selected = index;
@ -65,12 +62,12 @@ function applyFromAdvancedMenu(locale)
{
var languageList = Engine.GetGUIObjectByName("languageList");
var localeBaseName = Engine.GetLocaleBaseName(locale);
var localeLanguage = Engine.GetLocaleLanguage(locale);
if (languageList.list_data.indexOf(localeBaseName) != -1)
languageList.selected = languageList.list_data.indexOf(localeBaseName);
else if (languageList.list_data.indexOf(localeLanguage) != -1)
languageList.selected = languageList.list_data.indexOf(localeLanguage);
var currentLocaleDictName = Engine.GetFallbackToAvailableDictLocale(locale);
var index = -1;
index = languageList.list_data.indexOf(currentLocaleDictName);
if (index != -1)
languageList.selected = index;
var localeText = Engine.GetGUIObjectByName("localeText");
localeText.caption = locale;

View File

@ -79,7 +79,7 @@ function updateResultingLocale()
if (Engine.ValidateLocale(resultingLocaleTmp))
{
resultingLocaleText.caption = resultingLocaleTmp;
var dictionaryFileList = Engine.GetDictionariesForDictLocale(Engine.GetDictionaryLocale(resultingLocaleTmp));
var dictionaryFileList = Engine.GetDictionariesForLocale(Engine.GetDictionaryLocale(resultingLocaleTmp));
var dictionaryFileString = "";
dictionaryFileList.forEach( function (entry) { dictionaryFileString = dictionaryFileString + entry + "\n"; });
dictionaryFile.caption = dictionaryFileString;

View File

@ -102,45 +102,23 @@ bool L10n::ValidateLocale(const std::string& localeCode)
// 2. Either a dictionary for language_country or for language is available.
bool L10n::ValidateLocale(Locale locale)
{
int32_t count;
bool icuSupported = false;
const Locale* icuSupportedLocales = Locale::getAvailableLocales(count);
for (int i=0; i<count; ++i)
{
if (icuSupportedLocales[i] == locale)
{
icuSupported = true;
break;
}
}
if(!icuSupported)
if(locale.isBogus())
return false;
for (std::vector<Locale*>::iterator iterator = availableLocales.begin(); iterator != availableLocales.end(); ++iterator)
{
if ((strcmp((*iterator)->getLanguage(), locale.getLanguage()) == 0 && strcmp((*iterator)->getCountry(), "") == 0) ||
(strcmp((*iterator)->getLanguage(), locale.getLanguage()) == 0 && strcmp((*iterator)->getCountry(), locale.getCountry()) == 0))
{
return true;
}
}
return false;
std::wstring dictLocale = GetFallbackToAvailableDictLocale(locale);
if (dictLocale.empty())
return false;
return true;
}
std::vector<std::wstring> L10n::GetDictionariesForDictLocale(const std::string& locale)
std::vector<std::wstring> L10n::GetDictionariesForLocale(const std::string& locale)
{
std::wstring tmpLocale(locale.begin(), locale.end());
std::vector<std::wstring> ret;
VfsPaths filenames;
if (vfs::GetPathnames(g_VFS, L"l10n/", tmpLocale.append(L".*.po").c_str(), filenames) < 0)
return ret;
if (filenames.size() == 0)
{
Locale tmpLocale1 = Locale::createCanonical(locale.c_str());
if (vfs::GetPathnames(g_VFS, L"l10n/", wstring_from_utf8(tmpLocale1.getLanguage()).append(L".*.po").c_str(), filenames) < 0)
return ret;
}
std::wstring dictName = GetFallbackToAvailableDictLocale(Locale::createCanonical(locale.c_str()));
vfs::GetPathnames(g_VFS, L"l10n/", dictName.append(L".*.po").c_str(), filenames);
for (VfsPaths::iterator it = filenames.begin(); it != filenames.end(); ++it)
{
@ -150,6 +128,60 @@ std::vector<std::wstring> L10n::GetDictionariesForDictLocale(const std::string&
return ret;
}
L10n::CheckLangAndCountry::CheckLangAndCountry(const Locale& locale) : m_MatchLocale(locale)
{
}
bool L10n::CheckLangAndCountry::operator()(const Locale* const locale)
{
bool found = false;
found = strcmp(m_MatchLocale.getLanguage(), locale->getLanguage()) == 0;
found &= strcmp(m_MatchLocale.getCountry(), locale->getCountry()) == 0;
return found;
}
L10n::CheckLang::CheckLang(const Locale& locale) : m_MatchLocale(locale)
{
}
bool L10n::CheckLang::operator()(const Locale* const locale)
{
bool found = false;
found = strcmp(m_MatchLocale.getLanguage(), locale->getLanguage()) == 0;
return found;
}
std::wstring L10n::GetFallbackToAvailableDictLocale(const std::string& locale)
{
return GetFallbackToAvailableDictLocale(Locale::createCanonical(locale.c_str()));
}
std::wstring L10n::GetFallbackToAvailableDictLocale(const Locale& locale)
{
std::wstringstream stream;
if (strcmp(locale.getCountry(), "") != 0)
{
CheckLangAndCountry fun(locale);
std::vector<Locale*>::iterator itr = find_if(availableLocales.begin(), availableLocales.end(), fun);
if (itr != availableLocales.end())
{
stream << locale.getLanguage() << L"_" << locale.getCountry();
return stream.str();
}
}
CheckLang fun(locale);
std::vector<Locale*>::iterator itr = find_if(availableLocales.begin(), availableLocales.end(), fun);
if (itr != availableLocales.end())
{
stream << locale.getLanguage();
return stream.str();
}
return L"";
}
std::string L10n::GetDictionaryLocale(std::string configLocaleString)
{
Locale out;
@ -180,7 +212,7 @@ void L10n::GetDictionaryLocale(std::string configLocaleString, Locale& outLocale
}
// Try to find the best disctionary locale based on user configuration and system locale, set the currentLocale and reload the dictionary.
// Try to find the best dictionary locale based on user configuration and system locale, set the currentLocale and reload the dictionary.
void L10n::ReevaluateCurrentLocaleAndReload()
{
std::string locale;
@ -427,15 +459,12 @@ void L10n::LoadDictionaryForCurrentLocale()
}
else
{
if (vfs::GetPathnames(g_VFS, L"l10n/", (wstring_from_utf8(currentLocale.getBaseName()) + L".*.po").c_str(), filenames) < 0)
return;
}
// If not matching country is found, try to fall back to a matching language
if (filenames.size() == 0)
{
if (vfs::GetPathnames(g_VFS, L"l10n/", (wstring_from_utf8(currentLocale.getLanguage()) + L".*.po").c_str(), filenames) < 0)
std::wstring dictName = GetFallbackToAvailableDictLocale(currentLocale);
if (vfs::GetPathnames(g_VFS, L"l10n/", dictName.append(L".*.po").c_str(), filenames) < 0)
{
LOGERROR(L"No files for the dictionary found, but at this point the input should already be validated!");
return;
}
}
for (VfsPaths::iterator it = filenames.begin(); it != filenames.end(); ++it)

View File

@ -250,7 +250,27 @@ public:
* @return Array of paths to files in the virtual filesystem that provide
* translations for @p locale.
*/
std::vector<std::wstring> GetDictionariesForDictLocale(const std::string& locale);
std::vector<std::wstring> GetDictionariesForLocale(const std::string& locale);
std::wstring GetFallbackToAvailableDictLocale(const Locale& locale);
std::wstring GetFallbackToAvailableDictLocale(const std::string& locale);
struct CheckLangAndCountry
{
CheckLangAndCountry(const Locale& locale);
const Locale& m_MatchLocale;
bool operator()(const Locale* const locale);
};
struct CheckLang
{
CheckLang(const Locale& locale);
const Locale& m_MatchLocale;
bool operator()(const Locale* const locale);
};
/**
* Returns the code of the recommended locale for the current user that the

View File

@ -64,6 +64,11 @@ std::vector<std::wstring> JSI_L10n::TranslateArray(ScriptInterface::CxPrivate* U
return translatedArray;
}
std::wstring JSI_L10n::GetFallbackToAvailableDictLocale(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string locale)
{
return L10n::Instance().GetFallbackToAvailableDictLocale(locale);
}
// Return a localized version of a time given in milliseconds.
std::wstring JSI_L10n::FormatMillisecondsIntoDateString(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), UDate milliseconds, std::wstring formatString)
{
@ -106,9 +111,9 @@ std::string JSI_L10n::GetDictionaryLocale(ScriptInterface::CxPrivate* UNUSED(pCx
return L10n::Instance().GetDictionaryLocale(configLocale);
}
std::vector<std::wstring> JSI_L10n::GetDictionariesForDictLocale(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string locale)
std::vector<std::wstring> JSI_L10n::GetDictionariesForLocale(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string locale)
{
return L10n::Instance().GetDictionariesForDictLocale(locale);
return L10n::Instance().GetDictionariesForLocale(locale);
}
std::string JSI_L10n::GetLocaleLanguage(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string locale)
@ -163,13 +168,14 @@ void JSI_L10n::RegisterScriptFunctions(ScriptInterface& scriptInterface)
scriptInterface.RegisterFunction<std::string, &GetCurrentLocale>("GetCurrentLocale");
scriptInterface.RegisterFunction<std::vector<std::string>, &GetAllLocales>("GetAllLocales");
scriptInterface.RegisterFunction<std::string, std::string, &GetDictionaryLocale>("GetDictionaryLocale");
scriptInterface.RegisterFunction<std::vector<std::wstring>, std::string, &GetDictionariesForDictLocale>("GetDictionariesForDictLocale");
scriptInterface.RegisterFunction<std::vector<std::wstring>, std::string, &GetDictionariesForLocale>("GetDictionariesForLocale");
scriptInterface.RegisterFunction<bool, &UseLongStrings>("UseLongStrings");
scriptInterface.RegisterFunction<std::string, std::string, &GetLocaleLanguage>("GetLocaleLanguage");
scriptInterface.RegisterFunction<std::string, std::string, &GetLocaleBaseName>("GetLocaleBaseName");
scriptInterface.RegisterFunction<std::string, std::string, &GetLocaleCountry>("GetLocaleCountry");
scriptInterface.RegisterFunction<std::string, std::string, &GetLocaleScript>("GetLocaleScript");
scriptInterface.RegisterFunction<std::wstring, std::string, &GetFallbackToAvailableDictLocale>("GetFallbackToAvailableDictLocale");
scriptInterface.RegisterFunction<bool, std::string, &ValidateLocale>("ValidateLocale");
scriptInterface.RegisterFunction<bool, std::string, &SaveLocale>("SaveLocale");

View File

@ -292,14 +292,14 @@ namespace JSI_L10n
* Returns an array of paths to files in the virtual filesystem that provide
* translations for the specified locale code.
*
* This is a JavaScript interface to L10n::GetDictionariesForDictLocale().
* This is a JavaScript interface to L10n::GetDictionariesForLocale().
*
* @param pCxPrivate JavaScript context.
* @param locale Locale code.
* @return Array of paths to files in the virtual filesystem that provide
* translations for @p locale.
*/
std::vector<std::wstring> GetDictionariesForDictLocale(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string locale);
std::vector<std::wstring> GetDictionariesForLocale(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string locale);
/**
* Returns the ISO-639 language code of the specified locale code.
@ -357,6 +357,9 @@ namespace JSI_L10n
*/
std::string GetLocaleScript(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string locale);
std::wstring GetFallbackToAvailableDictLocale(ScriptInterface::CxPrivate* UNUSED(pCxPrivate), std::string locale);
/**
* Returns @c true if the current locale is the special Long Strings
* locale. It returns @c false otherwise.