CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Common/Data/Text/I18n.cpp
Views: 1401
#include <cstring>12#include "Common/Data/Text/I18n.h"3#include "Common/Data/Format/IniFile.h"4#include "Common/File/VFS/VFS.h"5#include "Common/Log.h"67#include "Common/StringUtils.h"89static const char * const g_categoryNames[(size_t)I18NCat::CATEGORY_COUNT] = {10"Audio",11"Controls",12"CwCheats",13"DesktopUI",14"Developer",15"Dialog",16"Error",17"Game",18"Graphics",19"InstallZip",20"KeyMapping",21"MainMenu",22"MainSettings",23"MappableControls",24"Networking",25"Pause",26"PostShaders",27"PSPCredits",28"MemStick",29"RemoteISO",30"Reporting",31"Savedata",32"Screen",33"Search",34"Store",35"SysInfo",36"System",37"TextureShaders",38"Themes",39"UI Elements",40"Upgrade",41"VR",42"Achievements",43"PSPSettings",44};4546I18NRepo g_i18nrepo;4748std::string I18NRepo::LanguageID() {49return languageID_;50}5152I18NRepo::I18NRepo() {53Clear();54}5556void I18NRepo::Clear() {57std::lock_guard<std::mutex> guard(catsLock_);58for (auto &iter : cats_) {59// Initialize with empty categories, so that early lookups don't crash.60iter = std::make_shared<I18NCategory>();61}62}6364I18NCategory::I18NCategory(const Section §ion) {65std::map<std::string, std::string> sectionMap = section.ToMap();66SetMap(sectionMap);67}6869void I18NCategory::Clear() {70map_.clear();71missedKeyLog_.clear();72}7374std::string_view I18NCategory::T(std::string_view key, std::string_view def) {75auto iter = map_.find(key);76if (iter != map_.end()) {77return iter->second.text.c_str();78} else {79std::lock_guard<std::mutex> guard(missedKeyLock_);80std::string missedKey(key);81if (!def.empty())82missedKeyLog_[missedKey] = def;83else84missedKeyLog_[missedKey] = std::string(key);85return !def.empty() ? def : key;86}87}8889const char *I18NCategory::T_cstr(const char *key, const char *def) {90auto iter = map_.find(key);91if (iter != map_.end()) {92return iter->second.text.c_str();93} else {94std::lock_guard<std::mutex> guard(missedKeyLock_);95std::string missedKey(key);96if (def)97missedKeyLog_[missedKey] = def;98else99missedKeyLog_[missedKey] = std::string(key);100return def ? def : key;101}102}103104void I18NCategory::SetMap(const std::map<std::string, std::string> &m) {105for (const auto &[key, value] : m) {106if (map_.find(key) == map_.end()) {107std::string text = ReplaceAll(value, "\\n", "\n");108_dbg_assert_(key.find('\n') == std::string::npos);109map_[key] = I18NEntry(text);110}111}112}113114std::map<std::string, std::string> I18NCategory::Missed() const {115std::lock_guard<std::mutex> guard(missedKeyLock_);116return missedKeyLog_;117}118119std::shared_ptr<I18NCategory> I18NRepo::GetCategory(I18NCat category) {120std::lock_guard<std::mutex> guard(catsLock_);121if (category != I18NCat::NONE)122return cats_[(size_t)category];123else124return nullptr;125}126127Path I18NRepo::GetIniPath(const std::string &languageID) const {128return Path("lang") / (languageID + ".ini");129}130131bool I18NRepo::IniExists(const std::string &languageID) const {132File::FileInfo info;133if (!g_VFS.GetFileInfo(GetIniPath(languageID).ToString().c_str(), &info))134return false;135if (!info.exists)136return false;137return true;138}139140bool I18NRepo::LoadIni(const std::string &languageID, const Path &overridePath) {141IniFile ini;142Path iniPath;143144// INFO_LOG(Log::System, "Loading lang ini %s", iniPath.c_str());145if (!overridePath.empty()) {146iniPath = overridePath / (languageID + ".ini");147} else {148iniPath = GetIniPath(languageID);149}150151if (!ini.LoadFromVFS(g_VFS, iniPath.ToString()))152return false;153154Clear();155156const std::vector<std::unique_ptr<Section>> §ions = ini.Sections();157158std::lock_guard<std::mutex> guard(catsLock_);159for (auto §ion : sections) {160for (size_t i = 0; i < (size_t)I18NCat::CATEGORY_COUNT; i++) {161if (!strcmp(section->name().c_str(), g_categoryNames[i])) {162cats_[i].reset(new I18NCategory(*section.get()));163}164}165}166167languageID_ = languageID;168return true;169}170171void I18NRepo::LogMissingKeys() const {172std::lock_guard<std::mutex> guard(catsLock_);173for (size_t i = 0; i < (size_t)I18NCat::CATEGORY_COUNT; i++) {174auto &cat = cats_[i];175for (auto &key : cat->Missed()) {176INFO_LOG(Log::System, "Missing translation [%s]: %s (%s)", g_categoryNames[i], key.first.c_str(), key.second.c_str());177}178}179}180181std::shared_ptr<I18NCategory> GetI18NCategory(I18NCat category) {182if (category == I18NCat::NONE) {183return std::shared_ptr<I18NCategory>();184}185std::shared_ptr<I18NCategory> cat = g_i18nrepo.GetCategory(category);186_dbg_assert_(cat);187return cat;188}189190191