diff --git a/.github/helper/semgrep_rules/ux.js b/.github/helper/semgrep_rules/ux.js new file mode 100644 index 0000000000..ae73f9cc60 --- /dev/null +++ b/.github/helper/semgrep_rules/ux.js @@ -0,0 +1,9 @@ + +// ok: frappe-missing-translate-function-js +frappe.msgprint('{{ _("Both login and password required") }}'); + +// ruleid: frappe-missing-translate-function-js +frappe.msgprint('What'); + +// ok: frappe-missing-translate-function-js +frappe.throw(' {{ _("Both login and password required") }}. '); diff --git a/.github/helper/semgrep_rules/ux.py b/.github/helper/semgrep_rules/ux.py index 4a74457435..a00d3cd8ae 100644 --- a/.github/helper/semgrep_rules/ux.py +++ b/.github/helper/semgrep_rules/ux.py @@ -2,30 +2,30 @@ import frappe from frappe import msgprint, throw, _ -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python throw("Error Occured") -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python frappe.throw("Error Occured") -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python frappe.msgprint("Useful message") -# ruleid: frappe-missing-translate-function +# ruleid: frappe-missing-translate-function-python msgprint("Useful message") -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python translatedmessage = _("Hello") -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python throw(translatedmessage) -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python msgprint(translatedmessage) -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python msgprint(_("Helpful message")) -# ok: frappe-missing-translate-function +# ok: frappe-missing-translate-function-python frappe.throw(_("Error occured")) diff --git a/.github/helper/semgrep_rules/ux.yml b/.github/helper/semgrep_rules/ux.yml index ed06a6a80c..dd667f36c0 100644 --- a/.github/helper/semgrep_rules/ux.yml +++ b/.github/helper/semgrep_rules/ux.yml @@ -1,15 +1,30 @@ rules: -- id: frappe-missing-translate-function +- id: frappe-missing-translate-function-python pattern-either: - patterns: - pattern: frappe.msgprint("...", ...) - pattern-not: frappe.msgprint(_("..."), ...) - - pattern-not: frappe.msgprint(__("..."), ...) - patterns: - pattern: frappe.throw("...", ...) - pattern-not: frappe.throw(_("..."), ...) + message: | + All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations + languages: [python] + severity: ERROR + +- id: frappe-missing-translate-function-js + pattern-either: + - patterns: + - pattern: frappe.msgprint("...", ...) + - pattern-not: frappe.msgprint(__("..."), ...) + # ignore microtemplating e.g. msgprint("{{ _("server side translation") }}") + - pattern-not: frappe.msgprint("=~/\{\{.*\_.*\}\}/i", ...) + - patterns: + - pattern: frappe.throw("...", ...) - pattern-not: frappe.throw(__("..."), ...) + # ignore microtemplating + - pattern-not: frappe.throw("=~/\{\{.*\_.*\}\}/i", ...) message: | All user facing text must be wrapped in translate function. Please refer to translation documentation. https://frappeframework.com/docs/user/en/guides/basics/translations - languages: [python, javascript, json] + languages: [javascript] severity: ERROR diff --git a/frappe/templates/includes/contact.js b/frappe/templates/includes/contact.js index 130d8bfc0c..fb0b73ff80 100644 --- a/frappe/templates/includes/contact.js +++ b/frappe/templates/includes/contact.js @@ -12,14 +12,12 @@ frappe.ready(function() { var message = $('[name="message"]').val(); if(!(email && message)) { - frappe.msgprint("{{ _("Please enter both your email and message so that we \ - can get back to you. Thanks!") }}"); + frappe.msgprint('{{ _("Please enter both your email and message so that we can get back to you. Thanks!") }}'); return false; } if(!validate_email(email)) { - frappe.msgprint("{{ _("You seem to have written your name instead of your email. \ - Please enter a valid email address so that we can get back.") }}"); + frappe.msgprint('{{ _("You seem to have written your name instead of your email. Please enter a valid email address so that we can get back.") }}'); $('[name="email"]').focus(); return false; } @@ -31,9 +29,9 @@ frappe.ready(function() { message: message, callback: function(r) { if(r.message==="okay") { - frappe.msgprint("{{ _("Thank you for your message") }}"); + frappe.msgprint('{{ _("Thank you for your message") }}'); } else { - frappe.msgprint("{{ _("There were errors") }}"); + frappe.msgprint('{{ _("There were errors") }}'); console.log(r.exc); } $(':input').val(''); diff --git a/frappe/tests/ui_test_helpers.py b/frappe/tests/ui_test_helpers.py index f56311b2e3..7670f99698 100644 --- a/frappe/tests/ui_test_helpers.py +++ b/frappe/tests/ui_test_helpers.py @@ -1,4 +1,5 @@ import frappe +from frappe import _ from frappe.utils import add_to_date, now @frappe.whitelist() @@ -10,7 +11,7 @@ def create_if_not_exists(doc): ''' if not frappe.local.dev_server: - frappe.throw('This method can only be accessed in development', frappe.PermissionError) + frappe.throw(_('This method can only be accessed in development'), frappe.PermissionError) doc = frappe.parse_json(doc) diff --git a/frappe/utils/safe_exec.py b/frappe/utils/safe_exec.py index 632fc5df23..8bb2e1bfac 100644 --- a/frappe/utils/safe_exec.py +++ b/frappe/utils/safe_exec.py @@ -5,6 +5,7 @@ from html2text import html2text from RestrictedPython import compile_restricted, safe_globals import RestrictedPython.Guards import frappe +from frappe import _ import frappe.utils import frappe.utils.data from frappe.website.utils import (get_shade, get_toc, get_next_link) @@ -31,7 +32,7 @@ class NamespaceDict(frappe._dict): def safe_exec(script, _globals=None, _locals=None): # script reports must be enabled via site_config.json if not frappe.conf.server_script_enabled: - frappe.throw('Please Enable Server Scripts', ServerScriptNotEnabled) + frappe.throw(_('Please Enable Server Scripts'), ServerScriptNotEnabled) # build globals exec_globals = get_safe_globals()