mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
feat(imap): add message size check before download
This commit is contained in:
@@ -250,6 +250,7 @@ impl From<AccountV3> for AccountModel {
|
|||||||
account_type: value.account_type,
|
account_type: value.account_type,
|
||||||
download_interval_min: value.sync_interval_min,
|
download_interval_min: value.sync_interval_min,
|
||||||
download_batch_size: value.sync_batch_size,
|
download_batch_size: value.sync_batch_size,
|
||||||
|
max_email_size_bytes: None,
|
||||||
known_folders: value.known_folders,
|
known_folders: value.known_folders,
|
||||||
created_at: value.created_at,
|
created_at: value.created_at,
|
||||||
updated_at: value.updated_at,
|
updated_at: value.updated_at,
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ pub struct Account {
|
|||||||
pub account_type: AccountType,
|
pub account_type: AccountType,
|
||||||
pub download_interval_min: Option<i64>,
|
pub download_interval_min: Option<i64>,
|
||||||
pub download_batch_size: Option<u32>,
|
pub download_batch_size: Option<u32>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub max_email_size_bytes: Option<u64>,
|
||||||
pub known_folders: Option<BTreeSet<String>>,
|
pub known_folders: Option<BTreeSet<String>>,
|
||||||
pub created_at: i64,
|
pub created_at: i64,
|
||||||
pub updated_at: i64,
|
pub updated_at: i64,
|
||||||
@@ -128,6 +130,7 @@ impl Account {
|
|||||||
pgp_key: request.pgp_key,
|
pgp_key: request.pgp_key,
|
||||||
created_by: user_id,
|
created_by: user_id,
|
||||||
download_batch_size: request.download_batch_size,
|
download_batch_size: request.download_batch_size,
|
||||||
|
max_email_size_bytes: request.max_email_size_bytes,
|
||||||
date_before: request.date_before,
|
date_before: request.date_before,
|
||||||
auto_download_new_mailboxes: request.auto_download_new_mailboxes,
|
auto_download_new_mailboxes: request.auto_download_new_mailboxes,
|
||||||
imap_quota_bytes: request.imap_quota_bytes,
|
imap_quota_bytes: request.imap_quota_bytes,
|
||||||
@@ -395,6 +398,10 @@ impl Account {
|
|||||||
new.download_batch_size = Some(*download_batch_size);
|
new.download_batch_size = Some(*download_batch_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(max_email_size_bytes) = request.max_email_size_bytes {
|
||||||
|
new.max_email_size_bytes = Some(max_email_size_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(use_proxy) = request.use_proxy {
|
if let Some(use_proxy) = request.use_proxy {
|
||||||
new.use_proxy = Some(use_proxy);
|
new.use_proxy = Some(use_proxy);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ pub struct AccountCreateRequest {
|
|||||||
oai(validator(minimum(value = "10"), maximum(value = "200")))
|
oai(validator(minimum(value = "10"), maximum(value = "200")))
|
||||||
)]
|
)]
|
||||||
pub download_batch_size: Option<u32>,
|
pub download_batch_size: Option<u32>,
|
||||||
|
pub max_email_size_bytes: Option<u64>,
|
||||||
pub use_proxy: Option<u64>,
|
pub use_proxy: Option<u64>,
|
||||||
pub use_dangerous: bool,
|
pub use_dangerous: bool,
|
||||||
pub pgp_key: Option<String>,
|
pub pgp_key: Option<String>,
|
||||||
@@ -165,6 +166,7 @@ pub struct AccountUpdateRequest {
|
|||||||
oai(validator(minimum(value = "10"), maximum(value = "200")))
|
oai(validator(minimum(value = "10"), maximum(value = "200")))
|
||||||
)]
|
)]
|
||||||
pub download_batch_size: Option<u32>,
|
pub download_batch_size: Option<u32>,
|
||||||
|
pub max_email_size_bytes: Option<u64>,
|
||||||
/// Optional proxy ID for establishing the connection to external APIs (e.g., Gmail, Outlook).
|
/// Optional proxy ID for establishing the connection to external APIs (e.g., Gmail, Outlook).
|
||||||
/// - If `None` or not provided, the client will connect directly to the API server.
|
/// - If `None` or not provided, the client will connect directly to the API server.
|
||||||
/// - If `Some(proxy_id)`, the client will use the pre-configured proxy with the given ID for API requests.
|
/// - If `Some(proxy_id)`, the client will use the pre-configured proxy with the given ID for API requests.
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ pub struct AccountResp {
|
|||||||
pub account_type: AccountType,
|
pub account_type: AccountType,
|
||||||
pub download_interval_min: Option<i64>,
|
pub download_interval_min: Option<i64>,
|
||||||
pub download_batch_size: Option<u32>,
|
pub download_batch_size: Option<u32>,
|
||||||
|
pub max_email_size_bytes: Option<u64>,
|
||||||
pub known_folders: Option<BTreeSet<String>>,
|
pub known_folders: Option<BTreeSet<String>>,
|
||||||
pub created_at: i64,
|
pub created_at: i64,
|
||||||
pub updated_at: i64,
|
pub updated_at: i64,
|
||||||
@@ -76,6 +77,7 @@ impl AccountResp {
|
|||||||
account_type: account.account_type,
|
account_type: account.account_type,
|
||||||
download_interval_min: account.download_interval_min,
|
download_interval_min: account.download_interval_min,
|
||||||
download_batch_size: account.download_batch_size,
|
download_batch_size: account.download_batch_size,
|
||||||
|
max_email_size_bytes: account.max_email_size_bytes,
|
||||||
known_folders: account.known_folders,
|
known_folders: account.known_folders,
|
||||||
created_at: account.created_at,
|
created_at: account.created_at,
|
||||||
updated_at: account.updated_at,
|
updated_at: account.updated_at,
|
||||||
|
|||||||
+4
-2
@@ -157,12 +157,13 @@ pub async fn fetch_and_save_by_date(
|
|||||||
account_id,
|
account_id,
|
||||||
mailbox.id,
|
mailbox.id,
|
||||||
&batch.0,
|
&batch.0,
|
||||||
|
account.max_email_size_bytes,
|
||||||
token.clone(),
|
token.clone(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(_) => {
|
Ok(processed) => {
|
||||||
current_processed += batch.1;
|
current_processed += processed;
|
||||||
DownloadState::update_folder_progress(
|
DownloadState::update_folder_progress(
|
||||||
account_id,
|
account_id,
|
||||||
mailbox.name.clone(),
|
mailbox.name.clone(),
|
||||||
@@ -290,6 +291,7 @@ pub async fn fetch_and_save_full_mailbox(
|
|||||||
page as u64,
|
page as u64,
|
||||||
page_size as u64,
|
page_size as u64,
|
||||||
&mailbox.encoded_name(),
|
&mailbox.encoded_name(),
|
||||||
|
account.max_email_size_bytes,
|
||||||
token.clone(),
|
token.clone(),
|
||||||
&mut max_uid,
|
&mut max_uid,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ use tokio_util::sync::CancellationToken;
|
|||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
const BODY_FETCH_COMMAND: &str = "(UID INTERNALDATE RFC822.SIZE BODY.PEEK[])";
|
const BODY_FETCH_COMMAND: &str = "(UID INTERNALDATE RFC822.SIZE BODY.PEEK[])";
|
||||||
|
const SIZE_ONLY_FETCH: &str = "(UID RFC822.SIZE)";
|
||||||
|
|
||||||
pub struct ImapExecutor;
|
pub struct ImapExecutor;
|
||||||
|
|
||||||
@@ -183,15 +184,16 @@ impl ImapExecutor {
|
|||||||
ErrorCode::InternalError
|
ErrorCode::InternalError
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Self::uid_batch_retrieve_emails(
|
let processed = Self::uid_batch_retrieve_emails(
|
||||||
session,
|
session,
|
||||||
account.id,
|
account.id,
|
||||||
mailbox.id,
|
mailbox.id,
|
||||||
&batch.0,
|
&batch.0,
|
||||||
|
account.max_email_size_bytes,
|
||||||
token.clone(),
|
token.clone(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
count += batch.1;
|
count += processed;
|
||||||
DownloadState::update_folder_progress(
|
DownloadState::update_folder_progress(
|
||||||
account.id,
|
account.id,
|
||||||
mailbox.name.clone(),
|
mailbox.name.clone(),
|
||||||
@@ -239,7 +241,9 @@ impl ImapExecutor {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut count = 0u64;
|
let mut count = 0u64;
|
||||||
|
let mut skipped = 0u64;
|
||||||
let mut max_uid: Option<u32> = None;
|
let mut max_uid: Option<u32> = None;
|
||||||
|
let size_limit = account.max_email_size_bytes.unwrap_or(DEFAULT_MAX_EMAIL_SIZE);
|
||||||
while let Some(fetch) = stream
|
while let Some(fetch) = stream
|
||||||
.try_next()
|
.try_next()
|
||||||
.await
|
.await
|
||||||
@@ -258,6 +262,20 @@ impl ImapExecutor {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let msg_size = fetch.size.unwrap_or(0) as u64;
|
||||||
|
if msg_size > 0 && msg_size > size_limit {
|
||||||
|
tracing::warn!(
|
||||||
|
account_id = account.id,
|
||||||
|
mailbox_id = mailbox.id,
|
||||||
|
uid = fetch.uid,
|
||||||
|
size = msg_size,
|
||||||
|
limit = size_limit,
|
||||||
|
"Skipping oversized email (streaming mode)"
|
||||||
|
);
|
||||||
|
skipped += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(uid) = fetch.uid {
|
if let Some(uid) = fetch.uid {
|
||||||
max_uid = Some(max_uid.unwrap_or(0).max(uid));
|
max_uid = Some(max_uid.unwrap_or(0).max(uid));
|
||||||
}
|
}
|
||||||
@@ -265,7 +283,8 @@ impl ImapExecutor {
|
|||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if count == 0 {
|
let total = count + skipped;
|
||||||
|
if total == 0 {
|
||||||
DownloadState::update_folder_progress(
|
DownloadState::update_folder_progress(
|
||||||
account.id,
|
account.id,
|
||||||
mailbox.name.clone(),
|
mailbox.name.clone(),
|
||||||
@@ -278,10 +297,14 @@ impl ImapExecutor {
|
|||||||
DownloadState::update_folder_progress(
|
DownloadState::update_folder_progress(
|
||||||
account.id,
|
account.id,
|
||||||
mailbox.name.clone(),
|
mailbox.name.clone(),
|
||||||
count,
|
total,
|
||||||
count,
|
count,
|
||||||
FolderStatus::Success,
|
FolderStatus::Success,
|
||||||
None,
|
if skipped > 0 {
|
||||||
|
Some(format!("{skipped} email(s) skipped due to size limit"))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,6 +319,7 @@ impl ImapExecutor {
|
|||||||
page: u64,
|
page: u64,
|
||||||
page_size: u64,
|
page_size: u64,
|
||||||
encoded_mailbox_name: &str,
|
encoded_mailbox_name: &str,
|
||||||
|
max_email_size_bytes: Option<u64>,
|
||||||
token: CancellationToken,
|
token: CancellationToken,
|
||||||
max_uid: &mut Option<u32>,
|
max_uid: &mut Option<u32>,
|
||||||
) -> BichonResult<usize> {
|
) -> BichonResult<usize> {
|
||||||
@@ -315,13 +339,52 @@ impl ImapExecutor {
|
|||||||
encoded_mailbox_name, sequence_set, page, page_size
|
encoded_mailbox_name, sequence_set, page, page_size
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut stream = session
|
let limit = max_email_size_bytes.unwrap_or(DEFAULT_MAX_EMAIL_SIZE);
|
||||||
.fetch(sequence_set.as_str(), BODY_FETCH_COMMAND)
|
|
||||||
|
// PASS 1: fetch only SIZE to identify oversized messages
|
||||||
|
let acceptable_uids = {
|
||||||
|
let mut size_stream = session
|
||||||
|
.fetch(sequence_set.as_str(), SIZE_ONLY_FETCH)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut uids: Vec<u32> = Vec::new();
|
||||||
|
while let Some(fetch) = size_stream.try_next().await.map_err(|e| {
|
||||||
|
raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed)
|
||||||
|
})? {
|
||||||
|
let uid = fetch.uid.unwrap_or(0);
|
||||||
|
let msg_size = fetch.size.unwrap_or(0) as u64;
|
||||||
|
if msg_size == 0 || msg_size <= limit {
|
||||||
|
uids.push(uid);
|
||||||
|
} else {
|
||||||
|
tracing::warn!(
|
||||||
|
account_id,
|
||||||
|
mailbox_id,
|
||||||
|
uid,
|
||||||
|
size = msg_size,
|
||||||
|
limit,
|
||||||
|
"Skipping oversized email"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uids
|
||||||
|
};
|
||||||
|
|
||||||
|
if acceptable_uids.is_empty() {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PASS 2: fetch bodies only for acceptable UIDs
|
||||||
|
let filtered = compress_uid_list(acceptable_uids);
|
||||||
|
let mut body_stream = session
|
||||||
|
.uid_fetch(&filtered, BODY_FETCH_COMMAND)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed))?;
|
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed))?;
|
||||||
|
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
while let Some(fetch) = stream
|
while let Some(fetch) = body_stream
|
||||||
.try_next()
|
.try_next()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed))?
|
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed))?
|
||||||
@@ -347,13 +410,55 @@ impl ImapExecutor {
|
|||||||
account_id: u64,
|
account_id: u64,
|
||||||
mailbox_id: u64,
|
mailbox_id: u64,
|
||||||
uid_set: &str,
|
uid_set: &str,
|
||||||
|
max_email_size_bytes: Option<u64>,
|
||||||
token: CancellationToken,
|
token: CancellationToken,
|
||||||
) -> BichonResult<()> {
|
) -> BichonResult<u64> {
|
||||||
let mut stream = session
|
let limit = max_email_size_bytes.unwrap_or(DEFAULT_MAX_EMAIL_SIZE);
|
||||||
.uid_fetch(uid_set, BODY_FETCH_COMMAND)
|
|
||||||
|
// PASS 1: fetch only SIZE to identify oversized messages
|
||||||
|
let acceptable_uids = {
|
||||||
|
let mut size_stream = session
|
||||||
|
.uid_fetch(uid_set, SIZE_ONLY_FETCH)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut uids: Vec<u32> = Vec::new();
|
||||||
|
while let Some(fetch) = size_stream.try_next().await.map_err(|e| {
|
||||||
|
raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed)
|
||||||
|
})? {
|
||||||
|
let uid = fetch.uid.unwrap_or(0);
|
||||||
|
let msg_size = fetch.size.unwrap_or(0) as u64;
|
||||||
|
if msg_size == 0 || msg_size <= limit {
|
||||||
|
uids.push(uid);
|
||||||
|
} else {
|
||||||
|
tracing::warn!(
|
||||||
|
account_id,
|
||||||
|
mailbox_id,
|
||||||
|
uid,
|
||||||
|
size = msg_size,
|
||||||
|
limit,
|
||||||
|
"Skipping oversized email"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uids
|
||||||
|
};
|
||||||
|
|
||||||
|
if acceptable_uids.is_empty() {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PASS 2: fetch bodies only for acceptable UIDs
|
||||||
|
let filtered = compress_uid_list(acceptable_uids);
|
||||||
|
let mut body_stream = session
|
||||||
|
.uid_fetch(&filtered, BODY_FETCH_COMMAND)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed))?;
|
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed))?;
|
||||||
while let Some(fetch) = stream
|
|
||||||
|
let mut count = 0u64;
|
||||||
|
while let Some(fetch) = body_stream
|
||||||
.try_next()
|
.try_next()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed))?
|
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::ImapCommandFailed))?
|
||||||
@@ -366,8 +471,9 @@ impl ImapExecutor {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
extract_envelope_and_store_it(fetch, account_id, mailbox_id).await?;
|
extract_envelope_and_store_it(fetch, account_id, mailbox_id).await?;
|
||||||
|
count += 1;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetches the raw RFC822 body of a single message by UID.
|
/// Fetches the raw RFC822 body of a single message by UID.
|
||||||
@@ -430,6 +536,7 @@ impl ImapExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const DEFAULT_BATCH_SIZE: u32 = 30;
|
pub const DEFAULT_BATCH_SIZE: u32 = 30;
|
||||||
|
pub const DEFAULT_MAX_EMAIL_SIZE: u64 = 100 * 1024 * 1024;
|
||||||
|
|
||||||
/// Compresses a sorted list of UIDs into an IMAP sequence-set string.
|
/// Compresses a sorted list of UIDs into an IMAP sequence-set string.
|
||||||
/// Consecutive UIDs become ranges (e.g. `1:5`), non-consecutive are
|
/// Consecutive UIDs become ranges (e.g. `1:5`), non-consecutive are
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ export interface AccountModel {
|
|||||||
download_folders: string[];
|
download_folders: string[];
|
||||||
download_interval_min?: number;
|
download_interval_min?: number;
|
||||||
download_batch_size?: number;
|
download_batch_size?: number;
|
||||||
|
max_email_size_bytes?: number;
|
||||||
created_by: number;
|
created_by: number;
|
||||||
created_user_name: string;
|
created_user_name: string;
|
||||||
created_user_email: string;
|
created_user_email: string;
|
||||||
|
|||||||
@@ -28,18 +28,54 @@ interface GithubLinkButtonProps {
|
|||||||
title?: string;
|
title?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CACHE_KEY = "github_stars_cache";
|
||||||
|
const CACHE_TTL = 6 * 60 * 60 * 1000; // 6 hours
|
||||||
|
|
||||||
|
interface StarsCache {
|
||||||
|
stars: number;
|
||||||
|
fetchedAt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCachedStars(repo: string): number | null {
|
||||||
|
try {
|
||||||
|
const raw = localStorage.getItem(`${CACHE_KEY}_${repo}`);
|
||||||
|
if (!raw) return null;
|
||||||
|
const cache: StarsCache = JSON.parse(raw);
|
||||||
|
if (Date.now() - cache.fetchedAt > CACHE_TTL) return null;
|
||||||
|
return cache.stars;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCachedStars(repo: string, stars: number) {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(
|
||||||
|
`${CACHE_KEY}_${repo}`,
|
||||||
|
JSON.stringify({ stars, fetchedAt: Date.now() })
|
||||||
|
);
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
|
||||||
export const GithubLinkButton: React.FC<GithubLinkButtonProps> = ({
|
export const GithubLinkButton: React.FC<GithubLinkButtonProps> = ({
|
||||||
href = "https://github.com/rustmailer/bichon",
|
href = "https://github.com/rustmailer/bichon",
|
||||||
repo = "rustmailer/bichon",
|
repo = "rustmailer/bichon",
|
||||||
size = 18,
|
size = 18,
|
||||||
title = "View on GitHub",
|
title = "View on GitHub",
|
||||||
}) => {
|
}) => {
|
||||||
const [stars, setStars] = useState<number | null>(null);
|
const [stars, setStars] = useState<number | null>(() => getCachedStars(repo));
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (stars !== null) return; // already have cached value, skip fetch
|
||||||
fetch(`https://api.github.com/repos/${repo}`)
|
fetch(`https://api.github.com/repos/${repo}`)
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(data => setStars(data.stargazers_count))
|
.then(data => {
|
||||||
|
const count = data.stargazers_count;
|
||||||
|
if (typeof count === "number") {
|
||||||
|
setStars(count);
|
||||||
|
setCachedStars(repo, count);
|
||||||
|
}
|
||||||
|
})
|
||||||
.catch(() => { });
|
.catch(() => { });
|
||||||
}, [repo]);
|
}, [repo]);
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,10 @@ export function AccountDetailDrawer({ open, onOpenChange, currentRow }: Props) {
|
|||||||
<span className="text-muted-foreground">{t('accounts.downloadBatchSize')}:</span>
|
<span className="text-muted-foreground">{t('accounts.downloadBatchSize')}:</span>
|
||||||
<span>{currentRow.download_batch_size}</span>
|
<span>{currentRow.download_batch_size}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
|
<span className="text-muted-foreground">{t('accounts.maxEmailSizeBytes')}:</span>
|
||||||
|
<span>{currentRow.max_email_size_bytes ? `${(currentRow.max_email_size_bytes / 1024 / 1024).toFixed(0)} MB` : t('accounts.maxEmailSizeBytesUnlimited')}</span>
|
||||||
|
</div>
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<span className="text-muted-foreground">{t('accounts.capabilities')}:</span>
|
<span className="text-muted-foreground">{t('accounts.capabilities')}:</span>
|
||||||
<code className="rounded-md bg-muted/50 px-2 py-1 text-sm border overflow-x-auto inline-block">
|
<code className="rounded-md bg-muted/50 px-2 py-1 text-sm border overflow-x-auto inline-block">
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export type Steps = [...Step[]];
|
|||||||
const getSteps = (t: (key: string) => string): Steps => [
|
const getSteps = (t: (key: string) => string): Steps => [
|
||||||
{ id: "step-1", name: t('accounts.steps.emailAddress'), fields: ["email", "account_name"] },
|
{ id: "step-1", name: t('accounts.steps.emailAddress'), fields: ["email", "account_name"] },
|
||||||
{ id: "step-2", name: t('accounts.steps.imap'), fields: ["imap", "use_dangerous", "login_name"] },
|
{ id: "step-2", name: t('accounts.steps.imap'), fields: ["imap", "use_dangerous", "login_name"] },
|
||||||
{ id: "step-3", name: t('accounts.steps.syncPreferences'), fields: ["enabled", "date_since", "date_before", "download_interval_min", "download_batch_size", "auto_download_new_mailboxes", "download_schedule"] },
|
{ id: "step-3", name: t('accounts.steps.syncPreferences'), fields: ["enabled", "date_since", "date_before", "download_interval_min", "download_batch_size", "max_email_size_bytes", "auto_download_new_mailboxes", "download_schedule"] },
|
||||||
{ id: "step-4", name: t('accounts.steps.summary'), fields: [] },
|
{ id: "step-4", name: t('accounts.steps.summary'), fields: [] },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -81,6 +81,7 @@ const defaultValues: Account = {
|
|||||||
date_before: undefined,
|
date_before: undefined,
|
||||||
download_interval_min: 60,
|
download_interval_min: 60,
|
||||||
download_batch_size: 30,
|
download_batch_size: 30,
|
||||||
|
max_email_size_bytes: 100 * 1024 * 1024,
|
||||||
auto_download_new_mailboxes: true,
|
auto_download_new_mailboxes: true,
|
||||||
download_schedule: undefined,
|
download_schedule: undefined,
|
||||||
};
|
};
|
||||||
@@ -111,6 +112,7 @@ const mapCurrentRowToFormValues = (currentRow: AccountModel): Account => {
|
|||||||
date_before: currentRow.date_before ?? undefined,
|
date_before: currentRow.date_before ?? undefined,
|
||||||
download_interval_min: currentRow.download_interval_min ?? 60,
|
download_interval_min: currentRow.download_interval_min ?? 60,
|
||||||
download_batch_size: currentRow.download_batch_size ?? 30,
|
download_batch_size: currentRow.download_batch_size ?? 30,
|
||||||
|
max_email_size_bytes: currentRow.max_email_size_bytes ?? 100 * 1024 * 1024,
|
||||||
auto_download_new_mailboxes: currentRow.auto_download_new_mailboxes ?? true,
|
auto_download_new_mailboxes: currentRow.auto_download_new_mailboxes ?? true,
|
||||||
download_schedule: currentRow.download_schedule ?? undefined,
|
download_schedule: currentRow.download_schedule ?? undefined,
|
||||||
};
|
};
|
||||||
@@ -193,6 +195,7 @@ export function AccountActionDialog({ currentRow, open, onOpenChange }: Props) {
|
|||||||
date_before: data.date_before,
|
date_before: data.date_before,
|
||||||
download_interval_min: data.download_interval_min,
|
download_interval_min: data.download_interval_min,
|
||||||
download_batch_size: data.download_batch_size,
|
download_batch_size: data.download_batch_size,
|
||||||
|
max_email_size_bytes: data.max_email_size_bytes,
|
||||||
auto_download_new_mailboxes: data.auto_download_new_mailboxes,
|
auto_download_new_mailboxes: data.auto_download_new_mailboxes,
|
||||||
download_schedule: data.download_schedule || null,
|
download_schedule: data.download_schedule || null,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -100,6 +100,13 @@ export const getAccountSchema = (isEdit: boolean, t: (key: string) => string) =>
|
|||||||
.max(200, {
|
.max(200, {
|
||||||
message: t('validation.singleRequestBatchSizeTooLarge'),
|
message: t('validation.singleRequestBatchSizeTooLarge'),
|
||||||
}),
|
}),
|
||||||
|
max_email_size_bytes: z
|
||||||
|
.number({
|
||||||
|
invalid_type_error: t('validation.maxEmailSizeMustBeNumber'),
|
||||||
|
})
|
||||||
|
.int()
|
||||||
|
.min(1 * 1024 * 1024, { message: t('validation.maxEmailSizeTooSmall') })
|
||||||
|
.max(100 * 1024 * 1024, { message: t('validation.maxEmailSizeTooLarge') }),
|
||||||
auto_download_new_mailboxes: z.boolean(),
|
auto_download_new_mailboxes: z.boolean(),
|
||||||
download_schedule: z
|
download_schedule: z
|
||||||
.string()
|
.string()
|
||||||
|
|||||||
@@ -392,6 +392,38 @@ export default function Step3() {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
control={control}
|
||||||
|
name="max_email_size_bytes"
|
||||||
|
render={({ field }) => {
|
||||||
|
const BYTES_PER_MB = 1024 * 1024;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t('accounts.maxEmailSizeBytes')}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
placeholder={t('accounts.maxEmailSizeBytesPlaceholder')}
|
||||||
|
className="flex-1"
|
||||||
|
value={field.value ? field.value / BYTES_PER_MB : ''}
|
||||||
|
onChange={(e) => {
|
||||||
|
const parsed = parseInt(e.target.value, 10);
|
||||||
|
field.onChange(isNaN(parsed) ? parsed : parsed * BYTES_PER_MB);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span className="text-sm text-muted-foreground whitespace-nowrap">MB</span>
|
||||||
|
</div>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
<FormDescription>
|
||||||
|
{t('accounts.maxEmailSizeBytesDescription')}
|
||||||
|
</FormDescription>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,11 @@ export default function Step4() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-xl">
|
<div className="rounded-xl">
|
||||||
<Accordion type="multiple" defaultValue={['email', 'account_name', 'login_name', 'imap', 'date_since', 'sync_interval', 'sync_scope', 'sync_batch_size', 'download_schedule']}>
|
<Accordion type="multiple" defaultValue={[
|
||||||
|
'email', 'account_name', 'login_name', 'imap', 'date_since',
|
||||||
|
'max_email_size_bytes', 'sync_interval', 'sync_scope',
|
||||||
|
'sync_batch_size', 'download_schedule'
|
||||||
|
]}>
|
||||||
<AccordionItem key="email" value="email">
|
<AccordionItem key="email" value="email">
|
||||||
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.email')}:</AccordionTrigger>
|
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.email')}:</AccordionTrigger>
|
||||||
<AccordionContent>{summaryData.email}</AccordionContent>
|
<AccordionContent>{summaryData.email}</AccordionContent>
|
||||||
@@ -164,6 +168,11 @@ export default function Step4() {
|
|||||||
<AccordionContent>{summaryData.download_batch_size}</AccordionContent>
|
<AccordionContent>{summaryData.download_batch_size}</AccordionContent>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
|
||||||
|
<AccordionItem key="max_email_size_bytes" value="max_email_size_bytes">
|
||||||
|
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.maxEmailSizeBytes')}:</AccordionTrigger>
|
||||||
|
<AccordionContent>{summaryData.max_email_size_bytes ? `${(summaryData.max_email_size_bytes / 1024 / 1024).toFixed(0)} MB` : t('accounts.maxEmailSizeBytesUnlimited')}</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
|
||||||
<AccordionItem key="download_schedule" value="download_schedule">
|
<AccordionItem key="download_schedule" value="download_schedule">
|
||||||
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.downloadSchedule')}:</AccordionTrigger>
|
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.downloadSchedule')}:</AccordionTrigger>
|
||||||
<AccordionContent>{summaryData.download_schedule || t('accounts.notAvailable')}</AccordionContent>
|
<AccordionContent>{summaryData.download_schedule || t('accounts.notAvailable')}</AccordionContent>
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "اترك فارغًا للاحتفاظ بكلمة المرور الحالية، أو أدخل كلمة مرور جديدة لتحديثها.",
|
"leaveEmptyToKeepExisting": "اترك فارغًا للاحتفاظ بكلمة المرور الحالية، أو أدخل كلمة مرور جديدة لتحديثها.",
|
||||||
"leaveEmptyToKeepPassword": "اترك فارغًا للاحتفاظ بكلمة المرور الحالية",
|
"leaveEmptyToKeepPassword": "اترك فارغًا للاحتفاظ بكلمة المرور الحالية",
|
||||||
"login_name": "اسم الدخول",
|
"login_name": "اسم الدخول",
|
||||||
|
"maxEmailSizeBytes": "الحد الأقصى لحجم البريد",
|
||||||
|
"maxEmailSizeBytesDescription": "سيتم تخطي الرسائل الأكبر من هذا الحجم. اتركه فارغاً لاستخدام الحد الافتراضي (100 ميجابايت).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "الافتراضي: 100 ميجابايت",
|
||||||
|
"maxEmailSizeBytesUnlimited": "الافتراضي: 100 ميجابايت",
|
||||||
"minutes": "دقائق",
|
"minutes": "دقائق",
|
||||||
"months": "أشهر",
|
"months": "أشهر",
|
||||||
"mustBeAtLeast1": "يجب أن يكون 1 على الأقل",
|
"mustBeAtLeast1": "يجب أن يكون 1 على الأقل",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "عنوان بريد إلكتروني غير صالح",
|
"invalidEmail": "عنوان بريد إلكتروني غير صالح",
|
||||||
"invalidUrl": "عنوان URL غير صالح",
|
"invalidUrl": "عنوان URL غير صالح",
|
||||||
|
"maxEmailSizeMustBeNumber": "يجب أن يكون الحد الأقصى لحجم البريد رقماً.",
|
||||||
|
"maxEmailSizeTooLarge": "يجب ألا يتجاوز الحد الأقصى لحجم البريد 100 ميجابايت.",
|
||||||
|
"maxEmailSizeTooSmall": "يجب أن يكون الحد الأقصى لحجم البريد 1 ميجابايت على الأقل.",
|
||||||
"passwordMinLength": "يجب أن تتكون كلمة المرور من {{min}} أحرف على الأقل",
|
"passwordMinLength": "يجب أن تتكون كلمة المرور من {{min}} أحرف على الأقل",
|
||||||
"passwordRequired": "كلمة المرور مطلوبة عندما تكون طريقة المصادقة هي كلمة المرور",
|
"passwordRequired": "كلمة المرور مطلوبة عندما تكون طريقة المصادقة هي كلمة المرور",
|
||||||
"pleaseEnterPassword": "الرجاء إدخال كلمة المرور الخاصة بك",
|
"pleaseEnterPassword": "الرجاء إدخال كلمة المرور الخاصة بك",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Lad stå tomt for at beholde den eksisterende adgangskode, eller indtast en ny for at opdatere den.",
|
"leaveEmptyToKeepExisting": "Lad stå tomt for at beholde den eksisterende adgangskode, eller indtast en ny for at opdatere den.",
|
||||||
"leaveEmptyToKeepPassword": "Lad stå tomt for at beholde nuværende adgangskode",
|
"leaveEmptyToKeepPassword": "Lad stå tomt for at beholde nuværende adgangskode",
|
||||||
"login_name": "Logindnavn",
|
"login_name": "Logindnavn",
|
||||||
|
"maxEmailSizeBytes": "Maks. e-mailstørrelse",
|
||||||
|
"maxEmailSizeBytesDescription": "E-mails større end dette vil blive oversprunget. Lad være tom for at bruge standarden (100 MB).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Standard: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Standard: 100 MB",
|
||||||
"minutes": "minutter",
|
"minutes": "minutter",
|
||||||
"months": "Måneder",
|
"months": "Måneder",
|
||||||
"mustBeAtLeast1": "Skal være mindst 1",
|
"mustBeAtLeast1": "Skal være mindst 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Ugyldig e-mailadresse",
|
"invalidEmail": "Ugyldig e-mailadresse",
|
||||||
"invalidUrl": "Ugyldig URL",
|
"invalidUrl": "Ugyldig URL",
|
||||||
|
"maxEmailSizeMustBeNumber": "Maks. e-mailstørrelse skal være et tal.",
|
||||||
|
"maxEmailSizeTooLarge": "Maks. e-mailstørrelse må ikke overstige 100 MB.",
|
||||||
|
"maxEmailSizeTooSmall": "Maks. e-mailstørrelse skal være mindst 1 MB.",
|
||||||
"passwordMinLength": "Adgangskoden skal være mindst {{min}} tegn lang",
|
"passwordMinLength": "Adgangskoden skal være mindst {{min}} tegn lang",
|
||||||
"passwordRequired": "Adgangskode er påkrævet, når godkendelsesmetoden er Adgangskode",
|
"passwordRequired": "Adgangskode er påkrævet, når godkendelsesmetoden er Adgangskode",
|
||||||
"pleaseEnterPassword": "Indtast venligst din adgangskode",
|
"pleaseEnterPassword": "Indtast venligst din adgangskode",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Leer lassen, um das bestehende Passwort beizubehalten, oder einen neuen Wert eingeben, um es zu aktualisieren.",
|
"leaveEmptyToKeepExisting": "Leer lassen, um das bestehende Passwort beizubehalten, oder einen neuen Wert eingeben, um es zu aktualisieren.",
|
||||||
"leaveEmptyToKeepPassword": "Leer lassen, um das aktuelle Passwort beizubehalten",
|
"leaveEmptyToKeepPassword": "Leer lassen, um das aktuelle Passwort beizubehalten",
|
||||||
"login_name": "Anmeldename",
|
"login_name": "Anmeldename",
|
||||||
|
"maxEmailSizeBytes": "Max. E-Mail-Größe",
|
||||||
|
"maxEmailSizeBytesDescription": "Größere E-Mails werden übersprungen. Leer lassen, um den Standardwert (100 MB) zu verwenden.",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Standard: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Standard: 100 MB",
|
||||||
"minutes": "Minuten",
|
"minutes": "Minuten",
|
||||||
"months": "Monate",
|
"months": "Monate",
|
||||||
"mustBeAtLeast1": "Muss mindestens 1 sein",
|
"mustBeAtLeast1": "Muss mindestens 1 sein",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Ungültige E-Mail-Adresse",
|
"invalidEmail": "Ungültige E-Mail-Adresse",
|
||||||
"invalidUrl": "Ungültige URL",
|
"invalidUrl": "Ungültige URL",
|
||||||
|
"maxEmailSizeMustBeNumber": "Die maximale E-Mail-Größe muss eine Zahl sein.",
|
||||||
|
"maxEmailSizeTooLarge": "Die maximale E-Mail-Größe darf 100 MB nicht überschreiten.",
|
||||||
|
"maxEmailSizeTooSmall": "Die maximale E-Mail-Größe muss mindestens 1 MB betragen.",
|
||||||
"passwordMinLength": "Das Passwort muss mindestens {{min}} Zeichen lang sein",
|
"passwordMinLength": "Das Passwort muss mindestens {{min}} Zeichen lang sein",
|
||||||
"passwordRequired": "Passwort ist erforderlich, wenn die Authentifizierungsmethode Passwort ist",
|
"passwordRequired": "Passwort ist erforderlich, wenn die Authentifizierungsmethode Passwort ist",
|
||||||
"pleaseEnterPassword": "Bitte geben Sie Ihr Passwort ein",
|
"pleaseEnterPassword": "Bitte geben Sie Ihr Passwort ein",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Leave empty to keep the existing password, or enter a new password to update it.",
|
"leaveEmptyToKeepExisting": "Leave empty to keep the existing password, or enter a new password to update it.",
|
||||||
"leaveEmptyToKeepPassword": "Leave empty to keep current password",
|
"leaveEmptyToKeepPassword": "Leave empty to keep current password",
|
||||||
"login_name": "Login Name",
|
"login_name": "Login Name",
|
||||||
|
"maxEmailSizeBytes": "Max email size",
|
||||||
|
"maxEmailSizeBytesDescription": "Emails larger than this will be skipped. Leave empty to use the default (100 MB).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Default: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Default: 100 MB",
|
||||||
"minutes": "minutes",
|
"minutes": "minutes",
|
||||||
"months": "Months",
|
"months": "Months",
|
||||||
"mustBeAtLeast1": "Must be at least 1",
|
"mustBeAtLeast1": "Must be at least 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Invalid email address",
|
"invalidEmail": "Invalid email address",
|
||||||
"invalidUrl": "Invalid URL",
|
"invalidUrl": "Invalid URL",
|
||||||
|
"maxEmailSizeMustBeNumber": "Max email size must be a number.",
|
||||||
|
"maxEmailSizeTooLarge": "Max email size must not exceed 100 MB.",
|
||||||
|
"maxEmailSizeTooSmall": "Max email size must be at least 1 MB.",
|
||||||
"passwordMinLength": "Password must be at least {{min}} characters long",
|
"passwordMinLength": "Password must be at least {{min}} characters long",
|
||||||
"passwordRequired": "Password is required when auth method is Password",
|
"passwordRequired": "Password is required when auth method is Password",
|
||||||
"pleaseEnterPassword": "Please enter your password",
|
"pleaseEnterPassword": "Please enter your password",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Deja vacío para mantener la contraseña existente, o introduce un nuevo valor para actualizarla.",
|
"leaveEmptyToKeepExisting": "Deja vacío para mantener la contraseña existente, o introduce un nuevo valor para actualizarla.",
|
||||||
"leaveEmptyToKeepPassword": "Deja vacío para mantener la contraseña actual",
|
"leaveEmptyToKeepPassword": "Deja vacío para mantener la contraseña actual",
|
||||||
"login_name": "Nombre de usuario",
|
"login_name": "Nombre de usuario",
|
||||||
|
"maxEmailSizeBytes": "Tamaño máx. de correo",
|
||||||
|
"maxEmailSizeBytesDescription": "Se omitirán los correos más grandes. Déjelo vacío para usar el valor predeterminado (100 MB).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Predeterminado: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Predeterminado: 100 MB",
|
||||||
"minutes": "minutos",
|
"minutes": "minutos",
|
||||||
"months": "Meses",
|
"months": "Meses",
|
||||||
"mustBeAtLeast1": "Debe ser al menos 1",
|
"mustBeAtLeast1": "Debe ser al menos 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Dirección de correo electrónico inválida",
|
"invalidEmail": "Dirección de correo electrónico inválida",
|
||||||
"invalidUrl": "URL inválida",
|
"invalidUrl": "URL inválida",
|
||||||
|
"maxEmailSizeMustBeNumber": "El tamaño máximo de correo debe ser un número.",
|
||||||
|
"maxEmailSizeTooLarge": "El tamaño máximo de correo no debe superar los 100 MB.",
|
||||||
|
"maxEmailSizeTooSmall": "El tamaño máximo de correo debe ser de al menos 1 MB.",
|
||||||
"passwordMinLength": "La contraseña debe tener al menos {{min}} caracteres",
|
"passwordMinLength": "La contraseña debe tener al menos {{min}} caracteres",
|
||||||
"passwordRequired": "La contraseña es obligatoria cuando el método de autenticación es Contraseña",
|
"passwordRequired": "La contraseña es obligatoria cuando el método de autenticación es Contraseña",
|
||||||
"pleaseEnterPassword": "Por favor, introduce tu contraseña",
|
"pleaseEnterPassword": "Por favor, introduce tu contraseña",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Jätä tyhjäksi säilyttääksesi olemassa olevan salasanan, tai syötä uusi päivittääksesi sen.",
|
"leaveEmptyToKeepExisting": "Jätä tyhjäksi säilyttääksesi olemassa olevan salasanan, tai syötä uusi päivittääksesi sen.",
|
||||||
"leaveEmptyToKeepPassword": "Jätä tyhjäksi säilyttääksesi nykyisen salasanan",
|
"leaveEmptyToKeepPassword": "Jätä tyhjäksi säilyttääksesi nykyisen salasanan",
|
||||||
"login_name": "Kirjautumisnimi",
|
"login_name": "Kirjautumisnimi",
|
||||||
|
"maxEmailSizeBytes": "Sähköpostin maksimikoko",
|
||||||
|
"maxEmailSizeBytesDescription": "Tätä suuremmat sähköpostit ohitetaan. Jätä tyhjäksi käyttääksesi oletusarvoa (100 MB).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Oletus: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Oletus: 100 MB",
|
||||||
"minutes": "minuuttia",
|
"minutes": "minuuttia",
|
||||||
"months": "Kuukautta",
|
"months": "Kuukautta",
|
||||||
"mustBeAtLeast1": "Täytyy olla vähintään 1",
|
"mustBeAtLeast1": "Täytyy olla vähintään 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Virheellinen sähköpostiosoite",
|
"invalidEmail": "Virheellinen sähköpostiosoite",
|
||||||
"invalidUrl": "Virheellinen URL-osoite",
|
"invalidUrl": "Virheellinen URL-osoite",
|
||||||
|
"maxEmailSizeMustBeNumber": "Sähköpostin maksimikoon on oltava numero.",
|
||||||
|
"maxEmailSizeTooLarge": "Sähköpostin maksimikoko ei saa ylittää 100 megatavua.",
|
||||||
|
"maxEmailSizeTooSmall": "Sähköpostin maksimikoon on oltava vähintään 1 MB.",
|
||||||
"passwordMinLength": "Salasanan on oltava vähintään {{min}} merkkiä pitkä",
|
"passwordMinLength": "Salasanan on oltava vähintään {{min}} merkkiä pitkä",
|
||||||
"passwordRequired": "Salasana on pakollinen, kun todennusmenetelmä on Salasana",
|
"passwordRequired": "Salasana on pakollinen, kun todennusmenetelmä on Salasana",
|
||||||
"pleaseEnterPassword": "Syötä salasanasi",
|
"pleaseEnterPassword": "Syötä salasanasi",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Laissez vide pour conserver le mot de passe existant, ou entrez-en un nouveau pour le mettre à jour.",
|
"leaveEmptyToKeepExisting": "Laissez vide pour conserver le mot de passe existant, ou entrez-en un nouveau pour le mettre à jour.",
|
||||||
"leaveEmptyToKeepPassword": "Laisser vide pour conserver le mot de passe actuel",
|
"leaveEmptyToKeepPassword": "Laisser vide pour conserver le mot de passe actuel",
|
||||||
"login_name": "Nom de connexion",
|
"login_name": "Nom de connexion",
|
||||||
|
"maxEmailSizeBytes": "Taille max. des e-mails",
|
||||||
|
"maxEmailSizeBytesDescription": "Les e-mails plus grands seront ignorés. Laisser vide pour utiliser la valeur par défaut (100 MB).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Par défaut : 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Par défaut : 100 MB",
|
||||||
"minutes": "minutes",
|
"minutes": "minutes",
|
||||||
"months": "Mois",
|
"months": "Mois",
|
||||||
"mustBeAtLeast1": "Doit être au moins 1",
|
"mustBeAtLeast1": "Doit être au moins 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Adresse e-mail non valide",
|
"invalidEmail": "Adresse e-mail non valide",
|
||||||
"invalidUrl": "URL non valide",
|
"invalidUrl": "URL non valide",
|
||||||
|
"maxEmailSizeMustBeNumber": "La taille maximale des e-mails doit être un nombre.",
|
||||||
|
"maxEmailSizeTooLarge": "La taille maximale des e-mails ne doit pas dépasser 100 MB.",
|
||||||
|
"maxEmailSizeTooSmall": "La taille maximale des e-mails doit être d'au moins 1 MB.",
|
||||||
"passwordMinLength": "Le mot de passe doit contenir au moins {{min}} caractères",
|
"passwordMinLength": "Le mot de passe doit contenir au moins {{min}} caractères",
|
||||||
"passwordRequired": "Le mot de passe est obligatoire lorsque la méthode d'authentification est Mot de passe",
|
"passwordRequired": "Le mot de passe est obligatoire lorsque la méthode d'authentification est Mot de passe",
|
||||||
"pleaseEnterPassword": "Veuillez entrer votre mot de passe",
|
"pleaseEnterPassword": "Veuillez entrer votre mot de passe",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Lascia vuoto per mantenere la password esistente, o inseriscine una nuova per aggiornarla.",
|
"leaveEmptyToKeepExisting": "Lascia vuoto per mantenere la password esistente, o inseriscine una nuova per aggiornarla.",
|
||||||
"leaveEmptyToKeepPassword": "Lascia vuoto per mantenere la password attuale",
|
"leaveEmptyToKeepPassword": "Lascia vuoto per mantenere la password attuale",
|
||||||
"login_name": "Nome di accesso",
|
"login_name": "Nome di accesso",
|
||||||
|
"maxEmailSizeBytes": "Dimensione massima email",
|
||||||
|
"maxEmailSizeBytesDescription": "Le email più grandi saranno ignorate. Lascia vuoto per utilizzare il valore predefinito (100 MB).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Predefinito: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Predefinito: 100 MB",
|
||||||
"minutes": "minuti",
|
"minutes": "minuti",
|
||||||
"months": "Mesi",
|
"months": "Mesi",
|
||||||
"mustBeAtLeast1": "Deve essere almeno 1",
|
"mustBeAtLeast1": "Deve essere almeno 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Indirizzo email non valido",
|
"invalidEmail": "Indirizzo email non valido",
|
||||||
"invalidUrl": "URL non valido",
|
"invalidUrl": "URL non valido",
|
||||||
|
"maxEmailSizeMustBeNumber": "La dimensione massima dell'email deve essere un numero.",
|
||||||
|
"maxEmailSizeTooLarge": "La dimensione massima dell'email non deve superare i 100 MB.",
|
||||||
|
"maxEmailSizeTooSmall": "La dimensione massima dell'email deve essere di almeno 1 MB.",
|
||||||
"passwordMinLength": "La password deve contenere almeno {{min}} caratteri",
|
"passwordMinLength": "La password deve contenere almeno {{min}} caratteri",
|
||||||
"passwordRequired": "La password è obbligatoria quando il metodo di autenticazione è Password",
|
"passwordRequired": "La password è obbligatoria quando il metodo di autenticazione è Password",
|
||||||
"pleaseEnterPassword": "Inserisci la tua password",
|
"pleaseEnterPassword": "Inserisci la tua password",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "既存のパスワードを保持する場合は空欄にしてください。更新する場合は新しいパスワードを入力してください。",
|
"leaveEmptyToKeepExisting": "既存のパスワードを保持する場合は空欄にしてください。更新する場合は新しいパスワードを入力してください。",
|
||||||
"leaveEmptyToKeepPassword": "現在のパスワードを保持する場合は空欄にしてください",
|
"leaveEmptyToKeepPassword": "現在のパスワードを保持する場合は空欄にしてください",
|
||||||
"login_name": "ログイン名",
|
"login_name": "ログイン名",
|
||||||
|
"maxEmailSizeBytes": "最大メールサイズ",
|
||||||
|
"maxEmailSizeBytesDescription": "これより大きいメールはスキップされます。空欄にするとデフォルト(100 MB)が使用されます。",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "デフォルト:100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "デフォルト:100 MB",
|
||||||
"minutes": "分",
|
"minutes": "分",
|
||||||
"months": "月",
|
"months": "月",
|
||||||
"mustBeAtLeast1": "1以上である必要があります",
|
"mustBeAtLeast1": "1以上である必要があります",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "無効なメールアドレスです",
|
"invalidEmail": "無効なメールアドレスです",
|
||||||
"invalidUrl": "無効なURLです",
|
"invalidUrl": "無効なURLです",
|
||||||
|
"maxEmailSizeMustBeNumber": "最大メールサイズは数値で入力してください。",
|
||||||
|
"maxEmailSizeTooLarge": "最大メールサイズは 100 MB 以下にしてください。",
|
||||||
|
"maxEmailSizeTooSmall": "最大メールサイズは 1 MB 以上にしてください。",
|
||||||
"passwordMinLength": "パスワードは{{min}}文字以上である必要があります",
|
"passwordMinLength": "パスワードは{{min}}文字以上である必要があります",
|
||||||
"passwordRequired": "認証方式がパスワードの場合、パスワードは必須です",
|
"passwordRequired": "認証方式がパスワードの場合、パスワードは必須です",
|
||||||
"pleaseEnterPassword": "パスワードを入力してください",
|
"pleaseEnterPassword": "パスワードを入力してください",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "기존 비밀번호를 유지하려면 비워 두십시오. 업데이트할 경우에만 새 비밀번호를 입력하십시오.",
|
"leaveEmptyToKeepExisting": "기존 비밀번호를 유지하려면 비워 두십시오. 업데이트할 경우에만 새 비밀번호를 입력하십시오.",
|
||||||
"leaveEmptyToKeepPassword": "현재 비밀번호를 유지하려면 비워 두십시오",
|
"leaveEmptyToKeepPassword": "현재 비밀번호를 유지하려면 비워 두십시오",
|
||||||
"login_name": "로그인 이름",
|
"login_name": "로그인 이름",
|
||||||
|
"maxEmailSizeBytes": "최대 이메일 크기",
|
||||||
|
"maxEmailSizeBytesDescription": "이보다 큰 이메일은 건너뜁니다. 기본값(100 MB)을 사용하려면 비워두세요.",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "기본값: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "기본값: 100 MB",
|
||||||
"minutes": "분",
|
"minutes": "분",
|
||||||
"months": "개월",
|
"months": "개월",
|
||||||
"mustBeAtLeast1": "최소 1 이상이어야 합니다",
|
"mustBeAtLeast1": "최소 1 이상이어야 합니다",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "유효하지 않은 이메일 주소",
|
"invalidEmail": "유효하지 않은 이메일 주소",
|
||||||
"invalidUrl": "유효하지 않은 URL",
|
"invalidUrl": "유효하지 않은 URL",
|
||||||
|
"maxEmailSizeMustBeNumber": "최대 이메일 크기는 숫자여야 합니다.",
|
||||||
|
"maxEmailSizeTooLarge": "최대 이메일 크기는 100 MB를 초과할 수 없습니다.",
|
||||||
|
"maxEmailSizeTooSmall": "최대 이메일 크기는 최소 1 MB여야 합니다.",
|
||||||
"passwordMinLength": "비밀번호는 {{min}}자 이상이어야 합니다",
|
"passwordMinLength": "비밀번호는 {{min}}자 이상이어야 합니다",
|
||||||
"passwordRequired": "인증 방법이 비밀번호인 경우 비밀번호는 필수입니다",
|
"passwordRequired": "인증 방법이 비밀번호인 경우 비밀번호는 필수입니다",
|
||||||
"pleaseEnterPassword": "비밀번호를 입력하십시오",
|
"pleaseEnterPassword": "비밀번호를 입력하십시오",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Laat leeg om het bestaande wachtwoord te behouden, of voer een nieuw wachtwoord in om het bij te werken.",
|
"leaveEmptyToKeepExisting": "Laat leeg om het bestaande wachtwoord te behouden, of voer een nieuw wachtwoord in om het bij te werken.",
|
||||||
"leaveEmptyToKeepPassword": "Laat leeg om huidig wachtwoord te behouden",
|
"leaveEmptyToKeepPassword": "Laat leeg om huidig wachtwoord te behouden",
|
||||||
"login_name": "Inlognaam",
|
"login_name": "Inlognaam",
|
||||||
|
"maxEmailSizeBytes": "Max. e-mailgrootte",
|
||||||
|
"maxEmailSizeBytesDescription": "E-mails groter dan dit worden overgeslagen. Laat leeg om de standaard (100 MB) te gebruiken.",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Standaard: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Standaard: 100 MB",
|
||||||
"minutes": "minuten",
|
"minutes": "minuten",
|
||||||
"months": "Maanden",
|
"months": "Maanden",
|
||||||
"mustBeAtLeast1": "Moet ten minste 1 zijn",
|
"mustBeAtLeast1": "Moet ten minste 1 zijn",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Ongeldig e-mailadres",
|
"invalidEmail": "Ongeldig e-mailadres",
|
||||||
"invalidUrl": "Ongeldige URL",
|
"invalidUrl": "Ongeldige URL",
|
||||||
|
"maxEmailSizeMustBeNumber": "Maximale e-mailgrootte moet un nummer zijn.",
|
||||||
|
"maxEmailSizeTooLarge": "Maximale e-mailgrootte mag niet groter zijn dan 100 MB.",
|
||||||
|
"maxEmailSizeTooSmall": "Maximale e-mailgrootte moet minstens 1 MB zijn.",
|
||||||
"passwordMinLength": "Wachtwoord moet ten minste {{min}} tekens lang zijn",
|
"passwordMinLength": "Wachtwoord moet ten minste {{min}} tekens lang zijn",
|
||||||
"passwordRequired": "Wachtwoord is vereist wanneer de authenticatiemethode Wachtwoord is",
|
"passwordRequired": "Wachtwoord is vereist wanneer de authenticatiemethode Wachtwoord is",
|
||||||
"pleaseEnterPassword": "Voer uw wachtwoord in",
|
"pleaseEnterPassword": "Voer uw wachtwoord in",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "La stå tomt for å beholde det eksisterende passordet, eller skriv inn et nytt passord for å oppdatere det.",
|
"leaveEmptyToKeepExisting": "La stå tomt for å beholde det eksisterende passordet, eller skriv inn et nytt passord for å oppdatere det.",
|
||||||
"leaveEmptyToKeepPassword": "La stå tomt for å beholde nåværende passord",
|
"leaveEmptyToKeepPassword": "La stå tomt for å beholde nåværende passord",
|
||||||
"login_name": "Påloggingsnavn",
|
"login_name": "Påloggingsnavn",
|
||||||
|
"maxEmailSizeBytes": "Maks. e-poststørrelse",
|
||||||
|
"maxEmailSizeBytesDescription": "E-poster større enn dette vil bli hoppet over. La stå tom for å bruke standarden (100 MB).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Standard: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Standard: 100 MB",
|
||||||
"minutes": "minutter",
|
"minutes": "minutter",
|
||||||
"months": "Måneder",
|
"months": "Måneder",
|
||||||
"mustBeAtLeast1": "Må være minst 1",
|
"mustBeAtLeast1": "Må være minst 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Ugyldig e-postadresse",
|
"invalidEmail": "Ugyldig e-postadresse",
|
||||||
"invalidUrl": "Ugyldig URL",
|
"invalidUrl": "Ugyldig URL",
|
||||||
|
"maxEmailSizeMustBeNumber": "Maks. e-poststørrelse må være et tall.",
|
||||||
|
"maxEmailSizeTooLarge": "Maks. e-poststørrelse må ikke overstige 100 MB.",
|
||||||
|
"maxEmailSizeTooSmall": "Maks. e-poststørrelse må være minst 1 MB.",
|
||||||
"passwordMinLength": "Passordet må være minst {{min}} tegn langt",
|
"passwordMinLength": "Passordet må være minst {{min}} tegn langt",
|
||||||
"passwordRequired": "Passord er påkrevd når autentiseringsmetoden er Passord",
|
"passwordRequired": "Passord er påkrevd når autentiseringsmetoden er Passord",
|
||||||
"pleaseEnterPassword": "Vennligst skriv inn passordet ditt",
|
"pleaseEnterPassword": "Vennligst skriv inn passordet ditt",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Pozostaw to pole puste, jeśli chcesz zachować dotychczasowe hasło lub wpisz nowe, aby zaktualizować.",
|
"leaveEmptyToKeepExisting": "Pozostaw to pole puste, jeśli chcesz zachować dotychczasowe hasło lub wpisz nowe, aby zaktualizować.",
|
||||||
"leaveEmptyToKeepPassword": "Pozostaw to pole puste, jeśli chcesz zachować dotychczasowe hasło",
|
"leaveEmptyToKeepPassword": "Pozostaw to pole puste, jeśli chcesz zachować dotychczasowe hasło",
|
||||||
"login_name": "Login",
|
"login_name": "Login",
|
||||||
|
"maxEmailSizeBytes": "Maks. rozmiar e-maila",
|
||||||
|
"maxEmailSizeBytesDescription": "Większe wiadomości zostaną pominięte. Pozostaw puste, aby użyć domyślnego limitu (100 MB).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Domyślnie: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Domyślnie: 100 MB",
|
||||||
"minutes": "minut",
|
"minutes": "minut",
|
||||||
"months": "Miesiące",
|
"months": "Miesiące",
|
||||||
"mustBeAtLeast1": "Nie mniej jak 1",
|
"mustBeAtLeast1": "Nie mniej jak 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Niewłaściwy adres email",
|
"invalidEmail": "Niewłaściwy adres email",
|
||||||
"invalidUrl": "Niewłaściwy URL",
|
"invalidUrl": "Niewłaściwy URL",
|
||||||
|
"maxEmailSizeMustBeNumber": "Maksymalny rozmiar e-maila musi być liczbą.",
|
||||||
|
"maxEmailSizeTooLarge": "Maksymalny rozmiar e-maila nie może przekraczać 100 MB.",
|
||||||
|
"maxEmailSizeTooSmall": "Maksymalny rozmiar e-maila musi wynosić co najmniej 1 MB.",
|
||||||
"passwordMinLength": "Hasło musi posiadać conajmniej {{min}} znaków",
|
"passwordMinLength": "Hasło musi posiadać conajmniej {{min}} znaków",
|
||||||
"passwordRequired": "Hasło jest wymagane, gdy metodą uwierzytelniania jest hasło",
|
"passwordRequired": "Hasło jest wymagane, gdy metodą uwierzytelniania jest hasło",
|
||||||
"pleaseEnterPassword": "Proszę podać hasło",
|
"pleaseEnterPassword": "Proszę podać hasło",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Deixe vazio para manter a senha existente. Insira a nova senha apenas se estiver atualizando.",
|
"leaveEmptyToKeepExisting": "Deixe vazio para manter a senha existente. Insira a nova senha apenas se estiver atualizando.",
|
||||||
"leaveEmptyToKeepPassword": "Deixe vazio para manter a senha atual",
|
"leaveEmptyToKeepPassword": "Deixe vazio para manter a senha atual",
|
||||||
"login_name": "Nome de login",
|
"login_name": "Nome de login",
|
||||||
|
"maxEmailSizeBytes": "Tamanho máx. do email",
|
||||||
|
"maxEmailSizeBytesDescription": "Emails maiores do que isso serão ignorados. Deixe vazio para usar o padrão (100 MB).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Padrão: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Padrão: 100 MB",
|
||||||
"minutes": "minutos",
|
"minutes": "minutos",
|
||||||
"months": "Meses",
|
"months": "Meses",
|
||||||
"mustBeAtLeast1": "Deve ser pelo menos 1",
|
"mustBeAtLeast1": "Deve ser pelo menos 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Endereço de email inválido",
|
"invalidEmail": "Endereço de email inválido",
|
||||||
"invalidUrl": "URL inválido",
|
"invalidUrl": "URL inválido",
|
||||||
|
"maxEmailSizeMustBeNumber": "O tamanho máximo do email deve ser um número.",
|
||||||
|
"maxEmailSizeTooLarge": "O tamanho máximo do email não deve exceder 100 MB.",
|
||||||
|
"maxEmailSizeTooSmall": "O tamanho máximo do email deve ser de pelo menos 1 MB.",
|
||||||
"passwordMinLength": "A senha deve ter pelo menos {{min}} caracteres",
|
"passwordMinLength": "A senha deve ter pelo menos {{min}} caracteres",
|
||||||
"passwordRequired": "A senha é obrigatória se o método de autenticação for Senha",
|
"passwordRequired": "A senha é obrigatória se o método de autenticação for Senha",
|
||||||
"pleaseEnterPassword": "Por favor, insira a senha",
|
"pleaseEnterPassword": "Por favor, insira a senha",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Оставьте пустым, чтобы сохранить существующий пароль, или введите новый для обновления.",
|
"leaveEmptyToKeepExisting": "Оставьте пустым, чтобы сохранить существующий пароль, или введите новый для обновления.",
|
||||||
"leaveEmptyToKeepPassword": "Оставьте пустым, чтобы сохранить текущий пароль",
|
"leaveEmptyToKeepPassword": "Оставьте пустым, чтобы сохранить текущий пароль",
|
||||||
"login_name": "Имя для входа",
|
"login_name": "Имя для входа",
|
||||||
|
"maxEmailSizeBytes": "Макс. размер письма",
|
||||||
|
"maxEmailSizeBytesDescription": "Письма больше этого размера будут пропущены. Оставьте пустым для использования значения по умолчанию (100 МБ).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "По умолчанию: 100 МБ",
|
||||||
|
"maxEmailSizeBytesUnlimited": "По умолчанию: 100 МБ",
|
||||||
"minutes": "минут",
|
"minutes": "минут",
|
||||||
"months": "Месяцы",
|
"months": "Месяцы",
|
||||||
"mustBeAtLeast1": "Должно быть не менее 1",
|
"mustBeAtLeast1": "Должно быть не менее 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Неверный адрес электронной почты",
|
"invalidEmail": "Неверный адрес электронной почты",
|
||||||
"invalidUrl": "Неверный URL",
|
"invalidUrl": "Неверный URL",
|
||||||
|
"maxEmailSizeMustBeNumber": "Максимальный размер письма должен быть числом.",
|
||||||
|
"maxEmailSizeTooLarge": "Максимальный размер письма не должен превышать 100 МБ.",
|
||||||
|
"maxEmailSizeTooSmall": "Максимальный размер письма должен быть не менее 1 МБ.",
|
||||||
"passwordMinLength": "Пароль должен быть не менее {{min}} символов",
|
"passwordMinLength": "Пароль должен быть не менее {{min}} символов",
|
||||||
"passwordRequired": "Пароль обязателен, когда метод авторизации - Пароль",
|
"passwordRequired": "Пароль обязателен, когда метод авторизации - Пароль",
|
||||||
"pleaseEnterPassword": "Пожалуйста, введите ваш пароль",
|
"pleaseEnterPassword": "Пожалуйста, введите ваш пароль",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "Lämna tomt för att behålla det befintliga lösenordet, eller ange ett nytt för att uppdatera det.",
|
"leaveEmptyToKeepExisting": "Lämna tomt för att behålla det befintliga lösenordet, eller ange ett nytt för att uppdatera det.",
|
||||||
"leaveEmptyToKeepPassword": "Lämna tomt för att behålla nuvarande lösenord",
|
"leaveEmptyToKeepPassword": "Lämna tomt för att behålla nuvarande lösenord",
|
||||||
"login_name": "Inloggningsnamn",
|
"login_name": "Inloggningsnamn",
|
||||||
|
"maxEmailSizeBytes": "Max e-poststorlek",
|
||||||
|
"maxEmailSizeBytesDescription": "E-post större än detta kommer att hoppas över. Lämna tomt för att använda standard (100 MB).",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "Standard: 100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "Standard: 100 MB",
|
||||||
"minutes": "minuter",
|
"minutes": "minuter",
|
||||||
"months": "Månader",
|
"months": "Månader",
|
||||||
"mustBeAtLeast1": "Måste vara minst 1",
|
"mustBeAtLeast1": "Måste vara minst 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "Ogiltig e-postadress",
|
"invalidEmail": "Ogiltig e-postadress",
|
||||||
"invalidUrl": "Ogiltig URL",
|
"invalidUrl": "Ogiltig URL",
|
||||||
|
"maxEmailSizeMustBeNumber": "Max e-poststorlek måste vara ett nummer.",
|
||||||
|
"maxEmailSizeTooLarge": "Max e-poststorlek får inte överstiga 100 MB.",
|
||||||
|
"maxEmailSizeTooSmall": "Max e-poststorlek måste vara minst 1 MB.",
|
||||||
"passwordMinLength": "Lösenordet måste vara minst {{min}} tecken långt",
|
"passwordMinLength": "Lösenordet måste vara minst {{min}} tecken långt",
|
||||||
"passwordRequired": "Lösenord krävs när autentiseringsmetoden är Lösenord",
|
"passwordRequired": "Lösenord krävs när autentiseringsmetoden är Lösenord",
|
||||||
"pleaseEnterPassword": "Vänligen ange ditt lösenord",
|
"pleaseEnterPassword": "Vänligen ange ditt lösenord",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "保留現有密碼請留空。若要更新,請輸入新密碼。",
|
"leaveEmptyToKeepExisting": "保留現有密碼請留空。若要更新,請輸入新密碼。",
|
||||||
"leaveEmptyToKeepPassword": "保留現有密碼請留空",
|
"leaveEmptyToKeepPassword": "保留現有密碼請留空",
|
||||||
"login_name": "登入名稱",
|
"login_name": "登入名稱",
|
||||||
|
"maxEmailSizeBytes": "最大郵件大小",
|
||||||
|
"maxEmailSizeBytesDescription": "超出此大小的郵件將被跳過。留空則使用預設值(100 MB)。",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "預設:100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "預設:100 MB",
|
||||||
"minutes": "分鐘",
|
"minutes": "分鐘",
|
||||||
"months": "月",
|
"months": "月",
|
||||||
"mustBeAtLeast1": "必須大於或等於 1",
|
"mustBeAtLeast1": "必須大於或等於 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "無效的電子郵件地址",
|
"invalidEmail": "無效的電子郵件地址",
|
||||||
"invalidUrl": "無效的網址",
|
"invalidUrl": "無效的網址",
|
||||||
|
"maxEmailSizeMustBeNumber": "最大郵件大小必須是數字。",
|
||||||
|
"maxEmailSizeTooLarge": "最大郵件大小不能超過 100 MB。",
|
||||||
|
"maxEmailSizeTooSmall": "最大郵件大小不能小於 1 MB。",
|
||||||
"passwordMinLength": "密碼長度必須至少 {{min}} 個字元",
|
"passwordMinLength": "密碼長度必須至少 {{min}} 個字元",
|
||||||
"passwordRequired": "如果驗證方法是密碼,則密碼為必填項",
|
"passwordRequired": "如果驗證方法是密碼,則密碼為必填項",
|
||||||
"pleaseEnterPassword": "請輸入密碼",
|
"pleaseEnterPassword": "請輸入密碼",
|
||||||
|
|||||||
@@ -208,6 +208,10 @@
|
|||||||
"leaveEmptyToKeepExisting": "留空以保持现有密码,或输入新密码进行更新。",
|
"leaveEmptyToKeepExisting": "留空以保持现有密码,或输入新密码进行更新。",
|
||||||
"leaveEmptyToKeepPassword": "留空以保持当前密码",
|
"leaveEmptyToKeepPassword": "留空以保持当前密码",
|
||||||
"login_name": "登录名",
|
"login_name": "登录名",
|
||||||
|
"maxEmailSizeBytes": "最大邮件大小",
|
||||||
|
"maxEmailSizeBytesDescription": "超出此大小的邮件将被跳过。留空则使用默认值(100 MB)。",
|
||||||
|
"maxEmailSizeBytesPlaceholder": "默认:100 MB",
|
||||||
|
"maxEmailSizeBytesUnlimited": "默认:100 MB",
|
||||||
"minutes": "分钟",
|
"minutes": "分钟",
|
||||||
"months": "月",
|
"months": "月",
|
||||||
"mustBeAtLeast1": "必须至少为 1",
|
"mustBeAtLeast1": "必须至少为 1",
|
||||||
@@ -1681,6 +1685,9 @@
|
|||||||
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
"invalidCronExpression": "Invalid cron expression. Must be 6 fields: second minute hour day-of-month month day-of-week (e.g. '0 0 0 * * *')",
|
||||||
"invalidEmail": "无效的电子邮件地址",
|
"invalidEmail": "无效的电子邮件地址",
|
||||||
"invalidUrl": "无效的 URL",
|
"invalidUrl": "无效的 URL",
|
||||||
|
"maxEmailSizeMustBeNumber": "最大邮件大小必须是数字。",
|
||||||
|
"maxEmailSizeTooLarge": "最大邮件大小不能超过 100 MB。",
|
||||||
|
"maxEmailSizeTooSmall": "最大邮件大小不能小于 1 MB。",
|
||||||
"passwordMinLength": "密码长度至少为 {{min}} 个字符",
|
"passwordMinLength": "密码长度至少为 {{min}} 个字符",
|
||||||
"passwordRequired": "当认证方法为密码时,密码为必填项",
|
"passwordRequired": "当认证方法为密码时,密码为必填项",
|
||||||
"pleaseEnterPassword": "请输入您的密码",
|
"pleaseEnterPassword": "请输入您的密码",
|
||||||
|
|||||||
Reference in New Issue
Block a user