diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 370fa3ba2..a51091be1 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -14,11 +14,13 @@ #include "GCode/WipeTower.hpp" #include "Utils.hpp" #include "BuildVolume.hpp" +#include "format.hpp" #include #include #include +#include #include #include #include @@ -1182,12 +1184,49 @@ void Print::alert_when_supports_needed() break; case SupportSpotsGenerator::SupportPointCause::SeparationFromBed: message = L("low bed adhesion"); break; case SupportSpotsGenerator::SupportPointCause::UnstableFloatingPart: message = L("floating object part"); break; - case SupportSpotsGenerator::SupportPointCause::WeakObjectPart: message = L("thin fragile section"); break; + case SupportSpotsGenerator::SupportPointCause::WeakObjectPart: message = L("thin fragile part"); break; } return message; }; + // TRN this translation rule is used to translate lists of uknown size on single line. The first argument is element of the list, + // the second argument may be element or rest of the list. + auto single_line_list_rule = L("%1%, %2%"); + auto multiline_list_rule = "%1%\n%2%"; + + auto elements_to_translated_list = [](const std::vector &translated_elements, std::string expansion_rule) { + if (expansion_rule.find("%1%") == expansion_rule.npos || expansion_rule.find("%2%") == expansion_rule.npos) { + BOOST_LOG_TRIVIAL(error) << "INCORRECT EXPANSION RULE FOR LIST TRANSLATION: " << expansion_rule + << " - IT SHOULD CONTAIN %1% and %2%!"; + expansion_rule = "%1% %2%"; + } + if (translated_elements.size() == 0) { + return std::string{}; + } + if (translated_elements.size() == 1) { + return translated_elements.front(); + } + + std::string translated_list = expansion_rule; + for (int i = 0; i < translated_elements.size() - 1; i++) { + auto first_elem = translated_list.find("%1%"); + assert(first_elem != translated_list.npos); + translated_list.replace(first_elem, 3, translated_elements[i]); + + // expand the translated list by another application of the same rule + auto second_elem = translated_list.find("%2%"); + assert(second_elem != translated_list.npos); + if (i < translated_elements.size() - 2) { + translated_list.replace(second_elem, 3, expansion_rule); + } else { + translated_list.replace(second_elem, 3, translated_elements[i + 1]); + } + } + + return translated_list; + }; + // vector of pairs of object and its issues, where each issue is a pair of type and critical flag std::vector>>> objects_isssues; @@ -1207,45 +1246,60 @@ void Print::alert_when_supports_needed() } } - bool recommend_brim = false; + bool recommend_brim = false; std::map, std::vector> po_by_support_issues; for (const auto &obj : objects_isssues) { for (const auto &issue : obj.second) { po_by_support_issues[issue].push_back(obj.first); - if (issue.first == SupportSpotsGenerator::SupportPointCause::SeparationFromBed && !obj.first->has_brim()){ + if (issue.first == SupportSpotsGenerator::SupportPointCause::SeparationFromBed && !obj.first->has_brim()) { recommend_brim = true; } } } - auto message = L("Detected print stability issues") + ": \n"; + // TRN first argument is a list of detected issues + auto top_level_message = L("Detected print stability issues:\n%1%"); + + std::vector>> message_elements; if (objects_isssues.size() > po_by_support_issues.size()) { // there are more objects than causes, group by issues for (const auto &issue : po_by_support_issues) { - message += "\n" + issue_to_alert_message(issue.first.first, issue.first.second) + " >> "; + auto &pair = message_elements.emplace_back(issue_to_alert_message(issue.first.first, issue.first.second), + std::vector{}); for (const auto &obj : issue.second) { - message += obj->m_model_object->name + ", "; + pair.second.push_back(obj->m_model_object->name); } - message.pop_back(); - message.pop_back(); // remove , - message += ".\n"; } } else { // more causes than objects, group by objects for (const auto &obj : objects_isssues) { - message += "\n" + L("Object") + " " + obj.first->model_object()->name + " << "; + auto &pair = message_elements.emplace_back(obj.first->model_object()->name, std::vector{}); for (const auto &issue : obj.second) { - message += issue_to_alert_message(issue.first, issue.second) + ", "; + pair.second.push_back(issue_to_alert_message(issue.first, issue.second)); } - message.pop_back(); - message.pop_back(); // remove , - message += ".\n"; } } - bool brim_or_supp = recommend_brim && po_by_support_issues.size() < 2; - auto brim_part = " " + (brim_or_supp ? L("or") : L("and")) + " " + L("brim"); - message += "\n" + L("Consider enabling supports") + (recommend_brim ? brim_part : "") + "."; + // first, gather sublements into single line list, store in first subelement + for (auto &pair : message_elements) { + pair.second.front() = elements_to_translated_list(pair.second, single_line_list_rule); + } + + // then gather elements to create multiline list + std::vector lines = {}; + for (auto &pair : message_elements) { + lines.push_back(""); // empty line for readability + lines.push_back(pair.first); + lines.push_back(pair.second.front()); + } + + lines.push_back(""); + lines.push_back(L("Consider enabling supports.")); + if (recommend_brim) { + lines.push_back(L("Also consider enabling brim.")); + } + + auto message = Slic3r::format(top_level_message, elements_to_translated_list(lines, multiline_list_rule)); if (objects_isssues.size() > 0) { this->active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL, message);