diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index 3ddc070fc5..c356da366f 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -13,6 +13,7 @@ from frappe.core.doctype.version.version import get_diff from frappe.model import no_value_fields from frappe.utils import cint, cstr, duration_to_seconds, flt, update_progress_bar from frappe.utils.csvutils import get_csv_content_from_google_sheets, read_csv_content +from frappe.utils.data import escape_html from frappe.utils.xlsxutils import ( read_xls_file_from_attached_file, read_xlsx_file_from_attached_file, @@ -727,7 +728,9 @@ class Row: elif df.fieldtype == "Link": exists = self.link_exists(value, df) if not exists: - msg = _("Value {0} missing for {1}").format(frappe.bold(value), frappe.bold(df.options)) + msg = _("Value {0} missing for {1}").format( + frappe.bold(escape_html(cstr(value))), frappe.bold(df.options) + ) self.warnings.append( { "row": self.row_number, @@ -746,7 +749,8 @@ class Row: "col": col.column_number, "field": df_as_json(df), "message": _("Value {0} must in {1} format").format( - frappe.bold(value), frappe.bold(get_user_format(col.date_format)) + frappe.bold(escape_html(cstr(value))), + frappe.bold(get_user_format(col.date_format)), ), } ) @@ -761,7 +765,8 @@ class Row: "col": col.column_number, "field": df_as_json(df), "message": _("Value {0} must in {1} format").format( - frappe.bold(value), frappe.bold(get_user_format(col.date_format)) + frappe.bold(escape_html(cstr(value))), + frappe.bold(get_user_format(col.date_format)), ), } ) @@ -774,7 +779,7 @@ class Row: "col": col.column_number, "field": df_as_json(df), "message": _("Value {0} must be in the valid duration format: d h m s").format( - frappe.bold(value) + frappe.bold(escape_html(cstr(value))) ), } ) @@ -1045,7 +1050,7 @@ class Column: ] not_exists = list(set(values) - set(exists)) if not_exists: - missing_values = ", ".join(not_exists) + missing_values = ", ".join(escape_html(v) for v in not_exists) message = _("The following values do not exist for {0}: {1}") self.warnings.append( { @@ -1088,7 +1093,7 @@ class Column: invalid = values - set(options) if invalid: valid_values = ", ".join(frappe.bold(o) for o in options) - invalid_values = ", ".join(frappe.bold(i) for i in invalid) + invalid_values = ", ".join(frappe.bold(escape_html(i)) for i in invalid) message = _("The following values are invalid: {0}. Values must be one of {1}") self.warnings.append( { diff --git a/frappe/core/doctype/version/version.py b/frappe/core/doctype/version/version.py index 7ea6f2f039..68e4afc37f 100644 --- a/frappe/core/doctype/version/version.py +++ b/frappe/core/doctype/version/version.py @@ -199,6 +199,7 @@ def get_diff(old, new, for_child=False, compare_cancelled=False): field_meta.options, {"name": ("in", (old_value, new_value))}, ["name", title_field], + ignore_ifnull=True, ) for r in result: if r[0] == old_value: diff --git a/frappe/database/schema.py b/frappe/database/schema.py index 9bd0a1e45b..d29bff1615 100644 --- a/frappe/database/schema.py +++ b/frappe/database/schema.py @@ -5,7 +5,7 @@ from frappe import _ from frappe.utils import cint, cstr, flt from frappe.utils.defaults import get_not_null_defaults -# This matches anything that isn't [a-zA-Z0-9_] +# This matches anything that isn't Unicode Word Characters, Numbers and Underscore. SPECIAL_CHAR_PATTERN = re.compile(r"[\W]", flags=re.UNICODE) VARCHAR_CAST_PATTERN = re.compile(r"varchar\(([\d]+)\)") diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index 6e0041e2b2..4a88211ef8 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -188,16 +188,18 @@ class EmailQueue(Document): if ctx.smtp_server.session.has_extn("SIZE"): if max_size := ctx.smtp_server.session.esmtp_features.get("size"): max_size = int(max_size) - msg_size = len(msg) - if msg_size > max_size: - msg_size_mb = msg_size / (1024 * 1024) - max_size_mb = max_size / (1024 * 1024) - frappe.throw( - _( - "Email size {0:.2f} MB exceeds the maximum allowed size of {1:.2f} MB" - ).format(msg_size_mb, max_size_mb) - ) + if max_size > 0: + msg_size = len(msg) + + if msg_size > max_size: + msg_size_mb = msg_size / (1024 * 1024) + max_size_mb = max_size / (1024 * 1024) + frappe.throw( + _( + "Email size {0:.2f} MB exceeds the maximum allowed size of {1:.2f} MB" + ).format(msg_size_mb, max_size_mb) + ) return msg diff --git a/frappe/locale/bs.po b/frappe/locale/bs.po index d301c4afd0..f88053f5bd 100644 --- a/frappe/locale/bs.po +++ b/frappe/locale/bs.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" "POT-Creation-Date: 2026-04-05 09:44+0000\n" -"PO-Revision-Date: 2026-04-05 14:45\n" +"PO-Revision-Date: 2026-04-06 15:04\n" "Last-Translator: developers@frappe.io\n" "Language-Team: Bosnian\n" "MIME-Version: 1.0\n" @@ -9692,7 +9692,7 @@ msgstr "Ovdje unesi statičke parametre URL-a (npr. pošiljatelj=ERPNext, korisn #: frappe/public/js/form_builder/components/FieldProperties.vue:66 msgid "Enter the fieldname of the currency field or a cached value (e.g. Company:company:default_currency)." -msgstr "" +msgstr "Unesite naziv polja za valutu ili keširanu vrijednost (npr. Company:company:default_currency)." #. Description of the 'Message Parameter' (Data) field in DocType 'SMS #. Settings' @@ -23504,7 +23504,7 @@ msgstr "SQL" #. Description of the 'Condition' (Small Text) field in DocType 'Bulk Update' #: frappe/desk/doctype/bulk_update/bulk_update.json msgid "SQL Conditions. Example: {\"status\" : \"open\", \"priority\" : \"medium\"}" -msgstr "" +msgstr "SQL Uslovi. Primjer: {\"status\" : \"open\", \"priority\" : \"medium\"}" #. Label of the sql_explain_html (HTML) field in DocType 'Recorder Query' #: frappe/core/doctype/recorder/recorder.js:85 @@ -27373,7 +27373,7 @@ msgstr "Automatsko Ponavljanje za ovaj dokument je onemogućeno." #: frappe/desk/doctype/bulk_update/bulk_update.py:43 msgid "The Bulk Update could not happen due to {0}" -msgstr "" +msgstr "Masovno ažuriranje nije moglo da se desi zbog {0}" #: frappe/public/js/frappe/form/grid.js:1310 msgid "The CSV format is case sensitive" diff --git a/frappe/locale/hr.po b/frappe/locale/hr.po index 82b6eb8bb1..55f61d2754 100644 --- a/frappe/locale/hr.po +++ b/frappe/locale/hr.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" "POT-Creation-Date: 2026-04-05 09:44+0000\n" -"PO-Revision-Date: 2026-04-05 14:45\n" +"PO-Revision-Date: 2026-04-06 15:04\n" "Last-Translator: developers@frappe.io\n" "Language-Team: Croatian\n" "MIME-Version: 1.0\n" @@ -9692,7 +9692,7 @@ msgstr "Ovdje unesi statičke parametre URL-a (npr. pošiljatelj=ERPNext, korisn #: frappe/public/js/form_builder/components/FieldProperties.vue:66 msgid "Enter the fieldname of the currency field or a cached value (e.g. Company:company:default_currency)." -msgstr "" +msgstr "Unesite naziv polja za valutu ili predmemoriranu vrijednost (npr. Company:company:default_valute)." #. Description of the 'Message Parameter' (Data) field in DocType 'SMS #. Settings' @@ -23504,7 +23504,7 @@ msgstr "SQL" #. Description of the 'Condition' (Small Text) field in DocType 'Bulk Update' #: frappe/desk/doctype/bulk_update/bulk_update.json msgid "SQL Conditions. Example: {\"status\" : \"open\", \"priority\" : \"medium\"}" -msgstr "" +msgstr "SQL Uvjeti. Primjer: {\"status\" : \"open\", \"priority\" : \"medium\"}" #. Label of the sql_explain_html (HTML) field in DocType 'Recorder Query' #: frappe/core/doctype/recorder/recorder.js:85 @@ -27373,7 +27373,7 @@ msgstr "Automatsko Ponavljanje za ovaj dokument je onemogućeno." #: frappe/desk/doctype/bulk_update/bulk_update.py:43 msgid "The Bulk Update could not happen due to {0}" -msgstr "" +msgstr "Masovno ažuriranje nije se moglo dogoditi zbog {0}" #: frappe/public/js/frappe/form/grid.js:1310 msgid "The CSV format is case sensitive" diff --git a/frappe/locale/ru.po b/frappe/locale/ru.po index d6248b4bad..0dc8b1e076 100644 --- a/frappe/locale/ru.po +++ b/frappe/locale/ru.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" "POT-Creation-Date: 2026-04-05 09:44+0000\n" -"PO-Revision-Date: 2026-04-05 14:45\n" +"PO-Revision-Date: 2026-04-06 15:03\n" "Last-Translator: developers@frappe.io\n" "Language-Team: Russian\n" "MIME-Version: 1.0\n" @@ -9694,7 +9694,7 @@ msgstr "Введите здесь статические параметры url #: frappe/public/js/form_builder/components/FieldProperties.vue:66 msgid "Enter the fieldname of the currency field or a cached value (e.g. Company:company:default_currency)." -msgstr "" +msgstr "Введите имя поля валюты или кэшированное значение (например, Company:company:default_currency)." #. Description of the 'Message Parameter' (Data) field in DocType 'SMS #. Settings' @@ -23506,7 +23506,7 @@ msgstr "SQL" #. Description of the 'Condition' (Small Text) field in DocType 'Bulk Update' #: frappe/desk/doctype/bulk_update/bulk_update.json msgid "SQL Conditions. Example: {\"status\" : \"open\", \"priority\" : \"medium\"}" -msgstr "" +msgstr "Условия SQL. Пример: {\"status\" : \"open\", \"priority\" : \"medium\"}" #. Label of the sql_explain_html (HTML) field in DocType 'Recorder Query' #: frappe/core/doctype/recorder/recorder.js:85 @@ -27375,7 +27375,7 @@ msgstr "Автоповтор для этого документа был отк #: frappe/desk/doctype/bulk_update/bulk_update.py:43 msgid "The Bulk Update could not happen due to {0}" -msgstr "" +msgstr "Массовое обновление не удалось выполнить из-за {0}" #: frappe/public/js/frappe/form/grid.js:1310 msgid "The CSV format is case sensitive" diff --git a/frappe/locale/sr.po b/frappe/locale/sr.po index 8eef42db72..42632c259d 100644 --- a/frappe/locale/sr.po +++ b/frappe/locale/sr.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" "POT-Creation-Date: 2026-04-05 09:44+0000\n" -"PO-Revision-Date: 2026-04-05 14:45\n" +"PO-Revision-Date: 2026-04-06 15:03\n" "Last-Translator: developers@frappe.io\n" "Language-Team: Serbian (Cyrillic)\n" "MIME-Version: 1.0\n" @@ -9690,7 +9690,7 @@ msgstr "Унесите статичке URL параметре (нпр. sender=E #: frappe/public/js/form_builder/components/FieldProperties.vue:66 msgid "Enter the fieldname of the currency field or a cached value (e.g. Company:company:default_currency)." -msgstr "" +msgstr "Унесите назив поља за валуту или кеширану вредност (нпр. Company:company:default_currency)." #. Description of the 'Message Parameter' (Data) field in DocType 'SMS #. Settings' @@ -23502,7 +23502,7 @@ msgstr "SQL" #. Description of the 'Condition' (Small Text) field in DocType 'Bulk Update' #: frappe/desk/doctype/bulk_update/bulk_update.json msgid "SQL Conditions. Example: {\"status\" : \"open\", \"priority\" : \"medium\"}" -msgstr "" +msgstr "SQL услови. Пример: {\"status\" : \"open\", \"priority\" : \"medium\"}" #. Label of the sql_explain_html (HTML) field in DocType 'Recorder Query' #: frappe/core/doctype/recorder/recorder.js:85 @@ -27371,7 +27371,7 @@ msgstr "Аутоматско понављање за овај документ #: frappe/desk/doctype/bulk_update/bulk_update.py:43 msgid "The Bulk Update could not happen due to {0}" -msgstr "" +msgstr "Масовно ажурирање није могло бити извршено због {0}" #: frappe/public/js/frappe/form/grid.js:1310 msgid "The CSV format is case sensitive" diff --git a/frappe/locale/sr_CS.po b/frappe/locale/sr_CS.po index f8ca732b70..e926d3c8c8 100644 --- a/frappe/locale/sr_CS.po +++ b/frappe/locale/sr_CS.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" "POT-Creation-Date: 2026-04-05 09:44+0000\n" -"PO-Revision-Date: 2026-04-05 14:46\n" +"PO-Revision-Date: 2026-04-06 15:04\n" "Last-Translator: developers@frappe.io\n" "Language-Team: Serbian (Latin)\n" "MIME-Version: 1.0\n" @@ -9691,7 +9691,7 @@ msgstr "Unesite statičke URL parametre (npr. sender=ERPNext, username=ERPNext, #: frappe/public/js/form_builder/components/FieldProperties.vue:66 msgid "Enter the fieldname of the currency field or a cached value (e.g. Company:company:default_currency)." -msgstr "" +msgstr "Unesite naziv polja za valutu ili keširanu vrednost (npr. Company:company:default_currency)." #. Description of the 'Message Parameter' (Data) field in DocType 'SMS #. Settings' @@ -23503,7 +23503,7 @@ msgstr "SQL" #. Description of the 'Condition' (Small Text) field in DocType 'Bulk Update' #: frappe/desk/doctype/bulk_update/bulk_update.json msgid "SQL Conditions. Example: {\"status\" : \"open\", \"priority\" : \"medium\"}" -msgstr "" +msgstr "SQL uslovi. Primer: {\"status\" : \"open\", \"priority\" : \"medium\"}" #. Label of the sql_explain_html (HTML) field in DocType 'Recorder Query' #: frappe/core/doctype/recorder/recorder.js:85 @@ -27372,7 +27372,7 @@ msgstr "Automatsko ponavljanje za ovaj dokument je onemogućeno." #: frappe/desk/doctype/bulk_update/bulk_update.py:43 msgid "The Bulk Update could not happen due to {0}" -msgstr "" +msgstr "Masovno ažuriranje nije moglo biti izvršeno zbog {0}" #: frappe/public/js/frappe/form/grid.js:1310 msgid "The CSV format is case sensitive" diff --git a/frappe/locale/sv.po b/frappe/locale/sv.po index 1b4eff3cbe..c3dc0e8bf2 100644 --- a/frappe/locale/sv.po +++ b/frappe/locale/sv.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" "POT-Creation-Date: 2026-04-05 09:44+0000\n" -"PO-Revision-Date: 2026-04-05 14:45\n" +"PO-Revision-Date: 2026-04-06 15:03\n" "Last-Translator: developers@frappe.io\n" "Language-Team: Swedish\n" "MIME-Version: 1.0\n" @@ -9691,7 +9691,7 @@ msgstr "Ange statiska url parametrar här (T.ex.. Avsändare = System, användar #: frappe/public/js/form_builder/components/FieldProperties.vue:66 msgid "Enter the fieldname of the currency field or a cached value (e.g. Company:company:default_currency)." -msgstr "" +msgstr "Ange fältnamn för valutafält eller cachat värde (t.ex. Company:company:default_currency)." #. Description of the 'Message Parameter' (Data) field in DocType 'SMS #. Settings' @@ -23503,7 +23503,7 @@ msgstr "SQL" #. Description of the 'Condition' (Small Text) field in DocType 'Bulk Update' #: frappe/desk/doctype/bulk_update/bulk_update.json msgid "SQL Conditions. Example: {\"status\" : \"open\", \"priority\" : \"medium\"}" -msgstr "" +msgstr "SQL Villkor. Exempel: {\"status\" : \"open\", \"priority\" : \"medium\"}" #. Label of the sql_explain_html (HTML) field in DocType 'Recorder Query' #: frappe/core/doctype/recorder/recorder.js:85 @@ -27372,7 +27372,7 @@ msgstr "Återkommande för detta dokument är inaktiverad." #: frappe/desk/doctype/bulk_update/bulk_update.py:43 msgid "The Bulk Update could not happen due to {0}" -msgstr "" +msgstr "Mass uppdatering kunde inte ske på grund av {0}" #: frappe/public/js/frappe/form/grid.js:1310 msgid "The CSV format is case sensitive" diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js index e27968fac2..1aea6a02a9 100644 --- a/frappe/public/js/frappe/desk.js +++ b/frappe/public/js/frappe/desk.js @@ -380,15 +380,17 @@ frappe.Application = class Application { logout() { var me = this; me.logged_out = true; - return frappe.call({ - method: "logout", - callback: function (r) { - if (r.exc) { - return; - } + frappe.confirm(__("Are you sure you want to log out?"), function () { + return frappe.call({ + method: "logout", + callback: function (r) { + if (r.exc) { + return; + } - me.redirect_to_login(); - }, + me.redirect_to_login(); + }, + }); }); } handle_session_expired() { diff --git a/frappe/public/js/frappe/form/controls/link.js b/frappe/public/js/frappe/form/controls/link.js index 12f7d68503..d0e30386df 100644 --- a/frappe/public/js/frappe/form/controls/link.js +++ b/frappe/public/js/frappe/form/controls/link.js @@ -242,7 +242,7 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat ) { html += '
' + - __(frappe.utils.escape_html(frappe.utils.html2text(d.description))) + + __(frappe.utils.html2text(frappe.utils.escape_html(d.description))) + ""; } return $(`
`) diff --git a/frappe/public/js/frappe/form/toolbar.js b/frappe/public/js/frappe/form/toolbar.js index ed6b86045a..7432b0fe2b 100644 --- a/frappe/public/js/frappe/form/toolbar.js +++ b/frappe/public/js/frappe/form/toolbar.js @@ -341,7 +341,7 @@ frappe.ui.form.Toolbar = class Toolbar { // Navigate if (!this.frm.is_new() && !this.frm.meta.issingle) { this.page.add_action_icon( - "es-line-left-chevron", + frappe.utils.is_rtl() ? "es-line-right-chevron" : "es-line-left-chevron", () => { this.frm.navigate_records(1); }, @@ -349,7 +349,7 @@ frappe.ui.form.Toolbar = class Toolbar { __("Previous Document") ); this.page.add_action_icon( - "es-line-right-chevron", + frappe.utils.is_rtl() ? "es-line-left-chevron" : "es-line-right-chevron", () => { this.frm.navigate_records(0); },