Use IDEX/IQEX in the user-facing strings

Closes review comment 10.

`461c69c83e` settled this in April — IMEX internally, IDEX/IQEX as the user-facing label — but the
UI strings were never converted. Every translated string naming the feature now reads IDEX/IQEX:
41 occurrences across the printer and process option labels and tooltips, the modes editor, the
plate mode indicator, the pre-slice warnings, the placement refusals and the slicing errors. The
reviewer listed eight; the rest were in the same class.

Nothing else moves. The config keys keep the `imex_` spelling — `is_imex`, `imex_mode_names`,
`imex_parallel_mode` and the rest are on-disk format in existing printer presets and 3MF projects,
so renaming them would break every profile and project already saved. C++ identifiers, filenames,
comments and test names keep IMEX as well: it stays the internal name of the subsystem, which is
what covers the topology space (one gantry with 2-4 tools, 2x1 and 2x2 grids) that neither acronym
names on its own. Where a tooltip quotes a key, the key spelling is preserved and only the feature
word around it changed.

The `is_imex` tooltip is reworded rather than substituted: it already named the hardware families
parenthetically, so a literal replacement would have said IDEX/IQEX twice in one sentence.

No translation impact — no IMEX string had reached OrcaSlicer.pot or any catalogue, so there is
nothing to migrate. One test asserted on the old error text and now matches the new one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Clifford Garwood
2026-09-03 10:05:37 -04:00
co-authored by Claude Opus 5
parent bd8dfd6250
commit 5eac300d91
9 changed files with 39 additions and 39 deletions
+4 -4
View File
@@ -3731,13 +3731,13 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
print.active_step_add_warning(
PrintStateBase::WarningLevel::NON_CRITICAL,
imex_mode_resolved
? Slic3r::format(_(L("The IMEX mode \"%1%\" has no tools assigned on the selected printer. "
? Slic3r::format(_(L("The IDEX/IQEX mode \"%1%\" has no tools assigned on the selected printer. "
"Printing in Primary mode instead. Assign the mode's tools in Printer "
"Settings, or pick another mode from the plate's IMEX button.")),
"Settings, or pick another mode from the plate's IDEX/IQEX button.")),
imex_active_mode)
: Slic3r::format(_(L("This plate is set to the IMEX mode \"%1%\", which the selected printer "
: Slic3r::format(_(L("This plate is set to the IDEX/IQEX mode \"%1%\", which the selected printer "
"does not define. Printing in Primary mode instead. Pick a mode from the "
"plate's IMEX button, or restore the mode in Printer Settings.")),
"plate's IDEX/IQEX button, or restore the mode in Printer Settings.")),
imex_active_mode));
imex_active_mode = kImexPrimaryMode;
imex_active_mode_index = 0;
+2 -2
View File
@@ -1377,7 +1377,7 @@ StringObjectException Print::validate(std::vector<StringObjectException> *warnin
StringObjectException err;
// "Mixed filament" is the term the rest of the UI uses -- the button that
// creates one, and the sibling refusal for the wipe tower filament.
err.string = L("Mixed filaments are not supported in IMEX parallel modes. "
err.string = L("Mixed filaments are not supported in IDEX/IQEX parallel modes. "
"Switch this plate to Primary mode.");
err.object = m_objects.front();
return err;
@@ -1442,7 +1442,7 @@ StringObjectException Print::validate(std::vector<StringObjectException> *warnin
StringObjectException err;
err.string = Slic3r::format(
L("IMEX mode \"%1%\" prints with T%2%, but this plate's filaments are on %3%. "
L("IDEX/IQEX mode \"%1%\" prints with T%2%, but this plate's filaments are on %3%. "
"Assign a filament loaded on T%2%, or switch this plate to Primary mode."),
parallel_mode, routing.primary_phys, routed_list);
// Gives the notification a "Jump to <object>" link, which selects the object
+17 -17
View File
@@ -6611,8 +6611,8 @@ void PrintConfigDef::init_fff_params()
// g-code. They all carry non-nil defaults, so emitting them would add a line to every
// printer's dump. Kept out of the g-code config block (banned_keys).
def = this->add("is_imex", coBool);
def->label = L("IMEX Printer");
def->tooltip = L("Enable IMEX parallel printing for printers with multiple independent carriages (IDEX, IQEX, and similar).");
def->label = L("IDEX/IQEX Printer");
def->tooltip = L("Enable parallel printing for printers with multiple independent carriages (IDEX, IQEX, and similar).");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
@@ -6693,7 +6693,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("imex_viz_theme", coEnum);
def->label = L("Visualization Theme");
def->tooltip = L("Color theme for IMEX bed zone visualization. Choose a colorblind-friendly theme if needed.");
def->tooltip = L("Color theme for IDEX/IQEX bed zone visualization. Choose a colorblind-friendly theme if needed.");
def->mode = comAdvanced;
def->enum_keys_map = &ConfigOptionEnum<ImexVizTheme>::get_enum_values();
def->enum_values.push_back("standard");
@@ -6707,32 +6707,32 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionEnum<ImexVizTheme>(ImexVizTheme::Standard));
def = this->add("imex_parallel_mode", coString);
def->label = L("IMEX Print Mode");
def->tooltip = L("Name of the active IMEX parallel print mode, or \"primary\" for single-carriage printing. Requires IMEX Printer enabled in the Printer preset (Printer \u2192 Multimaterial \u2192 IMEX Configuration).");
def->label = L("IDEX/IQEX Print Mode");
def->tooltip = L("Name of the active IDEX/IQEX parallel print mode, or \"primary\" for single-carriage printing. Requires IDEX/IQEX Printer enabled in the Printer preset (Printer \u2192 Multimaterial \u2192 IDEX/IQEX Configuration).");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionString("primary"));
def = this->add("imex_head_filament_map", coString);
def->label = L("IMEX head filament map");
def->label = L("IDEX/IQEX head filament map");
def->tooltip = L("Per-plate override mapping physical heads to filament slots "
"(1-based). Empty means use pem-inversion defaults.");
def->mode = comDevelop;
def->set_default_value(new ConfigOptionString(""));
def = this->add("imex_mode_names", coStrings);
def->label = L("IMEX Mode Names");
def->tooltip = L("Display names for each user-defined IMEX parallel print mode.");
def->label = L("IDEX/IQEX Mode Names");
def->tooltip = L("Display names for each user-defined IDEX/IQEX parallel print mode.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionStrings());
def = this->add("imex_mode_active_tools", coStrings);
def->label = L("IMEX Mode Active Tools");
def->tooltip = L("Tool role assignments for each mode. Format: \"idx:P,idx:C,idx:M\" where P=Primary, C=Copy, M=Mirror (e.g. \"0:P,1:C,2:M,3:M\"). Managed by the IMEX Modes editor in the Printer preset.");
def->label = L("IDEX/IQEX Mode Active Tools");
def->tooltip = L("Tool role assignments for each mode. Format: \"idx:P,idx:C,idx:M\" where P=Primary, C=Copy, M=Mirror (e.g. \"0:P,1:C,2:M,3:M\"). Managed by the IDEX/IQEX Modes editor in the Printer preset.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionStrings());
def = this->add("imex_mode_gcodes", coStrings);
def->label = L("IMEX Mode G-codes");
def->label = L("IDEX/IQEX Mode G-codes");
def->tooltip = L("G-code or macro call to inject at print start for each mode.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionStrings());
@@ -12629,16 +12629,16 @@ OtherSlicingStatesConfigDef::OtherSlicingStatesConfigDef()
new_def("in_head_wrap_detect_zone", coBool, "In head wrap detect zone", "Indicates if the first layer overlaps with the head wrap zone.");
def = this->add("imex_mode", coString);
def->label = L("IMEX active mode");
def->tooltip = L("Name of the active IMEX parallel print mode for this plate (e.g. 'primary', 'mirror', 'copy'). Empty string if IMEX is not enabled.");
def->label = L("IDEX/IQEX active mode");
def->tooltip = L("Name of the active IDEX/IQEX parallel print mode for this plate (e.g. 'primary', 'mirror', 'copy'). Empty string if IDEX/IQEX is not enabled.");
def = this->add("imex_mode_index", coInt);
def->label = L("IMEX active mode index");
def->tooltip = L("Zero-based index of the active IMEX parallel print mode within imex_mode_names.");
def->label = L("IDEX/IQEX active mode index");
def->tooltip = L("Zero-based index of the active IDEX/IQEX parallel print mode within imex_mode_names.");
def = this->add("imex_mode_gcode", coString);
def->label = L("IMEX active mode G-code");
def->tooltip = L("The raw mode G-code template for the active IMEX parallel print mode, after placeholder evaluation. Globals defined here flow into machine_start_gcode.");
def->label = L("IDEX/IQEX active mode G-code");
def->tooltip = L("The raw mode G-code template for the active IDEX/IQEX parallel print mode, after placeholder evaluation. Globals defined here flow into machine_start_gcode.");
}
PrintStatisticsConfigDef::PrintStatisticsConfigDef()
+2 -2
View File
@@ -104,7 +104,7 @@ void IMEXModesCtrl::rebuild_info_and_header() {
auto* hdr_name = new wxStaticText(m_hdr_panel, wxID_ANY, _L("Name"));
auto* hdr_tools = new wxStaticText(m_hdr_panel, wxID_ANY, _L("Tools"));
auto* hdr_gcode = new wxStaticText(m_hdr_panel, wxID_ANY, _L("G-code"));
hdr_name->SetToolTip(_L("How the mode is labelled in the plate's IMEX mode selector. "
hdr_name->SetToolTip(_L("How the mode is labelled in the plate's IDEX/IQEX mode selector. "
"Required — a mode with no name cannot be selected."));
hdr_tools->SetToolTip(_L("Which tool heads take part in the mode and what role each one plays. "
"Click a tile to cycle its role."));
@@ -368,7 +368,7 @@ void IMEXModesCtrl::add_row(const std::string& name,
r.orig_name = nm;
r.name = new wxTextCtrl(r.panel, wxID_ANY, from_u8(nm), wxDefaultPosition, FromDIP(wxSize(130, -1)));
r.name->SetHint(_L("Mode name (required)"));
r.name->SetToolTip(_L("Name of this parallel mode, as it appears in the plate's IMEX mode "
r.name->SetToolTip(_L("Name of this parallel mode, as it appears in the plate's IDEX/IQEX mode "
"selector. Stored in the project by name, so renaming a mode that "
"plates already use makes them fall back to Primary. Cannot be empty "
"— a blank name is replaced with a generated one."));
+2 -2
View File
@@ -3190,8 +3190,8 @@ void MainFrame::init_menubar_as_editor()
// change adds true toolhead model support (cf. printer bed models) this same toggle
// governs that. Only relevant on Preview, and only meaningful when the active
// printer is IDEX/IQEX — gated to keep the menu uncluttered for everyone else.
append_menu_check_item(viewMenu, wxID_ANY, _L("Show IMEX Toolhead"),
_L("Show the IMEX toolhead representation around each active nozzle in the G-code preview."),
append_menu_check_item(viewMenu, wxID_ANY, _L("Show IDEX/IQEX Toolhead"),
_L("Show the IDEX/IQEX toolhead representation around each active nozzle in the G-code preview."),
[this](wxCommandEvent&) {
const bool current = wxGetApp().app_config->get("show_imex_toolhead_boxes") != "false";
wxGetApp().app_config->set("show_imex_toolhead_boxes", current ? "false" : "true");
+2 -2
View File
@@ -2127,7 +2127,7 @@ void PartPlate::render_icons(bool bottom, bool only_name, int hover_id)
render_icon_texture(m_imex_mode_icon.model, m_partplate_list->m_imex_mode_hovered_texture);
std::string cur = get_imex_mode();
if (cur == kImexPrimaryMode) cur = _u8L("Primary");
show_tooltip(_u8L("IMEX mode: ") + cur + _u8L(" (left-click to cycle, right-click for menu)"));
show_tooltip(_u8L("IDEX/IQEX mode: ") + cur + _u8L(" (left-click to cycle, right-click for menu)"));
} else {
render_icon_texture(m_imex_mode_icon.model, m_partplate_list->m_imex_mode_texture);
}
@@ -2135,7 +2135,7 @@ void PartPlate::render_icons(bool bottom, bool only_name, int hover_id)
if (has_imex_multimaterial_conflict()) {
render_icon_texture(m_imex_warn_icon, m_partplate_list->m_imex_warn_texture);
if (hover_id == (int)PLATE_IMEX_MODE_ID)
show_tooltip(_u8L("Warning: this plate uses a parallel IMEX mode with multi-material objects. Proceed with caution — verify your G-code handles this combination correctly."));
show_tooltip(_u8L("Warning: this plate uses a parallel IDEX/IQEX mode with multi-material objects. Proceed with caution — verify your G-code handles this combination correctly."));
}
}
}
+6 -6
View File
@@ -10457,10 +10457,10 @@ std::string imex_placement_error(PartPlate* plate)
return {};
switch (plate->imex_placement_violation()) {
case PartPlate::ImexPlacementViolation::Object:
return _u8L("Cannot slice: an object overlaps an area reserved for IMEX parallel printing "
return _u8L("Cannot slice: an object overlaps an area reserved for IDEX/IQEX parallel printing "
"(a secondary zone, or a carriage clearance strip inside the primary zone).");
case PartPlate::ImexPlacementViolation::PrimeTower:
return _u8L("Cannot slice: the prime tower overlaps an area reserved for IMEX parallel printing "
return _u8L("Cannot slice: the prime tower overlaps an area reserved for IDEX/IQEX parallel printing "
"(a secondary zone, or a carriage clearance strip inside the primary zone).");
case PartPlate::ImexPlacementViolation::None:
break;
@@ -12843,11 +12843,11 @@ void Plater::priv::on_action_slice_plate(SimpleEvent&)
std::vector<wxString> warnings = collect_imex_warnings(plate);
if (!warnings.empty()) {
int plate_num = partplate_list.get_curr_plate_index() + 1;
wxString msg = wxString::Format(_L("Plate %d has IMEX parallel mode active with the following concerns:\n\n"), plate_num);
wxString msg = wxString::Format(_L("Plate %d has IDEX/IQEX parallel mode active with the following concerns:\n\n"), plate_num);
for (const wxString& w : warnings)
msg += L"\u2022 " + w + "\n\n";
msg += _L("Continue slicing?");
RichMessageDialog dlg(q, msg, _L("IMEX Parallel Mode Warning"), wxICON_WARNING | wxYES | wxNO);
RichMessageDialog dlg(q, msg, _L("IDEX/IQEX Parallel Mode Warning"), wxICON_WARNING | wxYES | wxNO);
dlg.ShowCheckBox(_L("Don't show these warnings again"));
int result = dlg.ShowModal();
if (dlg.IsCheckBoxChecked())
@@ -12892,10 +12892,10 @@ void Plater::priv::on_action_slice_all(SimpleEvent&)
combined_msg += "\n";
}
if (!combined_msg.empty()) {
wxString msg = _L("The following IMEX parallel mode concerns were detected:\n\n")
wxString msg = _L("The following IDEX/IQEX parallel mode concerns were detected:\n\n")
+ combined_msg
+ _L("Continue slicing?");
RichMessageDialog dlg(q, msg, _L("IMEX Parallel Mode Warning"), wxICON_WARNING | wxYES | wxNO);
RichMessageDialog dlg(q, msg, _L("IDEX/IQEX Parallel Mode Warning"), wxICON_WARNING | wxYES | wxNO);
dlg.ShowCheckBox(_L("Don't show these warnings again"));
int result = dlg.ShowModal();
if (dlg.IsCheckBoxChecked())
+3 -3
View File
@@ -5636,7 +5636,7 @@ if (is_marlin_flavor)
optgroup->append_single_option_line("machine_tool_change_time", "printer_multimaterial_advanced#tool-change-time");
// IDEX/IQEX (IMEX) parallel printing configuration
optgroup = page->new_optgroup(L("IMEX Configuration"), L"param_advanced");
optgroup = page->new_optgroup(L("IDEX/IQEX Configuration"), L"param_advanced");
optgroup->append_single_option_line("is_imex");
optgroup->append_single_option_line("imex_firmware_managed_zones");
optgroup->append_single_option_line("imex_gantry_count");
@@ -5657,7 +5657,7 @@ if (is_marlin_flavor)
// activate_line to return early before build_field.
ConfigOptionDef placeholder_def;
placeholder_def.label = L("Pre-slice warnings");
placeholder_def.tooltip = L("Show a warning dialog before slicing if IMEX parallel mode "
placeholder_def.tooltip = L("Show a warning dialog before slicing if IDEX/IQEX parallel mode "
"concerns are detected (bed temperature conflicts, filament type "
"mismatches, multi-material conflicts). Can be suppressed from the "
"dialog itself. Re-enable here if suppressed accidentally.");
@@ -5678,7 +5678,7 @@ if (is_marlin_flavor)
}
optgroup->append_single_option_line("imex_viz_theme");
{
auto modes_og = page->new_optgroup(L("IMEX Parallel Modes"), L"param_advanced");
auto modes_og = page->new_optgroup(L("IDEX/IQEX Parallel Modes"), L"param_advanced");
auto line = Line{ L("Modes"), L("") };
line.full_width = 1;
line.widget = [this](wxWindow* parent) -> wxSizer* {
+1 -1
View File
@@ -1246,7 +1246,7 @@ TEST_CASE("A mixed filament outranks the multi-color rule on the same plate",
Slic3r::Print print;
const StringObjectException err = validate_plate(build(true), print, model);
REQUIRE_FALSE(err.string.empty());
CHECK(err.string.find("not supported in IMEX parallel modes") != std::string::npos);
CHECK(err.string.find("not supported in IDEX/IQEX parallel modes") != std::string::npos);
CHECK(err.string.find("Multi-color") == std::string::npos);
// The two rules differ in more than wording: the mixed path attaches an object (for the
// notification's "Jump to" link), the multi-color path returns none. Pins which fired