Loading panel/src/i18n/resources/en-US/errors.json +38 −1 Changes for panel/src/i18n/resources/en-US/errors.json: 38 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -26,5 +26,42 @@ "passkey_already_bound": "This Passkey is already bound to another account.", "passkey_unavailable": "Passkey subsystem is not available right now.", "passkey_not_allowed": "The operation was cancelled by the user or browser.", "passkey_aborted": "Passkey registration was aborted." "passkey_aborted": "Passkey registration was aborted.", "bad_name": "That server name is invalid — use 3–32 lowercase letters, digits or dashes, and avoid reserved names.", "bad_subdomain": "That subdomain is invalid — use 3–32 lowercase letters, digits or dashes, and avoid reserved names.", "at_capacity": "The cluster is at its running-server cap — try again once a server stops.", "storage_immutable": "Storage size can't be changed online.", "email_taken": "That email is already verified on another account — sign in with it or use another address.", "mail_undeliverable": "The verification email could not be delivered — try again later, or ask the operator to check the mail relay.", "bad_path": "That path is invalid — use a relative path inside the world directory.", "too_large": "That is larger than the size limit.", "files_timeout": "The file operation timed out — try again shortly.", "files_unavailable": "File editing isn't available right now.", "jobs_unavailable": "The background job service isn't available right now.", "already_terminal": "This build already finished — there is nothing to cancel.", "build_unavailable": "Image builds aren't available right now.", "build_logs_unavailable": "Build logs aren't available right now.", "already_reviewed": "This submission has already been reviewed.", "submissions_unavailable": "Submissions aren't available right now.", "uploads_unavailable": "Uploads aren't available right now.", "backup_unavailable": "Backups aren't available right now.", "account_retired": "This account has been retired — sign in with the account it was migrated to.", "no_migration": "There is no migration in progress.", "not_confirmed": "This migration hasn't been confirmed yet.", "already_confirmed": "This migration has already been confirmed.", "invalid_target": "The migration target must be a different account.", "target_not_found": "No account matches that migration target.", "target_unavailable": "That migration target isn't available.", "no_passkey": "This account has no Passkey bound yet.", "passkey_required": "Bind a Passkey before doing that.", "no_step_up_factor": "This account has no verified email or Passkey to confirm with yet.", "passkey_login_failed": "Passkey verification failed — try again.", "passkey_login_invalid": "That Passkey sign-in request is invalid or expired — start it again.", "too_many_challenges": "Too many verification attempts right now — try again shortly.", "op_login_invalid": "This operator sign-in couldn't be completed — restart the sign-in.", "op_login_not_found": "No pending operator sign-in with that id.", "too_many_streams": "Too many live streams are open — close some pages and try again.", "protected_admin": "That name belongs to a linked administrator and can't be reclaimed.", "auth_unavailable": "The sign-in service isn't available right now.", "setup_token_invalid": "That setup token is invalid or expired." } panel/src/i18n/resources/zh-CN/errors.json +38 −1 Changes for panel/src/i18n/resources/zh-CN/errors.json: 38 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -26,5 +26,42 @@ "passkey_already_bound": "此 Passkey 已被其他账户绑定。", "passkey_unavailable": "Passkey 功能当前不可用。", "passkey_not_allowed": "操作已被用户或浏览器取消。", "passkey_aborted": "Passkey 注册已被取消。" "passkey_aborted": "Passkey 注册已被取消。", "bad_name": "服务器名称不合法:需为 3–32 位小写字母、数字或连字符,且不能使用保留名。", "bad_subdomain": "子域名不合法:需为 3–32 位小写字母、数字或连字符,且不能使用保留名。", "at_capacity": "集群的在线服务器已达上限——等一台服务器停止后再试。", "storage_immutable": "存储容量不支持在线调整。", "email_taken": "该邮箱已在其他账户上完成验证;请直接用该邮箱登录,或换一个地址。", "mail_undeliverable": "验证码邮件发送失败——请稍后重试,或联系管理员检查邮件服务。", "bad_path": "路径不合法——请使用世界目录内的相对路径。", "too_large": "内容超出大小限制,无法处理。", "files_timeout": "文件操作超时——请稍后重试。", "files_unavailable": "文件功能当前不可用。", "jobs_unavailable": "后台任务服务当前不可用。", "already_terminal": "该构建已经结束,无法重复取消。", "build_unavailable": "构建功能当前不可用。", "build_logs_unavailable": "构建日志暂时不可用。", "already_reviewed": "该提交已经审核过了。", "submissions_unavailable": "提交流程当前不可用。", "uploads_unavailable": "上传功能当前不可用。", "backup_unavailable": "备份功能当前不可用。", "account_retired": "该账户已退役——请使用迁移后的账户登录。", "no_migration": "当前没有进行中的迁移。", "not_confirmed": "该迁移尚未完成确认。", "already_confirmed": "该迁移已经确认过了。", "invalid_target": "迁移目标账户不能与来源账户相同。", "target_not_found": "找不到迁移目标账户。", "target_unavailable": "迁移目标账户当前不可用。", "no_passkey": "该账户尚未绑定 Passkey。", "passkey_required": "此操作需要先绑定 Passkey。", "no_step_up_factor": "该账户还没有已验证的邮箱或 Passkey,无法完成此操作。", "passkey_login_failed": "Passkey 验证失败——请重试。", "passkey_login_invalid": "Passkey 登录请求无效或已过期——请重新发起。", "too_many_challenges": "验证请求过于频繁——请稍后再试。", "op_login_invalid": "本次管理员登录未能完成——请重新发起登录。", "op_login_not_found": "找不到该管理员登录请求。", "too_many_streams": "同时打开的实时连接过多——请关闭一些页面后再试。", "protected_admin": "该名字属于已绑定的管理员账户,不能被认领。", "auth_unavailable": "登录服务当前不可用。", "setup_token_invalid": "初始化令牌无效或已过期。" } panel/src/lib/api.ts +86 −0 Changes for panel/src/lib/api.ts: 86 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -683,6 +683,92 @@ export function humanizeError(e: unknown): string { return t("no_world_volume"); case "restore_unavailable": return t("restore_unavailable"); // Server create/edit (spec §22): the portability regex + reservation list are // enforced server-side, and the create form's own checks are weaker, so these // refusals reach the dialog as-is. case "bad_name": return t("bad_name"); case "bad_subdomain": return t("bad_subdomain"); case "at_capacity": return t("at_capacity"); case "storage_immutable": return t("storage_immutable"); // Email identity: the verified-email uniqueness index (migration 0020) plus // VerifyEmailOTP's guard make a second verified holder impossible; the OTP // relay can also refuse to deliver at all. case "email_taken": return t("email_taken"); case "mail_undeliverable": return t("mail_undeliverable"); // File editor (spec §7): path/size refusals from the sandboxed job, plus the // subsystem being unwired. case "bad_path": return t("bad_path"); case "too_large": return t("too_large"); case "files_timeout": return t("files_timeout"); case "files_unavailable": return t("files_unavailable"); case "jobs_unavailable": return t("jobs_unavailable"); // Builds, uploads and review: terminal-state conflicts and unwired subsystems. case "already_terminal": return t("already_terminal"); case "build_unavailable": return t("build_unavailable"); case "build_logs_unavailable": return t("build_logs_unavailable"); case "already_reviewed": return t("already_reviewed"); case "submissions_unavailable": return t("submissions_unavailable"); case "uploads_unavailable": return t("uploads_unavailable"); case "backup_unavailable": return t("backup_unavailable"); // Account migration + the re-auth steps it depends on: every refusal below is // an expected outcome of the Account → migrate flow, not a fault. case "account_retired": return t("account_retired"); case "no_migration": return t("no_migration"); case "not_confirmed": return t("not_confirmed"); case "already_confirmed": return t("already_confirmed"); case "invalid_target": return t("invalid_target"); case "target_not_found": return t("target_not_found"); case "target_unavailable": return t("target_unavailable"); case "no_passkey": return t("no_passkey"); case "passkey_required": return t("passkey_required"); case "no_step_up_factor": return t("no_step_up_factor"); case "passkey_login_failed": return t("passkey_login_failed"); case "passkey_login_invalid": return t("passkey_login_invalid"); case "too_many_challenges": return t("too_many_challenges"); // Operator-login approvals, live streams, and the remaining auth doors. case "op_login_invalid": return t("op_login_invalid"); case "op_login_not_found": return t("op_login_not_found"); case "too_many_streams": return t("too_many_streams"); case "protected_admin": return t("protected_admin"); case "auth_unavailable": return t("auth_unavailable"); case "setup_token_invalid": return t("setup_token_invalid"); default: if (err.status === 401) return t("session_expired"); if (err.status === 403) return t("forbidden"); Loading Loading
panel/src/i18n/resources/en-US/errors.json +38 −1 Changes for panel/src/i18n/resources/en-US/errors.json: 38 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -26,5 +26,42 @@ "passkey_already_bound": "This Passkey is already bound to another account.", "passkey_unavailable": "Passkey subsystem is not available right now.", "passkey_not_allowed": "The operation was cancelled by the user or browser.", "passkey_aborted": "Passkey registration was aborted." "passkey_aborted": "Passkey registration was aborted.", "bad_name": "That server name is invalid — use 3–32 lowercase letters, digits or dashes, and avoid reserved names.", "bad_subdomain": "That subdomain is invalid — use 3–32 lowercase letters, digits or dashes, and avoid reserved names.", "at_capacity": "The cluster is at its running-server cap — try again once a server stops.", "storage_immutable": "Storage size can't be changed online.", "email_taken": "That email is already verified on another account — sign in with it or use another address.", "mail_undeliverable": "The verification email could not be delivered — try again later, or ask the operator to check the mail relay.", "bad_path": "That path is invalid — use a relative path inside the world directory.", "too_large": "That is larger than the size limit.", "files_timeout": "The file operation timed out — try again shortly.", "files_unavailable": "File editing isn't available right now.", "jobs_unavailable": "The background job service isn't available right now.", "already_terminal": "This build already finished — there is nothing to cancel.", "build_unavailable": "Image builds aren't available right now.", "build_logs_unavailable": "Build logs aren't available right now.", "already_reviewed": "This submission has already been reviewed.", "submissions_unavailable": "Submissions aren't available right now.", "uploads_unavailable": "Uploads aren't available right now.", "backup_unavailable": "Backups aren't available right now.", "account_retired": "This account has been retired — sign in with the account it was migrated to.", "no_migration": "There is no migration in progress.", "not_confirmed": "This migration hasn't been confirmed yet.", "already_confirmed": "This migration has already been confirmed.", "invalid_target": "The migration target must be a different account.", "target_not_found": "No account matches that migration target.", "target_unavailable": "That migration target isn't available.", "no_passkey": "This account has no Passkey bound yet.", "passkey_required": "Bind a Passkey before doing that.", "no_step_up_factor": "This account has no verified email or Passkey to confirm with yet.", "passkey_login_failed": "Passkey verification failed — try again.", "passkey_login_invalid": "That Passkey sign-in request is invalid or expired — start it again.", "too_many_challenges": "Too many verification attempts right now — try again shortly.", "op_login_invalid": "This operator sign-in couldn't be completed — restart the sign-in.", "op_login_not_found": "No pending operator sign-in with that id.", "too_many_streams": "Too many live streams are open — close some pages and try again.", "protected_admin": "That name belongs to a linked administrator and can't be reclaimed.", "auth_unavailable": "The sign-in service isn't available right now.", "setup_token_invalid": "That setup token is invalid or expired." }
panel/src/i18n/resources/zh-CN/errors.json +38 −1 Changes for panel/src/i18n/resources/zh-CN/errors.json: 38 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -26,5 +26,42 @@ "passkey_already_bound": "此 Passkey 已被其他账户绑定。", "passkey_unavailable": "Passkey 功能当前不可用。", "passkey_not_allowed": "操作已被用户或浏览器取消。", "passkey_aborted": "Passkey 注册已被取消。" "passkey_aborted": "Passkey 注册已被取消。", "bad_name": "服务器名称不合法:需为 3–32 位小写字母、数字或连字符,且不能使用保留名。", "bad_subdomain": "子域名不合法:需为 3–32 位小写字母、数字或连字符,且不能使用保留名。", "at_capacity": "集群的在线服务器已达上限——等一台服务器停止后再试。", "storage_immutable": "存储容量不支持在线调整。", "email_taken": "该邮箱已在其他账户上完成验证;请直接用该邮箱登录,或换一个地址。", "mail_undeliverable": "验证码邮件发送失败——请稍后重试,或联系管理员检查邮件服务。", "bad_path": "路径不合法——请使用世界目录内的相对路径。", "too_large": "内容超出大小限制,无法处理。", "files_timeout": "文件操作超时——请稍后重试。", "files_unavailable": "文件功能当前不可用。", "jobs_unavailable": "后台任务服务当前不可用。", "already_terminal": "该构建已经结束,无法重复取消。", "build_unavailable": "构建功能当前不可用。", "build_logs_unavailable": "构建日志暂时不可用。", "already_reviewed": "该提交已经审核过了。", "submissions_unavailable": "提交流程当前不可用。", "uploads_unavailable": "上传功能当前不可用。", "backup_unavailable": "备份功能当前不可用。", "account_retired": "该账户已退役——请使用迁移后的账户登录。", "no_migration": "当前没有进行中的迁移。", "not_confirmed": "该迁移尚未完成确认。", "already_confirmed": "该迁移已经确认过了。", "invalid_target": "迁移目标账户不能与来源账户相同。", "target_not_found": "找不到迁移目标账户。", "target_unavailable": "迁移目标账户当前不可用。", "no_passkey": "该账户尚未绑定 Passkey。", "passkey_required": "此操作需要先绑定 Passkey。", "no_step_up_factor": "该账户还没有已验证的邮箱或 Passkey,无法完成此操作。", "passkey_login_failed": "Passkey 验证失败——请重试。", "passkey_login_invalid": "Passkey 登录请求无效或已过期——请重新发起。", "too_many_challenges": "验证请求过于频繁——请稍后再试。", "op_login_invalid": "本次管理员登录未能完成——请重新发起登录。", "op_login_not_found": "找不到该管理员登录请求。", "too_many_streams": "同时打开的实时连接过多——请关闭一些页面后再试。", "protected_admin": "该名字属于已绑定的管理员账户,不能被认领。", "auth_unavailable": "登录服务当前不可用。", "setup_token_invalid": "初始化令牌无效或已过期。" }
panel/src/lib/api.ts +86 −0 Changes for panel/src/lib/api.ts: 86 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -683,6 +683,92 @@ export function humanizeError(e: unknown): string { return t("no_world_volume"); case "restore_unavailable": return t("restore_unavailable"); // Server create/edit (spec §22): the portability regex + reservation list are // enforced server-side, and the create form's own checks are weaker, so these // refusals reach the dialog as-is. case "bad_name": return t("bad_name"); case "bad_subdomain": return t("bad_subdomain"); case "at_capacity": return t("at_capacity"); case "storage_immutable": return t("storage_immutable"); // Email identity: the verified-email uniqueness index (migration 0020) plus // VerifyEmailOTP's guard make a second verified holder impossible; the OTP // relay can also refuse to deliver at all. case "email_taken": return t("email_taken"); case "mail_undeliverable": return t("mail_undeliverable"); // File editor (spec §7): path/size refusals from the sandboxed job, plus the // subsystem being unwired. case "bad_path": return t("bad_path"); case "too_large": return t("too_large"); case "files_timeout": return t("files_timeout"); case "files_unavailable": return t("files_unavailable"); case "jobs_unavailable": return t("jobs_unavailable"); // Builds, uploads and review: terminal-state conflicts and unwired subsystems. case "already_terminal": return t("already_terminal"); case "build_unavailable": return t("build_unavailable"); case "build_logs_unavailable": return t("build_logs_unavailable"); case "already_reviewed": return t("already_reviewed"); case "submissions_unavailable": return t("submissions_unavailable"); case "uploads_unavailable": return t("uploads_unavailable"); case "backup_unavailable": return t("backup_unavailable"); // Account migration + the re-auth steps it depends on: every refusal below is // an expected outcome of the Account → migrate flow, not a fault. case "account_retired": return t("account_retired"); case "no_migration": return t("no_migration"); case "not_confirmed": return t("not_confirmed"); case "already_confirmed": return t("already_confirmed"); case "invalid_target": return t("invalid_target"); case "target_not_found": return t("target_not_found"); case "target_unavailable": return t("target_unavailable"); case "no_passkey": return t("no_passkey"); case "passkey_required": return t("passkey_required"); case "no_step_up_factor": return t("no_step_up_factor"); case "passkey_login_failed": return t("passkey_login_failed"); case "passkey_login_invalid": return t("passkey_login_invalid"); case "too_many_challenges": return t("too_many_challenges"); // Operator-login approvals, live streams, and the remaining auth doors. case "op_login_invalid": return t("op_login_invalid"); case "op_login_not_found": return t("op_login_not_found"); case "too_many_streams": return t("too_many_streams"); case "protected_admin": return t("protected_admin"); case "auth_unavailable": return t("auth_unavailable"); case "setup_token_invalid": return t("setup_token_invalid"); default: if (err.status === 401) return t("session_expired"); if (err.status === 403) return t("forbidden"); Loading