diff --git a/frappe/__init__.py b/frappe/__init__.py index ac6b0edff5..4c1873ea9b 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -442,6 +442,12 @@ def get_site_config(sites_path: str | None = None, site_path: str | None = None) # Set the user as database name if not set in config config["db_user"] = os.environ.get("FRAPPE_DB_USER") or config.get("db_user") or config.get("db_name") + # vice versa for dbname if not defined + config["db_name"] = os.environ.get("FRAPPE_DB_NAME") or config.get("db_name") or config["db_user"] + + # read password + config["db_password"] = os.environ.get("FRAPPE_DB_PASSWORD") or config.get("db_password") + # Allow externally extending the config with hooks if extra_config := config.get("extra_config"): if isinstance(extra_config, str): diff --git a/frappe/core/doctype/data_import/data_import.py b/frappe/core/doctype/data_import/data_import.py index cfecb3fbda..b2de0badc9 100644 --- a/frappe/core/doctype/data_import/data_import.py +++ b/frappe/core/doctype/data_import/data_import.py @@ -138,7 +138,7 @@ def get_preview_from_template(data_import, import_file=None, google_sheets_url=N @frappe.whitelist() -def form_start_import(data_import): +def form_start_import(data_import: str): return frappe.get_doc("Data Import", data_import).start_import() diff --git a/frappe/core/doctype/doctype/doctype.js b/frappe/core/doctype/doctype/doctype.js index f672db1f92..6cfb54dc1c 100644 --- a/frappe/core/doctype/doctype/doctype.js +++ b/frappe/core/doctype/doctype/doctype.js @@ -62,7 +62,7 @@ frappe.ui.form.on("DocType", { } } - const customize_form_link = "Customize Form"; + const customize_form_link = `${__("Customize Form")}`; if (!frappe.boot.developer_mode && !frm.doc.custom) { // make the document read-only frm.set_read_only(); diff --git a/frappe/core/doctype/file/test_file.py b/frappe/core/doctype/file/test_file.py index 6c9b9f5872..03a8927dac 100644 --- a/frappe/core/doctype/file/test_file.py +++ b/frappe/core/doctype/file/test_file.py @@ -17,7 +17,7 @@ from frappe.core.api.file import ( unzip_file, ) from frappe.core.doctype.file.exceptions import FileTypeNotAllowed -from frappe.core.doctype.file.utils import get_extension +from frappe.core.doctype.file.utils import get_corrupted_image_msg, get_extension from frappe.desk.form.utils import add_comment from frappe.exceptions import ValidationError from frappe.tests.utils import FrappeTestCase, change_settings @@ -768,6 +768,25 @@ class TestFileUtils(FrappeTestCase): ) self.assertRegex(communication.content, r"") + def test_broken_image(self): + """Ensure that broken inline images don't cause errors.""" + is_private = not frappe.get_meta("Communication").make_attachments_public + communication = frappe.get_doc( + doctype="Communication", + communication_type="Communication", + communication_medium="Email", + content='
', + recipients="to ", + cc=None, + bcc=None, + sender="sender@test.com", + ).insert(ignore_permissions=True) + + self.assertFalse( + frappe.db.exists("File", {"attached_to_name": communication.name, "is_private": is_private}) + ) + self.assertIn(f'{get_corrupted_image_msg()}', communication.content) + def test_create_new_folder(self): folder = create_new_folder("test_folder", "Home") self.assertTrue(folder.is_folder) diff --git a/frappe/core/doctype/file/utils.py b/frappe/core/doctype/file/utils.py index 578c760389..d16f76b090 100644 --- a/frappe/core/doctype/file/utils.py +++ b/frappe/core/doctype/file/utils.py @@ -2,6 +2,7 @@ import hashlib import mimetypes import os import re +from binascii import Error as BinasciiError from io import BytesIO from typing import TYPE_CHECKING, Optional from urllib.parse import unquote @@ -234,7 +235,12 @@ def extract_images_from_html(doc: "Document", content: str, is_private: bool = F content = content.encode("utf-8") if b"," in content: content = content.split(b",")[1] - content = safe_b64decode(content) + + try: + content = safe_b64decode(content) + except BinasciiError: + frappe.flags.has_dataurl = True + return f'{get_corrupted_image_msg()} str: extn = None if content_type: diff --git a/frappe/core/doctype/server_script/server_script.js b/frappe/core/doctype/server_script/server_script.js index 2ec0b0ade7..7053670307 100644 --- a/frappe/core/doctype/server_script/server_script.js +++ b/frappe/core/doctype/server_script/server_script.js @@ -72,20 +72,23 @@ if doc.allocated_to: # retreive payment session state ps = doc.flags.payment_session -if ps.changed: # could be an idempotent run - if ps.flags.status_changed_to in ps.flowstates.success: +if ps.is_success: + if ps.changed: # could be an idempotent run doc.set_as_paid() - # custom process return values - doc.flags.payment_result = { - "message": "Thank you for your payment", - "action": {"href": "https://shop.example.com", "label": "Return to shop"}, - } - if ps.flags.status_changed_to in ps.flowstates.pre_authorized: - # do something else - if ps.flags.status_changed_to in ps.flowstates.processing: - # do something else - if ps.flags.status_changed_to in ps.flowstates.declined: - # do something else + # custom process return values + doc.flags.payment_session.result = { + "message": "Thank you for your payment", + "action": {"href": "https://shop.example.com", "label": "Return to shop"}, + } +if ps.is_pre_authorized: + if ps.changed: # could be an idempotent run + ... +if ps.is_processing: + if ps.changed: # could be an idempotent run + ... +if ps.is_declined: + if ps.changed: # could be an idempotent run + ...

The On Payment Failed (on_payment_failed) event only transports the error message which the controller implementation had extracted from the transaction.

diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index 96891b53e1..3269d2860e 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -17,7 +17,6 @@ from frappe.desk.doctype.notification_settings.notification_settings import ( toggle_notifications, ) from frappe.desk.notifications import clear_notifications -from frappe.model.delete_doc import check_if_doc_is_linked from frappe.model.document import Document from frappe.query_builder import DocType from frappe.rate_limiter import rate_limit @@ -536,11 +535,20 @@ class User(Document): # Delete EPS data frappe.db.delete("Energy Point Log", {"user": self.name}) - # Ask user to disable instead if document is still linked - try: - check_if_doc_is_linked(self) - except frappe.LinkExistsError: - frappe.throw(_("You can disable the user instead of deleting it."), frappe.LinkExistsError) + # Remove user link from Workflow Action + frappe.db.set_value("Workflow Action", {"user": self.name}, "user", None) + + # Delete user's List Filters + frappe.db.delete("List Filter", {"for_user": self.name}) + + # Remove user from Note's Seen By table + seen_notes = frappe.get_all("Note", filters=[["Note Seen By", "user", "=", self.name]], pluck="name") + for note_id in seen_notes: + note = frappe.get_doc("Note", note_id) + for row in note.seen_by: + if row.user == self.name: + note.remove(row) + note.save(ignore_permissions=True) def before_rename(self, old_name, new_name, merge=False): # if merging, delete the old user notification settings diff --git a/frappe/core/page/permission_manager/permission_manager.js b/frappe/core/page/permission_manager/permission_manager.js index 308bbfedba..0df30519e9 100644 --- a/frappe/core/page/permission_manager/permission_manager.js +++ b/frappe/core/page/permission_manager/permission_manager.js @@ -106,7 +106,7 @@ frappe.PermissionEngine = class PermissionEngine { reset_std_permissions(data) { let doctype = this.get_doctype(); - let d = frappe.confirm(__("Reset Permissions for {0}?", [doctype]), () => { + let d = frappe.confirm(__("Reset Permissions for {0}?", [__(doctype)]), () => { return frappe .call({ module: "frappe.core", @@ -122,7 +122,7 @@ frappe.PermissionEngine = class PermissionEngine { // show standard permissions let $d = $(d.wrapper) .find(".frappe-confirm-message") - .append("
Standard Permissions:

"); + .append(`
${__("Standard Permissions")}:

`); let $wrapper = $("

").appendTo($d); data.message.forEach((d) => { let rights = this.rights @@ -134,7 +134,7 @@ frappe.PermissionEngine = class PermissionEngine { d.rights = rights.join(", "); $wrapper.append(`
\ -
${d.role}, Level ${d.permlevel || 0}
\ +
${__(d.role)}, ${__("Level")} ${d.permlevel || 0}
\
${d.rights}
\

`); }); diff --git a/frappe/desk/doctype/dashboard_chart/dashboard_chart.js b/frappe/desk/doctype/dashboard_chart/dashboard_chart.js index 31fb7e5167..e11d496d69 100644 --- a/frappe/desk/doctype/dashboard_chart/dashboard_chart.js +++ b/frappe/desk/doctype/dashboard_chart/dashboard_chart.js @@ -397,7 +397,7 @@ frappe.ui.form.on("Dashboard Chart", { } } }, - primary_action_label: "Set", + primary_action_label: __("Set"), }); frappe.dashboards.filters_dialog = dialog; @@ -484,7 +484,7 @@ frappe.ui.form.on("Dashboard Chart", { } frm.trigger("set_dynamic_filters_in_table"); }, - primary_action_label: "Set", + primary_action_label: __("Set"), }); dialog.show(); diff --git a/frappe/desk/doctype/notification_log/notification_log.py b/frappe/desk/doctype/notification_log/notification_log.py index 70f31606c1..8793559611 100644 --- a/frappe/desk/doctype/notification_log/notification_log.py +++ b/frappe/desk/doctype/notification_log/notification_log.py @@ -93,6 +93,7 @@ def enqueue_create_notification(users: list[str] | str, doc: dict): doc=doc, users=users, now=frappe.flags.in_test, + enqueue_after_commit=not frappe.flags.in_test, ) diff --git a/frappe/desk/doctype/number_card/number_card.js b/frappe/desk/doctype/number_card/number_card.js index ef04ac5b3e..274ca76848 100644 --- a/frappe/desk/doctype/number_card/number_card.js +++ b/frappe/desk/doctype/number_card/number_card.js @@ -33,7 +33,7 @@ frappe.ui.form.on("Number Card", { }, create_add_to_dashboard_button: function (frm) { - frm.add_custom_button("Add Card to Dashboard", () => { + frm.add_custom_button(__("Add Card to Dashboard"), () => { const dialog = frappe.dashboard_utils.get_add_to_dashboard_dialog( frm.doc.name, "Number Card", @@ -292,7 +292,7 @@ frappe.ui.form.on("Number Card", { frm.trigger("render_filters_table"); } }, - primary_action_label: "Set", + primary_action_label: __("Set"), }); if (is_document_type) { @@ -384,7 +384,7 @@ frappe.ui.form.on("Number Card", { } frm.trigger("set_dynamic_filters_in_table"); }, - primary_action_label: "Set", + primary_action_label: __("Set"), }); dialog.show(); diff --git a/frappe/desk/doctype/system_health_report/system_health_report.py b/frappe/desk/doctype/system_health_report/system_health_report.py index 1f136d43b9..abdc1b0272 100644 --- a/frappe/desk/doctype/system_health_report/system_health_report.py +++ b/frappe/desk/doctype/system_health_report/system_health_report.py @@ -186,19 +186,40 @@ class SystemHealthReport(Document): # Exclude "maybe" curently executing job upper_threshold = add_to_date(None, minutes=-30, as_datetime=True) self.scheduler_status = get_scheduler_status().get("status") - failing_jobs = frappe.db.sql( - """ - select scheduled_job_type, - avg(CASE WHEN status != 'Complete' THEN 1 ELSE 0 END) * 100 as failure_rate - from `tabScheduled Job Log` - where - creation > %(lower_threshold)s - and modified > %(lower_threshold)s - and creation < %(upper_threshold)s - group by scheduled_job_type - having failure_rate > 0 - order by failure_rate desc - limit 5""", + + mariadb_query = """ + SELECT scheduled_job_type, + AVG(CASE WHEN status != 'Complete' THEN 1 ELSE 0 END) * 100 AS failure_rate + FROM `tabScheduled Job Log` + WHERE + creation > %(lower_threshold)s + AND modified > %(lower_threshold)s + AND creation < %(upper_threshold)s + GROUP BY scheduled_job_type + HAVING failure_rate > 0 + ORDER BY failure_rate DESC + LIMIT 5 + """ + + postgres_query = """ + SELECT scheduled_job_type, + AVG(CASE WHEN status != 'Complete' THEN 1 ELSE 0 END) * 100 AS "failure_rate" + FROM "tabScheduled Job Log" + WHERE + creation > %(lower_threshold)s + AND modified > %(lower_threshold)s + AND creation < %(upper_threshold)s + GROUP BY scheduled_job_type + HAVING AVG(CASE WHEN status != 'Complete' THEN 1 ELSE 0 END) * 100 > 0 + ORDER BY "failure_rate" DESC + LIMIT 5 + """ + + failing_jobs = frappe.db.multisql( + { + "mariadb": mariadb_query, + "postgres": postgres_query, + }, {"lower_threshold": lower_threshold, "upper_threshold": upper_threshold}, as_dict=True, ) diff --git a/frappe/desk/form/linked_with.py b/frappe/desk/form/linked_with.py index 96c9cacd64..c68388aa70 100644 --- a/frappe/desk/form/linked_with.py +++ b/frappe/desk/form/linked_with.py @@ -421,99 +421,85 @@ def get_linked_docs(doctype: str, name: str, linkinfo: dict | None = None) -> di if not linkinfo: return results - for dt, link in linkinfo.items(): - filters = [] - link["doctype"] = dt - try: - link_meta_bundle = frappe.desk.form.load.get_meta_bundle(dt) - except Exception as e: - if isinstance(e, frappe.DoesNotExistError): - frappe.clear_last_message() + is_target_doctype_table = frappe.get_meta(doctype).istable + + for linked_doctype, link_context in linkinfo.items(): + linked_doctype_meta = frappe.get_meta(linked_doctype) + + if linked_doctype_meta.issingle: continue - linkmeta = link_meta_bundle[0] - if not linkmeta.get("issingle"): - fields = [ - d.fieldname - for d in linkmeta.get( - "fields", - { - "in_list_view": 1, - "fieldtype": ["not in", ("Image", "HTML", "Button", *frappe.model.table_fields)], - }, - ) - ] + ["name", "modified", "docstatus"] + filters = [] + ret = None + parent_info = None - if link.get("add_fields"): - fields += link["add_fields"] + fields = [ + d.fieldname + for d in linked_doctype_meta.get( + "fields", + { + "in_list_view": 1, + "fieldtype": ["not in", ("Image", "HTML", "Button", *frappe.model.table_fields)], + }, + ) + ] + ["name", "modified", "docstatus"] - fields = [f"`tab{dt}`.`{sf.strip()}`" for sf in fields if sf and "`tab" not in sf] + if add_fields := link_context.get("add_fields"): + fields += add_fields - try: - if link.get("filters"): - ret = frappe.get_all( - doctype=dt, fields=fields, filters=link.get("filters"), order_by=None - ) + fields = [f"`tab{linked_doctype}`.`{sf.strip()}`" for sf in fields if sf and "`tab" not in sf] - elif link.get("get_parent"): - ret = None - - # check for child table - if not frappe.get_meta(doctype).istable: - continue - - me = frappe.db.get_value( - doctype, name, ["parenttype", "parent"], as_dict=True, order_by=None - ) - if me and me.parenttype == dt: - ret = frappe.get_all( - doctype=dt, fields=fields, filters=[[dt, "name", "=", me.parent]], order_by=None - ) - - elif link.get("child_doctype"): - or_filters = [ - [link.get("child_doctype"), link_fieldnames, "=", name] - for link_fieldnames in link.get("fieldname") - ] - - # dynamic link - if link.get("doctype_fieldname"): - filters.append( - [link.get("child_doctype"), link.get("doctype_fieldname"), "=", doctype] - ) - - ret = frappe.get_all( - doctype=dt, - fields=fields, - filters=filters, - or_filters=or_filters, - distinct=True, - order_by=None, - ) - - else: - link_fieldnames = link.get("fieldname") - if link_fieldnames: - if isinstance(link_fieldnames, str): - link_fieldnames = [link_fieldnames] - or_filters = [[dt, fieldname, "=", name] for fieldname in link_fieldnames] - # dynamic link - if link.get("doctype_fieldname"): - filters.append([dt, link.get("doctype_fieldname"), "=", doctype]) - ret = frappe.get_all( - doctype=dt, fields=fields, filters=filters, or_filters=or_filters, order_by=None - ) - - else: - ret = None - - except frappe.PermissionError: - frappe.clear_last_message() + if filters_ctx := link_context.get("filters"): + ret = frappe.get_list(doctype=linked_doctype, fields=fields, filters=filters_ctx, order_by=None) + elif link_context.get("get_parent"): + # check for child table + if not is_target_doctype_table: continue - if ret: - results[dt] = ret + parent_info = parent_info or frappe.db.get_value( + doctype, name, ["parenttype", "parent"], as_dict=True, order_by=None + ) + + if parent_info and parent_info.parenttype == linked_doctype: + ret = frappe.get_list( + doctype=linked_doctype, + fields=fields, + filters=[[linked_doctype, "name", "=", parent_info.parent]], + order_by=None, + ) + + elif child_doctype := link_context.get("child_doctype"): + or_filters = [ + [child_doctype, link_fieldnames, "=", name] for link_fieldnames in link_context["fieldname"] + ] + + # dynamic link_context + if doctype_fieldname := link_context.get("doctype_fieldname"): + filters.append([child_doctype, doctype_fieldname, "=", doctype]) + + ret = frappe.get_list( + doctype=linked_doctype, + fields=fields, + filters=filters, + or_filters=or_filters, + distinct=True, + order_by=None, + ) + + elif link_fieldnames := link_context.get("fieldname"): + if isinstance(link_fieldnames, str): + link_fieldnames = [link_fieldnames] + or_filters = [[linked_doctype, fieldname, "=", name] for fieldname in link_fieldnames] + # dynamic link_context + if doctype_fieldname := link_context.get("doctype_fieldname"): + filters.append([linked_doctype, doctype_fieldname, "=", doctype]) + ret = frappe.get_list( + doctype=linked_doctype, fields=fields, filters=filters, or_filters=or_filters, order_by=None + ) + + if ret: + results[linked_doctype] = ret return results diff --git a/frappe/desk/form/load.py b/frappe/desk/form/load.py index 9b01c8ecee..7409941b60 100644 --- a/frappe/desk/form/load.py +++ b/frappe/desk/form/load.py @@ -38,7 +38,7 @@ def getdoc(doctype, name, user=None): if not doc.has_permission("read"): frappe.flags.error_message = _("Insufficient Permission for {0}").format( - frappe.bold(doctype + " " + name) + frappe.bold(_(doctype) + " " + name) ) raise frappe.PermissionError(("read", doctype, name)) diff --git a/frappe/desk/page/user_profile/user_profile_controller.js b/frappe/desk/page/user_profile/user_profile_controller.js index fd38f09ddd..abf0bea297 100644 --- a/frappe/desk/page/user_profile/user_profile_controller.js +++ b/frappe/desk/page/user_profile/user_profile_controller.js @@ -77,7 +77,7 @@ class UserProfile { render_heatmap() { this.heatmap = new frappe.Chart(".performance-heatmap", { type: "heatmap", - countLabel: "Energy Points", + countLabel: __("Energy Points"), data: {}, discreteDomains: 1, radius: 3, @@ -111,7 +111,7 @@ class UserProfile { value_based_on: "points", chart_type: "Sum", document_type: "Energy Point Log", - name: "Energy Points", + name: __("Energy Points"), width: "half", based_on: "creation", }; diff --git a/frappe/email/doctype/email_account/email_account.js b/frappe/email/doctype/email_account/email_account.js index 959a1908a0..3a0baa9564 100644 --- a/frappe/email/doctype/email_account/email_account.js +++ b/frappe/email/doctype/email_account/email_account.js @@ -1,4 +1,24 @@ frappe.email_defaults = { + "Frappe Mail": { + domain: null, + password: null, + awaiting_password: 0, + ascii_encode_password: 0, + login_id_is_different: 0, + login_id: null, + use_imap: 0, + use_ssl: 0, + validate_ssl_certificate: 0, + use_starttls: 0, + email_server: null, + incoming_port: 0, + always_use_account_email_id_as_sender: 1, + use_tls: 0, + use_ssl_for_outgoing: 0, + smtp_server: null, + smtp_port: null, + no_smtp_authentication: 0, + }, GMail: { email_server: "imap.gmail.com", incoming_port: 993, @@ -144,11 +164,11 @@ frappe.ui.form.on("Email Account", { frm.refresh_field("imap_folder"); } set_default_max_attachment_size(frm); - frm.events.show_oauth_authorization_message(frm); }, refresh: function (frm) { frm.events.enable_incoming(frm); + frm.events.show_oauth_authorization_message(frm); if (frappe.route_flags.delete_user_from_locals && frappe.route_flags.linked_user) { delete frappe.route_flags.delete_user_from_locals; @@ -169,6 +189,15 @@ frappe.ui.form.on("Email Account", { oauth_access(frm); }, + validate_frappe_mail_settings: function (frm) { + if (frm.doc.service == "Frappe Mail") { + frappe.call({ + doc: frm.doc, + method: "validate_frappe_mail_settings", + }); + } + }, + show_oauth_authorization_message(frm) { if (frm.doc.auth_method === "OAuth" && frm.doc.connected_app) { frappe.call({ diff --git a/frappe/email/doctype/email_account/email_account.json b/frappe/email/doctype/email_account/email_account.json index 5ddaed911d..dd244285c1 100644 --- a/frappe/email/doctype/email_account/email_account.json +++ b/frappe/email/doctype/email_account/email_account.json @@ -2,7 +2,7 @@ "actions": [], "allow_rename": 1, "autoname": "field:email_account_name", - "creation": "2014-09-11 12:04:34.163728", + "creation": "2024-06-11 16:39:01.323289", "doctype": "DocType", "document_type": "Setup", "engine": "InnoDB", @@ -13,22 +13,30 @@ "enable_incoming", "enable_outgoing", "column_break_3", - "domain", "service", + "domain", + "frappe_mail_site", "authentication_column", "auth_method", "authorize_api_access", + "validate_frappe_mail_settings", "password", "awaiting_password", "ascii_encode_password", "column_break_10", + "api_key", + "api_secret", "connected_app", "connected_user", "login_id_is_different", "login_id", "incoming_popimap_tab", - "mailbox_settings", + "section_break_uc6h", "default_incoming", + "column_break_uynb", + "attachment_limit", + "last_synced_at", + "mailbox_settings", "use_imap", "use_ssl", "validate_ssl_certificate", @@ -36,7 +44,6 @@ "email_server", "incoming_port", "column_break_18", - "attachment_limit", "email_sync_option", "initial_sync_count", "section_break_25", @@ -50,19 +57,19 @@ "notify_if_unreplied", "unreplied_for_mins", "send_notification_to", - "outgoing_smtp_tab", + "outgoing_tab", + "default_outgoing", + "column_break_h5pd", + "always_use_account_email_id_as_sender", + "always_use_account_name_as_sender_name", + "send_unsubscribe_message", + "track_email_status", "outgoing_mail_settings", - "column_break_bidn", "use_tls", "use_ssl_for_outgoing", "smtp_server", "smtp_port", "column_break_38", - "default_outgoing", - "always_use_account_email_id_as_sender", - "always_use_account_name_as_sender_name", - "send_unsubscribe_message", - "track_email_status", "no_smtp_authentication", "signature_section", "add_signature", @@ -92,6 +99,7 @@ }, { "default": "0", + "depends_on": "eval: doc.service != \"Frappe Mail\"", "fieldname": "login_id_is_different", "fieldtype": "Check", "hide_days": 1, @@ -107,7 +115,7 @@ "label": "Alternative Email ID" }, { - "depends_on": "eval: doc.auth_method === \"Basic\"", + "depends_on": "eval: doc.auth_method === \"Basic\" && doc.service != \"Frappe Mail\"", "fieldname": "password", "fieldtype": "Password", "hide_days": 1, @@ -116,7 +124,7 @@ }, { "default": "0", - "depends_on": "eval: doc.auth_method === \"Basic\"", + "depends_on": "eval: doc.auth_method === \"Basic\" && doc.service != \"Frappe Mail\"", "fieldname": "awaiting_password", "fieldtype": "Check", "hide_days": 1, @@ -125,7 +133,7 @@ }, { "default": "0", - "depends_on": "eval: doc.auth_method === \"Basic\"", + "depends_on": "eval: doc.auth_method === \"Basic\" && doc.service != \"Frappe Mail\"", "fieldname": "ascii_encode_password", "fieldtype": "Check", "hide_days": 1, @@ -159,9 +167,10 @@ "hide_days": 1, "hide_seconds": 1, "label": "Service", - "options": "\nGMail\nSendgrid\nSparkPost\nYahoo Mail\nOutlook.com\nYandex.Mail" + "options": "\nFrappe Mail\nGMail\nSendgrid\nSparkPost\nYahoo Mail\nOutlook.com\nYandex.Mail" }, { + "depends_on": "eval: doc.service != \"Frappe Mail\"", "fieldname": "mailbox_settings", "fieldtype": "Section Break", "hide_days": 1, @@ -289,6 +298,7 @@ "mandatory_depends_on": "notify_if_unreplied" }, { + "depends_on": "eval: doc.service != \"Frappe Mail\"", "fieldname": "outgoing_mail_settings", "fieldtype": "Section Break", "hide_days": 1, @@ -621,23 +631,65 @@ "depends_on": "enable_incoming", "fieldname": "incoming_popimap_tab", "fieldtype": "Tab Break", - "label": "Incoming (POP/IMAP)" + "label": "Incoming" + }, + { + "default": "https://frappemail.com", + "depends_on": "eval: doc.service == \"Frappe Mail\"", + "fieldname": "frappe_mail_site", + "fieldtype": "Data", + "label": "Frappe Mail Site", + "mandatory_depends_on": "eval: doc.service == \"Frappe Mail\"" }, { "depends_on": "enable_outgoing", - "fieldname": "outgoing_smtp_tab", + "fieldname": "outgoing_tab", "fieldtype": "Tab Break", - "label": "Outgoing (SMTP)" + "label": "Outgoing" }, { - "fieldname": "column_break_bidn", + "fieldname": "column_break_h5pd", "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_uc6h", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_uynb", + "fieldtype": "Column Break" + }, + { + "depends_on": "eval: doc.service == \"Frappe Mail\"", + "fieldname": "last_synced_at", + "fieldtype": "Datetime", + "label": "Last Synced At" + }, + { + "depends_on": "eval: (doc.service == \"Frappe Mail\" && doc.auth_method != \"Basic\" && !doc.__islocal && !doc.__unsaved)", + "fieldname": "validate_frappe_mail_settings", + "fieldtype": "Button", + "label": "Validate Frappe Mail Settings" + }, + { + "depends_on": "eval: doc.service == \"Frappe Mail\" && doc.auth_method == \"Basic\"", + "fieldname": "api_key", + "fieldtype": "Data", + "label": "API Key", + "mandatory_depends_on": "eval: doc.service == \"Frappe Mail\" && doc.auth_method == \"Basic\"" + }, + { + "depends_on": "eval: doc.service == \"Frappe Mail\" && doc.auth_method == \"Basic\"", + "fieldname": "api_secret", + "fieldtype": "Password", + "label": "API Secret", + "mandatory_depends_on": "eval: doc.service == \"Frappe Mail\" && doc.auth_method == \"Basic\"" } ], "icon": "fa fa-inbox", "index_web_pages_for_search": 1, "links": [], - "modified": "2024-04-17 14:46:38.836631", + "modified": "2024-06-28 08:45:43.565934", "modified_by": "Administrator", "module": "Email", "name": "Email Account", diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 3078c09b0a..bffccfd07f 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -12,6 +12,7 @@ import frappe from frappe import _, are_emails_muted, safe_encode from frappe.desk.form import assign_to from frappe.email.doctype.email_domain.email_domain import EMAIL_DOMAIN_FIELDS +from frappe.email.frappemail import FrappeMail from frappe.email.receive import EmailServer, InboundMail, SentEmailInInboxError from frappe.email.smtp import SMTPServer from frappe.email.utils import get_port @@ -61,6 +62,8 @@ class EmailAccount(Document): add_signature: DF.Check always_use_account_email_id_as_sender: DF.Check always_use_account_name_as_sender_name: DF.Check + api_key: DF.Data | None + api_secret: DF.Password | None append_emails_to_sent_folder: DF.Check append_to: DF.Link | None ascii_encode_password: DF.Check @@ -84,9 +87,11 @@ class EmailAccount(Document): enable_incoming: DF.Check enable_outgoing: DF.Check footer: DF.TextEditor | None + frappe_mail_site: DF.Data | None imap_folder: DF.Table[IMAPFolder] incoming_port: DF.Data | None initial_sync_count: DF.Literal["100", "250", "500"] + last_synced_at: DF.Datetime | None login_id: DF.Data | None login_id_is_different: DF.Check no_failed: DF.Int @@ -96,13 +101,7 @@ class EmailAccount(Document): send_notification_to: DF.SmallText | None send_unsubscribe_message: DF.Check service: DF.Literal[ - "", - "GMail", - "Sendgrid", - "SparkPost", - "Yahoo Mail", - "Outlook.com", - "Yandex.Mail", + "", "Frappe Mail", "GMail", "Sendgrid", "SparkPost", "Yahoo Mail", "Outlook.com", "Yandex.Mail" ] signature: DF.TextEditor | None smtp_port: DF.Data | None @@ -142,6 +141,13 @@ class EmailAccount(Document): else: self.login_id = None + if self.service == "Frappe Mail": + self.use_imap = 0 + self.always_use_account_email_id_as_sender = 1 + + if self.auth_method == "Basic" or self.get_oauth_token(): + self.validate_frappe_mail_settings() + # validate the imap settings if self.enable_incoming and self.use_imap and len(self.imap_folder) <= 0: frappe.throw(_("You need to set one IMAP folder for {0}").format(frappe.bold(self.email_id))) @@ -158,7 +164,11 @@ class EmailAccount(Document): self.awaiting_password = 0 self.password = None - if not frappe.local.flags.in_install and not self.awaiting_password: + if ( + not frappe.local.flags.in_install + and not self.awaiting_password + and not self.service == "Frappe Mail" + ): if validate_oauth or self.password or self.smtp_server in ("127.0.0.1", "localhost"): if self.enable_incoming: self.get_incoming_server() @@ -184,6 +194,12 @@ class EmailAccount(Document): if folder.append_to not in valid_doctypes: frappe.throw(_("Append To can be one of {0}").format(comma_or(valid_doctypes))) + @frappe.whitelist() + def validate_frappe_mail_settings(self): + if self.service == "Frappe Mail": + frappe_mail_client = self.get_frappe_mail_client() + frappe_mail_client.validate(for_inbound=self.enable_incoming, for_outbound=self.enable_outgoing) + def validate_smtp_conn(self): if not self.smtp_server: frappe.throw(_("SMTP Server is required")) @@ -476,9 +492,11 @@ class EmailAccount(Document): return account_details - def sendmail_config(self): + def get_access_token(self) -> str | None: oauth_token = self.get_oauth_token() + return oauth_token.get_password("access_token") if oauth_token else None + def sendmail_config(self): return { "email_account": self.name, "server": self.smtp_server, @@ -488,7 +506,7 @@ class EmailAccount(Document): "use_ssl": cint(self.use_ssl_for_outgoing), "use_tls": cint(self.use_tls), "use_oauth": self.auth_method == "OAuth", - "access_token": oauth_token.get_password("access_token") if oauth_token else None, + "access_token": self.get_access_token(), } def get_smtp_server(self): @@ -504,6 +522,26 @@ class EmailAccount(Document): config = self.sendmail_config() return SMTPServer(**config) + def get_frappe_mail_client(self): + return self._frappe_mail_client + + @functools.cached_property + def _frappe_mail_client(self): + if self.auth_method == "OAuth": + if access_token := self.get_access_token(): + return FrappeMail(self.frappe_mail_site, self.email_id, access_token=access_token) + + frappe.throw( + _("Please Authorize OAuth for Email Account {0}").format( + frappe.bold(self.email_account_name) + ), + title=_("Frappe Mail OAuth Error"), + ) + else: + return FrappeMail( + self.frappe_mail_site, self.email_id, self.api_key, self.get_password("api_secret") + ) + def remove_unpicklable_values(self, state): super().remove_unpicklable_values(state) state.pop("_smtp_server_instance", None) @@ -594,25 +632,33 @@ class EmailAccount(Document): if not self.enable_incoming: return [] - email_sync_rule = self.build_email_sync_rule() try: - email_server = self.get_incoming_server(in_receive=True, email_sync_rule=email_sync_rule) - if self.use_imap: - # process all given imap folder - for folder in self.imap_folder: - if email_server.select_imap_folder(folder.folder_name): - email_server.settings["uid_validity"] = folder.uidvalidity - messages = email_server.get_messages(folder=f'"{folder.folder_name}"') or {} - process_mail(messages, folder.append_to) - else: - # process the pop3 account - messages = email_server.get_messages() or {} + if self.service == "Frappe Mail": + frappe_mail_client = self.get_frappe_mail_client() + messages = frappe_mail_client.pull_raw(last_synced_at=self.last_synced_at) process_mail(messages) - # close connection to mailserver - email_server.logout() + self.db_set("last_synced_at", messages["last_synced_at"], update_modified=False) + else: + email_sync_rule = self.build_email_sync_rule() + email_server = self.get_incoming_server(in_receive=True, email_sync_rule=email_sync_rule) + if self.use_imap: + # process all given imap folder + for folder in self.imap_folder: + if email_server.select_imap_folder(folder.folder_name): + email_server.settings["uid_validity"] = folder.uidvalidity + messages = email_server.get_messages(folder=f'"{folder.folder_name}"') or {} + process_mail(messages, folder.append_to) + else: + # process the pop3 account + messages = email_server.get_messages() or {} + process_mail(messages) + + # close connection to mailserver + email_server.logout() except Exception: self.log_error(title=_("Error while connecting to email account {0}").format(self.name)) return [] + return mails def handle_bad_emails(self, uid, raw, reason): diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index bb568b2658..dbf4ba68ad 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -14,6 +14,7 @@ from frappe.core.utils import html2text from frappe.database.database import savepoint from frappe.email.doctype.email_account.email_account import EmailAccount from frappe.email.email_body import add_attachment, get_email, get_formatted_html +from frappe.email.frappemail import FrappeMail from frappe.email.queue import get_unsubcribed_url, get_unsubscribe_message from frappe.email.smtp import SMTPServer from frappe.model.document import Document @@ -153,13 +154,13 @@ class EmailQueue(Document): return True - def send(self, smtp_server_instance: SMTPServer = None): + def send(self, smtp_server_instance: SMTPServer = None, frappe_mail_client: FrappeMail = None): """Send emails to recipients.""" if not self.can_send_now(): return - with SendMailContext(self, smtp_server_instance) as ctx: - ctx.fetch_smtp_server() + with SendMailContext(self, smtp_server_instance, frappe_mail_client) as ctx: + ctx.fetch_outgoing_server() message = None for recipient in self.recipients: if recipient.is_mail_sent(): @@ -168,8 +169,14 @@ class EmailQueue(Document): message = ctx.build_message(recipient.recipient) if method := get_hook_method("override_email_send"): method(self, self.sender, recipient.recipient, message) - else: - if not frappe.flags.in_test or frappe.flags.testing_email: + elif not frappe.flags.in_test or frappe.flags.testing_email: + if ctx.email_account_doc.service == "Frappe Mail": + ctx.frappe_mail_client.send_raw( + sender=self.sender, + recipients=recipient.recipient, + message=message.decode("utf-8"), + ) + else: ctx.smtp_server.session.sendmail( from_addr=self.sender, to_addrs=recipient.recipient, @@ -231,17 +238,23 @@ class SendMailContext: self, queue_doc: Document, smtp_server_instance: SMTPServer = None, + frappe_mail_client: FrappeMail = None, ): self.queue_doc: EmailQueue = queue_doc self.smtp_server: SMTPServer = smtp_server_instance + self.frappe_mail_client: FrappeMail = frappe_mail_client self.sent_to_atleast_one_recipient = any( rec.recipient for rec in self.queue_doc.recipients if rec.is_mail_sent() ) self.email_account_doc = None - def fetch_smtp_server(self): + def fetch_outgoing_server(self): self.email_account_doc = self.queue_doc.get_email_account(raise_error=True) - if not self.smtp_server: + + if self.email_account_doc.service == "Frappe Mail": + if not self.frappe_mail_client: + self.frappe_mail_client = self.email_account_doc.get_frappe_mail_client() + elif not self.smtp_server: self.smtp_server = self.email_account_doc.get_smtp_server() def __enter__(self): @@ -751,16 +764,21 @@ class QueueBuilder: def send_emails(self, queue_data, final_recipients): # This is used to bulk send emails from same sender to multiple recipients separately # This re-uses smtp server instance to minimize the cost of new session creation + frappe_mail_client = None smtp_server_instance = None for r in final_recipients: recipients = list(set([r, *self.final_cc(), *self.bcc])) q = EmailQueue.new({**queue_data, **{"recipients": recipients}}, ignore_permissions=True) - if not smtp_server_instance: + if not frappe_mail_client and not smtp_server_instance: email_account = q.get_email_account(raise_error=True) - smtp_server_instance = email_account.get_smtp_server() + + if email_account.service == "Frappe Mail": + frappe_mail_client = email_account.get_frappe_mail_client() + else: + smtp_server_instance = email_account.get_smtp_server() with suppress(Exception): - q.send(smtp_server_instance=smtp_server_instance) + q.send(smtp_server_instance=smtp_server_instance, frappe_mail_client=frappe_mail_client) smtp_server_instance.quit() diff --git a/frappe/email/doctype/notification/notification.js b/frappe/email/doctype/notification/notification.js index b88d10ea0d..bede0b429b 100644 --- a/frappe/email/doctype/notification/notification.js +++ b/frappe/email/doctype/notification/notification.js @@ -1,6 +1,8 @@ // Copyright (c) 2018, Frappe Technologies and contributors // For license information, please see license.txt +const DATE_BASED_EVENTS = ["Days Before", "Days After"]; + frappe.notification = { setup_fieldname_select: function (frm) { // get the doctype to update fields @@ -129,6 +131,8 @@ Last comment: {{ comments[-1].comment }} by {{ comments[-1].by }} frappe.ui.form.on("Notification", { onload: function (frm) { frm.set_query("document_type", function () { + if (DATE_BASED_EVENTS.includes(frm.doc.event)) return; + return { filters: { istable: 0, @@ -166,23 +170,23 @@ frappe.ui.form.on("Notification", { frappe.set_route("Form", "Customize Form"); }, event: function (frm) { - if (["Days Before", "Days After"].includes(frm.doc.event)) { - frm.add_custom_button(__("Get Alerts for Today"), function () { - frappe.call({ - method: "frappe.email.doctype.notification.notification.get_documents_for_today", - args: { - notification: frm.doc.name, - }, - callback: function (r) { - if (r.message && r.message.length > 0) { - frappe.msgprint(r.message.toString()); - } else { - frappe.msgprint(__("No alerts for today")); - } - }, - }); + if (!DATE_BASED_EVENTS.includes(frm.doc.event) || frm.is_new()) return; + + frm.add_custom_button(__("Get Alerts for Today"), function () { + frappe.call({ + method: "frappe.email.doctype.notification.notification.get_documents_for_today", + args: { + notification: frm.doc.name, + }, + callback: function (r) { + if (r.message && r.message.length > 0) { + frappe.msgprint(r.message.toString()); + } else { + frappe.msgprint(__("No alerts for today")); + } + }, }); - } + }); }, channel: function (frm) { frm.toggle_reqd("recipients", frm.doc.channel == "Email"); diff --git a/frappe/email/doctype/notification/notification.json b/frappe/email/doctype/notification/notification.json index b50c8d8468..c05ea05b01 100644 --- a/frappe/email/doctype/notification/notification.json +++ b/frappe/email/doctype/notification/notification.json @@ -8,16 +8,16 @@ "engine": "InnoDB", "field_order": [ "enabled", + "is_standard", + "module", "column_break_2", "channel", "slack_webhook_url", "filters", "subject", - "document_type", - "is_standard", - "module", - "col_break_1", "event", + "document_type", + "col_break_1", "method", "date_changed", "days_in_advance", @@ -119,7 +119,6 @@ "fieldtype": "Column Break" }, { - "depends_on": "eval: doc.document_type", "fieldname": "event", "fieldtype": "Select", "in_list_view": 1, @@ -292,7 +291,7 @@ "icon": "fa fa-envelope", "index_web_pages_for_search": 1, "links": [], - "modified": "2024-06-17 04:03:22.591781", + "modified": "2024-07-04 05:53:40.595130", "modified_by": "Administrator", "module": "Email", "name": "Notification", @@ -315,4 +314,4 @@ "states": [], "title_field": "subject", "track_changes": 1 -} +} \ No newline at end of file diff --git a/frappe/email/doctype/notification/notification.py b/frappe/email/doctype/notification/notification.py index 72c95cf194..c9e9f44a53 100644 --- a/frappe/email/doctype/notification/notification.py +++ b/frappe/email/doctype/notification/notification.py @@ -18,6 +18,8 @@ from frappe.utils.jinja import validate_template from frappe.utils.safe_exec import get_safe_globals FORMATS = {"HTML": ".html", "Markdown": ".md", "Plain Text": ".txt"} +FORBIDDEN_DOCUMENT_TYPES = frozenset(("Email Queue",)) +DATE_BASED_EVENTS = frozenset(("Days Before", "Days After")) class Notification(Document): @@ -27,9 +29,7 @@ class Notification(Document): from typing import TYPE_CHECKING if TYPE_CHECKING: - from frappe.email.doctype.notification_recipient.notification_recipient import ( - NotificationRecipient, - ) + from frappe.email.doctype.notification_recipient.notification_recipient import NotificationRecipient from frappe.types import DF attach_print: DF.Check @@ -90,7 +90,7 @@ class Notification(Document): if self.event == "Value Change" and not self.value_changed: frappe.throw(_("Please specify which value field must be checked")) - self.validate_forbidden_types() + self.validate_forbidden_document_types() self.validate_condition() self.validate_standard() frappe.cache.hdel("notifications", self.document_type) @@ -130,12 +130,16 @@ def get_context(context): except Exception: frappe.throw(_("The Condition '{0}' is invalid").format(self.condition)) - def validate_forbidden_types(self): - forbidden_document_types = ("Email Queue",) - if self.document_type in forbidden_document_types or frappe.get_meta(self.document_type).istable: - # currently notifications don't work on child tables as events are not fired for each record of child table - - frappe.throw(_("Cannot set Notification on Document Type {0}").format(self.document_type)) + def validate_forbidden_document_types(self): + if self.document_type in FORBIDDEN_DOCUMENT_TYPES or ( + frappe.get_meta(self.document_type).istable and self.event not in DATE_BASED_EVENTS + ): + # only date based events are allowed for child tables + frappe.throw( + _("Cannot set Notification with event {0} on Document Type {1}").format( + _(self.event), _(self.document_type) + ) + ) def get_documents_for_today(self): """get list of documents that will be triggered today""" @@ -237,8 +241,8 @@ def get_context(context): notification_doc = { "type": "Alert", - "document_type": doc.doctype, - "document_name": doc.name, + "document_type": get_reference_doctype(doc), + "document_name": get_reference_name(doc), "subject": subject, "from_user": doc.modified_by or doc.owner, "email_content": frappe.render_template(self.message, context), @@ -270,8 +274,8 @@ def get_context(context): # No need to add if it is already a communication. if doc.doctype != "Communication": communication = make_communication( - doctype=doc.doctype, - name=doc.name, + doctype=get_reference_doctype(doc), + name=get_reference_name(doc), content=message, subject=subject, sender=sender, @@ -294,8 +298,8 @@ def get_context(context): cc=cc, bcc=bcc, message=message, - reference_doctype=doc.doctype, - reference_name=doc.name, + reference_doctype=get_reference_doctype(doc), + reference_name=get_reference_name(doc), attachments=attachments, expose_recipients="header", print_letterhead=((attachments and attachments[0].get("print_letterhead")) or False), @@ -306,8 +310,8 @@ def get_context(context): send_slack_message( webhook_url=self.slack_webhook_url, message=frappe.render_template(self.message, context), - reference_doctype=doc.doctype, - reference_name=doc.name, + reference_doctype=get_reference_doctype(doc), + reference_name=get_reference_name(doc), ) def send_sms(self, doc, context): @@ -543,3 +547,11 @@ def get_emails_from_template(template, context): emails = frappe.render_template(template, context) if "{" in template else template return filter(None, emails.replace(",", "\n").split("\n")) + + +def get_reference_doctype(doc): + return doc.parenttype if doc.meta.istable else doc.doctype + + +def get_reference_name(doc): + return doc.parent if doc.meta.istable else doc.name diff --git a/frappe/email/frappemail.py b/frappe/email/frappemail.py new file mode 100644 index 0000000000..e9d792aae6 --- /dev/null +++ b/frappe/email/frappemail.py @@ -0,0 +1,140 @@ +from datetime import datetime +from typing import TYPE_CHECKING +from urllib.parse import urljoin + +import pytz + +import frappe +from frappe import _ +from frappe.frappeclient import FrappeClient, FrappeOAuth2Client +from frappe.utils import convert_utc_to_system_timezone, get_datetime, get_datetime_str, get_system_timezone + +if TYPE_CHECKING: + from requests import Response + + +class FrappeMail: + """Class to interact with the Frappe Mail API.""" + + def __init__( + self, + site: str, + mailbox: str, + api_key: str | None = None, + api_secret: str | None = None, + access_token: str | None = None, + ) -> None: + self.site = site + self.mailbox = mailbox + self.api_key = api_key + self.api_secret = api_secret + self.access_token = access_token + + @staticmethod + def get_client( + site: str, + mailbox: str, + api_key: str | None = None, + api_secret: str | None = None, + access_token: str | None = None, + ) -> FrappeClient | FrappeOAuth2Client: + """Returns a FrappeClient or FrappeOAuth2Client instance.""" + + if hasattr(frappe.local, "frappe_mail_clients"): + if client := frappe.local.frappe_mail_clients.get(mailbox): + return client + else: + frappe.local.frappe_mail_clients = {} + + client = ( + FrappeOAuth2Client(url=site, access_token=access_token) + if access_token + else FrappeClient(url=site, api_key=api_key, api_secret=api_secret) + ) + frappe.local.frappe_mail_clients[mailbox] = client + + return client + + def request( + self, + method: str, + endpoint: str, + params: dict | None = None, + data: dict | None = None, + json: dict | None = None, + headers: dict[str, str] | None = None, + timeout: int | tuple[int, int] = (60, 120), + raise_exception: bool = True, + ) -> "Response": + """Makes a HTTP request to the Frappe Mail API.""" + + url = urljoin(self.site, endpoint) + client = self.get_client(self.site, self.mailbox, self.api_key, self.api_secret, self.access_token) + + headers = headers or {} + headers.update(client.headers) + + response = client.session.request( + method=method, url=url, params=params, data=data, json=json, headers=headers, timeout=timeout + ) + + if not response.ok and raise_exception: + error_msg = response.text + if response.status_code == 401: + if self.access_token: + error_msg = _("Authentication Error: Reauthorize OAuth for Email Account {0}.").format( + frappe.bold(self.mailbox) + ) + else: + error_msg = _("Authentication Error: Invalid API Key or Secret") + + frappe.throw(title=_("Frappe Mail"), msg=error_msg) + + return response + + def validate(self, for_outbound: bool = False, for_inbound: bool = False) -> None: + """Validates the mailbox for inbound and outbound emails.""" + + endpoint = "auth/validate" + data = {"mailbox": self.mailbox, "for_outbound": for_outbound, "for_inbound": for_inbound} + response = self.request("POST", endpoint=endpoint, data=data, raise_exception=False) + + if not response.ok: + if error_msg := response.json().get("exception"): + if error_msg == "frappe.exceptions.AuthenticationError": + error_msg += ": Invalid API Key or Secret" + + frappe.throw(title="Frappe Mail", msg=error_msg) + + def send_raw(self, sender: str, recipients: str, message: str) -> None: + """Sends an email using the Frappe Mail API.""" + + endpoint = "outbound/send-raw" + json_data = {"from": sender, "to": recipients, "raw_message": message} + self.request("POST", endpoint=endpoint, json=json_data) + + def pull_raw(self, limit: int = 50, last_synced_at: str | None = None) -> dict[str, list[str] | str]: + """Pulls emails from the mailbox using the Frappe Mail API.""" + + endpoint = "inbound/pull-raw" + if last_synced_at: + last_synced_at = convert_to_utc(last_synced_at) + + data = {"mailbox": self.mailbox, "limit": limit, "last_synced_at": last_synced_at} + headers = {"X-Site": frappe.utils.get_url()} + response = self.request("GET", endpoint=endpoint, data=data, headers=headers).json()["message"] + last_synced_at = convert_utc_to_system_timezone(get_datetime(response["last_synced_at"])) + + return {"latest_messages": response["mails"], "last_synced_at": last_synced_at} + + +def convert_to_utc(date_time: datetime | str, from_timezone: str | None = None) -> str: + """Converts datetime to UTC timezone.""" + + dt = ( + pytz.timezone(from_timezone or get_system_timezone()) + .localize(get_datetime(date_time)) + .astimezone(pytz.utc) + ) + + return get_datetime_str(dt) diff --git a/frappe/geo/country_info.json b/frappe/geo/country_info.json index 1e4d4fa443..163f7fd9c0 100644 --- a/frappe/geo/country_info.json +++ b/frappe/geo/country_info.json @@ -2731,18 +2731,6 @@ ], "isd": "+216" }, - "Turkey": { - "code": "tr", - "currency": "TRY", - "currency_fraction": "Kuru\u015f", - "currency_fraction_units": 100, - "currency_symbol": "\u20ba", - "number_format": "#.###,##", - "timezones": [ - "Europe/Istanbul" - ], - "isd": "+90" - }, "Turkmenistan": { "code": "tm", "currency": "TMM", @@ -2774,6 +2762,18 @@ "Pacific/Funafuti" ], "isd": "+688" + }, + "T\u00fcrkiye": { + "code": "tr", + "currency": "TRY", + "currency_fraction": "Kuru\u015f", + "currency_fraction_units": 100, + "currency_symbol": "\u20ba", + "number_format": "#.###,##", + "timezones": [ + "Europe/Istanbul" + ], + "isd": "+90" }, "Uganda": { "code": "ug", diff --git a/frappe/integrations/doctype/connected_app/connected_app.json b/frappe/integrations/doctype/connected_app/connected_app.json index 201f161120..9fc63cd520 100644 --- a/frappe/integrations/doctype/connected_app/connected_app.json +++ b/frappe/integrations/doctype/connected_app/connected_app.json @@ -139,7 +139,7 @@ "link_fieldname": "connected_app" } ], - "modified": "2024-03-23 16:01:30.633764", + "modified": "2024-07-05 08:24:50.182706", "modified_by": "Administrator", "module": "Integrations", "name": "Connected App", @@ -162,6 +162,7 @@ "role": "All" } ], + "show_title_field_in_link": 1, "sort_field": "creation", "sort_order": "DESC", "states": [], diff --git a/frappe/locale/eo.po b/frappe/locale/eo.po index 8305c8614a..7bd6eb076f 100644 --- a/frappe/locale/eo.po +++ b/frappe/locale/eo.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" -"POT-Creation-Date: 2024-06-30 09:33+0000\n" -"PO-Revision-Date: 2024-07-02 15:49\n" +"POT-Creation-Date: 2024-07-07 09:33+0000\n" +"PO-Revision-Date: 2024-07-10 16:24\n" "Last-Translator: developers@frappe.io\n" "Language-Team: Esperanto\n" "MIME-Version: 1.0\n" @@ -1003,8 +1003,8 @@ msgid "Add Child" msgstr "crwdns90826:0crwdne90826:0" #: public/js/frappe/views/kanban/kanban_board.html:4 -#: public/js/frappe/views/reports/query_report.js:1696 -#: public/js/frappe/views/reports/query_report.js:1699 +#: public/js/frappe/views/reports/query_report.js:1681 +#: public/js/frappe/views/reports/query_report.js:1684 #: public/js/frappe/views/reports/report_view.js:324 #: public/js/frappe/views/reports/report_view.js:349 msgid "Add Column" @@ -3719,6 +3719,7 @@ msgstr "crwdns128570:0crwdne128570:0" #. Name of a DocType #: desk/doctype/calendar_view/calendar_view.json +#: public/js/frappe/list/base_list.js:208 msgid "Calendar View" msgstr "crwdns91974:0crwdne91974:0" @@ -3895,7 +3896,7 @@ msgstr "crwdns92056:0crwdne92056:0" msgid "Cannot Remove" msgstr "crwdns92058:0crwdne92058:0" -#: model/base_document.py:1072 +#: model/base_document.py:1073 msgid "Cannot Update After Submit" msgstr "crwdns92060:0crwdne92060:0" @@ -3983,7 +3984,7 @@ msgstr "crwdns92100:0{0}crwdne92100:0" msgid "Cannot delete {0}" msgstr "crwdns92102:0{0}crwdne92102:0" -#: utils/nestedset.py:296 +#: utils/nestedset.py:299 msgid "Cannot delete {0} as it has child nodes" msgstr "crwdns92104:0{0}crwdne92104:0" @@ -3991,7 +3992,7 @@ msgstr "crwdns92104:0{0}crwdne92104:0" msgid "Cannot edit Standard Dashboards" msgstr "crwdns92106:0crwdne92106:0" -#: email/doctype/notification/notification.py:121 +#: email/doctype/notification/notification.py:122 msgid "Cannot edit Standard Notification. To edit, please disable this and duplicate it" msgstr "crwdns92108:0crwdne92108:0" @@ -4060,7 +4061,7 @@ msgstr "crwdns92136:0crwdne92136:0" msgid "Cannot set 'Report' permission if 'Only If Creator' permission is set" msgstr "crwdns110830:0crwdne110830:0" -#: email/doctype/notification/notification.py:137 +#: email/doctype/notification/notification.py:138 msgid "Cannot set Notification on Document Type {0}" msgstr "crwdns92138:0{0}crwdne92138:0" @@ -4234,6 +4235,8 @@ msgstr "crwdns128610:0crwdne128610:0" #. Label of the chart_name (Link) field in DocType 'Workspace Chart' #: desk/doctype/dashboard_chart/dashboard_chart.json #: desk/doctype/workspace_chart/workspace_chart.json +#: public/js/frappe/views/reports/query_report.js:289 +#: public/js/frappe/widgets/widget_dialog.js:137 msgid "Chart Name" msgstr "crwdns128612:0crwdne128612:0" @@ -4650,7 +4653,7 @@ msgctxt "Shrink code field." msgid "Collapse" msgstr "crwdns92402:0crwdne92402:0" -#: public/js/frappe/views/reports/query_report.js:1979 +#: public/js/frappe/views/reports/query_report.js:1964 #: public/js/frappe/views/treeview.js:121 msgid "Collapse All" msgstr "crwdns92404:0crwdne92404:0" @@ -6179,6 +6182,10 @@ msgstr "crwdns128842:0crwdne128842:0" msgid "Dashboard Settings" msgstr "crwdns93118:0crwdne93118:0" +#: public/js/frappe/list/base_list.js:205 +msgid "Dashboard View" +msgstr "crwdns142844:0crwdne142844:0" + #. Label of the tab_break_2 (Tab Break) field in DocType 'Workspace' #: desk/doctype/workspace/workspace.json msgid "Dashboards" @@ -6760,7 +6767,8 @@ msgid "Department" msgstr "crwdns128922:0crwdne128922:0" #. Label of the dependencies (Data) field in DocType 'Workspace Link' -#: desk/doctype/workspace_link/workspace_link.json www/attribution.html:29 +#: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:318 www/attribution.html:29 msgid "Dependencies" msgstr "crwdns112688:0crwdne112688:0" @@ -7219,6 +7227,7 @@ msgstr "crwdns93582:0{0}crwdne93582:0" #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: integrations/doctype/webhook/webhook.json #: printing/doctype/print_format/print_format.json +#: public/js/frappe/widgets/widget_dialog.js:164 #: website/doctype/website_slideshow/website_slideshow.js:18 msgid "DocType" msgstr "crwdns93584:0crwdne93584:0" @@ -7277,6 +7286,7 @@ msgstr "crwdns93632:0crwdne93632:0" #. Label of the doc_view (Select) field in DocType 'Workspace Shortcut' #: desk/doctype/workspace_shortcut/workspace_shortcut.json +#: public/js/frappe/widgets/widget_dialog.js:477 msgid "DocType View" msgstr "crwdns128992:0crwdne128992:0" @@ -7800,7 +7810,7 @@ msgstr "crwdns129042:0crwdne129042:0" msgid "Download Your Data" msgstr "crwdns93896:0crwdne93896:0" -#: contacts/doctype/contact/contact.js:93 +#: contacts/doctype/contact/contact.js:98 msgid "Download vCard" msgstr "crwdns140790:0crwdne140790:0" @@ -7988,7 +7998,7 @@ msgstr "crwdns93972:0crwdne93972:0" #: public/js/frappe/form/templates/contact_list.html:7 #: public/js/frappe/form/toolbar.js:681 #: public/js/frappe/views/reports/query_report.js:815 -#: public/js/frappe/views/reports/query_report.js:1649 +#: public/js/frappe/views/reports/query_report.js:1634 #: public/js/frappe/views/workspace/workspace.js:460 #: public/js/frappe/views/workspace/workspace.js:816 #: public/js/frappe/widgets/base_widget.js:64 @@ -8965,9 +8975,9 @@ msgstr "crwdns94422:0crwdne94422:0" msgid "Error in Header/Footer Script" msgstr "crwdns110924:0crwdne110924:0" -#: email/doctype/notification/notification.py:394 -#: email/doctype/notification/notification.py:510 -#: email/doctype/notification/notification.py:516 +#: email/doctype/notification/notification.py:395 +#: email/doctype/notification/notification.py:511 +#: email/doctype/notification/notification.py:517 msgid "Error in Notification" msgstr "crwdns94424:0crwdne94424:0" @@ -8979,7 +8989,7 @@ msgstr "crwdns94426:0{0}crwdnd94426:0{1}crwdne94426:0" msgid "Error while connecting to email account {0}" msgstr "crwdns94428:0{0}crwdne94428:0" -#: email/doctype/notification/notification.py:507 +#: email/doctype/notification/notification.py:508 msgid "Error while evaluating Notification {0}. Please fix your template." msgstr "crwdns94430:0{0}crwdne94430:0" @@ -9136,7 +9146,7 @@ msgstr "crwdns94494:0crwdne94494:0" msgid "Executing..." msgstr "crwdns94496:0crwdne94496:0" -#: public/js/frappe/views/reports/query_report.js:1993 +#: public/js/frappe/views/reports/query_report.js:1978 msgid "Execution Time: {0} sec" msgstr "crwdns94498:0{0}crwdne94498:0" @@ -9154,7 +9164,7 @@ msgctxt "Enlarge code field." msgid "Expand" msgstr "crwdns94504:0crwdne94504:0" -#: public/js/frappe/views/reports/query_report.js:1979 +#: public/js/frappe/views/reports/query_report.js:1964 #: public/js/frappe/views/treeview.js:125 msgid "Expand All" msgstr "crwdns94506:0crwdne94506:0" @@ -9210,7 +9220,7 @@ msgstr "crwdns129232:0crwdne129232:0" #: core/doctype/docperm/docperm.json core/doctype/recorder/recorder_list.js:37 #: public/js/frappe/data_import/data_exporter.js:91 #: public/js/frappe/data_import/data_exporter.js:242 -#: public/js/frappe/views/reports/query_report.js:1684 +#: public/js/frappe/views/reports/query_report.js:1669 #: public/js/frappe/views/reports/report_view.js:1550 msgid "Export" msgstr "crwdns94526:0crwdne94526:0" @@ -9551,7 +9561,7 @@ msgstr "crwdns94660:0crwdne94660:0" #: public/js/frappe/list/bulk_operations.js:297 #: public/js/frappe/list/list_view_permission_restrictions.html:3 #: public/js/frappe/views/reports/query_report.js:236 -#: public/js/frappe/views/reports/query_report.js:1738 +#: public/js/frappe/views/reports/query_report.js:1723 #: website/doctype/web_form_field/web_form_field.json #: website/doctype/web_form_list_column/web_form_list_column.json msgid "Field" @@ -9859,7 +9869,7 @@ msgstr "crwdns94824:0crwdne94824:0" #: desk/doctype/number_card/number_card.js:205 #: desk/doctype/number_card/number_card.js:336 #: email/doctype/auto_email_report/auto_email_report.js:90 -#: public/js/frappe/list/base_list.js:882 +#: public/js/frappe/list/base_list.js:890 #: public/js/frappe/ui/filters/filter_list.js:134 #: website/doctype/web_form/web_form.js:197 msgid "Filter" @@ -10295,7 +10305,7 @@ msgstr "crwdns95024:0crwdne95024:0" msgid "For Value" msgstr "crwdns129392:0crwdne129392:0" -#: public/js/frappe/views/reports/query_report.js:1990 +#: public/js/frappe/views/reports/query_report.js:1975 #: public/js/frappe/views/reports/report_view.js:96 msgid "For comparison, use >5, <10 or =324. For ranges, use 5:10 (for values between 5 & 10)." msgstr "crwdns95034:0crwdne95034:0" @@ -10542,7 +10552,7 @@ msgstr "crwdns95156:0crwdne95156:0" msgid "From Date Field" msgstr "crwdns129430:0crwdne129430:0" -#: public/js/frappe/views/reports/query_report.js:1704 +#: public/js/frappe/views/reports/query_report.js:1689 msgid "From Document Type" msgstr "crwdns95162:0crwdne95162:0" @@ -10638,6 +10648,10 @@ msgstr "crwdns129446:0crwdne129446:0" msgid "Gantt" msgstr "crwdns95208:0crwdne95208:0" +#: public/js/frappe/list/base_list.js:206 +msgid "Gantt View" +msgstr "crwdns142846:0crwdne142846:0" + #. Label of the gender (Link) field in DocType 'Contact' #. Name of a DocType #. Label of the gender (Data) field in DocType 'Gender' @@ -12009,6 +12023,10 @@ msgstr "crwdns129686:0crwdne129686:0" msgid "Image Link" msgstr "crwdns129688:0crwdne129688:0" +#: public/js/frappe/list/base_list.js:209 +msgid "Image View" +msgstr "crwdns142848:0crwdne142848:0" + #. Label of the image_width (Float) field in DocType 'Letter Head' #. Label of the footer_image_width (Float) field in DocType 'Letter Head' #: printing/doctype/letter_head/letter_head.json @@ -12280,6 +12298,10 @@ msgstr "crwdns95966:0crwdne95966:0" msgid "Inbox User" msgstr "crwdns95970:0crwdne95970:0" +#: public/js/frappe/list/base_list.js:210 +msgid "Inbox View" +msgstr "crwdns142850:0crwdne142850:0" + #. Label of the include_name_field (Check) field in DocType 'Form Tour' #: desk/doctype/form_tour/form_tour.json msgid "Include Name Field" @@ -12299,11 +12321,11 @@ msgstr "crwdns95976:0crwdne95976:0" msgid "Include Web View Link in Email" msgstr "crwdns129732:0crwdne129732:0" -#: public/js/frappe/views/reports/query_report.js:1521 +#: public/js/frappe/views/reports/query_report.js:1506 msgid "Include filters" msgstr "crwdns95980:0crwdne95980:0" -#: public/js/frappe/views/reports/query_report.js:1513 +#: public/js/frappe/views/reports/query_report.js:1498 msgid "Include indentation" msgstr "crwdns95982:0crwdne95982:0" @@ -12459,7 +12481,7 @@ msgstr "crwdns110970:0crwdne110970:0" #. Label of the insert_after (Select) field in DocType 'Custom Field' #: custom/doctype/custom_field/custom_field.json -#: public/js/frappe/views/reports/query_report.js:1744 +#: public/js/frappe/views/reports/query_report.js:1729 msgid "Insert After" msgstr "crwdns96046:0crwdne96046:0" @@ -12666,7 +12688,7 @@ msgstr "crwdns96132:0{0}crwdne96132:0" msgid "Invalid \"mandatory_depends_on\" expression" msgstr "crwdns96134:0crwdne96134:0" -#: utils/nestedset.py:177 +#: utils/nestedset.py:178 msgid "Invalid Action" msgstr "crwdns96136:0crwdne96136:0" @@ -13037,6 +13059,7 @@ msgstr "crwdns96308:0crwdne96308:0" #. Label of the is_query_report (Check) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:336 msgid "Is Query Report" msgstr "crwdns129828:0crwdne129828:0" @@ -13140,7 +13163,7 @@ msgstr "crwdns129850:0crwdne129850:0" msgid "Item Type" msgstr "crwdns129852:0crwdne129852:0" -#: utils/nestedset.py:228 +#: utils/nestedset.py:229 msgid "Item cannot be added to its own descendants" msgstr "crwdns96372:0crwdne96372:0" @@ -13265,6 +13288,7 @@ msgstr "crwdns129880:0crwdne129880:0" #. Label of the kanban_board (Link) field in DocType 'Workspace Shortcut' #: desk/doctype/kanban_board/kanban_board.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json +#: public/js/frappe/widgets/widget_dialog.js:509 msgid "Kanban Board" msgstr "crwdns96432:0crwdne96432:0" @@ -13284,6 +13308,10 @@ msgctxt "Button in kanban view menu" msgid "Kanban Settings" msgstr "crwdns96444:0crwdne96444:0" +#: public/js/frappe/list/base_list.js:207 +msgid "Kanban View" +msgstr "crwdns142852:0crwdne142852:0" + #. Description of a DocType #: core/doctype/activity_log/activity_log.json msgid "Keep track of all update feeds" @@ -13529,7 +13557,10 @@ msgstr "crwdns96524:0{0}crwdne96524:0" #: desk/doctype/workspace_quick_list/workspace_quick_list.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: printing/page/print_format_builder/print_format_builder.js:474 +#: public/js/frappe/widgets/widget_dialog.js:187 #: public/js/frappe/widgets/widget_dialog.js:255 +#: public/js/frappe/widgets/widget_dialog.js:304 +#: public/js/frappe/widgets/widget_dialog.js:421 #: public/js/frappe/widgets/widget_dialog.js:645 #: public/js/frappe/widgets/widget_dialog.js:678 #: templates/form_grid/fields.html:37 @@ -14096,6 +14127,8 @@ msgstr "crwdns130038:0crwdne130038:0" #. Label of the link_to (Dynamic Link) field in DocType 'Workspace Shortcut' #: desk/doctype/workspace_link/workspace_link.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json +#: public/js/frappe/widgets/widget_dialog.js:285 +#: public/js/frappe/widgets/widget_dialog.js:430 msgid "Link To" msgstr "crwdns130040:0crwdne130040:0" @@ -14105,6 +14138,7 @@ msgstr "crwdns110990:0crwdne110990:0" #. Label of the link_type (Select) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:277 msgid "Link Type" msgstr "crwdns130042:0crwdne130042:0" @@ -14148,7 +14182,7 @@ msgstr "crwdns96840:0crwdne96840:0" #. Label of the links (Table) field in DocType 'Customize Form' #. Label of the links (Table) field in DocType 'Workspace' #: contacts/doctype/address/address.js:39 contacts/doctype/address/address.json -#: contacts/doctype/contact/contact.js:87 contacts/doctype/contact/contact.json +#: contacts/doctype/contact/contact.js:92 contacts/doctype/contact/contact.json #: core/doctype/doctype/doctype.json #: custom/doctype/customize_form/customize_form.json #: desk/doctype/workspace/workspace.json public/js/frappe/form/toolbar.js:377 @@ -14201,6 +14235,10 @@ msgctxt "Button in list view menu" msgid "List Settings" msgstr "crwdns96868:0crwdne96868:0" +#: public/js/frappe/list/base_list.js:203 +msgid "List View" +msgstr "crwdns142854:0crwdne142854:0" + #. Name of a DocType #: desk/doctype/list_view_settings/list_view_settings.json msgid "List View Settings" @@ -14237,7 +14275,7 @@ msgstr "crwdns96884:0crwdne96884:0" msgid "Load Balancing" msgstr "crwdns130066:0crwdne130066:0" -#: public/js/frappe/list/base_list.js:378 +#: public/js/frappe/list/base_list.js:386 #: website/doctype/blog_post/templates/blog_post_list.html:50 #: website/doctype/help_article/templates/help_article_list.html:30 msgid "Load More" @@ -14251,7 +14289,7 @@ msgstr "crwdns96890:0crwdne96890:0" #: core/page/permission_manager/permission_manager.js:165 #: public/js/frappe/form/controls/multicheck.js:13 #: public/js/frappe/form/linked_with.js:13 -#: public/js/frappe/list/base_list.js:490 +#: public/js/frappe/list/base_list.js:498 #: public/js/frappe/list/list_view.js:335 public/js/frappe/ui/listing.html:16 #: public/js/frappe/views/reports/query_report.js:1017 msgid "Loading" @@ -14279,7 +14317,7 @@ msgstr "crwdns110996:0crwdne110996:0" #: public/js/frappe/views/kanban/kanban_board.html:11 #: public/js/frappe/widgets/chart_widget.js:50 #: public/js/frappe/widgets/number_card_widget.js:174 -#: public/js/frappe/widgets/quick_list_widget.js:126 +#: public/js/frappe/widgets/quick_list_widget.js:128 msgid "Loading..." msgstr "crwdns96898:0crwdne96898:0" @@ -14664,6 +14702,10 @@ msgstr "crwdns130124:0crwdne130124:0" msgid "Map Columns" msgstr "crwdns97072:0crwdne97072:0" +#: public/js/frappe/list/base_list.js:212 +msgid "Map View" +msgstr "crwdns142856:0crwdne142856:0" + #: public/js/frappe/data_import/import_preview.js:290 msgid "Map columns from {0} to fields in {1}" msgstr "crwdns111002:0{0}crwdnd111002:0{1}crwdne111002:0" @@ -14893,7 +14935,7 @@ msgstr "crwdns97168:0crwdne97168:0" msgid "Merge with existing" msgstr "crwdns97170:0crwdne97170:0" -#: utils/nestedset.py:304 +#: utils/nestedset.py:307 msgid "Merging is only possible between Group-to-Group or Leaf Node-to-Leaf Node" msgstr "crwdns97172:0crwdne97172:0" @@ -15049,6 +15091,10 @@ msgstr "crwdns97252:0crwdne97252:0" msgid "Method" msgstr "crwdns130200:0crwdne130200:0" +#: __init__.py:936 +msgid "Method Not Allowed" +msgstr "crwdns142858:0crwdne142858:0" + #: desk/doctype/number_card/number_card.py:70 msgid "Method is required to create a number card" msgstr "crwdns97266:0crwdne97266:0" @@ -15440,7 +15486,7 @@ msgstr "crwdns130234:0crwdne130234:0" msgid "Mozilla doesn't support :has() so you can pass parent selector here as workaround" msgstr "crwdns130236:0crwdne130236:0" -#: utils/nestedset.py:328 +#: utils/nestedset.py:331 msgid "Multiple root nodes not allowed." msgstr "crwdns97478:0crwdne97478:0" @@ -15674,7 +15720,7 @@ msgstr "crwdns97574:0crwdne97574:0" msgid "Negative Value" msgstr "crwdns97576:0crwdne97576:0" -#: utils/nestedset.py:93 +#: utils/nestedset.py:94 msgid "Nested set error. Please contact the Administrator." msgstr "crwdns97578:0crwdne97578:0" @@ -16021,7 +16067,7 @@ msgstr "crwdns130294:0crwdne130294:0" #: public/js/form_builder/utils.js:341 #: public/js/frappe/form/controls/link.js:475 #: public/js/frappe/list/list_sidebar_group_by.js:223 -#: public/js/frappe/views/reports/query_report.js:1541 +#: public/js/frappe/views/reports/query_report.js:1526 #: website/doctype/help_article/templates/help_article.html:26 msgid "No" msgstr "crwdns97696:0crwdne97696:0" @@ -16065,7 +16111,7 @@ msgstr "crwdns97718:0crwdne97718:0" msgid "No Data to Show" msgstr "crwdns111038:0crwdne111038:0" -#: public/js/frappe/widgets/quick_list_widget.js:131 +#: public/js/frappe/widgets/quick_list_widget.js:133 msgid "No Data..." msgstr "crwdns111040:0crwdne111040:0" @@ -16532,7 +16578,7 @@ msgstr "crwdns97892:0crwdne97892:0" msgid "Not allowed for {0}: {1}" msgstr "crwdns97894:0{0}crwdnd97894:0{1}crwdne97894:0" -#: email/doctype/notification/notification.py:391 +#: email/doctype/notification/notification.py:392 msgid "Not allowed to attach {0} document, please enable Allow Print For {0} in Print Settings" msgstr "crwdns97896:0{0}crwdnd97896:0{0}crwdne97896:0" @@ -16651,7 +16697,7 @@ msgstr "crwdns97940:0crwdne97940:0" msgid "Nothing left to undo" msgstr "crwdns97942:0crwdne97942:0" -#: public/js/frappe/list/base_list.js:362 +#: public/js/frappe/list/base_list.js:370 #: public/js/frappe/views/reports/query_report.js:105 #: templates/includes/list/list.html:7 #: website/doctype/blog_post/templates/blog_post_list.html:41 @@ -17057,9 +17103,14 @@ msgstr "crwdns111096:0{0}crwdnd111096:0{1}crwdne111096:0" #. Label of the onboard (Check) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:330 msgid "Onboard" msgstr "crwdns130402:0crwdne130402:0" +#: public/js/frappe/widgets/widget_dialog.js:236 +msgid "Onboarding Name" +msgstr "crwdns142860:0crwdne142860:0" + #. Name of a DocType #: desk/doctype/onboarding_permission/onboarding_permission.json msgid "Onboarding Permission" @@ -17167,6 +17218,7 @@ msgstr "crwdns127690:0crwdne127690:0" #. Label of the only_for (Link) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:323 msgid "Only for" msgstr "crwdns130412:0crwdne130412:0" @@ -17516,7 +17568,7 @@ msgstr "crwdns130460:0crwdne130460:0" #: printing/page/print/print.js:71 #: public/js/frappe/form/templates/print_layout.html:44 -#: public/js/frappe/views/reports/query_report.js:1669 +#: public/js/frappe/views/reports/query_report.js:1654 msgid "PDF" msgstr "crwdns98288:0crwdne98288:0" @@ -17908,8 +17960,8 @@ msgid "Password not found for {0} {1} {2}" msgstr "crwdns98464:0{0}crwdnd98464:0{1}crwdnd98464:0{2}crwdne98464:0" #: core/doctype/user/user.py:1021 -msgid "Password reset instructions have been sent to your email" -msgstr "crwdns98466:0crwdne98466:0" +msgid "Password reset instructions have been sent to {}'s email" +msgstr "crwdns142862:0crwdne142862:0" #: www/update-password.html:164 msgid "Password set" @@ -18308,7 +18360,7 @@ msgstr "crwdns98646:0crwdne98646:0" msgid "Please check the filter values set for Dashboard Chart: {}" msgstr "crwdns98648:0crwdne98648:0" -#: model/base_document.py:872 +#: model/base_document.py:873 msgid "Please check the value of \"Fetch From\" set for field {0}" msgstr "crwdns98650:0{0}crwdne98650:0" @@ -18610,11 +18662,11 @@ msgstr "crwdns98790:0crwdne98790:0" msgid "Please specify a valid parent DocType for {0}" msgstr "crwdns98792:0{0}crwdne98792:0" -#: email/doctype/notification/notification.py:87 +#: email/doctype/notification/notification.py:88 msgid "Please specify which date field must be checked" msgstr "crwdns98794:0crwdne98794:0" -#: email/doctype/notification/notification.py:90 +#: email/doctype/notification/notification.py:91 msgid "Please specify which value field must be checked" msgstr "crwdns98796:0crwdne98796:0" @@ -18947,7 +18999,7 @@ msgstr "crwdns112704:0{0}crwdne112704:0" #: public/js/frappe/form/templates/print_layout.html:46 #: public/js/frappe/form/toolbar.js:332 public/js/frappe/form/toolbar.js:344 #: public/js/frappe/list/bulk_operations.js:87 -#: public/js/frappe/views/reports/query_report.js:1655 +#: public/js/frappe/views/reports/query_report.js:1640 #: public/js/frappe/views/reports/report_view.js:1460 #: public/js/frappe/views/treeview.js:469 www/printview.html:18 msgid "Print" @@ -19809,7 +19861,7 @@ msgstr "crwdns99328:0crwdne99328:0" msgid "Rebuild Tree" msgstr "crwdns99330:0crwdne99330:0" -#: utils/nestedset.py:176 +#: utils/nestedset.py:177 msgid "Rebuilding of tree is not supported for {}" msgstr "crwdns99332:0crwdne99332:0" @@ -20167,7 +20219,7 @@ msgstr "crwdns99526:0crwdne99526:0" #: public/js/frappe/desk.js:533 public/js/frappe/form/form.js:1196 #: public/js/frappe/form/templates/print_layout.html:6 #: public/js/frappe/list/base_list.js:66 -#: public/js/frappe/views/reports/query_report.js:1644 +#: public/js/frappe/views/reports/query_report.js:1629 #: public/js/frappe/views/treeview.js:475 #: public/js/frappe/widgets/chart_widget.js:290 #: public/js/frappe/widgets/number_card_widget.js:324 @@ -20265,7 +20317,7 @@ msgstr "crwdns99566:0crwdne99566:0" msgid "Reload File" msgstr "crwdns111162:0crwdne111162:0" -#: public/js/frappe/list/base_list.js:242 +#: public/js/frappe/list/base_list.js:250 msgid "Reload List" msgstr "crwdns99568:0crwdne99568:0" @@ -20534,7 +20586,7 @@ msgstr "crwdns99694:0crwdne99694:0" #: core/doctype/report/report.json #: desk/doctype/dashboard_chart/dashboard_chart.json #: desk/doctype/number_card/number_card.json -#: public/js/frappe/views/reports/query_report.js:1825 +#: public/js/frappe/views/reports/query_report.js:1810 msgid "Report Name" msgstr "crwdns99696:0crwdne99696:0" @@ -20557,6 +20609,10 @@ msgstr "crwdns130836:0crwdne130836:0" msgid "Report Type" msgstr "crwdns130838:0crwdne130838:0" +#: public/js/frappe/list/base_list.js:204 +msgid "Report View" +msgstr "crwdns142864:0crwdne142864:0" + #: core/doctype/doctype/doctype.py:1780 msgid "Report cannot be set for Single types" msgstr "crwdns99718:0crwdne99718:0" @@ -20591,7 +20647,7 @@ msgstr "crwdns99730:0crwdne99730:0" msgid "Report was not saved (there were errors)" msgstr "crwdns99732:0crwdne99732:0" -#: public/js/frappe/views/reports/query_report.js:1863 +#: public/js/frappe/views/reports/query_report.js:1848 msgid "Report with more than 10 columns looks better in Landscape mode." msgstr "crwdns99734:0crwdne99734:0" @@ -21177,7 +21233,7 @@ msgstr "crwdns130922:0crwdne130922:0" msgid "Roles can be set for users from their User page." msgstr "crwdns111176:0crwdne111176:0" -#: utils/nestedset.py:277 +#: utils/nestedset.py:280 msgid "Root {0} cannot be deleted" msgstr "crwdns100012:0{0}crwdne100012:0" @@ -21250,7 +21306,7 @@ msgstr "crwdns111178:0crwdne111178:0" msgid "Row # {0}: Non administrator user can not set the role {1} to the custom doctype" msgstr "crwdns100056:0{0}crwdnd100056:0{1}crwdne100056:0" -#: model/base_document.py:903 +#: model/base_document.py:904 msgid "Row #{0}:" msgstr "crwdns100058:0#{0}crwdne100058:0" @@ -21534,11 +21590,11 @@ msgstr "crwdns130978:0crwdne130978:0" #: public/js/frappe/views/kanban/kanban_settings.js:45 #: public/js/frappe/views/kanban/kanban_settings.js:189 #: public/js/frappe/views/kanban/kanban_view.js:343 -#: public/js/frappe/views/reports/query_report.js:1817 +#: public/js/frappe/views/reports/query_report.js:1802 #: public/js/frappe/views/reports/report_view.js:1640 #: public/js/frappe/views/workspace/workspace.js:501 #: public/js/frappe/widgets/base_widget.js:142 -#: public/js/frappe/widgets/quick_list_widget.js:117 +#: public/js/frappe/widgets/quick_list_widget.js:119 #: public/js/print_format_builder/print_format_builder.bundle.js:15 #: public/js/workflow_builder/workflow_builder.bundle.js:33 msgid "Save" @@ -21565,7 +21621,7 @@ msgstr "crwdns100180:0crwdne100180:0" msgid "Save Filter" msgstr "crwdns111194:0crwdne111194:0" -#: public/js/frappe/views/reports/query_report.js:1820 +#: public/js/frappe/views/reports/query_report.js:1805 msgid "Save Report" msgstr "crwdns100182:0crwdne100182:0" @@ -22689,7 +22745,7 @@ msgid "Set Filters" msgstr "crwdns100696:0crwdne100696:0" #: public/js/frappe/widgets/chart_widget.js:395 -#: public/js/frappe/widgets/quick_list_widget.js:102 +#: public/js/frappe/widgets/quick_list_widget.js:104 msgid "Set Filters for {0}" msgstr "crwdns100698:0{0}crwdne100698:0" @@ -22902,7 +22958,7 @@ msgstr "crwdns111218:0crwdne111218:0" msgid "Setup Approval Workflows" msgstr "crwdns100772:0crwdne100772:0" -#: public/js/frappe/views/reports/query_report.js:1690 +#: public/js/frappe/views/reports/query_report.js:1675 #: public/js/frappe/views/reports/report_view.js:1618 msgid "Setup Auto Email" msgstr "crwdns100774:0crwdne100774:0" @@ -24936,7 +24992,7 @@ msgid "The Client ID obtained from the Google Cloud Console under " msgstr "crwdns131442:0crwdne131442:0" -#: email/doctype/notification/notification.py:130 +#: email/doctype/notification/notification.py:131 msgid "The Condition '{0}' is invalid" msgstr "crwdns101636:0{0}crwdne101636:0" @@ -25390,7 +25446,7 @@ msgstr "crwdns131482:0crwdne131482:0" msgid "This goes above the slideshow." msgstr "crwdns131484:0crwdne131484:0" -#: public/js/frappe/views/reports/query_report.js:2027 +#: public/js/frappe/views/reports/query_report.js:2012 msgid "This is a background report. Please set the appropriate filters and then generate a new one." msgstr "crwdns101812:0crwdne101812:0" @@ -26249,6 +26305,10 @@ msgstr "crwdns131624:0crwdne131624:0" msgid "Tree" msgstr "crwdns131626:0crwdne131626:0" +#: public/js/frappe/list/base_list.js:211 +msgid "Tree View" +msgstr "crwdns142866:0crwdne142866:0" + #. Description of the 'Is Tree' (Check) field in DocType 'DocType' #: core/doctype/doctype/doctype.json msgid "Tree structures are implemented using Nested Set" @@ -26354,6 +26414,7 @@ msgstr "crwdns131640:0crwdne131640:0" #: desk/doctype/workspace_link/workspace_link.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: public/js/frappe/views/file/file_view.js:337 +#: public/js/frappe/widgets/widget_dialog.js:399 #: social/doctype/energy_point_log/energy_point_log.json #: website/doctype/web_template/web_template.json www/attribution.html:35 msgid "Type" @@ -26435,6 +26496,7 @@ msgstr "crwdns131652:0crwdne131652:0" #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: integrations/doctype/integration_request/integration_request.json #: integrations/doctype/webhook_request_log/webhook_request_log.json +#: public/js/frappe/widgets/widget_dialog.js:469 #: website/doctype/top_bar_item/top_bar_item.json #: website/doctype/website_slideshow_item/website_slideshow_item.json msgid "URL" @@ -27111,7 +27173,7 @@ msgid "User Permission" msgstr "crwdns102624:0crwdne102624:0" #: core/page/permission_manager/permission_manager_help.html:30 -#: public/js/frappe/views/reports/query_report.js:1804 +#: public/js/frappe/views/reports/query_report.js:1789 #: public/js/frappe/views/reports/report_view.js:1666 msgid "User Permissions" msgstr "crwdns102628:0crwdne102628:0" @@ -27429,7 +27491,7 @@ msgstr "crwdns131784:0crwdne131784:0" msgid "Value To Be Set" msgstr "crwdns131786:0crwdne131786:0" -#: model/base_document.py:965 model/document.py:682 +#: model/base_document.py:966 model/document.py:682 msgid "Value cannot be changed for {0}" msgstr "crwdns102750:0{0}crwdne102750:0" @@ -27472,7 +27534,7 @@ msgstr "crwdns102766:0{0}crwdne102766:0" msgid "Value to Validate" msgstr "crwdns131790:0crwdne131790:0" -#: model/base_document.py:1035 +#: model/base_document.py:1036 msgid "Value too big" msgstr "crwdns102770:0crwdne102770:0" @@ -27571,7 +27633,7 @@ msgid "View Full Log" msgstr "crwdns111324:0crwdne111324:0" #: public/js/frappe/views/treeview.js:463 -#: public/js/frappe/widgets/quick_list_widget.js:245 +#: public/js/frappe/widgets/quick_list_widget.js:247 msgid "View List" msgstr "crwdns102808:0crwdne102808:0" @@ -28453,7 +28515,7 @@ msgstr "crwdns127790:0crwdne127790:0" msgid "Write" msgstr "crwdns131894:0crwdne131894:0" -#: model/base_document.py:875 +#: model/base_document.py:876 msgid "Wrong Fetch From value" msgstr "crwdns103194:0crwdne103194:0" @@ -28540,7 +28602,7 @@ msgstr "crwdns131908:0crwdne131908:0" #: public/js/form_builder/utils.js:336 #: public/js/frappe/form/controls/link.js:475 #: public/js/frappe/list/list_sidebar_group_by.js:223 -#: public/js/frappe/views/reports/query_report.js:1541 +#: public/js/frappe/views/reports/query_report.js:1526 #: website/doctype/help_article/templates/help_article.html:25 msgid "Yes" msgstr "crwdns103238:0crwdne103238:0" @@ -29753,7 +29815,7 @@ msgstr "crwdns104008:0crwdne104008:0" msgid "via Google Meet" msgstr "crwdns132068:0crwdne132068:0" -#: email/doctype/notification/notification.py:215 +#: email/doctype/notification/notification.py:216 msgid "via Notification" msgstr "crwdns104012:0crwdne104012:0" @@ -29896,7 +29958,7 @@ msgstr "crwdns104080:0{0}crwdne104080:0" msgid "{0} Name" msgstr "crwdns104082:0{0}crwdne104082:0" -#: model/base_document.py:1065 +#: model/base_document.py:1066 msgid "{0} Not allowed to change {1} after submission from {2} to {3}" msgstr "crwdns104084:0{0}crwdnd104084:0{1}crwdnd104084:0{2}crwdnd104084:0{3}crwdne104084:0" @@ -29922,10 +29984,6 @@ msgstr "crwdns104088:0{0}crwdne104088:0" msgid "{0} Tree" msgstr "crwdns104090:0{0}crwdne104090:0" -#: public/js/frappe/list/base_list.js:209 -msgid "{0} View" -msgstr "crwdns104092:0{0}crwdne104092:0" - #: public/js/frappe/form/footer/form_timeline.js:126 #: public/js/frappe/form/sidebar/form_sidebar.js:86 msgid "{0} Web page views" @@ -30539,11 +30597,11 @@ msgstr "crwdns104370:0{0}crwdnd104370:0{1}crwdnd104370:0{2}crwdne104370:0" msgid "{0} {1} already exists" msgstr "crwdns104372:0{0}crwdnd104372:0{1}crwdne104372:0" -#: model/base_document.py:908 +#: model/base_document.py:909 msgid "{0} {1} cannot be \"{2}\". It should be one of \"{3}\"" msgstr "crwdns104374:0{0}crwdnd104374:0{1}crwdnd104374:0{2}crwdnd104374:0{3}crwdne104374:0" -#: utils/nestedset.py:337 +#: utils/nestedset.py:340 msgid "{0} {1} cannot be a leaf node as it has children" msgstr "crwdns104376:0{0}crwdnd104376:0{1}crwdne104376:0" @@ -30563,11 +30621,11 @@ msgstr "crwdns104382:0{0}crwdnd104382:0{1}crwdne104382:0" msgid "{0} {1}: Submitted Record cannot be deleted. You must {2} Cancel {3} it first." msgstr "crwdns104384:0{0}crwdnd104384:0{1}crwdnd104384:0{2}crwdnd104384:0{3}crwdne104384:0" -#: model/base_document.py:1026 +#: model/base_document.py:1027 msgid "{0}, Row {1}" msgstr "crwdns104386:0{0}crwdnd104386:0{1}crwdne104386:0" -#: model/base_document.py:1031 +#: model/base_document.py:1032 msgid "{0}: '{1}' ({3}) will get truncated, as max characters allowed is {2}" msgstr "crwdns104388:0{0}crwdnd104388:0{1}crwdnd104388:0{3}crwdnd104388:0{2}crwdne104388:0" @@ -30660,7 +30718,7 @@ msgid "{0}: fieldname cannot be set to reserved keyword {1}" msgstr "crwdns104430:0{0}crwdnd104430:0{1}crwdne104430:0" #: contacts/doctype/address/address.js:35 -#: contacts/doctype/contact/contact.js:83 +#: contacts/doctype/contact/contact.js:88 #: public/js/frappe/views/workspace/workspace.js:170 msgid "{0}: {1}" msgstr "crwdns104432:0{0}crwdnd104432:0{1}crwdne104432:0" diff --git a/frappe/locale/main.pot b/frappe/locale/main.pot index fce323b8bf..a9fbc81610 100644 --- a/frappe/locale/main.pot +++ b/frappe/locale/main.pot @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Frappe Framework VERSION\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" -"POT-Creation-Date: 2024-06-30 09:33+0000\n" -"PO-Revision-Date: 2024-06-30 09:33+0000\n" +"POT-Creation-Date: 2024-07-14 09:33+0000\n" +"PO-Revision-Date: 2024-07-14 09:33+0000\n" "Last-Translator: developers@frappe.io\n" "Language-Team: developers@frappe.io\n" "MIME-Version: 1.0\n" @@ -96,7 +96,7 @@ msgstr "" msgid "'{0}' not allowed for type {1} in row {2}" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:301 +#: public/js/frappe/data_import/data_exporter.js:302 msgid "(Mandatory)" msgstr "" @@ -167,7 +167,7 @@ msgstr "" msgid "1 month ago" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:226 +#: public/js/frappe/data_import/data_exporter.js:227 msgid "1 record will be exported" msgstr "" @@ -692,10 +692,11 @@ msgid "API Endpoint Args" msgstr "" #. Label of the api_key (Data) field in DocType 'User' +#. Label of the api_key (Data) field in DocType 'Email Account' #. Label of the api_key (Data) field in DocType 'Google Settings' #. Label of the sb_01 (Section Break) field in DocType 'Google Settings' #. Label of the api_key (Data) field in DocType 'Push Notification Settings' -#: core/doctype/user/user.json +#: core/doctype/user/user.json email/doctype/email_account/email_account.json #: integrations/doctype/google_settings/google_settings.json #: integrations/doctype/push_notification_settings/push_notification_settings.json msgid "API Key" @@ -718,9 +719,10 @@ msgid "API Method" msgstr "" #. Label of the api_secret (Password) field in DocType 'User' +#. Label of the api_secret (Password) field in DocType 'Email Account' #. Label of the api_secret (Password) field in DocType 'Push Notification #. Settings' -#: core/doctype/user/user.json +#: core/doctype/user/user.json email/doctype/email_account/email_account.json #: integrations/doctype/push_notification_settings/push_notification_settings.json msgid "API Secret" msgstr "" @@ -985,11 +987,6 @@ msgstr "" msgid "Add" msgstr "" -#: public/js/frappe/list/list_view.js:266 -msgctxt "Primary action in list view" -msgid "Add" -msgstr "" - #: public/js/frappe/form/grid_row.js:431 msgid "Add / Remove Columns" msgstr "" @@ -1027,6 +1024,10 @@ msgstr "" msgid "Add Border at Top" msgstr "" +#: desk/doctype/number_card/number_card.js:36 +msgid "Add Card to Dashboard" +msgstr "" + #: public/js/frappe/views/reports/query_report.js:210 msgid "Add Chart to Dashboard" msgstr "" @@ -1036,8 +1037,8 @@ msgid "Add Child" msgstr "" #: public/js/frappe/views/kanban/kanban_board.html:4 -#: public/js/frappe/views/reports/query_report.js:1696 -#: public/js/frappe/views/reports/query_report.js:1699 +#: public/js/frappe/views/reports/query_report.js:1681 +#: public/js/frappe/views/reports/query_report.js:1684 #: public/js/frappe/views/reports/report_view.js:324 #: public/js/frappe/views/reports/report_view.js:349 msgid "Add Column" @@ -1101,7 +1102,7 @@ msgstr "" msgid "Add Review" msgstr "" -#: core/doctype/user/user.py:757 +#: core/doctype/user/user.py:765 msgid "Add Roles" msgstr "" @@ -1134,7 +1135,7 @@ msgstr "" msgid "Add Tags" msgstr "" -#: public/js/frappe/list/list_view.js:1903 +#: public/js/frappe/list/list_view.js:1955 msgctxt "Button in list view actions menu" msgid "Add Tags" msgstr "" @@ -1170,7 +1171,7 @@ msgstr "" msgid "Add a New Role" msgstr "" -#: public/js/frappe/form/form_tour.js:205 +#: public/js/frappe/form/form_tour.js:211 msgid "Add a Row" msgstr "" @@ -1228,6 +1229,11 @@ msgstr "" msgid "Add {0}" msgstr "" +#: public/js/frappe/list/list_view.js:264 +msgctxt "Primary action in list view" +msgid "Add {0}" +msgstr "" + #. Description of the '<head> HTML' (Code) field in DocType 'Website #. Settings' #: website/doctype/website_settings/website_settings.json @@ -1347,11 +1353,11 @@ msgstr "" msgid "Administrator" msgstr "" -#: core/doctype/user/user.py:1161 +#: core/doctype/user/user.py:1169 msgid "Administrator Logged In" msgstr "" -#: core/doctype/user/user.py:1155 +#: core/doctype/user/user.py:1163 msgid "Administrator accessed {0} on {1} via IP Address {2}." msgstr "" @@ -1829,7 +1835,7 @@ msgstr "" msgid "Allowing DocType, DocType. Be careful!" msgstr "" -#: core/doctype/user/user.py:964 +#: core/doctype/user/user.py:972 msgid "Already Registered" msgstr "" @@ -2045,7 +2051,7 @@ msgstr "" msgid "App not found for module: {0}" msgstr "" -#: __init__.py:1794 +#: __init__.py:1800 msgid "App {0} is not installed" msgstr "" @@ -2065,7 +2071,7 @@ msgstr "" msgid "Append To" msgstr "" -#: email/doctype/email_account/email_account.py:185 +#: email/doctype/email_account/email_account.py:195 msgid "Append To can be one of {0}" msgstr "" @@ -2106,7 +2112,7 @@ msgstr "" msgid "Applied On" msgstr "" -#: public/js/frappe/list/list_view.js:1888 +#: public/js/frappe/list/list_view.js:1940 msgctxt "Button in list view actions menu" msgid "Apply Assignment Rule" msgstr "" @@ -2200,7 +2206,7 @@ msgstr "" msgid "Archived Columns" msgstr "" -#: public/js/frappe/list/list_view.js:1867 +#: public/js/frappe/list/list_view.js:1919 msgid "Are you sure you want to clear the assignments?" msgstr "" @@ -2296,7 +2302,7 @@ msgstr "" msgid "Assign To" msgstr "" -#: public/js/frappe/list/list_view.js:1849 +#: public/js/frappe/list/list_view.js:1901 msgctxt "Button in list view actions menu" msgid "Assign To" msgstr "" @@ -2603,7 +2609,15 @@ msgstr "" msgid "Authentication Apps you can use are: " msgstr "" -#: email/doctype/email_account/email_account.py:312 +#: email/frappemail.py:89 +msgid "Authentication Error: Invalid API Key or Secret" +msgstr "" + +#: email/frappemail.py:85 +msgid "Authentication Error: Reauthorize OAuth for Email Account {0}." +msgstr "" + +#: email/doctype/email_account/email_account.py:328 msgid "Authentication failed while receiving emails from Email Account: {0}." msgstr "" @@ -2817,11 +2831,11 @@ msgstr "" msgid "Automatic" msgstr "" -#: email/doctype/email_account/email_account.py:715 +#: email/doctype/email_account/email_account.py:761 msgid "Automatic Linking can be activated only for one Email Account." msgstr "" -#: email/doctype/email_account/email_account.py:709 +#: email/doctype/email_account/email_account.py:755 msgid "Automatic Linking can be activated only if Incoming is enabled." msgstr "" @@ -3753,6 +3767,7 @@ msgstr "" #. Name of a DocType #: desk/doctype/calendar_view/calendar_view.json +#: public/js/frappe/list/base_list.js:208 msgid "Calendar View" msgstr "" @@ -3859,7 +3874,7 @@ msgstr "" msgid "Cancel" msgstr "" -#: public/js/frappe/list/list_view.js:1958 +#: public/js/frappe/list/list_view.js:2010 msgctxt "Button in list view actions menu" msgid "Cancel" msgstr "" @@ -3881,7 +3896,7 @@ msgstr "" msgid "Cancel Scheduling" msgstr "" -#: public/js/frappe/list/list_view.js:1963 +#: public/js/frappe/list/list_view.js:2015 msgctxt "Title of confirmation dialog" msgid "Cancel {0} documents?" msgstr "" @@ -3929,7 +3944,7 @@ msgstr "" msgid "Cannot Remove" msgstr "" -#: model/base_document.py:1072 +#: model/base_document.py:1073 msgid "Cannot Update After Submit" msgstr "" @@ -3981,7 +3996,7 @@ msgstr "" msgid "Cannot delete Home and Attachments folders" msgstr "" -#: model/delete_doc.py:373 +#: model/delete_doc.py:382 msgid "Cannot delete or cancel because {0} {1} is linked with {2} {3} {4}" msgstr "" @@ -4017,7 +4032,7 @@ msgstr "" msgid "Cannot delete {0}" msgstr "" -#: utils/nestedset.py:296 +#: utils/nestedset.py:299 msgid "Cannot delete {0} as it has child nodes" msgstr "" @@ -4025,7 +4040,7 @@ msgstr "" msgid "Cannot edit Standard Dashboards" msgstr "" -#: email/doctype/notification/notification.py:121 +#: email/doctype/notification/notification.py:122 msgid "Cannot edit Standard Notification. To edit, please disable this and duplicate it" msgstr "" @@ -4094,8 +4109,8 @@ msgstr "" msgid "Cannot set 'Report' permission if 'Only If Creator' permission is set" msgstr "" -#: email/doctype/notification/notification.py:137 -msgid "Cannot set Notification on Document Type {0}" +#: email/doctype/notification/notification.py:139 +msgid "Cannot set Notification with event {0} on Document Type {1}" msgstr "" #: core/doctype/docshare/docshare.py:67 @@ -4270,6 +4285,8 @@ msgstr "" #. Label of the chart_name (Link) field in DocType 'Workspace Chart' #: desk/doctype/dashboard_chart/dashboard_chart.json #: desk/doctype/workspace_chart/workspace_chart.json +#: public/js/frappe/views/reports/query_report.js:289 +#: public/js/frappe/widgets/widget_dialog.js:137 msgid "Chart Name" msgstr "" @@ -4442,7 +4459,7 @@ msgstr "" msgid "Clear & Add template" msgstr "" -#: public/js/frappe/list/list_view.js:1864 +#: public/js/frappe/list/list_view.js:1916 msgctxt "Button in list view actions menu" msgid "Clear Assignment" msgstr "" @@ -4541,7 +4558,7 @@ msgstr "" msgid "Click to Set Filters" msgstr "" -#: public/js/frappe/list/list_view.js:680 +#: public/js/frappe/list/list_view.js:677 msgid "Click to sort by {0}" msgstr "" @@ -4621,7 +4638,8 @@ msgid "Client URLs" msgstr "" #: core/doctype/communication/communication.js:39 desk/doctype/todo/todo.js:23 -#: public/js/frappe/ui/messages.js:243 website/js/bootstrap-4.js:24 +#: public/js/frappe/form/form_tour.js:17 public/js/frappe/ui/messages.js:244 +#: website/js/bootstrap-4.js:24 msgid "Close" msgstr "" @@ -4676,7 +4694,7 @@ msgstr "" msgid "Code challenge method" msgstr "" -#: public/js/frappe/form/form_tour.js:270 +#: public/js/frappe/form/form_tour.js:276 #: public/js/frappe/widgets/base_widget.js:159 msgid "Collapse" msgstr "" @@ -4686,7 +4704,7 @@ msgctxt "Shrink code field." msgid "Collapse" msgstr "" -#: public/js/frappe/views/reports/query_report.js:1979 +#: public/js/frappe/views/reports/query_report.js:1964 #: public/js/frappe/views/treeview.js:121 msgid "Collapse All" msgstr "" @@ -4978,7 +4996,7 @@ msgstr "" msgid "Complete By" msgstr "" -#: core/doctype/user/user.py:426 templates/emails/new_user.html:10 +#: core/doctype/user/user.py:425 templates/emails/new_user.html:10 msgid "Complete Registration" msgstr "" @@ -5543,7 +5561,7 @@ msgstr "" msgid "Create New" msgstr "" -#: public/js/frappe/list/list_view.js:487 +#: public/js/frappe/list/list_view.js:484 msgctxt "Create a new document from list view" msgid "Create New" msgstr "" @@ -5583,7 +5601,7 @@ msgstr "" #: public/js/frappe/form/controls/link.js:295 #: public/js/frappe/form/controls/link.js:297 #: public/js/frappe/form/link_selector.js:139 -#: public/js/frappe/list/list_view.js:476 +#: public/js/frappe/list/list_view.js:473 #: public/js/frappe/web_form/web_form_list.js:225 msgid "Create a new {0}" msgstr "" @@ -5610,7 +5628,7 @@ msgstr "" msgid "Create or Edit Workflow" msgstr "" -#: public/js/frappe/list/list_view.js:479 +#: public/js/frappe/list/list_view.js:476 msgid "Create your first {0}" msgstr "" @@ -5641,7 +5659,7 @@ msgid "Created Custom Field {0} in {1}" msgstr "" #: desk/doctype/dashboard_chart/dashboard_chart.js:241 -#: email/doctype/notification/notification.js:30 model/meta.py:46 +#: email/doctype/notification/notification.js:32 model/meta.py:46 #: public/js/frappe/model/meta.js:198 public/js/frappe/model/model.js:125 #: public/js/frappe/views/dashboard/dashboard_view.js:478 msgid "Created On" @@ -6011,7 +6029,7 @@ msgstr "" msgid "Customize" msgstr "" -#: public/js/frappe/list/list_view.js:1709 +#: public/js/frappe/list/list_view.js:1761 msgctxt "Button in list view menu" msgid "Customize" msgstr "" @@ -6026,6 +6044,7 @@ msgstr "" #. Name of a DocType #: automation/doctype/auto_repeat/auto_repeat.js:33 +#: core/doctype/doctype/doctype.js:65 #: custom/doctype/customize_form/customize_form.json #: public/js/frappe/views/kanban/kanban_view.js:343 msgid "Customize Form" @@ -6218,6 +6237,10 @@ msgstr "" msgid "Dashboard Settings" msgstr "" +#: public/js/frappe/list/base_list.js:205 +msgid "Dashboard View" +msgstr "" + #. Label of the tab_break_2 (Tab Break) field in DocType 'Workspace' #: desk/doctype/workspace/workspace.json msgid "Dashboards" @@ -6252,7 +6275,7 @@ msgstr "" msgid "Data" msgstr "" -#: public/js/frappe/form/controls/data.js:58 +#: public/js/frappe/form/controls/data.js:59 msgid "Data Clipped" msgstr "" @@ -6357,6 +6380,7 @@ msgstr "" #. Trail' #: core/doctype/audit_trail/audit_trail.json #: desk/page/leaderboard/leaderboard.js:165 +#: public/js/frappe/widgets/chart_widget.js:237 msgid "Date Range" msgstr "" @@ -6490,7 +6514,7 @@ msgstr "" #. Label of the default_incoming (Check) field in DocType 'Email Account' #: email/doctype/email_account/email_account.json -#: email/doctype/email_account/email_account.py:201 +#: email/doctype/email_account/email_account.py:217 msgid "Default Incoming" msgstr "" @@ -6510,7 +6534,7 @@ msgstr "" #. Label of the default_outgoing (Check) field in DocType 'Email Account' #: email/doctype/email_account/email_account.json -#: email/doctype/email_account/email_account.py:209 +#: email/doctype/email_account/email_account.py:225 msgid "Default Outgoing" msgstr "" @@ -6625,7 +6649,7 @@ msgstr "" msgid "Defaults" msgstr "" -#: email/doctype/email_account/email_account.py:220 +#: email/doctype/email_account/email_account.py:236 msgid "Defaults Updated" msgstr "" @@ -6661,7 +6685,7 @@ msgstr "" msgid "Delete" msgstr "" -#: public/js/frappe/list/list_view.js:1926 +#: public/js/frappe/list/list_view.js:1978 msgctxt "Button in list view actions menu" msgid "Delete" msgstr "" @@ -6698,12 +6722,12 @@ msgstr "" msgid "Delete this record to allow sending to this email address" msgstr "" -#: public/js/frappe/list/list_view.js:1931 +#: public/js/frappe/list/list_view.js:1983 msgctxt "Title of confirmation dialog" msgid "Delete {0} item permanently?" msgstr "" -#: public/js/frappe/list/list_view.js:1937 +#: public/js/frappe/list/list_view.js:1989 msgctxt "Title of confirmation dialog" msgid "Delete {0} items permanently?" msgstr "" @@ -6799,7 +6823,8 @@ msgid "Department" msgstr "" #. Label of the dependencies (Data) field in DocType 'Workspace Link' -#: desk/doctype/workspace_link/workspace_link.json www/attribution.html:29 +#: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:318 www/attribution.html:29 msgid "Dependencies" msgstr "" @@ -7089,7 +7114,7 @@ msgstr "" msgid "Disabled" msgstr "" -#: email/doctype/email_account/email_account.js:232 +#: email/doctype/email_account/email_account.js:261 msgid "Disabled Auto Reply" msgstr "" @@ -7259,6 +7284,7 @@ msgstr "" #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: integrations/doctype/webhook/webhook.json #: printing/doctype/print_format/print_format.json +#: public/js/frappe/widgets/widget_dialog.js:164 #: website/doctype/website_slideshow/website_slideshow.js:18 msgid "DocType" msgstr "" @@ -7317,6 +7343,7 @@ msgstr "" #. Label of the doc_view (Select) field in DocType 'Workspace Shortcut' #: desk/doctype/workspace_shortcut/workspace_shortcut.json +#: public/js/frappe/widgets/widget_dialog.js:477 msgid "DocType View" msgstr "" @@ -7468,7 +7495,7 @@ msgstr "" #: core/doctype/user_permission/user_permission_list.js:36 #: core/doctype/version/version.json desk/doctype/tag_link/tag_link.json #: email/doctype/document_follow/document_follow.json -#: public/js/frappe/form/form_tour.js:60 +#: public/js/frappe/form/form_tour.js:62 msgid "Document Name" msgstr "" @@ -7652,15 +7679,15 @@ msgstr "" msgid "Document Unlocked" msgstr "" -#: public/js/frappe/list/list_view.js:1081 +#: public/js/frappe/list/list_view.js:1116 msgid "Document has been cancelled" msgstr "" -#: public/js/frappe/list/list_view.js:1080 +#: public/js/frappe/list/list_view.js:1115 msgid "Document has been submitted" msgstr "" -#: public/js/frappe/list/list_view.js:1079 +#: public/js/frappe/list/list_view.js:1114 msgid "Document is in draft state" msgstr "" @@ -7783,7 +7810,7 @@ msgstr "" msgid "Don't have an account?" msgstr "" -#: public/js/frappe/ui/messages.js:231 +#: public/js/frappe/form/form_tour.js:16 public/js/frappe/ui/messages.js:231 #: public/js/onboarding_tours/onboarding_tours.js:17 msgid "Done" msgstr "" @@ -7840,7 +7867,7 @@ msgstr "" msgid "Download Your Data" msgstr "" -#: contacts/doctype/contact/contact.js:93 +#: contacts/doctype/contact/contact.js:98 msgid "Download vCard" msgstr "" @@ -8028,11 +8055,11 @@ msgstr "" #: public/js/frappe/form/templates/contact_list.html:7 #: public/js/frappe/form/toolbar.js:681 #: public/js/frappe/views/reports/query_report.js:815 -#: public/js/frappe/views/reports/query_report.js:1649 +#: public/js/frappe/views/reports/query_report.js:1634 #: public/js/frappe/views/workspace/workspace.js:460 #: public/js/frappe/views/workspace/workspace.js:816 #: public/js/frappe/widgets/base_widget.js:64 -#: public/js/frappe/widgets/chart_widget.js:298 +#: public/js/frappe/widgets/chart_widget.js:299 #: public/js/frappe/widgets/number_card_widget.js:331 #: templates/discussions/reply_card.html:29 #: templates/discussions/reply_section.html:29 @@ -8041,7 +8068,7 @@ msgstr "" msgid "Edit" msgstr "" -#: public/js/frappe/list/list_view.js:2012 +#: public/js/frappe/list/list_view.js:2064 msgctxt "Button in list view actions menu" msgid "Edit" msgstr "" @@ -8071,7 +8098,7 @@ msgstr "" msgid "Edit DocType" msgstr "" -#: public/js/frappe/list/list_view.js:1736 +#: public/js/frappe/list/list_view.js:1788 msgctxt "Button in list view menu" msgid "Edit DocType" msgstr "" @@ -8264,7 +8291,7 @@ msgctxt "Email Account" msgid "Email Account" msgstr "" -#: email/doctype/email_account/email_account.py:316 +#: email/doctype/email_account/email_account.py:332 msgid "Email Account Disabled." msgstr "" @@ -8273,7 +8300,7 @@ msgstr "" msgid "Email Account Name" msgstr "" -#: core/doctype/user/user.py:690 +#: core/doctype/user/user.py:698 msgid "Email Account added multiple times" msgstr "" @@ -8569,7 +8596,7 @@ msgstr "" #. Label of the enable_incoming (Check) field in DocType 'Email Account' #: email/doctype/email_account/email_account.json -#: email/doctype/email_account/email_account.py:202 +#: email/doctype/email_account/email_account.py:218 msgid "Enable Incoming" msgstr "" @@ -8582,7 +8609,7 @@ msgstr "" #. Label of the enable_outgoing (Check) field in DocType 'Email Account' #: core/doctype/user_email/user_email.json #: email/doctype/email_account/email_account.json -#: email/doctype/email_account/email_account.py:210 +#: email/doctype/email_account/email_account.py:226 msgid "Enable Outgoing" msgstr "" @@ -8723,7 +8750,7 @@ msgstr "" msgid "Enabled Scheduler" msgstr "" -#: email/doctype/email_account/email_account.py:936 +#: email/doctype/email_account/email_account.py:982 msgid "Enabled email inbox for user {0}" msgstr "" @@ -8736,7 +8763,7 @@ msgstr "" msgid "Enables Calendar and Gantt views." msgstr "" -#: email/doctype/email_account/email_account.js:227 +#: email/doctype/email_account/email_account.js:256 msgid "Enabling auto reply on an incoming email account will send automated replies to all the synchronized emails. Do you wish to continue?" msgstr "" @@ -8844,6 +8871,8 @@ msgstr "" #. 'Notification Settings' #: desk/doctype/notification_settings/notification_settings.json #: desk/page/user_profile/user_profile.html:28 +#: desk/page/user_profile/user_profile_controller.js:80 +#: desk/page/user_profile/user_profile_controller.js:114 #: desk/page/user_profile/user_profile_controller.js:402 #: templates/emails/energy_points_summary.html:39 msgid "Energy Points" @@ -8884,7 +8913,7 @@ msgctxt "Title of prompt dialog" msgid "Enter Value" msgstr "" -#: public/js/frappe/form/form_tour.js:58 +#: public/js/frappe/form/form_tour.js:60 msgid "Enter a name for this {0}" msgstr "" @@ -8915,7 +8944,7 @@ msgstr "" msgid "Enter url parameter for receiver nos" msgstr "" -#: public/js/frappe/ui/messages.js:332 +#: public/js/frappe/ui/messages.js:334 msgid "Enter your password" msgstr "" @@ -9006,9 +9035,9 @@ msgstr "" msgid "Error in Header/Footer Script" msgstr "" -#: email/doctype/notification/notification.py:394 -#: email/doctype/notification/notification.py:510 -#: email/doctype/notification/notification.py:516 +#: email/doctype/notification/notification.py:399 +#: email/doctype/notification/notification.py:515 +#: email/doctype/notification/notification.py:521 msgid "Error in Notification" msgstr "" @@ -9016,11 +9045,11 @@ msgstr "" msgid "Error in print format on line {0}: {1}" msgstr "" -#: email/doctype/email_account/email_account.py:614 +#: email/doctype/email_account/email_account.py:659 msgid "Error while connecting to email account {0}" msgstr "" -#: email/doctype/notification/notification.py:507 +#: email/doctype/notification/notification.py:512 msgid "Error while evaluating Notification {0}. Please fix your template." msgstr "" @@ -9179,7 +9208,7 @@ msgstr "" msgid "Executing..." msgstr "" -#: public/js/frappe/views/reports/query_report.js:1993 +#: public/js/frappe/views/reports/query_report.js:1978 msgid "Execution Time: {0} sec" msgstr "" @@ -9197,7 +9226,7 @@ msgctxt "Enlarge code field." msgid "Expand" msgstr "" -#: public/js/frappe/views/reports/query_report.js:1979 +#: public/js/frappe/views/reports/query_report.js:1964 #: public/js/frappe/views/treeview.js:125 msgid "Expand All" msgstr "" @@ -9251,19 +9280,19 @@ msgstr "" #. Label of the export (Check) field in DocType 'DocPerm' #: core/doctype/custom_docperm/custom_docperm.json #: core/doctype/docperm/docperm.json core/doctype/recorder/recorder_list.js:37 -#: public/js/frappe/data_import/data_exporter.js:91 -#: public/js/frappe/data_import/data_exporter.js:242 -#: public/js/frappe/views/reports/query_report.js:1684 +#: public/js/frappe/data_import/data_exporter.js:92 +#: public/js/frappe/data_import/data_exporter.js:243 +#: public/js/frappe/views/reports/query_report.js:1669 #: public/js/frappe/views/reports/report_view.js:1550 msgid "Export" msgstr "" -#: public/js/frappe/list/list_view.js:2034 +#: public/js/frappe/list/list_view.js:2086 msgctxt "Button in list view actions menu" msgid "Export" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:244 +#: public/js/frappe/data_import/data_exporter.js:245 msgid "Export 1 record" msgstr "" @@ -9336,7 +9365,7 @@ msgstr "" msgid "Export without main header" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:246 +#: public/js/frappe/data_import/data_exporter.js:247 msgid "Export {0} records" msgstr "" @@ -9489,7 +9518,7 @@ msgstr "" msgid "Failed to optimize image: {0}" msgstr "" -#: email/doctype/email_queue/email_queue.py:281 +#: email/doctype/email_queue/email_queue.py:294 msgid "Failed to send email with subject:" msgstr "" @@ -9594,7 +9623,7 @@ msgstr "" #: public/js/frappe/list/bulk_operations.js:297 #: public/js/frappe/list/list_view_permission_restrictions.html:3 #: public/js/frappe/views/reports/query_report.js:236 -#: public/js/frappe/views/reports/query_report.js:1738 +#: public/js/frappe/views/reports/query_report.js:1723 #: website/doctype/web_form_field/web_form_field.json #: website/doctype/web_form_list_column/web_form_list_column.json msgid "Field" @@ -9902,7 +9931,7 @@ msgstr "" #: desk/doctype/number_card/number_card.js:205 #: desk/doctype/number_card/number_card.js:336 #: email/doctype/auto_email_report/auto_email_report.js:90 -#: public/js/frappe/list/base_list.js:882 +#: public/js/frappe/list/base_list.js:890 #: public/js/frappe/ui/filters/filter_list.js:134 #: website/doctype/web_form/web_form.js:197 msgid "Filter" @@ -10339,7 +10368,7 @@ msgstr "" msgid "For Value" msgstr "" -#: public/js/frappe/views/reports/query_report.js:1990 +#: public/js/frappe/views/reports/query_report.js:1975 #: public/js/frappe/views/reports/report_view.js:96 msgid "For comparison, use >5, <10 or =324. For ranges, use 5:10 (for values between 5 & 10)." msgstr "" @@ -10348,6 +10377,10 @@ msgstr "" msgid "For example if you cancel and amend INV004 it will become a new document INV004-1. This helps you to keep track of each amendment." msgstr "" +#: public/js/frappe/utils/dashboard_utils.js:162 +msgid "For example:" +msgstr "" + #: printing/page/print_format_builder/print_format_builder.js:744 msgid "For example: If you want to include the document ID, use {0}" msgstr "" @@ -10527,6 +10560,20 @@ msgstr "" msgid "Frappe Light" msgstr "" +#. Option for the 'Service' (Select) field in DocType 'Email Account' +#: email/doctype/email_account/email_account.json email/frappemail.py:91 +msgid "Frappe Mail" +msgstr "" + +#: email/doctype/email_account/email_account.py:538 +msgid "Frappe Mail OAuth Error" +msgstr "" + +#. Label of the frappe_mail_site (Data) field in DocType 'Email Account' +#: email/doctype/email_account/email_account.json +msgid "Frappe Mail Site" +msgstr "" + #. Label of a standard help item #. Type: Action #: hooks.py @@ -10586,7 +10633,7 @@ msgstr "" msgid "From Date Field" msgstr "" -#: public/js/frappe/views/reports/query_report.js:1704 +#: public/js/frappe/views/reports/query_report.js:1689 msgid "From Document Type" msgstr "" @@ -10644,7 +10691,7 @@ msgstr "" msgid "Function Based On" msgstr "" -#: __init__.py:934 +#: __init__.py:940 msgid "Function {0} is not whitelisted." msgstr "" @@ -10682,6 +10729,10 @@ msgstr "" msgid "Gantt" msgstr "" +#: public/js/frappe/list/base_list.js:206 +msgid "Gantt View" +msgstr "" + #. Label of the gender (Link) field in DocType 'Contact' #. Name of a DocType #. Label of the gender (Data) field in DocType 'Gender' @@ -10727,7 +10778,7 @@ msgstr "" msgid "Geolocation" msgstr "" -#: email/doctype/notification/notification.js:170 +#: email/doctype/notification/notification.js:175 msgid "Get Alerts for Today" msgstr "" @@ -11552,7 +11603,7 @@ msgstr "" msgid "Hide Standard Menu" msgstr "" -#: public/js/frappe/list/list_view.js:1611 +#: public/js/frappe/list/list_view.js:1663 msgid "Hide Tags" msgstr "" @@ -11673,11 +11724,11 @@ msgstr "" #: core/doctype/data_import/importer.py:1139 #: core/doctype/data_import/importer.py:1204 #: core/doctype/data_import/importer.py:1207 desk/report/todo/todo.py:36 -#: model/meta.py:45 public/js/frappe/data_import/data_exporter.js:329 -#: public/js/frappe/data_import/data_exporter.js:344 +#: model/meta.py:45 public/js/frappe/data_import/data_exporter.js:330 +#: public/js/frappe/data_import/data_exporter.js:345 #: public/js/frappe/list/list_settings.js:334 -#: public/js/frappe/list/list_view.js:358 -#: public/js/frappe/list/list_view.js:422 public/js/frappe/model/meta.js:197 +#: public/js/frappe/list/list_view.js:355 +#: public/js/frappe/list/list_view.js:419 public/js/frappe/model/meta.js:197 #: public/js/frappe/model/model.js:122 msgid "ID" msgstr "" @@ -12053,6 +12104,10 @@ msgstr "" msgid "Image Link" msgstr "" +#: public/js/frappe/list/base_list.js:209 +msgid "Image View" +msgstr "" + #. Label of the image_width (Float) field in DocType 'Letter Head' #. Label of the footer_image_width (Float) field in DocType 'Letter Head' #: printing/doctype/letter_head/letter_head.json @@ -12113,7 +12168,7 @@ msgstr "" msgid "Import" msgstr "" -#: public/js/frappe/list/list_view.js:1673 +#: public/js/frappe/list/list_view.js:1725 msgctxt "Button in list view menu" msgid "Import" msgstr "" @@ -12324,6 +12379,10 @@ msgstr "" msgid "Inbox User" msgstr "" +#: public/js/frappe/list/base_list.js:210 +msgid "Inbox View" +msgstr "" + #. Label of the include_name_field (Check) field in DocType 'Form Tour' #: desk/doctype/form_tour/form_tour.json msgid "Include Name Field" @@ -12343,11 +12402,11 @@ msgstr "" msgid "Include Web View Link in Email" msgstr "" -#: public/js/frappe/views/reports/query_report.js:1521 +#: public/js/frappe/views/reports/query_report.js:1506 msgid "Include filters" msgstr "" -#: public/js/frappe/views/reports/query_report.js:1513 +#: public/js/frappe/views/reports/query_report.js:1498 msgid "Include indentation" msgstr "" @@ -12358,7 +12417,7 @@ msgstr "" #. Label of the incoming_popimap_tab (Tab Break) field in DocType 'Email #. Account' #: email/doctype/email_account/email_account.json -msgid "Incoming (POP/IMAP)" +msgid "Incoming" msgstr "" #. Label of the mailbox_settings (Section Break) field in DocType 'Email @@ -12503,7 +12562,7 @@ msgstr "" #. Label of the insert_after (Select) field in DocType 'Custom Field' #: custom/doctype/custom_field/custom_field.json -#: public/js/frappe/views/reports/query_report.js:1744 +#: public/js/frappe/views/reports/query_report.js:1729 msgid "Insert After" msgstr "" @@ -12710,7 +12769,7 @@ msgstr "" msgid "Invalid \"mandatory_depends_on\" expression" msgstr "" -#: utils/nestedset.py:177 +#: utils/nestedset.py:178 msgid "Invalid Action" msgstr "" @@ -12802,7 +12861,7 @@ msgstr "" msgid "Invalid Parameters." msgstr "" -#: core/doctype/user/user.py:1176 www/update-password.html:121 +#: core/doctype/user/user.py:1184 www/update-password.html:121 #: www/update-password.html:142 www/update-password.html:144 #: www/update-password.html:245 msgid "Invalid Password" @@ -13081,6 +13140,7 @@ msgstr "" #. Label of the is_query_report (Check) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:336 msgid "Is Query Report" msgstr "" @@ -13184,7 +13244,7 @@ msgstr "" msgid "Item Type" msgstr "" -#: utils/nestedset.py:228 +#: utils/nestedset.py:229 msgid "Item cannot be added to its own descendants" msgstr "" @@ -13309,6 +13369,7 @@ msgstr "" #. Label of the kanban_board (Link) field in DocType 'Workspace Shortcut' #: desk/doctype/kanban_board/kanban_board.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json +#: public/js/frappe/widgets/widget_dialog.js:509 msgid "Kanban Board" msgstr "" @@ -13328,6 +13389,10 @@ msgctxt "Button in kanban view menu" msgid "Kanban Settings" msgstr "" +#: public/js/frappe/list/base_list.js:207 +msgid "Kanban View" +msgstr "" + #. Description of a DocType #: core/doctype/activity_log/activity_log.json msgid "Keep track of all update feeds" @@ -13573,7 +13638,10 @@ msgstr "" #: desk/doctype/workspace_quick_list/workspace_quick_list.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: printing/page/print_format_builder/print_format_builder.js:474 +#: public/js/frappe/widgets/widget_dialog.js:187 #: public/js/frappe/widgets/widget_dialog.js:255 +#: public/js/frappe/widgets/widget_dialog.js:304 +#: public/js/frappe/widgets/widget_dialog.js:421 #: public/js/frappe/widgets/widget_dialog.js:645 #: public/js/frappe/widgets/widget_dialog.js:678 #: templates/form_grid/fields.html:37 @@ -13669,7 +13737,7 @@ msgstr "" msgid "Last Login" msgstr "" -#: email/doctype/notification/notification.js:31 +#: email/doctype/notification/notification.js:33 msgid "Last Modified Date" msgstr "" @@ -13717,6 +13785,11 @@ msgstr "" msgid "Last Sync On" msgstr "" +#. Label of the last_synced_at (Datetime) field in DocType 'Email Account' +#: email/doctype/email_account/email_account.json +msgid "Last Synced At" +msgstr "" + #. Label of the last_synced_on (Datetime) field in DocType 'Dashboard Chart' #: desk/doctype/dashboard_chart/dashboard_chart.json msgid "Last Synced On" @@ -13747,7 +13820,7 @@ msgstr "" msgid "Last Year" msgstr "" -#: public/js/frappe/widgets/chart_widget.js:698 +#: public/js/frappe/widgets/chart_widget.js:701 msgid "Last synced {0}" msgstr "" @@ -13799,7 +13872,7 @@ msgid "Leave blank to repeat always" msgstr "" #: core/doctype/communication/mixins.py:207 -#: email/doctype/email_account/email_account.py:663 +#: email/doctype/email_account/email_account.py:709 msgid "Leave this conversation" msgstr "" @@ -13858,7 +13931,7 @@ msgstr "" msgid "Length of {0} should be between 1 and 1000" msgstr "" -#: public/js/frappe/widgets/chart_widget.js:674 +#: public/js/frappe/widgets/chart_widget.js:677 msgid "Less" msgstr "" @@ -13941,6 +14014,7 @@ msgstr "" #. Label of the level (Select) field in DocType 'Help Article' #: core/doctype/custom_docperm/custom_docperm.json #: core/doctype/docperm/docperm.json +#: core/page/permission_manager/permission_manager.js:137 #: core/page/permission_manager/permission_manager.js:213 #: public/js/frappe/roles_editor.js:66 #: website/doctype/help_article/help_article.json @@ -14140,6 +14214,8 @@ msgstr "" #. Label of the link_to (Dynamic Link) field in DocType 'Workspace Shortcut' #: desk/doctype/workspace_link/workspace_link.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json +#: public/js/frappe/widgets/widget_dialog.js:285 +#: public/js/frappe/widgets/widget_dialog.js:430 msgid "Link To" msgstr "" @@ -14149,6 +14225,7 @@ msgstr "" #. Label of the link_type (Select) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:277 msgid "Link Type" msgstr "" @@ -14192,7 +14269,7 @@ msgstr "" #. Label of the links (Table) field in DocType 'Customize Form' #. Label of the links (Table) field in DocType 'Workspace' #: contacts/doctype/address/address.js:39 contacts/doctype/address/address.json -#: contacts/doctype/contact/contact.js:87 contacts/doctype/contact/contact.json +#: contacts/doctype/contact/contact.js:92 contacts/doctype/contact/contact.json #: core/doctype/doctype/doctype.json #: custom/doctype/customize_form/customize_form.json #: desk/doctype/workspace/workspace.json public/js/frappe/form/toolbar.js:377 @@ -14240,11 +14317,15 @@ msgstr "" msgid "List Settings" msgstr "" -#: public/js/frappe/list/list_view.js:1753 +#: public/js/frappe/list/list_view.js:1805 msgctxt "Button in list view menu" msgid "List Settings" msgstr "" +#: public/js/frappe/list/base_list.js:203 +msgid "List View" +msgstr "" + #. Name of a DocType #: desk/doctype/list_view_settings/list_view_settings.json msgid "List View Settings" @@ -14281,7 +14362,7 @@ msgstr "" msgid "Load Balancing" msgstr "" -#: public/js/frappe/list/base_list.js:378 +#: public/js/frappe/list/base_list.js:386 #: website/doctype/blog_post/templates/blog_post_list.html:50 #: website/doctype/help_article/templates/help_article_list.html:30 msgid "Load More" @@ -14295,8 +14376,8 @@ msgstr "" #: core/page/permission_manager/permission_manager.js:165 #: public/js/frappe/form/controls/multicheck.js:13 #: public/js/frappe/form/linked_with.js:13 -#: public/js/frappe/list/base_list.js:490 -#: public/js/frappe/list/list_view.js:335 public/js/frappe/ui/listing.html:16 +#: public/js/frappe/list/base_list.js:498 +#: public/js/frappe/list/list_view.js:332 public/js/frappe/ui/listing.html:16 #: public/js/frappe/views/reports/query_report.js:1017 msgid "Loading" msgstr "" @@ -14323,7 +14404,7 @@ msgstr "" #: public/js/frappe/views/kanban/kanban_board.html:11 #: public/js/frappe/widgets/chart_widget.js:50 #: public/js/frappe/widgets/number_card_widget.js:174 -#: public/js/frappe/widgets/quick_list_widget.js:126 +#: public/js/frappe/widgets/quick_list_widget.js:128 msgid "Loading..." msgstr "" @@ -14407,7 +14488,7 @@ msgstr "" msgid "Login Failed please try again" msgstr "" -#: email/doctype/email_account/email_account.py:141 +#: email/doctype/email_account/email_account.py:140 msgid "Login Id is required" msgstr "" @@ -14708,6 +14789,10 @@ msgstr "" msgid "Map Columns" msgstr "" +#: public/js/frappe/list/base_list.js:212 +msgid "Map View" +msgstr "" + #: public/js/frappe/data_import/import_preview.js:290 msgid "Map columns from {0} to fields in {1}" msgstr "" @@ -14938,7 +15023,7 @@ msgstr "" msgid "Merge with existing" msgstr "" -#: utils/nestedset.py:304 +#: utils/nestedset.py:307 msgid "Merging is only possible between Group-to-Group or Leaf Node-to-Leaf Node" msgstr "" @@ -14974,7 +15059,7 @@ msgstr "" msgid "Message" msgstr "" -#: __init__.py:618 public/js/frappe/ui/messages.js:265 +#: __init__.py:624 public/js/frappe/ui/messages.js:267 msgctxt "Default title of the message dialog" msgid "Message" msgstr "" @@ -15015,7 +15100,7 @@ msgstr "" msgid "Message clipped" msgstr "" -#: email/doctype/email_account/email_account.py:317 +#: email/doctype/email_account/email_account.py:333 msgid "Message from server: {0}" msgstr "" @@ -15094,6 +15179,10 @@ msgstr "" msgid "Method" msgstr "" +#: __init__.py:942 +msgid "Method Not Allowed" +msgstr "" + #: desk/doctype/number_card/number_card.py:70 msgid "Method is required to create a number card" msgstr "" @@ -15403,7 +15492,7 @@ msgstr "" #: public/js/frappe/form/multi_select_dialog.js:72 #: public/js/frappe/ui/toolbar/search.js:285 #: public/js/frappe/ui/toolbar/search.js:300 -#: public/js/frappe/widgets/chart_widget.js:674 +#: public/js/frappe/widgets/chart_widget.js:677 #: templates/includes/list/list.html:23 #: templates/includes/search_template.html:13 msgid "More" @@ -15485,7 +15574,7 @@ msgstr "" msgid "Mozilla doesn't support :has() so you can pass parent selector here as workaround" msgstr "" -#: utils/nestedset.py:328 +#: utils/nestedset.py:331 msgid "Multiple root nodes not allowed." msgstr "" @@ -15689,12 +15778,12 @@ msgstr "" msgid "Navigate Home" msgstr "" -#: public/js/frappe/list/list_view.js:1161 +#: public/js/frappe/list/list_view.js:1196 msgctxt "Description of a list view shortcut" msgid "Navigate list down" msgstr "" -#: public/js/frappe/list/list_view.js:1168 +#: public/js/frappe/list/list_view.js:1203 msgctxt "Description of a list view shortcut" msgid "Navigate list up" msgstr "" @@ -15721,7 +15810,7 @@ msgstr "" msgid "Negative Value" msgstr "" -#: utils/nestedset.py:93 +#: utils/nestedset.py:94 msgid "Nested set error. Please contact the Administrator." msgstr "" @@ -15931,7 +16020,7 @@ msgstr "" msgid "New {} releases for the following apps are available" msgstr "" -#: core/doctype/user/user.py:753 +#: core/doctype/user/user.py:761 msgid "Newly created user {0} has no roles enabled." msgstr "" @@ -15982,7 +16071,7 @@ msgstr "" msgid "Newsletters" msgstr "" -#: public/js/frappe/form/form_tour.js:318 +#: public/js/frappe/form/form_tour.js:14 public/js/frappe/form/form_tour.js:324 #: public/js/frappe/web_form/web_form.js:91 #: public/js/onboarding_tours/onboarding_tours.js:15 #: public/js/onboarding_tours/onboarding_tours.js:240 @@ -16068,7 +16157,7 @@ msgstr "" #: public/js/form_builder/utils.js:341 #: public/js/frappe/form/controls/link.js:475 #: public/js/frappe/list/list_sidebar_group_by.js:223 -#: public/js/frappe/views/reports/query_report.js:1541 +#: public/js/frappe/views/reports/query_report.js:1526 #: website/doctype/help_article/templates/help_article.html:26 msgid "No" msgstr "" @@ -16112,7 +16201,7 @@ msgstr "" msgid "No Data to Show" msgstr "" -#: public/js/frappe/widgets/quick_list_widget.js:131 +#: public/js/frappe/widgets/quick_list_widget.js:133 msgid "No Data..." msgstr "" @@ -16132,7 +16221,7 @@ msgstr "" msgid "No Entry for the User {0} found within LDAP!" msgstr "" -#: public/js/frappe/widgets/chart_widget.js:366 +#: public/js/frappe/widgets/chart_widget.js:367 msgid "No Filters Set" msgstr "" @@ -16210,7 +16299,7 @@ msgstr "" msgid "No Results found" msgstr "" -#: core/doctype/user/user.py:754 +#: core/doctype/user/user.py:762 msgid "No Roles Specified" msgstr "" @@ -16238,7 +16327,7 @@ msgstr "" msgid "No address added yet." msgstr "" -#: email/doctype/notification/notification.js:180 +#: email/doctype/notification/notification.js:185 msgid "No alerts for today" msgstr "" @@ -16365,7 +16454,7 @@ msgstr "" msgid "No of Sent SMS" msgstr "" -#: __init__.py:1126 client.py:109 client.py:151 +#: __init__.py:1132 client.py:109 client.py:151 msgid "No permission for {0}" msgstr "" @@ -16394,7 +16483,7 @@ msgstr "" msgid "No records tagged." msgstr "" -#: public/js/frappe/data_import/data_exporter.js:224 +#: public/js/frappe/data_import/data_exporter.js:225 msgid "No records will be exported" msgstr "" @@ -16418,7 +16507,7 @@ msgstr "" msgid "No {0} found" msgstr "" -#: public/js/frappe/list/list_view.js:469 +#: public/js/frappe/list/list_view.js:466 msgid "No {0} found with matching filters. Clear filters to see all {0}." msgstr "" @@ -16460,7 +16549,7 @@ msgstr "" msgid "Normalized Query" msgstr "" -#: core/doctype/user/user.py:959 templates/includes/login/login.js:257 +#: core/doctype/user/user.py:967 templates/includes/login/login.js:257 #: utils/oauth.py:265 msgid "Not Allowed" msgstr "" @@ -16507,7 +16596,7 @@ msgstr "" msgid "Not Nullable" msgstr "" -#: __init__.py:1018 app.py:357 desk/calendar.py:26 geo/utils.py:97 +#: __init__.py:1024 app.py:357 desk/calendar.py:26 geo/utils.py:97 #: public/js/frappe/web_form/webform_script.js:15 #: website/doctype/web_form/web_form.py:602 #: website/page_renderers/not_permitted_page.py:20 www/login.py:181 @@ -16559,7 +16648,7 @@ msgstr "" msgid "Not a valid Comma Separated Value (CSV File)" msgstr "" -#: core/doctype/user/user.py:235 +#: core/doctype/user/user.py:234 msgid "Not a valid User Image." msgstr "" @@ -16579,7 +16668,7 @@ msgstr "" msgid "Not allowed for {0}: {1}" msgstr "" -#: email/doctype/notification/notification.py:391 +#: email/doctype/notification/notification.py:396 msgid "Not allowed to attach {0} document, please enable Allow Print For {0} in Print Settings" msgstr "" @@ -16698,7 +16787,7 @@ msgstr "" msgid "Nothing left to undo" msgstr "" -#: public/js/frappe/list/base_list.js:362 +#: public/js/frappe/list/base_list.js:370 #: public/js/frappe/views/reports/query_report.js:105 #: templates/includes/list/list.html:7 #: website/doctype/blog_post/templates/blog_post_list.html:41 @@ -16965,7 +17054,7 @@ msgstr "" msgid "OAuth Scope" msgstr "" -#: email/doctype/email_account/email_account.js:182 +#: email/doctype/email_account/email_account.js:211 msgid "OAuth has been enabled but not authorised. Please use \"Authorise API Access\" button to do the same." msgstr "" @@ -17104,9 +17193,14 @@ msgstr "" #. Label of the onboard (Check) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:330 msgid "Onboard" msgstr "" +#: public/js/frappe/widgets/widget_dialog.js:236 +msgid "Onboarding Name" +msgstr "" + #. Name of a DocType #: desk/doctype/onboarding_permission/onboarding_permission.json msgid "Onboarding Permission" @@ -17160,7 +17254,7 @@ msgstr "" msgid "Only 200 inserts allowed in one request" msgstr "" -#: email/doctype/email_queue/email_queue.py:81 +#: email/doctype/email_queue/email_queue.py:82 msgid "Only Administrator can delete Email Queue" msgstr "" @@ -17214,6 +17308,7 @@ msgstr "" #. Label of the only_for (Link) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:323 msgid "Only for" msgstr "" @@ -17323,7 +17418,7 @@ msgstr "" msgid "Open a module or tool" msgstr "" -#: public/js/frappe/list/list_view.js:1214 +#: public/js/frappe/list/list_view.js:1249 msgctxt "Description of a list view shortcut" msgid "Open list item" msgstr "" @@ -17498,9 +17593,9 @@ msgstr "" msgid "Other" msgstr "" -#. Label of the outgoing_smtp_tab (Tab Break) field in DocType 'Email Account' +#. Label of the outgoing_tab (Tab Break) field in DocType 'Email Account' #: email/doctype/email_account/email_account.json -msgid "Outgoing (SMTP)" +msgid "Outgoing" msgstr "" #. Label of the outgoing_mail_settings (Section Break) field in DocType 'Email @@ -17563,7 +17658,7 @@ msgstr "" #: printing/page/print/print.js:71 #: public/js/frappe/form/templates/print_layout.html:44 -#: public/js/frappe/views/reports/query_report.js:1669 +#: public/js/frappe/views/reports/query_report.js:1654 msgid "PDF" msgstr "" @@ -17916,11 +18011,11 @@ msgstr "" msgid "Password" msgstr "" -#: core/doctype/user/user.py:1022 +#: core/doctype/user/user.py:1030 msgid "Password Email Sent" msgstr "" -#: core/doctype/user/user.py:406 +#: core/doctype/user/user.py:405 msgid "Password Reset" msgstr "" @@ -17942,7 +18037,7 @@ msgstr "" msgid "Password for Base DN" msgstr "" -#: email/doctype/email_account/email_account.py:172 +#: email/doctype/email_account/email_account.py:182 msgid "Password is required or select Awaiting Password" msgstr "" @@ -17954,8 +18049,8 @@ msgstr "" msgid "Password not found for {0} {1} {2}" msgstr "" -#: core/doctype/user/user.py:1021 -msgid "Password reset instructions have been sent to your email" +#: core/doctype/user/user.py:1029 +msgid "Password reset instructions have been sent to {}'s email" msgstr "" #: www/update-password.html:164 @@ -17966,7 +18061,7 @@ msgstr "" msgid "Password size exceeded the maximum allowed size" msgstr "" -#: core/doctype/user/user.py:817 +#: core/doctype/user/user.py:825 msgid "Password size exceeded the maximum allowed size." msgstr "" @@ -18299,6 +18394,10 @@ msgstr "" msgid "Plant" msgstr "" +#: email/doctype/email_account/email_account.py:535 +msgid "Please Authorize OAuth for Email Account {0}" +msgstr "" + #: email/oauth.py:29 msgid "Please Authorize OAuth for Email Account {}" msgstr "" @@ -18327,7 +18426,7 @@ msgstr "" msgid "Please add a valid comment." msgstr "" -#: core/doctype/user/user.py:1004 +#: core/doctype/user/user.py:1012 msgid "Please ask your administrator to verify your sign-up" msgstr "" @@ -18355,11 +18454,11 @@ msgstr "" msgid "Please check the filter values set for Dashboard Chart: {}" msgstr "" -#: model/base_document.py:872 +#: model/base_document.py:873 msgid "Please check the value of \"Fetch From\" set for field {0}" msgstr "" -#: core/doctype/user/user.py:1002 +#: core/doctype/user/user.py:1010 msgid "Please check your email for verification" msgstr "" @@ -18641,11 +18740,11 @@ msgstr "" msgid "Please setup a message first" msgstr "" -#: email/doctype/email_account/email_account.py:407 +#: email/doctype/email_account/email_account.py:423 msgid "Please setup default Email Account from Settings > Email Account" msgstr "" -#: core/doctype/user/user.py:371 +#: core/doctype/user/user.py:370 msgid "Please setup default outgoing Email Account from Settings > Email Account" msgstr "" @@ -18657,11 +18756,11 @@ msgstr "" msgid "Please specify a valid parent DocType for {0}" msgstr "" -#: email/doctype/notification/notification.py:87 +#: email/doctype/notification/notification.py:88 msgid "Please specify which date field must be checked" msgstr "" -#: email/doctype/notification/notification.py:90 +#: email/doctype/notification/notification.py:91 msgid "Please specify which value field must be checked" msgstr "" @@ -18926,6 +19025,7 @@ msgstr "" msgid "Preview:" msgstr "" +#: public/js/frappe/form/form_tour.js:15 #: public/js/frappe/web_form/web_form.js:95 #: public/js/onboarding_tours/onboarding_tours.js:16 #: templates/includes/slideshow.html:34 @@ -18994,13 +19094,13 @@ msgstr "" #: public/js/frappe/form/templates/print_layout.html:46 #: public/js/frappe/form/toolbar.js:332 public/js/frappe/form/toolbar.js:344 #: public/js/frappe/list/bulk_operations.js:87 -#: public/js/frappe/views/reports/query_report.js:1655 +#: public/js/frappe/views/reports/query_report.js:1640 #: public/js/frappe/views/reports/report_view.js:1460 #: public/js/frappe/views/treeview.js:469 www/printview.html:18 msgid "Print" msgstr "" -#: public/js/frappe/list/list_view.js:1918 +#: public/js/frappe/list/list_view.js:1970 msgctxt "Button in list view actions menu" msgid "Print" msgstr "" @@ -19260,7 +19360,7 @@ msgstr "" msgid "Processing" msgstr "" -#: email/doctype/email_queue/email_queue.py:434 +#: email/doctype/email_queue/email_queue.py:447 msgid "Processing..." msgstr "" @@ -19396,7 +19496,7 @@ msgstr "" msgid "Publishing Dates" msgstr "" -#: email/doctype/email_account/email_account.js:159 +#: email/doctype/email_account/email_account.js:179 msgid "Pull Emails" msgstr "" @@ -19743,7 +19843,7 @@ msgstr "" msgid "Re-Run in Console" msgstr "" -#: email/doctype/email_account/email_account.py:669 +#: email/doctype/email_account/email_account.py:715 msgid "Re:" msgstr "" @@ -19856,7 +19956,7 @@ msgstr "" msgid "Rebuild Tree" msgstr "" -#: utils/nestedset.py:176 +#: utils/nestedset.py:177 msgid "Rebuilding of tree is not supported for {}" msgstr "" @@ -20214,9 +20314,9 @@ msgstr "" #: public/js/frappe/desk.js:533 public/js/frappe/form/form.js:1196 #: public/js/frappe/form/templates/print_layout.html:6 #: public/js/frappe/list/base_list.js:66 -#: public/js/frappe/views/reports/query_report.js:1644 +#: public/js/frappe/views/reports/query_report.js:1629 #: public/js/frappe/views/treeview.js:475 -#: public/js/frappe/widgets/chart_widget.js:290 +#: public/js/frappe/widgets/chart_widget.js:291 #: public/js/frappe/widgets/number_card_widget.js:324 msgid "Refresh" msgstr "" @@ -20243,7 +20343,7 @@ msgstr "" msgid "Refresh Token" msgstr "" -#: public/js/frappe/list/list_view.js:507 +#: public/js/frappe/list/list_view.js:504 msgctxt "Document count in list view" msgid "Refreshing" msgstr "" @@ -20253,7 +20353,7 @@ msgstr "" msgid "Refreshing..." msgstr "" -#: core/doctype/user/user.py:966 +#: core/doctype/user/user.py:974 msgid "Registered but disabled" msgstr "" @@ -20312,7 +20412,7 @@ msgstr "" msgid "Reload File" msgstr "" -#: public/js/frappe/list/base_list.js:242 +#: public/js/frappe/list/base_list.js:250 msgid "Reload List" msgstr "" @@ -20581,7 +20681,7 @@ msgstr "" #: core/doctype/report/report.json #: desk/doctype/dashboard_chart/dashboard_chart.json #: desk/doctype/number_card/number_card.json -#: public/js/frappe/views/reports/query_report.js:1825 +#: public/js/frappe/views/reports/query_report.js:1810 msgid "Report Name" msgstr "" @@ -20604,6 +20704,10 @@ msgstr "" msgid "Report Type" msgstr "" +#: public/js/frappe/list/base_list.js:204 +msgid "Report View" +msgstr "" + #: core/doctype/doctype/doctype.py:1780 msgid "Report cannot be set for Single types" msgstr "" @@ -20638,7 +20742,7 @@ msgstr "" msgid "Report was not saved (there were errors)" msgstr "" -#: public/js/frappe/views/reports/query_report.js:1863 +#: public/js/frappe/views/reports/query_report.js:1848 msgid "Report with more than 10 columns looks better in Landscape mode." msgstr "" @@ -20792,7 +20896,7 @@ msgstr "" msgid "Reset Changes" msgstr "" -#: public/js/frappe/widgets/chart_widget.js:305 +#: public/js/frappe/widgets/chart_widget.js:306 msgid "Reset Chart" msgstr "" @@ -21140,7 +21244,7 @@ msgstr "" msgid "Role Permissions Manager" msgstr "" -#: public/js/frappe/list/list_view.js:1695 +#: public/js/frappe/list/list_view.js:1747 msgctxt "Button in list view menu" msgid "Role Permissions Manager" msgstr "" @@ -21172,7 +21276,7 @@ msgstr "" msgid "Role and Level" msgstr "" -#: core/doctype/user/user.py:316 +#: core/doctype/user/user.py:315 msgid "Role has been set as per the user type {0}" msgstr "" @@ -21224,7 +21328,7 @@ msgstr "" msgid "Roles can be set for users from their User page." msgstr "" -#: utils/nestedset.py:277 +#: utils/nestedset.py:280 msgid "Root {0} cannot be deleted" msgstr "" @@ -21297,7 +21401,7 @@ msgstr "" msgid "Row # {0}: Non administrator user can not set the role {1} to the custom doctype" msgstr "" -#: model/base_document.py:903 +#: model/base_document.py:904 msgid "Row #{0}:" msgstr "" @@ -21473,7 +21577,7 @@ msgstr "" msgid "SMS was not sent. Please contact Administrator." msgstr "" -#: email/doctype/email_account/email_account.py:189 +#: email/doctype/email_account/email_account.py:205 msgid "SMTP Server is required" msgstr "" @@ -21581,11 +21685,11 @@ msgstr "" #: public/js/frappe/views/kanban/kanban_settings.js:45 #: public/js/frappe/views/kanban/kanban_settings.js:189 #: public/js/frappe/views/kanban/kanban_view.js:343 -#: public/js/frappe/views/reports/query_report.js:1817 +#: public/js/frappe/views/reports/query_report.js:1802 #: public/js/frappe/views/reports/report_view.js:1640 #: public/js/frappe/views/workspace/workspace.js:501 #: public/js/frappe/widgets/base_widget.js:142 -#: public/js/frappe/widgets/quick_list_widget.js:117 +#: public/js/frappe/widgets/quick_list_widget.js:119 #: public/js/print_format_builder/print_format_builder.bundle.js:15 #: public/js/workflow_builder/workflow_builder.bundle.js:33 msgid "Save" @@ -21612,7 +21716,7 @@ msgstr "" msgid "Save Filter" msgstr "" -#: public/js/frappe/views/reports/query_report.js:1820 +#: public/js/frappe/views/reports/query_report.js:1805 msgid "Save Report" msgstr "" @@ -21625,7 +21729,7 @@ msgstr "" msgid "Save on Completion" msgstr "" -#: public/js/frappe/form/form_tour.js:289 +#: public/js/frappe/form/form_tour.js:295 msgid "Save the document." msgstr "" @@ -22027,7 +22131,7 @@ msgstr "" msgid "Select" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:148 +#: public/js/frappe/data_import/data_exporter.js:149 #: public/js/frappe/form/controls/multicheck.js:166 msgid "Select All" msgstr "" @@ -22115,11 +22219,11 @@ msgstr "" msgid "Select Fields" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:146 +#: public/js/frappe/data_import/data_exporter.js:147 msgid "Select Fields To Insert" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:147 +#: public/js/frappe/data_import/data_exporter.js:148 msgid "Select Fields To Update" msgstr "" @@ -22152,7 +22256,7 @@ msgstr "" msgid "Select List View" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:157 +#: public/js/frappe/data_import/data_exporter.js:158 msgid "Select Mandatory" msgstr "" @@ -22234,7 +22338,7 @@ msgstr "" msgid "Select a valid Subject field for creating documents from Email" msgstr "" -#: public/js/frappe/form/form_tour.js:315 +#: public/js/frappe/form/form_tour.js:321 msgid "Select an Image" msgstr "" @@ -22256,13 +22360,13 @@ msgstr "" msgid "Select atleast 2 actions" msgstr "" -#: public/js/frappe/list/list_view.js:1228 +#: public/js/frappe/list/list_view.js:1263 msgctxt "Description of a list view shortcut" msgid "Select list item" msgstr "" -#: public/js/frappe/list/list_view.js:1180 -#: public/js/frappe/list/list_view.js:1196 +#: public/js/frappe/list/list_view.js:1215 +#: public/js/frappe/list/list_view.js:1231 msgctxt "Description of a list view shortcut" msgid "Select multiple list items" msgstr "" @@ -22704,6 +22808,14 @@ msgstr "" msgid "Session Expiry must be in format {0}" msgstr "" +#: desk/doctype/dashboard_chart/dashboard_chart.js:400 +#: desk/doctype/dashboard_chart/dashboard_chart.js:487 +#: desk/doctype/number_card/number_card.js:295 +#: desk/doctype/number_card/number_card.js:387 +#: public/js/frappe/widgets/chart_widget.js:407 +msgid "Set" +msgstr "" + #: public/js/frappe/ui/filters/filter.js:569 msgctxt "Field value is set" msgid "Set" @@ -22735,8 +22847,8 @@ msgstr "" msgid "Set Filters" msgstr "" -#: public/js/frappe/widgets/chart_widget.js:395 -#: public/js/frappe/widgets/quick_list_widget.js:102 +#: public/js/frappe/widgets/chart_widget.js:396 +#: public/js/frappe/widgets/quick_list_widget.js:104 msgid "Set Filters for {0}" msgstr "" @@ -22824,6 +22936,10 @@ msgstr "" msgid "Set by user" msgstr "" +#: public/js/frappe/utils/dashboard_utils.js:162 +msgid "Set dynamic filter values in JavaScript for the required fields here." +msgstr "" + #. Description of the 'Precision' (Select) field in DocType 'DocField' #. Description of the 'Precision' (Select) field in DocType 'Custom Field' #. Description of the 'Precision' (Select) field in DocType 'Customize Form @@ -22952,7 +23068,7 @@ msgstr "" msgid "Setup Approval Workflows" msgstr "" -#: public/js/frappe/views/reports/query_report.js:1690 +#: public/js/frappe/views/reports/query_report.js:1675 #: public/js/frappe/views/reports/report_view.js:1618 msgid "Setup Auto Email" msgstr "" @@ -23214,7 +23330,7 @@ msgid "Show Sidebar" msgstr "" #: public/js/frappe/list/list_sidebar.html:66 -#: public/js/frappe/list/list_view.js:1611 +#: public/js/frappe/list/list_view.js:1663 msgid "Show Tags" msgstr "" @@ -23355,7 +23471,7 @@ msgstr "" msgid "Sign Up and Confirmation" msgstr "" -#: core/doctype/user/user.py:959 +#: core/doctype/user/user.py:967 msgid "Sign Up is disabled" msgstr "" @@ -23753,6 +23869,10 @@ msgstr "" msgid "Standard Not Set" msgstr "" +#: core/page/permission_manager/permission_manager.js:125 +msgid "Standard Permissions" +msgstr "" + #: printing/doctype/print_format/print_format.py:74 msgid "Standard Print Format cannot be updated" msgstr "" @@ -24155,7 +24275,7 @@ msgstr "" msgid "Submit" msgstr "" -#: public/js/frappe/list/list_view.js:1985 +#: public/js/frappe/list/list_view.js:2037 msgctxt "Button in list view actions menu" msgid "Submit" msgstr "" @@ -24212,7 +24332,7 @@ msgstr "" msgid "Submit this document to confirm" msgstr "" -#: public/js/frappe/list/list_view.js:1990 +#: public/js/frappe/list/list_view.js:2042 msgctxt "Title of confirmation dialog" msgid "Submit {0} documents?" msgstr "" @@ -24362,7 +24482,7 @@ msgstr "" msgid "Suggested Indexes" msgstr "" -#: core/doctype/user/user.py:674 +#: core/doctype/user/user.py:682 msgid "Suggested Username: {0}" msgstr "" @@ -24885,7 +25005,7 @@ msgstr "" msgid "Templates" msgstr "" -#: core/doctype/user/user.py:970 +#: core/doctype/user/user.py:978 msgid "Temporarily Disabled" msgstr "" @@ -24991,7 +25111,7 @@ msgid "" "" msgstr "" -#: email/doctype/notification/notification.py:130 +#: email/doctype/notification/notification.py:131 msgid "The Condition '{0}' is invalid" msgstr "" @@ -25041,7 +25161,7 @@ msgstr "" msgid "The comment cannot be empty" msgstr "" -#: public/js/frappe/list/list_view.js:630 +#: public/js/frappe/list/list_view.js:627 msgid "The count shown is an estimated count. Click here to see the accurate count." msgstr "" @@ -25141,11 +25261,11 @@ msgid "" "" msgstr "" -#: core/doctype/user/user.py:930 +#: core/doctype/user/user.py:938 msgid "The reset password link has been expired" msgstr "" -#: core/doctype/user/user.py:932 +#: core/doctype/user/user.py:940 msgid "The reset password link has either been used before or is invalid" msgstr "" @@ -25183,7 +25303,7 @@ msgstr "" msgid "The user from this field will be rewarded points" msgstr "" -#: public/js/frappe/form/controls/data.js:24 +#: public/js/frappe/form/controls/data.js:25 msgid "The value you pasted was {0} characters long. Max allowed characters is {1}." msgstr "" @@ -25344,7 +25464,7 @@ msgstr "" msgid "This action is irreversible. Do you wish to continue?" msgstr "" -#: __init__.py:1014 +#: __init__.py:1020 msgid "This action is only allowed for {}" msgstr "" @@ -25449,7 +25569,7 @@ msgstr "" msgid "This goes above the slideshow." msgstr "" -#: public/js/frappe/views/reports/query_report.js:2027 +#: public/js/frappe/views/reports/query_report.js:2012 msgid "This is a background report. Please set the appropriate filters and then generate a new one." msgstr "" @@ -25577,7 +25697,7 @@ msgstr "" msgid "This will terminate the job immediately and might be dangerous, are you sure? " msgstr "" -#: core/doctype/user/user.py:1190 +#: core/doctype/user/user.py:1198 msgid "Throttled" msgstr "" @@ -26000,7 +26120,7 @@ msgstr "" msgid "Toggle Sidebar" msgstr "" -#: public/js/frappe/list/list_view.js:1726 +#: public/js/frappe/list/list_view.js:1778 msgctxt "Button in list view menu" msgid "Toggle Sidebar" msgstr "" @@ -26047,7 +26167,7 @@ msgstr "" msgid "Too many changes to database in single action." msgstr "" -#: core/doctype/user/user.py:971 +#: core/doctype/user/user.py:979 msgid "Too many users signed up recently, so the registration is disabled. Please try back in an hour" msgstr "" @@ -26315,6 +26435,10 @@ msgstr "" msgid "Tree" msgstr "" +#: public/js/frappe/list/base_list.js:211 +msgid "Tree View" +msgstr "" + #. Description of the 'Is Tree' (Check) field in DocType 'DocType' #: core/doctype/doctype/doctype.json msgid "Tree structures are implemented using Nested Set" @@ -26420,6 +26544,7 @@ msgstr "" #: desk/doctype/workspace_link/workspace_link.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: public/js/frappe/views/file/file_view.js:337 +#: public/js/frappe/widgets/widget_dialog.js:399 #: social/doctype/energy_point_log/energy_point_log.json #: website/doctype/web_template/web_template.json www/attribution.html:35 msgid "Type" @@ -26502,6 +26627,7 @@ msgstr "" #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: integrations/doctype/integration_request/integration_request.json #: integrations/doctype/webhook_request_log/webhook_request_log.json +#: public/js/frappe/widgets/widget_dialog.js:469 #: website/doctype/top_bar_item/top_bar_item.json #: website/doctype/website_slideshow_item/website_slideshow_item.json msgid "URL" @@ -26655,7 +26781,7 @@ msgstr "" msgid "Unsafe SQL query" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:158 +#: public/js/frappe/data_import/data_exporter.js:159 #: public/js/frappe/form/controls/multicheck.js:166 msgid "Unselect All" msgstr "" @@ -26825,7 +26951,7 @@ msgctxt "Freeze message while updating a document" msgid "Updating" msgstr "" -#: email/doctype/email_queue/email_queue.py:433 +#: email/doctype/email_queue/email_queue.py:446 msgid "Updating Email Queue Statuses. The emails will be picked up in the next scheduled run." msgstr "" @@ -27178,12 +27304,12 @@ msgid "User Permission" msgstr "" #: core/page/permission_manager/permission_manager_help.html:30 -#: public/js/frappe/views/reports/query_report.js:1804 +#: public/js/frappe/views/reports/query_report.js:1789 #: public/js/frappe/views/reports/report_view.js:1666 msgid "User Permissions" msgstr "" -#: public/js/frappe/list/list_view.js:1684 +#: public/js/frappe/list/list_view.js:1736 msgctxt "Button in list view menu" msgid "User Permissions" msgstr "" @@ -27290,7 +27416,7 @@ msgstr "" msgid "User must always select" msgstr "" -#: model/delete_doc.py:235 +#: model/delete_doc.py:244 msgid "User not allowed to delete {0}: {1}" msgstr "" @@ -27306,15 +27432,15 @@ msgstr "" msgid "User with email: {0} does not exist in the system. Please ask 'System Administrator' to create the user for you." msgstr "" -#: core/doctype/user/user.py:485 +#: core/doctype/user/user.py:484 msgid "User {0} cannot be deleted" msgstr "" -#: core/doctype/user/user.py:280 +#: core/doctype/user/user.py:279 msgid "User {0} cannot be disabled" msgstr "" -#: core/doctype/user/user.py:556 +#: core/doctype/user/user.py:564 msgid "User {0} cannot be renamed" msgstr "" @@ -27335,7 +27461,7 @@ msgstr "" msgid "User {0} has requested for data deletion" msgstr "" -#: core/doctype/user/user.py:1319 +#: core/doctype/user/user.py:1327 msgid "User {0} impersonated as {1}" msgstr "" @@ -27363,7 +27489,7 @@ msgstr "" msgid "Username" msgstr "" -#: core/doctype/user/user.py:641 +#: core/doctype/user/user.py:649 msgid "Username {0} already exists" msgstr "" @@ -27426,6 +27552,12 @@ msgstr "" msgid "Validate Field" msgstr "" +#. Label of the validate_frappe_mail_settings (Button) field in DocType 'Email +#. Account' +#: email/doctype/email_account/email_account.json +msgid "Validate Frappe Mail Settings" +msgstr "" + #. Label of the validate_ssl_certificate (Check) field in DocType 'Email #. Account' #. Label of the validate_ssl_certificate (Check) field in DocType 'Email @@ -27496,7 +27628,7 @@ msgstr "" msgid "Value To Be Set" msgstr "" -#: model/base_document.py:965 model/document.py:682 +#: model/base_document.py:966 model/document.py:682 msgid "Value cannot be changed for {0}" msgstr "" @@ -27539,7 +27671,7 @@ msgstr "" msgid "Value to Validate" msgstr "" -#: model/base_document.py:1035 +#: model/base_document.py:1036 msgid "Value too big" msgstr "" @@ -27585,11 +27717,11 @@ msgstr "" msgid "Verified" msgstr "" -#: public/js/frappe/ui/messages.js:350 +#: public/js/frappe/ui/messages.js:352 msgid "Verify" msgstr "" -#: public/js/frappe/ui/messages.js:349 +#: public/js/frappe/ui/messages.js:351 msgid "Verify Password" msgstr "" @@ -27638,7 +27770,7 @@ msgid "View Full Log" msgstr "" #: public/js/frappe/views/treeview.js:463 -#: public/js/frappe/widgets/quick_list_widget.js:245 +#: public/js/frappe/widgets/quick_list_widget.js:247 msgid "View List" msgstr "" @@ -28200,11 +28332,11 @@ msgstr "" msgid "Welcome Workspace" msgstr "" -#: core/doctype/user/user.py:363 +#: core/doctype/user/user.py:362 msgid "Welcome email sent" msgstr "" -#: core/doctype/user/user.py:424 +#: core/doctype/user/user.py:423 msgid "Welcome to {0}" msgstr "" @@ -28520,7 +28652,7 @@ msgstr "" msgid "Write" msgstr "" -#: model/base_document.py:875 +#: model/base_document.py:876 msgid "Wrong Fetch From value" msgstr "" @@ -28607,7 +28739,7 @@ msgstr "" #: public/js/form_builder/utils.js:336 #: public/js/frappe/form/controls/link.js:475 #: public/js/frappe/list/list_sidebar_group_by.js:223 -#: public/js/frappe/views/reports/query_report.js:1541 +#: public/js/frappe/views/reports/query_report.js:1526 #: website/doctype/help_article/templates/help_article.html:25 msgid "Yes" msgstr "" @@ -28691,7 +28823,7 @@ msgstr "" msgid "You are not permitted to access this page." msgstr "" -#: __init__.py:933 +#: __init__.py:939 msgid "You are not permitted to access this resource." msgstr "" @@ -28703,7 +28835,7 @@ msgstr "" msgid "You are only allowed to update order, do not remove or add apps." msgstr "" -#: email/doctype/email_account/email_account.js:216 +#: email/doctype/email_account/email_account.js:245 msgid "You are selecting Sync Option as ALL, It will resync all read as well as unread message from server. This may also cause the duplication of Communication (emails)." msgstr "" @@ -28744,8 +28876,8 @@ msgstr "" msgid "You can continue with the onboarding after exploring this page" msgstr "" -#: core/doctype/user/user.py:543 -msgid "You can disable the user instead of deleting it." +#: model/delete_doc.py:136 +msgid "You can disable this {0} instead of deleting it." msgstr "" #: core/doctype/file/file.py:691 @@ -28945,7 +29077,7 @@ msgstr "" msgid "You haven't added any Dashboard Charts or Number Cards yet." msgstr "" -#: public/js/frappe/list/list_view.js:473 +#: public/js/frappe/list/list_view.js:470 msgid "You haven't created a {0} yet" msgstr "" @@ -29014,7 +29146,7 @@ msgstr "" msgid "You need to select indexes you want to add first." msgstr "" -#: email/doctype/email_account/email_account.py:147 +#: email/doctype/email_account/email_account.py:153 msgid "You need to set one IMAP folder for {0}" msgstr "" @@ -29775,7 +29907,7 @@ msgstr "" msgid "text in document type" msgstr "" -#: public/js/frappe/form/controls/data.js:35 +#: public/js/frappe/form/controls/data.js:36 msgid "this form" msgstr "" @@ -29820,7 +29952,7 @@ msgstr "" msgid "via Google Meet" msgstr "" -#: email/doctype/notification/notification.py:215 +#: email/doctype/notification/notification.py:220 msgid "via Notification" msgstr "" @@ -29888,12 +30020,12 @@ msgstr "" msgid "{0} ${type}" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:79 +#: public/js/frappe/data_import/data_exporter.js:80 #: public/js/frappe/views/gantt/gantt_view.js:54 msgid "{0} ({1})" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:76 +#: public/js/frappe/data_import/data_exporter.js:77 msgid "{0} ({1}) (1 row mandatory)" msgstr "" @@ -29943,7 +30075,7 @@ msgstr "" #: public/js/frappe/ui/toolbar/search_utils.js:83 #: public/js/frappe/ui/toolbar/search_utils.js:84 #: public/js/frappe/utils/utils.js:924 -#: public/js/frappe/widgets/chart_widget.js:317 www/list.html:4 www/list.html:8 +#: public/js/frappe/widgets/chart_widget.js:318 www/list.html:4 www/list.html:8 msgid "{0} List" msgstr "" @@ -29963,14 +30095,14 @@ msgstr "" msgid "{0} Name" msgstr "" -#: model/base_document.py:1065 +#: model/base_document.py:1066 msgid "{0} Not allowed to change {1} after submission from {2} to {3}" msgstr "" #: public/js/frappe/ui/toolbar/search_utils.js:95 #: public/js/frappe/ui/toolbar/search_utils.js:96 #: public/js/frappe/utils/utils.js:921 -#: public/js/frappe/widgets/chart_widget.js:325 +#: public/js/frappe/widgets/chart_widget.js:326 msgid "{0} Report" msgstr "" @@ -29989,10 +30121,6 @@ msgstr "" msgid "{0} Tree" msgstr "" -#: public/js/frappe/list/base_list.js:209 -msgid "{0} View" -msgstr "" - #: public/js/frappe/form/footer/form_timeline.js:126 #: public/js/frappe/form/sidebar/form_sidebar.js:86 msgid "{0} Web page views" @@ -30007,7 +30135,7 @@ msgstr "" msgid "{0} added" msgstr "" -#: public/js/frappe/form/controls/data.js:203 +#: public/js/frappe/form/controls/data.js:204 msgid "{0} already exists. Select another name" msgstr "" @@ -30212,7 +30340,7 @@ msgstr "" msgid "{0} has left the conversation in {1} {2}" msgstr "" -#: __init__.py:2493 +#: __init__.py:2499 msgid "{0} has no versions tracked." msgstr "" @@ -30278,7 +30406,7 @@ msgstr "" msgid "{0} is like {1}" msgstr "" -#: email/doctype/email_account/email_account.py:176 +#: email/doctype/email_account/email_account.py:186 msgid "{0} is mandatory" msgstr "" @@ -30358,7 +30486,7 @@ msgstr "" msgid "{0} is one of {1}" msgstr "" -#: email/doctype/email_account/email_account.py:277 model/naming.py:217 +#: email/doctype/email_account/email_account.py:293 model/naming.py:217 #: printing/doctype/print_format/print_format.py:91 utils/csvutils.py:153 msgid "{0} is required" msgstr "" @@ -30371,11 +30499,11 @@ msgstr "" msgid "{0} is within {1}" msgstr "" -#: public/js/frappe/list/list_view.js:1601 +#: public/js/frappe/list/list_view.js:1653 msgid "{0} items selected" msgstr "" -#: core/doctype/user/user.py:1328 +#: core/doctype/user/user.py:1336 msgid "{0} just impersonated as you. They gave this reason: {1}" msgstr "" @@ -30442,11 +30570,11 @@ msgstr "" msgid "{0} not found" msgstr "" -#: core/doctype/report/report.py:413 public/js/frappe/list/list_view.js:992 +#: core/doctype/report/report.py:413 public/js/frappe/list/list_view.js:1027 msgid "{0} of {1}" msgstr "" -#: public/js/frappe/list/list_view.js:994 +#: public/js/frappe/list/list_view.js:1029 msgid "{0} of {1} ({2} rows with children)" msgstr "" @@ -30479,7 +30607,7 @@ msgstr "" msgid "{0} records deleted" msgstr "" -#: public/js/frappe/data_import/data_exporter.js:228 +#: public/js/frappe/data_import/data_exporter.js:229 msgid "{0} records will be exported" msgstr "" @@ -30607,11 +30735,11 @@ msgstr "" msgid "{0} {1} already exists" msgstr "" -#: model/base_document.py:908 +#: model/base_document.py:909 msgid "{0} {1} cannot be \"{2}\". It should be one of \"{3}\"" msgstr "" -#: utils/nestedset.py:337 +#: utils/nestedset.py:340 msgid "{0} {1} cannot be a leaf node as it has children" msgstr "" @@ -30627,15 +30755,15 @@ msgstr "" msgid "{0} {1} not found" msgstr "" -#: model/delete_doc.py:242 +#: model/delete_doc.py:251 msgid "{0} {1}: Submitted Record cannot be deleted. You must {2} Cancel {3} it first." msgstr "" -#: model/base_document.py:1026 +#: model/base_document.py:1027 msgid "{0}, Row {1}" msgstr "" -#: model/base_document.py:1031 +#: model/base_document.py:1032 msgid "{0}: '{1}' ({3}) will get truncated, as max characters allowed is {2}" msgstr "" @@ -30719,7 +30847,7 @@ msgstr "" msgid "{0}: Permission at level 0 must be set before higher levels are set" msgstr "" -#: public/js/frappe/form/controls/data.js:50 +#: public/js/frappe/form/controls/data.js:51 msgid "{0}: You can increase the limit for the field if required via {1}" msgstr "" @@ -30728,7 +30856,7 @@ msgid "{0}: fieldname cannot be set to reserved keyword {1}" msgstr "" #: contacts/doctype/address/address.js:35 -#: contacts/doctype/contact/contact.js:83 +#: contacts/doctype/contact/contact.js:88 #: public/js/frappe/views/workspace/workspace.js:170 msgid "{0}: {1}" msgstr "" @@ -30803,8 +30931,8 @@ msgstr "" msgid "{} field cannot be empty." msgstr "" -#: email/doctype/email_account/email_account.py:200 -#: email/doctype/email_account/email_account.py:208 +#: email/doctype/email_account/email_account.py:216 +#: email/doctype/email_account/email_account.py:224 msgid "{} has been disabled. It can only be enabled if {} is checked." msgstr "" diff --git a/frappe/locale/sv.po b/frappe/locale/sv.po index 40911e214d..f9bd261dfa 100644 --- a/frappe/locale/sv.po +++ b/frappe/locale/sv.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: frappe\n" "Report-Msgid-Bugs-To: developers@frappe.io\n" -"POT-Creation-Date: 2024-06-30 09:33+0000\n" -"PO-Revision-Date: 2024-07-02 15:49\n" +"POT-Creation-Date: 2024-07-07 09:33+0000\n" +"PO-Revision-Date: 2024-07-14 17:15\n" "Last-Translator: developers@frappe.io\n" "Language-Team: Swedish\n" "MIME-Version: 1.0\n" @@ -540,7 +540,7 @@ msgstr "

E-post Svar Exempel

\n\n" "- Kund: {{ customer }}\n" "- Belopp: {{ grand_total }}\n" "\n\n" -"

Hur man får fältnamn

\n\n" +"

Hur hämtas fältnamn

\n\n" "

Fältnamn som kan använda i e-post mall är fält i dokument som du skickar e-post meddelande från. Ta reda på fält namn för alla dokument via Inställningar > Anpassa formulär vy och välja dokument typ (t.ex. Försäljning Faktura)

\n\n" "

Mallar

\n\n" "

Mallar kompileras med Jinja Templating Language. För att lära dig mer om Jinja, läs denna dokumentation.

\n" @@ -1182,8 +1182,8 @@ msgid "Add Child" msgstr "Lägg till Underval" #: public/js/frappe/views/kanban/kanban_board.html:4 -#: public/js/frappe/views/reports/query_report.js:1696 -#: public/js/frappe/views/reports/query_report.js:1699 +#: public/js/frappe/views/reports/query_report.js:1681 +#: public/js/frappe/views/reports/query_report.js:1684 #: public/js/frappe/views/reports/report_view.js:324 #: public/js/frappe/views/reports/report_view.js:349 msgid "Add Column" @@ -1292,7 +1292,7 @@ msgstr "Lägg till Mall" #. Label of the add_total_row (Check) field in DocType 'Report' #: core/doctype/report/report.json msgid "Add Total Row" -msgstr "Lägg till Totalt Rad" +msgstr "Lägg till Totalt Antal Rader" #. Label of the add_unsubscribe_link (Check) field in DocType 'Email Queue' #: email/doctype/email_queue/email_queue.json @@ -3154,7 +3154,7 @@ msgstr "Bakgrund Jobb" #. Report' #: desk/doctype/system_health_report/system_health_report.json msgid "Background Jobs Check" -msgstr "Bakgrund Jobb Koll" +msgstr "Bakgrund Jobb Status" #. Label of the background_jobs_queue (Autocomplete) field in DocType 'Webhook' #: integrations/doctype/webhook/webhook.json @@ -3407,7 +3407,7 @@ msgstr "Faktura Kontakt" #. Label of the binary_logging (Data) field in DocType 'System Health Report' #: desk/doctype/system_health_report/system_health_report.json msgid "Binary Logging" -msgstr "Fakturering Logg" +msgstr "Binär Logg" #. Label of the bio (Small Text) field in DocType 'User' #. Label of the bio (Small Text) field in DocType 'About Us Team Member' @@ -3899,6 +3899,7 @@ msgstr "Kalender Namn" #. Name of a DocType #: desk/doctype/calendar_view/calendar_view.json +#: public/js/frappe/list/base_list.js:208 msgid "Calendar View" msgstr "Kalender Vy" @@ -4075,7 +4076,7 @@ msgstr "Kan inte Hämta Värden" msgid "Cannot Remove" msgstr "Kan inte Ta Bort" -#: model/base_document.py:1072 +#: model/base_document.py:1073 msgid "Cannot Update After Submit" msgstr "Kan inte Uppdatera efter Godkännande" @@ -4163,7 +4164,7 @@ msgstr "Kan inte ta bort system skapad fält {0}. Dölj det ist msgid "Cannot delete {0}" msgstr "Kan inte radera {0}" -#: utils/nestedset.py:296 +#: utils/nestedset.py:299 msgid "Cannot delete {0} as it has child nodes" msgstr "Kan inte radera {0} eftersom det har underordnade noder" @@ -4171,7 +4172,7 @@ msgstr "Kan inte radera {0} eftersom det har underordnade noder" msgid "Cannot edit Standard Dashboards" msgstr "Kan inte redigera standard översikt panel" -#: email/doctype/notification/notification.py:121 +#: email/doctype/notification/notification.py:122 msgid "Cannot edit Standard Notification. To edit, please disable this and duplicate it" msgstr "Kan inte redigera standard avisering. Kopiera och skapa ny" @@ -4240,7 +4241,7 @@ msgstr "Kan inte ta bort ID fält" msgid "Cannot set 'Report' permission if 'Only If Creator' permission is set" msgstr "Kan inte ange \"Rapport\" behörighet om behörighet \"Endast om Ägare\" är angiven" -#: email/doctype/notification/notification.py:137 +#: email/doctype/notification/notification.py:138 msgid "Cannot set Notification on Document Type {0}" msgstr "Kan inte ange Avisering för DocType {0}" @@ -4354,7 +4355,7 @@ msgstr "Ändra" #: tests/test_translate.py:99 msgctxt "Coins" msgid "Change" -msgstr "Ändra" +msgstr "Växel" #. Label of the label (Data) field in DocType 'Customize Form' #: custom/doctype/customize_form/customize_form.json @@ -4415,6 +4416,8 @@ msgstr "Diagram Inställningar" #. Label of the chart_name (Link) field in DocType 'Workspace Chart' #: desk/doctype/dashboard_chart/dashboard_chart.json #: desk/doctype/workspace_chart/workspace_chart.json +#: public/js/frappe/views/reports/query_report.js:289 +#: public/js/frappe/widgets/widget_dialog.js:137 msgid "Chart Name" msgstr "Diagram Namn" @@ -4831,7 +4834,7 @@ msgctxt "Shrink code field." msgid "Collapse" msgstr "Fäll In" -#: public/js/frappe/views/reports/query_report.js:1979 +#: public/js/frappe/views/reports/query_report.js:1964 #: public/js/frappe/views/treeview.js:121 msgid "Collapse All" msgstr "Fäll In Alla" @@ -6362,6 +6365,10 @@ msgstr "Översikt Panel Namn" msgid "Dashboard Settings" msgstr "Översikt Panel Inställningar" +#: public/js/frappe/list/base_list.js:205 +msgid "Dashboard View" +msgstr "Översikt Panel Vy" + #. Label of the tab_break_2 (Tab Break) field in DocType 'Workspace' #: desk/doctype/workspace/workspace.json msgid "Dashboards" @@ -6943,7 +6950,8 @@ msgid "Department" msgstr "Avdelning" #. Label of the dependencies (Data) field in DocType 'Workspace Link' -#: desk/doctype/workspace_link/workspace_link.json www/attribution.html:29 +#: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:318 www/attribution.html:29 msgid "Dependencies" msgstr "Beroenden " @@ -7405,6 +7413,7 @@ msgstr "Status för följande tillstånd är ändrad:
{0}
5, <10 or =324. For ranges, use 5:10 (for values between 5 & 10)." msgstr "För jämförelse, använd >5, <10 eller = 324. För intervall, använd 5:10 (för värden mellan 5 och 10)." @@ -10730,7 +10740,7 @@ msgstr "Från Datum" msgid "From Date Field" msgstr "Från Datum" -#: public/js/frappe/views/reports/query_report.js:1704 +#: public/js/frappe/views/reports/query_report.js:1689 msgid "From Document Type" msgstr "Från DocType" @@ -10826,6 +10836,10 @@ msgstr "GNU General Public License" msgid "Gantt" msgstr "Gantt" +#: public/js/frappe/list/base_list.js:206 +msgid "Gantt View" +msgstr "Gantt Vy" + #. Label of the gender (Link) field in DocType 'Contact' #. Name of a DocType #. Label of the gender (Data) field in DocType 'Gender' @@ -12197,6 +12211,10 @@ msgstr "Bild Höjd" msgid "Image Link" msgstr "Bild Länk" +#: public/js/frappe/list/base_list.js:209 +msgid "Image View" +msgstr "Visa Bild" + #. Label of the image_width (Float) field in DocType 'Letter Head' #. Label of the footer_image_width (Float) field in DocType 'Letter Head' #: printing/doctype/letter_head/letter_head.json @@ -12468,6 +12486,10 @@ msgstr "Inkorg" msgid "Inbox User" msgstr "Inkorg Användare" +#: public/js/frappe/list/base_list.js:210 +msgid "Inbox View" +msgstr "Inkorg Vy" + #. Label of the include_name_field (Check) field in DocType 'Form Tour' #: desk/doctype/form_tour/form_tour.json msgid "Include Name Field" @@ -12487,11 +12509,11 @@ msgstr "Inkludera Tema från Appar" msgid "Include Web View Link in Email" msgstr "Inkludera Länk till Webbvy i E-post" -#: public/js/frappe/views/reports/query_report.js:1521 +#: public/js/frappe/views/reports/query_report.js:1506 msgid "Include filters" msgstr "Inkludera Filter" -#: public/js/frappe/views/reports/query_report.js:1513 +#: public/js/frappe/views/reports/query_report.js:1498 msgid "Include indentation" msgstr "Inkludera Fördjupning" @@ -12647,7 +12669,7 @@ msgstr "Infoga \tOvan" #. Label of the insert_after (Select) field in DocType 'Custom Field' #: custom/doctype/custom_field/custom_field.json -#: public/js/frappe/views/reports/query_report.js:1744 +#: public/js/frappe/views/reports/query_report.js:1729 msgid "Insert After" msgstr "Infoga Efter" @@ -12854,7 +12876,7 @@ msgstr "Ogiltig uttryck 'beroende på' i filter {0}" msgid "Invalid \"mandatory_depends_on\" expression" msgstr "Ogiltigt uttryck för \"obligatoriskt_beror_på\"" -#: utils/nestedset.py:177 +#: utils/nestedset.py:178 msgid "Invalid Action" msgstr "Ogiltig åtgärd" @@ -13048,7 +13070,7 @@ msgstr "Ogiltiga begäran argument" #: integrations/doctype/connected_app/connected_app.py:173 msgid "Invalid state." -msgstr "Ogiltig status." +msgstr "Ogiltigt tillstånd." #: core/doctype/data_import/importer.py:423 msgid "Invalid template file for import" @@ -13225,6 +13247,7 @@ msgstr "Är Publicerad Fält måste vara giltig Fält Namn" #. Label of the is_query_report (Check) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:336 msgid "Is Query Report" msgstr "Är Dataförfråga Rapport" @@ -13328,7 +13351,7 @@ msgstr "Artikel Titel" msgid "Item Type" msgstr "Artikel Typ" -#: utils/nestedset.py:228 +#: utils/nestedset.py:229 msgid "Item cannot be added to its own descendants" msgstr "Artikel kan inte läggas till egna undertyper" @@ -13453,6 +13476,7 @@ msgstr "Anslag Tavla" #. Label of the kanban_board (Link) field in DocType 'Workspace Shortcut' #: desk/doctype/kanban_board/kanban_board.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json +#: public/js/frappe/widgets/widget_dialog.js:509 msgid "Kanban Board" msgstr "Anslag Tavla" @@ -13472,6 +13496,10 @@ msgctxt "Button in kanban view menu" msgid "Kanban Settings" msgstr "Anslag Tavla Inställningar" +#: public/js/frappe/list/base_list.js:207 +msgid "Kanban View" +msgstr "Anslag Tavla Vy" + #. Description of a DocType #: core/doctype/activity_log/activity_log.json msgid "Keep track of all update feeds" @@ -13717,7 +13745,10 @@ msgstr "LDAP Inställningar felaktiga. validering svar var: {0}" #: desk/doctype/workspace_quick_list/workspace_quick_list.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: printing/page/print_format_builder/print_format_builder.js:474 +#: public/js/frappe/widgets/widget_dialog.js:187 #: public/js/frappe/widgets/widget_dialog.js:255 +#: public/js/frappe/widgets/widget_dialog.js:304 +#: public/js/frappe/widgets/widget_dialog.js:421 #: public/js/frappe/widgets/widget_dialog.js:645 #: public/js/frappe/widgets/widget_dialog.js:678 #: templates/form_grid/fields.html:37 @@ -13848,7 +13879,7 @@ msgstr "Senaste Tilldelning Datum" #. Option for the 'Timespan' (Select) field in DocType 'Dashboard Chart' #: desk/doctype/dashboard_chart/dashboard_chart.json msgid "Last Quarter" -msgstr "Sista Kvartal" +msgstr "Förra Kvartal" #. Label of the last_reset_password_key_generated_on (Datetime) field in #. DocType 'User' @@ -14284,6 +14315,8 @@ msgstr "Länk Titel" #. Label of the link_to (Dynamic Link) field in DocType 'Workspace Shortcut' #: desk/doctype/workspace_link/workspace_link.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json +#: public/js/frappe/widgets/widget_dialog.js:285 +#: public/js/frappe/widgets/widget_dialog.js:430 msgid "Link To" msgstr "Länk Till" @@ -14293,6 +14326,7 @@ msgstr "Länk Till i Rad" #. Label of the link_type (Select) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:277 msgid "Link Type" msgstr "Länk Typ" @@ -14336,7 +14370,7 @@ msgstr "Länkad Med" #. Label of the links (Table) field in DocType 'Customize Form' #. Label of the links (Table) field in DocType 'Workspace' #: contacts/doctype/address/address.js:39 contacts/doctype/address/address.json -#: contacts/doctype/contact/contact.js:87 contacts/doctype/contact/contact.json +#: contacts/doctype/contact/contact.js:92 contacts/doctype/contact/contact.json #: core/doctype/doctype/doctype.json #: custom/doctype/customize_form/customize_form.json #: desk/doctype/workspace/workspace.json public/js/frappe/form/toolbar.js:377 @@ -14389,6 +14423,10 @@ msgctxt "Button in list view menu" msgid "List Settings" msgstr "Lista Inställningar" +#: public/js/frappe/list/base_list.js:203 +msgid "List View" +msgstr "List Vy" + #. Name of a DocType #: desk/doctype/list_view_settings/list_view_settings.json msgid "List View Settings" @@ -14425,7 +14463,7 @@ msgstr "Listor" msgid "Load Balancing" msgstr "Last Balansering" -#: public/js/frappe/list/base_list.js:378 +#: public/js/frappe/list/base_list.js:386 #: website/doctype/blog_post/templates/blog_post_list.html:50 #: website/doctype/help_article/templates/help_article_list.html:30 msgid "Load More" @@ -14439,7 +14477,7 @@ msgstr "Ladda Mer Korenspondens" #: core/page/permission_manager/permission_manager.js:165 #: public/js/frappe/form/controls/multicheck.js:13 #: public/js/frappe/form/linked_with.js:13 -#: public/js/frappe/list/base_list.js:490 +#: public/js/frappe/list/base_list.js:498 #: public/js/frappe/list/list_view.js:335 public/js/frappe/ui/listing.html:16 #: public/js/frappe/views/reports/query_report.js:1017 msgid "Loading" @@ -14467,7 +14505,7 @@ msgstr "Laddar versioner..." #: public/js/frappe/views/kanban/kanban_board.html:11 #: public/js/frappe/widgets/chart_widget.js:50 #: public/js/frappe/widgets/number_card_widget.js:174 -#: public/js/frappe/widgets/quick_list_widget.js:126 +#: public/js/frappe/widgets/quick_list_widget.js:128 msgid "Loading..." msgstr "Laddar..." @@ -14852,6 +14890,10 @@ msgstr "Mapp" msgid "Map Columns" msgstr "Mappa Kolumner" +#: public/js/frappe/list/base_list.js:212 +msgid "Map View" +msgstr "Mapp Vy" + #: public/js/frappe/data_import/import_preview.js:290 msgid "Map columns from {0} to fields in {1}" msgstr "Mappa Kolumner från {0} till fält i {1}" @@ -15081,7 +15123,7 @@ msgstr "Meny" msgid "Merge with existing" msgstr "Slå samman med befintlig" -#: utils/nestedset.py:304 +#: utils/nestedset.py:307 msgid "Merging is only possible between Group-to-Group or Leaf Node-to-Leaf Node" msgstr "Sammanslafning är endast möjlig mellan grupp till grupp eller underordnad till underordnad" @@ -15237,6 +15279,10 @@ msgstr "Meta Titel för SEO" msgid "Method" msgstr "Sätt" +#: __init__.py:936 +msgid "Method Not Allowed" +msgstr "Metod ej Tillåten" + #: desk/doctype/number_card/number_card.py:70 msgid "Method is required to create a number card" msgstr "Sätt erfodras för att skapa nummerkort" @@ -15628,7 +15674,7 @@ msgstr "Flytta till nästa steg när du klickar i det markerade området." msgid "Mozilla doesn't support :has() so you can pass parent selector here as workaround" msgstr "Mozilla stöder inte :has() så du kan skicka överordnad väljare här som lösning" -#: utils/nestedset.py:328 +#: utils/nestedset.py:331 msgid "Multiple root nodes not allowed." msgstr "Flera rot noder är inte tillåtna." @@ -15866,7 +15912,7 @@ msgstr "Arbetsyta Ansvarig roll erfodras för att dölja/visa publika arbetsyto msgid "Negative Value" msgstr "Negativ Värde" -#: utils/nestedset.py:93 +#: utils/nestedset.py:94 msgid "Nested set error. Please contact the Administrator." msgstr "Nested set fel. Kontakta Administratör." @@ -16074,7 +16120,7 @@ msgstr "Ny {0}: {1}" #: utils/change_log.py:373 msgid "New {} releases for the following apps are available" -msgstr "Nya {} utgåvor för följande appar finns tillgängliga" +msgstr "Nya {} versioner för följande appar finns tillgängliga" #: core/doctype/user/user.py:753 msgid "Newly created user {0} has no roles enabled." @@ -16213,7 +16259,7 @@ msgstr "Nästa på Klick" #: public/js/form_builder/utils.js:341 #: public/js/frappe/form/controls/link.js:475 #: public/js/frappe/list/list_sidebar_group_by.js:223 -#: public/js/frappe/views/reports/query_report.js:1541 +#: public/js/frappe/views/reports/query_report.js:1526 #: website/doctype/help_article/templates/help_article.html:26 msgid "No" msgstr "Nej" @@ -16257,7 +16303,7 @@ msgstr "Ingen Data" msgid "No Data to Show" msgstr "Ingen Data att visa" -#: public/js/frappe/widgets/quick_list_widget.js:131 +#: public/js/frappe/widgets/quick_list_widget.js:133 msgid "No Data..." msgstr "Ingen Data..." @@ -16724,7 +16770,7 @@ msgstr "Inte Aktiv" msgid "Not allowed for {0}: {1}" msgstr "Ej tillåtet för {0}: {1}" -#: email/doctype/notification/notification.py:391 +#: email/doctype/notification/notification.py:392 msgid "Not allowed to attach {0} document, please enable Allow Print For {0} in Print Settings" msgstr "Ej Tillåtet att bifoga {0} dokument, aktivera \"Tillåt Utskrift\" för {0} i Utskrift Inställningar" @@ -16843,7 +16889,7 @@ msgstr "Inget mer att göra om" msgid "Nothing left to undo" msgstr "Inget mer att ångra" -#: public/js/frappe/list/base_list.js:362 +#: public/js/frappe/list/base_list.js:370 #: public/js/frappe/views/reports/query_report.js:105 #: templates/includes/list/list.html:7 #: website/doctype/blog_post/templates/blog_post_list.html:41 @@ -17047,7 +17093,7 @@ msgstr "Antal dagar efter vilka dokument Webb Vy länk delad i e-post kommer att #. Label of the cache_keys (Int) field in DocType 'System Health Report' #: desk/doctype/system_health_report/system_health_report.json msgid "Number of keys" -msgstr "Antal nycklar" +msgstr "Antal Nycklar" #. Label of the onsite_backups (Int) field in DocType 'System Health Report' #: desk/doctype/system_health_report/system_health_report.json @@ -17249,9 +17295,14 @@ msgstr "{0}, {1} skrev" #. Label of the onboard (Check) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:330 msgid "Onboard" msgstr "Introduktion" +#: public/js/frappe/widgets/widget_dialog.js:236 +msgid "Onboarding Name" +msgstr "Introduktion Namn" + #. Name of a DocType #: desk/doctype/onboarding_permission/onboarding_permission.json msgid "Onboarding Permission" @@ -17359,6 +17410,7 @@ msgstr "Endast utkast dokument kan förkastas" #. Label of the only_for (Link) field in DocType 'Workspace Link' #: desk/doctype/workspace_link/workspace_link.json +#: public/js/frappe/widgets/widget_dialog.js:323 msgid "Only for" msgstr "Endast för" @@ -17658,7 +17710,7 @@ msgstr "Utgående (SMTP) Inställningar" #. Health Report' #: desk/doctype/system_health_report/system_health_report.json msgid "Outgoing Emails (Last 7 days)" -msgstr "Utgående E-post (sista 7 dagar)" +msgstr "Utgående E-post (Senaste 7 dagar)" #. Label of the smtp_server (Data) field in DocType 'Email Account' #. Label of the smtp_server (Data) field in DocType 'Email Domain' @@ -17708,7 +17760,7 @@ msgstr "PATCH" #: printing/page/print/print.js:71 #: public/js/frappe/form/templates/print_layout.html:44 -#: public/js/frappe/views/reports/query_report.js:1669 +#: public/js/frappe/views/reports/query_report.js:1654 msgid "PDF" msgstr "PDF" @@ -18100,8 +18152,8 @@ msgid "Password not found for {0} {1} {2}" msgstr "Lösenord hittades inte för {0} {1} {2}" #: core/doctype/user/user.py:1021 -msgid "Password reset instructions have been sent to your email" -msgstr "Lösenord Återställning instruktioner har skickats till din E-post" +msgid "Password reset instructions have been sent to {}'s email" +msgstr "Instruktioner för återställning av lösenord är skickade till {}'s e-post" #: www/update-password.html:164 msgid "Password set" @@ -18198,24 +18250,24 @@ msgstr "Pågående" #. Request' #: website/doctype/personal_data_deletion_request/personal_data_deletion_request.json msgid "Pending Approval" -msgstr "Pågående Godkännande" +msgstr "Godkännande Kö" #. Label of the pending_emails (Int) field in DocType 'System Health Report' #: desk/doctype/system_health_report/system_health_report.json msgid "Pending Emails" -msgstr "Pågående E-post" +msgstr "E-post Kö" #. Label of the pending_jobs (Int) field in DocType 'System Health Report #. Queue' #: desk/doctype/system_health_report_queue/system_health_report_queue.json msgid "Pending Jobs" -msgstr "Pågående Jobb" +msgstr "Jobb Kö" #. Option for the 'Status' (Select) field in DocType 'Personal Data Deletion #. Request' #: website/doctype/personal_data_deletion_request/personal_data_deletion_request.json msgid "Pending Verification" -msgstr "Pågående Verifiering" +msgstr "Verifiering Kö" #. Option for the 'Type' (Select) field in DocType 'DocField' #. Option for the 'Field Type' (Select) field in DocType 'Custom Field' @@ -18500,7 +18552,7 @@ msgstr "Kontrollera OpenID Configuration URL" msgid "Please check the filter values set for Dashboard Chart: {}" msgstr "Kontrollera filter värden angivna för Översikt Panel Diagram: {}" -#: model/base_document.py:872 +#: model/base_document.py:873 msgid "Please check the value of \"Fetch From\" set for field {0}" msgstr "Kontrollera värde för uppsättning 'Hämta från' för fält {0}" @@ -18802,11 +18854,11 @@ msgstr "Specificera" msgid "Please specify a valid parent DocType for {0}" msgstr "Ange giltig överordnad DocType för {0}" -#: email/doctype/notification/notification.py:87 +#: email/doctype/notification/notification.py:88 msgid "Please specify which date field must be checked" msgstr "Ange Datum Fält som måste kontrolleras" -#: email/doctype/notification/notification.py:90 +#: email/doctype/notification/notification.py:91 msgid "Please specify which value field must be checked" msgstr "Ange Värde Fält som måste kontrolleras" @@ -19139,7 +19191,7 @@ msgstr "Primär nyckel för doctype {0} kan inte ändras eftersom det finns befi #: public/js/frappe/form/templates/print_layout.html:46 #: public/js/frappe/form/toolbar.js:332 public/js/frappe/form/toolbar.js:344 #: public/js/frappe/list/bulk_operations.js:87 -#: public/js/frappe/views/reports/query_report.js:1655 +#: public/js/frappe/views/reports/query_report.js:1640 #: public/js/frappe/views/reports/report_view.js:1460 #: public/js/frappe/views/treeview.js:469 www/printview.html:18 msgid "Print" @@ -20001,7 +20053,7 @@ msgstr "Uppdatera" msgid "Rebuild Tree" msgstr "Uppdatera Träd Vy" -#: utils/nestedset.py:176 +#: utils/nestedset.py:177 msgid "Rebuilding of tree is not supported for {}" msgstr "Uppdatering av Träd Vy stöds inte för {}" @@ -20359,7 +20411,7 @@ msgstr "Referens" #: public/js/frappe/desk.js:533 public/js/frappe/form/form.js:1196 #: public/js/frappe/form/templates/print_layout.html:6 #: public/js/frappe/list/base_list.js:66 -#: public/js/frappe/views/reports/query_report.js:1644 +#: public/js/frappe/views/reports/query_report.js:1629 #: public/js/frappe/views/treeview.js:475 #: public/js/frappe/widgets/chart_widget.js:290 #: public/js/frappe/widgets/number_card_widget.js:324 @@ -20457,7 +20509,7 @@ msgstr "Ladda om" msgid "Reload File" msgstr "Ladda om Fil" -#: public/js/frappe/list/base_list.js:242 +#: public/js/frappe/list/base_list.js:250 msgid "Reload List" msgstr "Ladda om Lista" @@ -20726,7 +20778,7 @@ msgstr "Rapport Ansvarig" #: core/doctype/report/report.json #: desk/doctype/dashboard_chart/dashboard_chart.json #: desk/doctype/number_card/number_card.json -#: public/js/frappe/views/reports/query_report.js:1825 +#: public/js/frappe/views/reports/query_report.js:1810 msgid "Report Name" msgstr "Rapport Namn" @@ -20749,6 +20801,10 @@ msgstr "Rapportera Referens DocType" msgid "Report Type" msgstr "Rapport Typ" +#: public/js/frappe/list/base_list.js:204 +msgid "Report View" +msgstr "Rapport Vy" + #: core/doctype/doctype/doctype.py:1780 msgid "Report cannot be set for Single types" msgstr "Rapport kan inte anges för Enskilda Typer" @@ -20783,7 +20839,7 @@ msgstr "Rapport är uppdaterad" msgid "Report was not saved (there were errors)" msgstr "Rapport är inte sparad (det fanns fel)" -#: public/js/frappe/views/reports/query_report.js:1863 +#: public/js/frappe/views/reports/query_report.js:1848 msgid "Report with more than 10 columns looks better in Landscape mode." msgstr "Rapport med mer än 10 kolumner ser bättre ut i Liggande Läge." @@ -21369,7 +21425,7 @@ msgstr "Roller HTML" msgid "Roles can be set for users from their User page." msgstr "Roller kan anges för användare från deras Användarsida." -#: utils/nestedset.py:277 +#: utils/nestedset.py:280 msgid "Root {0} cannot be deleted" msgstr "Root {0} kan inte raderas" @@ -21442,7 +21498,7 @@ msgstr "Rad #" msgid "Row # {0}: Non administrator user can not set the role {1} to the custom doctype" msgstr "Rad # {0}: Användare som inte är administratör kan inte ange roll {1} till anpassad Dokument Typ" -#: model/base_document.py:903 +#: model/base_document.py:904 msgid "Row #{0}:" msgstr "Rad # {0}:" @@ -21726,11 +21782,11 @@ msgstr "Lördag" #: public/js/frappe/views/kanban/kanban_settings.js:45 #: public/js/frappe/views/kanban/kanban_settings.js:189 #: public/js/frappe/views/kanban/kanban_view.js:343 -#: public/js/frappe/views/reports/query_report.js:1817 +#: public/js/frappe/views/reports/query_report.js:1802 #: public/js/frappe/views/reports/report_view.js:1640 #: public/js/frappe/views/workspace/workspace.js:501 #: public/js/frappe/widgets/base_widget.js:142 -#: public/js/frappe/widgets/quick_list_widget.js:117 +#: public/js/frappe/widgets/quick_list_widget.js:119 #: public/js/print_format_builder/print_format_builder.bundle.js:15 #: public/js/workflow_builder/workflow_builder.bundle.js:33 msgid "Save" @@ -21757,7 +21813,7 @@ msgstr "Spara Anpassningar" msgid "Save Filter" msgstr "Spara Filter " -#: public/js/frappe/views/reports/query_report.js:1820 +#: public/js/frappe/views/reports/query_report.js:1805 msgid "Save Report" msgstr "Spara Rapport" @@ -22881,7 +22937,7 @@ msgid "Set Filters" msgstr "Ange Filter" #: public/js/frappe/widgets/chart_widget.js:395 -#: public/js/frappe/widgets/quick_list_widget.js:102 +#: public/js/frappe/widgets/quick_list_widget.js:104 msgid "Set Filters for {0}" msgstr "Ange Filter för {0}" @@ -23118,7 +23174,7 @@ msgstr "Inställningar > Användar Behörigheter" msgid "Setup Approval Workflows" msgstr "Ange Arbetsflöde för Godkännande " -#: public/js/frappe/views/reports/query_report.js:1690 +#: public/js/frappe/views/reports/query_report.js:1675 #: public/js/frappe/views/reports/report_view.js:1618 msgid "Setup Auto Email" msgstr "Automatisk E-post Rapport" @@ -25154,7 +25210,7 @@ msgid "The Client ID obtained from the Google Cloud Console under " msgstr "Klient ID som erhållits från Google Cloud Console under \"API och tjänster\" > \"Inloggningsuppgifter\"" -#: email/doctype/notification/notification.py:130 +#: email/doctype/notification/notification.py:131 msgid "The Condition '{0}' is invalid" msgstr "Villkor '{0}' är ogiltig" @@ -25613,7 +25669,7 @@ msgstr "Detta format används om land specifika format inte hittas" msgid "This goes above the slideshow." msgstr "Text ovanför Bildspel." -#: public/js/frappe/views/reports/query_report.js:2027 +#: public/js/frappe/views/reports/query_report.js:2012 msgid "This is a background report. Please set the appropriate filters and then generate a new one." msgstr "Detta är bakgrund rapport. Ange lämplig filter och skapa ny rapport." @@ -26284,16 +26340,16 @@ msgstr "Totalt" #. Report' #: desk/doctype/system_health_report/system_health_report.json msgid "Total Background Workers" -msgstr "Totalt Bakgrund Tjänster" +msgstr "Totalt Antal Bakgrund Tjänster" #. Label of the total_errors (Int) field in DocType 'System Health Report' #: desk/doctype/system_health_report/system_health_report.json msgid "Total Errors (last 1 day)" -msgstr "Totalt Fel (sista dagen)" +msgstr "Totalt Antal Fel (Senaste dag)" #: public/js/frappe/ui/capture.js:259 msgid "Total Images" -msgstr "Totalt Bilder" +msgstr "Totalt Antal Bilder" #. Label of the total_outgoing_emails (Int) field in DocType 'System Health #. Report' @@ -26322,18 +26378,18 @@ msgstr "Totalt Användare" #. Label of the total_views (Int) field in DocType 'Newsletter' #: email/doctype/newsletter/newsletter.json msgid "Total Views" -msgstr "Totalt Visningar" +msgstr "Totalt Antal Visningar" #. Label of the total_working_time (Duration) field in DocType 'RQ Worker' #: core/doctype/rq_worker/rq_worker.json msgid "Total Working Time" -msgstr "Totalt Antal Arbetstimmar" +msgstr "Totalt Antal Arbetade Timmar" #. Description of the 'Initial Sync Count' (Select) field in DocType 'Email #. Account' #: email/doctype/email_account/email_account.json msgid "Total number of emails to sync in initial sync process " -msgstr "Totalt antal E-post meddelande som ska synkroniseras i första synkronisering behandling" +msgstr "Totalt antal E-post meddelande som ska synkroniseras i första synkronisering " #: public/js/frappe/views/reports/report_view.js:1178 msgid "Totals" @@ -26341,7 +26397,7 @@ msgstr "Totals" #: public/js/frappe/views/reports/report_view.js:1153 msgid "Totals Row" -msgstr "Totalt Rad" +msgstr "Totalt Antal Rader" #. Label of the trace_id (Data) field in DocType 'Error Log' #: core/doctype/error_log/error_log.json @@ -26478,6 +26534,10 @@ msgstr "Skräp" msgid "Tree" msgstr "Träd Vy" +#: public/js/frappe/list/base_list.js:211 +msgid "Tree View" +msgstr "Träd Vy" + #. Description of the 'Is Tree' (Check) field in DocType 'DocType' #: core/doctype/doctype/doctype.json msgid "Tree structures are implemented using Nested Set" @@ -26583,6 +26643,7 @@ msgstr "Två Faktor Autentisering Sätt" #: desk/doctype/workspace_link/workspace_link.json #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: public/js/frappe/views/file/file_view.js:337 +#: public/js/frappe/widgets/widget_dialog.js:399 #: social/doctype/energy_point_log/energy_point_log.json #: website/doctype/web_template/web_template.json www/attribution.html:35 msgid "Type" @@ -26665,6 +26726,7 @@ msgstr "URI för att ta emot behörighet kod när Användare tillåter tillgång #: desk/doctype/workspace_shortcut/workspace_shortcut.json #: integrations/doctype/integration_request/integration_request.json #: integrations/doctype/webhook_request_log/webhook_request_log.json +#: public/js/frappe/widgets/widget_dialog.js:469 #: website/doctype/top_bar_item/top_bar_item.json #: website/doctype/website_slideshow_item/website_slideshow_item.json msgid "URL" @@ -27341,7 +27403,7 @@ msgid "User Permission" msgstr "Användare Behörighet" #: core/page/permission_manager/permission_manager_help.html:30 -#: public/js/frappe/views/reports/query_report.js:1804 +#: public/js/frappe/views/reports/query_report.js:1789 #: public/js/frappe/views/reports/report_view.js:1666 msgid "User Permissions" msgstr "Användare Behörigheter" @@ -27659,7 +27721,7 @@ msgstr "Värde Ändrad" msgid "Value To Be Set" msgstr "Värde som ska Anges" -#: model/base_document.py:965 model/document.py:682 +#: model/base_document.py:966 model/document.py:682 msgid "Value cannot be changed for {0}" msgstr "Värde kan inte ändras för {0}" @@ -27702,7 +27764,7 @@ msgstr "Värde måste vara ett av {0}" msgid "Value to Validate" msgstr "Värde att Validera" -#: model/base_document.py:1035 +#: model/base_document.py:1036 msgid "Value too big" msgstr "Värde för hög" @@ -27801,7 +27863,7 @@ msgid "View Full Log" msgstr "Visa Full Logg" #: public/js/frappe/views/treeview.js:463 -#: public/js/frappe/widgets/quick_list_widget.js:245 +#: public/js/frappe/widgets/quick_list_widget.js:247 msgid "View List" msgstr "Visa Lista" @@ -28569,7 +28631,7 @@ msgstr "Arbetsflöde Tillstånd inte angiven" #: model/workflow.py:197 model/workflow.py:205 msgid "Workflow State transition not allowed from {0} to {1}" -msgstr "Arbetsflöde Övergång inte tillåten från {0} till {1}" +msgstr "Arbetsflöde Tillstånd Övergång inte tillåten från {0} till {1}" #: model/workflow.py:320 msgid "Workflow Status" @@ -28683,7 +28745,7 @@ msgstr "Slutför" msgid "Write" msgstr "Skriva" -#: model/base_document.py:875 +#: model/base_document.py:876 msgid "Wrong Fetch From value" msgstr "Fel Hämtning Från Värde" @@ -28770,7 +28832,7 @@ msgstr "Gul" #: public/js/form_builder/utils.js:336 #: public/js/frappe/form/controls/link.js:475 #: public/js/frappe/list/list_sidebar_group_by.js:223 -#: public/js/frappe/views/reports/query_report.js:1541 +#: public/js/frappe/views/reports/query_report.js:1526 #: website/doctype/help_article/templates/help_article.html:25 msgid "Yes" msgstr "Ja" @@ -29983,7 +30045,7 @@ msgstr "via Data Import" msgid "via Google Meet" msgstr "via Google Meet" -#: email/doctype/notification/notification.py:215 +#: email/doctype/notification/notification.py:216 msgid "via Notification" msgstr "via Avisering" @@ -30126,7 +30188,7 @@ msgstr "{0} Moduler" msgid "{0} Name" msgstr "{0} Namn" -#: model/base_document.py:1065 +#: model/base_document.py:1066 msgid "{0} Not allowed to change {1} after submission from {2} to {3}" msgstr "{0} Ej Tillåtet att ändra {1} efter godkännande från {2} till {3}" @@ -30152,10 +30214,6 @@ msgstr "{0} Inställningar" msgid "{0} Tree" msgstr "{0} Träd Vy" -#: public/js/frappe/list/base_list.js:209 -msgid "{0} View" -msgstr "{0} Vy" - #: public/js/frappe/form/footer/form_timeline.js:126 #: public/js/frappe/form/sidebar/form_sidebar.js:86 msgid "{0} Web page views" @@ -30595,7 +30653,7 @@ msgstr "{0} måste börja och sluta med bokstav och får bara innehålla bokstä #: workflow/doctype/workflow/workflow.py:91 msgid "{0} not a valid State" -msgstr "{0} inte en giltig Tillstånd" +msgstr "{0} är inte giltig Tillstånd" #: model/rename_doc.py:380 msgid "{0} not allowed to be renamed" @@ -30770,11 +30828,11 @@ msgstr "{0} {1} är lagd till i Översikt Panel {2}" msgid "{0} {1} already exists" msgstr "{0} {1} finns redan" -#: model/base_document.py:908 +#: model/base_document.py:909 msgid "{0} {1} cannot be \"{2}\". It should be one of \"{3}\"" msgstr "{0} {1} kan inte vara \"{2}\". Det kan vara en av följande: \"{3}\"" -#: utils/nestedset.py:337 +#: utils/nestedset.py:340 msgid "{0} {1} cannot be a leaf node as it has children" msgstr "{0} {1} kan inte vara undernod då den har undernoder" @@ -30794,11 +30852,11 @@ msgstr "{0} {1} hittades inte" msgid "{0} {1}: Submitted Record cannot be deleted. You must {2} Cancel {3} it first." msgstr "{0} {1}: Godkänd Post kan inte raderas. Du måste {2} Annullera {3} det först." -#: model/base_document.py:1026 +#: model/base_document.py:1027 msgid "{0}, Row {1}" msgstr "{0}, Rad {1}" -#: model/base_document.py:1031 +#: model/base_document.py:1032 msgid "{0}: '{1}' ({3}) will get truncated, as max characters allowed is {2}" msgstr "{0}: {1} ({3}) kommer att förminskas då maximum tillåtna antal tecken är {2}" @@ -30891,7 +30949,7 @@ msgid "{0}: fieldname cannot be set to reserved keyword {1}" msgstr "{0}: fältnamn kan inte anges för reserverad sökord {1}" #: contacts/doctype/address/address.js:35 -#: contacts/doctype/contact/contact.js:83 +#: contacts/doctype/contact/contact.js:88 #: public/js/frappe/views/workspace/workspace.js:170 msgid "{0}: {1}" msgstr "{0}: {1}" diff --git a/frappe/model/delete_doc.py b/frappe/model/delete_doc.py index 3d83af16b7..c1c8f2cb70 100644 --- a/frappe/model/delete_doc.py +++ b/frappe/model/delete_doc.py @@ -127,8 +127,17 @@ def delete_doc( # check if links exist if not force: - check_if_doc_is_linked(doc) - check_if_doc_is_dynamically_linked(doc) + try: + check_if_doc_is_linked(doc) + check_if_doc_is_dynamically_linked(doc) + except frappe.LinkExistsError as e: + if doc.meta.has_field("enabled") or doc.meta.has_field("disabled"): + frappe.throw( + _("You can disable this {0} instead of deleting it.").format(_(doctype)), + frappe.LinkExistsError, + ) + else: + raise e update_naming_series(doc) delete_from_table(doctype, name, ignore_doctypes, doc) diff --git a/frappe/model/document.py b/frappe/model/document.py index 01278775b3..d216aebacc 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -238,7 +238,7 @@ class Document(BaseDocument): def raise_no_permission_to(self, perm_type): """Raise `frappe.PermissionError`.""" frappe.flags.error_message = ( - _("Insufficient Permission for {0}").format(self.doctype) + f" ({frappe.bold(_(perm_type))})" + _("Insufficient Permission for {0}").format(_(self.doctype)) + f" ({frappe.bold(_(perm_type))})" ) raise frappe.PermissionError @@ -458,7 +458,7 @@ class Document(BaseDocument): d: Document d.db_update() - def get_doc_before_save(self) -> "Document": + def get_doc_before_save(self) -> "Self": return getattr(self, "_doc_before_save", None) def has_value_changed(self, fieldname): @@ -1031,7 +1031,7 @@ class Document(BaseDocument): "on_cancel": "Cancel", } - if not self.flags.in_insert: + if not self.flags.in_insert and not self.flags.in_delete: # value change is not applicable in insert event_map["on_change"] = "Value Change" diff --git a/frappe/public/icons/timeless/icons.svg b/frappe/public/icons/timeless/icons.svg index 1ea247b405..769c2fbbba 100644 --- a/frappe/public/icons/timeless/icons.svg +++ b/frappe/public/icons/timeless/icons.svg @@ -419,7 +419,7 @@ - + diff --git a/frappe/public/js/form_builder/components/controls/FetchFromControl.vue b/frappe/public/js/form_builder/components/controls/FetchFromControl.vue index 1873a7b5d4..3afdaa69b7 100644 --- a/frappe/public/js/form_builder/components/controls/FetchFromControl.vue +++ b/frappe/public/js/form_builder/components/controls/FetchFromControl.vue @@ -63,7 +63,7 @@ let field_df = computedAsync(async () => { watch( () => props.value, (value) => { - [doctype.value, fieldname.value] = value?.split(".") || ["", ""]; + if (value) [doctype.value, fieldname.value] = value.split(".") || ["", ""]; }, { immediate: true } ); diff --git a/frappe/public/js/frappe/data_import/data_exporter.js b/frappe/public/js/frappe/data_import/data_exporter.js index 6cd0adf029..4ff41ab355 100644 --- a/frappe/public/js/frappe/data_import/data_exporter.js +++ b/frappe/public/js/frappe/data_import/data_exporter.js @@ -67,6 +67,7 @@ frappe.data_import.DataExporter = class DataExporter { columns: 2, on_change: () => this.update_primary_action(), options: this.get_multicheck_options(this.doctype), + sort_options: false, }, ...frappe.meta.get_table_fields(this.doctype).map((df) => { let doctype = df.options; diff --git a/frappe/public/js/frappe/form/controls/data.js b/frappe/public/js/frappe/form/controls/data.js index b090ed3cf2..a66aaa30b8 100644 --- a/frappe/public/js/frappe/form/controls/data.js +++ b/frappe/public/js/frappe/form/controls/data.js @@ -7,10 +7,11 @@ frappe.ui.form.ControlData = class ControlData extends frappe.ui.form.ControlInp make_input() { if (this.$input) return; - let { html_element, input_type } = this.constructor; + let { html_element, input_type, input_mode } = this.constructor; this.$input = $("<" + html_element + ">") .attr("type", input_type) + .attr("inputmode", input_mode) .attr("autocomplete", "off") .addClass("input-with-feedback form-control") .prependTo(this.input_area); diff --git a/frappe/public/js/frappe/form/controls/duration.js b/frappe/public/js/frappe/form/controls/duration.js index 9ef8b3b1e2..66f73060b2 100644 --- a/frappe/public/js/frappe/form/controls/duration.js +++ b/frappe/public/js/frappe/form/controls/duration.js @@ -4,6 +4,13 @@ frappe.ui.form.ControlDuration = class ControlDuration extends frappe.ui.form.Co this.make_picker(); } + validate(value) { + if (!value) { + return null; + } + return super.validate(value); + } + make_picker() { this.inputs = []; this.set_duration_options(); diff --git a/frappe/public/js/frappe/form/controls/int.js b/frappe/public/js/frappe/form/controls/int.js index 122b43b498..48175a92c0 100644 --- a/frappe/public/js/frappe/form/controls/int.js +++ b/frappe/public/js/frappe/form/controls/int.js @@ -1,5 +1,6 @@ frappe.ui.form.ControlInt = class ControlInt extends frappe.ui.form.ControlData { static trigger_change_on_input_event = false; + static input_mode = "numeric"; make() { super.make(); } diff --git a/frappe/public/js/frappe/form/controls/link.js b/frappe/public/js/frappe/form/controls/link.js index 86b30757d7..62e5e4de67 100644 --- a/frappe/public/js/frappe/form/controls/link.js +++ b/frappe/public/js/frappe/form/controls/link.js @@ -255,7 +255,7 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat doctype: doctype, ignore_user_permissions: me.df.ignore_user_permissions, reference_doctype: me.get_reference_doctype() || "", - page_length: cint(frappe.boot.sysdefaults.link_field_results_limit) || 10, + page_length: cint(frappe.boot.sysdefaults?.link_field_results_limit) || 10, }; me.set_custom_query(args); diff --git a/frappe/public/js/frappe/form/controls/multiselect_list.js b/frappe/public/js/frappe/form/controls/multiselect_list.js index 7ccde751ca..0e6198085a 100644 --- a/frappe/public/js/frappe/form/controls/multiselect_list.js +++ b/frappe/public/js/frappe/form/controls/multiselect_list.js @@ -139,7 +139,7 @@ frappe.ui.form.ControlMultiSelectList = class ControlMultiSelectList extends ( //Unselect old values this.values.forEach((value) => { this.$list_wrapper - .find(`.selectable-item[data-value=${value}]`) + .find(`.selectable-item[data-value=${CSS.escape(value)}]`) .toggleClass("selected"); }); this.values = value; @@ -147,7 +147,7 @@ frappe.ui.form.ControlMultiSelectList = class ControlMultiSelectList extends ( this.update_selected_values(value); //Select new values this.$list_wrapper - .find(`.selectable-item[data-value=${value}]`) + .find(`.selectable-item[data-value=${CSS.escape(value)}]`) .toggleClass("selected"); }); this.parse_validate_and_set_in_model(""); diff --git a/frappe/public/js/frappe/form/dashboard.js b/frappe/public/js/frappe/form/dashboard.js index 6efcdd3079..d1a2fde9d2 100644 --- a/frappe/public/js/frappe/form/dashboard.js +++ b/frappe/public/js/frappe/form/dashboard.js @@ -633,8 +633,8 @@ frappe.ui.form.Dashboard = class FormDashboard { } // TODO: Review! code related to headline should be the part of layout/form - set_headline(html, color) { - this.frm.layout.show_message(html, color); + set_headline(html, color, permanent = false) { + this.frm.layout.show_message(html, color, permanent); } clear_headline() { @@ -642,7 +642,7 @@ frappe.ui.form.Dashboard = class FormDashboard { } add_comment(text, alert_class, permanent) { - this.set_headline_alert(text, alert_class); + this.set_headline_alert(text, alert_class, permanent); if (!permanent) { setTimeout(() => { this.clear_headline(); @@ -654,9 +654,9 @@ frappe.ui.form.Dashboard = class FormDashboard { this.clear_headline(); } - set_headline_alert(text, color) { + set_headline_alert(text, color, permanent = false) { if (text) { - this.set_headline(`
${text}
`, color); + this.set_headline(`
${text}
`, color, permanent); } else { this.clear_headline(); } diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js index 5410b1caec..7edf8544cc 100644 --- a/frappe/public/js/frappe/form/form.js +++ b/frappe/public/js/frappe/form/form.js @@ -550,7 +550,6 @@ frappe.ui.form.Form = class FrappeForm { } trigger_onload(switched) { - this.cscript.is_onload = false; if (!this.opendocs[this.docname]) { var me = this; this.cscript.is_onload = true; @@ -628,6 +627,7 @@ frappe.ui.form.Form = class FrappeForm { () => this.cscript.is_onload && this.is_new() && this.focus_on_first_input(), () => this.run_after_load_hook(), () => this.dashboard.after_refresh(), + () => (this.cscript.is_onload = false), ]); } else { this.refresh_header(switched); diff --git a/frappe/public/js/frappe/form/form_tour.js b/frappe/public/js/frappe/form/form_tour.js index 94f37876bd..61f9ec07e2 100644 --- a/frappe/public/js/frappe/form/form_tour.js +++ b/frappe/public/js/frappe/form/form_tour.js @@ -11,8 +11,10 @@ frappe.ui.form.FormTour = class FormTour { padding: 10, overlayClickNext: true, keyboardControl: true, - nextBtnText: "Next", - prevBtnText: "Previous", + nextBtnText: __("Next"), + prevBtnText: __("Previous"), + doneBtnText: __("Done"), + closeBtnText: __("Close"), opacity: 0.25, onHighlighted: (step) => { // if last step is to save, then attach a listener to save button @@ -135,7 +137,11 @@ frappe.ui.form.FormTour = class FormTour { return { element, name, - popover: { title, description, position: frappe.router.slug(position || "Bottom") }, + popover: { + title: __(title), + description: __(description), + position: frappe.router.slug(position || "Bottom"), + }, onNext: on_next, onPrevious: on_prev, }; diff --git a/frappe/public/js/frappe/form/layout.js b/frappe/public/js/frappe/form/layout.js index d761403489..038e3c55ef 100644 --- a/frappe/public/js/frappe/form/layout.js +++ b/frappe/public/js/frappe/form/layout.js @@ -97,7 +97,7 @@ frappe.ui.form.Layout = class Layout { return fields; } - show_message(html, color) { + show_message(html, color, permanent = false) { if (this.message_color) { // remove previous color this.message.removeClass(this.message_color); @@ -112,8 +112,10 @@ frappe.ui.form.Layout = class Layout { } this.message.removeClass("hidden").addClass(this.message_color); $(html).appendTo(this.message); - close_message.appendTo(this.message); - close_message.on("click", () => this.message.empty().addClass("hidden")); + if (!permanent) { + close_message.appendTo(this.message); + close_message.on("click", () => this.message.empty().addClass("hidden")); + } } else { this.message.empty().addClass("hidden"); } diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index b96245de86..c904dd7544 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -260,12 +260,8 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { set_primary_action() { if (this.can_create && !frappe.boot.read_only) { const doctype_name = __(frappe.router.doctype_layout) || __(this.doctype); - - // Better style would be __("Add {0}", [doctype_name], "Primary action in list view") - // Keeping it like this to not disrupt existing translations - const label = `${__("Add", null, "Primary action in list view")} ${doctype_name}`; this.page.set_primary_action( - label, + __("Add {0}", [doctype_name], "Primary action in list view"), () => { if (this.settings.primary_action) { this.settings.primary_action(); @@ -315,6 +311,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { this.update_checkbox(); this.update_url_with_filters(); this.setup_realtime_updates(); + this.apply_styles_basedon_dropdown(); }); } @@ -547,7 +544,9 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { toggle_result_area() { super.toggle_result_area(); - this.toggle_actions_menu_button(this.$result.find(".list-row-check:checked").length > 0); + this.toggle_actions_menu_button( + this.$result.find(".list-row-checkbox:checked").length > 0 + ); } toggle_actions_menu_button(toggle) { @@ -787,9 +786,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { } const format = () => { - if (df.fieldtype === "Code") { - return value; - } else if (df.fieldtype === "Percent") { + if (df.fieldtype === "Percent") { return `
${_value} `; - } else if ( - ["Text Editor", "Text", "Small Text", "HTML Editor", "Markdown Editor"].includes( - df.fieldtype - ) - ) { + } else if (frappe.model.html_fieldtypes.includes(df.fieldtype)) { html = ` ${_value} `; @@ -915,8 +908,10 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { get_meta_html(doc) { let html = ""; + let settings_button = ""; + let button_section = ""; + const dropdown_button = this.generate_dropdown_html(doc); - let settings_button = null; if (this.settings.button && this.settings.button.show(doc)) { settings_button = ` @@ -929,6 +924,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { `; } + button_section = settings_button + dropdown_button; const modified = comment_when(doc.modified, true); let assigned_to = ``; @@ -950,13 +946,13 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { html += ` `; }) .join(""); - - return `
${filter_html}
- `; } export_report() { diff --git a/frappe/public/js/frappe/widgets/chart_widget.js b/frappe/public/js/frappe/widgets/chart_widget.js index 24d726ba85..cfaba04a71 100644 --- a/frappe/public/js/frappe/widgets/chart_widget.js +++ b/frappe/public/js/frappe/widgets/chart_widget.js @@ -125,7 +125,7 @@ export default class ChartWidget extends Widget { if (this.chart_doc.type == "Heatmap") { filters = [ { - label: this.chart_settings.heatmap_year || this.chart_doc.heatmap_year, + label: __(this.chart_settings.heatmap_year) || __(this.chart_doc.heatmap_year), options: frappe.dashboard_utils.get_years_since_creation( frappe.boot.user.creation ), @@ -141,7 +141,8 @@ export default class ChartWidget extends Widget { } else { filters = [ { - label: this.chart_settings.time_interval || this.chart_doc.time_interval, + label: + __(this.chart_settings.time_interval) || __(this.chart_doc.time_interval), options: ["Yearly", "Quarterly", "Monthly", "Weekly", "Daily"], icon: "calendar", class: "time-interval-filter", @@ -233,7 +234,7 @@ export default class ChartWidget extends Widget { df: { fieldtype: "DateRange", fieldname: "from_date", - placeholder: "Date Range", + placeholder: __("Date Range"), input_class: "input-xs", default: [this.chart_settings.from_date, this.chart_settings.to_date], value: [this.chart_settings.from_date, this.chart_settings.to_date], @@ -314,7 +315,7 @@ export default class ChartWidget extends Widget { if (this.chart_doc.document_type) { actions.push({ - label: __("{0} List", [this.chart_doc.document_type]), + label: __("{0} List", [__(this.chart_doc.document_type)]), action: "action-list", handler: () => { frappe.set_route("List", this.chart_doc.document_type); @@ -322,7 +323,7 @@ export default class ChartWidget extends Widget { }); } else if (this.chart_doc.chart_type === "Report") { actions.push({ - label: __("{0} Report", [this.chart_doc.report_name]), + label: __("{0} Report", [__(this.chart_doc.report_name)]), action: "action-list", handler: () => { frappe.set_route("query-report", this.chart_doc.report_name, this.filters); @@ -392,7 +393,7 @@ export default class ChartWidget extends Widget { setup_filter_dialog(fields) { let me = this; let dialog = new frappe.ui.Dialog({ - title: __("Set Filters for {0}", [this.chart_doc.chart_name]), + title: __("Set Filters for {0}", [__(this.chart_doc.chart_name)]), fields: fields, primary_action: function () { let values = this.get_values(); @@ -403,7 +404,7 @@ export default class ChartWidget extends Widget { me.fetch_and_update_chart(); } }, - primary_action_label: "Set", + primary_action_label: __("Set"), }); dialog.show(); @@ -473,7 +474,9 @@ export default class ChartWidget extends Widget { ${actions .map( (action) => - `
  • ${action.label}
  • ` + `
  • ${__( + action.label + )}
  • ` ) .join("")} diff --git a/frappe/public/js/frappe/widgets/onboarding_widget.js b/frappe/public/js/frappe/widgets/onboarding_widget.js index 4853c04b6a..ae4b86d8a4 100644 --- a/frappe/public/js/frappe/widgets/onboarding_widget.js +++ b/frappe/public/js/frappe/widgets/onboarding_widget.js @@ -129,9 +129,9 @@ export default class OnboardingWidget extends Widget { .on("click", toggle_video); } else { $( - `` + `` ) .appendTo(this.step_footer) .on("click", () => actions[step.action](step)); @@ -139,8 +139,8 @@ export default class OnboardingWidget extends Widget { }; const set_description = () => { - let content = step.description - ? frappe.markdown(step.description) + let content = __(step.description) + ? frappe.markdown(__(step.description)) : `

    ${__(step.title)}

    `; if (step.action === "Create Entry") { @@ -168,9 +168,9 @@ export default class OnboardingWidget extends Widget { }); $( - `` + `` ) .appendTo(this.step_footer) .on("click", () => { diff --git a/frappe/public/scss/print.bundle.scss b/frappe/public/scss/print.bundle.scss index a69bcbe4b4..8e0d385431 100644 --- a/frappe/public/scss/print.bundle.scss +++ b/frappe/public/scss/print.bundle.scss @@ -46,3 +46,8 @@ overflow-wrap: anywhere; } } + +/* prevent newline and right alignment of number fields in printed report filters */ +.filter-row div { + display: inline-block; +} diff --git a/frappe/templates/emails/workflow_action.html b/frappe/templates/emails/workflow_action.html index 51ec9b6c01..9cc6359244 100644 --- a/frappe/templates/emails/workflow_action.html +++ b/frappe/templates/emails/workflow_action.html @@ -5,4 +5,7 @@ {{_(action.action_name)}} {% endfor %}

    +
    + {{ _("The contents of this email are strictly confidential. Please do not forward this email to anyone.") }} +
    \ No newline at end of file diff --git a/frappe/templates/includes/breadcrumbs.html b/frappe/templates/includes/breadcrumbs.html index 6e7d47cade..0c9f0484b3 100644 --- a/frappe/templates/includes/breadcrumbs.html +++ b/frappe/templates/includes/breadcrumbs.html @@ -14,7 +14,7 @@ {% endfor %} diff --git a/frappe/templates/includes/login/login.js b/frappe/templates/includes/login/login.js index e4db68aba0..427e4c3ee6 100644 --- a/frappe/templates/includes/login/login.js +++ b/frappe/templates/includes/login/login.js @@ -329,7 +329,7 @@ var request_otp = function (r) { $('.login-content:visible').append( `
    -
    +
    {{ _("Verification") | e }}
    diff --git a/frappe/templates/print_formats/standard_macros.html b/frappe/templates/print_formats/standard_macros.html index 5fd271b75c..273ce65a13 100644 --- a/frappe/templates/print_formats/standard_macros.html +++ b/frappe/templates/print_formats/standard_macros.html @@ -153,7 +153,7 @@ data-fieldname="{{ df.fieldname }}" data-fieldtype="{{ df.fieldtype }}" {% elif df.fieldtype=="Signature" %} - {% elif df.fieldtype in ("Attach", "Attach Image") %} + {% elif df.fieldtype in ("Attach", "Attach Image") and frappe.utils.is_image(doc[df.fieldname]) %} {% elif df.fieldtype=="HTML" %} diff --git a/frappe/tests/test_db.py b/frappe/tests/test_db.py index 2d939f7a72..d4ccb78d65 100644 --- a/frappe/tests/test_db.py +++ b/frappe/tests/test_db.py @@ -1080,7 +1080,6 @@ class TestSqlIterator(FrappeTestCase): with frappe.db.unbuffered_cursor(): self.test_db_sql_iterator() - class ExtFrappeTestCase(FrappeTestCase): def assertSqlException(self): class SqlExceptionContextManager: @@ -1259,3 +1258,88 @@ class TestPostgresSchemaQueryIndependence(ExtFrappeTestCase): self.assertEqual(rows, []) # there are no records in the alt_schema table del frappe.conf["db_schema"] + +class TestDbConnectWithEnvCredentials(FrappeTestCase): + current_site = frappe.local.site + + def tearDown(self): + frappe.init(self.current_site, force=True) + frappe.connect() + + def test_connect_fails_with_wrong_credentials_by_env(self) -> None: + import contextlib + import os + import re + + @contextlib.contextmanager + def set_env_variable(key, value): + if orig_value_set := key in os.environ: + orig_value = os.environ.get(key) + + os.environ[key] = value + + try: + yield + finally: + if orig_value_set: + os.environ[key] = orig_value + else: + del os.environ[key] + + # with wrong db name + with set_env_variable("FRAPPE_DB_NAME", "dbiq"): + frappe.init(self.current_site, force=True) + frappe.connect() + + with self.assertRaises(Exception) as cm: + frappe.db.connect() + + self.assertTrue(re.search(r"database [\"']dbiq[\"']", str(cm.exception))) + + # with wrong host + with set_env_variable("FRAPPE_DB_HOST", "iqx.local"): + frappe.init(self.current_site, force=True) + frappe.connect() + + with self.assertRaises(Exception) as cm: + frappe.db.connect() + + self.assertTrue(re.search(r"(host name|server on) [\"']iqx.local[\"']", str(cm.exception))) + + # with wrong user name + with set_env_variable("FRAPPE_DB_USER", "uname"): + frappe.init(self.current_site, force=True) + frappe.connect() + + with self.assertRaises(Exception) as cm: + frappe.db.connect() + + self.assertTrue(re.search(r"user [\"']uname[\"']", str(cm.exception))) + + # with wrong password + with set_env_variable("FRAPPE_DB_PASSWORD", "pass"): + frappe.init(self.current_site, force=True) + frappe.connect() + + with self.assertRaises(Exception) as cm: + frappe.db.connect() + + self.assertTrue( + re.search(r"(password authentication failed|Access denied for)", str(cm.exception)) + ) + + # with wrong password + with set_env_variable("FRAPPE_DB_PORT", "1111"): + frappe.init(self.current_site, force=True) + frappe.connect() + + with self.assertRaises(Exception) as cm: + frappe.db.connect() + + self.assertTrue(re.search("(port 1111 failed|Errno 111)", str(cm.exception))) + + # now with configured settings without any influences from env + # finally connect should work without any error (when no wrong credentials are given via ENV) + frappe.init(self.current_site, force=True) + frappe.connect() + frappe.db.connect() diff --git a/frappe/twofactor.py b/frappe/twofactor.py index b5ddd080f0..9e60bd6a18 100644 --- a/frappe/twofactor.py +++ b/frappe/twofactor.py @@ -344,30 +344,14 @@ def send_token_via_email(user, token, otp_secret, otp_issuer, subject=None, mess hotp = pyotp.HOTP(otp_secret) otp = hotp.at(int(token)) template_args = {"otp": otp, "otp_issuer": otp_issuer} - if not subject: - subject = get_email_subject_for_2fa(template_args) - if not message: - message = get_email_body_for_2fa(template_args) - email_args = { - "recipients": user_email, - "sender": None, - "subject": subject, - "message": message, - "header": [_("Verfication Code"), "blue"], - "delayed": False, - "retry": 3, - } - - enqueue( - method=frappe.sendmail, - queue="short", - timeout=300, - event=None, - is_async=True, - job_name=None, - now=False, - **email_args, + frappe.sendmail( + recipients=user_email, + subject=subject or get_email_subject_for_2fa(template_args), + message=message or get_email_body_for_2fa(template_args), + header=[_("Verfication Code"), "blue"], + delayed=False, + retry=3, ) return True diff --git a/frappe/utils/background_jobs.py b/frappe/utils/background_jobs.py index 815145ef70..4e2a7c71b9 100644 --- a/frappe/utils/background_jobs.py +++ b/frappe/utils/background_jobs.py @@ -163,7 +163,7 @@ def enqueue( def enqueue_call(): return q.enqueue_call( - execute_job, + "frappe.utils.background_jobs.execute_job", on_success=Callback(func=on_success) if on_success else None, on_failure=Callback(func=on_failure) if on_failure else None, timeout=timeout, diff --git a/frappe/utils/redis_wrapper.py b/frappe/utils/redis_wrapper.py index c38f54a2f2..e494d07bab 100644 --- a/frappe/utils/redis_wrapper.py +++ b/frappe/utils/redis_wrapper.py @@ -2,6 +2,7 @@ # License: MIT. See LICENSE import pickle import re +from contextlib import suppress import redis from redis.commands.search import Search @@ -62,14 +63,8 @@ class RedisWrapper(redis.Redis): if not expires_in_sec: frappe.local.cache[key] = val - try: - if expires_in_sec: - self.setex(name=key, time=expires_in_sec, value=pickle.dumps(val)) - else: - self.set(key, pickle.dumps(val)) - - except redis.exceptions.ConnectionError: - return None + with suppress(redis.exceptions.ConnectionError): + self.set(name=key, value=pickle.dumps(val), ex=expires_in_sec) def get_value(self, key, generator=None, user=None, expires=False, shared=False): """Return cache value. If not found and generator function is diff --git a/pyproject.toml b/pyproject.toml index 79c4d519b9..6b27020480 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,7 +80,7 @@ dependencies = [ "markdownify~=0.11.6", # integration dependencies - "boto3~=1.28.10", + "boto3~=1.34.143", "dropbox~=11.36.2", "google-api-python-client~=2.2.0", "google-auth-oauthlib~=0.4.4",