From cb64f49ba1b6d08da6b0cfbd659d1352dd92316a Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 25 Jul 2022 08:54:05 +0400 Subject: [PATCH] Allow to configure locales via settings menu --- apps/openmw/mwgui/settingswindow.cpp | 74 +++++++++++++++++++ apps/openmw/mwgui/settingswindow.hpp | 7 ++ apps/openmw/mwlua/luamanagerimp.cpp | 4 +- .../reference/modding/settings/general.rst | 2 +- files/data/l10n/SettingsMenu/en.yaml | 6 ++ files/data/l10n/SettingsMenu/ru.yaml | 6 ++ .../data/mygui/openmw_settings_window.layout | 22 ++++++ 7 files changed, 117 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index d38763663a..1a63f98a8f 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include #include #include @@ -18,12 +20,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -254,6 +258,8 @@ namespace MWGui getWidget(mWaterTextureSize, "WaterTextureSize"); getWidget(mWaterReflectionDetail, "WaterReflectionDetail"); getWidget(mWaterRainRippleDetail, "WaterRainRippleDetail"); + getWidget(mPrimaryLanguage, "PrimaryLanguage"); + getWidget(mSecondaryLanguage, "SecondaryLanguage"); getWidget(mLightingMethodButton, "LightingMethodButton"); getWidget(mLightsResetButton, "LightsResetButton"); getWidget(mMaxLights, "MaxLights"); @@ -297,6 +303,9 @@ namespace MWGui mKeyboardSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onKeyboardSwitchClicked); mControllerSwitch->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onControllerSwitchClicked); + mPrimaryLanguage->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onPrimaryLanguageChanged); + mSecondaryLanguage->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSecondaryLanguageChanged); + computeMinimumWindowSize(); center(); @@ -353,6 +362,55 @@ namespace MWGui mScriptFilter->eventEditTextChange += MyGUI::newDelegate(this, &SettingsWindow::onScriptFilterChange); mScriptList->eventListMouseItemActivate += MyGUI::newDelegate(this, &SettingsWindow::onScriptListSelection); + + std::vector availableLanguages; + const VFS::Manager* vfs = MWBase::Environment::get().getResourceSystem()->getVFS(); + for (const auto& path : vfs->getRecursiveDirectoryIterator("l10n/")) + { + if (Misc::getFileExtension(path) == "yaml") + { + std::string localeName(Misc::stemFile(path)); + if (std::find(availableLanguages.begin(), availableLanguages.end(), localeName) == availableLanguages.end()) + availableLanguages.push_back(localeName); + } + } + + std::sort (availableLanguages.begin(), availableLanguages.end()); + + std::vector currentLocales = Settings::Manager::getStringArray("preferred locales", "General"); + if (currentLocales.empty()) + currentLocales.push_back("en"); + + icu::Locale primaryLocale(currentLocales[0].c_str()); + + mPrimaryLanguage->removeAllItems(); + mSecondaryLanguage->removeAllItems(); + + size_t i = 0, primaryLocaleIndex = MyGUI::ITEM_NONE, secondaryLocaleIndex = MyGUI::ITEM_NONE; + for (const auto& language : availableLanguages) + { + icu::Locale locale(language.c_str()); + + icu::UnicodeString str(language.c_str()); + locale.getDisplayName(primaryLocale, str); + std::string localeString; + str.toUTF8String(localeString); + mPrimaryLanguage->addItem(localeString); + mSecondaryLanguage->addItem(localeString); + + if (language == currentLocales[0]) + primaryLocaleIndex = i; + if (currentLocales.size() > 1 && language == currentLocales[1]) + secondaryLocaleIndex = i; + + i++; + } + + mPrimaryLanguage->setUserData(availableLanguages); + mSecondaryLanguage->setUserData(availableLanguages); + + mPrimaryLanguage->setIndexSelected(primaryLocaleIndex); + mSecondaryLanguage->setIndexSelected(secondaryLocaleIndex); } void SettingsWindow::onTabChanged(MyGUI::TabControl* /*_sender*/, size_t /*index*/) @@ -454,6 +512,22 @@ namespace MWGui apply(); } + void SettingsWindow::onLanguageChanged(size_t langPriority, MyGUI::ComboBox* _sender, size_t pos) + { + if (pos == MyGUI::ITEM_NONE) + return; + + MWBase::Environment::get().getWindowManager()->interactiveMessageBox("#{SettingsMenu:ChangeRequiresRestart}", {"#{sOK}"}, true); + const auto languageNames = _sender->getUserData>(); + + std::vector currentLocales = Settings::Manager::getStringArray("preferred locales", "General"); + if (currentLocales.size() <= langPriority) + currentLocales.resize(langPriority + 1, "en"); + currentLocales[langPriority] = languageNames->at(pos); + + Settings::Manager::setStringArray("preferred locales", "General", currentLocales); + } + void SettingsWindow::onWindowModeChanged(MyGUI::ComboBox* _sender, size_t pos) { if (pos == MyGUI::ITEM_NONE) diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 6bc6b7c610..451ba7a7a5 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -40,6 +40,9 @@ namespace MWGui MyGUI::ComboBox* mLightingMethodButton; MyGUI::Button* mLightsResetButton; + MyGUI::ComboBox* mPrimaryLanguage; + MyGUI::ComboBox* mSecondaryLanguage; + // controls MyGUI::ScrollView* mControlsBox; MyGUI::Button* mResetControlsButton; @@ -72,6 +75,10 @@ namespace MWGui void onLightsResetButtonClicked(MyGUI::Widget* _sender); void onMaxLightsChanged(MyGUI::ComboBox* _sender, size_t pos); + void onPrimaryLanguageChanged(MyGUI::ComboBox* _sender, size_t pos) { onLanguageChanged(0, _sender, pos); } + void onSecondaryLanguageChanged(MyGUI::ComboBox* _sender, size_t pos) { onLanguageChanged(1, _sender, pos); } + void onLanguageChanged(size_t langPriority, MyGUI::ComboBox* _sender, size_t pos); + void onWindowModeChanged(MyGUI::ComboBox* _sender, size_t pos); void onRebindAction(MyGUI::Widget* _sender); diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index 1678743257..fba78e47de 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -58,9 +58,7 @@ namespace MWLua void LuaManager::initL10n() { mL10n.init(); - std::vector preferredLocales; - Misc::StringUtils::split(Settings::Manager::getString("preferred locales", "General"), preferredLocales, ", "); - mL10n.setPreferredLocales(preferredLocales); + mL10n.setPreferredLocales(Settings::Manager::getStringArray("preferred locales", "General")); } void LuaManager::init() diff --git a/docs/source/reference/modding/settings/general.rst b/docs/source/reference/modding/settings/general.rst index 39045e7733..a7a64e04b8 100644 --- a/docs/source/reference/modding/settings/general.rst +++ b/docs/source/reference/modding/settings/general.rst @@ -85,7 +85,7 @@ will match "en"), so is recommended that you include the country codes where pos since if the country code isn't specified the generic language-code only locale might refer to any of the country-specific variants. -This setting can only be configured by editing the settings configuration file. +Two highest priority locales may be assigned via the Localization tab of the in-game options. log buffer size --------------- diff --git a/files/data/l10n/SettingsMenu/en.yaml b/files/data/l10n/SettingsMenu/en.yaml index da3eeaceb7..d57377ceef 100644 --- a/files/data/l10n/SettingsMenu/en.yaml +++ b/files/data/l10n/SettingsMenu/en.yaml @@ -8,6 +8,8 @@ Controller: "Controller" FieldOfView: "Field of View" FrameRateHint: "Hint: press F3 to show\nthe current frame rate." InvertXAxis: "Invert X Axis" +Language: "Language" +LanguageNote: "Note: these settings do not affect strings from ESM files." LightingMethod: "Lighting Method" LightingMethodLegacy: "Legacy" LightingMethodShaders: "Shaders" @@ -27,6 +29,8 @@ MaxLightsTooltip: "Default: 8\nMaximum number of lights per object.\n\nA low num MouseAndKeyboard: "Mouse/Keyboard" PostProcessing: "Post Processing" PostProcessingTooltip: "Tweaked via Post Processor HUD, see input bindings." +PrimaryLanguage: "Primary Language" +PrimaryLanguageTooltip: "Localization files for this language have the highest priority." RainRippleDetail: "Rain ripple detail" RainRippleDetailDense: "Dense" RainRippleDetailSimple: "Simple" @@ -41,6 +45,8 @@ ReflectionShaderDetailWorld: "World" Refraction: "Refraction" Screenshot: "Screenshot" Scripts: "Scripts" +SecondaryLanguage: "Secondary Language" +SecondaryLanguageTooltip: "Localization files for this language may be used if the primary language files lack the necessary lines." TextureFiltering: "Texture Filtering" TextureFilteringBilinear: "Bilinear" TextureFilteringDisabled: "None" diff --git a/files/data/l10n/SettingsMenu/ru.yaml b/files/data/l10n/SettingsMenu/ru.yaml index 1662153f7c..5108702adf 100644 --- a/files/data/l10n/SettingsMenu/ru.yaml +++ b/files/data/l10n/SettingsMenu/ru.yaml @@ -8,6 +8,8 @@ Controller: "Геймпад" FieldOfView: "Поле зрения" FrameRateHint: "Подсказка: нажмите F3, чтобы показать\nтекущую частоту смены кадров." InvertXAxis: "Инвертировать ось X" +Language: "Язык" +LanguageNote: "Примечание: эти настройки не затрагивают строки из ESM-файлов." LightingMethod: "Способ освещения" LightingMethodLegacy: "Устаревший" LightingMethodShaders: "Шейдеры" @@ -27,6 +29,8 @@ MaxLightsTooltip: "Значение по умолчанию: 8\nМаксимал MouseAndKeyboard: "Мышь/Клавиатура" PostProcessing: "Постобработка" PostProcessingTooltip: "Настраивается через меню настроек постобработки, см. привязки клавиш." +PrimaryLanguage: "Основной язык" +PrimaryLanguageTooltip: "Язык, строки на котором будут использоваться в первую очередь." RainRippleDetail: "Капли дождя на воде" RainRippleDetailDense: "Плотные" RainRippleDetailSimple: "Упрощенные" @@ -41,6 +45,8 @@ ReflectionShaderDetailWorld: "Мир" Refraction: "Рефракция" Screenshot: "Снимок экрана" Scripts: "Скрипты" +SecondaryLanguage: "Дополнительный язык" +SecondaryLanguageTooltip: "Язык, строки на котором будут использоваться, если соответствующие строки на основном языке не найдены." TextureFiltering: "Фильтрация текстур" TextureFilteringBilinear: "Билинейная" TextureFilteringDisabled: "Отключена" diff --git a/files/data/mygui/openmw_settings_window.layout b/files/data/mygui/openmw_settings_window.layout index dfb291ea60..0d6d68d6c7 100644 --- a/files/data/mygui/openmw_settings_window.layout +++ b/files/data/mygui/openmw_settings_window.layout @@ -670,6 +670,28 @@ + + + + + + + + + + + + + + + + + + + + + +