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..4f149872905 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,11 @@ 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(
+ _("Postal Code {0} is not associated with {1}").format(
+ billing_details.postal_code, billing_details.state
+ )
+ )
@frappe.whitelist(allow_guest=True)
@@ -1157,7 +1163,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 +1198,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 +1238,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 +1255,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 +1267,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 +1282,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 +1315,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..42cf355d123 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}.").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")
- 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/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/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..f6e769b9ae0 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(
+ _("Another site already exists in {0} with name: {1}.").format(self.bench, 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..0b23a20815e 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
@@ -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..1fc15debde2 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(_("Site {0} already exists. Please choose another subdomain.").format(self.new_site))
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..3ae33445e55 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(
+ _("{0} is banned. Please signup with a different email or contact support.").format(self.user)
+ )
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()