mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
fix: account deletion times out #291
This commit is contained in:
@@ -262,6 +262,7 @@ impl From<AccountV3> for AccountModel {
|
|||||||
imap_quota_bytes: None,
|
imap_quota_bytes: None,
|
||||||
auto_download_new_mailboxes: None,
|
auto_download_new_mailboxes: None,
|
||||||
download_schedule: None,
|
download_schedule: None,
|
||||||
|
deleting: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ pub struct Account {
|
|||||||
pub imap_quota_window: Option<QuotaWindow>,
|
pub imap_quota_window: Option<QuotaWindow>,
|
||||||
pub auto_download_new_mailboxes: Option<bool>,
|
pub auto_download_new_mailboxes: Option<bool>,
|
||||||
pub download_schedule: Option<String>,
|
pub download_schedule: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub deleting: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemDbModel for Account {
|
impl MemDbModel for Account {
|
||||||
@@ -136,6 +138,7 @@ impl Account {
|
|||||||
imap_quota_bytes: request.imap_quota_bytes,
|
imap_quota_bytes: request.imap_quota_bytes,
|
||||||
imap_quota_window: request.imap_quota_window,
|
imap_quota_window: request.imap_quota_window,
|
||||||
download_schedule: request.download_schedule,
|
download_schedule: request.download_schedule,
|
||||||
|
deleting: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,14 +226,46 @@ impl Account {
|
|||||||
|
|
||||||
pub async fn delete(account_id: u64) -> BichonResult<()> {
|
pub async fn delete(account_id: u64) -> BichonResult<()> {
|
||||||
let account = Self::get(account_id)?;
|
let account = Self::get(account_id)?;
|
||||||
if let Err(error) = Self::cleanup_account_resources_sequential(&account).await {
|
|
||||||
tracing::error!(
|
// Immediately stop scheduling to prevent new downloads
|
||||||
"[CLEANUP_ACCOUNT_ERROR] Account {}: failed to cleanup resources: {:#?}",
|
if matches!(account.account_type, AccountType::IMAP) {
|
||||||
account_id,
|
SYNC_TASKS.stop(account.id).await?;
|
||||||
error
|
|
||||||
);
|
|
||||||
return Err(error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark as deleting and disabled so frontend shows status and download tasks skip it
|
||||||
|
update_impl(
|
||||||
|
DB_MANAGER.db(),
|
||||||
|
&account_id.to_string(),
|
||||||
|
move |current: Account| {
|
||||||
|
let mut updated = current.clone();
|
||||||
|
updated.deleting = true;
|
||||||
|
updated.enabled = false;
|
||||||
|
Ok(updated)
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Spawn background cleanup — heavy work (Tantivy, attachments) runs off the request path
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(error) = Self::cleanup_account_resources_sequential(&account).await {
|
||||||
|
tracing::error!(
|
||||||
|
"[CLEANUP_ACCOUNT_ERROR] Account {}: cleanup failed, reverting deleting flag: {:#?}",
|
||||||
|
account_id,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
// Revert deleting flag so the user can retry (only if account record still exists)
|
||||||
|
let _ = update_impl(
|
||||||
|
DB_MANAGER.db(),
|
||||||
|
&account_id.to_string(),
|
||||||
|
move |current: Account| {
|
||||||
|
let mut updated = current.clone();
|
||||||
|
updated.deleting = false;
|
||||||
|
updated.enabled = true;
|
||||||
|
Ok(updated)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,8 +274,8 @@ impl Account {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn cleanup_account_resources_sequential(account: &AccountModel) -> BichonResult<()> {
|
async fn cleanup_account_resources_sequential(account: &AccountModel) -> BichonResult<()> {
|
||||||
|
// Sync task already stopped in delete() before spawning this background task
|
||||||
if matches!(account.account_type, AccountType::IMAP) {
|
if matches!(account.account_type, AccountType::IMAP) {
|
||||||
SYNC_TASKS.stop(account.id).await?;
|
|
||||||
DownloadState::delete(account.id)?;
|
DownloadState::delete(account.id)?;
|
||||||
}
|
}
|
||||||
OAuth2AccessToken::try_delete(account.id)?;
|
OAuth2AccessToken::try_delete(account.id)?;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ pub struct AccountResp {
|
|||||||
pub imap_quota_window: Option<QuotaWindow>,
|
pub imap_quota_window: Option<QuotaWindow>,
|
||||||
pub auto_download_new_mailboxes: Option<bool>,
|
pub auto_download_new_mailboxes: Option<bool>,
|
||||||
pub download_schedule: Option<String>,
|
pub download_schedule: Option<String>,
|
||||||
|
pub deleting: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountResp {
|
impl AccountResp {
|
||||||
@@ -95,6 +96,7 @@ impl AccountResp {
|
|||||||
imap_quota_window: account.imap_quota_window,
|
imap_quota_window: account.imap_quota_window,
|
||||||
auto_download_new_mailboxes: account.auto_download_new_mailboxes,
|
auto_download_new_mailboxes: account.auto_download_new_mailboxes,
|
||||||
download_schedule: account.download_schedule,
|
download_schedule: account.download_schedule,
|
||||||
|
deleting: account.deleting,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+7
@@ -113,6 +113,9 @@ impl AccountDownTask {
|
|||||||
let account = AccountModel::get(account_id).ok();
|
let account = AccountModel::get(account_id).ok();
|
||||||
match account {
|
match account {
|
||||||
Some(account) => {
|
Some(account) => {
|
||||||
|
if account.deleting {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
if !account.enabled {
|
if !account.enabled {
|
||||||
let last = LAST_WARN_TIME.load(Ordering::Relaxed);
|
let last = LAST_WARN_TIME.load(Ordering::Relaxed);
|
||||||
let now = utc_now!();
|
let now = utc_now!();
|
||||||
@@ -246,6 +249,10 @@ impl AccountDownTask {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if account.deleting {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Err(e) = process_imap_download(&account, token_clone, TriggerType::Manual).await
|
if let Err(e) = process_imap_download(&account, token_clone, TriggerType::Manual).await
|
||||||
{
|
{
|
||||||
error!("Manual download failed for {}: {:?}", account_id, e);
|
error!("Manual download failed for {}: {:?}", account_id, e);
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ export interface AccountModel {
|
|||||||
imap_quota_bytes?: number;
|
imap_quota_bytes?: number;
|
||||||
auto_download_new_mailboxes?: boolean;
|
auto_download_new_mailboxes?: boolean;
|
||||||
download_schedule?: string;
|
download_schedule?: string;
|
||||||
|
deleting?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const download_state = async (account_id: number) => {
|
export const download_state = async (account_id: number) => {
|
||||||
|
|||||||
@@ -50,13 +50,16 @@ export function DataTableRowActions({ row }: DataTableRowActionsProps) {
|
|||||||
const hasPermission = require_any_permission(['system:root', 'account:manage'], row.original.id);
|
const hasPermission = require_any_permission(['system:root', 'account:manage'], row.original.id);
|
||||||
const hasReadPermission = require_any_permission(['system:root', 'account:read_details'], row.original.id);
|
const hasReadPermission = require_any_permission(['system:root', 'account:read_details'], row.original.id);
|
||||||
|
|
||||||
|
const isDeleting = row.original.deleting === true;
|
||||||
|
|
||||||
const canShowAnyAction =
|
const canShowAnyAction =
|
||||||
|
!isDeleting && (
|
||||||
(hasPermission) ||
|
(hasPermission) ||
|
||||||
(account_type === 'IMAP' && hasPermission) ||
|
(account_type === 'IMAP' && hasPermission) ||
|
||||||
(account_type === 'IMAP' && hasReadPermission);
|
(account_type === 'IMAP' && hasReadPermission)
|
||||||
|
);
|
||||||
|
|
||||||
const showDownload = account_type === 'IMAP' && hasPermission;
|
const showDownload = !isDeleting && account_type === 'IMAP' && hasPermission;
|
||||||
|
|
||||||
const handleStartDownload = async () => {
|
const handleStartDownload = async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ export function AccountDeleteDialog({ open, onOpenChange, currentRow }: Props) {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
function handleSuccess() {
|
function handleSuccess() {
|
||||||
toast({
|
toast({
|
||||||
title: t('dialogs.accountDeleted'),
|
title: t('dialogs.accountDeletionStarted'),
|
||||||
description: t('dialogs.accountDeletedDesc'),
|
description: t('dialogs.accountDeletionStartedDesc'),
|
||||||
action: <ToastAction altText={t('common.close')}>{t('common.close')}</ToastAction>,
|
action: <ToastAction altText={t('common.close')}>{t('common.close')}</ToastAction>,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export function EnableAction({ row }: DataTableRowActionsProps) {
|
|||||||
<Switch
|
<Switch
|
||||||
checked={row.original.enabled}
|
checked={row.original.enabled}
|
||||||
onCheckedChange={() => setOpen(true)}
|
onCheckedChange={() => setOpen(true)}
|
||||||
disabled={!hasPermission || updateMutation.isPending}
|
disabled={!hasPermission || updateMutation.isPending || row.original.deleting}
|
||||||
/>
|
/>
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
open={open}
|
open={open}
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ export function RunningStateCellAction({ row }: Props) {
|
|||||||
const { setOpen, setCurrentRow } = useAccountContext()
|
const { setOpen, setCurrentRow } = useAccountContext()
|
||||||
const { require_any_permission } = useCurrentUser()
|
const { require_any_permission } = useCurrentUser()
|
||||||
|
|
||||||
|
if (row.original.deleting) {
|
||||||
|
return <span className="text-xs text-muted-foreground italic">Deleting...</span>
|
||||||
|
}
|
||||||
let account_type = row.original.account_type;
|
let account_type = row.original.account_type;
|
||||||
if (account_type === "NoSync") {
|
if (account_type === "NoSync") {
|
||||||
return <span className="text-xs text-muted-foreground">n/a</span>
|
return <span className="text-xs text-muted-foreground">n/a</span>
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ export function AccountTable({ columns, data }: DataTableProps) {
|
|||||||
<TableRow
|
<TableRow
|
||||||
key={row.id}
|
key={row.id}
|
||||||
data-state={row.getIsSelected() && 'selected'}
|
data-state={row.getIsSelected() && 'selected'}
|
||||||
className='group/row'
|
className={row.original.deleting ? 'opacity-50' : 'group/row'}
|
||||||
>
|
>
|
||||||
{row.getVisibleCells().map((cell) => (
|
{row.getVisibleCells().map((cell) => (
|
||||||
<TableCell
|
<TableCell
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ export default function Accounts() {
|
|||||||
const { data: accountList, isLoading } = useQuery({
|
const { data: accountList, isLoading } = useQuery({
|
||||||
queryKey: ['account-list'],
|
queryKey: ['account-list'],
|
||||||
queryFn: list_accounts,
|
queryFn: list_accounts,
|
||||||
|
refetchInterval: (query) => {
|
||||||
|
const items = (query.state.data as { items?: { deleting?: boolean }[] })?.items;
|
||||||
|
return items?.some((item) => item.deleting) ? 5000 : false;
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const hasAccounts = accountList != null && accountList.items.length > 0;
|
const hasAccounts = accountList != null && accountList.items.length > 0;
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "فشل حذف الحساب",
|
"accountDeleteFailed": "فشل حذف الحساب",
|
||||||
"accountDeleted": "تم حذف الحساب",
|
"accountDeleted": "تم حذف الحساب",
|
||||||
"accountDeletedDesc": "تم حذف حسابك بنجاح.",
|
"accountDeletedDesc": "تم حذف حسابك بنجاح.",
|
||||||
|
"accountDeletionStarted": "بدء حذف الحساب",
|
||||||
|
"accountDeletionStartedDesc": "جاري حذف الحساب في الخلفية، وسيختفي بعد اكتمال التنظيف.",
|
||||||
"allResourcesErased": "سيتم مسح جميع الموارد ذات الصلة نهائيًا.",
|
"allResourcesErased": "سيتم مسح جميع الموارد ذات الصلة نهائيًا.",
|
||||||
"cannotBeUndone": "لا يمكن التراجع عن هذا الإجراء!",
|
"cannotBeUndone": "لا يمكن التراجع عن هذا الإجراء!",
|
||||||
"confirmDelete": "تأكيد الحذف",
|
"confirmDelete": "تأكيد الحذف",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Sletning af konto mislykkedes",
|
"accountDeleteFailed": "Sletning af konto mislykkedes",
|
||||||
"accountDeleted": "Konto slettet",
|
"accountDeleted": "Konto slettet",
|
||||||
"accountDeletedDesc": "Din konto er blevet slettet.",
|
"accountDeletedDesc": "Din konto er blevet slettet.",
|
||||||
|
"accountDeletionStarted": "Kontoen slettes nu",
|
||||||
|
"accountDeletionStartedDesc": "Kontoen slettes i baggrunden og forsvinder, når oprydningen er færdig.",
|
||||||
"allResourcesErased": "Alle relaterede ressourcer vil blive slettet permanent.",
|
"allResourcesErased": "Alle relaterede ressourcer vil blive slettet permanent.",
|
||||||
"cannotBeUndone": "Denne handling kan ikke fortrydes!",
|
"cannotBeUndone": "Denne handling kan ikke fortrydes!",
|
||||||
"confirmDelete": "Bekræft Sletning",
|
"confirmDelete": "Bekræft Sletning",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Löschen des Kontos fehlgeschlagen",
|
"accountDeleteFailed": "Löschen des Kontos fehlgeschlagen",
|
||||||
"accountDeleted": "Konto gelöscht",
|
"accountDeleted": "Konto gelöscht",
|
||||||
"accountDeletedDesc": "Ihr Konto wurde erfolgreich gelöscht.",
|
"accountDeletedDesc": "Ihr Konto wurde erfolgreich gelöscht.",
|
||||||
|
"accountDeletionStarted": "Kontolöschung gestartet",
|
||||||
|
"accountDeletionStartedDesc": "Konto wird im Hintergrund gelöscht und verschwindet nach der Bereinigung.",
|
||||||
"allResourcesErased": "Alle zugehörigen Ressourcen werden dauerhaft gelöscht.",
|
"allResourcesErased": "Alle zugehörigen Ressourcen werden dauerhaft gelöscht.",
|
||||||
"cannotBeUndone": "Diese Aktion kann nicht rückgängig gemacht werden!",
|
"cannotBeUndone": "Diese Aktion kann nicht rückgängig gemacht werden!",
|
||||||
"confirmDelete": "Löschung bestätigen",
|
"confirmDelete": "Löschung bestätigen",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Account delete Failed",
|
"accountDeleteFailed": "Account delete Failed",
|
||||||
"accountDeleted": "Account Deleted",
|
"accountDeleted": "Account Deleted",
|
||||||
"accountDeletedDesc": "Your account has been successfully deleted.",
|
"accountDeletedDesc": "Your account has been successfully deleted.",
|
||||||
|
"accountDeletionStarted": "Account deletion started",
|
||||||
|
"accountDeletionStartedDesc": "Account is being deleted in the background and will disappear after cleanup.",
|
||||||
"allResourcesErased": "All related resources will be permanently erased.",
|
"allResourcesErased": "All related resources will be permanently erased.",
|
||||||
"cannotBeUndone": "This action cannot be undone!",
|
"cannotBeUndone": "This action cannot be undone!",
|
||||||
"confirmDelete": "Confirm Delete",
|
"confirmDelete": "Confirm Delete",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Error al eliminar la cuenta",
|
"accountDeleteFailed": "Error al eliminar la cuenta",
|
||||||
"accountDeleted": "Cuenta eliminada",
|
"accountDeleted": "Cuenta eliminada",
|
||||||
"accountDeletedDesc": "Tu cuenta ha sido eliminada con éxito.",
|
"accountDeletedDesc": "Tu cuenta ha sido eliminada con éxito.",
|
||||||
|
"accountDeletionStarted": "Eliminación de cuenta iniciada",
|
||||||
|
"accountDeletionStartedDesc": "La cuenta se está eliminando en segundo plano y desaparecerá tras la limpieza.",
|
||||||
"allResourcesErased": "Todos los recursos asociados se borrarán permanentemente.",
|
"allResourcesErased": "Todos los recursos asociados se borrarán permanentemente.",
|
||||||
"cannotBeUndone": "¡Esta acción no se puede deshacer!",
|
"cannotBeUndone": "¡Esta acción no se puede deshacer!",
|
||||||
"confirmDelete": "Confirmar eliminación",
|
"confirmDelete": "Confirmar eliminación",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Tilin poistaminen epäonnistui",
|
"accountDeleteFailed": "Tilin poistaminen epäonnistui",
|
||||||
"accountDeleted": "Tili poistettu",
|
"accountDeleted": "Tili poistettu",
|
||||||
"accountDeletedDesc": "Tilisi on poistettu onnistuneesti.",
|
"accountDeletedDesc": "Tilisi on poistettu onnistuneesti.",
|
||||||
|
"accountDeletionStarted": "Tilin poistaminen aloitettu",
|
||||||
|
"accountDeletionStartedDesc": "Tiliä poistetaan taustalla. Se katoaa, kun puhdistus on valmis.",
|
||||||
"allResourcesErased": "Kaikki liittyvät resurssit poistetaan pysyvästi.",
|
"allResourcesErased": "Kaikki liittyvät resurssit poistetaan pysyvästi.",
|
||||||
"cannotBeUndone": "Tätä toimenpidettä ei voi kumota!",
|
"cannotBeUndone": "Tätä toimenpidettä ei voi kumota!",
|
||||||
"confirmDelete": "Vahvista poisto",
|
"confirmDelete": "Vahvista poisto",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Échec de la suppression du compte",
|
"accountDeleteFailed": "Échec de la suppression du compte",
|
||||||
"accountDeleted": "Compte Supprimé",
|
"accountDeleted": "Compte Supprimé",
|
||||||
"accountDeletedDesc": "Votre compte a été supprimé avec succès.",
|
"accountDeletedDesc": "Votre compte a été supprimé avec succès.",
|
||||||
|
"accountDeletionStarted": "Suppression du compte lancée",
|
||||||
|
"accountDeletionStartedDesc": "Compte en cours de suppression en arrière-plan, disparaîtra après nettoyage.",
|
||||||
"allResourcesErased": "Toutes les ressources associées seront effacées définitivement.",
|
"allResourcesErased": "Toutes les ressources associées seront effacées définitivement.",
|
||||||
"cannotBeUndone": "Cette action ne peut pas être annulée !",
|
"cannotBeUndone": "Cette action ne peut pas être annulée !",
|
||||||
"confirmDelete": "Confirmer la Suppression",
|
"confirmDelete": "Confirmer la Suppression",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Eliminazione account fallita",
|
"accountDeleteFailed": "Eliminazione account fallita",
|
||||||
"accountDeleted": "Account Eliminato",
|
"accountDeleted": "Account Eliminato",
|
||||||
"accountDeletedDesc": "Il tuo account è stato eliminato con successo.",
|
"accountDeletedDesc": "Il tuo account è stato eliminato con successo.",
|
||||||
|
"accountDeletionStarted": "Eliminazione account avviata",
|
||||||
|
"accountDeletionStartedDesc": "L'account è in fase di eliminazione in background e scomparirà dopo la pulizia.",
|
||||||
"allResourcesErased": "Tutte le risorse correlate verranno cancellate permanentemente.",
|
"allResourcesErased": "Tutte le risorse correlate verranno cancellate permanentemente.",
|
||||||
"cannotBeUndone": "Questa azione non può essere annullata!",
|
"cannotBeUndone": "Questa azione non può essere annullata!",
|
||||||
"confirmDelete": "Conferma Eliminazione",
|
"confirmDelete": "Conferma Eliminazione",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "アカウントの削除に失敗しました",
|
"accountDeleteFailed": "アカウントの削除に失敗しました",
|
||||||
"accountDeleted": "アカウントが削除されました",
|
"accountDeleted": "アカウントが削除されました",
|
||||||
"accountDeletedDesc": "アカウントが正常に削除されました。",
|
"accountDeletedDesc": "アカウントが正常に削除されました。",
|
||||||
|
"accountDeletionStarted": "アカウントの削除を開始しました",
|
||||||
|
"accountDeletionStartedDesc": "バックグラウンドで削除中です。完了するとリストから消えます。",
|
||||||
"allResourcesErased": "関連するすべてのリソースは完全に消去されます。",
|
"allResourcesErased": "関連するすべてのリソースは完全に消去されます。",
|
||||||
"cannotBeUndone": "この操作は元に戻せません!",
|
"cannotBeUndone": "この操作は元に戻せません!",
|
||||||
"confirmDelete": "削除の確認",
|
"confirmDelete": "削除の確認",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "계정 삭제 실패",
|
"accountDeleteFailed": "계정 삭제 실패",
|
||||||
"accountDeleted": "계정 삭제됨",
|
"accountDeleted": "계정 삭제됨",
|
||||||
"accountDeletedDesc": "계정이 성공적으로 삭제되었습니다.",
|
"accountDeletedDesc": "계정이 성공적으로 삭제되었습니다.",
|
||||||
|
"accountDeletionStarted": "계정 삭제 시작됨",
|
||||||
|
"accountDeletionStartedDesc": "백그라운드에서 삭제 중이며, 정리가 끝나면 목록에서 사라집니다.",
|
||||||
"allResourcesErased": "모든 관련 리소스가 영구적으로 지워집니다.",
|
"allResourcesErased": "모든 관련 리소스가 영구적으로 지워집니다.",
|
||||||
"cannotBeUndone": "이 작업은 되돌릴 수 없습니다!",
|
"cannotBeUndone": "이 작업은 되돌릴 수 없습니다!",
|
||||||
"confirmDelete": "삭제 확인",
|
"confirmDelete": "삭제 확인",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Account verwijderen Mislukt",
|
"accountDeleteFailed": "Account verwijderen Mislukt",
|
||||||
"accountDeleted": "Account Verwijderd",
|
"accountDeleted": "Account Verwijderd",
|
||||||
"accountDeletedDesc": "Uw account is succesvol verwijderd.",
|
"accountDeletedDesc": "Uw account is succesvol verwijderd.",
|
||||||
|
"accountDeletionStarted": "Verwijdering account gestart",
|
||||||
|
"accountDeletionStartedDesc": "Account wordt op de achtergrond verwijderd en verdwijnt na opschonen.",
|
||||||
"allResourcesErased": "Alle gerelateerde bronnen worden permanent gewist.",
|
"allResourcesErased": "Alle gerelateerde bronnen worden permanent gewist.",
|
||||||
"cannotBeUndone": "Deze actie kan niet ongedaan worden gemaakt!",
|
"cannotBeUndone": "Deze actie kan niet ongedaan worden gemaakt!",
|
||||||
"confirmDelete": "Verwijdering Bevestigen",
|
"confirmDelete": "Verwijdering Bevestigen",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Sletting av konto mislyktes",
|
"accountDeleteFailed": "Sletting av konto mislyktes",
|
||||||
"accountDeleted": "Konto slettet",
|
"accountDeleted": "Konto slettet",
|
||||||
"accountDeletedDesc": "Kontoen din har blitt slettet.",
|
"accountDeletedDesc": "Kontoen din har blitt slettet.",
|
||||||
|
"accountDeletionStarted": "Kontosletting startet",
|
||||||
|
"accountDeletionStartedDesc": "Kontoen slettes i bakgrunnen og forsvinner når opprydningen er ferdig.",
|
||||||
"allResourcesErased": "Alle relaterte ressurser vil bli permanent slettet.",
|
"allResourcesErased": "Alle relaterte ressurser vil bli permanent slettet.",
|
||||||
"cannotBeUndone": "Denne handlingen kan ikke angres!",
|
"cannotBeUndone": "Denne handlingen kan ikke angres!",
|
||||||
"confirmDelete": "Bekreft sletting",
|
"confirmDelete": "Bekreft sletting",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Bład podczas usuwania konta",
|
"accountDeleteFailed": "Bład podczas usuwania konta",
|
||||||
"accountDeleted": "Konto usunięte",
|
"accountDeleted": "Konto usunięte",
|
||||||
"accountDeletedDesc": "Konto zostało usunięte.",
|
"accountDeletedDesc": "Konto zostało usunięte.",
|
||||||
|
"accountDeletionStarted": "Rozpoczęto usuwanie konta",
|
||||||
|
"accountDeletionStartedDesc": "Konto jest usuwane w tle i zniknie po zakończeniu czyszczenia.",
|
||||||
"allResourcesErased": "Wszystkie powiązane zasoby zostaną trwale usunięte.",
|
"allResourcesErased": "Wszystkie powiązane zasoby zostaną trwale usunięte.",
|
||||||
"cannotBeUndone": "Tej czynności nie można cofnąć!",
|
"cannotBeUndone": "Tej czynności nie można cofnąć!",
|
||||||
"confirmDelete": "Potwierdź usunięcie",
|
"confirmDelete": "Potwierdź usunięcie",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Falha ao Excluir Conta",
|
"accountDeleteFailed": "Falha ao Excluir Conta",
|
||||||
"accountDeleted": "Conta Excluída",
|
"accountDeleted": "Conta Excluída",
|
||||||
"accountDeletedDesc": "A conta foi excluída com sucesso.",
|
"accountDeletedDesc": "A conta foi excluída com sucesso.",
|
||||||
|
"accountDeletionStarted": "Exclusão da conta iniciada",
|
||||||
|
"accountDeletionStartedDesc": "A conta está sendo excluída em segundo plano e desaparecerá após a limpeza.",
|
||||||
"allResourcesErased": "Todos os recursos relacionados serão permanentemente apagados.",
|
"allResourcesErased": "Todos os recursos relacionados serão permanentemente apagados.",
|
||||||
"cannotBeUndone": "Esta ação não pode ser desfeita!",
|
"cannotBeUndone": "Esta ação não pode ser desfeita!",
|
||||||
"confirmDelete": "Confirmar Exclusão",
|
"confirmDelete": "Confirmar Exclusão",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Ошибка удаления аккаунта",
|
"accountDeleteFailed": "Ошибка удаления аккаунта",
|
||||||
"accountDeleted": "Аккаунт удален",
|
"accountDeleted": "Аккаунт удален",
|
||||||
"accountDeletedDesc": "Ваш аккаунт был успешно удален.",
|
"accountDeletedDesc": "Ваш аккаунт был успешно удален.",
|
||||||
|
"accountDeletionStarted": "Удаление аккаунта запущено",
|
||||||
|
"accountDeletionStartedDesc": "Аккаунт удаляется в фоновом режиме и исчезнет после очистки.",
|
||||||
"allResourcesErased": "Все связанные ресурсы будут безвозвратно стерты.",
|
"allResourcesErased": "Все связанные ресурсы будут безвозвратно стерты.",
|
||||||
"cannotBeUndone": "Это действие нельзя отменить!",
|
"cannotBeUndone": "Это действие нельзя отменить!",
|
||||||
"confirmDelete": "Подтвердить удаление",
|
"confirmDelete": "Подтвердить удаление",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "Borttagning av konto misslyckades",
|
"accountDeleteFailed": "Borttagning av konto misslyckades",
|
||||||
"accountDeleted": "Konto raderat",
|
"accountDeleted": "Konto raderat",
|
||||||
"accountDeletedDesc": "Ditt konto har tagits bort.",
|
"accountDeletedDesc": "Ditt konto har tagits bort.",
|
||||||
|
"accountDeletionStarted": "Kontoradering har startat",
|
||||||
|
"accountDeletionStartedDesc": "Kontot raderas i bakgrunden och försvinner när rensningen är klar.",
|
||||||
"allResourcesErased": "Alla relaterade resurser kommer att raderas permanent.",
|
"allResourcesErased": "Alla relaterade resurser kommer att raderas permanent.",
|
||||||
"cannotBeUndone": "Denna åtgärd kan inte ångras!",
|
"cannotBeUndone": "Denna åtgärd kan inte ångras!",
|
||||||
"confirmDelete": "Bekräfta borttagning",
|
"confirmDelete": "Bekräfta borttagning",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "帳號刪除失敗",
|
"accountDeleteFailed": "帳號刪除失敗",
|
||||||
"accountDeleted": "帳號已刪除",
|
"accountDeleted": "帳號已刪除",
|
||||||
"accountDeletedDesc": "帳號已成功刪除。",
|
"accountDeletedDesc": "帳號已成功刪除。",
|
||||||
|
"accountDeletionStarted": "帳戶刪除已開始",
|
||||||
|
"accountDeletionStartedDesc": "帳戶正在背景刪除,清理完成後將從列表中消失。",
|
||||||
"allResourcesErased": "所有相關資源將被永久清除。",
|
"allResourcesErased": "所有相關資源將被永久清除。",
|
||||||
"cannotBeUndone": "此操作無法復原!",
|
"cannotBeUndone": "此操作無法復原!",
|
||||||
"confirmDelete": "確認刪除",
|
"confirmDelete": "確認刪除",
|
||||||
|
|||||||
@@ -536,6 +536,8 @@
|
|||||||
"accountDeleteFailed": "账户删除失败",
|
"accountDeleteFailed": "账户删除失败",
|
||||||
"accountDeleted": "账户已删除",
|
"accountDeleted": "账户已删除",
|
||||||
"accountDeletedDesc": "您的账户已成功删除。",
|
"accountDeletedDesc": "您的账户已成功删除。",
|
||||||
|
"accountDeletionStarted": "账户删除已开始",
|
||||||
|
"accountDeletionStartedDesc": "账户正在后台删除,清理完成后将从列表中消失。",
|
||||||
"allResourcesErased": "所有相关资源将被永久删除。",
|
"allResourcesErased": "所有相关资源将被永久删除。",
|
||||||
"cannotBeUndone": "此操作无法撤销!",
|
"cannotBeUndone": "此操作无法撤销!",
|
||||||
"confirmDelete": "确认删除",
|
"confirmDelete": "确认删除",
|
||||||
|
|||||||
Reference in New Issue
Block a user