diff --git a/resources/localization/PrusaSlicer.pot b/resources/localization/PrusaSlicer.pot index 87a7fe3c0..b0c5a3051 100644 --- a/resources/localization/PrusaSlicer.pot +++ b/resources/localization/PrusaSlicer.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-29 11:15+0200\n" +"POT-Creation-Date: 2019-08-29 14:09+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -138,6 +138,7 @@ msgstr "" #: src/slic3r/GUI/BedShapeDialog.cpp:91 src/slic3r/GUI/ConfigWizard.cpp:123 #: src/slic3r/GUI/ConfigWizard.cpp:576 src/slic3r/GUI/ConfigWizard.cpp:590 +#: src/slic3r/GUI/GUI_ObjectLayers.cpp:135 #: src/slic3r/GUI/GUI_ObjectManipulation.cpp:390 #: src/slic3r/GUI/WipeTowerDialog.cpp:84 src/slic3r/GUI/wxExtensions.cpp:509 #: src/libslic3r/PrintConfig.cpp:70 src/libslic3r/PrintConfig.cpp:77 @@ -398,7 +399,7 @@ msgstr "" msgid "Welcome" msgstr "" -#: src/slic3r/GUI/ConfigWizard.cpp:309 src/slic3r/GUI/GUI_App.cpp:773 +#: src/slic3r/GUI/ConfigWizard.cpp:309 src/slic3r/GUI/GUI_App.cpp:783 #, possible-c-format msgid "Run %s" msgstr "" @@ -645,6 +646,7 @@ msgid "%s doesn't support percentage" msgstr "" #: src/slic3r/GUI/Field.cpp:174 src/slic3r/GUI/Field.cpp:197 +#: src/slic3r/GUI/GUI_ObjectLayers.cpp:337 msgid "Invalid numeric input." msgstr "" @@ -1203,7 +1205,7 @@ msgstr "" msgid "Notice" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:132 +#: src/slic3r/GUI/GUI_App.cpp:133 #, possible-c-format msgid "" "%s has encountered an error. It was likely caused by running out of memory. " @@ -1213,96 +1215,96 @@ msgid "" "The application will now terminate." msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:135 +#: src/slic3r/GUI/GUI_App.cpp:136 msgid "Fatal error" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:301 +#: src/slic3r/GUI/GUI_App.cpp:299 #, possible-c-format msgid "" "PrusaSlicer requires OpenGL 2.0 capable graphics driver to run correctly, \n" "while OpenGL version %s, render %s, vendor %s was detected." msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:304 +#: src/slic3r/GUI/GUI_App.cpp:302 msgid "You may need to update your graphics card driver." msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:307 +#: src/slic3r/GUI/GUI_App.cpp:305 msgid "" "As a workaround, you may run PrusaSlicer with a software rendered 3D " "graphics by running prusa-slicer.exe with the --sw_renderer parameter." msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:309 +#: src/slic3r/GUI/GUI_App.cpp:307 msgid "Unsupported OpenGL version" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:460 +#: src/slic3r/GUI/GUI_App.cpp:458 msgid "Changing of an application language" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:468 src/slic3r/GUI/GUI_App.cpp:477 +#: src/slic3r/GUI/GUI_App.cpp:466 src/slic3r/GUI/GUI_App.cpp:475 msgid "Recreating" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:481 +#: src/slic3r/GUI/GUI_App.cpp:479 msgid "Loading of current presets" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:489 +#: src/slic3r/GUI/GUI_App.cpp:487 msgid "Loading of a mode view" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:569 +#: src/slic3r/GUI/GUI_App.cpp:567 msgid "Choose one file (3MF/AMF):" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:581 +#: src/slic3r/GUI/GUI_App.cpp:579 msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:617 +#: src/slic3r/GUI/GUI_App.cpp:641 msgid "Select the language" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:617 +#: src/slic3r/GUI/GUI_App.cpp:641 msgid "Language" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:776 +#: src/slic3r/GUI/GUI_App.cpp:786 msgid "&Configuration Snapshots" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:776 +#: src/slic3r/GUI/GUI_App.cpp:786 msgid "Inspect / activate configuration snapshots" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:777 +#: src/slic3r/GUI/GUI_App.cpp:787 msgid "Take Configuration &Snapshot" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:777 +#: src/slic3r/GUI/GUI_App.cpp:787 msgid "Capture a configuration snapshot" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:780 +#: src/slic3r/GUI/GUI_App.cpp:790 msgid "&Preferences" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:786 +#: src/slic3r/GUI/GUI_App.cpp:796 msgid "Application preferences" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:789 src/slic3r/GUI/wxExtensions.cpp:3041 +#: src/slic3r/GUI/GUI_App.cpp:799 src/slic3r/GUI/wxExtensions.cpp:3041 msgid "Simple" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:789 +#: src/slic3r/GUI/GUI_App.cpp:799 msgid "Simple View Mode" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:790 src/slic3r/GUI/GUI_ObjectList.cpp:97 +#: src/slic3r/GUI/GUI_App.cpp:800 src/slic3r/GUI/GUI_ObjectList.cpp:97 #: src/slic3r/GUI/GUI_ObjectList.cpp:620 src/slic3r/GUI/Tab.cpp:1058 #: src/slic3r/GUI/Tab.cpp:1073 src/slic3r/GUI/Tab.cpp:1171 #: src/slic3r/GUI/Tab.cpp:1174 src/slic3r/GUI/Tab.cpp:1682 @@ -1313,77 +1315,98 @@ msgstr "" msgid "Advanced" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:790 +#: src/slic3r/GUI/GUI_App.cpp:800 msgid "Advanced View Mode" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:791 src/slic3r/GUI/wxExtensions.cpp:3043 +#: src/slic3r/GUI/GUI_App.cpp:801 src/slic3r/GUI/wxExtensions.cpp:3043 msgid "Expert" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:791 +#: src/slic3r/GUI/GUI_App.cpp:801 msgid "Expert View Mode" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:796 +#: src/slic3r/GUI/GUI_App.cpp:806 msgid "Mode" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:796 +#: src/slic3r/GUI/GUI_App.cpp:806 #, possible-c-format msgid "%s View Mode" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:798 +#: src/slic3r/GUI/GUI_App.cpp:808 msgid "Change Application &Language" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:800 +#: src/slic3r/GUI/GUI_App.cpp:810 msgid "Flash printer &firmware" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:800 +#: src/slic3r/GUI/GUI_App.cpp:810 msgid "Upload a firmware image into an Arduino based printer" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:812 +#: src/slic3r/GUI/GUI_App.cpp:822 msgid "Taking configuration snapshot" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:812 +#: src/slic3r/GUI/GUI_App.cpp:822 msgid "Snapshot name" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:855 +#: src/slic3r/GUI/GUI_App.cpp:865 msgid "" "Switching the language will trigger application restart.\n" "You will lose content of the plater." msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:857 +#: src/slic3r/GUI/GUI_App.cpp:867 msgid "Do you want to proceed?" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:858 +#: src/slic3r/GUI/GUI_App.cpp:868 msgid "Language selection" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:881 +#: src/slic3r/GUI/GUI_App.cpp:891 msgid "&Configuration" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:903 +#: src/slic3r/GUI/GUI_App.cpp:913 msgid "The presets on the following tabs were modified" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:903 src/slic3r/GUI/Tab.cpp:3130 +#: src/slic3r/GUI/GUI_App.cpp:913 src/slic3r/GUI/Tab.cpp:3130 msgid "Discard changes and continue anyway?" msgstr "" -#: src/slic3r/GUI/GUI_App.cpp:906 +#: src/slic3r/GUI/GUI_App.cpp:916 msgid "Unsaved Presets" msgstr "" +#: src/slic3r/GUI/GUI_ObjectLayers.cpp:27 +msgid "Start at height" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectLayers.cpp:27 +msgid "Stop at height" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectLayers.cpp:27 src/slic3r/GUI/Tab.cpp:1030 +#: src/libslic3r/PrintConfig.cpp:66 +msgid "Layer height" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectLayers.cpp:153 +msgid "Remove layer range" +msgstr "" + +#: src/slic3r/GUI/GUI_ObjectLayers.cpp:162 +msgid "Add layer range" +msgstr "" + #: src/slic3r/GUI/GUI_ObjectList.cpp:34 src/slic3r/GUI/GUI_ObjectList.cpp:88 #: src/slic3r/GUI/GUI_ObjectList.cpp:611 src/libslic3r/PrintConfig.cpp:67 #: src/libslic3r/PrintConfig.cpp:160 src/libslic3r/PrintConfig.cpp:392 @@ -4050,10 +4073,6 @@ msgstr "" msgid "Layers and perimeters" msgstr "" -#: src/slic3r/GUI/Tab.cpp:1030 src/libslic3r/PrintConfig.cpp:66 -msgid "Layer height" -msgstr "" - #: src/slic3r/GUI/Tab.cpp:1034 msgid "Vertical shells" msgstr "" diff --git a/resources/localization/list.txt b/resources/localization/list.txt index a553e775a..440f0ee4c 100644 --- a/resources/localization/list.txt +++ b/resources/localization/list.txt @@ -18,6 +18,7 @@ src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp src/slic3r/GUI/Gizmos/GLGizmosManager.cpp src/slic3r/GUI/GUI.cpp src/slic3r/GUI/GUI_App.cpp +src/slic3r/GUI/GUI_ObjectLayers.cpp src/slic3r/GUI/GUI_ObjectList.cpp src/slic3r/GUI/GUI_ObjectManipulation.cpp src/slic3r/GUI/GUI_ObjectSettings.cpp diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index ccda72f5c..0f1040d42 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -229,11 +230,8 @@ bool GUI_App::on_init_inner() init_label_colours(); init_fonts(); - wxString language = wxEmptyString; - if (app_config->has("translation_language")) - language = app_config->get("translation_language"); // If load_language() fails, the application closes. - load_language(language); + load_language(wxString(), true); // Suppress the '- default -' presets. preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1"); @@ -600,132 +598,156 @@ bool GUI_App::switch_language() // select language from the list of installed languages bool GUI_App::select_language() { - const std::vector langs = get_installed_languages(); + wxArrayString translations = wxTranslations::Get()->GetAvailableTranslations(SLIC3R_APP_KEY); + std::vector language_infos; + language_infos.emplace_back(wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH)); + for (size_t i = 0; i < translations.GetCount(); ++ i) { + const wxLanguageInfo *langinfo = wxLocale::FindLanguageInfo(translations[i]); + if (langinfo != nullptr) + language_infos.emplace_back(langinfo); + } + sort_remove_duplicates(language_infos); + std::sort(language_infos.begin(), language_infos.end(), [](const wxLanguageInfo* l, const wxLanguageInfo* r) { return l->Description < r->Description; }); + wxArrayString names; - names.Alloc(langs.size()); + names.Alloc(language_infos.size()); // Some valid language should be selected since the application start up. - assert(m_wxLocale != nullptr); - const auto current_language = m_wxLocale->GetLanguage(); - int init_selection = 0; - for (size_t i = 0; i < langs.size(); ++ i) { - if (langs[i]->Language == current_language) + const wxLanguage current_language = wxLanguage(m_wxLocale->GetLanguage()); + int init_selection = -1; + int init_selection_alt = -1; + int init_selection_default = -1; + for (size_t i = 0; i < language_infos.size(); ++ i) { + if (wxLanguage(language_infos[i]->Language) == current_language) + // The dictionary matches the active language and country. init_selection = i; - names.Add(langs[i]->Description); + else if ((language_infos[i]->CanonicalName.BeforeFirst('_') == m_wxLocale->GetCanonicalName().BeforeFirst('_')) || + // if the active language is Slovak, mark the Czech language as active. + (language_infos[i]->CanonicalName.BeforeFirst('_') == "cs" && m_wxLocale->GetCanonicalName().BeforeFirst('_') == "sk")) + // The dictionary matches the active language, it does not necessarily match the country. + init_selection_alt = i; + if (language_infos[i]->CanonicalName.BeforeFirst('_') == "en") + // This will be the default selection if the active language does not match any dictionary. + init_selection_default = i; + names.Add(language_infos[i]->Description); } + if (init_selection == -1) + // This is the dictionary matching the active language. + init_selection = init_selection_alt; + if (init_selection != -1) + // This is the language to highlight in the choice dialog initially. + init_selection_default = init_selection; - const long index = wxGetSingleChoiceIndex(_(L("Select the language")), _(L("Language")), names, init_selection); + const long index = wxGetSingleChoiceIndex(_(L("Select the language")), _(L("Language")), names, init_selection_default); // Try to load a new language. - if (index != -1 && langs[index]->Language != current_language && this->load_language(langs[index]->CanonicalName)) { - // Save language at application config. - app_config->set("translation_language", m_wxLocale->GetCanonicalName().ToUTF8().data()); - app_config->save(); - return true; + if (index != -1 && (init_selection == -1 || init_selection != index)) { + const wxLanguageInfo *new_language_info = language_infos[index]; + if (new_language_info == m_language_info_best || new_language_info == m_language_info_system) { + // The newly selected profile matches user's default profile exactly. That's great. + } else if (m_language_info_best != nullptr && new_language_info->CanonicalName.BeforeFirst('_') == m_language_info_best->CanonicalName.BeforeFirst('_')) + new_language_info = m_language_info_best; + else if (m_language_info_system != nullptr && new_language_info->CanonicalName.BeforeFirst('_') == m_language_info_system->CanonicalName.BeforeFirst('_')) + new_language_info = m_language_info_system; + if (this->load_language(new_language_info->CanonicalName, false)) { + // Save language at application config. + app_config->set("translation_language", m_wxLocale->GetCanonicalName().ToUTF8().data()); + app_config->save(); + return true; + } } return false; } -// Get the language code before underscore, if there is underscore. -static wxString language_code_short(const wxString &language_code) -{ - size_t idx_underscore = language_code.find('_'); - return (idx_underscore != wxString::npos) ? language_code.substr(0, idx_underscore) : language_code; -} - // Load gettext translation files and activate them at the start of the application, // based on the "translation_language" key stored in the application config. -bool GUI_App::load_language(wxString language) +bool GUI_App::load_language(wxString language, bool initial) { - if (language.IsEmpty()) { - int lang = wxLocale::GetSystemLanguage(); - if (lang != wxLANGUAGE_UNKNOWN) { - const wxLanguageInfo *info = wxLocale::GetLanguageInfo(lang); - if (info != nullptr) - language = info->CanonicalName; - } + if (initial) { + // There is a static list of lookup path prefixes in wxWidgets. Add ours. + wxFileTranslationsLoader::AddCatalogLookupPathPrefix(from_u8(localization_dir())); + // Get the active language from PrusaSlicer.ini, or empty string if the key does not exist. + language = app_config->get("translation_language"); + // Get the system language. + { + const wxLanguage lang_system = wxLanguage(wxLocale::GetSystemLanguage()); + if (lang_system != wxLANGUAGE_UNKNOWN) + m_language_info_system = wxLocale::GetLanguageInfo(lang_system); + } + { + // Allocating a temporary locale will switch the default wxTranslations to its internal wxTranslations instance. + wxLocale temp_locale; + // Set the current translation's language to default, otherwise GetBestTranslation() may not work (see the wxWidgets source code). + wxTranslations::Get()->SetLanguage(wxLANGUAGE_DEFAULT); + // Let the wxFileTranslationsLoader enumerate all translation dictionaries for PrusaSlicer + // and try to match them with the system specific "preferred languages". + // There seems to be a support for that on Windows and OSX, while on Linuxes the code just returns wxLocale::GetSystemLanguage(). + // The last parameter gets added to the list of detected dictionaries. This is a workaround + // for not having the English dictionary. Let's hope wxWidgets of various versions process this call the same way. + wxString best_language = wxTranslations::Get()->GetBestTranslation(SLIC3R_APP_KEY, wxLANGUAGE_ENGLISH); + if (! best_language.IsEmpty()) + m_language_info_best = wxLocale::FindLanguageInfo(best_language); + } } - if (language.IsEmpty()) - language = "en_US"; + const wxLanguageInfo *language_info = wxLocale::FindLanguageInfo(language); + if (language_info == nullptr) + language.clear(); + + if (language.IsEmpty()) { + if (m_language_info_system != nullptr && m_language_info_system->LayoutDirection != wxLayout_RightToLeft) + language = m_language_info_system->CanonicalName; + if (m_language_info_best != nullptr && m_language_info_best->LayoutDirection != wxLayout_RightToLeft) + language = m_language_info_best->CanonicalName; + if (language.IsEmpty()) + language = "en_US"; + } + + language_info = wxLocale::FindLanguageInfo(language); + if (language_info == nullptr || language_info->LayoutDirection == wxLayout_RightToLeft) { + // We don't support right-to-left rendering (Hebrew, Arabic ...), therefore we switch to English. + language = "en_US"; + language_info = wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US); + } // Alternate language code. - wxString language_code_alt = language_code_short(language); - if (language_code_alt == "sk") + wxLanguage language_dict = wxLanguage(language_info->Language); + if (language.BeforeFirst('_') == "sk") // Slovaks understand Czech well. Give them the Czech translation. - language_code_alt = "cz"; + language_dict = wxLANGUAGE_CZECH; - const wxLanguageInfo *info = nullptr; - for (const wxLanguageInfo *this_info : get_installed_languages()) { - if (this_info->CanonicalName == language) { - // The language matches exactly, including the country suffix. Use it. - info = this_info; - break; - } - if (language_code_short(this_info->CanonicalName) == language_code_alt) - // Alternatively try to match just the language without the country suffix. - info = this_info; - } - - wxString canonical_name; - if (info == nullptr) { - // Fallback for user languages, for which we do not have dictionaries. - canonical_name = "en_EN"; - info = wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US); - } else - canonical_name = info->CanonicalName; - - wxLocale *new_locale = new wxLocale; - if (info == nullptr || ! new_locale->Init(info->Language)) { + if (! wxLocale::IsAvailable(language_info->Language)) { // Loading the language dictionary failed. - wxString message = "Switching PrusaSlicer to language " + canonical_name + " failed."; + wxString message = "Switching PrusaSlicer to language " + language_info->CanonicalName + " failed."; #if !defined(_WIN32) && !defined(__APPLE__) - // likely some linux system - "\nYou may need to reconfigure the missing locales, likely by running the \"locale-gen\" and \"dpkg-reconfigure locales\" commands.\n"; + // likely some linux system + message += "\nYou may need to reconfigure the missing locales, likely by running the \"locale-gen\" and \"dpkg-reconfigure locales\" commands.\n"; #endif - delete new_locale; - if (m_wxLocale == nullptr) + if (initial) message + "\n\nApplication will close."; wxMessageBox(message, "PrusaSlicer - Switching language failed", wxOK | wxICON_ERROR); - if (m_wxLocale == nullptr) - std::terminate(); + if (initial) + std::exit(EXIT_FAILURE); else return false; } - wxLocale *old_locale = m_wxLocale; - m_wxLocale = new_locale; - m_wxLocale->AddCatalogLookupPathPrefix(from_u8(localization_dir())); + + // Release the old locales, create new locales. + //FIXME wxWidgets cause havoc if the current locale is deleted. We just forget it causing memory leaks for now. + m_wxLocale.release(); + m_wxLocale = Slic3r::make_unique(); + m_wxLocale->Init(language_info->Language); + // Override language at the active wxTranslations class (which is stored in the active m_wxLocale) + // to load possibly different dictionary, for example, load Czech dictionary for Slovak language. + wxTranslations::Get()->SetLanguage(language_dict); m_wxLocale->AddCatalog(SLIC3R_APP_KEY); - m_imgui->set_language(into_u8(info->CanonicalName)); + m_imgui->set_language(into_u8(language_info->CanonicalName)); //FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only. wxSetlocale(LC_NUMERIC, "C"); Preset::update_suffix_modified(); - //FIXME Why the following line crashes? - // delete old_locale; return true; } -// Get a list of installed languages (languages for which we have dictionaries). -std::vector GUI_App::get_installed_languages() -{ - wxDir dir(from_u8(localization_dir())); - wxString filename; - std::vector res; - res.emplace_back(wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US)); - for (bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS); cont; cont = dir.GetNext(&filename)) { - const wxLanguageInfo *langinfo = wxLocale::FindLanguageInfo(filename); - if (langinfo != nullptr) { - auto full_file_name = dir.GetName() + wxFileName::GetPathSeparator() + - filename + wxFileName::GetPathSeparator() + SLIC3R_APP_KEY + wxT(".mo"); - if (wxFileExists(full_file_name)) - res.push_back(langinfo); - } - } - // Remove duplicated "en_EN" and possible others. - sort_remove_duplicates(res); - return res; -} - Tab* GUI_App::get_tab(Preset::Type type) { for (Tab* tab: tabs_list) @@ -1019,7 +1041,7 @@ wxString GUI_App::current_language_code_safe() const { "uk", "uk_UA", }, { "zh", "zh_CN", }, }; - wxString language_code = language_code_short(this->current_language_code()); + wxString language_code = this->current_language_code().BeforeFirst('_'); auto it = mapping.find(language_code); if (it != mapping.end()) language_code = it->second; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 52c2a7a26..a8043e991 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -88,7 +88,11 @@ class GUI_App : public wxApp size_t m_em_unit; // width of a "m"-symbol in pixels for current system font // Note: for 100% Scale m_em_unit = 10 -> it's a good enough coefficient for a size setting of controls - wxLocale* m_wxLocale{ nullptr }; + std::unique_ptr m_wxLocale; + // System language, from locales, owned by wxWidgets. + const wxLanguageInfo *m_language_info_system = nullptr; + // Best translation language, provided by Windows or OSX, owned by wxWidgets. + const wxLanguageInfo *m_language_info_best = nullptr; std::unique_ptr m_imgui; std::unique_ptr m_printhost_job_queue; @@ -132,7 +136,7 @@ public: void update_ui_from_settings(); bool switch_language(); - bool load_language(wxString language); + bool load_language(wxString language, bool initial); Tab* get_tab(Preset::Type type); ConfigOptionMode get_mode(); @@ -144,7 +148,7 @@ public: bool checked_tab(Tab* tab); void load_current_presets(); - wxString current_language_code() const { assert(m_wxLocale != nullptr); return m_wxLocale->GetCanonicalName(); } + wxString current_language_code() const { return m_wxLocale->GetCanonicalName(); } // Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US". wxString current_language_code_safe() const; @@ -187,7 +191,6 @@ private: void window_pos_restore(wxTopLevelWindow* window, const std::string &name, bool default_maximized = false); void window_pos_sanitize(wxTopLevelWindow* window); bool select_language(); - std::vector get_installed_languages(); #ifdef __WXMSW__ void associate_3mf_files(); #endif // __WXMSW__