From 647fdc4e3d5e60d01fb3e3b3dc04b432abbcc3ca Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Thu, 25 Jun 2026 17:36:45 +0530 Subject: [PATCH] chore: rewrite user-facing messages in Manufacturing module Conservative cleanup of frappe.throw/msgprint messages per the message style guide; meaning, severity, and .format() arguments are unchanged: - index bare {} placeholders as {0}/{1}/... so translators can reorder - move f-strings / .format() / concatenation out of _() (they break gettext extraction and never translate) - wrap translatable dynamic values (DocType/Select labels) in _() - fix grammar and colloquialisms - drop no-op _() wrapping runtime-built strings Part of #53976. --- erpnext/manufacturing/doctype/bom/bom.py | 4 ++- erpnext/manufacturing/doctype/bom/mapper.py | 2 +- .../doctype/bom_update_log/bom_update_log.py | 2 +- .../doctype/job_card/job_card.py | 25 +++++++++++-------- .../doctype/operation/operation.py | 4 +-- .../doctype/work_order/mapper.py | 2 +- .../work_order/services/reservation.py | 2 +- .../doctype/work_order/work_order.py | 10 +++----- .../doctype/workstation/workstation.py | 6 ++--- 9 files changed, 29 insertions(+), 28 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 0f375271607..144cd302a4a 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -967,7 +967,9 @@ class BOM(WebsiteGenerator): frappe.throw(_("Process Loss Percentage cannot be greater than 100")) if process_loss_qty and must_be_whole_number and process_loss_qty % 1 != 0: - msg = f"Item: {frappe.bold(item_code)} with Stock UOM: {frappe.bold(uom)} can't have fractional process loss qty as UOM {frappe.bold(uom)} is a whole Number." + msg = _( + "Item: {0} with Stock UOM: {1} cannot have fractional process loss qty as UOM {2} is a whole number." + ).format(frappe.bold(item_code), frappe.bold(uom), frappe.bold(uom)) frappe.throw(msg, title=_("Invalid Process Loss Configuration")) def has_scrap_items(self): diff --git a/erpnext/manufacturing/doctype/bom/mapper.py b/erpnext/manufacturing/doctype/bom/mapper.py index 7f4dafcdfec..edf19083906 100644 --- a/erpnext/manufacturing/doctype/bom/mapper.py +++ b/erpnext/manufacturing/doctype/bom/mapper.py @@ -79,7 +79,7 @@ def get_bom_diff(bom1: str, bom2: str): frappe.has_permission("BOM", "read", throw=True) if bom1 == bom2: frappe.throw( - _("BOM 1 {0} and BOM 2 {1} should not be same").format(frappe.bold(bom1), frappe.bold(bom2)) + _("BOM 1 {0} and BOM 2 {1} should not be the same").format(frappe.bold(bom1), frappe.bold(bom2)) ) doc1 = frappe.get_doc("BOM", bom1) diff --git a/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py b/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py index a5f3ee4ea95..dd5fe0f0645 100644 --- a/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py +++ b/erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py @@ -77,7 +77,7 @@ class BOMUpdateLog(Document): def validate_same_bom(self): if cstr(self.current_bom) == cstr(self.new_bom): - frappe.throw(_("Current BOM and New BOM can not be same")) + frappe.throw(_("Current BOM and New BOM cannot be the same")) def validate_bom_items(self): current_bom_item = frappe.db.get_value("BOM", self.current_bom, "item") diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 9f4db6c117c..2937a9df616 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -187,7 +187,7 @@ class JobCard(Document): if self.items and not self.transferred_qty and not self.skip_material_transfer: frappe.throw( _( - "Materials needs to be transferred to the work in progress warehouse for the job card {0}" + "Materials need to be transferred to the work in progress warehouse for the job card {0}" ).format(self.name) ) @@ -352,7 +352,7 @@ class JobCard(Document): data = self.get_overlap_for(d, open_job_cards=open_job_cards) if data: frappe.throw( - _("Row {0}: From Time and To Time of {1} is overlapping with {2}").format( + _("Row {0}: From Time and To Time of {1} are overlapping with {2}").format( d.idx, self.name, data.name ), OverlapError, @@ -901,7 +901,7 @@ class JobCard(Document): ): frappe.throw( _( - "Materials needs to be transferred to the work in progress warehouse for the job card {0}" + "Materials need to be transferred to the work in progress warehouse for the job card {0}" ).format(self.name) ) @@ -1411,14 +1411,15 @@ class JobCard(Document): return current_operation_qty + flt(self.total_completed_qty) def validate_previous_operation(self, row, current_operation_qty): - message = "Job Card {}: As per the sequence of the operations in the work order {}".format( - bold(self.name), bold(get_link_to_form("Work Order", self.work_order)) - ) - if not row.completed_qty or (row.status != "Completed" and row.completed_qty < current_operation_qty): frappe.throw( - _("{0}, complete the operation {1} before the operation {2}.").format( - message, bold(row.operation), bold(self.operation) + _( + "Job Card {0}: As per the sequence of the operations in the work order {1}, complete the operation {2} before the operation {3}." + ).format( + bold(self.name), + bold(get_link_to_form("Work Order", self.work_order)), + bold(row.operation), + bold(self.operation), ), OperationSequenceError, ) @@ -1437,7 +1438,7 @@ class JobCard(Document): def validate_work_order(self): if self.is_work_order_closed(): - frappe.throw(_("You can't make any changes to Job Card since Work Order is closed.")) + frappe.throw(_("You cannot make any changes to Job Card since Work Order is closed.")) def set_employees(self): self.employee = [] @@ -1635,7 +1636,9 @@ class JobCard(Document): ste.stock_entry.save() frappe.msgprint( - _("Stock Entry {0} has created").format(get_link_to_form("Stock Entry", ste.stock_entry.name)) + _("Stock Entry {0} has been created").format( + get_link_to_form("Stock Entry", ste.stock_entry.name) + ) ) return ste.stock_entry.as_dict() diff --git a/erpnext/manufacturing/doctype/operation/operation.py b/erpnext/manufacturing/doctype/operation/operation.py index 39692910942..3ab95f48efc 100644 --- a/erpnext/manufacturing/doctype/operation/operation.py +++ b/erpnext/manufacturing/doctype/operation/operation.py @@ -40,12 +40,12 @@ class Operation(Document): for row in self.sub_operations: if row.operation in operation_list: frappe.throw( - _("The operation {0} can not add multiple times").format(frappe.bold(row.operation)) + _("The operation {0} cannot be added multiple times").format(frappe.bold(row.operation)) ) if self.name == row.operation: frappe.throw( - _("The operation {0} can not be the sub operation").format(frappe.bold(row.operation)) + _("The operation {0} cannot be its own sub-operation").format(frappe.bold(row.operation)) ) operation_list.append(row.operation) diff --git a/erpnext/manufacturing/doctype/work_order/mapper.py b/erpnext/manufacturing/doctype/work_order/mapper.py index 74377094470..cabd01bfa29 100644 --- a/erpnext/manufacturing/doctype/work_order/mapper.py +++ b/erpnext/manufacturing/doctype/work_order/mapper.py @@ -376,7 +376,7 @@ def validate_operation_data(row): if flt(row.get("qty")) > flt(row.get("pending_qty")): frappe.throw( - _("For operation {0}: Quantity ({1}) can not be greater than pending quantity({2})").format( + _("For operation {0}: Quantity ({1}) can not be greater than pending quantity ({2})").format( frappe.bold(row.get("operation")), frappe.bold(row.get("qty")), frappe.bold(row.get("pending_qty")), diff --git a/erpnext/manufacturing/doctype/work_order/services/reservation.py b/erpnext/manufacturing/doctype/work_order/services/reservation.py index 6af3a98e8ca..f22470cf2d4 100644 --- a/erpnext/manufacturing/doctype/work_order/services/reservation.py +++ b/erpnext/manufacturing/doctype/work_order/services/reservation.py @@ -183,7 +183,7 @@ class WorkOrderStockReservation: if details := sre_details.get(item.name): if details.reserved_qty < details.consumed_qty: frappe.throw( - _("Consumed Qty cannot be greater than Reserved Qty for item {0}").format( + _("Consumed Qty {0} cannot be greater than Reserved Qty {1} for item {2}").format( details.consumed_qty, details.reserved_qty, item.item_code ) ) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 8191e047d85..a7af812fd34 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -589,11 +589,7 @@ class WorkOrder(Document): if flt(allowed_qty - actual_qty, precision) < 0: frappe.throw( _( - """Additional Transferred Qty {0} - cannot be greater than {1}. - To fix this, increase the percentage value - of the field 'Transfer Extra Raw Materials to WIP' - in Manufacturing Settings.""" + "Additional Transferred Qty {0} cannot be greater than {1}. To fix this, increase the percentage value of the field 'Transfer Extra Raw Materials to WIP' in Manufacturing Settings." ).format(actual_qty, allowed_qty), ) @@ -743,7 +739,7 @@ class WorkOrder(Document): batch_auto_creation = frappe.get_cached_value("Item", self.production_item, "create_new_batch") if not batch_auto_creation: frappe.msgprint( - _("Batch not created for item {} since it does not have a batch series.").format( + _("Batch not created for item {0} since it does not have a batch series.").format( frappe.bold(self.production_item) ), alert=True, @@ -858,7 +854,7 @@ class WorkOrder(Document): def validate_production_item(self): if frappe.get_cached_value("Item", self.production_item, "has_variants"): - frappe.throw(_("Work Order cannot be raised against a Item Template"), ItemHasVariantError) + frappe.throw(_("Work Order cannot be raised against an Item Template"), ItemHasVariantError) if self.production_item: validate_end_of_life(self.production_item) diff --git a/erpnext/manufacturing/doctype/workstation/workstation.py b/erpnext/manufacturing/doctype/workstation/workstation.py index a8400683681..ab75ac8ef94 100644 --- a/erpnext/manufacturing/doctype/workstation/workstation.py +++ b/erpnext/manufacturing/doctype/workstation/workstation.py @@ -187,7 +187,7 @@ class Workstation(Document): if existing: frappe.throw( - _("Row #{0}: Timings conflicts with row {1}").format(d.idx, comma_and(existing)), + _("Row #{0}: Timings conflict with row {1}").format(d.idx, comma_and(existing)), OverlapError, ) @@ -451,7 +451,7 @@ def is_within_operating_hours(workstation, operation, from_datetime, to_datetime frappe.throw( _( - "Operation {0} longer than any available working hours in workstation {1}, break down the operation into multiple operations" + "Operation {0} is longer than any available working hours in workstation {1}, break down the operation into multiple operations" ).format(operation, workstation.name), NotInWorkingHoursError, ) @@ -592,7 +592,7 @@ def validate_job_card(job_card: str, status: str): ) else: frappe.throw( - _("The job card {0} is in {1} state and you cannot complete.").format( + _("The job card {0} is in {1} state and you cannot complete it.").format( job_card, current_status ) )