ppsspp/Common/Data/Text/I18n.cpp
Henrik Rydgård ff8148dd92 Move native/util, native/data and native/i18 to Common/Data.
Also move colorutil.cpp/h

linking build fix experiment

Delete a bunch of unused CMakeLists.txt files

CMakeLists.txt linking fix

Don't include NativeApp.h from any headers.

Android.mk buildfix

Half of the UWP fix

Buildfix

Minor project file cleanup

Buildfixes

Guess what? More buildfixes!
2020-10-04 07:28:29 +02:00

150 lines
4.2 KiB
C++

#include "Common/Data/Text/I18n.h"
#include "file/ini_file.h"
#include "file/vfs.h"
#include "Common/StringUtils.h"
I18NRepo i18nrepo;
I18NRepo::~I18NRepo() {
Clear();
}
std::string I18NRepo::LanguageID() {
return languageID_;
}
void I18NRepo::Clear() {
std::lock_guard<std::mutex> guard(catsLock_);
for (auto iter = cats_.begin(); iter != cats_.end(); ++iter) {
iter->second.reset();
}
cats_.clear();
}
const char *I18NCategory::T(const char *key, const char *def) {
if (!key) {
return "ERROR";
}
// Replace the \n's with \\n's so that key values with newlines will be found correctly.
std::string modifiedKey = key;
modifiedKey = ReplaceAll(modifiedKey, "\n", "\\n");
auto iter = map_.find(modifiedKey);
if (iter != map_.end()) {
// INFO_LOG(SYSTEM, "translation key found in %s: %s", name_.c_str(), key);
return iter->second.text.c_str();
} else {
std::lock_guard<std::mutex> guard(missedKeyLock_);
if (def)
missedKeyLog_[key] = def;
else
missedKeyLog_[key] = modifiedKey.c_str();
// INFO_LOG(SYSTEM, "Missed translation key in %s: %s", name_.c_str(), key);
return def ? def : key;
}
}
void I18NCategory::SetMap(const std::map<std::string, std::string> &m) {
for (auto iter = m.begin(); iter != m.end(); ++iter) {
if (map_.find(iter->first) == map_.end()) {
std::string text = ReplaceAll(iter->second, "\\n", "\n");
map_[iter->first] = I18NEntry(text);
// INFO_LOG(SYSTEM, "Language entry: %s -> %s", iter->first.c_str(), text.c_str());
}
}
}
std::shared_ptr<I18NCategory> I18NRepo::GetCategory(const char *category) {
std::lock_guard<std::mutex> guard(catsLock_);
auto iter = cats_.find(category);
if (iter != cats_.end()) {
return iter->second;
} else {
I18NCategory *c = new I18NCategory(this, category);
cats_[category].reset(c);
return cats_[category];
}
}
std::string I18NRepo::GetIniPath(const std::string &languageID) const {
return "lang/" + languageID + ".ini";
}
bool I18NRepo::IniExists(const std::string &languageID) const {
FileInfo info;
if (!VFSGetFileInfo(GetIniPath(languageID).c_str(), &info))
return false;
if (!info.exists)
return false;
return true;
}
bool I18NRepo::LoadIni(const std::string &languageID, const std::string &overridePath) {
IniFile ini;
std::string iniPath;
// INFO_LOG(SYSTEM, "Loading lang ini %s", iniPath.c_str());
if (!overridePath.empty()) {
iniPath = overridePath + languageID + ".ini";
} else {
iniPath = GetIniPath(languageID);
}
if (!ini.LoadFromVFS(iniPath))
return false;
Clear();
const std::vector<Section> &sections = ini.Sections();
std::lock_guard<std::mutex> guard(catsLock_);
for (auto iter = sections.begin(); iter != sections.end(); ++iter) {
if (iter->name() != "") {
cats_[iter->name()].reset(LoadSection(&(*iter), iter->name().c_str()));
}
}
languageID_ = languageID;
return true;
}
I18NCategory *I18NRepo::LoadSection(const Section *section, const char *name) {
I18NCategory *cat = new I18NCategory(this, name);
std::map<std::string, std::string> sectionMap = section->ToMap();
cat->SetMap(sectionMap);
return cat;
}
// This is a very light touched save variant - it won't overwrite
// anything, only create new entries.
void I18NRepo::SaveIni(const std::string &languageID) {
IniFile ini;
ini.Load(GetIniPath(languageID));
std::lock_guard<std::mutex> guard(catsLock_);
for (auto iter = cats_.begin(); iter != cats_.end(); ++iter) {
std::string categoryName = iter->first;
Section *section = ini.GetOrCreateSection(categoryName.c_str());
SaveSection(ini, section, iter->second);
}
ini.Save(GetIniPath(languageID));
}
void I18NRepo::SaveSection(IniFile &ini, Section *section, std::shared_ptr<I18NCategory> cat) {
const std::map<std::string, std::string> &missed = cat->Missed();
for (auto iter = missed.begin(); iter != missed.end(); ++iter) {
if (!section->Exists(iter->first.c_str())) {
std::string text = ReplaceAll(iter->second, "\n", "\\n");
section->Set(iter->first, text);
}
}
const std::map<std::string, I18NEntry> &entries = cat->GetMap();
for (auto iter = entries.begin(); iter != entries.end(); ++iter) {
std::string text = ReplaceAll(iter->second.text, "\n", "\\n");
section->Set(iter->first, text);
}
cat->ClearMissed();
}