From 4e03f4f55fda309d34ad689016c72a4eed7371e7 Mon Sep 17 00:00:00 2001 From: Sabu Siyad Date: Thu, 16 Apr 2026 17:02:28 +0530 Subject: [PATCH 1/7] chore(backend): Wrap `frappe.throw` with `_` (translate) --- .secrets.baseline | 4 +- press/agent.py | 5 +- press/api/__init__.py | 5 +- press/api/access.py | 8 +- press/api/account.py | 78 +++++++++-------- press/api/analytics.py | 18 ++-- press/api/assets.py | 13 +-- press/api/bench.py | 33 +++---- press/api/billing.py | 4 +- press/api/callbacks.py | 5 +- press/api/central.py | 3 +- press/api/client.py | 9 +- press/api/dashboard.py | 4 +- press/api/developer/__init__.py | 3 +- press/api/developer/saas.py | 11 +-- press/api/email.py | 5 +- press/api/github.py | 29 ++++--- press/api/google.py | 2 +- press/api/log_browser.py | 3 +- press/api/marketplace.py | 35 ++++---- press/api/oauth.py | 21 ++--- press/api/partner.py | 37 ++++---- press/api/product_trial.py | 19 ++-- press/api/saas.py | 19 ++-- press/api/selfhosted.py | 7 +- press/api/server.py | 13 +-- press/api/site.py | 31 +++---- press/api/site_backup.py | 7 +- press/api/site_login.py | 26 +++--- press/auth.py | 5 +- press/guards/settings.py | 3 +- .../arm_build_record/arm_build_record.py | 3 +- .../virtual_disk_resize.py | 17 ++-- .../virtual_machine_migration.py | 5 +- .../virtual_machine_replacement.py | 5 +- .../marketplace_app_subscription.py | 25 +++--- press/overrides.py | 3 +- .../partner_approval_request.py | 3 +- .../account_request/account_request.py | 3 +- press/press/doctype/agent_job/agent_job.py | 3 +- .../doctype/agent_update/agent_update.py | 33 ++++--- .../doctype/ansible_play/ansible_play.py | 4 +- press/press/doctype/app_patch/app_patch.py | 5 +- .../press/doctype/app_release/app_release.py | 3 +- .../app_release_approval_request.py | 5 +- .../app_release_difference.py | 7 +- press/press/doctype/app_source/app_source.py | 4 +- .../auto_scale_record/auto_scale_record.py | 5 +- .../backup_restoration_test.py | 7 +- .../balance_transaction.py | 5 +- press/press/doctype/bench/bench.py | 15 ++-- .../doctype/bench_update/bench_update.py | 7 +- .../build_cache_shell/build_cache_shell.py | 3 +- press/press/doctype/cluster/cluster.py | 47 +++++----- .../press/doctype/code_server/code_server.py | 13 +-- .../communication_info/communication_info.py | 17 ++-- .../database_server/database_server.py | 43 +++++----- .../database_server_mariadb_variable.py | 17 ++-- .../deploy_candidate/deploy_candidate.py | 3 +- .../deploy_candidate_build.py | 3 +- .../downtime_analysis/downtime_analysis.py | 5 +- .../github_webhook_log/github_webhook_log.py | 5 +- press/press/doctype/incident/incident.py | 7 +- press/press/doctype/invoice/invoice.py | 10 ++- .../logical_replication_backup.py | 15 ++-- .../logical_replication_step.py | 3 +- .../mariadb_variable/mariadb_variable.py | 3 +- .../marketplace_app/marketplace_app.py | 25 ++++-- .../doctype/monitor_server/monitor_server.py | 3 +- .../mpesa_payment_record.py | 5 +- .../mpesa_request_log/mpesa_request_log.py | 3 +- .../nfs_volume_detachment.py | 5 +- .../on_prem_failover/on_prem_failover.py | 11 +-- .../payment_due_extension.py | 7 +- .../doctype/payout_order/payout_order.py | 27 +++--- .../physical_backup_restoration.py | 21 ++--- .../physical_backup_restoration_step.py | 3 +- .../physical_restoration_test.py | 3 +- .../press/doctype/plan_change/plan_change.py | 2 +- .../press_role_permission.py | 7 +- .../doctype/press_settings/press_settings.py | 9 +- .../doctype/press_webhook/press_webhook.py | 19 ++-- .../process_snapshot/process_snapshot.py | 3 +- .../prometheus_alert_rule.py | 3 +- .../doctype/proxy_failover/proxy_failover.py | 3 +- .../doctype/proxy_server/proxy_server.py | 15 ++-- .../doctype/proxy_server/test_proxy_server.py | 3 +- .../registry_server/registry_server.py | 3 +- .../doctype/release_group/release_group.py | 36 ++++---- .../self_hosted_server/self_hosted_server.py | 21 +++-- .../test_self_hosted_server.py | 4 +- press/press/doctype/server/server.py | 50 +++++------ .../server_snapshot/server_snapshot.py | 27 +++--- .../server_snapshot_recovery.py | 25 ++++-- .../server_storage_plan.py | 3 +- .../doctype/silenced_alert/silenced_alert.py | 23 +++-- press/press/doctype/site/site.py | 86 +++++++++++-------- .../press/doctype/site_action/site_action.py | 15 ++-- .../site_action_step/site_action_step.py | 3 +- .../press/doctype/site_backup/site_backup.py | 15 ++-- .../site_database_user/site_database_user.py | 19 ++-- .../press/doctype/site_domain/site_domain.py | 9 +- .../site_group_deploy/site_group_deploy.py | 5 +- .../doctype/site_migration/site_migration.py | 9 +- .../site_plan_change/site_plan_change.py | 6 +- .../site_replication/site_replication.py | 20 ++--- .../press/doctype/site_update/site_update.py | 11 +-- press/press/doctype/site_user/site_user.py | 3 +- .../ssh_certificate/ssh_certificate.py | 13 ++- .../stripe_webhook_log/stripe_webhook_log.py | 5 +- .../doctype/subscription/subscription.py | 4 +- .../doctype/support_access/support_access.py | 10 +-- press/press/doctype/team/team.py | 18 ++-- .../press/doctype/team_change/team_change.py | 3 +- .../team_deletion_request.py | 12 ++- .../tls_certificate/tls_certificate.py | 9 +- .../user_ssh_certificate.py | 12 +-- .../version_upgrade/version_upgrade.py | 2 +- .../virtual_disk_snapshot.py | 5 +- .../virtual_machine/virtual_machine.py | 69 ++++++++------- .../virtual_machine_image.py | 3 +- .../doctype/wireguard_peer/wireguard_peer.py | 3 +- .../press_endpoints_audit.py | 3 +- press/saas/api/__init__.py | 11 +-- press/saas/api/billing.py | 5 +- .../doctype/product_trial/product_trial.py | 11 +-- .../product_trial_request.py | 5 +- .../doctype/saas_app_plan/saas_app_plan.py | 16 ++-- .../saas_app_subscription.py | 3 +- press/utils/__init__.py | 38 ++++---- press/utils/billing.py | 9 +- press/utils/extra.py | 3 +- press/utils/webhook.py | 3 +- .../doctype/press_workflow/press_workflow.py | 4 +- .../press_workflow_test.py | 3 +- press/www/dashboard.py | 3 +- 136 files changed, 936 insertions(+), 745 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 3b8c7a446a9..69001c13c65 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -303,7 +303,7 @@ "filename": "press/auth.py", "hashed_secret": "e9e1dcecdf9da58fdf07a40a711afbbe9bfe3697", "is_verified": false, - "line_number": 10 + "line_number": 11 } ], "press/fixtures/press_method_permission.json": [ @@ -547,5 +547,5 @@ } ] }, - "generated_at": "2026-04-15T16:58:31Z" + "generated_at": "2026-04-16T11:06:58Z" } diff --git a/press/agent.py b/press/agent.py index a0b05ea2d49..ac87e33a217 100644 --- a/press/agent.py +++ b/press/agent.py @@ -13,6 +13,7 @@ import frappe import frappe.utils import requests +from frappe import _ from frappe.utils.password import get_decrypted_password from requests.exceptions import HTTPError @@ -1807,7 +1808,7 @@ def backup_site_database_from_snapshot( if offsite_config: data.update({"offsite": offsite_config}) else: - frappe.throw("Offsite Backups aren't setup yet") + frappe.throw(_("Offsite Backups aren't setup yet")) return self.create_agent_job( "Backup Database From Snapshot", @@ -1836,7 +1837,7 @@ def backup_site_files_from_snapshot( if offsite_config: data.update({"offsite": offsite_config}) else: - frappe.throw("Offsite Backups aren't setup yet") + frappe.throw(_("Offsite Backups aren't setup yet")) return self.create_agent_job( "Backup Files From Snapshot", diff --git a/press/api/__init__.py b/press/api/__init__.py index 693afb2c134..e12692179b7 100644 --- a/press/api/__init__.py +++ b/press/api/__init__.py @@ -1,4 +1,5 @@ import frappe +from frappe import _ from press.api.client import dashboard_whitelist from press.utils import get_full_chain_cert_of_domain, get_minified_script, get_minified_script_2, log_error @@ -30,10 +31,10 @@ def download_ssl_cert(domain: str): not (domain.endswith("frappe.cloud") or domain.endswith("frappecloud.com")) and not frappe.conf.developer_mode ): - frappe.throw("Invalid domain provided") + frappe.throw(_("Invalid domain provided")) try: return get_full_chain_cert_of_domain(domain) except Exception as e: log_error("Error downloading SSL certificate", data=e) - frappe.throw("Failed to download SSL certificate. Please try again later.") + frappe.throw(_("Failed to download SSL certificate. Please try again later.")) diff --git a/press/api/access.py b/press/api/access.py index 75e9f6cec31..0bdc6fdb911 100644 --- a/press/api/access.py +++ b/press/api/access.py @@ -10,7 +10,9 @@ @typing_validations.validate_argument_types def status(doctype: str, docname: str): if not support_access.has_support_access(doctype, docname): - frappe.throw("You do not have support access to this document", frappe.PermissionError) # nosemgrep + frappe.throw( + frappe._("You do not have support access to this document"), frappe.PermissionError + ) # nosemgrep AccessRequest = frappe.qb.DocType("Support Access") AccessRequestResource = frappe.qb.DocType("Support Access Resource") @@ -30,7 +32,9 @@ def status(doctype: str, docname: str): results = query.run(as_dict=True) if len(results) == 0: - frappe.throw("You do not have support access to this document.", frappe.PermissionError) # nosemgrep + frappe.throw( + frappe._("You do not have support access to this document."), frappe.PermissionError + ) # nosemgrep until = results[0].access_allowed_till diff --git a/press/api/account.py b/press/api/account.py index 172a4245efd..0bf72ae1786 100644 --- a/press/api/account.py +++ b/press/api/account.py @@ -92,10 +92,10 @@ def verify_otp(account_request: str, otp: str) -> str: and not account_request_doc.product_trial ): ip_tracker and ip_tracker.add_failure_attempt() - frappe.throw("Invalid OTP. Please try again.") + frappe.throw(_("Invalid OTP. Please try again.")) if account_request_doc.otp != otp: ip_tracker and ip_tracker.add_failure_attempt() - frappe.throw("Invalid OTP. Please try again.") + frappe.throw(_("Invalid OTP. Please try again.")) ip_tracker and ip_tracker.add_success_attempt() account_request_doc.reset_otp() @@ -114,14 +114,14 @@ def verify_otp_and_login(email: str, otp: str): account_request = frappe.db.get_value("Account Request", {"email": email}, "name") if not account_request: - frappe.throw("Please sign up first") + frappe.throw(_("Please sign up first")) account_request_doc: "AccountRequest" = frappe.get_doc("Account Request", account_request) ip_tracker = get_login_attempt_tracker(frappe.local.request_ip) if account_request_doc.otp != otp: ip_tracker and ip_tracker.add_failure_attempt() - frappe.throw("Invalid OTP. Please try again.") + frappe.throw(_("Invalid OTP. Please try again.")) ip_tracker and ip_tracker.add_success_attempt() account_request_doc.reset_otp() @@ -139,14 +139,14 @@ def resend_otp(account_request: str, for_2fa_keys: bool = False): account_request_doc.otp_generated_at and (frappe.utils.now_datetime() - account_request_doc.otp_generated_at).seconds < 30 ): - frappe.throw("Please wait for 30 seconds before requesting a new OTP") + frappe.throw(_("Please wait for 30 seconds before requesting a new OTP")) # ensure no team has been created with this email if ( frappe.db.exists("Team", {"user": account_request_doc.email}) and not account_request_doc.product_trial ): - frappe.throw("Invalid Email") + frappe.throw(_("Invalid Email")) account_request_doc.reset_otp() account_request_doc.send_otp_mail(for_login=not for_2fa_keys) @@ -157,7 +157,7 @@ def send_otp(email: str, for_2fa_keys: bool = False): account_request = frappe.db.get_value("Account Request", {"email": email}, "name") if not account_request or (account_request and not frappe.db.exists("User", email)): - frappe.throw("Please sign up first") + frappe.throw(_("Please sign up first")) account_request_doc: "AccountRequest" = frappe.get_doc("Account Request", account_request) @@ -166,7 +166,7 @@ def send_otp(email: str, for_2fa_keys: bool = False): account_request_doc.otp_generated_at and (frappe.utils.now_datetime() - account_request_doc.otp_generated_at).seconds < 30 ): - frappe.throw("Please wait for 30 seconds before requesting a new OTP") + frappe.throw(_("Please wait for 30 seconds before requesting a new OTP")) account_request_doc.reset_otp() account_request_doc.send_otp_mail(for_login=not for_2fa_keys) @@ -190,20 +190,20 @@ def setup_account( # noqa: C901 ): account_request = get_account_request_from_key(key) if not account_request: - frappe.throw("Invalid or Expired Key") + frappe.throw(_("Invalid or Expired Key")) if not user_exists: if not first_name: - frappe.throw("First Name is required") + frappe.throw(_("First Name is required")) if not is_invitation and not country: - frappe.throw("Country is required") + frappe.throw(_("Country is required")) if not is_invitation and country: all_countries = frappe.db.get_all("Country", pluck="name") country = find(all_countries, lambda x: x.lower() == country.lower()) if not country: - frappe.throw("Please provide a valid country name") + frappe.throw(_("Please provide a valid country name")) # if the request is authenticated, set the user to Administrator frappe.set_user("Administrator") @@ -263,14 +263,16 @@ def accept_team_invite(key: str): account_request = get_account_request_from_key(key) if not account_request: - frappe.throw("Invalid or Expired Key") + frappe.throw(_("Invalid or Expired Key")) if not account_request.invited_by: - frappe.throw("You are not invited by any team") + frappe.throw(_("You are not invited by any team")) if frappe.session.user != account_request.email: frappe.throw( - "This invite can't be accepted with the current account. Please sign in with the invited account or request a new invite." + _( + "This invite can't be accepted with the current account. Please sign in with the invited account or request a new invite." + ) ) team = account_request.team @@ -291,7 +293,7 @@ def accept_team_invite(key: str): @rate_limit(limit=5, seconds=60 * 60) def send_login_link(email): if not frappe.db.exists("User", email): - frappe.throw("No registered account with this email address") + frappe.throw(_("No registered account with this email address")) key = frappe.generate_hash("Login Link", 20) minutes = 10 @@ -347,12 +349,12 @@ def disable_account(totp_code: str | None): if is_2fa_enabled(user): if not totp_code: - frappe.throw("2FA Code is required") + frappe.throw(_("2FA Code is required")) if not verify_2fa(user, totp_code): - frappe.throw("Invalid 2FA Code") + frappe.throw(_("Invalid 2FA Code")) if user != team.user: - frappe.throw("Only team owner can disable the account") + frappe.throw(_("Only team owner can disable the account")) team.disable_account() @@ -366,7 +368,7 @@ def has_active_servers(team): def enable_account(): team = get_current_team(get_doc=True) if frappe.session.user != team.user: - frappe.throw("Only team owner can enable the account") + frappe.throw(_("Only team owner can enable the account")) team.enable_account() @@ -632,9 +634,9 @@ def create_child_team(title): if title in [ d.team_title for d in frappe.get_all("Team", {"parent_team": current_team.name}, ["team_title"]) ]: - frappe.throw(f"Child Team {title} already exists.") + frappe.throw(_("Child Team {0} already exists.").format(title)) elif title == "Parent Team": - frappe.throw("Child team name cannot be same as parent team") + frappe.throw(_("Child team name cannot be same as parent team")) doc = frappe.get_doc( { @@ -689,7 +691,7 @@ def update_profile(first_name=None, last_name=None, email=None): frappe.utils.validate_email_address(email, True) STR_FORMAT = re.compile("^[a-zA-Z']+$") if (first_name and not STR_FORMAT.match(first_name)) or (last_name and not STR_FORMAT.match(last_name)): - frappe.throw("Names cannot contain invalid characters") + frappe.throw(_("Names cannot contain invalid characters")) user = frappe.session.user doc = frappe.get_doc("User", user) doc.first_name = first_name @@ -806,7 +808,7 @@ def remove_child_team(child_team): team = frappe.get_doc("Team", child_team) sites = frappe.get_all("Site", {"status": ("!=", "Archived"), "team": team.name}, pluck="name") if sites: - frappe.throw("Child team has Active Sites") + frappe.throw(_("Child team has Active Sites")) team.enabled = 0 team.parent_team = "" @@ -844,7 +846,7 @@ def leave_team(team): cur_team = frappe.session.user if team_to_leave.user == cur_team: - frappe.throw("Cannot leave this team as you are the owner.") + frappe.throw(_("Cannot leave this team as you are the owner.")) team_to_leave.remove_team_member(cur_team) @@ -874,7 +876,7 @@ def update_billing_information(billing_details): if (team.country != billing_details.country) and ( team.country == "India" or billing_details.country == "India" ): - frappe.throw("Cannot change country after registration") + frappe.throw(_("Cannot change country after registration")) team.update_billing_details(billing_details) @@ -884,7 +886,7 @@ def validate_pincode(billing_details): return PINCODE_FORMAT = re.compile(r"^[1-9][0-9]{5}$") if not PINCODE_FORMAT.match(billing_details.postal_code): - frappe.throw("Invalid Postal Code") + frappe.throw(_("Invalid Postal Code")) if billing_details.state not in STATE_PINCODE_MAPPING: return @@ -899,7 +901,9 @@ def validate_pincode(billing_details): if lower_limit <= int(first_three_digits) <= upper_limit: return - frappe.throw(f"Postal Code {billing_details.postal_code} is not associated with {billing_details.state}") + frappe.throw( + _(f"Postal Code {billing_details.postal_code} is not associated with {billing_details.state}") + ) @frappe.whitelist(allow_guest=True) @@ -1157,7 +1161,7 @@ def verify_2fa(user, totp_code): if verified: frappe.db.set_value("User 2FA", user, "last_verified_at", frappe.utils.now()) else: - frappe.throw("Invalid 2FA code", frappe.AuthenticationError) + frappe.throw(_("Invalid 2FA code"), frappe.AuthenticationError) return verified @@ -1192,7 +1196,7 @@ def enable_2fa(totp_code): user_totp_secret = get_decrypted_password("User 2FA", frappe.session.user, "totp_secret") if not pyotp.totp.TOTP(user_totp_secret).verify(totp_code): - frappe.throw("Invalid TOTP code") + frappe.throw(_("Invalid TOTP code")) two_fa.enabled = 1 @@ -1232,12 +1236,12 @@ def disable_2fa(totp_code): if frappe.db.exists("User 2FA", frappe.session.user): user_totp_secret = get_decrypted_password("User 2FA", frappe.session.user, "totp_secret") else: - frappe.throw(f"2FA is not enabled for {frappe.session.user}") + frappe.throw(_("2FA is not enabled for {0}").format(frappe.session.user)) if pyotp.totp.TOTP(user_totp_secret).verify(totp_code): frappe.db.set_value("User 2FA", frappe.session.user, "enabled", 0) else: - frappe.throw("Invalid TOTP code") + frappe.throw(_("Invalid TOTP code")) @frappe.whitelist(allow_guest=True) @@ -1249,7 +1253,7 @@ def recover_2fa(user: str, recovery_code: str): # Check if the user has 2FA enabled. if not two_fa.enabled: - frappe.throw(f"2FA is not enabled for {user}") + frappe.throw(_("2FA is not enabled for {0}").format(user)) # Get valid recovery code doc. code: "User2FARecoveryCode" | None = None @@ -1261,7 +1265,7 @@ def recover_2fa(user: str, recovery_code: str): # If no valid recovery code found, throw an error. if not code: - frappe.throw("Invalid or used recovery code") + frappe.throw(_("Invalid or used recovery code")) assert code is not None # Mark the recovery code as used. code.used_at = frappe.utils.now_datetime() @@ -1276,12 +1280,12 @@ def get_2fa_recovery_codes(verification_code: int): """Get the recovery codes for the user.""" if not frappe.db.exists("User 2FA", {"user": frappe.session.user, "enabled": 1}): - frappe.throw("2FA is not enabled for this user") + frappe.throw(_("2FA is not enabled for this user")) account_request: "AccountRequest" = frappe.get_doc("Account Request", {"email": frappe.session.user}) if account_request.otp != verification_code: - frappe.throw("Invalid OTP. Please try again.") + frappe.throw(_("Invalid OTP. Please try again.")) account_request.reset_otp() @@ -1309,7 +1313,7 @@ def reset_2fa_recovery_codes(): # Check if the user has 2FA enabled. if not frappe.db.exists("User 2FA", frappe.session.user): - frappe.throw("2FA is not enabled for this user") + frappe.throw(_("2FA is not enabled for this user")) # Get the User 2FA document. two_fa = frappe.get_doc("User 2FA", frappe.session.user) diff --git a/press/api/analytics.py b/press/api/analytics.py index 6703cde644f..15dcaed0472 100644 --- a/press/api/analytics.py +++ b/press/api/analytics.py @@ -11,11 +11,7 @@ import frappe import frappe.utils -import requests -import sqlparse -from elasticsearch import Elasticsearch -from elasticsearch_dsl import A, Search -from frappe import auth +from frappe import _, auth from frappe.utils import ( convert_utc_to_timezone, flt, @@ -234,7 +230,7 @@ def setup_search_filters(self): def setup_search_aggs(self): if not self.group_by_field: - frappe.throw("Group by field not set") + frappe.throw(_("Group by field not set")) if AggType(self.agg_type) is AggType.COUNT: self.search.aggs.bucket( "method_path", @@ -465,7 +461,7 @@ def setup_search_filters(self): ) ) ): - frappe.throw("Monitor server not set in Press Settings") + frappe.throw(_("Monitor server not set in Press Settings")) self.search = self.search.exclude("match_phrase", source__ip=monitor_ip) if ResourceType(self.resource_type) is ResourceType.SITE: server = frappe.db.get_value("Site", self.name, "server") @@ -600,12 +596,12 @@ def get_metrics( duration: str = "24h", ): if not name: - frappe.throw("No release group found!") + frappe.throw(_("No release group found!")) benches = frappe.get_all("Bench", {"status": "Active", "group": name}, pluck="name") if not benches: - frappe.throw("No active benches found!") + frappe.throw(_("No active benches found!")) benches = "|".join(benches) timespan, timegrain = TIMESPAN_TIMEGRAIN_MAP[duration] @@ -615,7 +611,7 @@ def get_metrics( datasets, labels = _get_cadvisor_data(promql_query, timezone, timespan, timegrain) return {response_key: {"datasets": datasets, "labels": labels}} except (ValueError, TypeError): - frappe.throw("Unable to fetch metrics") + frappe.throw(_("Unable to fetch metrics")) @frappe.whitelist() @@ -1691,7 +1687,7 @@ def mariadb_add_suggested_index(name: str, table: str, column: str): }, ) if record_exists: - frappe.throw("There is already a pending job for Add Database Index. Please wait until finished.") + frappe.throw(_("There is already a pending job for Add Database Index. Please wait until finished.")) doctype = get_doctype_name(table) site = frappe.get_cached_doc("Site", name) agent = Agent(site.server) diff --git a/press/api/assets.py b/press/api/assets.py index 60069908611..dde97deec68 100644 --- a/press/api/assets.py +++ b/press/api/assets.py @@ -6,6 +6,7 @@ import boto3 import botocore.exceptions import frappe +from frappe import _ if TYPE_CHECKING: from apps.press.press.press.doctype.press_settings.press_settings import PressSettings @@ -96,14 +97,14 @@ def upload_asset(): files = frappe.request.files if not files or "asset_file" not in files: - frappe.throw("No asset file uploaded") + frappe.throw(_("No asset file uploaded")) asset_file = files["asset_file"] credentials = _get_asset_store_credentials() has_existing_asset = check_existing_asset_in_s3(credentials, asset_file.filename) if has_existing_asset: - frappe.throw(f"Asset with name {asset_file.filename} already exists in the asset store") + frappe.throw(_("Asset with name {0} already exists in the asset store").format(asset_file.filename)) upload_assets_to_store(credentials, asset_file.stream, asset_file.filename) @@ -113,17 +114,19 @@ def get_credentials() -> AssetStoreCredentials: """Get asset store credentials if it is requested from a build server""" build_token = frappe.request.headers.get("build-token") if not build_token: - frappe.throw("Build token is required to access asset store credentials", frappe.PermissionError) + frappe.throw( + frappe._("Build token is required to access asset store credentials"), frappe.PermissionError + ) deploy_candidate = frappe.db.get_value("Deploy Candidate", {"build_token": build_token}) if not deploy_candidate: - frappe.throw("Invalid build token used", frappe.PermissionError) + frappe.throw(_("Invalid build token used"), frappe.PermissionError) running_build = frappe.db.get_value( "Deploy Candidate Build", {"deploy_candidate": deploy_candidate, "status": "Running"} ) if not running_build: - frappe.throw("Expired token used", frappe.PermissionError) + frappe.throw(_("Expired token used"), frappe.PermissionError) return _get_asset_store_credentials() diff --git a/press/api/bench.py b/press/api/bench.py index fac26a48b7e..15815ce22b7 100644 --- a/press/api/bench.py +++ b/press/api/bench.py @@ -8,6 +8,7 @@ import frappe import requests +from frappe import _ from frappe.core.utils import find, find_all from frappe.model.naming import append_number_if_name_exists from frappe.utils import flt, sbool @@ -51,16 +52,16 @@ def new(bench): team = get_current_team(get_doc=True) if not team.enabled: - frappe.throw("You cannot create a new bench because your account is disabled") + frappe.throw(_("You cannot create a new bench because your account is disabled")) if exists(bench["title"]): - frappe.throw("A bench exists with the same name") + frappe.throw(_("A bench exists with the same name")) if bench["server"] and not ( frappe.session.data.user_type == "System User" or frappe.db.get_value("Server", bench["server"], "team") == team.name ): - frappe.throw("You can only create benches on your servers") + frappe.throw(_("You can only create benches on your servers")) apps = [{"app": app["name"], "source": app["source"]} for app in bench["apps"]] group = new_release_group( @@ -285,7 +286,7 @@ def options(): clusters = Cluster.get_all_for_new_bench() if not versions: - frappe.throw("Only enabled and public app sources will reflect here!") + frappe.throw(_("Only enabled and public app sources will reflect here!")) return {"versions": versions, "clusters": clusters} @@ -395,10 +396,10 @@ def update_dependencies(name: str, dependencies: str): rg: ReleaseGroup = frappe.get_doc("Release Group", name) if len(rg.dependencies) != len(dependencies_dict): - frappe.throw("Need all required dependencies") + frappe.throw(_("Need all required dependencies")) if diff := set([d["key"] for d in dependencies_dict]) - set(d.dependency for d in rg.dependencies): - frappe.throw("Invalid dependencies: " + ", ".join(diff)) + frappe.throw(_("Invalid dependencies: ") + ", ".join(diff)) for dep, new in zip( sorted(rg.dependencies, key=lambda x: x.dependency), @@ -406,9 +407,9 @@ def update_dependencies(name: str, dependencies: str): strict=False, ): if dep.dependency != new["key"]: - frappe.throw(f"Invalid dependency: {new['key']}") + frappe.throw(_("Invalid dependency: {0}").format(new["key"])) if not re.match(r"^\d+\.\d+\.*\d*$", new["value"]): - frappe.throw(f"Invalid version for {new['key']}") + frappe.throw(_("Invalid version for {0}").format(new["key"])) dep.version = new["value"] rg.save() @@ -757,10 +758,10 @@ def deploy(name, apps): rg: ReleaseGroup = frappe.get_doc("Release Group", name) if rg.team != team.name: - frappe.throw("Bench can only be deployed by the bench owner", exc=frappe.PermissionError) + frappe.throw(_("Bench can only be deployed by the bench owner"), exc=frappe.PermissionError) if rg.deploy_in_progress: - frappe.throw("A deploy for this bench is already in progress") + frappe.throw(_("A deploy for this bench is already in progress")) candidate = rg.create_deploy_candidate(apps) deploy_candidate_build = candidate.schedule_build_and_deploy() @@ -776,7 +777,7 @@ def validate_app_hashes(apps: list[dict[str, str]]): hashes = [] for app in apps: if not app.get("release") or not app.get("hash"): - frappe.throw("Each app must have a release and hash to run deploy and update!") + frappe.throw(_("Each app must have a release and hash to run deploy and update!")) else: hashes.append(app.get("hash")) @@ -821,7 +822,7 @@ def deploy_and_update( rg_team = frappe.db.get_value("Release Group", name, "team") if rg_team != current_team: - frappe.throw("Bench can only be deployed by the bench owner", exc=frappe.PermissionError) + frappe.throw(_("Bench can only be deployed by the bench owner"), exc=frappe.PermissionError) release_pipeline: ReleasePipeline = frappe.get_doc( {"doctype": "Release Pipeline", "release_group": name, "team": current_team} @@ -953,7 +954,7 @@ def validate_branch(name: str, app: str, branch: str): if response.ok: return response.json() - frappe.throw("Error validating branch from GitHub: " + response.text) + frappe.throw(_("Error validating branch from GitHub: ") + response.text) return None @@ -1077,7 +1078,7 @@ def logs(name, bench): @protected("Release Group") def log(name, bench, log): if frappe.db.get_value("Bench", bench, "group") != name: - frappe.throw(f"Release Group name {name} does not match Bench Release Group") + frappe.throw(_("Release Group name {0} does not match Bench Release Group").format(name)) return frappe.get_doc("Bench", bench).get_server_log(log) @@ -1129,7 +1130,7 @@ def fail_build(dn: str): failed = fail_remote_job(dn) if not failed: - frappe.throw("No running job found!") + frappe.throw(_("No running job found!")) @frappe.whitelist() @@ -1186,7 +1187,7 @@ def redeploy(name: str, dc_name: str) -> str: response = redeploy_candidate(dc_name) if response["error"]: - frappe.throw("Unable to redeploy this build!", frappe.ValidationError) + frappe.throw(_("Unable to redeploy this build!"), frappe.ValidationError) return response["message"] diff --git a/press/api/billing.py b/press/api/billing.py index aff89c31e3a..499cceaaefb 100644 --- a/press/api/billing.py +++ b/press/api/billing.py @@ -589,10 +589,10 @@ def validate_gst(address, method=None): return if address.state not in states_with_tin: - frappe.throw("Invalid State for India.") # nosemgrep + frappe.throw(_("Invalid State for India.")) # nosemgrep if not address.gstin: - frappe.throw("GSTIN is required for Indian customers.") # nosemgrep + frappe.throw(_("GSTIN is required for Indian customers.")) # nosemgrep if address.gstin and address.gstin != "Not Applicable": if not GSTIN_FORMAT.match(address.gstin): diff --git a/press/api/callbacks.py b/press/api/callbacks.py index 1ae4641092f..1ae7877e7c5 100644 --- a/press/api/callbacks.py +++ b/press/api/callbacks.py @@ -5,6 +5,7 @@ import ipaddress import frappe +from frappe import _ from frappe.rate_limiter import rate_limit from press.agent import Agent @@ -111,10 +112,10 @@ def callback(job_id: str | None = None): # Request origin not authorized to update job status. if not server: - frappe.throw("Not permitted", frappe.ValidationError) + frappe.throw(_("Not permitted"), frappe.ValidationError) job = verify_job_id(server, job_id) if not job: - frappe.throw("Invalid Job Id", frappe.ValidationError) + frappe.throw(_("Invalid Job Id"), frappe.ValidationError) frappe.enqueue(handle_job_updates, server=server, job_identifier=job_id) diff --git a/press/api/central.py b/press/api/central.py index d4433c058a5..8d6cc481406 100644 --- a/press/api/central.py +++ b/press/api/central.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe import _ from frappe.geo.country_info import get_country_timezone_info from press.api.account import get_account_request_from_key @@ -11,7 +12,7 @@ def options_for_regional_data(key: str): account_request = get_account_request_from_key(key) if not account_request: - frappe.throw("Invalid or Expired Key") + frappe.throw(_("Invalid or Expired Key")) data = { "languages": frappe.db.get_all("Language", ["language_name", "language_code"]), diff --git a/press/api/client.py b/press/api/client.py index 38131269026..3429fa64b21 100644 --- a/press/api/client.py +++ b/press/api/client.py @@ -7,6 +7,7 @@ import typing import frappe +from frappe import _ from frappe.client import set_value as _set_value from frappe.handler import run_doc_method as _run_doc_method from frappe.model import child_table_fields, default_fields @@ -133,7 +134,7 @@ def get_list( meta = frappe.get_meta(doctype) if meta.istable and not (filters.get("parenttype") and filters.get("parent")): - frappe.throw("parenttype and parent are required to get child records") + frappe.throw(_("parenttype and parent are required to get child records")) apply_team_filter = not ( filters.get("skip_team_filter_for_system_user_and_support_agent") @@ -249,14 +250,14 @@ def get(doctype, name): @frappe.whitelist(methods=["POST", "PUT"]) def insert(doc=None): if not doc or not doc.get("doctype"): - frappe.throw(frappe._("doc.doctype is required")) + frappe.throw(_("doc.doctype is required")) check_permissions(doc.get("doctype")) doc = frappe._dict(doc) if frappe.is_table(doc.doctype): if not (doc.parenttype and doc.parent and doc.parentfield): - frappe.throw(frappe._("Parenttype, Parent and Parentfield are required to insert a child record")) + frappe.throw(_("Parenttype, Parent and Parentfield are required to insert a child record")) # inserting a child record parent = frappe.get_doc(doc.parenttype, doc.parent) @@ -516,7 +517,7 @@ def is_owned_by_team(doctype, docname, raise_exception=True): def raise_not_permitted(): - frappe.throw("Not permitted", frappe.PermissionError) + frappe.throw(_("Not permitted"), frappe.PermissionError) def dashboard_whitelist(allow_guest=False, xss_safe=False, methods=None): diff --git a/press/api/dashboard.py b/press/api/dashboard.py index 0741c401765..1f3af48a09c 100644 --- a/press/api/dashboard.py +++ b/press/api/dashboard.py @@ -1,9 +1,9 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe and contributors # For license information, please see license.txt import frappe +from frappe import _ from press.api.site import protected from press.utils import get_current_team @@ -25,7 +25,7 @@ def all(): def create_new_tag(name, doctype, tag): team = get_current_team() if frappe.db.exists("Press Tag", {"tag": tag, "doctype_name": doctype, "team": team}): - frappe.throw(f"Tag '{tag}' already exists") + frappe.throw(_("Tag '{0}' already exists").format(tag)) tag = frappe.get_doc( { "doctype": "Press Tag", diff --git a/press/api/developer/__init__.py b/press/api/developer/__init__.py index 0c25f5b9fdd..e1e933006d2 100644 --- a/press/api/developer/__init__.py +++ b/press/api/developer/__init__.py @@ -1,4 +1,5 @@ import frappe +from frappe import _ class InvalidSecretKeyError(Exception): @@ -6,4 +7,4 @@ class InvalidSecretKeyError(Exception): def raise_invalid_key_error(): - frappe.throw("Please provide a valid secret key.", InvalidSecretKeyError) + frappe.throw(_("Please provide a valid secret key."), InvalidSecretKeyError) diff --git a/press/api/developer/saas.py b/press/api/developer/saas.py index 5f555d2566f..741fa69e30e 100644 --- a/press/api/developer/saas.py +++ b/press/api/developer/saas.py @@ -2,6 +2,7 @@ import frappe import frappe.utils +from frappe import _ from frappe.rate_limiter import rate_limit from press.api.developer import raise_invalid_key_error @@ -129,7 +130,7 @@ def send_verification_code(domain: str, route: str = ""): domain_info = frappe.get_value("Site Domain", domain, ["site", "status"], as_dict=True) if not domain_info or domain_info.get("status") != "Active": - frappe.throw("The domain is not active currently. Please try again.") + frappe.throw(_("The domain is not active currently. Please try again.")) site_info = frappe.get_value( "Site", domain_info.get("site"), ["name", "team", "standby_for", "standby_for_product"], as_dict=True @@ -137,7 +138,7 @@ def send_verification_code(domain: str, route: str = ""): team_name = site_info.get("team") team_info = frappe.get_value("Team", team_name, ["name", "enabled", "user", "enforce_2fa"], as_dict=True) if not team_info or not team_info.get("enabled"): - frappe.throw("Your Frappe Cloud team is disabled currently.") + frappe.throw(_("Your Frappe Cloud team is disabled currently.")) check_if_user_can_login(team_info, site_info) @@ -170,7 +171,7 @@ def send_verification_code(domain: str, route: str = ""): def verify_verification_code(domain: str, verification_code: str, route: str = "dashboard"): otp_hash = frappe.cache.get_value(f"otp_hash_for_fc_login_via_saas_flow:{domain}", expires=True) if not otp_hash or otp_hash != frappe.utils.sha256_hash(str(verification_code)): - frappe.throw("Invalid Code. Please try again.") + frappe.throw(_("Invalid Code. Please try again.")) site = frappe.get_value("Site Domain", domain, "site") team = frappe.get_value("Site", site, "team") @@ -228,11 +229,11 @@ def check_if_user_can_login(team_info, site_info): team_info.get("user") == "Administrator" or frappe.db.get_value("User", team_info.get("user"), "user_type") != "Website User" ): - frappe.throw("Sorry, you cannot login with this method. Please contact support for more details.") + frappe.throw(_("Sorry, you cannot login with this method. Please contact support for more details.")) # restrict to SaaS Site if not (site_info.get("standby_for") or site_info.get("standby_for_product")): - frappe.throw("Only SaaS sites are allowed to login to Frappe Cloud via current method.") + frappe.throw(_("Only SaaS sites are allowed to login to Frappe Cloud via current method.")) def send_email_with_verification_code(email, otp): diff --git a/press/api/email.py b/press/api/email.py index 41e03d71dbb..0f6df106554 100644 --- a/press/api/email.py +++ b/press/api/email.py @@ -10,6 +10,7 @@ import frappe import requests +from frappe import _ from frappe.exceptions import OutgoingEmailError, TooManyRequestsError, ValidationError from frappe.utils import validate_email_address from frappe.utils.password import get_decrypted_password @@ -92,7 +93,7 @@ def get_analytics(**data): for value in (site, subscription_key): if not value or not isinstance(value, str): - frappe.throw("Invalid Request") + frappe.throw(_("Invalid Request")) return frappe.get_all( "Mail Log", @@ -233,7 +234,7 @@ def send_mime_mail(**data): return "Sending" # Not really required as v14 and up automatically marks the email q as sent if resp.status_code == 400: err_msg: str = resp.json().get("message", "Invalid request") - frappe.throw(f"Something went wrong with sending emails: {err_msg}", InvalidEmail) + frappe.throw(_("Something went wrong with sending emails: {0}").format(err_msg), InvalidEmail) log_error("Email Delivery Service: Sending error", response=resp.text, data=data, message=message) frappe.throw( "Something went wrong with sending emails. Please try again later or raise a support ticket with support.frappe.io", diff --git a/press/api/github.py b/press/api/github.py index 1da00d75bfb..7186580d3bf 100644 --- a/press/api/github.py +++ b/press/api/github.py @@ -18,6 +18,7 @@ import jwt import requests import tomli +from frappe import _ from frappe.utils.verified_command import get_secret from press.utils import get_current_team, log_error @@ -246,7 +247,11 @@ def fetch_installations(token): ) data = response.json() if not response.ok: - frappe.throw("Error fetching installations from GitHub: " + data.get("message", "Unknown error")) + frappe.throw( + frappe._("Error fetching installations from GitHub") + + ": " + + data.get("message", "Unknown error") + ) if len(data.get("installations", [])) < 100: is_last_page = True installations.extend(response.json().get("installations", [])) @@ -345,7 +350,9 @@ def app(owner, repository, branch, installation=None): ) if not response.ok: - frappe.throw(f"Could not fetch branch ({branch}) info for repo {owner}/{repository}") + frappe.throw( + frappe._("Could not fetch branch ({0}) info for repo {1}/{2}").format(branch, owner, repository) + ) branch_info = response.json() sha = branch_info["commit"]["commit"]["tree"]["sha"] @@ -360,7 +367,7 @@ def app(owner, repository, branch, installation=None): # Force pyproject.toml as a setup file if "pyproject.toml" not in tree: reason = "pyproject.toml does not exist in app directory." - frappe.throw(f"Not a valid Frappe App! {reason}") + frappe.throw(_("Not a valid Frappe App! {0}").format(reason)) app_name, title = _get_app_name_and_title_from_hooks( owner, @@ -400,7 +407,7 @@ def branches(owner, name, installation=None, app_source=None): timeout=20, ) if not resp.ok: - frappe.throw("Error fetching branch list from GitHub: " + resp.text) + frappe.throw(_("Error fetching branch list from GitHub") + ": " + resp.text) chunk = resp.json() or [] out.extend(chunk) @@ -436,7 +443,7 @@ def _get_compatible_frappe_version_from_pyproject( ).json() if "content" not in pyproject: - frappe.throw("Could not fetch pyproject.toml file.") + frappe.throw(_("Could not fetch pyproject.toml file.")) pyproject = b64decode(pyproject["content"]).decode() @@ -447,7 +454,7 @@ def _get_compatible_frappe_version_from_pyproject( out.append("Invalid pyproject.toml file found") if not hasattr(e, "doc") or not hasattr(e, "lineno"): - frappe.throw("\n".join(out)) + frappe.throw(_("\n".join(out))) lines = e.doc.splitlines() @@ -523,7 +530,7 @@ def _get_app_name_and_title_from_hooks( ) break - frappe.throw(f"Not a valid Frappe App! {reason_for_invalidation}") + frappe.throw(_("Not a valid Frappe App! {0}").format(reason_for_invalidation)) return None @@ -556,16 +563,18 @@ def _get_pyproject_from_commit(app_source: str, commit: str): response = requests.get(url, params={"ref": commit}, headers=headers) if response.status_code == 400: - frappe.throw("Pyproject not found at this commit", frappe.ValidationError) + frappe.throw(_("Pyproject not found at this commit"), frappe.ValidationError) if not response.ok: - frappe.throw("Error fetching app info from github", frappe.ValidationError) + frappe.throw(_("Error fetching app info from github"), frappe.ValidationError) content = b64decode(response.json().get("content", "")).decode() try: return tomli.loads(content) except tomli.TOMLDecodeError: - frappe.throw("Invalid pyproject.toml file found in the app repository.", frappe.ValidationError) + frappe.throw( + frappe._("Invalid pyproject.toml file found in the app repository."), frappe.ValidationError + ) def get_dependant_apps_with_versions(app_source: str, commit: str, cache: bool = True) -> AppDependencyFetch: diff --git a/press/api/google.py b/press/api/google.py index b1448ebceb7..ae7f112a89a 100644 --- a/press/api/google.py +++ b/press/api/google.py @@ -152,5 +152,5 @@ def get_google_credentials(): config = frappe.conf.get("google_credentials") if not config: - frappe.throw("google_credentials not found in site_config.json") + frappe.throw(_("google_credentials not found in site_config.json")) return config diff --git a/press/api/log_browser.py b/press/api/log_browser.py index fa60d51191e..9c91d32ab94 100644 --- a/press/api/log_browser.py +++ b/press/api/log_browser.py @@ -3,6 +3,7 @@ from enum import Enum import frappe +from frappe import _ from press.api.site import protected @@ -343,7 +344,7 @@ def get_raw_log(log_type: LOG_TYPE, doc_name: str, log_name: str) -> list: return frappe.get_doc("Bench", doc_name).get_server_log(log_name) if log_type == LOG_TYPE.SITE: return frappe.get_doc("Site", doc_name).get_server_log(log_name) - return frappe.throw("Invalid log type") # nosemgrep + return frappe.throw(_("Invalid log type")) # nosemgrep def format_log(log_name: str, log_entries: list) -> list: diff --git a/press/api/marketplace.py b/press/api/marketplace.py index 57ceba5840d..dd6cfd335e0 100644 --- a/press/api/marketplace.py +++ b/press/api/marketplace.py @@ -6,6 +6,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.core.utils import find from press.api.bench import options @@ -170,7 +171,7 @@ def create_site_on_public_bench( ): group = group[0].name else: - frappe.throw("No release group found for the selected apps") + frappe.throw(_("No release group found for the selected apps")) site = frappe.get_doc( { @@ -216,7 +217,7 @@ def create_site_on_private_bench( ) if not all_latest_stable_version_supported: - frappe.throw("No stable version found for the selected app(s)") + frappe.throw(_("No stable version found for the selected app(s)")) latest_stable_version_supported = sorted(all_latest_stable_version_supported, reverse=True)[0] @@ -253,7 +254,7 @@ def create_site_on_private_bench( for app in apps: app_source = find(frappe_app_source + app_sources, lambda x: x.app == app["app"]) if not app_source: - frappe.throw(f"Source not found for app {app['app']}") + frappe.throw(_("Source not found for app {0}").format(app["app"])) apps_with_sources.append( { @@ -442,7 +443,7 @@ def update_app_image() -> str: app_name = frappe.form_dict.docname app_team = frappe.db.get_value("Marketplace App", app_name, "team") if app_team != current_team: - frappe.throw("Not Permitted to update app image", frappe.PermissionError) + frappe.throw(_("Not Permitted to update app image"), frappe.PermissionError) file_content = frappe.local.uploaded_file file_name = frappe.local.uploaded_filename @@ -494,7 +495,7 @@ def add_app_screenshot() -> str: app_name = frappe.form_dict.docname app_team = frappe.db.get_value("Marketplace App", app_name, "team") if app_team != current_team: - frappe.throw("Not Permitted to add app screenshot", frappe.PermissionError) + frappe.throw(_("Not Permitted to add app screenshot"), frappe.PermissionError) file_content = frappe.local.uploaded_file file_name = frappe.local.uploaded_filename @@ -553,7 +554,7 @@ def validate_uploaded_image(file_content: bytes, file_name: str) -> None: """ ext = file_name.rsplit(".", 1)[-1].lower() if "." in file_name else "" if ext not in ALLOWED_IMAGE_EXTENSIONS: - frappe.throw(f"Only {', '.join(sorted(ALLOWED_IMAGE_EXTENSIONS))} images are allowed") + frappe.throw(_("Only {0} images are allowed").format(", ".join(sorted(ALLOWED_IMAGE_EXTENSIONS)))) from io import BytesIO @@ -576,7 +577,7 @@ def validate_app_image_dimensions(file_content): im = Image.open(BytesIO(file_content)) im_width, im_height = im.size if im_width != im_height or im_height < 300: - frappe.throw("Logo must be a square image atleast 300x300px in size") + frappe.throw(_("Logo must be a square image atleast 300x300px in size")) @frappe.whitelist() @@ -644,7 +645,7 @@ def reason_for_rejection(app_release: str) -> str: release_doc = frappe.get_doc("App Release", app_release) if release_doc.status != "Rejected": - frappe.throw("The request for the given app release was not rejected!") + frappe.throw(_("The request for the given app release was not rejected!")) return approval_request.reason_for_rejection @@ -659,7 +660,7 @@ def get_latest_approval_request(app_release: str): ) if len(approval_requests) == 0: - frappe.throw("No approval request exists for the given app release") + frappe.throw(_("No approval request exists for the given app release")) approval_request = frappe.get_doc("App Release Approval Request", approval_requests[0]) @@ -771,7 +772,9 @@ def add_app(source: str, app: str): marketplace_app = frappe.get_doc("Marketplace App", app) if marketplace_app.team != get_current_team(): - frappe.throw(f"The app {marketplace_app.name} already exists and is owned by some other team.") + frappe.throw( + _("The app {0} already exists and is owned by some other team.").format(marketplace_app.name) + ) # Versions on marketplace versions = [v.version for v in marketplace_app.sources] @@ -787,7 +790,7 @@ def add_app(source: str, app: str): marketplace_app.append("sources", {"source": source, "version": version}) marketplace_app.save(ignore_permissions=True) else: - frappe.throw("A marketplace app already exists with the given versions!") + frappe.throw(_("A marketplace app already exists with the given versions!")) return marketplace_app.name @@ -1036,7 +1039,7 @@ def create_app_plan(marketplace_app: str, plan_data: dict): @frappe.whitelist() def update_app_plan(app_plan_name: str, updated_plan_data: dict): if not updated_plan_data.get("title"): - frappe.throw("Plan title is required") + frappe.throw(_("Plan title is required")) app_plan_doc = frappe.get_doc("Marketplace App Plan", app_plan_name) @@ -1057,7 +1060,7 @@ def update_app_plan(app_plan_name: str, updated_plan_data: dict): # Someone is on this plan, don't change price for the plan, # instead create and link a new plan # TODO: Later we have to figure out a way for plan changes - frappe.throw("Plan is already in use, cannot update the plan. Please contact support to proceed.") + frappe.throw(_("Plan is already in use, cannot update the plan. Please contact support to proceed.")) app_plan_doc.update( { @@ -1079,7 +1082,7 @@ def reset_features_for_plan(app_plan_doc: MarketplaceAppPlan, feature_list: list app_plan_doc.features = [] for feature in feature_list: if not feature: - frappe.throw("Feature cannot be empty string") + frappe.throw(_("Feature cannot be empty string")) app_plan_doc.append("features", {"description": feature}) if save: @@ -1171,7 +1174,7 @@ def get_discount_percent(plan, discount=0.0): @frappe.whitelist(allow_guest=True) def login_via_token(token: str, team: str, site: str): if not token or not isinstance(token, str): - frappe.throw("Invalid Token") + frappe.throw(_("Invalid Token")) team = team.replace(" ", "+") token_exists = frappe.db.exists( @@ -1392,4 +1395,4 @@ def add_code_review_comment(name: str, filename: str, line_number: int, comment: doc.save() return {"status": "success", "message": "Comment added successfully."} except Exception as e: - frappe.throw(f"Unable to add comment. Something went wrong: {e!s}") + frappe.throw(_("Unable to add comment. Something went wrong: {0}").format(e)) diff --git a/press/api/oauth.py b/press/api/oauth.py index 4c785c90165..4394b187687 100644 --- a/press/api/oauth.py +++ b/press/api/oauth.py @@ -2,6 +2,7 @@ import os import frappe +from frappe import _ from frappe.core.utils import find from frappe.utils import get_url from frappe.utils.oauth import get_oauth2_authorize_url @@ -44,9 +45,7 @@ def google_login(saas_app=None): flow = google_oauth_flow() authorization_url, state = flow.authorization_url() minutes = 5 - frappe.cache().set_value( - f"fc_oauth_state:{state}", saas_app or state, expires_in_sec=minutes * 60 - ) + frappe.cache().set_value(f"fc_oauth_state:{state}", saas_app or state, expires_in_sec=minutes * 60) return authorization_url @@ -84,13 +83,9 @@ def callback(code=None, state=None): # phone (this may return nothing if info doesn't exists) number = "" if flow.credentials.refresh_token: # returns only for the first authorization - credentials = Credentials.from_authorized_user_info( - json.loads(flow.credentials.to_json()) - ) + credentials = Credentials.from_authorized_user_info(json.loads(flow.credentials.to_json())) service = build("people", "v1", credentials=credentials) - person = ( - service.people().get(resourceName="people/me", personFields="phoneNumbers").execute() - ) + person = service.people().get(resourceName="people/me", personFields="phoneNumbers").execute() if person: phone = person.get("phoneNumbers") if phone: @@ -120,9 +115,7 @@ def callback(code=None, state=None): phone_number=number, ) frappe.local.response.type = "redirect" - frappe.local.response.location = ( - f"/dashboard/setup-account/{account_request.request_key}" - ) + frappe.local.response.location = f"/dashboard/setup-account/{account_request.request_key}" # login else: frappe.local.login_manager.login_as(email) @@ -152,12 +145,12 @@ def create_account_request(email, first_name, last_name, phone_number=""): @frappe.whitelist(allow_guest=True) def saas_setup(key, app, country, subdomain): if not check_subdomain_availability(subdomain, app): - frappe.throw(f"Subdomain {subdomain} is already taken") + frappe.throw(_("Subdomain {0} is already taken").format(subdomain)) all_countries = frappe.db.get_all("Country", pluck="name") country = find(all_countries, lambda x: x.lower() == country.lower()) if not country: - frappe.throw("Country filed should be a valid country name") + frappe.throw(_("Country filed should be a valid country name")) # create team and user account_request = get_account_request_from_key(key) diff --git a/press/api/partner.py b/press/api/partner.py index 7d1bf556acb..cec2028fa2f 100644 --- a/press/api/partner.py +++ b/press/api/partner.py @@ -1,6 +1,7 @@ import json import frappe +from frappe import _ from frappe.core.utils import find from frappe.desk.form.load import get_docinfo from frappe.query_builder import Case @@ -107,7 +108,7 @@ def get_partner_details(partner_email): ) if data: return data[0] - frappe.throw("Partner Details not found") + frappe.throw(_("Partner Details not found")) return None @@ -117,7 +118,7 @@ def send_link_certificate_request(user_email, certificate_type): if not frappe.db.exists( "Partner Certificate", {"partner_member_email": user_email, "course": certificate_type} ): - frappe.throw(f"No certificate found for the {user_email} with given course") + frappe.throw(_("No certificate found for the {0} with given course").format(user_email)) team = get_current_team(get_doc=True) @@ -170,7 +171,7 @@ def transfer_credits(amount, customer): partner = get_current_team(get_doc=True) if not partner.erpnext_partner and partner.partner_status != "Active": - frappe.throw("Only Partner team can transfer credits.") + frappe.throw(_("Only Partner team can transfer credits.")) amt = frappe.utils.flt(amount) partner_doc = frappe.get_doc("Team", partner) @@ -179,7 +180,7 @@ def transfer_credits(amount, customer): discount_percent = DISCOUNT_MAP.get(partner_level[0]) if partner_level else 0 if credits_available < amt: - frappe.throw(f"Insufficient Credits to transfer. Credits Available: {credits_available}") + frappe.throw(_("Insufficient Credits to transfer. Credits Available: {0}").format(credits_available)) customer_doc = frappe.get_doc("Team", customer) credits_to_transfer = amt @@ -202,7 +203,7 @@ def transfer_credits(amount, customer): frappe.db.commit() return amt except Exception: - frappe.throw("Error in transferring credits") + frappe.throw(_("Error in transferring credits")) frappe.db.rollback() @@ -720,7 +721,7 @@ def create_audit_request(audit_date, audit_type="Online"): ) if frappe.utils.getdate(audit_date) <= frappe.utils.getdate(): - frappe.throw("Audit date must be in the future. Please choose a date later than today's date.") + frappe.throw(_("Audit date must be in the future. Please choose a date later than today's date.")) try: doc = frappe.new_doc("Partner Audit") @@ -737,7 +738,7 @@ def create_audit_request(audit_date, audit_type="Online"): def change_partner(lead_name, partner): doc = frappe.get_doc("Partner Lead", lead_name) if not is_lead_team(lead_name): - frappe.throw("You are not allowed to change the partner for this lead") + frappe.throw(_("You are not allowed to change the partner for this lead")) doc.partner_team = partner doc.status = "Open" @@ -768,12 +769,12 @@ def remove_partner(): def apply_for_certificate(member_name, certificate_type): team = get_current_team(get_doc=True) if not team.erpnext_partner and team.partner_status != "Active": - frappe.throw("Only Active Partner team can apply for certificates.") + frappe.throw(_("Only Active Partner team can apply for certificates.")) if frappe.db.exists( "Partner Certificate Request", {"partner_member_email": member_name, "course": certificate_type} ): - frappe.throw("A certificate request already exists for this team member and course.") + frappe.throw(_("A certificate request already exists for this team member and course.")) doc = frappe.new_doc("Partner Certificate Request") doc.update( @@ -790,7 +791,7 @@ def apply_for_certificate(member_name, certificate_type): @role_guard.api("partner") def get_partner_teams(company=None, email=None, country=None, tier=None, active_only=False): if not is_system_user(frappe.session.user): - frappe.throw("Only system users can access partner teams.") + frappe.throw(_("Only system users can access partner teams.")) filters = {"enabled": 1, "erpnext_partner": 1} if company: @@ -836,7 +837,7 @@ def update_lead_details(lead_name, lead_details): lead_details = frappe._dict(lead_details) doc = frappe.get_doc("Partner Lead", lead_name) if not is_lead_team(lead_name): - frappe.throw("You are not allowed to update this lead") + frappe.throw(_("You are not allowed to update this lead")) doc.update( { "organization_name": lead_details.organization_name, @@ -859,7 +860,7 @@ def update_lead_details(lead_name, lead_details): @role_guard.api("partner") def update_lead_status(lead_name, status, **kwargs): # noqa: C901 if not is_lead_team(lead_name): - frappe.throw("You are not allowed to update this lead") + frappe.throw(_("You are not allowed to update this lead")) doc = frappe.get_doc("Partner Lead", lead_name) status_dict = {"status": status} @@ -888,14 +889,14 @@ def update_lead_status(lead_name, status, **kwargs): # noqa: C901 ) result = query.run(as_dict=True) if not result: - frappe.throw("Server not found in Frappe Cloud") + frappe.throw(_("Server not found in Frappe Cloud")) amount = calculate_total_amount(result[0].name) elif team: team_id = frappe.db.exists("Team", {"user": team, "enabled": 1}) if not team_id: - frappe.throw("Team not found in Frappe Cloud") + frappe.throw(_("Team not found in Frappe Cloud")) else: amount = calculate_total_team_amount(team_id) @@ -908,7 +909,7 @@ def update_lead_status(lead_name, status, **kwargs): # noqa: C901 ) result = query.run(as_dict=True) if not result: - frappe.throw("Site not found in Frappe Cloud") + frappe.throw(_("Site not found in Frappe Cloud")) SitePlan = frappe.qb.DocType("Site Plan") paid_plans = ( @@ -919,7 +920,7 @@ def update_lead_status(lead_name, status, **kwargs): # noqa: C901 ) site_plan = result[0].plan if site_plan not in paid_plans: - frappe.throw("The site is not on a paid plan, please select the correct hosting") + frappe.throw(_("The site is not on a paid plan, please select the correct hosting")) status_dict.update( { @@ -1015,7 +1016,7 @@ def get_fc_plans(): @role_guard.api("partner") def update_followup_details(id, lead, followup_details): if not is_lead_team(lead): - frappe.throw("You are not allowed to update this followup") + frappe.throw(_("You are not allowed to update this followup")) followup_details = frappe._dict(followup_details) doc = frappe.get_doc("Partner Lead", lead) @@ -1052,7 +1053,7 @@ def add_new_lead(lead_details): lead_details = frappe._dict(lead_details) team = get_current_team(get_doc=True) if not team.erpnext_partner and team.partner_status != "Active": - frappe.throw("Only Active Partner team can add new leads.") + frappe.throw(_("Only Active Partner team can add new leads.")) doc = frappe.new_doc("Partner Lead") doc.update( diff --git a/press/api/product_trial.py b/press/api/product_trial.py index cde35f4795f..cb556295214 100644 --- a/press/api/product_trial.py +++ b/press/api/product_trial.py @@ -7,6 +7,7 @@ import frappe import frappe.utils +from frappe import _ from frappe.rate_limiter import rate_limit from press.api.account import get_account_request_from_key @@ -45,7 +46,7 @@ def send_verification_code_for_login(email: str, product: str): product, frappe.db.get_value("Team", {"user": email}, "name") ) if not is_user_exists: - frappe.throw("You have no active sites for this product. Please try signing up.") + frappe.throw(_("You have no active sites for this product. Please try signing up.")) # generate otp and store in redis otp = str(random.randint(100000, 999999)) frappe.cache.set_value( @@ -63,21 +64,21 @@ def login_using_code(email: str, product: str, code: str): team_exists = frappe.db.exists("Team", {"user": email}) site = _get_active_site(product, frappe.db.get_value("Team", {"user": email}, "name")) if not team_exists: - frappe.throw("You have no active sites for this product. Please try signing up.") + frappe.throw(_("You have no active sites for this product. Please try signing up.")) # check if team has 2fa enabled and active team = frappe.get_value("Team", {"user": email}, ["name", "enforce_2fa", "enabled"], as_dict=True) if not team.enabled: - frappe.throw("Your account is disabled. Please contact support.") + frappe.throw(_("Your account is disabled. Please contact support.")) if team.enforce_2fa: - frappe.throw("Your account has 2FA enabled. Please go to frappecloud.com to login.") + frappe.throw(_("Your account has 2FA enabled. Please go to frappecloud.com to login.")) # validate code code_hash_from_cache = frappe.cache.get_value(f"product_trial_login_verification_code:{email}") if not code_hash_from_cache: - frappe.throw("OTP has expired. Please try again.") + frappe.throw(_("OTP has expired. Please try again.")) if frappe.utils.sha256_hash(str(code)) != code_hash_from_cache: - frappe.throw("Invalid OTP. Please try again.") + frappe.throw(_("Invalid OTP. Please try again.")) # remove code from cache frappe.cache.delete_value(f"product_trial_login_verification_code:{email}") @@ -104,16 +105,16 @@ def get_account_request_for_product_signup(): def setup_account(key: str, country: str | None = None): ar = get_account_request_from_key(key) if not ar: - frappe.throw("Invalid or Expired Key") + frappe.throw(_("Invalid or Expired Key")) if not ar.product_trial: - frappe.throw("Invalid Product Trial") + frappe.throw(_("Invalid Product Trial")) if country: ar.country = country ar.save(ignore_permissions=True) if not ar.country: - frappe.throw("Please provide a valid country name") + frappe.throw(_("Please provide a valid country name")) frappe.set_user("Administrator") # check if team already exists diff --git a/press/api/saas.py b/press/api/saas.py index 052b3631eed..1245ccb3d6f 100644 --- a/press/api/saas.py +++ b/press/api/saas.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.core.utils import find from press.api.account import get_account_request_from_key @@ -43,16 +44,20 @@ def account_request( frappe.utils.validate_email_address(email, True) if not check_subdomain_availability(subdomain, app): - frappe.throw(f"Subdomain {subdomain} is already taken. Please try with some other subdomain.") + frappe.throw( + _("Subdomain {0} is already taken. Please try with some other subdomain.").format(subdomain) + ) all_countries = frappe.db.get_all("Country", pluck="name") country = find(all_countries, lambda x: x.lower() == country.lower()) if not country: - frappe.throw("{country} is not a valid country. Please choose the correct country value.") + frappe.throw(_("{country} is not a valid country. Please choose the correct country value.")) team = frappe.db.get_value("Team", {"user": email}) if team and frappe.db.exists("Invoice", {"team": team, "status": "Unpaid", "type": "Subscription"}): - frappe.throw(f"Account {email} already exists with unpaid invoices. Please clear the previous dues.") + frappe.throw( + _(f"Account {email} already exists with unpaid invoices. Please clear the previous dues.") + ) current_user = frappe.session.user try: @@ -209,7 +214,7 @@ def setup_account(key, business_data=None): """ account_request = get_account_request_from_key(key) if not account_request: - frappe.throw("Invalid or Expired Key") # nosemgrep + frappe.throw(_("Invalid or Expired Key")) # nosemgrep capture( "init_server_setup_account", @@ -254,7 +259,7 @@ def headless_setup_account(key): """ account_request = get_account_request_from_key(key) if not account_request: - frappe.throw("Invalid or Expired Key") # nosemgrep + frappe.throw(_("Invalid or Expired Key")) # nosemgrep capture( "init_server_setup_account", @@ -338,7 +343,7 @@ def get_site_status(key, app=None): """ account_request = get_account_request_from_key(key) if not account_request: - frappe.throw("Invalid or Expired Key") # nosemgrep + frappe.throw(_("Invalid or Expired Key")) # nosemgrep domain = get_saas_domain(app) if app else get_erpnext_domain() @@ -361,7 +366,7 @@ def get_site_url_and_sid(key, app=None): """ account_request = get_account_request_from_key(key) if not account_request: - frappe.throw("Invalid or Expired Key") # nosemgrep + frappe.throw(_("Invalid or Expired Key")) # nosemgrep domain = get_saas_domain(app) if app else get_erpnext_domain() diff --git a/press/api/selfhosted.py b/press/api/selfhosted.py index 13e4f80f559..432d5b92fe0 100644 --- a/press/api/selfhosted.py +++ b/press/api/selfhosted.py @@ -2,6 +2,7 @@ import frappe from dns.resolver import Resolver +from frappe import _ from frappe.utils import strip from press.api.server import plans @@ -50,10 +51,10 @@ def create_self_hosted_server(server_details, team, proxy_server): def validate_team(team): if not team: - frappe.throw("You must be part of a team to create a new server") + frappe.throw(_("You must be part of a team to create a new server")) if not team.enabled: - frappe.throw("You cannot create a new server because your account is disabled") + frappe.throw(_("You cannot create a new server because your account is disabled")) if not team.self_hosted_servers_enabled: frappe.throw( @@ -165,5 +166,5 @@ def create_and_verify_selfhosted(server): setup(self_hosted_server_name) return frappe.get_value("Self Hosted Server", self_hosted_server_name, "server") - frappe.throw("Server verification failed. Please check the server details and try again.") + frappe.throw(_("Server verification failed. Please check the server details and try again.")) return None diff --git a/press/api/server.py b/press/api/server.py index ba614fadb65..65e4244542d 100644 --- a/press/api/server.py +++ b/press/api/server.py @@ -9,6 +9,7 @@ import frappe import requests +from frappe import _ from frappe.utils import convert_utc_to_timezone, flt from frappe.utils.caching import redis_cache from frappe.utils.password import get_decrypted_password @@ -203,7 +204,7 @@ def get_reclaimable_size(name): def new_unified(server: UnifiedServerDetails): team = get_current_team(get_doc=True) if not team.enabled: - frappe.throw("You cannot create a new server because your account is disabled") + frappe.throw(_("You cannot create a new server because your account is disabled")) cluster: Cluster = frappe.get_doc("Cluster", server["cluster"]) @@ -240,11 +241,11 @@ def new(server): auto_increase_storage = server.get("auto_increase_storage", False) if server_plan_platform == "arm64" and not cluster_has_arm_support: - frappe.throw(f"ARM Instances are currently unavailable in the {server['cluster']} region") + frappe.throw(_("ARM Instances are currently unavailable in the {0} region").format(server["cluster"])) team = get_current_team(get_doc=True) if not team.enabled: - frappe.throw("You cannot create a new server because your account is disabled") + frappe.throw(_("You cannot create a new server because your account is disabled")) cluster: Cluster = frappe.get_doc("Cluster", server["cluster"]) @@ -596,7 +597,7 @@ def prometheus_query( try: response = requests.get(url, params=query, auth=("frappe", str(password))).json() except requests.exceptions.RequestException: - frappe.throw("Unable to connect to monitor server", MonitorServerDown) + frappe.throw(_("Unable to connect to monitor server"), MonitorServerDown) datasets: list[dict] = [] labels: list[float] = [] @@ -627,7 +628,7 @@ def prometheus_query( @frappe.whitelist() def options(): if not get_current_team(get_doc=True).servers_enabled: - frappe.throw("Servers feature is not yet enabled on your account") + frappe.throw(_("Servers feature is not yet enabled on your account")) regions_filter = {"cloud_provider": ("!=", "Generic"), "public": True, "status": "Active"} @@ -1027,7 +1028,7 @@ def schedule_auto_scale( ) if (formatted_scheduled_scale_down_time - formatted_scheduled_scale_up_time).total_seconds() / 60 < 60: - frappe.throw("Scheduled scales must be an hour apart", frappe.ValidationError) + frappe.throw(_("Scheduled scales must be an hour apart"), frappe.ValidationError) validate_scaling_schedule( name, diff --git a/press/api/site.py b/press/api/site.py index 2e55b739243..6d17c256d0c 100644 --- a/press/api/site.py +++ b/press/api/site.py @@ -10,6 +10,7 @@ import wrapt from boto3 import client from botocore.exceptions import ClientError +from frappe import _ from frappe.core.utils import find from frappe.desk.doctype.tag.tag import add_tag from frappe.query_builder import Case @@ -79,7 +80,7 @@ def wrapper(wrapped, instance, args, kwargs): # Get the name of the document being accessed. if not (docname := get_protected_doctype_name(args, kwargs, doctypes)): - frappe.throw("Name not found, API access not permitted", frappe.PermissionError) # nosemgrep + frappe.throw(_("Name not found, API access not permitted"), frappe.PermissionError) # nosemgrep current_team = get_current_team() for doctype in doctypes: @@ -87,7 +88,7 @@ def wrapper(wrapped, instance, args, kwargs): if document_team == current_team or has_support_access(doctype, docname): return wrapped(*args, **kwargs) - frappe.throw("Not Permitted", frappe.PermissionError) # nosemgrep + frappe.throw(_("Not Permitted"), frappe.PermissionError) # nosemgrep return None return wrapper @@ -275,7 +276,7 @@ def get_group_for_new_site_and_set_localisation_app(site, apps): @validate_argument_types def validate_plan(server: str, plan: str) -> None: if not frappe.db.exists("Site Plan", plan): - frappe.throw(f"Plan {plan} does not exist", frappe.DoesNotExistError) # nosemgrep + frappe.throw(_("Plan {0} does not exist").format(plan), frappe.DoesNotExistError) # nosemgrep site_plan = frappe.db.get_value( "Site Plan", @@ -307,7 +308,7 @@ def validate_plan(server: str, plan: str) -> None: if frappe.session.data.user_type == "System User": return - frappe.throw("You are not allowed to use this plan") # nosemgrep + frappe.throw(_("You are not allowed to use this plan")) # nosemgrep @frappe.whitelist() @@ -507,7 +508,7 @@ def create_site_on_private_bench( sources = {x.app: x.source for x in frappe_app_source + app_sources} for app in apps: if app not in sources: - frappe.throw(f"Source not found for app {app}. Please verify for a valid app source.") + frappe.throw(_("Source not found for app {0}. Please verify for a valid app source.").format(app)) apps_with_sources.append({"app": app, "source": sources[app]}) @@ -851,7 +852,7 @@ def _get_team_dedicated_server_info(for_server: str | None = None): if not servers: if for_server: - frappe.throw(f"Server {for_server} not found") # nosemgrep + frappe.throw(_("Server {0} not found").format(for_server)) # nosemgrep return { "case": "no_dedicated_server", "dedicated_servers": [], @@ -2297,7 +2298,7 @@ def get_backup_links(url, email, password): try: files = get_frappe_backups(url, email, password) except requests.RequestException as e: - frappe.throw(f"Could not fetch backups from {url}. Error: {e}") # nosemgrep + frappe.throw(_("Could not fetch backups from {0}. Error: {1}").format(url, e)) # nosemgrep remote_files = [] for file_type, file_url in files.items(): file_name = file_url.split("backups/")[1].split("?sid=")[0] @@ -2647,7 +2648,7 @@ def check_app_compatibility_for_upgrade(name, version): for app in site_app_names: source = source_map.get(app) if not source or not source.enabled: - frappe.throw(f"Could not find a valid source for app {app}.") # nosemgrep + frappe.throw(_("Could not find a valid source for app {0}.").format(app)) # nosemgrep # Treat frappe-owned apps as public apps requiring compatibility checks if source.public or source.repository_owner == "frappe": public_apps.append(app) @@ -2801,7 +2802,7 @@ def create_private_bench_for_site_upgrade( version_upgrade.insert() return release_group_doc.name except Exception as e: - frappe.throw(f"Failed to create and deploy bench: {e!s}") # nosemgrep + frappe.throw(_("Failed to create and deploy bench: {0}").format(e)) # nosemgrep @frappe.whitelist() @@ -2909,7 +2910,7 @@ def fetch_sites_data_for_export(): def get_next_version(version): version_number = frappe.db.get_value("Frappe Version", version, "number") if not version_number: - frappe.throw(f"Invalid Frappe version: {version}") # nosemgrep + frappe.throw(_("Invalid Frappe version: {0}").format(version)) # nosemgrep next_version = frappe.db.get_value( "Frappe Version", @@ -2921,7 +2922,7 @@ def get_next_version(version): "name", ) if not next_version: - frappe.throw(f"Next version not found for {version}") # nosemgrep + frappe.throw(_("Next version not found for {0}").format(version)) # nosemgrep return next_version @@ -2963,7 +2964,7 @@ def _get_apps_for_version_upgrade( # noqa: C901 if not source or not source.enabled: if not is_site_app: continue - frappe.throw(f"Invalid source for {app_name}") + frappe.throw(_("Invalid source for {0}").format(app_name)) # Public / Frappe app if source.public or source.repository_owner == "frappe": @@ -2989,7 +2990,7 @@ def _get_apps_for_version_upgrade( # noqa: C901 if not custom_source: if not is_site_app: continue - frappe.throw(f"Custom app source not provided for {app_name}") + frappe.throw(_("Custom app source not provided for {0}").format(app_name)) custom_source_name = _get_custom_app_upgrade_source( app_name=app_name, @@ -3018,9 +3019,9 @@ def _get_custom_app_upgrade_source( repository_url = app_source.repository_url github_installation_id = app_source.github_installation_id if not branch: - frappe.throw(f"Branch not provided for {app_name}") # nosemgrep + frappe.throw(_("Branch not provided for {0}").format(app_name)) # nosemgrep if not repository_url: - frappe.throw(f"Repository URL not provided for {app_name}") # nosemgrep + frappe.throw(_("Repository URL not provided for {0}").format(app_name)) # nosemgrep validate_frappe_version_for_branch( app_name=app_name, diff --git a/press/api/site_backup.py b/press/api/site_backup.py index d8cde87d8d9..6128f82fd49 100644 --- a/press/api/site_backup.py +++ b/press/api/site_backup.py @@ -1,6 +1,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from press.press.doctype.site_backup.site_backup import OngoingSnapshotError @@ -30,16 +31,16 @@ def create_snapshot(name: str, key: str): site_backup.reload() # Re-verify if the snapshot was created and linked to the site backup if not site_backup.database_snapshot: - frappe.throw("Failed to create a snapshot for the database server. Please retry.") + frappe.throw(_("Failed to create a snapshot for the database server. Please retry.")) except ClientError as e: if e.response["Error"]["Code"] == "SnapshotCreationPerVolumeRateExceeded": # Agent will wait atleast 15s and then will retry # https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html#:~:text=SnapshotCreationPerVolumeRateExceeded - frappe.throw("Snapshot creation per volume rate exceeded") + frappe.throw(_("Snapshot creation per volume rate exceeded")) else: raise e except OngoingSnapshotError: - frappe.throw("There are concurrent snapshot creation requests. Try again later.") + frappe.throw(_("There are concurrent snapshot creation requests. Try again later.")) except Exception as e: raise e finally: diff --git a/press/api/site_login.py b/press/api/site_login.py index 6e211c21438..a22271543a9 100644 --- a/press/api/site_login.py +++ b/press/api/site_login.py @@ -29,12 +29,12 @@ def sync_product_site_user(**data): ) if not site_token: - frappe.throw("Invalid communication secret. Please verify your key secret and retry.") + frappe.throw(_("Invalid communication secret. Please verify your key secret and retry.")) site = frappe.db.get_value("Site", site, ["saas_communication_secret", "name"], as_dict=True) if site.saas_communication_secret != site_token: - frappe.throw("The secret seems invalid. Please verify your key secret and retry.") + frappe.throw(_("The secret seems invalid. Please verify your key secret and retry.")) user_info = data.get("user_info") @@ -81,7 +81,7 @@ def get_product_sites_of_user(user: str): or not isinstance(session_id, str) or not frappe.db.exists("Site User Session", {"user": user, "session_id": session_id}) ) and (frappe.session.user == "Guest"): - return frappe.throw("Invalid session") # nosemgrep + return frappe.throw(_("Invalid session")) # nosemgrep sites = frappe.db.get_all( "Site User", filters={"user": user, "enabled": 1}, fields=["site"], pluck="site" @@ -110,7 +110,7 @@ def send_otp(email: str): last_otp = frappe.db.get_value("Site User Session", {"user": email}, "otp_generated_at") if last_otp and (frappe.utils.now_datetime() - last_otp).seconds < 30: - return frappe.throw("Please wait for 30 seconds before sending the OTP again") # nosemgrep + return frappe.throw(_("Please wait for 30 seconds before sending the OTP again")) # nosemgrep session = frappe.get_doc({"doctype": "Site User Session", "user": email}).insert(ignore_permissions=True) return session.send_otp() @@ -128,19 +128,19 @@ def verify_otp(email: str, otp: str): "Site User Session", {"user": email}, ["name", "session_id", "otp", "otp_generated_at"], as_dict=True ) if not session: - return frappe.throw("Invalid session") # nosemgrep + return frappe.throw(_("Invalid session")) # nosemgrep if not session.otp: - return frappe.throw("OTP is not set. Please set OTP and try.") + return frappe.throw(_("OTP is not set. Please set OTP and try.")) if (frappe.utils.now_datetime() - session.otp_generated_at).seconds > 300: - return frappe.throw("OTP is expired. Please re-send and try again") + return frappe.throw(_("OTP is expired. Please re-send and try again")) ip_tracker = get_login_attempt_tracker(frappe.local.request_ip) if session.otp != otp: ip_tracker and ip_tracker.add_failure_attempt() - return frappe.throw("Invalid OTP") # nosemgrep + return frappe.throw(_("Invalid OTP")) # nosemgrep frappe.db.set_value("Site User Session", session.name, {"otp": None, "verified": 1}) ip_tracker and ip_tracker.add_success_attempt() @@ -161,15 +161,15 @@ def login_to_site(email: str, site: str): session_id = frappe.local.request.cookies.get("site_user_sid") if not session_id or not isinstance(session_id, str): if frappe.session.user == "Guest": - return frappe.throw("Invalid session. Please login to {site}.") + return frappe.throw(_("Invalid session. Please login to {site}.")) frappe.get_doc({"doctype": "Site User Session", "user": email}).insert(ignore_permissions=True) - site_user_name = frappe.db.get_value("Site User", {"user": email, "site": site}, "name") - if not site_user_name: - return frappe.throw(f"User {email} not found in site {site}") + site_user_name = frappe.db.get_value("Site User", {"user": email, "site": site}, "name") + if not site_user_name: + return frappe.throw(_("User {0} not found in site {1}").format(email, site)) site_user = frappe.get_doc("Site User", site_user_name) if not site_user.enabled: - frappe.throw(_(f"User is disabled for the site {site}")) # nosemgrep + frappe.throw(_("User is disabled for the site {0}").format(site)) # nosemgrep return site_user.login_to_site() diff --git a/press/auth.py b/press/auth.py index 3e13cc093a8..aeb12c45446 100644 --- a/press/auth.py +++ b/press/auth.py @@ -6,6 +6,7 @@ import traceback import frappe +from frappe import _ PRESS_AUTH_KEY = "press-auth-logs" PRESS_AUTH_MAX_ENTRIES = 1000000 @@ -85,7 +86,7 @@ def hook(): # noqa: C901 if path in DENIED_PATHS: log(path, user_type) - frappe.throw("Access not allowed for this URL", frappe.AuthenticationError) + frappe.throw(_("Access not allowed for this URL"), frappe.AuthenticationError) for denied in DENIED_WILDCARD_PATHS: if path.startswith(denied): @@ -96,7 +97,7 @@ def hook(): # noqa: C901 return log(path, user_type) - frappe.throw("Access not allowed for this URL", frappe.AuthenticationError) + frappe.throw(_("Access not allowed for this URL"), frappe.AuthenticationError) return diff --git a/press/guards/settings.py b/press/guards/settings.py index 5cf6435cc0d..3b9b273a2c8 100644 --- a/press/guards/settings.py +++ b/press/guards/settings.py @@ -1,6 +1,7 @@ import functools import frappe +from frappe import _ SETTINGS_DOCTYPE = "Press Settings" @@ -23,7 +24,7 @@ def inner(*args, **kwargs): if frappe.db.get_single_value(SETTINGS_DOCTYPE, key, cache=True): return func(*args, **kwargs) if raise_error: - frappe.throw("This feature is disabled", frappe.ValidationError) + frappe.throw(_("This feature is disabled"), frappe.ValidationError) return default_value return inner diff --git a/press/infrastructure/doctype/arm_build_record/arm_build_record.py b/press/infrastructure/doctype/arm_build_record/arm_build_record.py index e97325ec431..92dd785c454 100644 --- a/press/infrastructure/doctype/arm_build_record/arm_build_record.py +++ b/press/infrastructure/doctype/arm_build_record/arm_build_record.py @@ -7,6 +7,7 @@ import typing import frappe +from frappe import _ from frappe.model.document import Document from press.agent import Agent @@ -117,7 +118,7 @@ def pull_images(self): for image in self.arm_images: if image.status != Status.SUCCESS.value: - frappe.throw("Some builds failed skipping image pull!", frappe.ValidationError) + frappe.throw(_("Some builds failed skipping image pull!"), frappe.ValidationError) builds.append(image.build) image_tags = frappe.db.get_all( diff --git a/press/infrastructure/doctype/virtual_disk_resize/virtual_disk_resize.py b/press/infrastructure/doctype/virtual_disk_resize/virtual_disk_resize.py index 9262d0b5b60..f48a57c0fed 100644 --- a/press/infrastructure/doctype/virtual_disk_resize/virtual_disk_resize.py +++ b/press/infrastructure/doctype/virtual_disk_resize/virtual_disk_resize.py @@ -10,6 +10,7 @@ import botocore import frappe +from frappe import _ from frappe.core.utils import find, find_all from frappe.model.document import Document @@ -132,7 +133,7 @@ def add_steps(self): def validate_aws_only(self): if self.machine.cloud_provider != "AWS EC2": - frappe.throw("This feature is only available for AWS EC2") + frappe.throw(_("This feature is only available for AWS EC2")) def validate_existing_migration(self): if existing := frappe.get_all( @@ -145,12 +146,12 @@ def validate_existing_migration(self): pluck="status", limit=1, ): - frappe.throw(f"An existing shrink document is already {existing[0].lower()}.") + frappe.throw(_("An existing shrink document is already {0}.").format(existing[0].lower())) def set_filesystem_attributes(self): devices = self.fetch_devices() if len(devices) != 1: - frappe.throw("Multiple filesystems found on volume. Can't shrink") + frappe.throw(_("Multiple filesystems found on volume. Can't shrink")) self.old_filesystem_device = f"/dev/{devices[0]['name']}" @@ -272,14 +273,14 @@ def _parse_filesystems(self, raw_filesystems): def verify_mount_point(self, device, filesystem): if device["mountpoint"] != filesystem["mount_point"]: - frappe.throw("Device and Filesystem mount point don't match. Can't shrink") + frappe.throw(_("Device and Filesystem mount point don't match. Can't shrink")) def reaffirm_old_filesystem_used(self, mountpoint: str): """Reaffirm file system usage using du""" output = self.ansible_run(f"du -sx --block-size=1024 {mountpoint}")["output"] if not output: - frappe.throw("Error occurred while fetching filesystem size") + frappe.throw(_("Error occurred while fetching filesystem size")) size = float(output.split()[0]) return size / 1024**2 @@ -303,9 +304,9 @@ def set_old_volume_id(self): volumes = find_all(machine.volumes, lambda v: v.volume_id != root_volume.volume_id) if len(volumes) == 0: - frappe.throw("No additional volumes found. Cannot shrink any volume.") + frappe.throw(_("No additional volumes found. Cannot shrink any volume.")) elif len(volumes) > 1: - frappe.throw("Multiple volumes found. Please select the volume to shrink.") + frappe.throw(_("Multiple volumes found. Please select the volume to shrink.")) self.old_volume_id = volumes[0].volume_id @@ -442,7 +443,7 @@ def snapshot_machine(self) -> StepStatus: pluck="name", ) if len(snapshots) == 0: - frappe.throw("Failed to create a snapshot") + frappe.throw(_("Failed to create a snapshot")) self.virtual_disk_snapshot = snapshots[0] return StepStatus.Success diff --git a/press/infrastructure/doctype/virtual_machine_migration/virtual_machine_migration.py b/press/infrastructure/doctype/virtual_machine_migration/virtual_machine_migration.py index e3554d27af6..1042d60b97f 100644 --- a/press/infrastructure/doctype/virtual_machine_migration/virtual_machine_migration.py +++ b/press/infrastructure/doctype/virtual_machine_migration/virtual_machine_migration.py @@ -10,6 +10,7 @@ from typing import TYPE_CHECKING, Literal import frappe +from frappe import _ from frappe.core.utils import find from frappe.model.document import Document @@ -254,7 +255,7 @@ def set_new_plan(self): def validate_aws_only(self): if self.machine.cloud_provider != "AWS EC2": - frappe.throw("This feature is only available for AWS EC2") + frappe.throw(_("This feature is only available for AWS EC2")) def validate_existing_migration(self): if existing := frappe.get_all( @@ -267,7 +268,7 @@ def validate_existing_migration(self): pluck="status", limit=1, ): - frappe.throw(f"An existing migration is already {existing[0].lower()}.") + frappe.throw(_("An existing migration is already {0}.").format(existing[0].lower())) @property def machine(self) -> VirtualMachine: diff --git a/press/infrastructure/doctype/virtual_machine_replacement/virtual_machine_replacement.py b/press/infrastructure/doctype/virtual_machine_replacement/virtual_machine_replacement.py index 75fd4aa67bc..eb158fa5f19 100644 --- a/press/infrastructure/doctype/virtual_machine_replacement/virtual_machine_replacement.py +++ b/press/infrastructure/doctype/virtual_machine_replacement/virtual_machine_replacement.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.model.document import Document if TYPE_CHECKING: @@ -67,7 +68,7 @@ def create_machine_copy(self): def validate_aws_only(self): if self.machine.cloud_provider != "AWS EC2": - frappe.throw("This feature is only available for AWS EC2") + frappe.throw(_("This feature is only available for AWS EC2")) def validate_existing_replacement(self): if existing := frappe.get_all( @@ -80,7 +81,7 @@ def validate_existing_replacement(self): pluck="status", limit=1, ): - frappe.throw(f"An existing replacement is already {existing[0].lower()}.") + frappe.throw(_("An existing replacement is already {0}.").format(existing[0].lower())) @property def machine(self): diff --git a/press/marketplace/doctype/marketplace_app_subscription/marketplace_app_subscription.py b/press/marketplace/doctype/marketplace_app_subscription/marketplace_app_subscription.py index 6401d88a7dc..3952fd9c127 100644 --- a/press/marketplace/doctype/marketplace_app_subscription/marketplace_app_subscription.py +++ b/press/marketplace/doctype/marketplace_app_subscription/marketplace_app_subscription.py @@ -3,6 +3,7 @@ import frappe import requests +from frappe import _ from frappe.model.document import Document from press.press.doctype.site.site import Site @@ -21,23 +22,19 @@ def set_secret_key(self): def create_site_config_key(self): if not frappe.db.exists("Site Config Key", {"key": f"sk_{self.app}"}): - frappe.get_doc( - doctype="Site Config Key", internal=True, key=f"sk_{self.app}" - ).insert(ignore_permissions=True) + frappe.get_doc(doctype="Site Config Key", internal=True, key=f"sk_{self.app}").insert( + ignore_permissions=True + ) def validate_marketplace_app_plan(self): app = frappe.db.get_value("Marketplace App Plan", self.marketplace_app_plan, "app") if app != self.app: - frappe.throw( - f"Plan {self.marketplace_app_plan} is not for app {frappe.bold(self.app)}!" - ) + frappe.throw(f"Plan {self.marketplace_app_plan} is not for app {frappe.bold(self.app)}!") def set_plan(self): if not self.plan or self.has_value_changed("marketplace_app_plan"): - self.plan = frappe.db.get_value( - "Marketplace App Plan", self.marketplace_app_plan, "plan" - ) + self.plan = frappe.db.get_value("Marketplace App Plan", self.marketplace_app_plan, "plan") def validate_duplicate_subscription(self): if not self.site: @@ -58,9 +55,7 @@ def before_insert(self): def on_update(self): if self.has_value_changed("marketplace_app_plan"): - self.plan = frappe.db.get_value( - "Marketplace App Plan", self.marketplace_app_plan, "plan" - ) + self.plan = frappe.db.get_value("Marketplace App Plan", self.marketplace_app_plan, "plan") frappe.db.set_value("Subscription", self.subscription, "plan", self.plan) if self.has_value_changed("team"): @@ -109,9 +104,9 @@ def set_keys_in_site_config(self): "type": "JSON", }, ] - if "prepaid" == frappe.db.get_value( + if frappe.db.get_value( "Saas Settings", self.app, "billing_type" - ) and frappe.db.get_value("Site", self.site, "trial_end_date"): + ) == "prepaid" and frappe.db.get_value("Site", self.site, "trial_end_date"): config.append( { "key": "app_include_js", @@ -131,7 +126,7 @@ def set_keys_in_site_config(self): @frappe.whitelist() def activate(self): if self.status == "Active": - frappe.throw("Subscription is already active.") + frappe.throw(_("Subscription is already active.")) self.status = "Active" self.save() diff --git a/press/overrides.py b/press/overrides.py index 0b8a6016c4e..7aff29c6aec 100644 --- a/press/overrides.py +++ b/press/overrides.py @@ -6,6 +6,7 @@ from functools import partial import frappe +from frappe import _ from frappe.core.doctype.user.user import User from frappe.handler import is_whitelisted from frappe.utils import cint @@ -85,7 +86,7 @@ def on_login(login_manager): not has_2fa.get("last_verified_at") or has_2fa.get("last_verified_at") < frappe.utils.add_to_date(None, seconds=-10) ): - frappe.throw("Please re-login to verify your identity.") + frappe.throw(_("Please re-login to verify your identity.")) if not frappe.db.exists("Team", {"user": frappe.session.user, "enabled": 1}) and frappe.db.exists( "Team", {"user": frappe.session.user, "enabled": 0} diff --git a/press/partner/doctype/partner_approval_request/partner_approval_request.py b/press/partner/doctype/partner_approval_request/partner_approval_request.py index 727c541e4ad..0472d8dc724 100644 --- a/press/partner/doctype/partner_approval_request/partner_approval_request.py +++ b/press/partner/doctype/partner_approval_request/partner_approval_request.py @@ -3,6 +3,7 @@ from __future__ import annotations import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils import get_url @@ -73,7 +74,7 @@ def send_approval_request_email(self): email = frappe.db.get_value("Team", self.partner, "partner_email") partner_manager = client.get_value("Partner", "success_manager", {"email": email}) if not partner_manager: - frappe.throw("Failed to create approval request. Please contact support.") + frappe.throw(_("Failed to create approval request. Please contact support.")) customer = frappe.db.get_value("Team", self.requested_by, "user") link = get_url(f"/api/method/press.api.partner.approve_partner_request?key={self.key}") diff --git a/press/press/doctype/account_request/account_request.py b/press/press/doctype/account_request/account_request.py index 44d2b56ea0a..e99e13da09c 100644 --- a/press/press/doctype/account_request/account_request.py +++ b/press/press/doctype/account_request/account_request.py @@ -6,6 +6,7 @@ import json import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils import get_url, random_string, validate_email_address @@ -79,7 +80,7 @@ def before_insert(self): and not self.oauth_signup and not is_valid_email_address(self.email) ): - frappe.throw(f"{self.email} is not a valid email address") + frappe.throw(_("{0} is not a valid email address").format(self.email)) if not self.team: self.team = self.email diff --git a/press/press/doctype/agent_job/agent_job.py b/press/press/doctype/agent_job/agent_job.py index b089f779d28..cfc822d2bc9 100644 --- a/press/press/doctype/agent_job/agent_job.py +++ b/press/press/doctype/agent_job/agent_job.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.core.utils import find from frappe.model.document import Document from frappe.monitor import add_data_to_monitor @@ -98,7 +99,7 @@ def get_list_query(query, filters=None, **list_args): bench = cstr(filters.get("bench", "")) if not (site or group or server or bench): - frappe.throw("Not permitted", frappe.PermissionError) + frappe.throw(_("Not permitted"), frappe.PermissionError) if site and not has_support_access("Site", site): is_owned_by_team("Site", site, raise_exception=True) diff --git a/press/press/doctype/agent_update/agent_update.py b/press/press/doctype/agent_update/agent_update.py index 4cea73b57b5..b203ace6b8e 100644 --- a/press/press/doctype/agent_update/agent_update.py +++ b/press/press/doctype/agent_update/agent_update.py @@ -11,6 +11,7 @@ import frappe import frappe.utils import requests +from frappe import _ from frappe.model.document import Document from press.agent import Agent @@ -136,10 +137,10 @@ def before_insert(self): # noqa: C901 self.status = "Draft" if not (self.app_server or self.database_server or self.proxy_server): - frappe.throw("Please select at least one server type") + frappe.throw(_("Please select at least one server type")) if not self.restart_web_workers and not self.restart_rq_workers and not self.restart_redis: - frappe.throw("At minimum, you need to restart web workers during update") + frappe.throw(_("At minimum, you need to restart web workers during update")) if self.restart_redis: # noqa: SIM102 if not self.restart_rq_workers or not self.restart_web_workers: @@ -159,14 +160,14 @@ def before_insert(self): # noqa: C901 self.branch = press_settings.branch or "master" if self.repo.startswith("http://") or self.repo.startswith("https://"): - frappe.throw("Please don't append http/https to the repo url") + frappe.throw(_("Please don't append http/https to the repo url")) # Set commit hash if not self.commit_hash: self.commit_hash = self.fetch_commit_hash(self.branch) else: if self.fetch_commit_hash(self.branch) != self.commit_hash: - frappe.throw("Commit hash looks in valid. Please recheck") + frappe.throw(_("Commit hash looks in valid. Please recheck")) # Set commit message if not self.commit_message: @@ -175,10 +176,12 @@ def before_insert(self): # noqa: C901 # Verify rollback commit hash if self.auto_rollback_changes and self.rollback_to_specific_commit: if not self.default_rollback_commit: - frappe.throw("Rollback commit hash is required when rollback to specific commit is enabled") + frappe.throw( + _("Rollback commit hash is required when rollback to specific commit is enabled") + ) if self.fetch_commit_date(self.default_rollback_commit) is None: - frappe.throw("Rollback commit hash is not valid") + frappe.throw(_("Rollback commit hash is not valid")) # Add servers self.add_server_entries() @@ -223,18 +226,20 @@ def _split_updates(self, no_of_batches: int): frappe.db.get_value(self.doctype, self.name, "name", for_update=True) if self.status != "Pending": - frappe.throw("You can only split updates when the status is Pending") + frappe.throw(_("You can only split updates when the status is Pending")) if not self.servers: - frappe.throw("No servers found to split updates") + frappe.throw(_("No servers found to split updates")) if len(self.servers) < no_of_batches: frappe.throw( - f"You have only {len(self.servers)} servers, can't split into {no_of_batches} groups" + _("You have only {0} servers, can't split into {1} groups").format( + len(self.servers), no_of_batches + ) ) if no_of_batches <= 1: - frappe.throw("You need to split into at least 2 groups") + frappe.throw(_("You need to split into at least 2 groups")) """ For splitting updates, we need to create a duplicate Agent Update document for N groups @@ -243,7 +248,7 @@ def _split_updates(self, no_of_batches: int): # Create N new Agent Update documents new_agent_updates = [self.name] - for _ in range(no_of_batches - 1): + for _i in range(no_of_batches - 1): doc = frappe.get_doc( { "doctype": "Agent Update", @@ -383,7 +388,7 @@ def _create_execution_plan(self): # noqa: C901 @frappe.whitelist() def force_continue(self): if self.status not in ["Failure", "Partial Success"]: - frappe.throw("You can only force continue when the status is Failure or Partial Success") + frappe.throw(_("You can only force continue when the status is Failure or Partial Success")) # Reset failed updates for failed_update in self.servers: @@ -406,14 +411,14 @@ def force_continue(self): @frappe.whitelist() def pause(self): if self.status not in ["Running"]: - frappe.throw("You can only pause when the update is Running") + frappe.throw(_("You can only pause when the update is Running")) self.status = "Paused" self.save(ignore_version=True) @frappe.whitelist() def execute(self): if self.status not in ["Pending", "Running"]: - frappe.throw("You can only call execute when the status is Pending or Running") + frappe.throw(_("You can only call execute when the status is Pending or Running")) if self._process_next_step(): frappe.enqueue_doc( diff --git a/press/press/doctype/ansible_play/ansible_play.py b/press/press/doctype/ansible_play/ansible_play.py index bd945b5418b..546d0ea9086 100644 --- a/press/press/doctype/ansible_play/ansible_play.py +++ b/press/press/doctype/ansible_play/ansible_play.py @@ -1,9 +1,9 @@ -# -*- coding: utf-8 -*- # Copyright (c) 2020, Frappe and contributors # For license information, please see license.txt import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils import cstr @@ -54,7 +54,7 @@ def get_list_query(query, filters=None, **list_args): server = cstr(filters.get("server", "")) if not server: - frappe.throw("Not permitted", frappe.PermissionError) + frappe.throw(_("Not permitted"), frappe.PermissionError) if server.startswith("["): servers = frappe.parse_json(server.replace("'", '"'))[1] diff --git a/press/press/doctype/app_patch/app_patch.py b/press/press/doctype/app_patch/app_patch.py index 46775618094..e4f3b88a8e4 100644 --- a/press/press/doctype/app_patch/app_patch.py +++ b/press/press/doctype/app_patch/app_patch.py @@ -9,6 +9,7 @@ import frappe import requests +from frappe import _ from frappe.model.document import Document from press.agent import Agent @@ -77,7 +78,7 @@ def validate(self): def validate_bench(self): if frappe.get_value("Bench", self.bench, "status") == "Active": return - frappe.throw(f"Bench {self.bench} is not Active, patch cannot be applied") + frappe.throw(_("Bench {0} is not Active, patch cannot be applied").format(self.bench)) def before_insert(self): patches = frappe.get_all( @@ -89,7 +90,7 @@ def before_insert(self): return filename = patches[0].get("filename") - frappe.throw(f"Patch already exists for {self.bench} by the filename {filename}") + frappe.throw(_("Patch already exists for {0} by the filename {1}").format(self.bench, filename)) def after_insert(self): self.apply_patch() diff --git a/press/press/doctype/app_release/app_release.py b/press/press/doctype/app_release/app_release.py index 2ae1e23706a..275ee8bbe36 100644 --- a/press/press/doctype/app_release/app_release.py +++ b/press/press/doctype/app_release/app_release.py @@ -13,6 +13,7 @@ import frappe import semantic_version as sv import tomli +from frappe import _ from frappe.model.document import Document from press.api.github import get_access_token @@ -598,7 +599,7 @@ def get_release_by_source_and_hash(source: str, hash: str) -> AppReleaseDict: ) if not releases: - frappe.throw(f"App Release not found with source: {source} and hash: {hash}") + frappe.throw(_("App Release not found with source: {0} and hash: {1}").format(source, hash)) return releases[0] diff --git a/press/press/doctype/app_release_approval_request/app_release_approval_request.py b/press/press/doctype/app_release_approval_request/app_release_approval_request.py index 3f7f3875ebc..0024cc7287f 100644 --- a/press/press/doctype/app_release_approval_request/app_release_approval_request.py +++ b/press/press/doctype/app_release_approval_request/app_release_approval_request.py @@ -6,6 +6,7 @@ import re import frappe +from frappe import _ from frappe.model.document import Document from frappe.model.naming import make_autoname from pygments import highlight @@ -94,7 +95,7 @@ def request_already_exists(self): ) if len(requests) > 0: - frappe.throw("An active request for this app release already exists!") + frappe.throw(_("An active request for this app release already exists!")) def another_request_awaiting_approval(self): request_source = frappe.db.get_value("App Release", self.app_release, "source") @@ -110,7 +111,7 @@ def another_request_awaiting_approval(self): # A request for this source is already open if request_source in sources_awaiting_approval: - frappe.throw("A previous release is already awaiting approval!") + frappe.throw(_("A previous release is already awaiting approval!")) def update_release_status(self): release: AppRelease = frappe.get_doc("App Release", self.app_release) diff --git a/press/press/doctype/app_release_difference/app_release_difference.py b/press/press/doctype/app_release_difference/app_release_difference.py index ae3f93ade37..957220c6086 100644 --- a/press/press/doctype/app_release_difference/app_release_difference.py +++ b/press/press/doctype/app_release_difference/app_release_difference.py @@ -7,6 +7,7 @@ import typing import frappe +from frappe import _ from frappe.model.document import Document from github import Github @@ -37,7 +38,9 @@ class AppReleaseDifference(Document): def validate(self): if self.source_release == self.destination_release: - frappe.throw("Destination Release must be different from Source Release", frappe.ValidationError) + frappe.throw( + frappe._("Destination Release must be different from Source Release"), frappe.ValidationError + ) def _get_branch_from_app_source(self, release: str) -> str | None: AppRelease = frappe.qb.DocType("App Release") @@ -76,7 +79,7 @@ def set_deploy_type(self): try: github_access_token = get_access_token(source.github_installation_id) except KeyError: - frappe.throw(f"Could not get access token for app source {source.name}") + frappe.throw(_("Could not get access token for app source {0}").format(source.name)) else: github_access_token = frappe.get_value("Press Settings", None, "github_access_token") diff --git a/press/press/doctype/app_source/app_source.py b/press/press/doctype/app_source/app_source.py index 1597d2cf321..cdaeee75de6 100644 --- a/press/press/doctype/app_source/app_source.py +++ b/press/press/doctype/app_source/app_source.py @@ -135,7 +135,9 @@ def validate_duplicate_versions(self): versions = set() for row in self.versions: if row.version in versions: - frappe.throw(f"Version {row.version} can be added only once", frappe.ValidationError) + frappe.throw( + frappe._("Version {0} can be added only once").format(row.version), frappe.ValidationError + ) versions.add(row.version) def before_save(self): diff --git a/press/press/doctype/auto_scale_record/auto_scale_record.py b/press/press/doctype/auto_scale_record/auto_scale_record.py index cd29d55ca26..da7488f8d60 100644 --- a/press/press/doctype/auto_scale_record/auto_scale_record.py +++ b/press/press/doctype/auto_scale_record/auto_scale_record.py @@ -9,6 +9,7 @@ from typing import Literal import frappe +from frappe import _ from frappe.model.document import Document from requests.exceptions import ConnectionError, HTTPError, JSONDecodeError @@ -130,7 +131,7 @@ def before_insert(self): self.secondary_server = frappe.db.get_value("Server", self.primary_server, "secondary_server") if not self.secondary_server: - frappe.throw("Primary server must have a secondary server to auto scale") + frappe.throw(_("Primary server must have a secondary server to auto scale")) def get_doc(self, doc): doc.steps = self.get_steps_for_dashboard() @@ -757,7 +758,7 @@ def validate_scaling_schedule( ) if existing_scheduled_scales: - frappe.throw("Scale is already scheduled for this time", frappe.ValidationError) + frappe.throw(_("Scale is already scheduled for this time"), frappe.ValidationError) _is_scale_up_colliding_with_a_existing_scaling_window(name, scale_up_time) _is_scale_down_colliding_with_a_existing_scaling_window(name, scale_down_time) diff --git a/press/press/doctype/backup_restoration_test/backup_restoration_test.py b/press/press/doctype/backup_restoration_test/backup_restoration_test.py index 6e69e9305c8..5860ae8fb70 100644 --- a/press/press/doctype/backup_restoration_test/backup_restoration_test.py +++ b/press/press/doctype/backup_restoration_test/backup_restoration_test.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe import _ from frappe.model.document import Document from press.api.site import _new @@ -49,7 +50,7 @@ def check_duplicate_test(self): pluck="name", ) if backups: - frappe.throw(f"Backup Restoration Test for {self.site} is already running.") + frappe.throw(_("Backup Restoration Test for {0} is already running.").format(self.site)) def check_duplicate_active_site(self): # check if any active backup restoration test site is active @@ -59,7 +60,9 @@ def check_duplicate_active_site(self): pluck="name", ) if sites: - frappe.throw(f"Site {self.test_site} is already active. Please archive the site first.") + frappe.throw( + _("Site {0} is already active. Please archive the site first.").format(self.test_site) + ) def create_brt_site(self) -> None: site_dict = prepare_site(str(self.site)) diff --git a/press/press/doctype/balance_transaction/balance_transaction.py b/press/press/doctype/balance_transaction/balance_transaction.py index f69fd92d43e..10a15b2c659 100644 --- a/press/press/doctype/balance_transaction/balance_transaction.py +++ b/press/press/doctype/balance_transaction/balance_transaction.py @@ -3,6 +3,7 @@ from __future__ import annotations import frappe +from frappe import _ from frappe.model.document import Document from press.overrides import get_permission_query_conditions_for_doctype @@ -47,7 +48,7 @@ class BalanceTransaction(Document): def validate(self): if self.amount == 0: - frappe.throw("Amount cannot be 0") + frappe.throw(_("Amount cannot be 0")) def before_submit(self): if self.type == "Partnership Fee": @@ -130,7 +131,7 @@ def validate_total_unallocated_amount(self): or [] ) if not unallocated_amounts: - frappe.throw("Cannot create transaction as no unallocated amount found") + frappe.throw(_("Cannot create transaction as no unallocated amount found")) if sum(unallocated_amounts) < abs(self.amount): frappe.throw( f"Cannot create transaction as unallocated amount {sum(unallocated_amounts)} is less than {self.amount}" diff --git a/press/press/doctype/bench/bench.py b/press/press/doctype/bench/bench.py index 809ef5d654b..73ca106f394 100644 --- a/press/press/doctype/bench/bench.py +++ b/press/press/doctype/bench/bench.py @@ -11,6 +11,7 @@ import frappe import pytz +from frappe import _ from frappe.exceptions import DoesNotExistError from frappe.model.document import Document from frappe.model.naming import append_number_if_name_exists, make_autoname @@ -323,7 +324,7 @@ def validate(self): self.update_config_with_rg_config(config) if not (server_private_ip := frappe.db.get_value("Server", self.server, "private_ip")): - frappe.throw("Server must have a private IP to create Bench") # nosemgrep + frappe.throw(_("Server must have a private IP to create Bench")) # nosemgrep bench_config = { "docker_image": self.docker_image, @@ -372,13 +373,13 @@ def add_limits(self, bench_config): if any([self.memory_high, self.memory_max, self.memory_swap]): if not all([self.memory_high, self.memory_max, self.memory_swap]): - frappe.throw("All memory limits are required. Please set the memory limits for the bench.") + frappe.throw(_("All memory limits are required. Please set the memory limits for the bench.")) if self.memory_swap != -1 and (self.memory_max > self.memory_swap): - frappe.throw("Memory Swap needs to be greater than Memory Max") # nosemgrep + frappe.throw(_("Memory Swap needs to be greater than Memory Max")) # nosemgrep if self.memory_high > self.memory_max: - frappe.throw("Memory Max needs to be greater than Memory High") # nosemgrep + frappe.throw(_("Memory Max needs to be greater than Memory High")) # nosemgrep bench_config.update(self.get_limits()) @@ -725,7 +726,7 @@ def move_sites(self, server: str): @frappe.whitelist() def retry_bench(self): if frappe.get_value("Deploy Candidate Build", self.build, "status") != "Success": - frappe.throw(f"Deploy Candidate Build {self.build} is not Active") # nosemgrep + frappe.throw(_("Deploy Candidate Build {0} is not Active").format(self.build)) # nosemgrep deploy_candidate_build: "DeployCandidateBuild" = frappe.get_doc("Deploy Candidate Build", self.build) deploy_candidate_build._create_deploy([self.server]) @@ -1080,7 +1081,7 @@ def check_archive_jobs(self): ignore_ifnull=True, order_by="job_type", ): - frappe.throw("Bench is already archived", ArchiveBenchError) # nosemgrep + frappe.throw(_("Bench is already archived"), ArchiveBenchError) # nosemgrep def check_ongoing_jobs(self): frappe.db.commit() @@ -1252,7 +1253,7 @@ class StagingSite(Site): def __init__(self, bench: Bench): plan = frappe.db.get_value("Press Settings", None, "staging_plan") if not plan: - frappe.throw("Staging plan not set in settings") # nosemgrep + frappe.throw(_("Staging plan not set in settings")) # nosemgrep log_error(title="Staging plan not set in settings") super().__init__( { diff --git a/press/press/doctype/bench_update/bench_update.py b/press/press/doctype/bench_update/bench_update.py index e4f5404a07d..46689056a8b 100644 --- a/press/press/doctype/bench_update/bench_update.py +++ b/press/press/doctype/bench_update/bench_update.py @@ -6,6 +6,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.model.document import Document from press.utils import get_current_team @@ -54,7 +55,7 @@ def before_save(self): def validate_pending_updates(self): if frappe.get_doc("Release Group", self.group).deploy_in_progress: - frappe.throw("A deploy for this bench is already in progress", frappe.ValidationError) + frappe.throw(_("A deploy for this bench is already in progress"), frappe.ValidationError) def validate_pending_site_updates(self): for site in self.sites: @@ -62,7 +63,7 @@ def validate_pending_site_updates(self): "Site Update", {"site": site.site, "status": ("in", ("Pending", "Running"))}, ): - frappe.throw("An update is already pending for this site", frappe.ValidationError) + frappe.throw(_("An update is already pending for this site"), frappe.ValidationError) def validate_inplace_update(self): sites = [s.site for s in self.sites if s.site] @@ -189,7 +190,7 @@ def get_bench_update( rg_team = frappe.db.get_value("Release Group", name, "team") if rg_team != current_team: - frappe.throw("Bench can only be deployed by the bench owner", exc=frappe.PermissionError) + frappe.throw(_("Bench can only be deployed by the bench owner"), exc=frappe.PermissionError) bench_update: "BenchUpdate" = frappe.get_doc( { diff --git a/press/press/doctype/build_cache_shell/build_cache_shell.py b/press/press/doctype/build_cache_shell/build_cache_shell.py index 085f4702086..640cbed8f12 100644 --- a/press/press/doctype/build_cache_shell/build_cache_shell.py +++ b/press/press/doctype/build_cache_shell/build_cache_shell.py @@ -4,6 +4,7 @@ import json import frappe +from frappe import _ from frappe.model.document import Document from press.agent import Agent @@ -38,7 +39,7 @@ def run_command(self): def _run_command(self): if not self.build_server: - frappe.throw("Please select a Build Server.") + frappe.throw(_("Please select a Build Server.")) return Agent(self.build_server).run_command_in_docker_cache( self.command, diff --git a/press/press/doctype/cluster/cluster.py b/press/press/doctype/cluster/cluster.py index c7987a73a75..7972d7696a9 100644 --- a/press/press/doctype/cluster/cluster.py +++ b/press/press/doctype/cluster/cluster.py @@ -15,6 +15,7 @@ import frappe import oci import pydo +from frappe import _ from frappe.model.document import Document from frappe.utils.caching import redis_cache from hcloud import APIException, Client @@ -179,14 +180,14 @@ def validate_hetzner_api_token(self): servers = client.servers.get_all() if servers is None: - frappe.throw("API token does not have read access to the Hetzner Cloud.") + frappe.throw(_("API token does not have read access to the Hetzner Cloud.")) except APIException as e: # Handle specific API exceptions like unauthorized access if e.code == "unauthorized": - frappe.throw("API token is invalid or does not have the correct permissions.") + frappe.throw(_("API token is invalid or does not have the correct permissions.")) else: - frappe.throw(f"An error occurred while validating the API token: {e}") + frappe.throw(_("An error occurred while validating the API token: {0}").format(e)) def validate_aws_credentials(self): settings: "PressSettings" = frappe.get_single("Press Settings") @@ -221,7 +222,7 @@ def validate_flush_table_execution_hour(self): "Flush Table Execution Hour is required when Enable Periodic Flush Table is checked." ) if not (0 <= self.flush_table_execution_hour <= 23): - frappe.throw("Flush Table Execution Hour must be between 0 and 23.") + frappe.throw(_("Flush Table Execution Hour must be between 0 and 23.")) def after_insert(self): if self.cloud_provider == "AWS EC2": @@ -273,7 +274,7 @@ def _add_digital_ocean_vpc(self, client): ) self.vpc_id = network["vpc"]["id"] except Exception as e: - frappe.throw(f"Failed to provision VPC on Digital Ocean: {e!s}") + frappe.throw(_("Failed to provision VPC on Digital Ocean: {0}").format(e)) def _add_digital_ocean_ssh_keys(self, client): """Adds the SSH key to Digital Ocean if it doesn't already exist""" @@ -287,7 +288,7 @@ def _add_digital_ocean_ssh_keys(self, client): except Exception as e: if "SSH Key is already in use" in str(e): return - frappe.throw(f"Failed to create SSH Key on Digital Ocean: {e!s}") + frappe.throw(_("Failed to create SSH Key on Digital Ocean: {0}").format(e)) def _add_digital_ocean_proxy_firewall(self, client): """Adds the proxy firewall to Digital Ocean if it doesn't already exist""" @@ -319,7 +320,7 @@ def _add_digital_ocean_proxy_firewall(self, client): ) self.proxy_security_group_id = firewall["firewall"]["id"] except Exception as e: - frappe.throw(f"Failed to create Proxy Firewall on Digital Ocean: {e!s}") + frappe.throw(_("Failed to create Proxy Firewall on Digital Ocean: {0}").format(e)) def _add_digital_ocean_firewall(self, client): """Adds the firewall to Digital Ocean if it doesn't already exist""" @@ -373,11 +374,11 @@ def _add_digital_ocean_firewall(self, client): ) if "id" not in firewall.get("firewall", {}): - frappe.throw("Failed to create Firewall on Digital Ocean.") + frappe.throw(_("Failed to create Firewall on Digital Ocean.")) self.security_group_id = firewall["firewall"]["id"] except Exception as e: - frappe.throw(f"Failed to create Firewall on Digital Ocean: {e!s}") + frappe.throw(_("Failed to create Firewall on Digital Ocean: {0}").format(e)) frappe.msgprint( "To add this cluster to monitoring, go to the Monitor Server and trigger the 'Reconfigure Monitor Server' action from the Actions menu." @@ -406,7 +407,7 @@ def provision_on_hetzner(self): self.vpc_id = network.id self.save() except APIException as e: - frappe.throw(f"Failed to provision network on Hetzner: {e!s}") + frappe.throw(_("Failed to provision network on Hetzner: {0}").format(e)) # Create the SSH Key on Hetzner try: @@ -418,7 +419,9 @@ def provision_on_hetzner(self): # If the SSH key already exists, retrieve it existing_keys = client.ssh_keys.get_all(name=self.ssh_key) if len(existing_keys) == 0: - frappe.throw(f"SSH Key creation failed and '{self.ssh_key}' not found on Hetzner Cloud.") + frappe.throw( + _("SSH Key creation failed and '{0}' not found on Hetzner Cloud.").format(self.ssh_key) + ) try: # Create Server Firewall @@ -486,7 +489,7 @@ def provision_on_hetzner(self): self.security_group_id = server_firewall.firewall.id self.save() except APIException as e: - frappe.throw(f"Failed to provision server firewall on Hetzner: {e!s}") + frappe.throw(_("Failed to provision server firewall on Hetzner: {0}").format(e)) try: # Create Proxy Server Firewall @@ -512,7 +515,7 @@ def provision_on_hetzner(self): self.proxy_security_group_id = proxy_firewall.firewall.id self.save() except APIException as e: - frappe.throw(f"Failed to provision proxy server firewall on Hetzner: {e!s}") + frappe.throw(_("Failed to provision proxy server firewall on Hetzner: {0}").format(e)) def on_trash(self): machines = frappe.get_all( @@ -526,7 +529,7 @@ def on_trash(self): @frappe.whitelist() def add_images(self): if self.images_available == 1: - frappe.throw("Images are already available", frappe.ValidationError) + frappe.throw(_("Images are already available"), frappe.ValidationError) if not set(self.get_other_region_vmis(get_series=True)) - set( self.get_same_region_vmis(get_series=True) ): @@ -560,7 +563,7 @@ def validate_cidr_block(self): self.subnet_cidr_block = cidr_block break if not self.cidr_block: - frappe.throw("No CIDR block available", frappe.ValidationError) + frappe.throw(_("No CIDR block available"), frappe.ValidationError) def validate_monitoring_password(self): if not self.monitoring_password: @@ -1166,7 +1169,7 @@ def create_proxy(self): frappe.ValidationError, ) if self.status != "Active": - frappe.throw("Cluster is not active", frappe.ValidationError) + frappe.throw(_("Cluster is not active"), frappe.ValidationError) self.create_server("Proxy Server", DEFAULT_SERVER_TITLE) @@ -1179,11 +1182,11 @@ def create_servers(self): frappe.ValidationError, ) if self.status != "Active": - frappe.throw("Cluster is not active", frappe.ValidationError) + frappe.throw(_("Cluster is not active"), frappe.ValidationError) - for doctype, _ in self.base_servers.items(): + for doctype, _server_doctype in self.base_servers.items(): # TODO: remove Test title # - server, _ = self.create_server( + server, _result = self.create_server( doctype, DEFAULT_SERVER_TITLE, ) @@ -1194,7 +1197,7 @@ def create_servers(self): self.proxy_server = server.name if self.public: return - for doctype, _ in self.private_servers.items(): + for doctype, _srv in self.private_servers.items(): self.create_server( doctype, DEFAULT_SERVER_TITLE, @@ -1477,14 +1480,14 @@ def _normalize_firewall_rules(self, rules) -> list[tuple[str | int, str]]: normalized_rules.append((port, self._normalize_firewall_protocol(protocol))) if not normalized_rules: - frappe.throw("At least one firewall rule is required") + frappe.throw(_("At least one firewall rule is required")) return normalized_rules def _normalize_firewall_protocol(self, protocol: str) -> str: protocol = (protocol or "tcp").lower().strip() if protocol not in {"tcp", "udp"}: - frappe.throw("Firewall protocol must be one of: tcp, udp") + frappe.throw(_("Firewall protocol must be one of: tcp, udp")) return protocol def _parse_port_range(self, port: str | int) -> tuple[int, int]: diff --git a/press/press/doctype/code_server/code_server.py b/press/press/doctype/code_server/code_server.py index d5c36dce6d0..55d14dbf4a3 100644 --- a/press/press/doctype/code_server/code_server.py +++ b/press/press/doctype/code_server/code_server.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe import _ from frappe.model.document import Document from frappe.model.naming import append_number_if_name_exists @@ -36,18 +37,18 @@ def autoname(self): def validate(self): if not frappe.get_value("Bench", self.bench, "is_code_server_enabled"): - frappe.throw(f"Code Server not enabled for the selected Bench {self.bench}") + frappe.throw(_("Code Server not enabled for the selected Bench {0}").format(self.bench)) if self.has_value_changed("subdomain"): if frappe.db.exists("Code Server", self.name): frappe.throw( - f"Code Server {self.name} already exists please choose a different name" + frappe._("Code Server {0} already exists please choose a different name").format( + self.name + ) ) - if frappe.db.exists( - "Code Server", {"bench": self.bench, "status": ("!=", "Archived")} - ): + if frappe.db.exists("Code Server", {"bench": self.bench, "status": ("!=", "Archived")}): frappe.throw( - "Code Server already exists for selected bench choose a different bench" + frappe._("Code Server already exists for selected bench choose a different bench") ) if not self.proxy_server and self.has_value_changed("server"): self.proxy_server = frappe.db.get_value("Server", self.server, "proxy_server") diff --git a/press/press/doctype/communication_info/communication_info.py b/press/press/doctype/communication_info/communication_info.py index 2236e95929a..e95c5893720 100644 --- a/press/press/doctype/communication_info/communication_info.py +++ b/press/press/doctype/communication_info/communication_info.py @@ -4,6 +4,7 @@ from typing import Literal import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils import validate_email_address, validate_phone_number from frappe.utils.caching import redis_cache @@ -37,13 +38,13 @@ class CommunicationInfo(Document): def validate(self): if not self.parenttype or not self.parent: - frappe.throw("parenttype and parent are required") + frappe.throw(_("parenttype and parent are required")) if self.parenttype not in ("Team", "Site", "Server"): - frappe.throw("parenttype must be one of 'Team', 'Site', 'Server'") + frappe.throw(_("parenttype must be one of 'Team', 'Site', 'Server'")) if self.channel == "Phone Call" and self.type != "Incident": - frappe.throw("Phone Call is available only for 'Incident'") + frappe.throw(_("Phone Call is available only for 'Incident'")) if self.channel == "Email": validate_email_address(self.value, throw=True) @@ -56,10 +57,12 @@ def validate(self): # For Team, all types are allowed if self.parenttype == "Server" and self.type not in ("General", "Server Activity", "Incident"): - frappe.throw(f"Communication type '{self.type}' is not allowed for '{self.parenttype}'") + frappe.throw( + _("Communication type '{0}' is not allowed for '{1}'").format(self.type, self.parenttype) + ) if self.parenttype == "Site" and self.type not in ("General", "Site Activity"): - frappe.throw(f"Communication type '{self.type}' is not allowed for 'Site'") + frappe.throw(_("Communication type '{0}' is not allowed for 'Site'").format(self.type)) @redis_cache(ttl=10 * 60) @@ -136,7 +139,7 @@ def update_communication_infos( # noqa: C901 """ if resource_type not in ("Team", "Site", "Server"): - frappe.throw("resource_type must be one of 'Team', 'Site', 'Server'") + frappe.throw(_("resource_type must be one of 'Team', 'Site', 'Server'")) # Remove values with empty value values = [value for value in values if value.get("value")] @@ -192,7 +195,7 @@ def update_communication_infos( # noqa: C901 if resource_type == "Team": billing_count = sum(1 for value in values if value.get("type") == "Billing") if billing_count > 1: - frappe.throw("For Billing, only one email can be configured") + frappe.throw(_("For Billing, only one email can be configured")) # Delete unwanted if to_delete: diff --git a/press/press/doctype/database_server/database_server.py b/press/press/doctype/database_server/database_server.py index f3c3cc04c21..e004b48fa78 100644 --- a/press/press/doctype/database_server/database_server.py +++ b/press/press/doctype/database_server/database_server.py @@ -12,6 +12,7 @@ import frappe import frappe.utils import rq +from frappe import _ from frappe.core.doctype.version.version import get_diff from frappe.core.utils import find from frappe.utils import now_datetime @@ -230,7 +231,7 @@ def on_update(self): return if self.is_replication_setup and self.auto_purge_binlog_based_on_size: - frappe.throw("Cannot enable binlog auto purge for replication configured servers") + frappe.throw(_("Cannot enable binlog auto purge for replication configured servers")) self.update_mariadb_system_variables() if ( @@ -662,7 +663,7 @@ def add_or_update_mariadb_variable( # noqa: C901 ): """Add or update MariaDB variable on the server""" if not skip and not value: - frappe.throw("For non-skippable variables, value is mandatory") + frappe.throw(_("For non-skippable variables, value is mandatory")) self.flags.update_mariadb_system_variables_synchronously = update_variables_synchronously @@ -737,7 +738,9 @@ def get_mariadb_variable_value( # noqa: C901 def update_innodb_buffer_pool_size(self, size_mb: int): # InnoDB need to be at least 20% of RAM if size_mb < int(self.ram_for_mariadb * 0.2): - frappe.throw(f"InnoDB Buffer Size cannot be less than {int(self.ram_for_mariadb * 0.2)}MB.") + frappe.throw( + _("InnoDB Buffer Size cannot be less than {0}MB.").format(int(self.ram_for_mariadb * 0.2)) + ) # Hard limit 70% of Memory if size_mb > int(self.ram_for_mariadb * 0.70): @@ -750,10 +753,10 @@ def update_innodb_buffer_pool_size(self, size_mb: int): def update_binlog_retention(self, days: str | int): if isinstance(days, str): if not days.isdigit(): - frappe.throw("Binlog retention days must be a positive integer") + frappe.throw(_("Binlog retention days must be a positive integer")) days = int(days) if days < 1: - frappe.throw("Binlog retention days cannot be less than 1") + frappe.throw(_("Binlog retention days cannot be less than 1")) self.binlog_retention_days = days # From MariaDB 10.6.1, expire_logs_days is alias of binlog_expire_logs_seconds @@ -763,13 +766,13 @@ def update_binlog_retention(self, days: str | int): @dashboard_whitelist() def update_binlog_size_limit(self, enabled: bool, percent_of_disk_size: int): if self.is_part_of_replica: - frappe.throw("Cannot update binlog size limit for database replicas") + frappe.throw(_("Cannot update binlog size limit for database replicas")) if percent_of_disk_size is None: percent_of_disk_size = 0 if enabled: if percent_of_disk_size < 10 or percent_of_disk_size > 90: - frappe.throw("Percent of disk space must be between 10 and 90") + frappe.throw(_("Percent of disk space must be between 10 and 90")) self.binlog_max_disk_usage_percent = percent_of_disk_size self.auto_purge_binlog_based_on_size = True else: @@ -786,7 +789,7 @@ def update_max_db_connections(self, max_connections: int): f"Max Connections cannot be greater than {max_possible_connections}. If you need more connections, please increase memory of database server." ) if max_connections < 10: - frappe.throw("Max Connections cannot be less than 10") + frappe.throw(_("Max Connections cannot be less than 10")) self.add_or_update_mariadb_variable("max_connections", "value_str", str(max_connections), save=True) @@ -1042,7 +1045,7 @@ def setup_replication(self): @frappe.whitelist() def perform_physical_backup(self, path): if not path: - frappe.throw("Provide a path to store the physical backup") + frappe.throw(_("Provide a path to store the physical backup")) frappe.enqueue_doc( self.doctype, self.name, @@ -1674,7 +1677,7 @@ def adjust_memory_config(self): # noqa: C901 def set_innodb_force_recovery(self, value: int): """Set innodb_force_recovery to the given value""" if value < 0 or value > 6: - frappe.throw("innodb_force_recovery value must be between 0 and 6") + frappe.throw(_("innodb_force_recovery value must be between 0 and 6")) self.add_or_update_mariadb_variable( "innodb_force_recovery", "value_str", str(value), skip=False, persist=True, save=True ) @@ -1786,7 +1789,7 @@ def get_mariadb_variables(self): agent = Agent(self.name, "Database Server") return agent.fetch_database_variables() except Exception: - frappe.throw("Failed to fetch MariaDB Variables. Please try again.") + frappe.throw(_("Failed to fetch MariaDB Variables. Please try again.")) @property def mariadb_depends_on_mounts(self): @@ -1796,7 +1799,7 @@ def mariadb_depends_on_mounts(self): def get_binlogs_raw_data(self): if self.agent.should_skip_requests(): - frappe.throw("Server is not reachable. Please try again later.") + frappe.throw(_("Server is not reachable. Please try again later.")) return self.agent.fetch_binlog_list() @dashboard_whitelist() @@ -1840,7 +1843,7 @@ def get_binlog_summary(self): @dashboard_whitelist() def get_binlogs_indexing_status(self): if not self.enable_binlog_indexing: - frappe.throw("Binlog Indexing is not enabled for this server.") + frappe.throw(_("Binlog Indexing is not enabled for this server.")) data = frappe.db.get_all( "MariaDB Binlog", @@ -1884,16 +1887,16 @@ def purge_binlogs(self, to_binlog: str): if self.enable_binlog_indexing: self.sync_binlogs_info(index_binlogs=False, upload_binlogs=False) except Exception as e: - frappe.throw(f"Failed to purge binlogs. Please try again later. {e!s}") + frappe.throw(_("Failed to purge binlogs. Please try again later. {0}").format(e)) raise e @dashboard_whitelist() def purge_binlogs_forcefully(self, no_of_binlogs: int): if self.is_part_of_replica: - frappe.throw("The server has replication setup. Binlogs cannot be purged forcefully.") + frappe.throw(_("The server has replication setup. Binlogs cannot be purged forcefully.")) if not no_of_binlogs or not isinstance(no_of_binlogs, int) or no_of_binlogs < 0: - frappe.throw("No of Binlogs are invalid") + frappe.throw(_("No of Binlogs are invalid")) proxy = frappe.db.get_value("Proxy Server", {"status": "Active", "cluster": self.cluster}, "name") @@ -1962,7 +1965,7 @@ def purge_binlogs_forcefully(self, no_of_binlogs: int): is_failed = True if is_failed: - frappe.throw("Failed to purge binlogs. Reach out to support.frappe.io if the issue persists.") + frappe.throw(_("Failed to purge binlogs. Reach out to support.frappe.io if the issue persists.")) def purge_binlogs_by_configured_size_limit(self): if not self.auto_purge_binlog_based_on_size: @@ -2187,10 +2190,10 @@ def index_binlogs_on_demand(self, binlog_file_names: list[str]): return None if not self.enable_binlog_indexing: - frappe.throw("Binlog Indexing is not enabled for this server.") + frappe.throw(_("Binlog Indexing is not enabled for this server.")) if self._is_binlog_indexing_related_operation_running() or self.is_binlog_indexer_running: - frappe.throw("Another Binlog Indexing related operation is already in progress.") + frappe.throw(_("Another Binlog Indexing related operation is already in progress.")) job = self.agent.add_binlogs_to_indexer(binlog_file_names) return job.name @@ -2404,7 +2407,7 @@ def get_storage_usage(self): "db_name_site_map": db_name_site_mapping, } except Exception: - frappe.throw("Failed to fetch storage usage. Try again later.") + frappe.throw(_("Failed to fetch storage usage. Try again later.")) def set_mariadb_mount_dependency(self, now: bool | None = None): if not self.mariadb_depends_on_mounts: diff --git a/press/press/doctype/database_server_mariadb_variable/database_server_mariadb_variable.py b/press/press/doctype/database_server_mariadb_variable/database_server_mariadb_variable.py index 79cd4239e01..3a12659b56e 100644 --- a/press/press/doctype/database_server_mariadb_variable/database_server_mariadb_variable.py +++ b/press/press/doctype/database_server_mariadb_variable/database_server_mariadb_variable.py @@ -5,6 +5,7 @@ from typing import Any import frappe +from frappe import _ from frappe.model.document import Document from press.runner import Ansible @@ -85,19 +86,25 @@ def get_variable_dict_for_play(self) -> dict: def validate_only_one_value_is_set(self): if sum([bool(self.get(f)) for f in self.value_fields]) > 1: - frappe.throw("Only one value can be set for MariaDB system variable") + frappe.throw(_("Only one value can be set for MariaDB system variable")) def validate_datatype_of_field_is_correct(self): if type(self.value).__name__ != self.datatype.lower(): - frappe.throw(f"Value for {self.mariadb_variable} must be {self.datatype}") + frappe.throw(_("Value for {0} must be {1}").format(self.mariadb_variable, self.datatype)) def validate_value_field_set_is_correct(self): if self.value_field != f"value_{self.datatype.lower()}": - frappe.throw(f"Value field for {self.mariadb_variable} must be value_{self.datatype.lower()}") + frappe.throw( + _("Value field for {0} must be value_{1}").format( + self.mariadb_variable, self.datatype.lower() + ) + ) def validate_skipped_should_be_skippable(self): if self.skip and not self.skippable: - frappe.throw(f"Only skippable variables can be skipped. {self.mariadb_variable} is not skippable") + frappe.throw( + _(f"Only skippable variables can be skipped. {self.mariadb_variable} is not skippable") + ) def set_default_value_if_no_value(self): if self.value: @@ -108,7 +115,7 @@ def set_default_value_if_no_value(self): def validate_empty_only_if_skippable(self): if not self.value and not self.skippable: - frappe.throw(f"Value for {self.mariadb_variable} cannot be empty") + frappe.throw(_("Value for {0} cannot be empty").format(self.mariadb_variable)) def set_persist_and_unset_dynamic_if_skipped(self): if self.skip: diff --git a/press/press/doctype/deploy_candidate/deploy_candidate.py b/press/press/doctype/deploy_candidate/deploy_candidate.py index bd8e0f25a62..c2a496214f4 100644 --- a/press/press/doctype/deploy_candidate/deploy_candidate.py +++ b/press/press/doctype/deploy_candidate/deploy_candidate.py @@ -16,6 +16,7 @@ import frappe import semantic_version +from frappe import _ from frappe.core.utils import find from frappe.model.document import Document from frappe.model.naming import make_autoname @@ -211,7 +212,7 @@ def create_build(self, **kwargs) -> DeployCandidateBuild: servers = [server_ref.server for server_ref in self.release_group.servers] if frappe.get_value("Server", {"name": ("in", servers)}, "stop_deployments"): - frappe.throw("Deployments on this server are currently halted!") + frappe.throw(_("Deployments on this server are currently halted!")) kwargs.update( {"doctype": "Deploy Candidate Build", "deploy_candidate": self.name}, diff --git a/press/press/doctype/deploy_candidate_build/deploy_candidate_build.py b/press/press/doctype/deploy_candidate_build/deploy_candidate_build.py index cbc7247c734..356f52abcb8 100644 --- a/press/press/doctype/deploy_candidate_build/deploy_candidate_build.py +++ b/press/press/doctype/deploy_candidate_build/deploy_candidate_build.py @@ -22,6 +22,7 @@ import frappe import requests import semantic_version +from frappe import _ from frappe.core.utils import find from frappe.model.document import Document from frappe.utils import now_datetime as now @@ -1229,7 +1230,7 @@ def create_deploy(self, check_image_exists: bool = False): def _create_deploy(self, servers: list[str], check_image_exists: bool = False): if check_image_exists and not self.check_image_in_registry(): - frappe.throw("Image not found in registry create a new build", ImageNotFoundInRegistry) + frappe.throw(_("Image not found in registry create a new build"), ImageNotFoundInRegistry) return frappe.get_doc( { diff --git a/press/press/doctype/downtime_analysis/downtime_analysis.py b/press/press/doctype/downtime_analysis/downtime_analysis.py index f6dcb48d232..a07a6ed5f23 100644 --- a/press/press/doctype/downtime_analysis/downtime_analysis.py +++ b/press/press/doctype/downtime_analysis/downtime_analysis.py @@ -4,6 +4,7 @@ import json import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils.background_jobs import get_job_status from frappe.utils.password import get_decrypted_password @@ -39,9 +40,9 @@ def load_from_db(self): def fetch_report(self): frappe.only_for("Desk User") if not (self.start_date and self.end_date): - frappe.throw("Start Date and End Date are required to fetch the report.") + frappe.throw(_("Start Date and End Date are required to fetch the report.")) if self.start_date > self.end_date: - frappe.throw("Start Date cannot be greater than End Date.") + frappe.throw(_("Start Date cannot be greater than End Date.")) if is_report_available(str(self.start_date), str(self.end_date)): self.status = "Report Available" diff --git a/press/press/doctype/github_webhook_log/github_webhook_log.py b/press/press/doctype/github_webhook_log/github_webhook_log.py index 052e7844d06..c59ccbf2cfa 100644 --- a/press/press/doctype/github_webhook_log/github_webhook_log.py +++ b/press/press/doctype/github_webhook_log/github_webhook_log.py @@ -5,9 +5,10 @@ import hashlib import hmac import json -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.model.document import Document from frappe.query_builder import Interval from frappe.query_builder.functions import Now @@ -42,7 +43,7 @@ def validate(self): # noqa: C901 secret = frappe.db.get_single_value("Press Settings", "github_webhook_secret") digest = hmac.HMAC(secret.encode(), self.payload.encode(), hashlib.sha1) if not hmac.compare_digest(digest.hexdigest(), self.signature): - frappe.throw("Invalid Signature") + frappe.throw(_("Invalid Signature")) payload = self.get_parsed_payload() self.github_installation_id = payload.get("installation", {}).get("id") diff --git a/press/press/doctype/incident/incident.py b/press/press/doctype/incident/incident.py index 8ee9c840f0c..d5eec50787b 100644 --- a/press/press/doctype/incident/incident.py +++ b/press/press/doctype/incident/incident.py @@ -12,6 +12,7 @@ import frappe import requests +from frappe import _ from frappe.types.DF import Phone from frappe.utils import cint from frappe.utils.background_jobs import enqueue_doc @@ -410,7 +411,7 @@ def add_node_exporter_screenshot(self, page: Page, instance: str | None): def monitor_server(self) -> MonitorServer: press_settings: PressSettings = frappe.get_cached_doc("Press Settings") if not (monitor_url := press_settings.monitor_server): - frappe.throw("Monitor Server not set in Press Settings") + frappe.throw(_("Monitor Server not set in Press Settings")) return frappe.get_cached_doc("Monitor Server", monitor_url) def get_grafana_auth_header(self): @@ -437,7 +438,7 @@ def take_grafana_screenshots(self): def reboot_database_server(self): db_server_name = frappe.db.get_value("Server", self.server, "database_server") if not db_server_name: - frappe.throw("No database server found for this server") + frappe.throw(_("No database server found for this server")) db_server = DatabaseServer("Database Server", db_server_name) try: db_server.reboot_with_serial_console() @@ -485,7 +486,7 @@ def restart_down_benches(self): """ down_benches = self.monitor_server.get_benches_down_for_server(str(self.server)) if not down_benches: - frappe.throw("No down benches found for this server") + frappe.throw(_("No down benches found for this server")) return for bench_name in down_benches: bench: Bench = Bench("Bench", bench_name) diff --git a/press/press/doctype/invoice/invoice.py b/press/press/doctype/invoice/invoice.py index 8a928d826bf..1ab11fe2feb 100644 --- a/press/press/doctype/invoice/invoice.py +++ b/press/press/doctype/invoice/invoice.py @@ -242,7 +242,7 @@ def validate(self): def before_submit(self): if self.total > 0 and self.status != "Paid": - frappe.throw("Invoice must be Paid to be submitted") + frappe.throw(_("Invoice must be Paid to be submitted")) def calculate_values(self): if self.status == "Paid" and self.docstatus == 1: @@ -669,7 +669,9 @@ def validate_duplicate(self): }, ) if self.type == "Prepaid Credits" and self.stripe_payment_intent_id and invoice_exists: - frappe.throw("Invoice with same Stripe payment intent exists", frappe.DuplicateEntryError) + frappe.throw( + frappe._("Invoice with same Stripe payment intent exists"), frappe.DuplicateEntryError + ) if self.type == "Subscription" and self.period_start and self.period_end and self.is_new(): query = ( @@ -701,7 +703,7 @@ def validate_team(self): if not self.payment_mode: self.payment_mode = team.payment_mode if not self.currency: - frappe.throw(f"Cannot create Invoice because Currency is not set in Team {self.team}") + frappe.throw(_("Cannot create Invoice because Currency is not set in Team {0}").format(self.team)) def validate_dates(self): if not self.period_start: @@ -1198,7 +1200,7 @@ def refund(self, reason): charge = payment_intent["charges"]["data"][0]["id"] if not charge: - frappe.throw("Cannot refund payment because Stripe Charge not found for this invoice") + frappe.throw(_("Cannot refund payment because Stripe Charge not found for this invoice")) stripe.Refund.create(charge=charge) self.status = "Refunded" diff --git a/press/press/doctype/logical_replication_backup/logical_replication_backup.py b/press/press/doctype/logical_replication_backup/logical_replication_backup.py index 0a26c010407..4c42f07fe61 100644 --- a/press/press/doctype/logical_replication_backup/logical_replication_backup.py +++ b/press/press/doctype/logical_replication_backup/logical_replication_backup.py @@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Literal import frappe +from frappe import _ from frappe.model.document import Document from press.press.doctype.ansible_console.ansible_console import AnsibleAdHoc @@ -254,7 +255,7 @@ def stage_status(self): return self.post_migrate_stage_status if self.execution_stage == "Failover": return self.failover_stage_status - frappe.throw("Invalid execution stage for getting stage status") + frappe.throw(_("Invalid execution stage for getting stage status")) return None @stage_status.setter @@ -266,7 +267,7 @@ def stage_status(self, value: Literal["Pending", "Running", "Success", "Failure" elif self.execution_stage == "Failover": self.failover_stage_status = value else: - frappe.throw("Invalid execution stage for setting stage status.") + frappe.throw(_("Invalid execution stage for setting stage status.")) @property def site_doc(self) -> "Site": @@ -333,14 +334,14 @@ def site_replication_config_dict(self) -> dict: # type: ignore[return-value] try: return json.loads(self.site_replication_config or "{}") except json.JSONDecodeError: - frappe.throw("Invalid site replication config JSON format.") + frappe.throw(_("Invalid site replication config JSON format.")) @property def bench_replication_config_dict(self) -> dict: # type: ignore[return-value] try: return json.loads(self.bench_replication_config or "{}") except json.JSONDecodeError: - frappe.throw("Invalid bench replication config JSON format.") + frappe.throw(_("Invalid bench replication config JSON format.")) def after_insert(self): self.populate_server_infos() @@ -400,7 +401,7 @@ def pre__create_consistent_server_snapshot(self): self.save() return StepStatus.Success except Exception as e: - frappe.throw(f"Failed to create consistent server snapshot: {e}") + frappe.throw(_("Failed to create consistent server snapshot: {0}").format(e)) return StepStatus.Failure def pre__wait_for_servers_to_be_online(self): @@ -700,7 +701,7 @@ def failover__gather_binlog_position_from_new_master(self): .get("gtid_current_pos", "") ) if not self.initial_binlog_position_of_new_primary_db: - frappe.throw("Failed to gather initial binlog position from new master database server") + frappe.throw(_("Failed to gather initial binlog position from new master database server")) self.save() return StepStatus.Success @@ -1085,7 +1086,7 @@ def current_execution_steps(self) -> list["LogicalReplicationStep"]: if self.execution_stage == "Failover": return self.failover_steps - frappe.throw(f"Invalid execution stage: {self.execution_stage}") + frappe.throw(_("Invalid execution stage: {0}").format(self.execution_stage)) return None # type: ignore[return-value] @property diff --git a/press/press/doctype/logical_replication_step/logical_replication_step.py b/press/press/doctype/logical_replication_step/logical_replication_step.py index ee1d7ed4826..37ba4a29313 100644 --- a/press/press/doctype/logical_replication_step/logical_replication_step.py +++ b/press/press/doctype/logical_replication_step/logical_replication_step.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe import _ from frappe.model.document import Document @@ -31,4 +32,4 @@ class LogicalReplicationStep(Document): def validate(self): if self.is_async and self.wait_for_completion: - frappe.throw("Cannot wait for completion on async kind of step") + frappe.throw(_("Cannot wait for completion on async kind of step")) diff --git a/press/press/doctype/mariadb_variable/mariadb_variable.py b/press/press/doctype/mariadb_variable/mariadb_variable.py index 806c37c7cea..a08a3c96685 100644 --- a/press/press/doctype/mariadb_variable/mariadb_variable.py +++ b/press/press/doctype/mariadb_variable/mariadb_variable.py @@ -5,6 +5,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.model.document import Document if TYPE_CHECKING: @@ -32,7 +33,7 @@ class MariaDBVariable(Document): def get_default_value(self): if not (value := self.default_value): - frappe.throw("Default Value is required") + frappe.throw(_("Default Value is required")) match self.datatype: case "Int": return int(value) diff --git a/press/press/doctype/marketplace_app/marketplace_app.py b/press/press/doctype/marketplace_app/marketplace_app.py index 31df7cf978f..64f5f8be1ca 100644 --- a/press/press/doctype/marketplace_app/marketplace_app.py +++ b/press/press/doctype/marketplace_app/marketplace_app.py @@ -117,10 +117,10 @@ def autoname(self): @dashboard_whitelist() def delete(self): if self.status != "Draft": - frappe.throw("You can only delete an app in Draft status") + frappe.throw(_("You can only delete an app in Draft status")) if get_current_team() != self.team: - frappe.throw("You are not authorized to delete this app") + frappe.throw(_("You are not authorized to delete this app")) super().delete() @@ -145,7 +145,7 @@ def cancel_approval_request(self, app_release: str): ) if len(approval_requests) == 0: - frappe.throw("No approval request exists for the given app release") + frappe.throw(_("No approval request exists for the given app release")) frappe.get_doc("App Release Approval Request", approval_requests[0]).cancel() @@ -180,7 +180,7 @@ def set_route(self): def check_if_duplicate(self): if frappe.db.exists("Marketplace App", self.name): - frappe.throw(f"App {self.name} already exists. Please contact support.") + frappe.throw(_("App {0} already exists. Please contact support.").format(self.name)) def create_app_and_source_if_needed(self): if frappe.db.exists("App", self.app or self.name): @@ -213,14 +213,16 @@ def validate(self): def validate_summary(self): if len(self.description) > 140: - frappe.throw("Marketplace App summary cannot be more than 140 characters.") + frappe.throw(_("Marketplace App summary cannot be more than 140 characters.")) def validate_sources(self): for source in self.sources: app_source = frappe.get_doc("App Source", source.source) if app_source.app != self.app: - frappe.throw(f"App Source {frappe.bold(source.source)} does not belong to this app!") + frappe.throw( + _("App Source {0} does not belong to this app!").format(frappe.bold(source.source)) + ) app_source_versions = [v.version for v in app_source.versions] if source.version not in app_source_versions: @@ -232,7 +234,9 @@ def validate_sources(self): def validate_number_of_screenshots(self): max_allowed_screenshots = frappe.db.get_single_value("Press Settings", "max_allowed_screenshots") if len(self.screenshots) > max_allowed_screenshots: - frappe.throw(f"You cannot add more than {max_allowed_screenshots} screenshots for an app.") + frappe.throw( + _("You cannot add more than {0} screenshots for an app.").format(max_allowed_screenshots) + ) def validate_has_approved_release_with_passing_audit(self): """ @@ -398,7 +402,7 @@ def add_version(self, version: str, branch: str): @dashboard_whitelist() def remove_version(self, version: str): if self.status == "Published" and len(self.sources) == 1: - frappe.throw("Failed to remove. Need at least 1 version for a published app") + frappe.throw(_("Failed to remove. Need at least 1 version for a published app")) for i, source in enumerate(self.sources): if source.version == version: @@ -781,7 +785,10 @@ def validate_frappe_version_for_branch( frappe_version = app_info.get("frappe_version") frappe_version = parse_frappe_version(frappe_version, app_info.get("title"), ease_versioning_constrains) if version not in frappe_version: - frappe.throw(f"{version} is not supported by branch {branch} for app {app_name}", VersioningError) + frappe.throw( + frappe._("{0} is not supported by branch {1} for app {2}").format(version, branch, app_name), + VersioningError, + ) def get_plans_for_app( diff --git a/press/press/doctype/monitor_server/monitor_server.py b/press/press/doctype/monitor_server/monitor_server.py index 6a87498cdcf..a0df4d4c8ab 100644 --- a/press/press/doctype/monitor_server/monitor_server.py +++ b/press/press/doctype/monitor_server/monitor_server.py @@ -8,6 +8,7 @@ import frappe import requests +from frappe import _ from frappe.utils.caching import redis_cache from frappe.utils.data import cint from requests.auth import HTTPBasicAuth @@ -253,7 +254,7 @@ def alerts(self): ret.raise_for_status() data = ret.json() if data["status"] != "success": - frappe.throw("Error fetching sites down") + frappe.throw(_("Error fetching sites down")) return data["data"]["groups"][0]["rules"] @property diff --git a/press/press/doctype/mpesa_payment_record/mpesa_payment_record.py b/press/press/doctype/mpesa_payment_record/mpesa_payment_record.py index f84b0e184bc..4296e9ce7e3 100644 --- a/press/press/doctype/mpesa_payment_record/mpesa_payment_record.py +++ b/press/press/doctype/mpesa_payment_record/mpesa_payment_record.py @@ -3,6 +3,7 @@ from __future__ import annotations import frappe +from frappe import _ from frappe.model.document import Document @@ -56,7 +57,9 @@ def validate_duplicate(self): "Mpesa Payment Record", {"transaction_id": self.transaction_id, "docstatus": 1}, ): - frappe.throw(f"Mpesa Payment Record for transaction {self.transaction_id} already exists") + frappe.throw( + _("Mpesa Payment Record for transaction {0} already exists").format(self.transaction_id) + ) def on_doctype_update(): diff --git a/press/press/doctype/mpesa_request_log/mpesa_request_log.py b/press/press/doctype/mpesa_request_log/mpesa_request_log.py index ad9601559cb..fa241a4f14e 100644 --- a/press/press/doctype/mpesa_request_log/mpesa_request_log.py +++ b/press/press/doctype/mpesa_request_log/mpesa_request_log.py @@ -3,6 +3,7 @@ from __future__ import annotations import frappe +from frappe import _ from frappe.model.document import Document @@ -42,4 +43,4 @@ def validate_duplicate_request_id(self): pluck="name", ) if request_logs: - frappe.throw(f"Request log already processed with this request id: {self.request_id}") + frappe.throw(_("Request log already processed with this request id: {0}").format(self.request_id)) diff --git a/press/press/doctype/nfs_volume_detachment/nfs_volume_detachment.py b/press/press/doctype/nfs_volume_detachment/nfs_volume_detachment.py index 4d23da05b34..ff3e5ad924c 100644 --- a/press/press/doctype/nfs_volume_detachment/nfs_volume_detachment.py +++ b/press/press/doctype/nfs_volume_detachment/nfs_volume_detachment.py @@ -5,6 +5,7 @@ import typing import frappe +from frappe import _ from frappe.model.document import Document from press.agent import Agent @@ -330,7 +331,7 @@ def before_insert(self): def validate(self): is_server_auto_scaled = frappe.db.get_value("Server", self.primary_server, "scaled_up") if is_server_auto_scaled: - frappe.throw("Benches are currently running on the secondary server!") + frappe.throw(_("Benches are currently running on the secondary server!")) has_triggers = frappe.db.get_value( "Prometheus Alert Rule", @@ -348,7 +349,7 @@ def validate(self): ) if has_triggers: - frappe.throw("Please remove all auto scale triggers before dropping the secondary server") + frappe.throw(_("Please remove all auto scale triggers before dropping the secondary server")) @frappe.whitelist() def force_continue(self): diff --git a/press/press/doctype/on_prem_failover/on_prem_failover.py b/press/press/doctype/on_prem_failover/on_prem_failover.py index 056370cc21e..a4950d53c1b 100644 --- a/press/press/doctype/on_prem_failover/on_prem_failover.py +++ b/press/press/doctype/on_prem_failover/on_prem_failover.py @@ -8,6 +8,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils import add_to_date @@ -398,7 +399,7 @@ def _setup_db_rsync_for_final_sync(self): play = ansible.run() if play.status != "Success": - frappe.throw("Failed to perform the final database sync.") + frappe.throw(_("Failed to perform the final database sync.")) def setup_and_configure_database_replica(self): frappe.enqueue_doc( @@ -421,7 +422,7 @@ def _setup_and_configure_database_replica(self): play = ansible.run() if play.status != "Success": - frappe.throw("Failed to setup replica on the on-premise server.") + frappe.throw(_("Failed to setup replica on the on-premise server.")) def setup_app_server_replica(self): frappe.enqueue_doc(self.doctype, self.name, "_setup_app_server_replica", timeout=3600, queue="long") @@ -438,7 +439,7 @@ def _setup_app_server_replica(self): play = ansible.run() if play.status != "Success": - frappe.throw("Failed to setup App Server replica synchronization on the on-premise server.") + frappe.throw(_("Failed to setup App Server replica synchronization on the on-premise server.")) def stop_replication_from_app_server(self): frappe.enqueue_doc( @@ -453,7 +454,7 @@ def _stop_replication_from_app_server(self): ) play = ansible.run() if play.status != "Success": - frappe.throw("Failed to stop replication on the App Server.") + frappe.throw(_("Failed to stop replication on the App Server.")) def stop_replication_from_db_server(self): frappe.enqueue_doc( @@ -468,7 +469,7 @@ def _stop_replication_from_db_server(self): ) play = ansible.run() if play.status != "Success": - frappe.throw("Failed to stop replication on the Database Server.") + frappe.throw(_("Failed to stop replication on the Database Server.")) # Internal methods diff --git a/press/press/doctype/payment_due_extension/payment_due_extension.py b/press/press/doctype/payment_due_extension/payment_due_extension.py index 88aa62e42be..f2029c4b0f6 100644 --- a/press/press/doctype/payment_due_extension/payment_due_extension.py +++ b/press/press/doctype/payment_due_extension/payment_due_extension.py @@ -3,6 +3,7 @@ from __future__ import annotations import frappe +from frappe import _ from frappe.model.document import Document @@ -23,18 +24,18 @@ class PaymentDueExtension(Document): def validate(self): if self.extension_date < frappe.utils.today(): - frappe.throw("Extension date cannot be in the past") + frappe.throw(_("Extension date cannot be in the past")) def before_insert(self): if frappe.db.exists( "Payment Due Extension", {"team": self.team, "docstatus": 1, "extension_date": (">=", frappe.utils.today())}, ): - frappe.throw("An active Payment due extension record already exists for this team") + frappe.throw(_("An active Payment due extension record already exists for this team")) def on_submit(self): frappe.db.set_value("Team", self.team, "extend_payment_due_suspension", 1) - + def on_cancel(self): frappe.db.set_value("Team", self.team, "extend_payment_due_suspension", 0) diff --git a/press/press/doctype/payout_order/payout_order.py b/press/press/doctype/payout_order/payout_order.py index 65d0f766f2f..b9062be1815 100644 --- a/press/press/doctype/payout_order/payout_order.py +++ b/press/press/doctype/payout_order/payout_order.py @@ -3,9 +3,9 @@ from datetime import date from itertools import groupby -from typing import List import frappe +from frappe import _ from frappe.model.document import Document from press.press.doctype.invoice_item.invoice_item import InvoiceItem @@ -21,6 +21,7 @@ class PayoutOrder(Document): if TYPE_CHECKING: from frappe.types import DF + from press.press.doctype.payout_order_item.payout_order_item import PayoutOrderItem amended_from: DF.Link | None @@ -57,7 +58,7 @@ class PayoutOrder(Document): @staticmethod def get_list_query(query): PayoutOrder = frappe.qb.DocType("Payout Order") - query = query.where((PayoutOrder.docstatus != 2)) + query = query.where(PayoutOrder.docstatus != 2) return query def validate(self): @@ -82,7 +83,7 @@ def validate_items(self): ) if invoice.status != "Paid": - frappe.throw(f"Invoice {invoice_name} is not paid yet.") + frappe.throw(_("Invoice {0} is not paid yet.").format(invoice_name)) invoice_item = get_invoice_item_for_po_item(invoice_name, row) @@ -150,14 +151,12 @@ def compute_total_amount(self): def before_submit(self): if self.mode_of_payment == "Cash" and (not self.frappe_purchase_order): frappe.throw( - "Frappe Purchase Order is required before marking this cash payout as Paid" + frappe._("Frappe Purchase Order is required before marking this cash payout as Paid") ) self.status = "Paid" -def get_invoice_item_for_po_item( - invoice_name: str, payout_order_item: PayoutOrderItem -) -> InvoiceItem | None: +def get_invoice_item_for_po_item(invoice_name: str, payout_order_item: PayoutOrderItem) -> InvoiceItem | None: try: if payout_order_item.invoice_item: item = frappe.get_doc("Invoice Item", payout_order_item.invoice_item) @@ -186,9 +185,7 @@ def get_invoice_item_for_po_item( def create_marketplace_payout_orders_monthly(period_start=None, period_end=None): period_start, period_end = ( - (period_start, period_end) - if period_start and period_end - else get_current_period_boundaries() + (period_start, period_end) if period_start and period_end else get_current_period_boundaries() ) items = get_unaccounted_marketplace_invoice_items() @@ -197,9 +194,7 @@ def create_marketplace_payout_orders_monthly(period_start=None, period_end=None) try: item_names = [i.name for i in items] - po_exists = frappe.db.exists( - "Payout Order", {"team": app_team, "period_end": period_end} - ) + po_exists = frappe.db.exists("Payout Order", {"team": app_team, "period_end": period_end}) if not po_exists: create_payout_order_from_invoice_item_names( @@ -266,9 +261,7 @@ def get_unaccounted_marketplace_invoice_items(): .where(invoice.status == "Paid") .where(invoice_item.document_type == "Marketplace App") .where(invoice_item.has_marketplace_payout_completed == 0) - .select( - invoice_item.name, invoice_item.document_name, marketplace_app.team.as_("app_team") - ) + .select(invoice_item.name, invoice_item.document_name, marketplace_app.team.as_("app_team")) .distinct() .run(as_dict=True) ) @@ -278,7 +271,7 @@ def get_unaccounted_marketplace_invoice_items(): @frappe.whitelist() def create_payout_order_from_invoice_items( - invoice_items: List[InvoiceItem], + invoice_items: list[InvoiceItem], team: str, period_start: date, period_end: date, diff --git a/press/press/doctype/physical_backup_restoration/physical_backup_restoration.py b/press/press/doctype/physical_backup_restoration/physical_backup_restoration.py index 59d66a981e4..04690c0094e 100644 --- a/press/press/doctype/physical_backup_restoration/physical_backup_restoration.py +++ b/press/press/doctype/physical_backup_restoration/physical_backup_restoration.py @@ -12,6 +12,7 @@ import frappe import frappe.utils +from frappe import _ from frappe.model.document import Document from press.agent import Agent @@ -160,33 +161,33 @@ def on_update(self): def validate_aws_only(self): server_provider = frappe.db.get_value("Database Server", self.destination_server, "provider") if server_provider != "AWS EC2": - frappe.throw("Only AWS hosted server is supported currently.") + frappe.throw(_("Only AWS hosted server is supported currently.")) def set_disk_snapshot(self): if not self.disk_snapshot: site_backup: SiteBackup = frappe.get_doc("Site Backup", self.site_backup) if not site_backup.physical: - frappe.throw("Provided site backup is not physical backup.") + frappe.throw(_("Provided site backup is not physical backup.")) if site_backup.status != "Success" or site_backup.files_availability != "Available": - frappe.throw("Provided site backup is not available.") + frappe.throw(_("Provided site backup is not available.")) if not site_backup.database_snapshot: - frappe.throw("Disk Snapshot is not available in site backup") + frappe.throw(_("Disk Snapshot is not available in site backup")) self.disk_snapshot = site_backup.database_snapshot if not self.disk_snapshot: - frappe.throw("Disk Snapshot is not available in site backup") + frappe.throw(_("Disk Snapshot is not available in site backup")) def validate_snapshot_region(self): snapshot_region = frappe.db.get_value("Virtual Disk Snapshot", self.disk_snapshot, "region") if snapshot_region != self.virtual_machine.region: - frappe.throw("Snapshot and server should be in same region.") + frappe.throw(_("Snapshot and server should be in same region.")) def validate_snapshot_status(self): snapshot_status = frappe.db.get_value("Virtual Disk Snapshot", self.disk_snapshot, "status") if snapshot_status not in ("Pending", "Completed"): - frappe.throw("Snapshot status should be Pending or Completed.") + frappe.throw(_("Snapshot status should be Pending or Completed.")) def cleanup_restorable_tables(self): if not self.restore_specific_tables: @@ -199,7 +200,7 @@ def cleanup_restorable_tables(self): # If restore_specific_tables is checked, raise error if tables_to_restore is empty if not tables_to_restore: - frappe.throw("You must provide at least one table to restore.") + frappe.throw(_("You must provide at least one table to restore.")) def set_mount_point(self): self.mount_point = f"/mnt/{self.name}" @@ -490,7 +491,7 @@ def unmount_volume_from_instance(self) -> StepStatus: def delete_mount_point(self) -> StepStatus: """Delete mount point""" if not self.mount_point or not self.mount_point.startswith("/mnt"): - frappe.throw("Mount point is not valid.") + frappe.throw(_("Mount point is not valid.")) # check if mount point was created if self.get_step_status(self.create_mount_point) != "Success": return StepStatus.Success @@ -713,7 +714,7 @@ def retry(self): if not step.is_cleanup_step: continue if step.status not in ["Success", "Skipped"]: - frappe.throw("Cleanup steps are not completed. Please clean up before retrying.") + frappe.throw(_("Cleanup steps are not completed. Please clean up before retrying.")) # Reset the states self.status = "Scheduled" self.start = frappe.utils.now_datetime() diff --git a/press/press/doctype/physical_backup_restoration_step/physical_backup_restoration_step.py b/press/press/doctype/physical_backup_restoration_step/physical_backup_restoration_step.py index a8c6860291c..f9b65bc05f5 100644 --- a/press/press/doctype/physical_backup_restoration_step/physical_backup_restoration_step.py +++ b/press/press/doctype/physical_backup_restoration_step/physical_backup_restoration_step.py @@ -4,6 +4,7 @@ from __future__ import annotations import frappe +from frappe import _ from frappe.model.document import Document @@ -34,4 +35,4 @@ class PhysicalBackupRestorationStep(Document): def validate(self): if self.is_async and self.wait_for_completion: - frappe.throw("Cannot wait for completion on async kind of step") + frappe.throw(_("Cannot wait for completion on async kind of step")) diff --git a/press/press/doctype/physical_restoration_test/physical_restoration_test.py b/press/press/doctype/physical_restoration_test/physical_restoration_test.py index a1a8797ba2a..0b7f3f984e5 100644 --- a/press/press/doctype/physical_restoration_test/physical_restoration_test.py +++ b/press/press/doctype/physical_restoration_test/physical_restoration_test.py @@ -6,6 +6,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.model.document import Document if TYPE_CHECKING: @@ -103,7 +104,7 @@ def start(self): else: self.completed = True self.save() - frappe.throw("No pending restoration found") + frappe.throw(_("No pending restoration found")) @frappe.whitelist() def sync(self): diff --git a/press/press/doctype/plan_change/plan_change.py b/press/press/doctype/plan_change/plan_change.py index 24f2e9661f8..b410aaa3c1d 100644 --- a/press/press/doctype/plan_change/plan_change.py +++ b/press/press/doctype/plan_change/plan_change.py @@ -55,7 +55,7 @@ def change_subscription_plan(self): document = frappe.get_doc(self.document_type, self.document_name) subscription = document.subscription if not subscription: - frappe.throw(f"No subscription for {self.document_type} {self.document_name}") + frappe.throw(_("No subscription for {0} {1}").format(self.document_type, self.document_name)) if self.from_plan and self.from_plan != subscription.plan: frappe.throw( diff --git a/press/press/doctype/press_role_permission/press_role_permission.py b/press/press/doctype/press_role_permission/press_role_permission.py index 6b2960aa05a..f87bce46bb2 100644 --- a/press/press/doctype/press_role_permission/press_role_permission.py +++ b/press/press/doctype/press_role_permission/press_role_permission.py @@ -3,6 +3,7 @@ from __future__ import annotations import frappe +from frappe import _ from frappe.model.document import Document from press.api.client import dashboard_whitelist @@ -32,7 +33,7 @@ def before_insert(self): and frappe.session.user != frappe.db.get_value("Team", self.team, "user") and not is_user_part_of_admin_role() ): - frappe.throw("Only the team owner or admin can create role permissions") + frappe.throw(_("Only the team owner or admin can create role permissions")) if frappe.db.exists( "Press Role Permission", @@ -44,7 +45,7 @@ def before_insert(self): "server": self.server, }, ): - frappe.throw("Role Permission already exists") + frappe.throw(_("Role Permission already exists")) @dashboard_whitelist() def delete(self): @@ -53,7 +54,7 @@ def delete(self): and frappe.session.user != frappe.get_cached_value("Team", self.team, "user") and not is_user_part_of_admin_role() ): - frappe.throw("Only the team owner or admin can delete this role permission") + frappe.throw(_("Only the team owner or admin can delete this role permission")) super().delete() diff --git a/press/press/doctype/press_settings/press_settings.py b/press/press/doctype/press_settings/press_settings.py index 4607b5cfb9d..549cfe95a76 100644 --- a/press/press/doctype/press_settings/press_settings.py +++ b/press/press/doctype/press_settings/press_settings.py @@ -5,6 +5,7 @@ import boto3 import frappe from boto3.session import Session +from frappe import _ from frappe.model.document import Document from frappe.utils import get_url, validate_email_address from twilio.rest import Client @@ -207,7 +208,7 @@ class PressSettings(Document): def validate(self): if self.max_concurrent_physical_restorations > 5: - frappe.throw("Max Concurrent Physical Restorations should be less than 5") + frappe.throw(_("Max Concurrent Physical Restorations should be less than 5")) if self.send_email_notifications: if self.email_recipients: @@ -215,12 +216,12 @@ def validate(self): email_list = [email.strip() for email in self.email_recipients.split(",")] for email in email_list: if not validate_email_address(email): - frappe.throw(f"Invalid email address: {email}") + frappe.throw(_("Invalid email address: {0}").format(email)) else: - frappe.throw("Email Recipients List can not be empty") + frappe.throw(_("Email Recipients List can not be empty")) if self.minimum_rebuild_memory < 2: - frappe.throw("Minimum rebuild memory needs to be 2 GB or more.") + frappe.throw(_("Minimum rebuild memory needs to be 2 GB or more.")) @frappe.whitelist() def create_stripe_webhook(self): diff --git a/press/press/doctype/press_webhook/press_webhook.py b/press/press/doctype/press_webhook/press_webhook.py index 3ea9c07944e..2e489a4d561 100644 --- a/press/press/doctype/press_webhook/press_webhook.py +++ b/press/press/doctype/press_webhook/press_webhook.py @@ -12,6 +12,7 @@ import frappe.query_builder import frappe.query_builder.functions import requests +from frappe import _ from frappe.model.document import Document from press.api.client import dashboard_whitelist @@ -47,13 +48,13 @@ class PressWebhook(Document): def validate(self): # maximum 5 webhooks per team if self.is_new() and frappe.db.count("Press Webhook", {"team": self.team}) > 5: - frappe.throw("You have reached the maximum number of webhooks per team") + frappe.throw(_("You have reached the maximum number of webhooks per team")) if self.has_value_changed("endpoint"): self.enabled = 0 # should have atleast one event selected if not self.events: - frappe.throw("At least one event should be selected") + frappe.throw(_("At least one event should be selected")) # validate endpoint url format self.validate_endpoint_url_format() # check for duplicate webhooks @@ -63,20 +64,20 @@ def validate(self): pluck="name", ) if len(webhooks) != 0: - frappe.throw("You have already added webhook for this endpoint") + frappe.throw(_("You have already added webhook for this endpoint")) def validate_endpoint_url_format(self): url = urlparse(self.endpoint) if not url.netloc: - frappe.throw("Endpoint should be a valid url") + frappe.throw(_("Endpoint should be a valid url")) # protocol should be http or https if url.scheme not in ["http", "https"]: - frappe.throw("Endpoint should start with http:// or https://") + frappe.throw(_("Endpoint should start with http:// or https://")) # dont allow query params if url.query: - frappe.throw("Endpoint should not have query params") + frappe.throw(_("Endpoint should not have query params")) isIPAddress = False # If endpoint target is ip address, it should be a public ip address @@ -84,16 +85,16 @@ def validate_endpoint_url_format(self): ip = ipaddress.ip_address(url.hostname) isIPAddress = True if not ip.is_global: - frappe.throw("Endpoint address should be a public ip or domain") + frappe.throw(_("Endpoint address should be a public ip or domain")) if not isIPAddress: # domain should be a fqdn if not is_valid_hostname(url.hostname): - frappe.throw("Endpoint address should be a valid domain") + frappe.throw(_("Endpoint address should be a valid domain")) # Endpoint can't be any local domain if not frappe.conf.developer_mode and ("localhost" in url.hostname or ".local" in url.hostname): - frappe.throw("Endpoint can't be localhost or local domain") + frappe.throw(_("Endpoint can't be localhost or local domain")) @dashboard_whitelist() def validate_endpoint(self) -> dict: diff --git a/press/press/doctype/process_snapshot/process_snapshot.py b/press/press/doctype/process_snapshot/process_snapshot.py index 651933b9fdc..064ce379ebe 100644 --- a/press/press/doctype/process_snapshot/process_snapshot.py +++ b/press/press/doctype/process_snapshot/process_snapshot.py @@ -8,6 +8,7 @@ import frappe import requests +from frappe import _ from frappe.model.document import Document if typing.TYPE_CHECKING: @@ -30,7 +31,7 @@ class ProcessSnapshot(Document): def check_bench_on_server(self): if not frappe.get_value("Bench", {"name": self.bench, "server": self.server}): - frappe.throw(f"{self.bench} does not exist on server {self.server}") + frappe.throw(_("{0} does not exist on server {1}").format(self.bench, self.server)) def validate(self): self.check_bench_on_server() diff --git a/press/press/doctype/prometheus_alert_rule/prometheus_alert_rule.py b/press/press/doctype/prometheus_alert_rule/prometheus_alert_rule.py index 2a38247d222..ee881b223d0 100644 --- a/press/press/doctype/prometheus_alert_rule/prometheus_alert_rule.py +++ b/press/press/doctype/prometheus_alert_rule/prometheus_alert_rule.py @@ -8,6 +8,7 @@ import frappe import yaml +from frappe import _ from frappe.core.utils import find from frappe.model.document import Document @@ -52,7 +53,7 @@ def validate(self): self.alert_preview = yaml.dump(self.get_rule()) self.route_preview = yaml.dump(self.get_route()) if self.enabled and not self.expression: - frappe.throw("Enabled alert rules require an expression") + frappe.throw(_("Enabled alert rules require an expression")) def get_rule(self): labels = json.loads(self.labels) diff --git a/press/press/doctype/proxy_failover/proxy_failover.py b/press/press/doctype/proxy_failover/proxy_failover.py index 9d786d04766..30bbf2e14d2 100644 --- a/press/press/doctype/proxy_failover/proxy_failover.py +++ b/press/press/doctype/proxy_failover/proxy_failover.py @@ -5,6 +5,7 @@ from itertools import groupby import frappe +from frappe import _ from frappe.model.document import Document from oci.core import VirtualNetworkClient from oci.core.models import ( @@ -48,7 +49,7 @@ def before_insert(self): ) if secondary.cluster != primary.cluster: - frappe.throw("Failover can only be initiated between Proxy Servers in the same cluster") + frappe.throw(_("Failover can only be initiated between Proxy Servers in the same cluster")) if (not primary.is_static_ip and not secondary.is_static_ip) or ( primary.is_static_ip and secondary.is_static_ip diff --git a/press/press/doctype/proxy_server/proxy_server.py b/press/press/doctype/proxy_server/proxy_server.py index 297b828a0d7..2927f901d8f 100644 --- a/press/press/doctype/proxy_server/proxy_server.py +++ b/press/press/doctype/proxy_server/proxy_server.py @@ -5,6 +5,7 @@ import json import frappe +from frappe import _ from frappe.utils import unique from press.press.doctype.server.server import BaseServer @@ -104,7 +105,7 @@ def validate_domains(self): if not frappe.db.exists( "TLS Certificate", {"wildcard": True, "status": "Active", "domain": domain} ): - # frappe.throw(f"Valid wildcard TLS Certificate not found for {domain}") + # frappe.throw(_("Valid wildcard TLS Certificate not found for {0}").format(domain)) ... def validate_proxysql_admin_password(self): @@ -179,7 +180,7 @@ def _install_exporters(self): @frappe.whitelist() def setup_ssh_proxy(self): if not self.ssh_certificate_authority: - frappe.throw("SSH Certificate Authority is required to setup SSH Proxy") + frappe.throw(_("SSH Certificate Authority is required to setup SSH Proxy")) frappe.enqueue_doc(self.doctype, self.name, "_setup_ssh_proxy", queue="long", timeout=1200) @@ -504,12 +505,12 @@ def pre_failover_tasks(self): primary = frappe.db.get_value("Proxy Server", self.primary, ["cluster", "is_static_ip"], as_dict=True) if self.cluster != primary.cluster: - frappe.throw("Failover can only be initiated between Proxy Servers in the same cluster") + frappe.throw(_("Failover can only be initiated between Proxy Servers in the same cluster")) if (not primary.is_static_ip and not self.is_static_ip) or ( primary.is_static_ip and self.is_static_ip ): - frappe.throw("Failover can only be initiated if one of the proxy server has a static ip") + frappe.throw(_("Failover can only be initiated if one of the proxy server has a static ip")) frappe.get_doc( { @@ -566,10 +567,12 @@ def set_memory_limits(self, limits: list): already_seen_processes = set() for limit in limits: if limit["process"] in already_seen_processes: - frappe.throw(f"Duplicate process {limit['process']} found in memory limits") + frappe.throw(_("Duplicate process {0} found in memory limits").format(limit["process"])) if int(limit["memory_high"]) > int(limit["memory_max"]): - frappe.throw(f"MemoryHigh cannot be more than MemoryMax for process {limit['process']}") + frappe.throw( + _("MemoryHigh cannot be more than MemoryMax for process {0}").format(limit["process"]) + ) for key in list(limit.keys()): if key not in ("process", "memory_high", "memory_max"): diff --git a/press/press/doctype/proxy_server/test_proxy_server.py b/press/press/doctype/proxy_server/test_proxy_server.py index 1dfa545c9d5..8109ba47d1b 100644 --- a/press/press/doctype/proxy_server/test_proxy_server.py +++ b/press/press/doctype/proxy_server/test_proxy_server.py @@ -5,6 +5,7 @@ from unittest.mock import Mock, patch import frappe +from frappe import _ from frappe.model.naming import make_autoname from frappe.tests.utils import FrappeTestCase @@ -37,7 +38,7 @@ def create_test_proxy_server( "status": "Active", "ip": frappe.mock("ipv4"), "private_ip": frappe.mock("ipv4_private"), - "hostname": make_autoname(hostname + ".######"), + "hostname": make_autoname(hostname + _(".######")), "cluster": cluster, "domain": domain, "domains": domains, diff --git a/press/press/doctype/registry_server/registry_server.py b/press/press/doctype/registry_server/registry_server.py index 9e71dca1979..b33b8d0decf 100644 --- a/press/press/doctype/registry_server/registry_server.py +++ b/press/press/doctype/registry_server/registry_server.py @@ -6,6 +6,7 @@ import os import frappe +from frappe import _ from frappe.frappeclient import FrappeClient from press.press.doctype.server.server import BaseServer @@ -208,7 +209,7 @@ def _rewrite_config(self): def rewrite_config(self): """Rewrite mirror's config""" if not self.is_mirror: - frappe.throw("Config can not be update for the hub registry") + frappe.throw(_("Config can not be update for the hub registry")) frappe.enqueue_doc(self.doctype, self.name, "_rewrite_config") diff --git a/press/press/doctype/release_group/release_group.py b/press/press/doctype/release_group/release_group.py index 063f5470cb4..5871c8484d5 100644 --- a/press/press/doctype/release_group/release_group.py +++ b/press/press/doctype/release_group/release_group.py @@ -378,7 +378,9 @@ def update_config(self, config): for key, value in config.items(): if key in get_client_blacklisted_keys(): - frappe.throw(_(f"The key {key} is blacklisted or is internal and cannot be updated")) + frappe.throw( + _("The key {0} is blacklisted or is internal and cannot be updated").format(key) + ) config_type = get_config_type(value) @@ -452,7 +454,9 @@ def update_environment_variable(self, environment_variables: dict): for env_var in self.environment_variables: if env_var.key == key: if env_var.internal: - frappe.throw(f"Environment variable {env_var.key} is internal and cannot be updated") + frappe.throw( + _(f"Environment variable {env_var.key} is internal and cannot be updated") + ) else: env_var.value = value is_updated = True @@ -487,14 +491,16 @@ def validate_title(self): def validate_frappe_app(self): if self.apps[0].app != "frappe": - frappe.throw("First app must be Frappe", frappe.ValidationError) + frappe.throw(_("First app must be Frappe"), frappe.ValidationError) def validate_duplicate_app(self): apps = set() for app in self.apps: app_name = app.app if app_name in apps: - frappe.throw(f"App {app.app} can be added only once", frappe.ValidationError) + frappe.throw( + frappe._("App {0} can be added only once").format(app.app), frappe.ValidationError + ) apps.add(app_name) def validate_app_versions(self): @@ -519,7 +525,7 @@ def validate_servers(self): if self.servers: servers = set(server.server for server in self.servers) if len(servers) != len(self.servers): - frappe.throw("Servers can be added only once", frappe.ValidationError) + frappe.throw(_("Servers can be added only once"), frappe.ValidationError) elif self.is_new(): server_for_new_bench = Server.get_prod_for_new_bench() if server_for_new_bench: @@ -570,7 +576,7 @@ def _validate_dependency_format(self, dependency: str, version: str): try: sv.Version(version) except ValueError as e: - frappe.throw(f"{dependency}: {e}") + frappe.throw(_("{0}: {1}").format(dependency, e)) def _validate_supported_wkhtmltopdf_version(self, version): if version not in SUPPORTED_WKHTMLTOPDF_VERSIONS: @@ -1025,12 +1031,12 @@ def send_change_team_request(self, team_mail_id: str, reason: str): ) if not frappe.db.exists("Team", {"user": team_mail_id, "enabled": 1}): - frappe.throw("No Active Team record found.") + frappe.throw(_("No Active Team record found.")) old_team = frappe.db.get_value("Team", self.team, "user") if old_team == team_mail_id: - frappe.throw(f"Bench is already owned by the team {team_mail_id}") + frappe.throw(_("Bench is already owned by the team {0}").format(team_mail_id)) key = frappe.generate_hash("Release Group Transfer Link", 20) frappe.get_doc( @@ -1430,7 +1436,7 @@ def change_app_branch(self, app: str, to_branch: str) -> None: # Already on that branch if current_app_source.branch == to_branch: - frappe.throw(f"App already on branch {to_branch}!") + frappe.throw(_("App already on branch {0}!").format(to_branch)) required_app_source = frappe.get_all( "App Source", @@ -1469,7 +1475,7 @@ def get_app_source(self, app: str) -> AppSource: if source: source = source[0] else: - frappe.throw("Release group app does not exist!") + frappe.throw(_("Release group app does not exist!")) return frappe.get_doc("App Source", source) @@ -1499,7 +1505,7 @@ def add_region(self, region): """ if len(self.get_clusters()) >= MAX_REGION_LIMIT: - frappe.throw(f"More than {MAX_REGION_LIMIT} for bench not allowed") + frappe.throw(_("More than {0} for bench not allowed").format(MAX_REGION_LIMIT)) self.add_cluster(region) def add_cluster(self, cluster: str): @@ -1510,7 +1516,7 @@ def add_cluster(self, cluster: str): if not server: log_error("No suitable server for new bench") - frappe.throw(f"No suitable server for new bench in {cluster}") + frappe.throw(_("No suitable server for new bench in {0}").format(cluster)) self.add_server(server, deploy=True) @@ -1556,7 +1562,7 @@ def deploy_on_server(self, server: str, force_new_build=False) -> str | None: ) # Checking for any platform build if not last_candidate_build: - frappe.throw("No build present for this release group", frappe.ValidationError) + frappe.throw(_("No build present for this release group"), frappe.ValidationError) return create_platform_build_and_deploy( deploy_candidate=last_candidate_build.candidate.name, # type: ignore @@ -1628,7 +1634,7 @@ def add_app(self, app, is_update: bool = False): path_parts = parsed_url.path.strip("/").split("/") if len(path_parts) < 2: - frappe.throw("Invalid repository URL for app!") + frappe.throw(_("Invalid repository URL for app!")) with suppress(frappe.ValidationError): validate_frappe_version_for_branch( @@ -1817,7 +1823,7 @@ def new_release_group(title, version, apps, team=None, cluster=None, saas_app="" ) if not servers: - frappe.throw("No servers found for new benches!") + frappe.throw(_("No servers found for new benches!")) else: server = servers[0] diff --git a/press/press/doctype/self_hosted_server/self_hosted_server.py b/press/press/doctype/self_hosted_server/self_hosted_server.py index 327cc87daa0..fd6f12978b1 100644 --- a/press/press/doctype/self_hosted_server/self_hosted_server.py +++ b/press/press/doctype/self_hosted_server/self_hosted_server.py @@ -6,6 +6,7 @@ import json import frappe +from frappe import _ from frappe.model.document import Document from frappe.model.naming import make_autoname @@ -341,7 +342,7 @@ def _create_server_plan(self, plan_name): def create_database_server(self): try: if not self.mariadb_ip: - frappe.throw("Public IP for MariaDB not found") + frappe.throw(_("Public IP for MariaDB not found")) db_server = frappe.new_doc( "Database Server", @@ -377,7 +378,7 @@ def create_database_server(self): frappe.msgprint(f"Database server record {db_server.name} created") except Exception: - frappe.throw("Adding Server to Database Server Doctype failed") + frappe.throw(_("Adding Server to Database Server Doctype failed")) self.status = "Broken" self.save() log_error("Inserting a new DB server failed") @@ -406,7 +407,7 @@ def append_site_configs(self, play_name): self.status = "Active" except Exception as e: self.status = "Broken" - frappe.throw("Fetching sites configs from Existing Bench failed", exc=e) + frappe.throw(_("Fetching sites configs from Existing Bench failed"), exc=e) self.save() @frappe.whitelist() @@ -451,7 +452,7 @@ def create_application_server(self): except Exception as e: self.status = "Broken" - frappe.throw("Server Creation Error", exc=e) + frappe.throw(_("Server Creation Error"), exc=e) self.save() @@ -480,7 +481,7 @@ def create_new_sites(self): "Bench", {"group": self.release_group, "server": self.name} ).name except Exception as e: - frappe.throw("Site Creation Failed", exc=e) + frappe.throw(_("Site Creation Failed"), exc=e) new_site.team = self.team new_site.server = self.name for app in _site.apps.split(","): @@ -577,7 +578,7 @@ def create_proxy_server(self): self.proxy_created = True except Exception as e: self.status = "Broken" - frappe.throw("Self Hosted Proxy Server Creation Error", exc=e) + frappe.throw(_("Self Hosted Proxy Server Creation Error"), exc=e) self.save() frappe.msgprint(f"Proxy server record {proxy_server.name} created") @@ -718,7 +719,9 @@ def validate_private_ip(self, play_id=None, server_type="app"): public_ip = self.mariadb_ip if private_ip not in all_ipv4_addresses: - frappe.throw(f"Private IP {private_ip} is not associated with server having IP {public_ip} ") + frappe.throw( + _("Private IP {0} is not associated with server having IP {1} ").format(private_ip, public_ip) + ) @frappe.whitelist() def fetch_private_ip(self, play_id=None, server_type="app"): @@ -788,7 +791,9 @@ def check_minimum_specs(self): """ if round(int(self.ram), -3) < 4000: # Round to nearest thousand - frappe.throw(f"Minimum RAM requirement not met, Minimum is 4GB and available is {self.ram} MB") + frappe.throw( + _("Minimum RAM requirement not met, Minimum is 4GB and available is {0} MB").format(self.ram) + ) if int(self.vcpus) < 2: frappe.throw( f"Minimum vCPU requirement not met, Minimum is 2 Cores and available is {self.vcpus}" diff --git a/press/press/doctype/self_hosted_server/test_self_hosted_server.py b/press/press/doctype/self_hosted_server/test_self_hosted_server.py index f9e378d9539..fb082fd7e45 100644 --- a/press/press/doctype/self_hosted_server/test_self_hosted_server.py +++ b/press/press/doctype/self_hosted_server/test_self_hosted_server.py @@ -313,8 +313,8 @@ def _create_test_ansible_play_and_task( "play": play.name, "role": play.playbook.split(".")[0], "task": kwargs.get("task_" + str(i + 1)), - "output": kwargs.get("task_" + str(i + 1) + "_output"), - "result": kwargs.get("task_" + str(i + 1) + "_result"), + "output": kwargs.get("task_" + str(i + 1) + _("_output")), + "result": kwargs.get("task_" + str(i + 1) + _("_result")), } ) task.insert() diff --git a/press/press/doctype/server/server.py b/press/press/doctype/server/server.py index e38e4e0edda..3d73bfa8fae 100644 --- a/press/press/doctype/server/server.py +++ b/press/press/doctype/server/server.py @@ -231,7 +231,7 @@ def get_communication_infos(self): @dashboard_whitelist() def update_communication_infos(self, values: list[dict]): if self.doctype != "Server": - frappe.throw("Setting up communication info is only allowed for App Server") + frappe.throw(_("Setting up communication info is only allowed for App Server")) return from press.press.doctype.communication_info.communication_info import ( @@ -246,7 +246,7 @@ def get_storage_usage(self): try: return self.agent.get("/server/storage-breakdown") except Exception: - frappe.throw("Failed to fetch storage usage. Try again later.") + frappe.throw(_("Failed to fetch storage usage. Try again later.")) @dashboard_whitelist() def increase_disk_size_for_server( @@ -600,7 +600,7 @@ def add_to_public_groups(self): @frappe.whitelist() def enable_for_new_benches_and_sites(self): if not self.public: - frappe.throw("Action only allowed for public servers") + frappe.throw(_("Action only allowed for public servers")) server = self.get_server_enabled_for_new_benches_and_sites() self.add_to_public_groups() @@ -659,7 +659,7 @@ def validate_cluster(self): if not self.cluster: self.cluster = frappe.db.get_value("Root Domain", self.domain, "default_cluster") if not self.cluster: - frappe.throw("Default Cluster not found", frappe.ValidationError) + frappe.throw(_("Default Cluster not found"), frappe.ValidationError) def validate_agent_password(self): # In case of unified servers the agent password is set during creation of the virtual machine @@ -941,7 +941,7 @@ def cleanup_unused_files(self, force: bool = False): "Agent Job", {"server": self.name, "job_type": "Cleanup Unused Files"} ) if cleanup_job.status in ["Running", "Pending"]: - frappe.throw("Cleanup job is already running") + frappe.throw(_("Cleanup job is already running")) self._cleanup_unused_files(force=force) @@ -1933,10 +1933,10 @@ def _parse_semantic_version(version_str: str) -> semantic_version.Version: @frappe.whitelist() def install_nat_iptables(self): if self.ip: - frappe.throw("NAT Iptables can only be installed on servers without public IP") + frappe.throw(_("NAT Iptables can only be installed on servers without public IP")) if not getattr(self, "nat_server", None): - frappe.throw("NAT Iptables requires a NAT server to be set") + frappe.throw(_("NAT Iptables requires a NAT server to be set")) frappe.enqueue_doc(self.doctype, self.name, "_install_nat_iptables") @@ -2348,7 +2348,7 @@ def get_primary_frappe_public_key(self): play = ansible.run() if play.status == "Success": return frappe.db.get_value(self.doctype, self.primary, "frappe_public_key") - frappe.throw(f"Failed to fetch {primary.name}'s Frappe public key") # nosemgrep + frappe.throw(_("Failed to fetch {0}'s Frappe public key").format(primary.name)) # nosemgrep return None def copy_files(self, source, destination, extra_options=None): @@ -2542,7 +2542,7 @@ def get_static_ip(self): if self.provider == "OCI": return self.get_oci_static_ip() - frappe.throw(f"Not implemented for {self.provider} provider") + frappe.throw(_("Not implemented for {0} provider").format(self.provider)) return None def get_aws_static_ip(self): @@ -2593,7 +2593,7 @@ def get_oci_static_ip(self): ).data if not vnic_attachments: - frappe.throw("No VNIC found for this OCI instance.") # nosemgrep + frappe.throw(_("No VNIC found for this OCI instance.")) # nosemgrep vnic_id = vnic_attachments[0].vnic_id @@ -2602,7 +2602,7 @@ def get_oci_static_ip(self): primary_private_ip = next((ip for ip in private_ips if ip.is_primary), None) if not primary_private_ip: - frappe.throw("Primary Private IP not found.") # nosemgrep + frappe.throw(_("Primary Private IP not found.")) # nosemgrep # 3. Check for existing Public IP and remove it if it exists existing_public_ip = network_client.get_public_ip_by_private_ip_id( @@ -3352,7 +3352,7 @@ def get_existing_on_prem_failover(self): @dashboard_whitelist() def generate_on_prem_failover_config(self): if not self.enable_on_prem_failover_support: - frappe.throw("On-Prem Failover support is not enabled for this server.") # nosemgrep + frappe.throw(_("On-Prem Failover support is not enabled for this server.")) # nosemgrep return None existsing_on_prem_failover = self.get_existing_on_prem_failover() @@ -3418,7 +3418,7 @@ def generate_on_prem_failover_config(self): def start_on_prem_server_replication(self): existsing_on_prem_failover = self.get_existing_on_prem_failover() if not existsing_on_prem_failover: - frappe.throw("On-Prem Failover is not configured for this server.") # nosemgrep + frappe.throw(_("On-Prem Failover is not configured for this server.")) # nosemgrep return current_user = frappe.session.user @@ -3434,7 +3434,7 @@ def start_on_prem_server_replication(self): def stop_on_prem_server_replication(self): existsing_on_prem_failover = self.get_existing_on_prem_failover() if not existsing_on_prem_failover: - frappe.throw("On-Prem Failover is not configured for this server.") # nosemgrep + frappe.throw(_("On-Prem Failover is not configured for this server.")) # nosemgrep return current_user = frappe.session.user @@ -3579,7 +3579,7 @@ def _install_earlyoom(self): def install_wazuh_agent(self): wazuh_server = frappe.get_value("Press Settings", "Press Settings", "wazuh_server") if not wazuh_server: - frappe.throw("Please configure Wazuh Server in Press Settings") + frappe.throw(_("Please configure Wazuh Server in Press Settings")) frappe.enqueue_doc( self.doctype, self.name, @@ -3654,21 +3654,21 @@ def _create_snapshot( def delete_snapshot(self, snapshot_name: str) -> None: doc = frappe.get_doc("Server Snapshot", snapshot_name) if doc.app_server != self.name: - frappe.throw("Snapshot does not belong to this server") # nosemgrep + frappe.throw(_("Snapshot does not belong to this server")) # nosemgrep doc.delete_snapshots() @dashboard_whitelist() def lock_snapshot(self, snapshot_name: str) -> None: doc = frappe.get_doc("Server Snapshot", snapshot_name) if doc.app_server != self.name: - frappe.throw("Snapshot does not belong to this server") # nosemgrep + frappe.throw(_("Snapshot does not belong to this server")) # nosemgrep doc.lock() @dashboard_whitelist() def unlock_snapshot(self, snapshot_name: str) -> None: doc = frappe.get_doc("Server Snapshot", snapshot_name) if doc.app_server != self.name: - frappe.throw("Snapshot does not belong to this server") # nosemgrep + frappe.throw(_("Snapshot does not belong to this server")) # nosemgrep doc.unlock() def validate_bench_status_before_scaling(self) -> bool: @@ -3690,7 +3690,7 @@ def validate_scale(self): - Check if there are active deployments on primary server """ if not self.can_scale: - frappe.throw("Server is not configured for auto scaling", frappe.ValidationError) + frappe.throw(_("Server is not configured for auto scaling"), frappe.ValidationError) if self.validate_bench_status_before_scaling(): frappe.throw( @@ -3712,7 +3712,7 @@ def validate_scale(self): ) if running_auto_scale: - frappe.throw("Auto scale is already running", frappe.ValidationError) # nosemgrep + frappe.throw(_("Auto scale is already running"), frappe.ValidationError) # nosemgrep if time_diff < timedelta(seconds=cool_off_period or 300): frappe.throw( @@ -3728,7 +3728,7 @@ def validate_scale(self): ) if not active_sites_on_primary and not active_sites_on_secondary: - frappe.throw("There are no active sites on this server!", frappe.ValidationError) + frappe.throw(_("There are no active sites on this server!"), frappe.ValidationError) active_deployments = frappe.db.get_value( "Bench", {"server": self.name, "status": ("in", ["Installing", "Pending"])} @@ -3796,7 +3796,7 @@ def add_automated_scaling_triggers( @frappe.whitelist() def scale_up(self, is_automatically_triggered: bool = False): if self.scaled_up: - frappe.throw("Server is already scaled up", frappe.ValidationError) + frappe.throw(_("Server is already scaled up"), frappe.ValidationError) self.validate_scale() @@ -3808,7 +3808,7 @@ def scale_up(self, is_automatically_triggered: bool = False): @frappe.whitelist() def scale_down(self, is_automatically_triggered: bool = False): if not self.scaled_up: - frappe.throw("Server is already scaled down", frappe.ValidationError) + frappe.throw(_("Server is already scaled down"), frappe.ValidationError) self.validate_scale() @@ -3858,7 +3858,7 @@ def get_next_plan(self, requires_cpu: bool = False, requires_memory: bool = Fals if not found we will relax the memory requirement to find a plan with higher CPU and higher memory. """ if not requires_cpu and not requires_memory: - frappe.throw("Specify CPU and/or memory requirements", frappe.ValidationError) + frappe.throw(_("Specify CPU and/or memory requirements"), frappe.ValidationError) current_plan: frappe._dict = frappe.db.get_value( "Server Plan", self.plan, ["vcpu", "memory", "enabled", "legacy_plan"], as_dict=True @@ -3972,7 +3972,7 @@ def get_hostname_abbreviation(hostname): def is_dedicated_server(server_name): if not isinstance(server_name, str): - frappe.throw("Invalid argument") + frappe.throw(_("Invalid argument")) is_public = frappe.db.get_value("Server", server_name, "public") return not is_public diff --git a/press/press/doctype/server_snapshot/server_snapshot.py b/press/press/doctype/server_snapshot/server_snapshot.py index a8419cb75e8..6d2423723c6 100644 --- a/press/press/doctype/server_snapshot/server_snapshot.py +++ b/press/press/doctype/server_snapshot/server_snapshot.py @@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Literal import frappe +from frappe import _ from frappe.model.document import Document from press.api.client import dashboard_whitelist @@ -173,7 +174,7 @@ def subscription(self) -> str | None: def validate(self): if self.provider != "AWS EC2": - frappe.throw("Only AWS Provider is supported for now") + frappe.throw(_("Only AWS Provider is supported for now")) def before_insert(self): # Ensure both the server and database server isn't archived @@ -402,7 +403,7 @@ def delete_snapshots(self): return if self.locked: - frappe.throw("Snapshot is locked. Unlock the snapshot before deleting.") + frappe.throw(_("Snapshot is locked. Unlock the snapshot before deleting.")) for s in self.snapshots: frappe.enqueue_doc( @@ -422,7 +423,7 @@ def lock(self, now: bool | None = False): return if self.free: - frappe.throw("Non-chargeable snapshots cannot be locked") + frappe.throw(_("Non-chargeable snapshots cannot be locked")) if now is None: now = False @@ -463,7 +464,7 @@ def recover_sites(self, sites: list[str] | None = None): sites = [] if not frappe.db.get_single_value("Press Settings", "enable_server_snapshot_recovery"): - frappe.throw("Server Snapshot Recovery is currently disabled. Please try again later.") + frappe.throw(_("Server Snapshot Recovery is currently disabled. Please try again later.")) recover_record = frappe.get_doc( { @@ -496,7 +497,7 @@ def create_server( # noqa: C901 press_job_arguments: dict[str, typing.Any] | None = None, ) -> str: if server_type not in ["Server", "Database Server"]: - frappe.throw("Invalid server type. Must be 'Server' or 'Database Server'.") + frappe.throw(_("Invalid server type. Must be 'Server' or 'Database Server'.")) if create_subscription is None: create_subscription = False @@ -511,13 +512,13 @@ def create_server( # noqa: C901 press_job_arguments = {} if server_type != "Database Server" and provision_db_replica: - frappe.throw("Provisioning a database replica is only applicable for Database Servers.") + frappe.throw(_("Provisioning a database replica is only applicable for Database Servers.")) if provision_db_replica and not master_db_server: - frappe.throw("Master Database Server is required for provisioning a database replica.") + frappe.throw(_("Master Database Server is required for provisioning a database replica.")) if temporary_server and provision_db_replica: - frappe.throw("Temporary server cannot be used for provisioning a database replica.") + frappe.throw(_("Temporary server cannot be used for provisioning a database replica.")) cluster: Cluster = frappe.get_doc("Cluster", self.cluster) if not plan: @@ -542,7 +543,7 @@ def create_server( # noqa: C901 if database_server: cluster.database_server = database_server - server, _ = cluster.create_server( + server, _result = cluster.create_server( doctype=server_type, title=title or self.name, team=team, @@ -579,14 +580,14 @@ def create_replica_db_server(self) -> str: use `create_server` method instead. """ if not self.database_server: - frappe.throw("Snapshot does not have a database server.") + frappe.throw(_("Snapshot does not have a database server.")) if self.status != "Completed": - frappe.throw("Please wait for the snapshot to be completed.") + frappe.throw(_("Please wait for the snapshot to be completed.")) database_server = frappe.get_doc("Database Server", self.database_server) if database_server.status != "Active": - frappe.throw("Master Database Server must be active to create a replica.") + frappe.throw(_("Master Database Server must be active to create a replica.")) return self.create_server( server_type="Database Server", @@ -608,7 +609,7 @@ def _create_subscription(self): plan = frappe.get_value("Server Snapshot Plan", {"provider": self.provider, "enabled": 1}, "name") if not plan: - frappe.throw(f"No active Server Snapshot Plan found for provider {self.provider}.") + frappe.throw(_("No active Server Snapshot Plan found for provider {0}.").format(self.provider)) if frappe.db.exists("Subscription", {"document_type": "Server Snapshot", "document_name": self.name}): return diff --git a/press/press/doctype/server_snapshot_recovery/server_snapshot_recovery.py b/press/press/doctype/server_snapshot_recovery/server_snapshot_recovery.py index e10873ed20f..b362008a7a3 100644 --- a/press/press/doctype/server_snapshot_recovery/server_snapshot_recovery.py +++ b/press/press/doctype/server_snapshot_recovery/server_snapshot_recovery.py @@ -5,6 +5,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils import add_to_date @@ -104,7 +105,9 @@ def validate_snapshot_status(self): self.snapshot, ) if snapshot.status != "Completed": - frappe.throw(f"Cannot recover from snapshot {snapshot.name} with status {snapshot.status}") + frappe.throw( + _("Cannot recover from snapshot {0} with status {1}").format(snapshot.name, snapshot.status) + ) def fill_site_list(self): sites_json = json.loads( @@ -128,10 +131,10 @@ def fill_site_list(self): else: for site in self.sites: if site.site not in sites_json: - frappe.throw(f"Site {site.site} not available in snapshot {self.snapshot}") + frappe.throw(_("Site {0} not available in snapshot {1}").format(site.site, self.snapshot)) if len(self.sites) == 0: - frappe.throw("Please choose at least one site to recover.") + frappe.throw(_("Please choose at least one site to recover.")) def on_update(self): if ( @@ -204,7 +207,7 @@ def provision_servers(self): @frappe.whitelist() def archive_servers(self): if not self.app_server or not self.database_server: - frappe.throw("Servers are not provisioned yet.") + frappe.throw(_("Servers are not provisioned yet.")) app_server_doc = frappe.get_doc("Server", self.app_server) if app_server_doc.status != "Archived": @@ -296,7 +299,7 @@ def _process_backup_files_from_snapshot_job_callback(self, job: AgentJob): # no break if not site_record: - frappe.throw(f"Site {site} not found in recovery sites.") + frappe.throw(_("Site {0} not found in recovery sites.").format(site)) if job.status == "Failure": site_record.status = "Failure" @@ -331,7 +334,7 @@ def _process_backup_database_from_snapshot_job_callback(self, job: AgentJob): site_record = s break if not site_record: - frappe.throw(f"Site {site} not found in recovery sites.") + frappe.throw(_("Site {0} not found in recovery sites.").format(site)) if job.status == "Failure": site_record.status = "Failure" @@ -381,7 +384,7 @@ def download_backup(self, site: str, file_type: str): # noqa: C901 break if not site_record: - frappe.throw(f"Site {site} not found in recovery sites.") + frappe.throw(_("Site {0} not found in recovery sites.").format(site)) if ( (file_type == "public" and not site_record.public_remote_file) @@ -389,7 +392,7 @@ def download_backup(self, site: str, file_type: str): # noqa: C901 or (file_type == "database" and not site_record.database_remote_file) or (file_type == "encryption_key" and not site_record.encryption_key) ): - frappe.throw(f"{file_type.capitalize()} backup not available for site {site}.") + frappe.throw(_("{0} backup not available for site {1}.").format(file_type.capitalize(), site)) try: remote_file_name = "" @@ -404,7 +407,11 @@ def download_backup(self, site: str, file_type: str): # noqa: C901 return frappe.get_doc("Remote File", remote_file_name).download_link except Exception: - frappe.throw(f"Error downloading {file_type} backup for site {site}. Please try again later.") + frappe.throw( + _("Error downloading {0} backup for site {1}. Please try again later.").format( + file_type, site + ) + ) @frappe.whitelist() def expire_backups(self): diff --git a/press/press/doctype/server_storage_plan/server_storage_plan.py b/press/press/doctype/server_storage_plan/server_storage_plan.py index 5d30100f122..46efb962f95 100644 --- a/press/press/doctype/server_storage_plan/server_storage_plan.py +++ b/press/press/doctype/server_storage_plan/server_storage_plan.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe import _ from press.press.doctype.site_plan.plan import Plan @@ -25,4 +26,4 @@ def validate(self): if self.enabled and frappe.db.exists( "Server Storage Plan", {"enabled": 1, "name": ("!=", self.name)} ): - frappe.throw("Only one storage add-on plan can be enabled at a time") + frappe.throw(_("Only one storage add-on plan can be enabled at a time")) diff --git a/press/press/doctype/silenced_alert/silenced_alert.py b/press/press/doctype/silenced_alert/silenced_alert.py index 3a7559b137c..be83f395751 100644 --- a/press/press/doctype/silenced_alert/silenced_alert.py +++ b/press/press/doctype/silenced_alert/silenced_alert.py @@ -7,6 +7,7 @@ import frappe import requests +from frappe import _ from frappe.model.document import Document from frappe.utils.data import format_duration, get_datetime @@ -64,10 +65,10 @@ def preview_alerts(self): "Monitor Server", "monitor.athul.fc.frappe.dev" ) # frappe.db.get_single_value("Press Settings","monitor_server")) auth_token = base64.b64encode( - f"frappe:{monitor_server.get_password('grafana_password')}".encode("utf-8") + f"frappe:{monitor_server.get_password('grafana_password')}".encode() ).decode("utf-8") # keyword = f'{self.get_keyword_based_on_instance_type()}%3D%22{self.instance.replace(" ","%20")}%22' - keyword = f'{self.get_keyword_based_on_instance_type()}="{"erpdb.innoterra.co.in" or self.instance}"' + keyword = f'{self.get_keyword_based_on_instance_type()}="{self.instance or "erpdb.innoterra.co.in"}"' print(keyword) res = requests.get( f"https://monitor.frappe.cloud/alertmanager/api/v2/alerts/groups?filter={keyword}&silenced=false&active=true", @@ -79,7 +80,7 @@ def preview_alerts(self): self.alert_previews = json.dumps(alerts, indent=2) self.save() else: - frappe.throw("Unable to fetch alerts from Alertmanager") + frappe.throw(_("Unable to fetch alerts from Alertmanager")) @frappe.whitelist() def create_new_silence(self): @@ -87,7 +88,7 @@ def create_new_silence(self): "Monitor Server", "monitor.athul.fc.frappe.dev" ) # frappe.db.get_single_value("Press Settings","monitor_server")) auth_token = base64.b64encode( - f"frappe:{monitor_server.get_password('grafana_password')}".encode("utf-8") + f"frappe:{monitor_server.get_password('grafana_password')}".encode() ).decode("utf-8") data = { "matchers": [ @@ -115,7 +116,7 @@ def create_new_silence(self): self.silence_id = alerts["silenceID"] self.save() else: - frappe.throw("Unable to fetch alerts from Alertmanager") + frappe.throw(_("Unable to fetch alerts from Alertmanager")) def check_silenced_alerts(): @@ -123,14 +124,12 @@ def check_silenced_alerts(): Checks for silenced alerts in Alertmanager and updates the status of the silenced alert in Press Runs every hour """ - silences = frappe.get_all( - "Silenced Alert", fields=["silence_id"], filters={"status": "Active"} - ) + silences = frappe.get_all("Silenced Alert", fields=["silence_id"], filters={"status": "Active"}) monitor_server = frappe.get_doc( "Monitor Server", "monitor.athul.fc.frappe.dev" ) # frappe.db.get_single_value("Press Settings","monitor_server")) auth_token = base64.b64encode( - f"frappe:{monitor_server.get_password('grafana_password')}".encode("utf-8") + f"frappe:{monitor_server.get_password('grafana_password')}".encode() ).decode("utf-8") req = requests.get( "https://monitor.frappe.cloud/alertmanager/api/v2/silences?silenced=false&inhibited=false&active=true", @@ -140,10 +139,8 @@ def check_silenced_alerts(): silences_from_alertmanager = req.json() s_ids = [x["silence_id"] for x in silences] for silence in silences_from_alertmanager: - if not silence["status"]["state"] == "active" and silence["id"] in s_ids: - frappe.db.set_value( - "Silenced Alert", {"silence_id": silence["id"]}, "status", "Expired" - ) + if silence["status"]["state"] != "active" and silence["id"] in s_ids: + frappe.db.set_value("Silenced Alert", {"silence_id": silence["id"]}, "status", "Expired") frappe.db.commit() else: log_error("Failed to fetch silences from Alertmanager") diff --git a/press/press/doctype/site/site.py b/press/press/doctype/site/site.py index 04a592b17d0..343ffe522fe 100644 --- a/press/press/doctype/site/site.py +++ b/press/press/doctype/site/site.py @@ -513,11 +513,13 @@ def validate_installed_apps(self): ) if self.apps[0].app != "frappe": - frappe.throw("First app to be installed on site must be frappe.") # nosemgrep + frappe.throw(_("First app to be installed on site must be frappe.")) # nosemgrep site_apps = [app.app for app in self.apps] if len(site_apps) != len(set(site_apps)): - frappe.throw("App {app.app} is already on installed on the bench. Cannot add the same app twice") + frappe.throw( + _("App {app.app} is already on installed on the bench. Cannot add the same app twice") + ) # Install apps in the same order as bench if self.is_new(): @@ -553,7 +555,7 @@ def validate_site_config(self): def validate_auto_update_fields(self): # Validate day of month if not (1 <= self.update_on_day_of_month <= 31): - frappe.throw("Day of the month must be between 1 and 31 (included)!") # nosemgrep + frappe.throw(_("Day of the month must be between 1 and 31 (included)!")) # nosemgrep # If site is on public bench, don't allow to disable auto updates if self.skip_auto_updates and self.is_group_public: frappe.throw( @@ -618,7 +620,7 @@ def validate_site_plan(self): # noqa: C901 plan.dedicated_server_plan or plan.is_trial_plan ) if is_plan_free: - frappe.throw("You can't select a free plan!") # nosemgrep + frappe.throw(_("You can't select a free plan!")) # nosemgrep # If site is on public server, don't allow unlimited plans if is_site_on_public_server and plan.dedicated_server_plan: @@ -742,14 +744,16 @@ def retry_rename(self): if self.name != self._get_site_name(self.subdomain): self.rename(self._get_site_name(self.subdomain)) else: - frappe.throw("Please choose a different subdomain") # nosemgrep + frappe.throw(_("Please choose a different subdomain")) # nosemgrep @frappe.whitelist() def retry_archive(self): """Retry archive with subdomain+domain name of site""" site_name = self.subdomain + "." + self.domain if frappe.db.exists("Site", {"name": site_name, "bench": self.bench}): - frappe.throw(f"Another site already exists in {self.bench} with name: {site_name}.") # nosemgrep + frappe.throw( + _(f"Another site already exists in {self.bench} with name: {site_name}.") + ) # nosemgrep self.archive(site_name=site_name, reason="Retry Archive") def check_duplicate_site(self): @@ -1243,7 +1247,7 @@ def backup( ) > 3 ): - frappe.throw("You cannot take more than 3 backups after site suspension") # nosemgrep + frappe.throw(_("You cannot take more than 3 backups after site suspension")) # nosemgrep return frappe.get_doc( { @@ -1263,7 +1267,7 @@ def get_backup_download_link(self, backup, file): from botocore.exceptions import ClientError if file not in ["database", "public", "private", "config"]: - frappe.throw("Invalid file type") # nosemgrep + frappe.throw(_("Invalid file type")) # nosemgrep try: remote_file = frappe.db.get_value( @@ -1287,9 +1291,9 @@ def site_update_scheduled(self): def check_move_scheduled(self): if time := self.site_migration_scheduled(): - frappe.throw(f"Site Migration is scheduled for {self.name} at {time}") # nosemgrep + frappe.throw(_("Site Migration is scheduled for {0} at {1}").format(self.name, time)) # nosemgrep if time := self.site_update_scheduled(): - frappe.throw(f"Site Update is scheduled for {self.name} at {time}") # nosemgrep + frappe.throw(_("Site Update is scheduled for {0} at {1}").format(self.name, time)) # nosemgrep def ready_for_move(self): if self.status in TRANSITORY_STATES: @@ -1298,7 +1302,7 @@ def ready_for_move(self): SiteUnderMaintenance, ) elif self.status == "Archived": - frappe.throw("The site has already been archived. Cannot move this site.", SiteAlreadyArchived) + frappe.throw(_("The site has already been archived. Cannot move this site."), SiteAlreadyArchived) self.check_move_scheduled() self.status_before_update = self.status @@ -1363,7 +1367,9 @@ def cancel_scheduled_update(self, site_update: str): ) except (frappe.QueryTimeoutError, frappe.QueryDeadlockError): - frappe.throw("The update is probably underway. Please reload/refresh to get the latest status.") + frappe.throw( + _("The update is probably underway. Please reload/refresh to get the latest status.") + ) # used document api for applying doc permissions doc = frappe.get_doc("Site Update", site_update) @@ -1393,7 +1399,9 @@ def create_migration_plan( # noqa: C901 ) if scheduled_time and scheduled_time < get_datetime(): - frappe.throw("Scheduled time must be in the future. Please provide a valid scheduled time.") + frappe.throw( + _("Scheduled time must be in the future. Please provide a valid scheduled time.") + ) doc = None if type == "Move Site To Different Server / Bench": @@ -1497,7 +1505,7 @@ def change_region( ) if bench_vals is None: - frappe.throw(f"Bench {group} does not have an existing deploy in {cluster}") + frappe.throw(_("Bench {0} does not have an existing deploy in {1}").format(group, cluster)) bench, server = bench_vals @@ -1634,7 +1642,7 @@ def remove_domain_from_config(self, domain): @site_action(["Active"]) def remove_domain(self, domain): if domain == self.name: - frappe.throw("Cannot delete default site_domain") # nosemgrep + frappe.throw(_("Cannot delete default site_domain")) # nosemgrep site_domain = frappe.get_all("Site Domain", filters={"site": self.name, "domain": domain})[0] frappe.delete_doc("Site Domain", site_domain.name) @@ -1831,12 +1839,12 @@ def send_change_team_request(self, team_mail_id: str, reason: str): ) if not frappe.db.exists("Team", {"user": team_mail_id, "enabled": 1}): - frappe.throw("No Active Team record found.") # nosemgrep + frappe.throw(_("No Active Team record found.")) # nosemgrep old_team = frappe.db.get_value("Team", self.team, "user") if old_team == team_mail_id: - frappe.throw(f"Site is already owned by the team {team_mail_id}") # nosemgrep + frappe.throw(_("Site is already owned by the team {0}").format(team_mail_id)) # nosemgrep key = frappe.generate_hash("Site Transfer Link", 20) frappe.get_doc( @@ -1891,7 +1899,7 @@ def login_as_team(self, reason=None): redirect_route = "/app" return f"https://{self.host_name or self.name}{redirect_route}?sid={sid}" - frappe.throw("No additional system user created for this site.") # nosemgrep + frappe.throw(_("No additional system user created for this site.")) # nosemgrep return None @site_action(["Active"]) @@ -1944,7 +1952,9 @@ def get_sid_from_agent(self, user: str) -> str | None: frappe.ValidationError, ) elif f"User {user} does not exist" in str(e): - frappe.throw(f"User {user} does not exist in the site", frappe.ValidationError) # nosemgrep + frappe.throw( + frappe._("User {0} does not exist in the site").format(user), frappe.ValidationError + ) # nosemgrep elif "certificate has expired" in str(e): frappe.throw( "SSL certificate for the {self.name} has expired. Please reach out to us at support.frappe.io if it is not automatically generated in a few minutes.", @@ -1988,7 +1998,7 @@ def get_login_sid(self, user: str = "Administrator"): if not sid or sid == "Guest": sid = self.get_sid_from_agent(user) if not sid or sid == "Guest": - frappe.throw(f"Could not login as {user}", frappe.ValidationError) # nosemgrep + frappe.throw(_("Could not login as {0}").format(user), frappe.ValidationError) # nosemgrep return sid def fetch_info(self): @@ -2503,7 +2513,7 @@ def disable_monitoring(self, reason=None): @dashboard_whitelist() def enable_monitoring(self): # noqa: C901 if not self.is_monitoring_disabled: - frappe.throw("Monitoring is already enabled") # nosemgrep + frappe.throw(_("Monitoring is already enabled")) # nosemgrep if self.status != "Active": frappe.throw( @@ -2885,7 +2895,7 @@ def get_plan_name(self, plan=None): if not plan: plan = self.subscription_plan if hasattr(self, "subscription_plan") else self.plan if plan and not isinstance(plan, str): - frappe.throw("Site.subscription_plan must be a string") # nosemgrep + frappe.throw(_("Site.subscription_plan must be a string")) # nosemgrep return plan def get_plan_config(self, plan=None): @@ -2953,10 +2963,10 @@ def set_bench_for_server(self): server_details = frappe.db.get_value("Server", self.server, ["public", "team"], as_dict=True) if not server_details: - frappe.throw(f"Server {self.server} not found") # nosemgrep + frappe.throw(_("Server {0} not found").format(self.server)) # nosemgrep if server_details.team != get_current_team(): - frappe.throw("You don't have permission to deploy on this server") # nosemgrep + frappe.throw(_("You don't have permission to deploy on this server")) # nosemgrep bench = frappe.db.get_value( "Bench", @@ -2972,11 +2982,13 @@ def set_bench_for_server(self): self.bench = bench.name if self.cluster != bench.cluster: - frappe.throw(f"Site cannot be deployed on {self.cluster} yet. Please contact support.") + frappe.throw( + _("Site cannot be deployed on {0} yet. Please contact support.").format(self.cluster) + ) def set_latest_bench(self): if not (self.domain and self.cluster and self.group): - frappe.throw("Domain, cluster and group are mandatory to create a site.") # nosemgrep + frappe.throw(_("Domain, cluster and group are mandatory to create a site.")) # nosemgrep proxy_servers_names = frappe.db.get_all( "Proxy Server Domain", {"domain": self.domain}, pluck="parent" @@ -3027,7 +3039,9 @@ def set_latest_bench(self): if release_group_names: self.group = benches[0].group if self.cluster != benches[0].cluster: - frappe.throw(f"Site cannot be deployed on {self.cluster} yet. Please contact support.") + frappe.throw( + _("Site cannot be deployed on {0} yet. Please contact support.").format(self.cluster) + ) def _create_initial_site_plan_change(self, plan): frappe.get_doc( @@ -3051,7 +3065,9 @@ def check_db_access_enabling(self): }, for_update=True, ): - frappe.throw("Database Access is already being enabled on this site. Please check after a while.") + frappe.throw( + _("Database Access is already being enabled on this site. Please check after a while.") + ) def get_auto_update_info(self): fields = [ @@ -3889,7 +3905,7 @@ def fetch_database_name(self): if not self.database_name: synced = self._sync_config_info() if not synced: - frappe.throw("Unable to fetch database name. Please try again.") # nosemgrep + frappe.throw(_("Unable to fetch database name. Please try again.")) # nosemgrep self.save() return self.database_name @@ -3948,7 +3964,7 @@ def fetch_binlog_timeline( # noqa: C901 ) if start >= end: - frappe.throw("Invalid time range. Start time must be less than end time.") + frappe.throw(_("Invalid time range. Start time must be less than end time.")) data = self.database_server_agent.get_binlogs_timeline( start=start, @@ -4024,13 +4040,15 @@ def search_binlogs( event_size: int | None = None, ): if (not self.is_binlog_indexing_enabled()) or (self.is_binlog_indexer_running()): - frappe.throw("Binlog indexing service is not enabled or in maintenance. Please try again later") + frappe.throw( + _("Binlog indexing service is not enabled or in maintenance. Please try again later") + ) if start >= end: - frappe.throw("Invalid time range. Start time must be less than end time.") + frappe.throw(_("Invalid time range. Start time must be less than end time.")) if (end - start) > 60 * 60 * 6: - frappe.throw("Binlog search is limited to 6 hours. Please select a smaller time range.") + frappe.throw(_("Binlog search is limited to 6 hours. Please select a smaller time range.")) if not table: table = None @@ -4053,7 +4071,7 @@ def fetch_queries_from_binlog(self, row_ids: dict[str, list[int]]): # Don't allow to fetch more than 100 rows at a time total_row_ids = sum(len(v) for v in row_ids.values()) if total_row_ids > 100: - frappe.throw("Cannot fetch more than 100 rows at a time from binlog.") # nosemgrep + frappe.throw(_("Cannot fetch more than 100 rows at a time from binlog.")) # nosemgrep return self.database_server_agent.get_binlog_queries( row_ids=row_ids, database=self.fetch_database_name() diff --git a/press/press/doctype/site_action/site_action.py b/press/press/doctype/site_action/site_action.py index 6883601f4cd..ce86d6ea7a9 100644 --- a/press/press/doctype/site_action/site_action.py +++ b/press/press/doctype/site_action/site_action.py @@ -10,6 +10,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils import add_to_date, now_datetime from rq.timeouts import JobTimeoutException @@ -106,7 +107,7 @@ def pre_validate_move_site_to_different_server(self): server: Server = frappe.get_doc("Server", destination_server) if not server.public and not server.has_permission("write"): - frappe.throw(f"You don't have permission to deploy on server {server.name}") + frappe.throw(_("You don't have permission to deploy on server {0}").format(server.name)) if self.get_argument("destination_release_group"): # Existing bench chosen - validate the release group @@ -118,7 +119,7 @@ def pre_validate_move_site_to_different_server(self): elif not self.get_argument("new_release_group_name"): # No destination group and no new name provided - auto-generate if current_release_group.public: - self.set_argument("new_release_group_name", current_release_group.title + " - Clone") + self.set_argument("new_release_group_name", current_release_group.title + _(" - Clone")) else: # Private group - add the destination server to the current group if needed if not any(s.server == destination_server for s in current_release_group.servers): @@ -380,7 +381,7 @@ def pre_validate_move_site_to_different_cluster(self): target_cluster = self.get_argument("cluster") current_cluster = frappe.db.get_value("Server", self.site_doc.server, "cluster") if target_cluster == current_cluster: - frappe.throw("Target cluster must be different from current cluster.") + frappe.throw(_("Target cluster must be different from current cluster.")) # create the `Site Migration` current_group = frappe.db.get_value("Site", self.site, "group") @@ -391,7 +392,9 @@ def pre_validate_move_site_to_different_cluster(self): ) if bench_vals is None: - frappe.throw(f"Bench {current_group} does not have an existing deploy in {target_cluster}") + frappe.throw( + _("Bench {0} does not have an existing deploy in {1}").format(current_group, target_cluster) + ) bench, server = bench_vals @@ -534,7 +537,7 @@ def after_insert(self): def validate(self): if self.action_type == "Move From Private To Shared Bench": - frappe.throw("Move From Private To Shared Bench action is not available currently.") + frappe.throw(_("Move From Private To Shared Bench action is not available currently.")) def on_update(self): save_doc = False @@ -620,7 +623,7 @@ def start_now(self): @dashboard_whitelist() def cancel_action(self): if self.status != "Scheduled": - frappe.throw("Only Scheduled actions can be cancelled.") + frappe.throw(_("Only Scheduled actions can be cancelled.")) return self.status = "Cancelled" diff --git a/press/press/doctype/site_action_step/site_action_step.py b/press/press/doctype/site_action_step/site_action_step.py index 869b7a4afab..63fc5a982aa 100644 --- a/press/press/doctype/site_action_step/site_action_step.py +++ b/press/press/doctype/site_action_step/site_action_step.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe import _ from frappe.model.document import Document @@ -33,7 +34,7 @@ class SiteActionStep(Document): def validate(self): if self.is_async_step and self.wait_for_completion: - frappe.throw("Cannot wait for completion on async kind of step") + frappe.throw(_("Cannot wait for completion on async kind of step")) def get_steps(self): if self.reference_doctype and self.reference_name: diff --git a/press/press/doctype/site_backup/site_backup.py b/press/press/doctype/site_backup/site_backup.py index 13b72b01894..83b8073085c 100644 --- a/press/press/doctype/site_backup/site_backup.py +++ b/press/press/doctype/site_backup/site_backup.py @@ -10,6 +10,7 @@ import frappe import frappe.utils +from frappe import _ from frappe.desk.doctype.tag.tag import add_tag from frappe.model.document import Document from frappe.query_builder.terms import ValueWrapper @@ -149,12 +150,12 @@ def get_list_query(query, filters=None, **list_args): def validate(self): if self.physical and self.with_files: - frappe.throw("Physical backups cannot be taken with files") + frappe.throw(_("Physical backups cannot be taken with files")) if self.physical and self.offsite: - frappe.throw("Physical and offsite logical backups cannot be taken together") + frappe.throw(_("Physical and offsite logical backups cannot be taken together")) if self.deactivate_site_during_backup and not self.physical: - frappe.throw("Site deactivation should be used for physical backups only") + frappe.throw(_("Site deactivation should be used for physical backups only")) def before_insert(self): if self.flags.get("skip_backup_after_insert"): @@ -162,7 +163,7 @@ def before_insert(self): if getattr(self, "force", False): if self.physical: - frappe.throw("Physical backups cannot be forcefully triggered") + frappe.throw(_("Physical backups cannot be forcefully triggered")) return # For backups, check if there are too many pending backups @@ -175,7 +176,7 @@ def before_insert(self): "creation": (">", two_hours_ago), }, ): - frappe.throw("Too many pending backups", SiteTooManyPendingBackups) + frappe.throw(_("Too many pending backups"), SiteTooManyPendingBackups) self.validate_and_setup_physical_backup() @@ -210,7 +211,7 @@ def validate_and_setup_physical_backup(self): site.sync_info() site.reload() if not site.database_name: - frappe.throw("Database name is missing in the site") + frappe.throw(_("Database name is missing in the site")) self.database_name = site.database_name self.snapshot_request_key = frappe.generate_hash(length=32) @@ -375,7 +376,7 @@ def create_database_snapshot(self): virtual_machine.create_snapshots(exclude_boot_volume=True, physical_backup=True) if len(virtual_machine.flags.created_snapshots) == 0: - frappe.throw("Failed to create a snapshot for the database server") + frappe.throw(_("Failed to create a snapshot for the database server")) frappe.db.set_value( "Site Backup", self.name, "database_snapshot", virtual_machine.flags.created_snapshots[0] ) diff --git a/press/press/doctype/site_database_user/site_database_user.py b/press/press/doctype/site_database_user/site_database_user.py index 2ce30d9c2da..0fb5c4aec6e 100644 --- a/press/press/doctype/site_database_user/site_database_user.py +++ b/press/press/doctype/site_database_user/site_database_user.py @@ -9,6 +9,7 @@ import frappe import frappe.utils from elasticsearch import Elasticsearch +from frappe import _ from frappe.model.document import Document from frappe.utils.password import get_decrypted_password @@ -72,7 +73,7 @@ def validate(self): self.permissions.clear() if not self.is_new() and self.has_value_changed("max_connections"): - frappe.throw("You can't update the max database connections. Archive it and create a new one.") + frappe.throw(_("You can't update the max database connections. Archive it and create a new one.")) if not self.max_connections: frappe.throw( @@ -82,9 +83,9 @@ def validate(self): def before_insert(self): site: Site = frappe.get_doc("Site", self.site) if not site.has_permission(): - frappe.throw("You don't have permission to create database user") + frappe.throw(_("You don't have permission to create database user")) if not frappe.db.get_value("Site Plan", site.plan, "database_access"): - frappe.throw(f"Database Access is not available on {site.plan} plan") + frappe.throw(_("Database Access is not available on {0} plan").format(site.plan)) # validate connection limit exists_db_users_connection_limit = frappe.db.get_all( @@ -112,7 +113,7 @@ def before_insert(self): }, ) if not replica_exists: - frappe.throw("Replica server is not available for this site") + frappe.throw(_("Replica server is not available for this site")) self.status = "Pending" if not self.username: @@ -143,19 +144,21 @@ def on_update(self): def _raise_error_if_archived(self): if self.status == "Archived": - frappe.throw("user has been deleted and no further changes can be made") + frappe.throw(_("user has been deleted and no further changes can be made")) def _get_database_name(self): site = frappe.get_doc("Site", self.site) db_name = site.fetch_info().get("config", {}).get("db_name") if not db_name: - frappe.throw("Failed to fetch database name of site") + frappe.throw(_("Failed to fetch database name of site")) return db_name @dashboard_whitelist() def save_and_apply_changes(self, label: str, mode: str, permissions: list): # noqa: C901 if self.status == "Pending" or self.status == "Archived": - frappe.throw(f"You can't modify information in {self.status} state. Please try again later") + frappe.throw( + _("You can't modify information in {0} state. Please try again later").format(self.status) + ) self.label = label is_db_user_configuration_changed = self.mode != mode or self._is_permissions_changed(permissions) @@ -412,7 +415,7 @@ def fetch_logs( ) # Convert to seconds return hits except Exception: - frappe.throw("Failed to fetch logs from log server. Please try again later.") + frappe.throw(_("Failed to fetch logs from log server. Please try again later.")) @staticmethod def process_job_update(job): # noqa: C901 diff --git a/press/press/doctype/site_domain/site_domain.py b/press/press/doctype/site_domain/site_domain.py index 37eea54e72c..0c7f50a7626 100644 --- a/press/press/doctype/site_domain/site_domain.py +++ b/press/press/doctype/site_domain/site_domain.py @@ -7,6 +7,7 @@ import frappe import rq +from frappe import _ from frappe.model.document import Document from press.agent import Agent @@ -68,7 +69,9 @@ def before_insert(self): .run(as_dict=True) ) if site: - frappe.throw(f"Domain {self.domain} is already taken. Please choose a different domain.") + frappe.throw( + _("Domain {0} is already taken. Please choose a different domain.").format(self.domain) + ) @property def agent(self): @@ -118,7 +121,9 @@ def setup_redirect_in_proxy(self): site: Site = frappe.get_doc("Site", self.site) target = site.host_name if target == self.name: - frappe.throw("Primary domain can't be redirected.", exc=frappe.exceptions.ValidationError) + frappe.throw( + frappe._("Primary domain can't be redirected."), exc=frappe.exceptions.ValidationError + ) site.set_redirects_in_proxy([self.name]) def remove_redirect_in_proxy(self): diff --git a/press/press/doctype/site_group_deploy/site_group_deploy.py b/press/press/doctype/site_group_deploy/site_group_deploy.py index 6a3f08ce594..dd675b573f3 100644 --- a/press/press/doctype/site_group_deploy/site_group_deploy.py +++ b/press/press/doctype/site_group_deploy/site_group_deploy.py @@ -3,6 +3,7 @@ from __future__ import annotations import frappe +from frappe import _ from frappe.model.document import Document @@ -74,11 +75,11 @@ def check_if_rg_or_site_exists(self): from press.press.doctype.site.site import Site if frappe.db.exists("Release Group", {"title": self.subdomain}): - frappe.throw(f"Release Group with title {self.subdomain} already exists") + frappe.throw(_("Release Group with title {0} already exists").format(self.subdomain)) domain = frappe.db.get_single_value("Press Settings", "domain") if Site.exists(self.subdomain, domain): - frappe.throw(f"Site with subdomain {self.subdomain} already exists") + frappe.throw(_("Site with subdomain {0} already exists").format(self.subdomain)) def get_optimal_server_for_private_bench(self): servers = frappe.get_all( diff --git a/press/press/doctype/site_migration/site_migration.py b/press/press/doctype/site_migration/site_migration.py index 0de34c598cf..d18c39c8e86 100644 --- a/press/press/doctype/site_migration/site_migration.py +++ b/press/press/doctype/site_migration/site_migration.py @@ -8,6 +8,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.core.utils import find from frappe.model.document import Document from frappe.utils import convert_utc_to_system_timezone @@ -82,7 +83,9 @@ class SiteMigration(Document): def before_insert(self): if get_ongoing_migration(self.site, scheduled=True): - frappe.throw(f"Ongoing/Scheduled Site Migration for the site {frappe.bold(self.site)} exists.") + frappe.throw( + _("Ongoing/Scheduled Site Migration for the site {0} exists.").format(frappe.bold(self.site)) + ) site: Site = frappe.get_doc("Site", self.site) site.check_move_scheduled() site.check_fatal_site_update() @@ -108,7 +111,7 @@ def check_for_existing_domains(self): def validate_bench(self): if frappe.db.get_value("Bench", self.destination_bench, "status", for_update=True) != "Active": - frappe.throw("Destination bench does not exist") + frappe.throw(_("Destination bench does not exist")) @cached_property def last_backup(self) -> SiteBackup | None: @@ -219,7 +222,7 @@ def check_for_ongoing_agent_jobs(self): "creation": (">", frappe.utils.add_to_date(None, hours=-24)), }, ): - frappe.throw("Ongoing Agent Job for site exists", OngoingAgentJob) + frappe.throw(_("Ongoing Agent Job for site exists"), OngoingAgentJob) def set_migration_type(self): if self.source_cluster != self.destination_cluster: diff --git a/press/press/doctype/site_plan_change/site_plan_change.py b/press/press/doctype/site_plan_change/site_plan_change.py index c2852f7e8b3..30f2c78a007 100644 --- a/press/press/doctype/site_plan_change/site_plan_change.py +++ b/press/press/doctype/site_plan_change/site_plan_change.py @@ -34,7 +34,7 @@ def validate(self): self.type = "Initial Plan" if self.from_plan and self.to_plan and self.from_plan == self.to_plan: - frappe.throw("From Plan and To Plan cannot be the same") + frappe.throw(_("From Plan and To Plan cannot be the same")) if self.from_plan and not self.type: from_plan_value = frappe.db.get_value("Site Plan", self.from_plan, "price_usd") @@ -69,7 +69,7 @@ def after_insert(self): # ) # # check if last site plan change was made before 48 hours # if last_plan_change.creation > frappe.utils.add_days(None, -2): - # frappe.throw("Cannot downgrade plan within 48 hours") + # frappe.throw(_("Cannot downgrade plan within 48 hours")) self.change_subscription_plan() @@ -87,7 +87,7 @@ def change_subscription_plan(self): site = frappe.get_doc("Site", self.site) subscription = site.subscription if not subscription: - frappe.throw(f"No subscription for site {site.name}") + frappe.throw(_("No subscription for site {0}").format(site.name)) if self.from_plan and self.from_plan != subscription.plan: frappe.throw( diff --git a/press/press/doctype/site_replication/site_replication.py b/press/press/doctype/site_replication/site_replication.py index d3ff255e18f..3c8e47c8676 100644 --- a/press/press/doctype/site_replication/site_replication.py +++ b/press/press/doctype/site_replication/site_replication.py @@ -1,9 +1,9 @@ # Copyright (c) 2022, Frappe and contributors # For license information, please see license.txt -from typing import List import frappe +from frappe import _ from frappe.model.document import Document from press.api.site import _new @@ -38,26 +38,20 @@ def validate_duplicate(self): # check for already running site replication site_reps = frappe.get_all( "Site Replication", - dict( - site=self.site, subdomain=self.subdomain, status="Running", name=("!=", self.name) - ), + dict(site=self.site, subdomain=self.subdomain, status="Running", name=("!=", self.name)), pluck="name", ) if site_reps: - frappe.throw(f"Site Replication for {self.site} is already running.") + frappe.throw(_("Site Replication for {0} is already running.").format(self.site)) def validate_site_name(self): # check if there is an non-archived site with same name domain = frappe.get_doc("Site", self.site).domain new_sitename = self.subdomain + "." + domain - sites = frappe.get_all( - "Site", dict(status=["!=", "Archived"], name=new_sitename), pluck="name" - ) + sites = frappe.get_all("Site", dict(status=["!=", "Archived"], name=new_sitename), pluck="name") if sites: - frappe.throw( - f"Site {self.new_site} already exists. Please choose another subdomain." - ) + frappe.throw(f"Site {self.new_site} already exists. Please choose another subdomain.") def after_insert(self): self.status = "Running" @@ -70,12 +64,12 @@ def after_insert(self): frappe.log_error("Site Replication Error") @classmethod - def get_all_running_site_replications(cls) -> List[Document]: + def get_all_running_site_replications(cls) -> list[Document]: replications = frappe.get_all(cls.doctype, dict(status="Running"), pluck="name") return cls.get_docs(replications) @classmethod - def get_docs(cls, names: List[str]) -> List[Document]: + def get_docs(cls, names: list[str]) -> list[Document]: return [frappe.get_doc(cls.doctype, name) for name in names] diff --git a/press/press/doctype/site_update/site_update.py b/press/press/doctype/site_update/site_update.py index 819b943b856..004a77ab347 100644 --- a/press/press/doctype/site_update/site_update.py +++ b/press/press/doctype/site_update/site_update.py @@ -11,6 +11,7 @@ import frappe import frappe.utils import pytz +from frappe import _ from frappe.core.utils import find from frappe.model.document import Document from frappe.utils import convert_utc_to_system_timezone @@ -140,7 +141,7 @@ def validate(self): filters={"group": self.group, "source": self.source_candidate}, ) if not differences: - frappe.throw("Could not find suitable Destination Bench", frappe.ValidationError) + frappe.throw(_("Could not find suitable Destination Bench"), frappe.ValidationError) self.validate_destination_bench(differences) self.validate_deploy_candidate_difference(differences) @@ -174,7 +175,7 @@ def validate_destination_bench(self, differences): self.destination_bench = destination_bench.name self.destination_candidate = destination_bench.candidate except Exception: - frappe.throw("Could not find suitable Destination Bench", frappe.ValidationError) + frappe.throw(_("Could not find suitable Destination Bench"), frappe.ValidationError) def validate_deploy_candidate_difference(self, differences): try: @@ -197,7 +198,7 @@ def validate_deploy_candidate_difference(self, differences): def validate_pending_updates(self): if self.has_pending_updates(): - frappe.throw("An update is already pending for this site", frappe.ValidationError) + frappe.throw(_("An update is already pending for this site"), frappe.ValidationError) @property def triggered_by_user(self): @@ -581,7 +582,7 @@ def trigger_recovery_job(self): # noqa: C901 return if physical_backup_restoration_status != "Success": # just to be safe - frappe.throw("Physical Backup Restoration is still in progress") + frappe.throw(_("Physical Backup Restoration is still in progress")) # Attempt to move site to source bench @@ -748,7 +749,7 @@ def update_status(cls, name, status): if ( _status := frappe.db.get_value("Site Update", name, "status", for_update=True, wait=False) ) != "Scheduled": - frappe.throw(f"Cannot cancel a Site Update with status {_status}") + frappe.throw(_("Cannot cancel a Site Update with status {0}").format(_status)) except (frappe.QueryTimeoutError, frappe.QueryDeadlockError): frappe.throw( diff --git a/press/press/doctype/site_user/site_user.py b/press/press/doctype/site_user/site_user.py index 95587425a0f..d86d44b7637 100644 --- a/press/press/doctype/site_user/site_user.py +++ b/press/press/doctype/site_user/site_user.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe import _ from frappe.model.document import Document @@ -22,7 +23,7 @@ class SiteUser(Document): def login_to_site(self): """Login to the site.""" if not self.enabled: - frappe.throw("User is disabled") + frappe.throw(_("User is disabled")) site = frappe.get_doc("Site", self.site) return site.login_as_user(self.user) diff --git a/press/press/doctype/ssh_certificate/ssh_certificate.py b/press/press/doctype/ssh_certificate/ssh_certificate.py index c70079d54bb..7830d7490f2 100644 --- a/press/press/doctype/ssh_certificate/ssh_certificate.py +++ b/press/press/doctype/ssh_certificate/ssh_certificate.py @@ -11,6 +11,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.model.document import Document from press.utils import log_error @@ -60,15 +61,15 @@ def validate_public_key(self): self.ssh_fingerprint = base64.b64encode(sha256_sum.digest()).decode() self.key_type = self.ssh_public_key.strip().split()[0].split("-")[1] except binascii.Error: - frappe.throw("Attached text is a not valid public key") + frappe.throw(_("Attached text is a not valid public key")) self.key_type = self.ssh_public_key.strip().split()[0].split("-")[1] if not self.key_type: - frappe.throw("Could not guess the key type. Please check your public key.") + frappe.throw(_("Could not guess the key type. Please check your public key.")) def validate_validity(self): if self.certificate_type == "User" and self.validity not in ("1h", "3h", "6h"): - frappe.throw("User certificates can only be valid for a short duration") + frappe.throw(_("User certificates can only be valid for a short duration")) def validate_certificate_authority(self): if not self.ssh_certificate_authority: @@ -90,7 +91,7 @@ def validate_existing_certificates(self): "group": self.group, }, ): - frappe.throw("A valid certificate already exists.") + frappe.throw(_("A valid certificate already exists.")) def create_public_key_file(self): with open(self.public_key_file, "w") as file: @@ -119,9 +120,7 @@ def generate_certificate(self): def run(self, command): try: - return subprocess.check_output( - shlex.split(command), stderr=subprocess.STDOUT - ).decode() + return subprocess.check_output(shlex.split(command), stderr=subprocess.STDOUT).decode() except subprocess.CalledProcessError as e: log_error("Command failed", output={e.output.decode()}, doc=self) raise diff --git a/press/press/doctype/stripe_webhook_log/stripe_webhook_log.py b/press/press/doctype/stripe_webhook_log/stripe_webhook_log.py index b5877b1765c..8458e2f3d8c 100644 --- a/press/press/doctype/stripe_webhook_log/stripe_webhook_log.py +++ b/press/press/doctype/stripe_webhook_log/stripe_webhook_log.py @@ -6,6 +6,7 @@ from datetime import datetime import frappe +from frappe import _ from frappe.model.document import Document import press.utils @@ -186,7 +187,7 @@ def parse_payload(payload, signature): return stripe.Webhook.construct_event(payload, signature, secret) except ValueError: # Invalid payload - frappe.throw("Invalid Payload", InvalidStripeWebhookEvent) + frappe.throw(_("Invalid Payload"), InvalidStripeWebhookEvent) except stripe.error.SignatureVerificationError: # Invalid signature - frappe.throw("Invalid Signature", InvalidStripeWebhookEvent) + frappe.throw(_("Invalid Signature"), InvalidStripeWebhookEvent) diff --git a/press/press/doctype/subscription/subscription.py b/press/press/doctype/subscription/subscription.py index 3fa36f69633..02e86a15e31 100644 --- a/press/press/doctype/subscription/subscription.py +++ b/press/press/doctype/subscription/subscription.py @@ -270,7 +270,9 @@ def validate_duplicate(self): ) if results: link = frappe.utils.get_link_to_form("Subscription", results[0]) - frappe.throw(f"A Subscription already exists: {link}", frappe.DuplicateEntryError) + frappe.throw( + frappe._("A Subscription already exists: {0}").format(link), frappe.DuplicateEntryError + ) def get_subscribed_document(self): if not hasattr(self, "_subscribed_document"): diff --git a/press/press/doctype/support_access/support_access.py b/press/press/doctype/support_access/support_access.py index a896ebae8c9..9029eb4659a 100644 --- a/press/press/doctype/support_access/support_access.py +++ b/press/press/doctype/support_access/support_access.py @@ -191,15 +191,15 @@ def validate_status_change(self): status_before = doc_before.status status_after = self.status if not self.is_valid_status_transition(status_before, status_after): - frappe.throw(f"Cannot change status from {status_before} to {status_after}") + frappe.throw(_("Cannot change status from {0} to {1}").format(status_before, status_after)) if status_after not in self.target_statuses: - frappe.throw("You are not allowed to set this status") + frappe.throw(_("You are not allowed to set this status")) def validate_expiry(self): if self.access_expired: - frappe.throw("Access expiry must be in the future") + frappe.throw(_("Access expiry must be in the future")) if self.status == "Pending" and self.access_allowed_till: - frappe.throw("Pending requests cannot have access expiry") + frappe.throw(_("Pending requests cannot have access expiry")) def validate_target_team(self): teams = set() @@ -207,7 +207,7 @@ def validate_target_team(self): team = frappe.get_value(resource.document_type, resource.document_name, "team") teams.add(team) if len(teams) != 1: - frappe.throw("Resources must belong to the same team") + frappe.throw(_("Resources must belong to the same team")) self.target_team = teams.pop() def validate_validity_change(self): diff --git a/press/press/doctype/team/team.py b/press/press/doctype/team/team.py index 28de461d09c..e087658874c 100644 --- a/press/press/doctype/team/team.py +++ b/press/press/doctype/team/team.py @@ -166,7 +166,7 @@ def get_doc(self, doc): and self.user != frappe.session.user and frappe.session.user not in self.get_user_list() ): - frappe.throw("You are not allowed to access this document") # nosemgrep + frappe.throw(_("You are not allowed to access this document")) # nosemgrep user = frappe.db.get_value( "User", @@ -288,7 +288,9 @@ def validate_billing_team(self): def reject_reenabling_team_for_banned_team(self): if self.has_value_changed("enabled") and self.enabled == 1 and self.banned: - frappe.throw(f"{self.user} is banned. Please signup with a different email or contact support.") + frappe.throw( + _(f"{self.user} is banned. Please signup with a different email or contact support.") + ) def delete(self, force=False, workflow=False): if not (force or workflow): @@ -373,7 +375,7 @@ def create_new( user.save(ignore_permissions=True) if frappe.db.exists("Team", {"user": user.name}): - frappe.throw("You have already an account with same email. Please login using the same email.") + frappe.throw(_("You have already an account with same email. Please login using the same email.")) team.team_title = "Parent Team" team.insert(ignore_permissions=True, ignore_links=True) @@ -453,7 +455,7 @@ def remove_team_member(self, member): for role in roles: frappe.get_doc("Press Role", role).remove_user(member) else: - frappe.throw(f"Team member {frappe.bold(member)} does not exists") + frappe.throw(_("Team member {0} does not exists").format(frappe.bold(member))) self.save(ignore_permissions=True) @@ -516,7 +518,7 @@ def validate_payment_mode(self): # noqa: C901 self.payment_mode == "Card" and frappe.db.count("Stripe Payment Method", {"team": self.name}) == 0 ): - frappe.throw("No card added. Please add a card to your account.") + frappe.throw(_("No card added. Please add a card to your account.")) # This check to verify recent pending payment is added to avoid validation issue when updating team doctype with payment mode as credits without balance as transaction is on going if ( self.payment_mode == "Prepaid Credits" @@ -642,7 +644,7 @@ def get_partnership_start_date(self): client = get_frappe_io_connection() data = client.get_value("Partner", "start_date", {"email": self.partner_email}) if not data: - frappe.throw("Partner not found on frappe.io") # nosemgrep + frappe.throw(_("Partner not found on frappe.io")) # nosemgrep return frappe.utils.getdate(data.get("start_date")) def create_referral_bonus(self, referrer_id): @@ -721,7 +723,7 @@ def update_billing_details(self, billing_details): if (address_doc.country != billing_details.country) and ( address_doc.country == "India" or billing_details.country == "India" ): - frappe.throw("Cannot change country of billing address") + frappe.throw(_("Cannot change country of billing address")) else: if self.account_request: ar: "AccountRequest" = frappe.get_doc("Account Request", self.account_request) @@ -997,7 +999,7 @@ def invite_team_member(self, email, roles=None): "request_key": ("is", "set"), }, ): - frappe.throw("User has already been invited recently. Please try again later.") + frappe.throw(_("User has already been invited recently. Please try again later.")) account_request = frappe.get_doc( { diff --git a/press/press/doctype/team_change/team_change.py b/press/press/doctype/team_change/team_change.py index 06fa1cf39e7..350c460c46c 100644 --- a/press/press/doctype/team_change/team_change.py +++ b/press/press/doctype/team_change/team_change.py @@ -4,6 +4,7 @@ from __future__ import annotations import frappe +from frappe import _ from frappe.model.document import Document @@ -28,7 +29,7 @@ class TeamChange(Document): def validate(self): team = frappe.get_doc(self.document_type, self.document_name).team if team != self.from_team: - frappe.throw(f"The owner of {self.document_type} is not {self.from_team}") + frappe.throw(_("The owner of {0} is not {1}").format(self.document_type, self.from_team)) def on_update(self): if self.document_type == "Site" and self.transfer_completed: diff --git a/press/press/doctype/team_deletion_request/team_deletion_request.py b/press/press/doctype/team_deletion_request/team_deletion_request.py index 8c2a4a5a6dc..a7e7d2ad695 100644 --- a/press/press/doctype/team_deletion_request/team_deletion_request.py +++ b/press/press/doctype/team_deletion_request/team_deletion_request.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe import _ from frappe.core.utils import find from frappe.utils.verified_command import get_signed_params from frappe.website.doctype.personal_data_deletion_request.personal_data_deletion_request import ( @@ -86,11 +87,16 @@ def validate_team_owner(self): if self.team_doc.user == frappe.session.user or "System Manager" in frappe.get_roles(): return - frappe.throw("You need to be a Team owner to request account deletion", exc=frappe.PermissionError) + frappe.throw( + frappe._("You need to be a Team owner to request account deletion"), exc=frappe.PermissionError + ) def validate_duplicate_request(self): if frappe.db.exists(self.doctype, {"team": self.team}): - frappe.throw(f"{self.doctype} for {self.team} already exists!", exc=frappe.DuplicateEntryError) + frappe.throw( + frappe._("{0} for {1} already exists!").format(self.doctype, self.team), + exc=frappe.DuplicateEntryError, + ) def delete_team_data(self): self.db_set("status", "Processing Deletion") @@ -263,7 +269,7 @@ def finalize_pending_invoices(self): def validate_outstanding_invoices(self): if self.team_doc.is_defaulter(): - frappe.throw("You have Unpaid Invoices. Clear them to delete your account") + frappe.throw(_("You have Unpaid Invoices. Clear them to delete your account")) def process_team_deletion_requests(): diff --git a/press/press/doctype/tls_certificate/tls_certificate.py b/press/press/doctype/tls_certificate/tls_certificate.py index fb5b3f109ed..8e254f5aca2 100644 --- a/press/press/doctype/tls_certificate/tls_certificate.py +++ b/press/press/doctype/tls_certificate/tls_certificate.py @@ -13,6 +13,7 @@ import frappe import OpenSSL +from frappe import _ from frappe.model.document import Document from frappe.query_builder.functions import Date @@ -71,7 +72,7 @@ def after_insert(self): def validate(self): if self.provider == "Other": if not self.team: - frappe.throw("Team is mandatory for custom TLS certificates.") + frappe.throw(_("Team is mandatory for custom TLS certificates.")) self.configure_full_chain() self.validate_key_length() @@ -91,7 +92,9 @@ def obtain_certificate(self): return if self.retry_count >= MANUAL_RETRY_LIMIT: - frappe.throw("Retry limit exceeded. Please check the error and try again.", TLSRetryLimitExceeded) + frappe.throw( + _("Retry limit exceeded. Please check the error and try again."), TLSRetryLimitExceeded + ) ( user, session_data, @@ -301,7 +304,7 @@ def validate_key_certificate_association(self): except OpenSSL.SSL.Error as e: self.error = repr(e) log_error("TLS Key Certificate Association Exception", certificate=self.name) - frappe.throw("Private Key and Certificate do not match") + frappe.throw(_("Private Key and Certificate do not match")) finally: if self.error: self.status = "Failure" diff --git a/press/press/doctype/user_ssh_certificate/user_ssh_certificate.py b/press/press/doctype/user_ssh_certificate/user_ssh_certificate.py index 116d005fe3f..6d1ef75adc8 100644 --- a/press/press/doctype/user_ssh_certificate/user_ssh_certificate.py +++ b/press/press/doctype/user_ssh_certificate/user_ssh_certificate.py @@ -10,7 +10,7 @@ import subprocess import frappe -from frappe import safe_decode +from frappe import _, safe_decode from frappe.model.document import Document from press.utils import log_error @@ -43,13 +43,13 @@ class UserSSHCertificate(Document): def validate(self): if not self.ssh_public_key: - frappe.throw("Please make sure that a valid public key has been added in team doc.") + frappe.throw(_("Please make sure that a valid public key has been added in team doc.")) # check if the ssh key is valid try: base64.b64decode(self.ssh_public_key.strip().split()[1]) except binascii.Error: - frappe.throw("Please ensure that the attached text is a valid public key") + frappe.throw(_("Please ensure that the attached text is a valid public key")) def before_insert(self): if frappe.get_all( @@ -62,7 +62,7 @@ def before_insert(self): "docstatus": 1, }, ): - frappe.throw("A valid certificate already exists.") + frappe.throw(_("A valid certificate already exists.")) def before_save(self): # decode the ssh key and generate a fingerprint @@ -76,7 +76,7 @@ def _set_key_type(self): # extract key_type (eg: rsa, ecdsa, ed25519.) for naming convention self.key_type = self.ssh_public_key.strip().split()[0].split("-")[1] if not self.key_type: - frappe.throw("Could not guess the key type. Please check your public key.") + frappe.throw(_("Could not guess the key type. Please check your public key.")) def before_submit(self): self._set_key_type() @@ -95,7 +95,7 @@ def before_submit(self): subprocess.check_output(shlex.split(command), cwd="/etc/ssh") except subprocess.CalledProcessError as e: log_error("SSH Certificate Generation Error", exception=e) - frappe.throw("Failed to generate a certificate for the specified key. Please try again.") + frappe.throw(_("Failed to generate a certificate for the specified key. Please try again.")) process = subprocess.Popen( shlex.split(f"ssh-keygen -Lf {tmp_pub_file_prefix}-cert.pub"), stdout=subprocess.PIPE, diff --git a/press/press/doctype/version_upgrade/version_upgrade.py b/press/press/doctype/version_upgrade/version_upgrade.py index 54b649c04d2..2fde569be77 100644 --- a/press/press/doctype/version_upgrade/version_upgrade.py +++ b/press/press/doctype/version_upgrade/version_upgrade.py @@ -137,7 +137,7 @@ def start(self): ) if site.status in TRANSITORY_STATES: - frappe.throw("Site is under maintenance. Cannot Update") + frappe.throw(_("Site is under maintenance. Cannot Update")) try: self.site_update = site.move_to_group( self.destination_group, self.skip_failing_patches, self.skip_backups diff --git a/press/press/doctype/virtual_disk_snapshot/virtual_disk_snapshot.py b/press/press/doctype/virtual_disk_snapshot/virtual_disk_snapshot.py index 3bc2715fc35..7530511eb02 100644 --- a/press/press/doctype/virtual_disk_snapshot/virtual_disk_snapshot.py +++ b/press/press/doctype/virtual_disk_snapshot/virtual_disk_snapshot.py @@ -12,6 +12,7 @@ import pytz import rq from botocore.exceptions import ClientError +from frappe import _ from frappe.model.document import Document from frappe.utils.data import cint from hcloud import Client as HetznerClient @@ -234,7 +235,7 @@ def lock(self): elif cluster.cloud_provider == "Hetzner": self.client.images.change_protection(HetznerImage(cint(self.snapshot_id)), delete=True) else: - frappe.throw("Only AWS and Hetzner Providers support snapshot locking/unlocking") + frappe.throw(_("Only AWS and Hetzner Providers support snapshot locking/unlocking")) @frappe.whitelist() def unlock(self): @@ -251,7 +252,7 @@ def unlock(self): self.client.images.change_protection(HetznerImage(cint(self.snapshot_id)), delete=False) else: - frappe.throw("Only AWS and Hetzner Providers support snapshot locking/unlocking") + frappe.throw(_("Only AWS and Hetzner Providers support snapshot locking/unlocking")) def create_volume( self, diff --git a/press/press/doctype/virtual_machine/virtual_machine.py b/press/press/doctype/virtual_machine/virtual_machine.py index b5046bb5f00..cee0fabb77a 100644 --- a/press/press/doctype/virtual_machine/virtual_machine.py +++ b/press/press/doctype/virtual_machine/virtual_machine.py @@ -12,6 +12,7 @@ import frappe import pydo import rq +from frappe import _ from frappe.core.utils import find from frappe.desk.utils import slug from frappe.model.document import Document @@ -209,7 +210,7 @@ def validate(self): self.validate_data_disk_snapshot() if self.series == "nat" and self.cloud_provider != "AWS EC2": - frappe.throw("NAT Servers are only supported on AWS EC2") + frappe.throw(_("NAT Servers are only supported on AWS EC2")) def validate_data_disk_snapshot(self): if not self.is_new() or not self.data_disk_snapshot: @@ -223,10 +224,10 @@ def validate_data_disk_snapshot(self): # Ensure the disk snapshot is Completed snapshot: VirtualDiskSnapshot = frappe.get_doc("Virtual Disk Snapshot", self.data_disk_snapshot) if snapshot.status != "Completed": - frappe.throw("The disk snapshot is unavailable because it has failed during the completion.") + frappe.throw(_("The disk snapshot is unavailable because it has failed during the completion.")) if snapshot.region != frappe.get_value("Cluster", self.cluster, "region"): - frappe.throw("Disk Snapshot is not available in the same region as the cluster.") # nosemgrep + frappe.throw(_("Disk Snapshot is not available in the same region as the cluster.")) # nosemgrep if not self.virtual_machine_image: frappe.throw( @@ -262,7 +263,7 @@ def on_update(self): def check_and_attach_data_disk_snapshot_volume(self): if not self.data_disk_snapshot_volume_id: - frappe.throw("Data Disk Snapshot Volume ID is not set.") + frappe.throw(_("Data Disk Snapshot Volume ID is not set.")) volume_state = self.get_state_of_volume(self.data_disk_snapshot_volume_id) if volume_state == "available": @@ -308,7 +309,7 @@ def ensure_no_data_disk_attached_before_attaching_snapshot_disk(self): # noqa: return if len(self.volumes) == 0: - frappe.throw("Sync the VM before checking data disk for snapshot recovery") + frappe.throw(_("Sync the VM before checking data disk for snapshot recovery")) if len(self.volumes) == 1: return @@ -455,7 +456,7 @@ def _get_digital_ocean_ssh_key_id(self) -> int: keys = keys.get("ssh_keys", []) existing_key = [key for key in keys if key["name"] == self.ssh_key] if not existing_key: - frappe.throw(f"No SSH Key found on Digital Ocean with the name {self.ssh_key}") + frappe.throw(_("No SSH Key found on Digital Ocean with the name {0}").format(self.ssh_key)) return existing_key[0]["id"] @@ -485,7 +486,7 @@ def _provision_frappe_compute(self): def _provision_digital_ocean(self): """Provision a Digital Ocean Droplet""" if not self.machine_image: - frappe.throw("Machine Image is required to provision Hetzner Virtual Machine.") + frappe.throw(_("Machine Image is required to provision Hetzner Virtual Machine.")) cluster: Cluster = frappe.get_doc("Cluster", self.cluster) @@ -494,7 +495,7 @@ def _provision_digital_ocean(self): cluster_firewall = next(fw for fw in firewalls if fw["id"] == cluster.security_group_id) if cluster_firewall["status"] == "failed": - frappe.throw(f"Firewall with id {cluster.security_group_id} failed") + frappe.throw(_("Firewall with id {0} failed").format(cluster.security_group_id)) try: droplet = self.client().droplets.create( @@ -511,13 +512,13 @@ def _provision_digital_ocean(self): ) self.instance_id = droplet["droplet"]["id"] except Exception as e: - frappe.throw(f"Failed to provision Digital Ocean Droplet: {e!s}") + frappe.throw(_("Failed to provision Digital Ocean Droplet: {0}").format(e)) try: for group in self.get_security_groups(): self.client().firewalls.assign_droplets(group, {"droplet_ids": [self.instance_id]}) except Exception as e: - frappe.throw(f"Failed to assign Firewall to Digital Ocean Droplet: {e!s}") + frappe.throw(_("Failed to assign Firewall to Digital Ocean Droplet: {0}").format(e)) self.status = self.get_digital_ocean_status_map()[droplet["droplet"]["status"]] self.save() @@ -532,7 +533,7 @@ def _provision_hetzner(self): from hcloud.ssh_keys.domain import SSHKey if not self.machine_image: - frappe.throw("Machine Image is required to provision Hetzner Virtual Machine.") + frappe.throw(_("Machine Image is required to provision Hetzner Virtual Machine.")) cluster = frappe.get_doc("Cluster", self.cluster) @@ -788,7 +789,7 @@ def get_cloud_init(self): if server.doctype == "Database Server" or getattr(server, "is_unified_server", False): memory = frappe.db.get_value("Server Plan", server.plan, "memory") or 1024 if memory < 1024: - frappe.throw("MariaDB cannot be installed on a server plan with less than 1GB RAM.") + frappe.throw(_("MariaDB cannot be installed on a server plan with less than 1GB RAM.")) mariadb_context = self.get_mariadb_context(server, memory) @@ -920,7 +921,7 @@ def get_latest_ubuntu_image(self): ubuntu_images = [image for image in images if "22.04" in image["name"]] if not ubuntu_images: - frappe.throw("No image available for Ubuntu 22.04") + frappe.throw(_("No image available for Ubuntu 22.04")) return ubuntu_images[0]["id"] @@ -974,7 +975,7 @@ def increase_disk_size(self, volume_id=None, increment=50): # noqa: C901 ) elif self.cloud_provider == "Hetzner": if volume_id == HETZNER_ROOT_DISK_ID: - frappe.throw("Cannot increase disk size for hetzner root disk.") + frappe.throw(_("Cannot increase disk size for hetzner root disk.")) from hcloud.volumes.domain import Volume @@ -982,7 +983,7 @@ def increase_disk_size(self, volume_id=None, increment=50): # noqa: C901 elif self.cloud_provider == "DigitalOcean": if volume_id == DIGITALOCEAN_ROOT_DISK_ID: - frappe.throw("Cannot increase disk size for Digital Ocean root disk.") + frappe.throw(_("Cannot increase disk size for Digital Ocean root disk.")) self.client().volumes.resize( volume_id, @@ -1509,15 +1510,17 @@ def assign_secondary_private_ip(self): def attach_secondary_private_ip(self, secondary_private_ip=None): if self.cloud_provider != "AWS EC2": - frappe.throw("Secondary IP assignment is currently only supported for AWS EC2 instances") + frappe.throw(_("Secondary IP assignment is currently only supported for AWS EC2 instances")) if self.series != "nat": - frappe.throw("Secondary IP assignment is only supported for NAT servers") + frappe.throw(_("Secondary IP assignment is only supported for NAT servers")) # this is needed if we do failover and attach the secondary private ip of one instance to another secondary_private_ip = secondary_private_ip or self.get_private_ip() if frappe.db.get_value("Virtual Machine", {"secondary_private_ip": secondary_private_ip}): - frappe.throw(f"Private IP {secondary_private_ip} is already assigned to another instance.") + frappe.throw( + _("Private IP {0} is already assigned to another instance.").format(secondary_private_ip) + ) ec2 = self.client() instance = ec2.describe_instances(InstanceIds=[self.instance_id]) @@ -1533,13 +1536,13 @@ def attach_secondary_private_ip(self, secondary_private_ip=None): def detach_secondary_private_ip(self): if self.cloud_provider != "AWS EC2": - frappe.throw("Secondary IP detachment is currently only supported for AWS EC2 instances") + frappe.throw(_("Secondary IP detachment is currently only supported for AWS EC2 instances")) if self.series != "nat": - frappe.throw("Secondary IP detachment is only supported for NAT servers") + frappe.throw(_("Secondary IP detachment is only supported for NAT servers")) if not self.secondary_private_ip: - frappe.throw("No secondary private IP assigned to this instance.") + frappe.throw(_("No secondary private IP assigned to this instance.")) ec2 = self.client() instance = ec2.describe_instances(InstanceIds=[self.instance_id]) @@ -1578,10 +1581,10 @@ def enable_source_dest_check(self): @frappe.whitelist() def disassociate_auto_assigned_public_ip(self): if self.cloud_provider != "AWS EC2": - frappe.throw("Public IP disassociation is currently only supported for AWS EC2 instances") + frappe.throw(_("Public IP disassociation is currently only supported for AWS EC2 instances")) if not self.public_ip_address: - frappe.throw("No public IP associated with this instance.") + frappe.throw(_("No public IP associated with this instance.")) try: frappe.db.get_value(self.doctype, self.name, "status", for_update=True, wait=False) @@ -2008,7 +2011,7 @@ def create_unified_server(self) -> tuple[Server, DatabaseServer]: """Virtual machines of series U will create a u series app server and u series database server""" if self.series != "u": - frappe.throw("Only virtual machines of series 'u' can create unified servers.") + frappe.throw(_("Only virtual machines of series 'u' can create unified servers.")) server_document = { "doctype": "Server", @@ -2223,7 +2226,7 @@ def create_registry_server(self): @frappe.whitelist() def create_nat_server(self): if self.series != "nat": - frappe.throw("Only virtual machines of series 'nat' can create NAT servers") + frappe.throw(_("Only virtual machines of series 'nat' can create NAT servers")) document = { "doctype": "NAT Server", @@ -2603,7 +2606,9 @@ def _create_vmm(self, virtual_machine_image: str, machine_type: str) -> VirtualM @frappe.whitelist() def convert_to_arm(self, virtual_machine_image, machine_type): if self.series == "f" and not self.ready_for_conversion: - frappe.throw("Please complete pre-migration steps before migrating", frappe.ValidationError) + frappe.throw( + frappe._("Please complete pre-migration steps before migrating"), frappe.ValidationError + ) return self._create_vmm(virtual_machine_image, machine_type) @@ -2779,7 +2784,7 @@ def get_next_volume_device_name(self): device_name = f"/dev/sd{chr(ord('a') + i)}" if device_name not in used_devices: return device_name - frappe.throw("No device name available for new volume") + frappe.throw(_("No device name available for new volume")) return None @frappe.whitelist() @@ -2797,7 +2802,7 @@ def detach(self, volume_id, sync: bool | None = None): from hcloud.volumes.domain import Volume if volume_id == HETZNER_ROOT_DISK_ID: - frappe.throw("Cannot detach hetzner root disk.") + frappe.throw(_("Cannot detach hetzner root disk.")) self.client().volumes.detach(Volume(id=volume_id)).wait_until_finished(HETZNER_ACTION_RETRIES) if sync: @@ -2818,7 +2823,7 @@ def delete_volume(self, volume_id, sync: bool | None = None): # noqa: C901 raise NotImplementedError if self.cloud_provider == "Hetzner": if volume_id == HETZNER_ROOT_DISK_ID: - frappe.throw("Cannot delete hetzner root disk.") + frappe.throw(_("Cannot delete hetzner root disk.")) from hcloud.volumes.domain import Volume @@ -2826,7 +2831,7 @@ def delete_volume(self, volume_id, sync: bool | None = None): # noqa: C901 if self.cloud_provider == "DigitalOcean": if volume_id == DIGITALOCEAN_ROOT_DISK_ID: - frappe.throw("Cannot delete digitalocean root disk.") + frappe.throw(_("Cannot delete digitalocean root disk.")) self.client().volumes.delete(volume_id=volume_id) @@ -2852,14 +2857,14 @@ def attach_static_ip(self, static_ip): return if self.is_static_ip: - frappe.throw("Virtual Machine already has a static IP associated.") + frappe.throw(_("Virtual Machine already has a static IP associated.")) client = self.client() response = client.describe_addresses(PublicIps=[static_ip]) address_info = response["Addresses"][0] if "AssociationId" in address_info: - frappe.throw("Static IP is already associated with another instance.") + frappe.throw(_("Static IP is already associated with another instance.")) client.associate_address(AllocationId=address_info["AllocationId"], InstanceId=self.instance_id) self.sync() diff --git a/press/press/doctype/virtual_machine_image/virtual_machine_image.py b/press/press/doctype/virtual_machine_image/virtual_machine_image.py index eca20b44264..a68fa66b361 100644 --- a/press/press/doctype/virtual_machine_image/virtual_machine_image.py +++ b/press/press/doctype/virtual_machine_image/virtual_machine_image.py @@ -7,6 +7,7 @@ import boto3 import frappe import pydo +from frappe import _ from frappe.core.utils import find from frappe.model.document import Document from hcloud import APIException, Client @@ -64,7 +65,7 @@ def before_insert(self): if ( self.cloud_provider == "Hetzner" or self.cloud_provider == "DigitalOcean" ) and self.has_data_volume: - frappe.throw("Hetzner Virtual Machine Images cannot have data volumes.") + frappe.throw(_("Hetzner Virtual Machine Images cannot have data volumes.")) if self.cloud_provider == "DigitalOcean": snapshots = self.client.droplets.list_snapshots(self.instance_id) diff --git a/press/press/doctype/wireguard_peer/wireguard_peer.py b/press/press/doctype/wireguard_peer/wireguard_peer.py index c03f6f301d2..9f2954d5821 100644 --- a/press/press/doctype/wireguard_peer/wireguard_peer.py +++ b/press/press/doctype/wireguard_peer/wireguard_peer.py @@ -6,6 +6,7 @@ import subprocess import frappe +from frappe import _ from frappe.model.document import Document from press.runner import Ansible @@ -65,7 +66,7 @@ def next_ip_address(self): self.peer_ip = str(next_ip_addr) except Exception: log_error("Wireguard Peer IP Exception", server=self.as_dict()) - frappe.throw("Invalid Wireguard Network") + frappe.throw(_("Invalid Wireguard Network")) @frappe.whitelist() def setup_wireguard(self): diff --git a/press/press/report/press_endpoints_audit/press_endpoints_audit.py b/press/press/report/press_endpoints_audit/press_endpoints_audit.py index 3835f315306..2edc0b2c3c2 100644 --- a/press/press/report/press_endpoints_audit/press_endpoints_audit.py +++ b/press/press/report/press_endpoints_audit/press_endpoints_audit.py @@ -10,6 +10,7 @@ import frappe import frappe.utils +from frappe import _ COLUMNS = [ { @@ -216,7 +217,7 @@ def audit_directory(self) -> Generator[FunctionAnalysis, None, None]: yield from self.analyze_file(file_path) except OSError as e: logging.error(f"Error walking directory {self.root_directory}: {e}") - frappe.throw(f"Failed to access directory: {e}") + frappe.throw(_("Failed to access directory: {0}").format(e)) def execute(filters) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]: diff --git a/press/saas/api/__init__.py b/press/saas/api/__init__.py index 02a6c6e2e75..4ef08043026 100644 --- a/press/saas/api/__init__.py +++ b/press/saas/api/__init__.py @@ -4,6 +4,7 @@ from contextlib import suppress import frappe +from frappe import _ def whitelist_saas_api(func): # noqa: C901 @@ -19,13 +20,13 @@ def auth_wrapper(*args, **kwargs): if site_access_token: splitted = site_access_token.split(":") if len(splitted) != 2: - frappe.throw("Invalid x-site-access-token provided", frappe.AuthenticationError) + frappe.throw(_("Invalid x-site-access-token provided"), frappe.AuthenticationError) accessTokenDocName = splitted[0] token = splitted[1] with suppress(frappe.DoesNotExistError): record = frappe.get_doc("Site Access Token", accessTokenDocName) if record.token != token: - frappe.throw("Invalid x-site-access-token provided", frappe.AuthenticationError) + frappe.throw(_("Invalid x-site-access-token provided"), frappe.AuthenticationError) # set site and site token from access token record site = record.site site_token = frappe.db.get_value("Site", site, "saas_communication_secret") @@ -58,13 +59,13 @@ def auth_wrapper(*args, **kwargs): ) if not site_record: - frappe.throw("Invalid x-site provided", frappe.AuthenticationError) + frappe.throw(_("Invalid x-site provided"), frappe.AuthenticationError) if site_record.saas_communication_secret != site_token: - frappe.throw("Invalid x-site-token provided", frappe.AuthenticationError) + frappe.throw(_("Invalid x-site-token provided"), frappe.AuthenticationError) if site_record.is_standby is None and site_record.standby_for_product is None: - frappe.throw("Sorry, this is not a SaaS site", frappe.AuthenticationError) + frappe.throw(_("Sorry, this is not a SaaS site"), frappe.AuthenticationError) # set site and team name in context frappe.local.site_name = site_record.name diff --git a/press/saas/api/billing.py b/press/saas/api/billing.py index 7baf4a6e8ba..05a2a948f06 100644 --- a/press/saas/api/billing.py +++ b/press/saas/api/billing.py @@ -4,6 +4,7 @@ import os import frappe +from frappe import _ from press.api import account as account_api from press.api import billing as billing_api @@ -128,7 +129,7 @@ def download_invoice(name: str): invoice = frappe.get_doc("Invoice", name) invoice.check_permission("read") if not invoice.invoice_pdf: - frappe.throw("Invoice PDF not found") + frappe.throw(_("Invoice PDF not found")) file_name = os.path.basename(invoice.invoice_pdf) file = frappe.get_doc("File", {"file_name": file_name}) frappe.local.response.filename = file.file_name @@ -144,7 +145,7 @@ def get_stripe_payment_url_for_invoice(name: str) -> str | None: return invoice.stripe_invoice_url return invoice.get_stripe_payment_url() except frappe.DoesNotExistError: - frappe.throw("Invoice not found") + frappe.throw(_("Invoice not found")) # Payment Method Related APIs diff --git a/press/saas/doctype/product_trial/product_trial.py b/press/saas/doctype/product_trial/product_trial.py index d89a9bc9788..5fdb55176b0 100644 --- a/press/saas/doctype/product_trial/product_trial.py +++ b/press/saas/doctype/product_trial/product_trial.py @@ -8,6 +8,7 @@ import frappe import frappe.utils +from frappe import _ from frappe.model.document import Document from frappe.utils.data import get_url @@ -65,7 +66,7 @@ class ProductTrial(Document): def get_doc(self, doc): if not self.published: - frappe.throw("Not permitted") + frappe.throw(_("Not permitted")) doc.proxy_servers = self.get_proxy_servers_for_available_clusters() return doc @@ -73,12 +74,12 @@ def get_doc(self, doc): def validate(self): plan = frappe.get_doc("Site Plan", self.trial_plan) if plan.document_type != "Site": - frappe.throw("Selected plan is not for site") + frappe.throw(_("Selected plan is not for site")) if not plan.is_trial_plan: - frappe.throw("Selected plan is not a trial plan") + frappe.throw(_("Selected plan is not a trial plan")) if not self.redirect_to_after_login.startswith("/"): - frappe.throw("Redirection route after login should start with /") + frappe.throw(_("Redirection route after login should start with /")) self.validate_hybrid_rules() @@ -101,7 +102,7 @@ def setup_trial_site( from press.press.doctype.site.site import Site, get_plan_config if Site.exists(subdomain, domain): - frappe.throw("Site with this subdomain already exists") + frappe.throw(_("Site with this subdomain already exists")) site_domain = f"{subdomain}.{domain}" diff --git a/press/saas/doctype/product_trial_request/product_trial_request.py b/press/saas/doctype/product_trial_request/product_trial_request.py index f6ffa58c6c8..ab8d72ee5ec 100644 --- a/press/saas/doctype/product_trial_request/product_trial_request.py +++ b/press/saas/doctype/product_trial_request/product_trial_request.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils.caching import redis_cache from frappe.utils.data import add_to_date, now_datetime @@ -210,12 +211,12 @@ def get_setup_wizard_payload(self): reference_doctype=self.doctype, reference_name=self.name, ) - frappe.throw(f"Failed to generate payload for Setup Wizard: {e}") + frappe.throw(_("Failed to generate payload for Setup Wizard: {0}").format(e)) def validate_subdomain_and_domain(self, subdomain: str, domain: str): validate_subdomain(subdomain) if domain not in get_domains(): - frappe.throw("Invalid domain") + frappe.throw(_("Invalid domain")) @dashboard_whitelist() def create_site(self, subdomain: str, domain: str): diff --git a/press/saas/doctype/saas_app_plan/saas_app_plan.py b/press/saas/doctype/saas_app_plan/saas_app_plan.py index 7037161a00c..c69e5d69da0 100644 --- a/press/saas/doctype/saas_app_plan/saas_app_plan.py +++ b/press/saas/doctype/saas_app_plan/saas_app_plan.py @@ -1,9 +1,9 @@ # Copyright (c) 2022, Frappe and contributors # For license information, please see license.txt -from typing import List import frappe +from frappe import _ from frappe.model.document import Document from press.press.doctype.invoice.invoice import calculate_gst @@ -19,7 +19,7 @@ def validate_plan(self): dt = frappe.db.get_value("Site Plan", self.plan, "document_type") if dt != "Saas App": - frappe.throw("The plan must be a Saas App plan.") + frappe.throw(_("The plan must be a Saas App plan.")) def get_total_amount(self, payment_option): """ @@ -34,9 +34,7 @@ def get_total_amount(self, payment_option): amount = amount + calculate_gst(amount) if payment_option == "Annual" and self.annual_discount: - amount -= ( - self.annual_discount_inr if team.country == "India" else self.annual_discount_usd - ) + amount -= self.annual_discount_inr if team.country == "India" else self.annual_discount_usd return amount @@ -46,10 +44,8 @@ def validate_payout_percentage(self): site_plan = frappe.db.get_value("Site Plan", self.site_plan, "price_usd") saas_plan = frappe.db.get_value("Site Plan", self.plan, "price_usd") - self.payout_percentage = 100 - float("{:.2f}".format((site_plan / saas_plan) * 100)) + self.payout_percentage = 100 - float(f"{(site_plan / saas_plan) * 100:.2f}") -def get_app_plan_features(app_plan: str) -> List[str]: - return frappe.get_all( - "Plan Feature", filters={"parent": app_plan}, pluck="description", order_by="idx" - ) +def get_app_plan_features(app_plan: str) -> list[str]: + return frappe.get_all("Plan Feature", filters={"parent": app_plan}, pluck="description", order_by="idx") diff --git a/press/saas/doctype/saas_app_subscription/saas_app_subscription.py b/press/saas/doctype/saas_app_subscription/saas_app_subscription.py index 35455040255..247bea68f87 100644 --- a/press/saas/doctype/saas_app_subscription/saas_app_subscription.py +++ b/press/saas/doctype/saas_app_subscription/saas_app_subscription.py @@ -5,6 +5,7 @@ from datetime import datetime import frappe +from frappe import _ from frappe.model.document import Document from frappe.utils import add_to_date @@ -63,7 +64,7 @@ def validate_saas_app_plan(self): app = frappe.db.get_value("Saas App Plan", self.saas_app_plan, "app") if app != self.app: - frappe.throw(f"Plan {self.saas_app_plan} is not for app {frappe.bold(self.app)}!") + frappe.throw(_("Plan {0} is not for app {1}!").format(self.saas_app_plan, frappe.bold(self.app))) def set_plan(self): self.plan, self.site_plan = frappe.db.get_value( diff --git a/press/utils/__init__.py b/press/utils/__init__.py index 571b212b52b..09353d6259d 100644 --- a/press/utils/__init__.py +++ b/press/utils/__init__.py @@ -25,6 +25,7 @@ from cryptography import x509 from cryptography.hazmat.backends import default_backend from cryptography.x509.oid import ExtensionOID +from frappe import _ from frappe.utils import get_datetime, get_system_timezone from frappe.utils.caching import redis_cache, site_cache @@ -104,7 +105,7 @@ def get_current_team(get_doc: Literal[False] = False) -> str: ... def get_current_team(get_doc=False) -> Team | str: if frappe.session.user == "Guest": - frappe.throw("Not Permitted", frappe.AuthenticationError) + frappe.throw(_("Not Permitted"), frappe.AuthenticationError) if not hasattr(frappe.local, "request"): # if this is not a request, send the current user as default team @@ -152,7 +153,7 @@ def get_current_team(get_doc=False) -> Team | str: ) if not system_user and not frappe.db.exists("Team", {"name": team, "enabled": 1}): - frappe.throw("Invalid Team", frappe.AuthenticationError) + frappe.throw(_("Invalid Team"), frappe.AuthenticationError) if get_doc: return frappe.get_doc("Team", team) @@ -354,7 +355,7 @@ def _validate_frappe_site(self): res = requests.get(f"{self.user_site}/api/method/frappe.ping", timeout=(5, 10)) if not res.ok: - frappe.throw("Invalid Frappe Site") + frappe.throw(_("Invalid Frappe Site")) if res.json().get("message") == "pong": # Get final redirect URL @@ -370,7 +371,7 @@ def _validate_user_permissions(self): ) if not response.ok: if response.status_code == 401: - frappe.throw("Invalid Credentials") + frappe.throw(_("Invalid Credentials")) else: response.raise_for_status() @@ -383,14 +384,14 @@ def _handle_backups_retrieval_failure(self, response): remote_site=self.site, ) if response.status_code == 403: - error_msg = "Insufficient Permissions" + frappe.throw(_("Insufficient Permissions")) else: side = "Client" if 400 <= response.status_code < 500 else "Server" - error_msg = ( - f"{side} Error occurred: {response.status_code} {response.raw.reason}" - f" received from {self.site}" + frappe.throw( + _("{0} Error occurred: {1} {2} received from {3}").format( + side, response.status_code, response.raw.reason, self.site + ) ) - frappe.throw(error_msg) def get_backups(self): self._create_fetch_backups_request() @@ -420,10 +421,11 @@ def _validate_missing_backups(self): if missing_files: missing_config = "site config and " if not self.backup_links.get("config") else "" - missing_backups = ( - f"Missing {missing_config}backup files: {', '.join([x.title() for x in missing_files])}" + frappe.throw( + _("Missing {0}backup files: {1}").format( + missing_config, ", ".join([x.title() for x in missing_files]) + ) ) - frappe.throw(missing_backups) def __process_frappe_url(self, path): if not path: @@ -463,7 +465,7 @@ def sanitize_config(config: dict) -> dict: def developer_mode_only(): if not frappe.conf.developer_mode: - frappe.throw("You don't know what you're doing. Go away!", frappe.ValidationError) + frappe.throw(_("You don't know what you're doing. Go away!"), frappe.ValidationError) def human_readable(num: int | float) -> str: @@ -944,13 +946,15 @@ def wrap(*args, **kwargs): def validate_subdomain(subdomain: str): site_regex = r"^[a-z0-9][a-z0-9-]*[a-z0-9]$" if not subdomain: - frappe.throw("Subdomain is required to create a site.") + frappe.throw(_("Subdomain is required to create a site.")) if not re.match(site_regex, subdomain): - frappe.throw("Subdomain contains invalid characters. Use lowercase characters, numbers and hyphens") + frappe.throw( + _("Subdomain contains invalid characters. Use lowercase characters, numbers and hyphens") + ) if len(subdomain) > 32: - frappe.throw("Subdomain too long. Use 32 or less characters") + frappe.throw(_("Subdomain too long. Use 32 or less characters")) if len(subdomain) < 5: - frappe.throw("Subdomain too short. Use 5 or more characters") + frappe.throw(_("Subdomain too short. Use 5 or more characters")) @site_cache(ttl=120) diff --git a/press/utils/billing.py b/press/utils/billing.py index 5f75485c230..7c1e78899b6 100644 --- a/press/utils/billing.py +++ b/press/utils/billing.py @@ -3,6 +3,7 @@ import frappe import razorpay import stripe +from frappe import _ from frappe.utils import fmt_money from press.exceptions import CentralServerNotSet, FrappeioServerNotSet @@ -62,7 +63,7 @@ def get_erpnext_com_connection(): erpnext_api_secret = press_settings.get_password("erpnext_api_secret", raise_exception=False) if not (press_settings.erpnext_api_key and press_settings.erpnext_url and erpnext_api_secret): - frappe.throw("ERPNext.com URL not set up in Press Settings", exc=CentralServerNotSet) + frappe.throw(_("ERPNext.com URL not set up in Press Settings"), exc=CentralServerNotSet) return FrappeClient( press_settings.erpnext_url, @@ -82,7 +83,7 @@ def get_frappe_io_connection(): frappe_api_secret = press_settings.get_password("frappeio_api_secret", raise_exception=False) if not (frappe_api_key and frappe_api_secret and press_settings.frappe_url): - frappe.throw("Frappe.io URL not set up in Press Settings", exc=FrappeioServerNotSet) + frappe.throw(_("Frappe.io URL not set up in Press Settings"), exc=FrappeioServerNotSet) frappe.local.press_frappeio_conn = FrappeClient( press_settings.frappe_url, api_key=frappe_api_key, api_secret=frappe_api_secret @@ -166,7 +167,7 @@ def get_stripe(): ) if not secret_key: - frappe.throw("Setup stripe via Press Settings before using press.api.billing.get_stripe") + frappe.throw(_("Setup stripe via Press Settings before using press.api.billing.get_stripe")) stripe.api_key = secret_key # Set the maximum number of retries for network requests @@ -259,7 +260,7 @@ def get_partner_external_connection(mpesa_setup): fields=["name", "url", "api_key", "api_secret"], ) if not payment_gateway: - frappe.throw("Mpesa Setup not set up in Payment Gateway") + frappe.throw(_("Mpesa Setup not set up in Payment Gateway")) # Fetch API key and secret pg = frappe.get_doc("Payment Gateway", payment_gateway[0].name) api_key = pg.api_key diff --git a/press/utils/extra.py b/press/utils/extra.py index b2e677eb010..e49db92908e 100644 --- a/press/utils/extra.py +++ b/press/utils/extra.py @@ -1,6 +1,7 @@ from functools import wraps import frappe +from frappe import _ def disabled(fn): @@ -11,6 +12,6 @@ def disabled(fn): @wraps(fn) def wrapper(*args, **kwargs): - frappe.throw("This method is disabled", frappe.PermissionError) + frappe.throw(_("This method is disabled"), frappe.PermissionError) return wrapper diff --git a/press/utils/webhook.py b/press/utils/webhook.py index 709ec1499df..b211bc40411 100644 --- a/press/utils/webhook.py +++ b/press/utils/webhook.py @@ -6,6 +6,7 @@ import json import frappe +from frappe import _ from frappe.model import default_fields from frappe.model.document import Document @@ -36,7 +37,7 @@ def create_webhook_event(event: str, payload: dict | Document, team: str) -> boo elif isinstance(payload, Document): data = _process_document_payload(payload) else: - frappe.throw("Invalid data type") + frappe.throw(_("Invalid data type")) request_payload = json.dumps( { diff --git a/press/workflow_engine/doctype/press_workflow/press_workflow.py b/press/workflow_engine/doctype/press_workflow/press_workflow.py index 25ec0d8a493..fa7d762de0b 100644 --- a/press/workflow_engine/doctype/press_workflow/press_workflow.py +++ b/press/workflow_engine/doctype/press_workflow/press_workflow.py @@ -68,7 +68,9 @@ def after_insert(self): def run(self): # noqa: C901 - best to keep it in one place if not self.linked_doctype or not self.linked_docname: - frappe.throw("Cannot run flow without linked_doctype and linked_docname", frappe.ValidationError) + frappe.throw( + frappe._("Cannot run flow without linked_doctype and linked_docname"), frappe.ValidationError + ) return try: diff --git a/press/workflow_engine/doctype/press_workflow_test/press_workflow_test.py b/press/workflow_engine/doctype/press_workflow_test/press_workflow_test.py index 45a6a3b4d2c..ce9aad6c657 100644 --- a/press/workflow_engine/doctype/press_workflow_test/press_workflow_test.py +++ b/press/workflow_engine/doctype/press_workflow_test/press_workflow_test.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import frappe +from frappe import _ from press.workflow_engine.doctype.press_workflow.decorators import flow, task from press.workflow_engine.doctype.press_workflow.workflow_builder import WorkflowBuilder @@ -26,7 +27,7 @@ class PressWorkflowTest(WorkflowBuilder): def validate(self): if not frappe.in_test: - frappe.throw("PressWorkflowTest doctype can be used only in Unit Tests") + frappe.throw(_("PressWorkflowTest doctype can be used only in Unit Tests")) @flow def main_success(self): diff --git a/press/www/dashboard.py b/press/www/dashboard.py index 54b88fe3e4d..f81bc870be9 100644 --- a/press/www/dashboard.py +++ b/press/www/dashboard.py @@ -3,6 +3,7 @@ import frappe +from frappe import _ from press.utils import get_default_team_for_user, get_valid_teams_for_user @@ -26,7 +27,7 @@ def _get_context(): @frappe.whitelist(methods=["POST"], allow_guest=True) def get_context_for_dev(): if not frappe.conf.developer_mode: - frappe.throw("This method is only meant for developer mode") + frappe.throw(_("This method is only meant for developer mode")) return get_boot() From b6504d347a074a88806be0657dfd4e996e52ab99 Mon Sep 17 00:00:00 2001 From: Sabu Siyad Date: Thu, 16 Apr 2026 17:16:07 +0530 Subject: [PATCH 2/7] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- press/api/site_login.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/press/api/site_login.py b/press/api/site_login.py index a22271543a9..42cf355d123 100644 --- a/press/api/site_login.py +++ b/press/api/site_login.py @@ -161,7 +161,7 @@ def login_to_site(email: str, site: str): session_id = frappe.local.request.cookies.get("site_user_sid") if not session_id or not isinstance(session_id, str): if frappe.session.user == "Guest": - return frappe.throw(_("Invalid session. Please login to {site}.")) + return frappe.throw(_("Invalid session. Please login to {site}.").format(site=site)) frappe.get_doc({"doctype": "Site User Session", "user": email}).insert(ignore_permissions=True) site_user_name = frappe.db.get_value("Site User", {"user": email, "site": site}, "name") From bf3d153270261319babe2ac226dd84aa41fc58c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 11:46:53 +0000 Subject: [PATCH 3/7] fix: wrap f-string in frappe.throw with _() and .format() in site_replication.py Agent-Logs-Url: https://github.com/frappe/press/sessions/191e6139-f282-41e1-bcc6-1f31a0eca427 Co-authored-by: ssiyad <28098330+ssiyad@users.noreply.github.com> --- press/press/doctype/site_replication/site_replication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/press/press/doctype/site_replication/site_replication.py b/press/press/doctype/site_replication/site_replication.py index 3c8e47c8676..1fc15debde2 100644 --- a/press/press/doctype/site_replication/site_replication.py +++ b/press/press/doctype/site_replication/site_replication.py @@ -51,7 +51,7 @@ def validate_site_name(self): sites = frappe.get_all("Site", dict(status=["!=", "Archived"], name=new_sitename), pluck="name") if sites: - frappe.throw(f"Site {self.new_site} already exists. Please choose another subdomain.") + frappe.throw(_("Site {0} already exists. Please choose another subdomain.").format(self.new_site)) def after_insert(self): self.status = "Running" From f4654a45b24fe47d1ab8507bcc8c48420b25de11 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 11:53:54 +0000 Subject: [PATCH 4/7] fix: remove _() from autoname pattern and fix f-string inside _() for team banned message Agent-Logs-Url: https://github.com/frappe/press/sessions/983a4265-2b05-4730-adde-6e4595ce8986 Co-authored-by: ssiyad <28098330+ssiyad@users.noreply.github.com> --- press/press/doctype/proxy_server/test_proxy_server.py | 3 +-- press/press/doctype/team/team.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/press/press/doctype/proxy_server/test_proxy_server.py b/press/press/doctype/proxy_server/test_proxy_server.py index 8109ba47d1b..1dfa545c9d5 100644 --- a/press/press/doctype/proxy_server/test_proxy_server.py +++ b/press/press/doctype/proxy_server/test_proxy_server.py @@ -5,7 +5,6 @@ from unittest.mock import Mock, patch import frappe -from frappe import _ from frappe.model.naming import make_autoname from frappe.tests.utils import FrappeTestCase @@ -38,7 +37,7 @@ def create_test_proxy_server( "status": "Active", "ip": frappe.mock("ipv4"), "private_ip": frappe.mock("ipv4_private"), - "hostname": make_autoname(hostname + _(".######")), + "hostname": make_autoname(hostname + ".######"), "cluster": cluster, "domain": domain, "domains": domains, diff --git a/press/press/doctype/team/team.py b/press/press/doctype/team/team.py index e087658874c..3ae33445e55 100644 --- a/press/press/doctype/team/team.py +++ b/press/press/doctype/team/team.py @@ -289,7 +289,7 @@ def validate_billing_team(self): def reject_reenabling_team_for_banned_team(self): if self.has_value_changed("enabled") and self.enabled == 1 and self.banned: frappe.throw( - _(f"{self.user} is banned. Please signup with a different email or contact support.") + _("{0} is banned. Please signup with a different email or contact support.").format(self.user) ) def delete(self, force=False, workflow=False): From 7d94efb11c8061c0e82e893b7e0b94230ba78bf0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 17:43:44 +0000 Subject: [PATCH 5/7] fix: remove _() from string key suffixes in test helper and from persisted Release Group title suffix Agent-Logs-Url: https://github.com/frappe/press/sessions/6840383d-730c-401f-8e20-1d1da2d80334 Co-authored-by: ssiyad <28098330+ssiyad@users.noreply.github.com> --- .../doctype/self_hosted_server/test_self_hosted_server.py | 4 ++-- press/press/doctype/site_action/site_action.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/press/press/doctype/self_hosted_server/test_self_hosted_server.py b/press/press/doctype/self_hosted_server/test_self_hosted_server.py index fb082fd7e45..f9e378d9539 100644 --- a/press/press/doctype/self_hosted_server/test_self_hosted_server.py +++ b/press/press/doctype/self_hosted_server/test_self_hosted_server.py @@ -313,8 +313,8 @@ def _create_test_ansible_play_and_task( "play": play.name, "role": play.playbook.split(".")[0], "task": kwargs.get("task_" + str(i + 1)), - "output": kwargs.get("task_" + str(i + 1) + _("_output")), - "result": kwargs.get("task_" + str(i + 1) + _("_result")), + "output": kwargs.get("task_" + str(i + 1) + "_output"), + "result": kwargs.get("task_" + str(i + 1) + "_result"), } ) task.insert() diff --git a/press/press/doctype/site_action/site_action.py b/press/press/doctype/site_action/site_action.py index ce86d6ea7a9..0b23a20815e 100644 --- a/press/press/doctype/site_action/site_action.py +++ b/press/press/doctype/site_action/site_action.py @@ -119,7 +119,7 @@ def pre_validate_move_site_to_different_server(self): elif not self.get_argument("new_release_group_name"): # No destination group and no new name provided - auto-generate if current_release_group.public: - self.set_argument("new_release_group_name", current_release_group.title + _(" - Clone")) + self.set_argument("new_release_group_name", current_release_group.title + " - Clone") else: # Private group - add the destination server to the current group if needed if not any(s.server == destination_server for s in current_release_group.servers): From e7fcd78d740a642cedd55654909e2c0f0a73c3cc Mon Sep 17 00:00:00 2001 From: Sabu Siyad Date: Wed, 22 Apr 2026 14:12:32 +0530 Subject: [PATCH 6/7] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- press/api/account.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/press/api/account.py b/press/api/account.py index 0bf72ae1786..4f149872905 100644 --- a/press/api/account.py +++ b/press/api/account.py @@ -902,7 +902,9 @@ def validate_pincode(billing_details): return frappe.throw( - _(f"Postal Code {billing_details.postal_code} is not associated with {billing_details.state}") + _("Postal Code {0} is not associated with {1}").format( + billing_details.postal_code, billing_details.state + ) ) From 3449c64f2ead2a7fe34fbc8e8291bdd1b75fc0b0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 08:44:34 +0000 Subject: [PATCH 7/7] fix: replace f-string inside _() with static placeholder form in site.py retry_archive Agent-Logs-Url: https://github.com/frappe/press/sessions/58140e3c-64ac-4fb9-acf2-fd75d4a47066 Co-authored-by: ssiyad <28098330+ssiyad@users.noreply.github.com> --- press/press/doctype/site/site.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/press/press/doctype/site/site.py b/press/press/doctype/site/site.py index 343ffe522fe..f6e769b9ae0 100644 --- a/press/press/doctype/site/site.py +++ b/press/press/doctype/site/site.py @@ -752,7 +752,7 @@ def retry_archive(self): site_name = self.subdomain + "." + self.domain if frappe.db.exists("Site", {"name": site_name, "bench": self.bench}): frappe.throw( - _(f"Another site already exists in {self.bench} with name: {site_name}.") + _("Another site already exists in {0} with name: {1}.").format(self.bench, site_name) ) # nosemgrep self.archive(site_name=site_name, reason="Retry Archive")