diff --git a/src/control/Control.cpp b/src/control/Control.cpp index 90e2e922..2f66040a 100644 --- a/src/control/Control.cpp +++ b/src/control/Control.cpp @@ -2460,7 +2460,13 @@ void Control::closeDocument() { this->undoRedoChanged(); } -void Control::applyPreferredLanguage() { setenv("LANGUAGE", this->settings->getPreferredLocale().c_str(), 1); } +void Control::applyPreferredLanguage() { +#ifdef _WIN32 + _putenv_s("LANGUAGE", this->settings->getPreferredLocale().c_str()); +#else + setenv("LANGUAGE", this->settings->getPreferredLocale().c_str(), 1); +#endif +} auto Control::askToReplace(fs::path const& filepath) const -> bool { if (fs::exists(filepath)) { diff --git a/src/gui/dialog/LanguageConfigGui.cpp b/src/gui/dialog/LanguageConfigGui.cpp index e87b7a3e..95ae5708 100644 --- a/src/gui/dialog/LanguageConfigGui.cpp +++ b/src/gui/dialog/LanguageConfigGui.cpp @@ -1,27 +1,89 @@ #include "LanguageConfigGui.h" -#include "i18n.h" + +#include + #include "control/settings/Settings.h" -LanguageConfigGui::LanguageConfigGui(GladeSearchpath* gladeSearchPath, GtkWidget* w, Settings* settings) : +#include "StringUtils.h" +#include "XojMsgBox.h" +#include "config-paths.h" +#include "config.h" +#include "filesystem.h" +#include "i18n.h" + +#ifdef _WIN32 +#undef PACKAGE_LOCALE_DIR +#define PACKAGE_LOCALE_DIR "../share/locale/" +#endif + +#ifdef __APPLE__ +#include "Stacktrace.h" +#undef PACKAGE_LOCALE_DIR +const char* PACKAGE_LOCALE_DIR = (Stacktrace::getExePath() / "../Resources/share/locale").c_str(); +#endif + +LanguageConfigGui::LanguageConfigGui(GladeSearchpath* gladeSearchPath, GtkWidget* w, Settings* settings): GladeGui(gladeSearchPath, "settingsLanguageConfig.glade", "offscreenwindow"), settings(settings) { - GtkWidget* dropdown = get("languageSettingsDropdown"); + auto dropdown = get("languageSettingsDropdown"); gtk_container_remove(GTK_CONTAINER(getWindow()), dropdown); gtk_container_add(GTK_CONTAINER(w), dropdown); gtk_widget_show_all(dropdown); -}; + + // Fetch available locales + try { + fs::path baseLocaleDir(PACKAGE_LOCALE_DIR); + for (auto const& d: fs::directory_iterator(baseLocaleDir)) { + if (fs::exists(d.path() / "LC_MESSAGES" / (std::string(GETTEXT_PACKAGE) + ".mo"))) { + availableLocales.push_back(d.path().filename().u8string()); + } + } + } catch (fs::filesystem_error const& e) { + g_warning("%s", e.what()); + } + std::sort(availableLocales.begin(), availableLocales.end()); + + // No pot file for English + if (auto enPos = std::lower_bound(availableLocales.begin(), availableLocales.end(), "en"); + enPos != availableLocales.end() && !StringUtils::startsWith(*enPos, "en")) { + availableLocales.insert(enPos, "en"); + } + + // Default + availableLocales.insert(availableLocales.begin(), _("System Default")); + + auto gtkAvailableLocales = gtk_list_store_new(1, G_TYPE_STRING); + for (auto const& i: availableLocales) { + GtkTreeIter iter; + gtk_list_store_append(gtkAvailableLocales, &iter); + gtk_list_store_set(gtkAvailableLocales, &iter, 0, i.c_str(), -1); + } + gtk_combo_box_set_model(GTK_COMBO_BOX(dropdown), GTK_TREE_MODEL(gtkAvailableLocales)); + + + // Set the current locale if previously selected + auto prefPos = availableLocales.begin(); + if (auto preferred = settings->getPreferredLocale(); !preferred.empty()) { + prefPos = std::lower_bound(availableLocales.begin(), availableLocales.end(), preferred); + if (*prefPos != preferred) { + XojMsgBox::showErrorToUser(nullptr, _("Previously selected language not available anymore!")); + + // Use system default + prefPos = availableLocales.begin(); + } + } + gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), prefPos - availableLocales.begin()); +} + void LanguageConfigGui::saveSettings() { gint pos = gtk_combo_box_get_active(GTK_COMBO_BOX(get("languageSettingsDropdown"))); + auto pref = (pos == 0) ? "" : availableLocales[pos]; - switch (pos) { - case 0: - settings->setPreferredLocale("en_US.UTF-8"); - break; - case 1: - settings->setPreferredLocale("de_DE.UTF-8"); - break; - default: - throw "No language selected"; - } + settings->setPreferredLocale(pref); settings->customSettingsChanged(); +#ifdef _WIN32 + _putenv_s("LANGUAGE", this->settings->getPreferredLocale().c_str()); +#else + setenv("LANGUAGE", this->settings->getPreferredLocale().c_str(), 1); +#endif } diff --git a/src/gui/dialog/LanguageConfigGui.h b/src/gui/dialog/LanguageConfigGui.h index 0c72c30c..b01fd016 100644 --- a/src/gui/dialog/LanguageConfigGui.h +++ b/src/gui/dialog/LanguageConfigGui.h @@ -11,8 +11,11 @@ #pragma once -#include #include +#include + +#include + #include "gui/GladeGui.h" class Settings; @@ -23,14 +26,15 @@ public: LanguageConfigGui(GladeSearchpath* gladeSearchPath, GtkWidget* w, Settings* settings); public: - void loadSettings() {}; + void loadSettings(){}; void saveSettings(); // Not implemented! This is not a dialog! - void show(GtkWindow* parent) override {}; + void show(GtkWindow* parent) override{}; private: + std::vector availableLocales; + -private: Settings* settings; }; diff --git a/src/gui/dialog/SettingsDialog.h b/src/gui/dialog/SettingsDialog.h index 3f691a2d..4622b596 100644 --- a/src/gui/dialog/SettingsDialog.h +++ b/src/gui/dialog/SettingsDialog.h @@ -17,11 +17,10 @@ #include "util/audio/DeviceInfo.h" #include "DeviceClassConfigGui.h" -#include "LatexSettingsPanel.h" #include "LanguageConfigGui.h" +#include "LatexSettingsPanel.h" class ButtonConfigGui; -class LanguageConfigGui; class SettingsDialog: public GladeGui { public: