1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

Use locale based on language set in config

This commit is contained in:
MichalZr6
2025-03-06 23:28:01 +01:00
parent 38b994f28e
commit e993c2aed0
5 changed files with 66 additions and 7 deletions

View File

@@ -59,7 +59,7 @@ bool mapSorter::operator()(const std::shared_ptr<ElementInfo> aaa, const std::sh
{
if(boost::algorithm::starts_with(aaa->folderName, "..") || boost::algorithm::starts_with(bbb->folderName, ".."))
return boost::algorithm::starts_with(aaa->folderName, "..");
return boost::ilexicographical_compare(aaa->folderName, bbb->folderName);
return TextOperations::compareLocalizedStrings(aaa->folderName, bbb->folderName);
}
}
@@ -114,9 +114,9 @@ bool mapSorter::operator()(const std::shared_ptr<ElementInfo> aaa, const std::sh
return (a->victoryIconIndex < b->victoryIconIndex);
break;
case _name: //by name
return aaa->name < bbb->name;
return TextOperations::compareLocalizedStrings(aaa->name, bbb->name);
case _fileName: //by filename
return boost::ilexicographical_compare(aaa->fileURI, bbb->fileURI);
return TextOperations::compareLocalizedStrings(aaa->fileURI, bbb->fileURI);
case _changeDate: //by changedate
return aaa->lastWrite < bbb->lastWrite;
default:
@@ -130,9 +130,9 @@ bool mapSorter::operator()(const std::shared_ptr<ElementInfo> aaa, const std::sh
case _numOfMaps: //by number of maps in campaign
return aaa->campaign->scenariosCount() < bbb->campaign->scenariosCount();
case _name: //by name
return boost::ilexicographical_compare(aaa->campaign->getNameTranslated(), bbb->campaign->getNameTranslated());
return TextOperations::compareLocalizedStrings(aaa->campaign->getNameTranslated(), bbb->campaign->getNameTranslated());
default:
return boost::ilexicographical_compare(aaa->campaign->getNameTranslated(), bbb->campaign->getNameTranslated());
return TextOperations::compareLocalizedStrings(aaa->campaign->getNameTranslated(), bbb->campaign->getNameTranslated());
}
}
}

View File

@@ -92,7 +92,7 @@ public:
return false;
}
return A->getNameTranslated() < B->getNameTranslated();
return TextOperations::compareLocalizedStrings(A->getNameTranslated(), B->getNameTranslated());
}
};

View File

@@ -63,6 +63,9 @@ struct Options
/// encoding that is used by H3 for this language
std::string encoding;
/// proper locale name, e.g. "en_US.UTF-8"
std::string localeName;
/// primary IETF language tag
std::string tagIETF;
@@ -83,6 +86,7 @@ inline const auto & getLanguageList()
{
static const std::array<Options, 20> languages
{ {
<<<<<<< HEAD
{ "czech", "Czech", "Čeština", "CP1250", "cs", "cze", "%d.%m.%Y %H:%M", EPluralForms::CZ_3, true },
{ "chinese", "Chinese", "简体中文", "GBK", "zh", "chi", "%Y-%m-%d %H:%M", EPluralForms::VI_1, true }, // Note: actually Simplified Chinese
{ "english", "English", "English", "CP1252", "en", "eng", "%Y-%m-%d %H:%M", EPluralForms::EN_2, true }, // English uses international date/time format here
@@ -103,6 +107,25 @@ inline const auto & getLanguageList()
{ "turkish", "Turkish", "Türkçe", "CP1254", "tr", "tur", "%d.%m.%Y %H:%M", EPluralForms::EN_2, true },
{ "ukrainian", "Ukrainian", "Українська", "CP1251", "uk", "ukr", "%d.%m.%Y %H:%M", EPluralForms::UK_3, true },
{ "vietnamese", "Vietnamese", "Tiếng Việt", "UTF-8", "vi", "vie", "%d/%m/%Y %H:%M", EPluralForms::VI_1, true }, // Fan translation uses special encoding
=======
{ "czech", "Czech", "Čeština", "CP1250", "cs_CZ.UTF-8", "cs", "cze", "%d.%m.%Y %H:%M", EPluralForms::CZ_3 },
{ "chinese", "Chinese", "简体中文", "GBK", "zh_CN.UTF-8", "zh", "chi", "%Y-%m-%d %H:%M", EPluralForms::VI_1 }, // Note: actually Simplified Chinese
{ "english", "English", "English", "CP1252", "en_US.UTF-8", "en", "eng", "%Y-%m-%d %H:%M", EPluralForms::EN_2 }, // English uses international date/time format here
{ "finnish", "Finnish", "Suomi", "CP1252", "fi_FI.UTF-8", "fi", "fin", "%d.%m.%Y %H:%M", EPluralForms::EN_2, },
{ "french", "French", "Français", "CP1252", "fr_FR.UTF-8", "fr", "fre", "%d/%m/%Y %H:%M", EPluralForms::FR_2, },
{ "german", "German", "Deutsch", "CP1252", "de_DE.UTF-8", "de", "ger", "%d.%m.%Y %H:%M", EPluralForms::EN_2, },
{ "hungarian", "Hungarian", "Magyar", "CP1250", "hu_HU.UTF-8", "hu", "hun", "%Y. %m. %d. %H:%M", EPluralForms::EN_2 },
{ "italian", "Italian", "Italiano", "CP1250", "it_IT.UTF-8", "it", "ita", "%d/%m/%Y %H:%M", EPluralForms::EN_2 },
{ "korean", "Korean", "한국어", "CP949", "ko_KR.UTF-8", "ko", "kor", "%Y-%m-%d %H:%M", EPluralForms::VI_1 },
{ "polish", "Polish", "Polski", "CP1250", "pl_PL.UTF-8", "pl", "pol", "%d.%m.%Y %H:%M", EPluralForms::PL_3 },
{ "portuguese", "Portuguese", "Português", "CP1252", "pt_BR.UTF-8", "pt", "por", "%d/%m/%Y %H:%M", EPluralForms::EN_2 }, // Note: actually Brazilian Portuguese
{ "russian", "Russian", "Русский", "CP1251", "ru_RU.UTF-8", "ru", "rus", "%d.%m.%Y %H:%M", EPluralForms::UK_3 },
{ "spanish", "Spanish", "Español", "CP1252", "es_ES.UTF-8", "es", "spa", "%d/%m/%Y %H:%M", EPluralForms::EN_2 },
{ "swedish", "Swedish", "Svenska", "CP1252", "sv_SE.UTF-8", "sv", "swe", "%Y-%m-%d %H:%M", EPluralForms::EN_2 },
{ "turkish", "Turkish", "Türkçe", "CP1254", "tr_TR.UTF-8", "tr", "tur", "%d.%m.%Y %H:%M", EPluralForms::EN_2 },
{ "ukrainian", "Ukrainian", "Українська", "CP1251", "uk_UA.UTF-8", "uk", "ukr", "%d.%m.%Y %H:%M", EPluralForms::UK_3 },
{ "vietnamese", "Vietnamese", "Tiếng Việt", "UTF-8", "vi_VN.UTF-8", "vi", "vie", "%d/%m/%Y %H:%M", EPluralForms::VI_1 }, // Fan translation uses special encoding
>>>>>>> 364b3cef9 (Use locale based on language set in config)
} };
static_assert(languages.size() == static_cast<size_t>(ELanguages::COUNT), "Languages array is missing a value!");

View File

@@ -300,10 +300,29 @@ int TextOperations::getLevenshteinDistance(const std::string & s, const std::str
return v0[n];
}
DLL_LINKAGE std::string TextOperations::getLocaleName()
{
try
{
const std::string localeName = Languages::getLanguageOptions(VLC->generaltexth->getPreferredLanguage()).localeName;
if(localeName.empty())
throw std::runtime_error("Locale name is empty, will use fallback option.");
return localeName;
}
catch(const std::exception & e)
{
logGlobal->warn("Failed to retrieve locale. Using fallback: en_US.UTF-8");
return "en_US.UTF-8";
}
}
bool TextOperations::textSearchSimilar(const std::string & s, const std::string & t)
{
boost::locale::generator gen;
std::locale loc = gen("en_US.UTF-8"); // support for UTF8 lowercase
std::locale loc = gen(getLocaleName());
auto haystack = boost::locale::to_lower(t, loc);
auto needle = boost::locale::to_lower(s, loc);

View File

@@ -9,6 +9,9 @@
*/
#pragma once
#include "../../lib/texts/Languages.h"
#include "../../lib/VCMI_Lib.h"
VCMI_LIB_NAMESPACE_BEGIN
/// Namespace that provides utilities for unicode support (UTF-8)
@@ -76,8 +79,22 @@ namespace TextOperations
/// https://en.wikipedia.org/wiki/Levenshtein_distance#Iterative_with_two_matrix_rows
DLL_LINKAGE int getLevenshteinDistance(const std::string & s, const std::string & t);
/// Retrieves the locale name based on the selected (in config) game language, with a safe fallback.
DLL_LINKAGE std::string getLocaleName();
/// Compares two strings using locale-aware collation based on the selected game language.
DLL_LINKAGE inline bool compareLocalizedStrings(std::string_view str1, std::string_view str2)
{
static const std::locale loc(getLocaleName());
static const std::collate<char> & col = std::use_facet<std::collate<char>>(loc);
return col.compare(str1.data(), str1.data() + str1.size(),
str2.data(), str2.data() + str2.size()) < 0;
}
/// Check if texts have similarity when typing into search boxes
DLL_LINKAGE bool textSearchSimilar(const std::string & s, const std::string & t);
};
template<typename Arithmetic>