This commit is contained in:
Enrico Turri 2019-08-28 16:03:36 +02:00
commit db0d877f85
10 changed files with 543 additions and 7898 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -15,6 +15,7 @@ src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
src/slic3r/GUI/Gizmos/GLGizmoScale.cpp src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
src/slic3r/GUI/GUI.cpp src/slic3r/GUI/GUI.cpp
src/slic3r/GUI/GUI_App.cpp src/slic3r/GUI/GUI_App.cpp
src/slic3r/GUI/GUI_ObjectList.cpp src/slic3r/GUI/GUI_ObjectList.cpp
@ -33,6 +34,7 @@ src/slic3r/GUI/PresetHints.cpp
src/slic3r/GUI/PrintHostDialogs.cpp src/slic3r/GUI/PrintHostDialogs.cpp
src/slic3r/GUI/ProgressStatusBar.cpp src/slic3r/GUI/ProgressStatusBar.cpp
src/slic3r/GUI/RammingChart.cpp src/slic3r/GUI/RammingChart.cpp
src/slic3r/GUI/Selection.cpp
src/slic3r/GUI/SysInfoDialog.cpp src/slic3r/GUI/SysInfoDialog.cpp
src/slic3r/GUI/Tab.cpp src/slic3r/GUI/Tab.cpp
src/slic3r/GUI/Tab.hpp src/slic3r/GUI/Tab.hpp

View file

@ -229,7 +229,11 @@ bool GUI_App::on_init_inner()
init_label_colours(); init_label_colours();
init_fonts(); init_fonts();
load_language(); 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);
// Suppress the '- default -' presets. // Suppress the '- default -' presets.
preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1"); preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1");
@ -585,7 +589,6 @@ void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files) const
bool GUI_App::switch_language() bool GUI_App::switch_language()
{ {
if (select_language()) { if (select_language()) {
save_language();
_3DScene::remove_all_canvases(); _3DScene::remove_all_canvases();
recreate_GUI(); recreate_GUI();
return true; return true;
@ -597,57 +600,43 @@ bool GUI_App::switch_language()
// select language from the list of installed languages // select language from the list of installed languages
bool GUI_App::select_language() bool GUI_App::select_language()
{ {
const auto langs = get_installed_languages(); const std::vector<const wxLanguageInfo*> langs = get_installed_languages();
wxArrayString names; wxArrayString names;
names.Alloc(langs.size()); names.Alloc(langs.size());
int init_selection = -1; // Some valid language should be selected since the application start up.
const auto current_language = m_wxLocale ? m_wxLocale->GetLanguage() : wxLocale::GetSystemLanguage(); assert(m_wxLocale != nullptr);
const auto current_language = m_wxLocale->GetLanguage();
for (size_t i = 0; i < langs.size(); i++) { int init_selection = 0;
const auto lang = langs[i]->Language; for (size_t i = 0; i < langs.size(); ++ i) {
const bool is_english = lang >= wxLANGUAGE_ENGLISH && lang <= wxLANGUAGE_ENGLISH_ZIMBABWE; if (langs[i]->Language == current_language)
if (lang == current_language || (current_language == wxLANGUAGE_UNKNOWN && is_english)) {
init_selection = i; init_selection = i;
}
names.Add(langs[i]->Description); names.Add(langs[i]->Description);
} }
const long index = wxGetSingleChoiceIndex( const long index = wxGetSingleChoiceIndex(_(L("Select the language")), _(L("Language")), names, init_selection);
_(L("Select the language")), // Try to load a new language.
_(L("Language")), names, init_selection >= 0 ? init_selection : 0); if (index != -1 && langs[index]->Language != current_language && this->load_language(langs[index]->CanonicalName)) {
// Save language at application config.
if (index != -1) { app_config->set("translation_language", m_wxLocale->GetCanonicalName().ToUTF8().data());
const wxLanguageInfo *lang = langs[index]; app_config->save();
if (lang->Language == current_language) { return true;
// There was no change
return false;
}
m_wxLocale = new wxLocale; // FIXME: leak?
m_wxLocale->Init(lang->Language);
m_wxLocale->AddCatalogLookupPathPrefix(from_u8(localization_dir()));
m_wxLocale->AddCatalog(SLIC3R_APP_KEY);
//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();
m_imgui->set_language(into_u8(lang->CanonicalName));
return true;
} }
return false; 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, // Load gettext translation files and activate them at the start of the application,
// based on the "translation_language" key stored in the application config. // based on the "translation_language" key stored in the application config.
bool GUI_App::load_language() bool GUI_App::load_language(wxString language)
{ {
wxString language = wxEmptyString;
if (app_config->has("translation_language"))
language = app_config->get("translation_language");
if (language.IsEmpty()) { if (language.IsEmpty()) {
int lang = wxLocale::GetSystemLanguage(); int lang = wxLocale::GetSystemLanguage();
if (lang != wxLANGUAGE_UNKNOWN) { if (lang != wxLANGUAGE_UNKNOWN) {
@ -657,67 +646,83 @@ bool GUI_App::load_language()
} }
} }
if (language.IsEmpty())
language = "en_US";
// Alternate language code.
wxString language_code_alt = language_code_short(language);
if (language_code_alt == "sk")
// Slovaks understand Czech well. Give them the Czech translation.
language_code_alt = "cz";
const wxLanguageInfo *info = nullptr; const wxLanguageInfo *info = nullptr;
if (! language.IsEmpty()) { for (const wxLanguageInfo *this_info : get_installed_languages()) {
const auto langs = get_installed_languages(); if (this_info->CanonicalName == language) {
for (const wxLanguageInfo *this_info : langs) // The language matches exactly, including the country suffix. Use it.
if (this_info->CanonicalName == language) { info = this_info;
info = this_info; break;
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;
} }
m_wxLocale = new wxLocale; wxString canonical_name;
if (info == nullptr) { if (info == nullptr) {
m_wxLocale->Init(wxLANGUAGE_DEFAULT); // Fallback for user languages, for which we do not have dictionaries.
m_imgui->set_language("en"); canonical_name = "en_EN";
} else { info = wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US);
m_wxLocale->Init(info->Language); } else
m_wxLocale->AddCatalogLookupPathPrefix(from_u8(localization_dir())); canonical_name = info->CanonicalName;
m_wxLocale->AddCatalog(SLIC3R_APP_KEY);
m_imgui->set_language(into_u8(info->CanonicalName)); wxLocale *new_locale = new wxLocale;
if (info == nullptr || ! new_locale->Init(info->Language)) {
// Loading the language dictionary failed.
wxString message = "Switching PrusaSlicer to language " + canonical_name + " 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";
#endif
delete new_locale;
if (m_wxLocale == nullptr)
message + "\n\nApplication will close.";
wxMessageBox(message, "PrusaSlicer - Switching language failed", wxOK | wxICON_ERROR);
if (m_wxLocale == nullptr)
std::terminate();
else
return false;
} }
wxLocale *old_locale = m_wxLocale;
m_wxLocale = new_locale;
m_wxLocale->AddCatalogLookupPathPrefix(from_u8(localization_dir()));
m_wxLocale->AddCatalog(SLIC3R_APP_KEY);
m_imgui->set_language(into_u8(info->CanonicalName));
//FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only. //FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only.
wxSetlocale(LC_NUMERIC, "C"); wxSetlocale(LC_NUMERIC, "C");
Preset::update_suffix_modified(); Preset::update_suffix_modified();
return true; //FIXME Why the following line crashes?
// delete old_locale;
return true;
} }
// save language at application config // Get a list of installed languages (languages for which we have dictionaries).
void GUI_App::save_language()
{
wxString language = wxEmptyString;
if (m_wxLocale)
language = m_wxLocale->GetCanonicalName();
app_config->set("translation_language", language.ToUTF8().data());
app_config->save();
}
// Get a list of installed languages
std::vector<const wxLanguageInfo*> GUI_App::get_installed_languages() std::vector<const wxLanguageInfo*> GUI_App::get_installed_languages()
{ {
std::vector<const wxLanguageInfo*> res;
wxDir dir(from_u8(localization_dir())); wxDir dir(from_u8(localization_dir()));
wxString filename; wxString filename;
const wxLanguageInfo * langinfo; std::vector<const wxLanguageInfo*> res;
wxString name = wxLocale::GetLanguageName(wxLANGUAGE_DEFAULT); res.emplace_back(wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US));
if (!name.IsEmpty()) {
res.push_back(wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT));
}
for (bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS); cont; cont = dir.GetNext(&filename)) { for (bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS); cont; cont = dir.GetNext(&filename)) {
langinfo = wxLocale::FindLanguageInfo(filename); const wxLanguageInfo *langinfo = wxLocale::FindLanguageInfo(filename);
if (langinfo != NULL) { if (langinfo != nullptr) {
auto full_file_name = dir.GetName() + wxFileName::GetPathSeparator() + auto full_file_name = dir.GetName() + wxFileName::GetPathSeparator() +
filename + wxFileName::GetPathSeparator() + SLIC3R_APP_KEY + wxT(".mo"); filename + wxFileName::GetPathSeparator() + SLIC3R_APP_KEY + wxT(".mo");
if (wxFileExists(full_file_name)) { if (wxFileExists(full_file_name))
res.push_back(langinfo); res.push_back(langinfo);
}
} }
} }
// Remove duplicated "en_EN" and possible others.
sort_remove_duplicates(res);
return res; return res;
} }
@ -1001,10 +1006,6 @@ int GUI_App::extruders_edited_cnt() const
wxString GUI_App::current_language_code_safe() const wxString GUI_App::current_language_code_safe() const
{ {
// Translate the language code to a code, for which Prusa Research maintains translations. // Translate the language code to a code, for which Prusa Research maintains translations.
wxString language_code = this->current_language_code();
size_t idx_underscore = language_code.find(language_code);
if (idx_underscore != wxString::npos)
language_code = language_code.substr(0, idx_underscore);
const std::map<wxString, wxString> mapping { const std::map<wxString, wxString> mapping {
{ "cs", "cs_CZ", }, { "cs", "cs_CZ", },
{ "sk", "cs_CZ", }, { "sk", "cs_CZ", },
@ -1018,6 +1019,7 @@ wxString GUI_App::current_language_code_safe() const
{ "uk", "uk_UA", }, { "uk", "uk_UA", },
{ "zh", "zh_CN", }, { "zh", "zh_CN", },
}; };
wxString language_code = language_code_short(this->current_language_code());
auto it = mapping.find(language_code); auto it = mapping.find(language_code);
if (it != mapping.end()) if (it != mapping.end())
language_code = it->second; language_code = it->second;

View file

@ -132,9 +132,7 @@ public:
void update_ui_from_settings(); void update_ui_from_settings();
bool switch_language(); bool switch_language();
// Load gettext translation files and activate them at the start of the application, bool load_language(wxString language);
// based on the "translation_language" key stored in the application config.
bool load_language();
Tab* get_tab(Preset::Type type); Tab* get_tab(Preset::Type type);
ConfigOptionMode get_mode(); ConfigOptionMode get_mode();
@ -146,9 +144,9 @@ public:
bool checked_tab(Tab* tab); bool checked_tab(Tab* tab);
void load_current_presets(); void load_current_presets();
wxString current_language_code() const { return m_wxLocale != nullptr ? m_wxLocale->GetCanonicalName() : wxString("en_US"); } wxString current_language_code() const { assert(m_wxLocale != nullptr); return m_wxLocale->GetCanonicalName(); }
// Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US". // Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US".
wxString current_language_code_safe() const; wxString current_language_code_safe() const;
virtual bool OnExceptionInMainLoop(); virtual bool OnExceptionInMainLoop();
@ -189,7 +187,6 @@ private:
void window_pos_restore(wxTopLevelWindow* window, const std::string &name, bool default_maximized = false); void window_pos_restore(wxTopLevelWindow* window, const std::string &name, bool default_maximized = false);
void window_pos_sanitize(wxTopLevelWindow* window); void window_pos_sanitize(wxTopLevelWindow* window);
bool select_language(); bool select_language();
void save_language();
std::vector<const wxLanguageInfo*> get_installed_languages(); std::vector<const wxLanguageInfo*> get_installed_languages();
#ifdef __WXMSW__ #ifdef __WXMSW__
void associate_3mf_files(); void associate_3mf_files();

View file

@ -268,7 +268,7 @@ void ObjectList::create_objects_ctrl()
AppendColumn(create_objects_list_extruder_column(4)); AppendColumn(create_objects_list_extruder_column(4));
// column ItemEditing of the view control: // column ItemEditing of the view control:
AppendBitmapColumn("Editing", colEditing, wxDATAVIEW_CELL_INERT, int(2.5 * wxGetApp().em_unit())/*25*/, AppendBitmapColumn(_(L("Editing")), colEditing, wxDATAVIEW_CELL_INERT, int(2.5 * wxGetApp().em_unit())/*25*/,
wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE);
} }

View file

@ -1183,7 +1183,7 @@ void Sidebar::show_sliced_info_sizer(const bool show)
info_text += wxString::Format("\n%s", ps.estimated_normal_print_time); info_text += wxString::Format("\n%s", ps.estimated_normal_print_time);
for (int i = (int)ps.estimated_normal_color_print_times.size() - 1; i >= 0; --i) for (int i = (int)ps.estimated_normal_color_print_times.size() - 1; i >= 0; --i)
{ {
new_label += wxString::Format("\n - %s%d", _(L("Color ")), i + 1); new_label += wxString::Format("\n - %s%d", _(L("Color")) + " ", i + 1);
info_text += wxString::Format("\n%s", ps.estimated_normal_color_print_times[i]); info_text += wxString::Format("\n%s", ps.estimated_normal_color_print_times[i]);
} }
} }
@ -1192,7 +1192,7 @@ void Sidebar::show_sliced_info_sizer(const bool show)
info_text += wxString::Format("\n%s", ps.estimated_silent_print_time); info_text += wxString::Format("\n%s", ps.estimated_silent_print_time);
for (int i = (int)ps.estimated_silent_color_print_times.size() - 1; i >= 0; --i) for (int i = (int)ps.estimated_silent_color_print_times.size() - 1; i >= 0; --i)
{ {
new_label += wxString::Format("\n - %s%d", _(L("Color ")), i + 1); new_label += wxString::Format("\n - %s%d", _(L("Color")) + " ", i + 1);
info_text += wxString::Format("\n%s", ps.estimated_silent_color_print_times[i]); info_text += wxString::Format("\n%s", ps.estimated_silent_color_print_times[i]);
} }
} }
@ -3387,7 +3387,7 @@ void Plater::priv::on_right_click(Vec2dEvent& evt)
*/ */
const MenuIdentifier id = printer_technology == ptSLA ? miObjectSLA : miObjectFFF; const MenuIdentifier id = printer_technology == ptSLA ? miObjectSLA : miObjectFFF;
if (wxGetApp().get_mode() == comSimple) { if (wxGetApp().get_mode() == comSimple) {
if (menu->FindItem(_(L("Increase copies"))) != wxNOT_FOUND) if (menu->FindItem(_(L("Add instance"))) != wxNOT_FOUND)
{ {
/* Detach an items from the menu, but don't delete them /* Detach an items from the menu, but don't delete them
* so that they can be added back later * so that they can be added back later
@ -3399,7 +3399,7 @@ void Plater::priv::on_right_click(Vec2dEvent& evt)
} }
} }
else { else {
if (menu->FindItem(_(L("Increase copies"))) == wxNOT_FOUND) if (menu->FindItem(_(L("Add instance"))) == wxNOT_FOUND)
{ {
// Prepend items to the menu, if those aren't not there // Prepend items to the menu, if those aren't not there
menu->Prepend(items_set_number_of_copies[id]); menu->Prepend(items_set_number_of_copies[id]);
@ -3513,11 +3513,11 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
sidebar->obj_list()->append_menu_item_export_stl(menu); sidebar->obj_list()->append_menu_item_export_stl(menu);
} }
else { else {
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Increase copies")) + "\t+", _(L("Place one more copy of the selected object")), wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Add instance")) + "\t+", _(L("Add one more instance of the selected object")),
[this](wxCommandEvent&) { q->increase_instances(); }, "add_copies", nullptr, [this]() { return can_increase_instances(); }, q); [this](wxCommandEvent&) { q->increase_instances(); }, "add_copies", nullptr, [this]() { return can_increase_instances(); }, q);
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Decrease copies")) + "\t-", _(L("Remove one copy of the selected object")), wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Remove instance")) + "\t-", _(L("Remove one instance of the selected object")),
[this](wxCommandEvent&) { q->decrease_instances(); }, "remove_copies", nullptr, [this]() { return can_decrease_instances(); }, q); [this](wxCommandEvent&) { q->decrease_instances(); }, "remove_copies", nullptr, [this]() { return can_decrease_instances(); }, q);
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies")) + dots, _(L("Change the number of copies of the selected object")), wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of instances")) + dots, _(L("Change the number of instances of the selected object")),
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "number_of_copies", nullptr, [this]() { return can_increase_instances(); }, q); [this](wxCommandEvent&) { q->set_number_of_copies(); }, "number_of_copies", nullptr, [this]() { return can_increase_instances(); }, q);

View file

@ -954,12 +954,12 @@ void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config)
// apply scale // apply scale
start_dragging(); start_dragging();
scale(s * Vec3d::Ones(), type); scale(s * Vec3d::Ones(), type);
wxGetApp().plater()->canvas3D()->do_scale(L("")); // avoid storing another snapshot wxGetApp().plater()->canvas3D()->do_scale(""); // avoid storing another snapshot
// center selection on print bed // center selection on print bed
start_dragging(); start_dragging();
translate(print_volume.center() - get_bounding_box().center()); translate(print_volume.center() - get_bounding_box().center());
wxGetApp().plater()->canvas3D()->do_move(L("")); // avoid storing another snapshot wxGetApp().plater()->canvas3D()->do_move(""); // avoid storing another snapshot
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
} }

View file

@ -1797,7 +1797,7 @@ void TabFilament::update_volumetric_flow_preset_hints()
try { try {
text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)); text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle));
} catch (std::exception &ex) { } catch (std::exception &ex) {
text = _(L("Volumetric flow hints not available\n\n")) + from_u8(ex.what()); text = _(L("Volumetric flow hints not available")) + "\n\n" + from_u8(ex.what());
} }
m_volumetric_speed_description_line->SetText(text); m_volumetric_speed_description_line->SetText(text);
} }