From 4c8742ce46e416ca1d0a01d48dfa622d0362d0de Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 18 Mar 2025 11:41:56 +0300 Subject: [PATCH] refactor frontend/locale --- src/engine/Engine.cpp | 6 +- src/frontend/locale.cpp | 112 ++++++++++++++---------- src/frontend/locale.hpp | 41 ++++----- src/io/engine_paths.cpp | 9 ++ src/io/engine_paths.hpp | 2 + src/logic/scripting/lua/libs/libgui.cpp | 2 +- 6 files changed, 95 insertions(+), 77 deletions(-) diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index 74c93ea2..85c45173 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -380,7 +380,7 @@ void Engine::loadContent() { ContentLoader::loadScripts(*content); - langs::setup("res:", langs::current->getId(), contentPacks); + langs::setup("res:", langs::get_current(), resPaths->collectRoots()); if (!isHeadless()) { loadAssets(); onAssetsLoaded(); @@ -404,7 +404,7 @@ void Engine::resetContent() { contentPacks.clear(); content.reset(); - langs::setup("res:", langs::current->getId(), contentPacks); + langs::setup("res:", langs::get_current(), resPaths->collectRoots()); if (!isHeadless()) { loadAssets(); onAssetsLoaded(); @@ -443,7 +443,7 @@ void Engine::setScreen(std::shared_ptr screen) { } void Engine::setLanguage(std::string locale) { - langs::setup("res:", std::move(locale), contentPacks); + langs::setup("res:", std::move(locale), resPaths->collectRoots()); } void Engine::onWorldOpen(std::unique_ptr level, int64_t localPlayer) { diff --git a/src/frontend/locale.cpp b/src/frontend/locale.cpp index 4e1812dd..53d8ce8c 100644 --- a/src/frontend/locale.cpp +++ b/src/frontend/locale.cpp @@ -4,7 +4,6 @@ #include "coders/json.hpp" #include "coders/BasicParser.hpp" -#include "content/ContentPack.hpp" #include "io/io.hpp" #include "util/stringutil.hpp" #include "data/dv.hpp" @@ -14,9 +13,12 @@ static debug::Logger logger("locale"); namespace fs = std::filesystem; using namespace std::literals; +using namespace langs; -std::unique_ptr langs::current; -std::unordered_map langs::locales_info; +namespace { + static std::unique_ptr current; + static std::unordered_map locales_info; +} langs::Lang::Lang(std::string locale) : locale(std::move(locale)) { } @@ -61,11 +63,11 @@ namespace { }; } -void langs::loadLocalesInfo(const io::path& resdir, std::string& fallback) { +static void load_locales_info(const io::path& resdir, std::string& fallback) { auto file = resdir / langs::TEXTS_FOLDER / "langs.json"; auto root = io::read_json(file); - langs::locales_info.clear(); + ::locales_info.clear(); root.at("fallback").get(fallback); if (auto found = root.at("langs")) { @@ -80,16 +82,64 @@ void langs::loadLocalesInfo(const io::path& resdir, std::string& fallback) { continue; } logline << key << " "; - langs::locales_info[key] = LocaleInfo {key, name}; + ::locales_info[key] = LocaleInfo {key, name}; } logline << "added"; } } +static void load( + const io::path& resdir, + const std::string& locale, + const std::vector& roots, + Lang& lang +) { + io::path filename = io::path(TEXTS_FOLDER) / (locale + LANG_FILE_EXT); + io::path core_file = resdir / filename; + + if (io::is_regular_file(core_file)) { + std::string text = io::read_string(core_file); + Reader reader(core_file.string(), text); + reader.read(lang, ""); + } + for (auto root : roots) { + io::path file = root / filename; + if (io::is_regular_file(file)) { + std::string text = io::read_string(file); + Reader reader(file.string(), text); + reader.read(lang, ""); + } + } +} +static void load( + const io::path& resdir, + const std::string& locale, + const std::string& fallback, + const std::vector& roots +) { + auto lang = std::make_unique(locale); + load(resdir, fallback, roots, *lang.get()); + if (locale != fallback) { + load(resdir, locale, roots, *lang.get()); + } + current = std::move(lang); +} + +const std::string& langs::get_current() { + if (current == nullptr) { + throw std::runtime_error("localization is not initialized"); + } + return current->getId(); +} + +const std::unordered_map& langs::get_locales_info() { + return ::locales_info; +} + std::string langs::locale_by_envlocale(const std::string& envlocale, const io::path& resdir){ std::string fallback = FALLBACK_DEFAULT; if (locales_info.size() == 0) { - loadLocalesInfo(resdir, fallback); + load_locales_info(resdir, fallback); } if (locales_info.find(envlocale) != locales_info.end()) { logger.info() << "locale " << envlocale << " is automatically selected"; @@ -107,49 +157,17 @@ std::string langs::locale_by_envlocale(const std::string& envlocale, const io::p } } -void langs::load(const io::path& resdir, - const std::string& locale, - const std::vector& packs, - Lang& lang) { - io::path filename = io::path(TEXTS_FOLDER) / (locale + LANG_FILE_EXT); - io::path core_file = resdir / filename; - - if (io::is_regular_file(core_file)) { - std::string text = io::read_string(core_file); - Reader reader(core_file.string(), text); - reader.read(lang, ""); - } - for (auto pack : packs) { - io::path file = pack.folder / filename; - if (io::is_regular_file(file)) { - std::string text = io::read_string(file); - Reader reader(file.string(), text); - reader.read(lang, ""); - } - } -} - -void langs::load(const io::path& resdir, - const std::string& locale, - const std::string& fallback, - const std::vector& packs) { - auto lang = std::make_unique(locale); - load(resdir, fallback, packs, *lang.get()); - if (locale != fallback) { - load(resdir, locale, packs, *lang.get()); - } - current = std::move(lang); -} - -void langs::setup(const io::path& resdir, - std::string locale, - const std::vector& packs) { +void langs::setup( + const io::path& resdir, + std::string locale, + const std::vector& roots +) { std::string fallback = langs::FALLBACK_DEFAULT; - langs::loadLocalesInfo(resdir, fallback); - if (langs::locales_info.find(locale) == langs::locales_info.end()) { + load_locales_info(resdir, fallback); + if (::locales_info.find(locale) == ::locales_info.end()) { locale = fallback; } - langs::load(resdir, locale, fallback, packs); + load(resdir, locale, fallback, roots); } const std::wstring& langs::get(const std::wstring& key) { diff --git a/src/frontend/locale.hpp b/src/frontend/locale.hpp index 1daaca21..e29f1a7a 100644 --- a/src/frontend/locale.hpp +++ b/src/frontend/locale.hpp @@ -7,8 +7,6 @@ #include "io/fwd.hpp" -struct ContentPack; - namespace langs { const char LANG_FILE_EXT[] = ".txt"; const char TEXTS_FOLDER[] = "texts"; @@ -41,30 +39,21 @@ namespace langs { std::string name; }; - extern std::unique_ptr current; - extern std::unordered_map locales_info; + std::string locale_by_envlocale( + const std::string& envlocale, const io::path& resdir + ); - extern void loadLocalesInfo( + const std::string& get_current(); + const std::unordered_map& get_locales_info(); + + const std::wstring& get(const std::wstring& key); + const std::wstring& get( + const std::wstring& key, const std::wstring& context + ); + + void setup( const io::path& resdir, - std::string& fallback); - - extern std::string locale_by_envlocale(const std::string& envlocale, - const io::path& resdir); - - extern void load(const io::path& resdir, - const std::string& locale, - const std::vector& packs, - Lang& lang); - extern void load(const io::path& resdir, - const std::string& locale, - const std::string& fallback, - const std::vector& packs); - - extern const std::wstring& get(const std::wstring& key); - extern const std::wstring& get(const std::wstring& key, - const std::wstring& context); - - extern void setup(const io::path& resdir, - std::string locale, - const std::vector& packs); + std::string locale, + const std::vector& roots + ); } diff --git a/src/io/engine_paths.cpp b/src/io/engine_paths.cpp index d580e139..07ab2060 100644 --- a/src/io/engine_paths.cpp +++ b/src/io/engine_paths.cpp @@ -345,6 +345,15 @@ dv::value ResPaths::readCombinedObject(const std::string& filename, bool deep) c return object; } +std::vector ResPaths::collectRoots() { + std::vector collected; + collected.reserve(roots.size()); + for (const auto& root : roots) { + collected.emplace_back(root.path); + } + return collected; +} + const io::path& ResPaths::getMainRoot() const { return mainRoot; } diff --git a/src/io/engine_paths.hpp b/src/io/engine_paths.hpp index b7e6ebe2..1d35185b 100644 --- a/src/io/engine_paths.hpp +++ b/src/io/engine_paths.hpp @@ -78,6 +78,8 @@ public: dv::value readCombinedObject(const std::string& file, bool deep=false) const; + std::vector collectRoots(); + const io::path& getMainRoot() const; private: diff --git a/src/logic/scripting/lua/libs/libgui.cpp b/src/logic/scripting/lua/libs/libgui.cpp index 131adb98..00c5fd4b 100644 --- a/src/logic/scripting/lua/libs/libgui.cpp +++ b/src/logic/scripting/lua/libs/libgui.cpp @@ -771,7 +771,7 @@ static int l_gui_reindex(lua::State* L) { /// @brief gui.get_locales_info() -> table of tables static int l_gui_get_locales_info(lua::State* L) { - auto& locales = langs::locales_info; + auto& locales = langs::get_locales_info(); lua::createtable(L, 0, locales.size()); for (auto& entry : locales) { lua::createtable(L, 0, 1);