diff --git a/lib/libimhex/include/hex/api/localization_manager.hpp b/lib/libimhex/include/hex/api/localization_manager.hpp index cfdd311b5..12284f94e 100644 --- a/lib/libimhex/include/hex/api/localization_manager.hpp +++ b/lib/libimhex/include/hex/api/localization_manager.hpp @@ -27,6 +27,7 @@ namespace hex { } void loadLanguage(const std::string &language); + std::string getLocalizedString(const std::string &unlocalizedString, const std::string &language = ""); [[nodiscard]] const std::map &getSupportedLanguages(); [[nodiscard]] const std::string &getFallbackLanguage(); diff --git a/lib/libimhex/source/api/localization_manager.cpp b/lib/libimhex/source/api/localization_manager.cpp index 421803adb..fd8f98b45 100644 --- a/lib/libimhex/source/api/localization_manager.cpp +++ b/lib/libimhex/source/api/localization_manager.cpp @@ -60,6 +60,29 @@ namespace hex { s_selectedLanguage = language; } + std::string getLocalizedString(const std::string& unlocalizedString, const std::string& language) { + if (language.empty()) + return getLocalizedString(unlocalizedString, getSelectedLanguage()); + + auto &languageDefinitions = ContentRegistry::Language::impl::getLanguageDefinitions(); + if (!languageDefinitions.contains(language)) + return ""; + + std::string localizedString; + for (const auto &definition : languageDefinitions[language]) { + if (definition.getEntries().contains(unlocalizedString)) { + localizedString = definition.getEntries().at(unlocalizedString); + break; + } + } + + if (localizedString.empty()) + return getLocalizedString(unlocalizedString, getFallbackLanguage()); + + return localizedString; + } + + const std::map &getSupportedLanguages() { return ContentRegistry::Language::impl::getLanguages(); } diff --git a/plugins/builtin/romfs/assets/common/globe.png b/plugins/builtin/romfs/assets/common/globe.png new file mode 100644 index 000000000..48249bcff Binary files /dev/null and b/plugins/builtin/romfs/assets/common/globe.png differ diff --git a/plugins/builtin/source/content/out_of_box_experience.cpp b/plugins/builtin/source/content/out_of_box_experience.cpp index e19aba7e0..5e2a1f43d 100644 --- a/plugins/builtin/source/content/out_of_box_experience.cpp +++ b/plugins/builtin/source/content/out_of_box_experience.cpp @@ -23,7 +23,7 @@ namespace hex::plugin::builtin { namespace { ImGuiExt::Texture s_imhexBanner; - ImGuiExt::Texture s_compassTexture; + ImGuiExt::Texture s_compassTexture, s_globeTexture; std::list> s_screenshots; nlohmann::json s_screenshotDescriptions; @@ -188,8 +188,71 @@ namespace hex::plugin::builtin { break; } - // Server contact page + // Language selection page case 1: { + static const auto &languages = LocalizationManager::getSupportedLanguages(); + static auto currLanguage = languages.begin(); + static float prevTime = 0; + + ImGui::NewLine(); + + ImGui::NewLine(); + ImGui::NewLine(); + ImGui::NewLine(); + + auto currTime = ImGui::GetTime(); + if ((currTime - prevTime) > 3) { + prevTime = currTime; + ++currLanguage; + } + + if (currLanguage == languages.end()) + currLanguage = languages.begin(); + + // Draw globe image + const auto imageSize = s_compassTexture.getSize() / (1.5F * (1.0F / ImHexApi::System::getGlobalScale())); + ImGui::SetCursorPos((ImGui::GetWindowSize() / 2 - imageSize / 2) - ImVec2(0, 50_scaled)); + ImGui::Image(s_globeTexture, imageSize); + + ImGui::NewLine(); + ImGui::NewLine(); + + + // Draw information text + ImGui::SetCursorPosX(0); + + const auto availableWidth = ImGui::GetContentRegionAvail().x; + if (ImGui::BeginChild("##language_text", ImVec2(availableWidth, 30_scaled))) { + ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_Text, std::cos((currTime / 3) * 2 * std::numbers::pi) * 3 + 2)); + ImGuiExt::TextFormattedCentered("{}", LocalizationManager::getLocalizedString("hex.builtin.setting.interface.language", currLanguage->first)); + ImGui::PopStyleColor(); + } + ImGui::EndChild(); + + ImGui::NewLine(); + + // Draw language selection list + ImGui::SetCursorPosX(availableWidth / 3); + if (ImGui::BeginListBox("##language", ImVec2(availableWidth / 3, 0))) { + for (const auto &[langId, language] : LocalizationManager::getSupportedLanguages()) { + if (ImGui::Selectable(language.c_str(), langId == LocalizationManager::getSelectedLanguage())) { + LocalizationManager::loadLanguage(langId); + } + } + ImGui::EndListBox(); + } + + // Continue button + const auto buttonSize = scaled({ 100, 50 }); + ImGui::SetCursorPos(ImHexApi::System::getMainWindowSize() - buttonSize - scaled({ 10, 10 })); + if (ImGuiExt::DimmedButton(hex::format("{} {}", "hex.ui.common.continue"_lang, ICON_VS_ARROW_RIGHT).c_str(), buttonSize)) + page += 1; + + break; + } + + // Server contact page + case 2: { static ImVec2 subWindowSize = { 0, 0 }; const auto windowSize = ImHexApi::System::getMainWindowSize(); @@ -287,7 +350,7 @@ namespace hex::plugin::builtin { } // Tutorial page - case 2: { + case 3: { ImGui::NewLine(); ImGui::NewLine(); @@ -365,8 +428,9 @@ namespace hex::plugin::builtin { ImHexApi::System::setWindowResizable(false); const auto imageTheme = ThemeManager::getImageTheme(); - s_imhexBanner = ImGuiExt::Texture(romfs::get(hex::format("assets/{}/banner.png", imageTheme)).span()); + s_imhexBanner = ImGuiExt::Texture(romfs::get(hex::format("assets/{}/banner.png", imageTheme)).span()); s_compassTexture = ImGuiExt::Texture(romfs::get("assets/common/compass.png").span()); + s_globeTexture = ImGuiExt::Texture(romfs::get("assets/common/globe.png").span()); s_screenshotDescriptions = nlohmann::json::parse(romfs::get("assets/screenshot_descriptions.json").string()); for (const auto &path : romfs::list("assets/screenshots")) {