mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
feat(locale): load every locale in locale.xml on request
Locale::LoadFromFile can keep the other locales' phrases too, and GetPhrase(id, locale) answers in one of them, falling back to the default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,12 +3,20 @@
|
||||
#include "Logger.h"
|
||||
|
||||
namespace {
|
||||
std::unordered_map<std::string, std::string> g_Phrases;
|
||||
std::unordered_map<std::string, std::string> g_Phrases; // the default locale's
|
||||
// The other locales' phrases (only loaded with allLocales), by locale
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> g_Others;
|
||||
std::vector<std::string> g_Locales;
|
||||
bool g_Loaded = false;
|
||||
const std::string g_Empty;
|
||||
}
|
||||
|
||||
void Locale::LoadFromFile(const std::string& filepath, const std::string& locale) {
|
||||
void Locale::LoadFromFile(const std::string& filepath, const std::string& locale, bool allLocales) {
|
||||
g_Phrases.clear();
|
||||
g_Others.clear();
|
||||
g_Locales.clear();
|
||||
g_Loaded = false;
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
if (doc.LoadFile(filepath.c_str()) != tinyxml2::XML_SUCCESS) {
|
||||
LOG("Failed to load locale file: %s", filepath.c_str());
|
||||
@@ -18,6 +26,18 @@ void Locale::LoadFromFile(const std::string& filepath, const std::string& locale
|
||||
auto* root = doc.FirstChildElement("localization");
|
||||
if (!root) return;
|
||||
|
||||
g_Locales.push_back(locale);
|
||||
if (allLocales) {
|
||||
if (auto* locales = root->FirstChildElement("locales")) {
|
||||
for (auto* entry = locales->FirstChildElement("locale"); entry; entry = entry->NextSiblingElement("locale")) {
|
||||
const char* name = entry->GetText();
|
||||
if (!name || locale == name || g_Others.contains(name)) continue;
|
||||
g_Locales.push_back(name);
|
||||
g_Others[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto* phrases = root->FirstChildElement("phrases");
|
||||
if (!phrases) return;
|
||||
|
||||
@@ -27,18 +47,20 @@ void Locale::LoadFromFile(const std::string& filepath, const std::string& locale
|
||||
|
||||
for (auto* trans = phrase->FirstChildElement("translation"); trans; trans = trans->NextSiblingElement("translation")) {
|
||||
const char* loc = trans->Attribute("locale");
|
||||
if (loc && locale == loc) {
|
||||
const char* text = trans->GetText();
|
||||
if (text) {
|
||||
g_Phrases[id] = text;
|
||||
}
|
||||
break;
|
||||
const char* text = trans->GetText();
|
||||
if (!loc || !text) continue;
|
||||
if (locale == loc) {
|
||||
g_Phrases[id] = text;
|
||||
if (!allLocales) break;
|
||||
} else if (allLocales) {
|
||||
const auto other = g_Others.find(loc);
|
||||
if (other != g_Others.end()) other->second[id] = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_Loaded = true;
|
||||
LOG("Loaded %zu locale phrases from %s (locale: %s)", g_Phrases.size(), filepath.c_str(), locale.c_str());
|
||||
LOG("Loaded %zu locale phrases from %s (locale: %s, %zu other locale(s))", g_Phrases.size(), filepath.c_str(), locale.c_str(), g_Others.size());
|
||||
}
|
||||
|
||||
const std::string& Locale::GetPhrase(const std::string& phraseId) {
|
||||
@@ -47,6 +69,17 @@ const std::string& Locale::GetPhrase(const std::string& phraseId) {
|
||||
return g_Empty;
|
||||
}
|
||||
|
||||
const std::string& Locale::GetPhrase(const std::string& phraseId, const std::string& locale) {
|
||||
if (const auto other = g_Others.find(locale); other != g_Others.end()) {
|
||||
if (const auto it = other->second.find(phraseId); it != other->second.end()) return it->second;
|
||||
}
|
||||
return GetPhrase(phraseId);
|
||||
}
|
||||
|
||||
const std::vector<std::string>& Locale::GetLocales() {
|
||||
return g_Locales;
|
||||
}
|
||||
|
||||
bool Locale::IsLoaded() {
|
||||
return g_Loaded;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user