mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
feat: added Cron scheduling for email downloads #211
This commit is contained in:
Generated
+21
@@ -346,6 +346,7 @@ dependencies = [
|
|||||||
"bytes 1.11.1",
|
"bytes 1.11.1",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
"cron",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"deunicode",
|
"deunicode",
|
||||||
"email_address",
|
"email_address",
|
||||||
@@ -875,6 +876,17 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cron"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5877d3fbf742507b66bc2a1945106bd30dd8504019d596901ddd012a4dd01740"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"once_cell",
|
||||||
|
"winnow 0.6.26",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.15"
|
version = "0.5.15"
|
||||||
@@ -5611,6 +5623,15 @@ version = "0.53.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.6.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.7.15"
|
version = "0.7.15"
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ impl From<AccountV3> for AccountModel {
|
|||||||
imap_quota_window: None,
|
imap_quota_window: None,
|
||||||
imap_quota_bytes: None,
|
imap_quota_bytes: None,
|
||||||
auto_download_new_mailboxes: None,
|
auto_download_new_mailboxes: None,
|
||||||
|
download_schedule: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,5 +69,6 @@ tokio-util.workspace = true
|
|||||||
whichlang = "0.1.1"
|
whichlang = "0.1.1"
|
||||||
deunicode = "1.6.2"
|
deunicode = "1.6.2"
|
||||||
scopeguard = "1.2.0"
|
scopeguard = "1.2.0"
|
||||||
|
cron = "0.15"
|
||||||
quick-xml = { version = "0.40.0", features = ["serialize"] }
|
quick-xml = { version = "0.40.0", features = ["serialize"] }
|
||||||
hickory-resolver = "0.26.0-alpha.1"
|
hickory-resolver = "0.26.0-alpha.1"
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ pub struct Account {
|
|||||||
pub imap_quota_bytes: Option<u64>,
|
pub imap_quota_bytes: Option<u64>,
|
||||||
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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemDbModel for Account {
|
impl MemDbModel for Account {
|
||||||
@@ -133,6 +134,7 @@ impl Account {
|
|||||||
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,
|
||||||
imap_quota_window: request.imap_quota_window,
|
imap_quota_window: request.imap_quota_window,
|
||||||
|
download_schedule: request.download_schedule,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,6 +441,12 @@ impl Account {
|
|||||||
if let Some(auto_download_new_mailboxes) = request.auto_download_new_mailboxes {
|
if let Some(auto_download_new_mailboxes) = request.auto_download_new_mailboxes {
|
||||||
new.auto_download_new_mailboxes = Some(auto_download_new_mailboxes);
|
new.auto_download_new_mailboxes = Some(auto_download_new_mailboxes);
|
||||||
}
|
}
|
||||||
|
if let Some(download_schedule) = request.download_schedule {
|
||||||
|
new.download_schedule = Some(download_schedule);
|
||||||
|
}
|
||||||
|
if request.clear_download_schedule == Some(true) {
|
||||||
|
new.download_schedule = None;
|
||||||
|
}
|
||||||
new.updated_at = utc_now!();
|
new.updated_at = utc_now!();
|
||||||
Ok(new)
|
Ok(new)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::account::entity::ImapConfig;
|
use crate::account::entity::ImapConfig;
|
||||||
use crate::account::migration::{AccountModel, AccountType, QuotaWindow};
|
use crate::account::migration::{AccountModel, AccountType, QuotaWindow};
|
||||||
use crate::account::since::{DateSince, RelativeDate};
|
use crate::account::since::{DateSince, RelativeDate};
|
||||||
@@ -54,6 +56,7 @@ pub struct AccountCreateRequest {
|
|||||||
pub imap_quota_bytes: Option<u64>,
|
pub imap_quota_bytes: Option<u64>,
|
||||||
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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountCreateRequest {
|
impl AccountCreateRequest {
|
||||||
@@ -92,12 +95,15 @@ impl AccountCreateRequest {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.download_interval_min.is_none() {
|
if self.download_interval_min.is_none() && self.download_schedule.is_none() {
|
||||||
return Err(raise_error!(
|
return Err(raise_error!(
|
||||||
"`sync_interval_min` is required for IMAP account type".into(),
|
"`sync_interval_min` or `download_schedule` is required for IMAP account type".into(),
|
||||||
ErrorCode::InvalidParameter
|
ErrorCode::InvalidParameter
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
if let Some(ref schedule) = self.download_schedule {
|
||||||
|
validate_cron_expression(schedule)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AccountType::NoSync => {}
|
AccountType::NoSync => {}
|
||||||
}
|
}
|
||||||
@@ -178,6 +184,8 @@ pub struct AccountUpdateRequest {
|
|||||||
pub imap_quota_bytes: Option<u64>,
|
pub imap_quota_bytes: Option<u64>,
|
||||||
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 clear_download_schedule: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountUpdateRequest {
|
impl AccountUpdateRequest {
|
||||||
@@ -230,11 +238,36 @@ impl AccountUpdateRequest {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if self.clear_download_schedule == Some(true) && self.download_schedule.is_some() {
|
||||||
|
return Err(raise_error!(
|
||||||
|
"clear_download_schedule cannot be combined with download_schedule".into(),
|
||||||
|
ErrorCode::InvalidParameter
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if let Some(ref schedule) = self.download_schedule {
|
||||||
|
validate_cron_expression(schedule)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_cron_expression(expr: &str) -> BichonResult<()> {
|
||||||
|
if expr.trim().is_empty() {
|
||||||
|
return Err(raise_error!(
|
||||||
|
"download_schedule must not be empty".into(),
|
||||||
|
ErrorCode::InvalidParameter
|
||||||
|
));
|
||||||
|
}
|
||||||
|
cron::Schedule::from_str(expr).map_err(|e| {
|
||||||
|
raise_error!(
|
||||||
|
format!("Invalid cron expression '{}': {}", expr, e),
|
||||||
|
ErrorCode::InvalidParameter
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
|
#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
|
||||||
|
|
||||||
@@ -253,3 +286,34 @@ pub fn filter_accessible_accounts<'a>(
|
|||||||
.cloned()
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::validate_cron_expression;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn valid_cron_expressions() {
|
||||||
|
assert!(validate_cron_expression("0 0 0 * * *").is_ok()); // daily at midnight
|
||||||
|
assert!(validate_cron_expression("0 */5 * * * *").is_ok()); // every 5 minutes
|
||||||
|
assert!(validate_cron_expression("0 0 12 * * 1-5").is_ok()); // weekdays at noon
|
||||||
|
assert!(validate_cron_expression("0 30 4 1 * *").is_ok()); // 1st of month at 04:30
|
||||||
|
assert!(validate_cron_expression("0 0 * * * *").is_ok()); // every hour
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_cron_expression_too_few_fields() {
|
||||||
|
assert!(validate_cron_expression("0 0 * *").is_err());
|
||||||
|
assert!(validate_cron_expression("* * * * *").is_err()); // 5 fields, needs seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_cron_expression_empty() {
|
||||||
|
assert!(validate_cron_expression("").is_err());
|
||||||
|
assert!(validate_cron_expression(" ").is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_cron_expression_garbage() {
|
||||||
|
assert!(validate_cron_expression("not a cron").is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ pub struct AccountResp {
|
|||||||
pub imap_quota_bytes: Option<u64>,
|
pub imap_quota_bytes: Option<u64>,
|
||||||
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>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountResp {
|
impl AccountResp {
|
||||||
@@ -93,6 +94,7 @@ impl AccountResp {
|
|||||||
imap_quota_bytes: account.imap_quota_bytes,
|
imap_quota_bytes: account.imap_quota_bytes,
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+99
-7
@@ -16,6 +16,11 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use chrono::{DateTime, Local, TimeZone, Utc};
|
||||||
|
use cron::Schedule;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
utc_now,
|
utc_now,
|
||||||
{
|
{
|
||||||
@@ -48,11 +53,20 @@ pub async fn decide_next_download_task(
|
|||||||
|
|
||||||
let should_start = match trigger_type {
|
let should_start = match trigger_type {
|
||||||
TriggerType::Manual => true,
|
TriggerType::Manual => true,
|
||||||
TriggerType::Scheduled => should_trigger_next_download(
|
TriggerType::Scheduled => {
|
||||||
state.last_trigger_at,
|
let now = utc_now!();
|
||||||
state.last_finished_at.unwrap_or(0),
|
let cooldown_ok = now - state.last_finished_at.unwrap_or(0) > 60 * 1000;
|
||||||
account.download_interval_min.unwrap_or(60),
|
if !cooldown_ok {
|
||||||
),
|
false
|
||||||
|
} else if let Some(ref schedule) = account.download_schedule {
|
||||||
|
should_trigger_scheduled(schedule, state.last_trigger_at)
|
||||||
|
} else {
|
||||||
|
should_trigger_next_download(
|
||||||
|
state.last_trigger_at,
|
||||||
|
account.download_interval_min.unwrap_or(60),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if should_start {
|
if should_start {
|
||||||
@@ -65,9 +79,87 @@ pub async fn decide_next_download_task(
|
|||||||
|
|
||||||
fn should_trigger_next_download(
|
fn should_trigger_next_download(
|
||||||
last_trigger_at: i64,
|
last_trigger_at: i64,
|
||||||
last_finished_at: i64,
|
|
||||||
sync_interval_min: i64,
|
sync_interval_min: i64,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let now = utc_now!();
|
let now = utc_now!();
|
||||||
now - last_trigger_at > (sync_interval_min * 60 * 1000) && now - last_finished_at > 60 * 1000
|
now - last_trigger_at > (sync_interval_min * 60 * 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_trigger_scheduled(schedule_str: &str, last_trigger_at: i64) -> bool {
|
||||||
|
let schedule = match Schedule::from_str(schedule_str) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => {
|
||||||
|
tracing::warn!(
|
||||||
|
"Invalid cron expression '{}', falling back to no trigger: {}",
|
||||||
|
schedule_str,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// last_trigger_at is a UTC millis timestamp; convert to server local time
|
||||||
|
let last_utc = match Utc.timestamp_millis_opt(last_trigger_at) {
|
||||||
|
chrono::LocalResult::Single(dt) => dt,
|
||||||
|
_ => {
|
||||||
|
tracing::warn!("Invalid last_trigger_at timestamp: {}", last_trigger_at);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let last_dt: DateTime<Local> = last_utc.with_timezone(&Local);
|
||||||
|
let now = Local::now();
|
||||||
|
schedule.after(&last_dt).next().map_or(false, |next| next <= now)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cron_every_minute_triggers_after_60s() {
|
||||||
|
// "0 * * * * *" = every minute at second 0. last_trigger 90s ago → should trigger
|
||||||
|
let now = Local::now();
|
||||||
|
let last_trigger = now.timestamp_millis() - 90_000;
|
||||||
|
assert!(should_trigger_scheduled("0 * * * * *", last_trigger));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cron_daily_midnight_triggers_when_missed() {
|
||||||
|
// "0 0 0 * * *" = daily at midnight
|
||||||
|
// last_trigger was 25 hours ago → should trigger (we missed midnight)
|
||||||
|
let now = Local::now();
|
||||||
|
let last_trigger = now.timestamp_millis() - 25 * 60 * 60 * 1000;
|
||||||
|
assert!(should_trigger_scheduled("0 0 0 * * *", last_trigger));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cron_daily_midnight_no_trigger_if_already_fired() {
|
||||||
|
// "0 0 0 * * *" = daily at midnight
|
||||||
|
// last_trigger was 1 minute ago → should NOT trigger
|
||||||
|
let now = Local::now();
|
||||||
|
let last_trigger = now.timestamp_millis() - 60_000;
|
||||||
|
assert!(!should_trigger_scheduled("0 0 0 * * *", last_trigger));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_cron_returns_false() {
|
||||||
|
assert!(!should_trigger_scheduled("invalid cron expression", 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cron_every_hour_triggers() {
|
||||||
|
// "0 0 * * * *" = every hour at minute 0, second 0
|
||||||
|
// last_trigger was 61 minutes ago → should trigger
|
||||||
|
let now = Local::now();
|
||||||
|
let last_trigger = now.timestamp_millis() - 61 * 60 * 1000;
|
||||||
|
assert!(should_trigger_scheduled("0 0 * * * *", last_trigger));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cron_every_hour_no_trigger_if_recent() {
|
||||||
|
// "0 0 * * * *" = every hour at minute 0, second 0
|
||||||
|
// last_trigger was just 1 minute ago → should NOT trigger (except at :00/:01 boundary)
|
||||||
|
let now = Local::now();
|
||||||
|
let last_trigger = now.timestamp_millis() - 60_000;
|
||||||
|
assert!(!should_trigger_scheduled("0 0 * * * *", last_trigger));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ export interface AccountModel {
|
|||||||
imap_quota_window?: QuotaWindow;
|
imap_quota_window?: QuotaWindow;
|
||||||
imap_quota_bytes?: number;
|
imap_quota_bytes?: number;
|
||||||
auto_download_new_mailboxes?: boolean;
|
auto_download_new_mailboxes?: boolean;
|
||||||
|
download_schedule?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const download_state = async (account_id: number) => {
|
export const download_state = async (account_id: number) => {
|
||||||
|
|||||||
@@ -213,37 +213,6 @@ describe('Account Form Schema', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('folder_limit field', () => {
|
|
||||||
it('accepts undefined folder_limit', () => {
|
|
||||||
const result = getAccountSchema(false, t).safeParse(validAccountData)
|
|
||||||
expect(result.success).toBe(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('accepts null folder_limit', () => {
|
|
||||||
const result = getAccountSchema(false, t).safeParse({
|
|
||||||
...validAccountData,
|
|
||||||
folder_limit: null,
|
|
||||||
})
|
|
||||||
expect(result.success).toBe(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('rejects folder_limit less than 100', () => {
|
|
||||||
const result = getAccountSchema(false, t).safeParse({
|
|
||||||
...validAccountData,
|
|
||||||
folder_limit: 50,
|
|
||||||
})
|
|
||||||
expect(result.success).toBe(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('accepts folder_limit of exactly 100', () => {
|
|
||||||
const result = getAccountSchema(false, t).safeParse({
|
|
||||||
...validAccountData,
|
|
||||||
folder_limit: 100,
|
|
||||||
})
|
|
||||||
expect(result.success).toBe(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('account_name and login_name fields', () => {
|
describe('account_name and login_name fields', () => {
|
||||||
it('accepts undefined account_name and login_name', () => {
|
it('accepts undefined account_name and login_name', () => {
|
||||||
const result = getAccountSchema(false, t).safeParse(validAccountData)
|
const result = getAccountSchema(false, t).safeParse(validAccountData)
|
||||||
@@ -266,6 +235,45 @@ describe('Account Form Schema', () => {
|
|||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('download_schedule field', () => {
|
||||||
|
it('accepts undefined download_schedule', () => {
|
||||||
|
const result = getAccountSchema(false, t).safeParse(validAccountData)
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('accepts valid 6-field cron expression', () => {
|
||||||
|
const result = getAccountSchema(false, t).safeParse({
|
||||||
|
...validAccountData,
|
||||||
|
download_schedule: '0 0 0 * * *',
|
||||||
|
})
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('accepts cron with */step syntax', () => {
|
||||||
|
const result = getAccountSchema(false, t).safeParse({
|
||||||
|
...validAccountData,
|
||||||
|
download_schedule: '0 */30 8-17 * * 1-5',
|
||||||
|
})
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('rejects cron with too few fields', () => {
|
||||||
|
const result = getAccountSchema(false, t).safeParse({
|
||||||
|
...validAccountData,
|
||||||
|
download_schedule: '0 0 *',
|
||||||
|
})
|
||||||
|
expect(result.success).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('accepts empty string cron (treated as not set)', () => {
|
||||||
|
const result = getAccountSchema(false, t).safeParse({
|
||||||
|
...validAccountData,
|
||||||
|
download_schedule: '',
|
||||||
|
})
|
||||||
|
expect(result.success).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Auth Config Schema (password validation)', () => {
|
describe('Auth Config Schema (password validation)', () => {
|
||||||
|
|||||||
@@ -133,8 +133,8 @@ export function AccountDetailDrawer({ open, onOpenChange, currentRow }: Props) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
<span className="text-muted-foreground">{t('accounts.folderLimit')}:</span>
|
<span className="text-muted-foreground">{t('accounts.downloadSchedule')}:</span>
|
||||||
<span>{currentRow.folder_limit ? currentRow.folder_limit : t('accounts.notAvailable')}</span>
|
<span>{currentRow.download_schedule || t('accounts.notAvailable')}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -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", "folder_limit", "download_interval_min", "download_batch_size", "auto_download_new_mailboxes"] },
|
{ 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-4", name: t('accounts.steps.summary'), fields: [] },
|
{ id: "step-4", name: t('accounts.steps.summary'), fields: [] },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -79,10 +79,10 @@ const defaultValues: Account = {
|
|||||||
use_dangerous: false,
|
use_dangerous: false,
|
||||||
date_since: undefined,
|
date_since: undefined,
|
||||||
date_before: undefined,
|
date_before: undefined,
|
||||||
folder_limit: undefined,
|
|
||||||
download_interval_min: 60,
|
download_interval_min: 60,
|
||||||
download_batch_size: 30,
|
download_batch_size: 30,
|
||||||
auto_download_new_mailboxes: true,
|
auto_download_new_mailboxes: true,
|
||||||
|
download_schedule: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const emptyImap: ImapConfig = {
|
const emptyImap: ImapConfig = {
|
||||||
@@ -109,10 +109,10 @@ const mapCurrentRowToFormValues = (currentRow: AccountModel): Account => {
|
|||||||
use_dangerous: currentRow.use_dangerous,
|
use_dangerous: currentRow.use_dangerous,
|
||||||
date_since: currentRow.date_since ?? undefined,
|
date_since: currentRow.date_since ?? undefined,
|
||||||
date_before: currentRow.date_before ?? undefined,
|
date_before: currentRow.date_before ?? undefined,
|
||||||
folder_limit: currentRow.folder_limit ?? 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,
|
||||||
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,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -191,18 +191,18 @@ export function AccountActionDialog({ currentRow, open, onOpenChange }: Props) {
|
|||||||
use_dangerous: data.use_dangerous,
|
use_dangerous: data.use_dangerous,
|
||||||
date_since: data.date_since,
|
date_since: data.date_since,
|
||||||
date_before: data.date_before,
|
date_before: data.date_before,
|
||||||
folder_limit: data.folder_limit,
|
|
||||||
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,
|
||||||
auto_download_new_mailboxes: data.auto_download_new_mailboxes,
|
auto_download_new_mailboxes: data.auto_download_new_mailboxes,
|
||||||
|
download_schedule: data.download_schedule || null,
|
||||||
};
|
};
|
||||||
if (isEdit) {
|
if (isEdit) {
|
||||||
const isAllMode = !data.date_since && !data.date_before;
|
const isAllMode = !data.date_since && !data.date_before;
|
||||||
const clear_folder_limit = !data.folder_limit;
|
const clear_download_schedule = !data.download_schedule && currentRow?.download_schedule;
|
||||||
updateMutation.mutate({
|
updateMutation.mutate({
|
||||||
...commonData,
|
...commonData,
|
||||||
...(isAllMode ? { clear_date_range: true } : {}),
|
...(isAllMode ? { clear_date_range: true } : {}),
|
||||||
...(clear_folder_limit ? { clear_folder_limit: true } : {})
|
...(clear_download_schedule ? { clear_download_schedule: true } : {})
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
createMutation.mutate({ ...commonData, account_type: "IMAP" });
|
createMutation.mutate({ ...commonData, account_type: "IMAP" });
|
||||||
|
|||||||
@@ -106,9 +106,12 @@ export function useColumns(): ColumnDef<AccountModel>[] {
|
|||||||
if (account_type === "NoSync") {
|
if (account_type === "NoSync") {
|
||||||
return <LongText className="text-center">n/a</LongText>
|
return <LongText className="text-center">n/a</LongText>
|
||||||
}
|
}
|
||||||
|
if (row.original.download_schedule) {
|
||||||
|
return <LongText className="text-center">{row.original.download_schedule}</LongText>
|
||||||
|
}
|
||||||
return <LongText className="text-center">{row.original.download_interval_min} min</LongText>
|
return <LongText className="text-center">{row.original.download_interval_min} min</LongText>
|
||||||
},
|
},
|
||||||
meta: { className: 'text-center max-w-[120px]' },
|
meta: { className: 'text-center max-w-[160px]' },
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -98,26 +98,6 @@ export function DataTableRowActions({ row }: DataTableRowActionsProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align='end' className='w-[220px]'>
|
<DropdownMenuContent align='end' className='w-[220px]'>
|
||||||
|
|
||||||
{showDownload && (
|
|
||||||
<DropdownMenuItem onClick={handleStartDownload}>
|
|
||||||
{t('accounts.startDownload')}
|
|
||||||
<DropdownMenuShortcut>
|
|
||||||
<IconPlayerPlay size={16} />
|
|
||||||
</DropdownMenuShortcut>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
|
||||||
|
|
||||||
|
|
||||||
{showDownload && (
|
|
||||||
<DropdownMenuItem onClick={handleCancelDownload}>
|
|
||||||
{t('accounts.cancelDownload')}
|
|
||||||
<DropdownMenuShortcut>
|
|
||||||
<IconPlayerStop size={16} />
|
|
||||||
</DropdownMenuShortcut>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
|
||||||
{showDownload && <DropdownMenuSeparator />}
|
|
||||||
{hasPermission && <DropdownMenuItem
|
{hasPermission && <DropdownMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrentRow(row.original)
|
setCurrentRow(row.original)
|
||||||
@@ -169,6 +149,27 @@ export function DataTableRowActions({ row }: DataTableRowActionsProps) {
|
|||||||
</DropdownMenuShortcut>
|
</DropdownMenuShortcut>
|
||||||
</DropdownMenuItem>}
|
</DropdownMenuItem>}
|
||||||
{hasPermission && <DropdownMenuSeparator />}
|
{hasPermission && <DropdownMenuSeparator />}
|
||||||
|
|
||||||
|
{showDownload && (
|
||||||
|
<DropdownMenuItem onClick={handleStartDownload}>
|
||||||
|
{t('accounts.startDownload')}
|
||||||
|
<DropdownMenuShortcut>
|
||||||
|
<IconPlayerPlay size={16} />
|
||||||
|
</DropdownMenuShortcut>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
{showDownload && (
|
||||||
|
<DropdownMenuItem onClick={handleCancelDownload}>
|
||||||
|
{t('accounts.cancelDownload')}
|
||||||
|
<DropdownMenuShortcut>
|
||||||
|
<IconPlayerStop size={16} />
|
||||||
|
</DropdownMenuShortcut>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
{showDownload && <DropdownMenuSeparator />}
|
||||||
|
|
||||||
{hasPermission && <DropdownMenuItem
|
{hasPermission && <DropdownMenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrentRow(row.original)
|
setCurrentRow(row.original)
|
||||||
|
|||||||
@@ -79,12 +79,6 @@ export const getAccountSchema = (isEdit: boolean, t: (key: string) => string) =>
|
|||||||
use_dangerous: z.boolean(),
|
use_dangerous: z.boolean(),
|
||||||
date_since: dateSelectionSchema(t).optional(),
|
date_since: dateSelectionSchema(t).optional(),
|
||||||
date_before: relativeDateSchema(t).optional(),
|
date_before: relativeDateSchema(t).optional(),
|
||||||
folder_limit: z
|
|
||||||
.number({ invalid_type_error: t('validation.folderLimitMustBeNumber') })
|
|
||||||
.int()
|
|
||||||
.min(100, { message: t('validation.folderLimitMustBeAtLeast100') })
|
|
||||||
.nullable()
|
|
||||||
.optional(),
|
|
||||||
download_interval_min: z
|
download_interval_min: z
|
||||||
.number({
|
.number({
|
||||||
invalid_type_error: t('validation.incrementalSyncMustBeNumber'),
|
invalid_type_error: t('validation.incrementalSyncMustBeNumber'),
|
||||||
@@ -107,6 +101,18 @@ export const getAccountSchema = (isEdit: boolean, t: (key: string) => string) =>
|
|||||||
message: t('validation.singleRequestBatchSizeTooLarge'),
|
message: t('validation.singleRequestBatchSizeTooLarge'),
|
||||||
}),
|
}),
|
||||||
auto_download_new_mailboxes: z.boolean(),
|
auto_download_new_mailboxes: z.boolean(),
|
||||||
|
download_schedule: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.refine(
|
||||||
|
(val) => {
|
||||||
|
if (!val || val.trim() === '') return true;
|
||||||
|
const fields = val.trim().split(/\s+/);
|
||||||
|
if (fields.length < 6) return false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{ message: t('validation.invalidCronExpression') }
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
export type AccountFormValues = z.infer<
|
export type AccountFormValues = z.infer<
|
||||||
|
|||||||
@@ -48,6 +48,72 @@ import i18n from "@/i18n";
|
|||||||
|
|
||||||
|
|
||||||
type SyncMode = 'all' | 'since_fixed' | 'since_relative' | 'before_relative';
|
type SyncMode = 'all' | 'since_fixed' | 'since_relative' | 'before_relative';
|
||||||
|
type ScheduleMode = 'interval' | 'cron';
|
||||||
|
type CronMode = 'simple' | 'advanced';
|
||||||
|
type CronFrequency = 'daily' | 'weekly' | 'monthly';
|
||||||
|
|
||||||
|
interface CronSimpleState {
|
||||||
|
frequency: CronFrequency;
|
||||||
|
hour: number;
|
||||||
|
minute: number;
|
||||||
|
dayOfWeek: number;
|
||||||
|
dayOfMonth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_CRON_SIMPLE: CronSimpleState = {
|
||||||
|
frequency: 'daily',
|
||||||
|
hour: 0,
|
||||||
|
minute: 0,
|
||||||
|
dayOfWeek: 1,
|
||||||
|
dayOfMonth: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
function buildCronFromSimple(s: CronSimpleState): string {
|
||||||
|
switch (s.frequency) {
|
||||||
|
case 'daily':
|
||||||
|
return `0 ${s.minute} ${s.hour} * * *`;
|
||||||
|
case 'weekly':
|
||||||
|
return `0 ${s.minute} ${s.hour} * * ${s.dayOfWeek}`;
|
||||||
|
case 'monthly':
|
||||||
|
return `0 ${s.minute} ${s.hour} ${s.dayOfMonth} * *`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tryParseCronToSimple(cron: string): CronSimpleState | null {
|
||||||
|
const fields = cron.trim().split(/\s+/);
|
||||||
|
if (fields.length < 6) return null;
|
||||||
|
|
||||||
|
const sec = fields[0];
|
||||||
|
const min = fields[1];
|
||||||
|
const hour = fields[2];
|
||||||
|
const dom = fields[3];
|
||||||
|
const month = fields[4];
|
||||||
|
const dow = fields[5];
|
||||||
|
|
||||||
|
if (sec !== '0') return null;
|
||||||
|
if (month !== '*') return null;
|
||||||
|
|
||||||
|
const minuteVal = parseInt(min, 10);
|
||||||
|
const hourVal = parseInt(hour, 10);
|
||||||
|
if (isNaN(minuteVal) || isNaN(hourVal)) return null;
|
||||||
|
|
||||||
|
if (dom === '*' && dow === '*') {
|
||||||
|
return { frequency: 'daily', hour: hourVal, minute: minuteVal, dayOfWeek: 1, dayOfMonth: 1 };
|
||||||
|
}
|
||||||
|
if (dom === '*') {
|
||||||
|
const dowVal = parseInt(dow, 10);
|
||||||
|
if (!isNaN(dowVal)) {
|
||||||
|
return { frequency: 'weekly', hour: hourVal, minute: minuteVal, dayOfWeek: dowVal, dayOfMonth: 1 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dow === '*') {
|
||||||
|
const domVal = parseInt(dom, 10);
|
||||||
|
if (!isNaN(domVal)) {
|
||||||
|
return { frequency: 'monthly', hour: hourVal, minute: minuteVal, dayOfWeek: 1, dayOfMonth: domVal };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
export default function Step3() {
|
export default function Step3() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -61,6 +127,31 @@ export default function Step3() {
|
|||||||
return 'all';
|
return 'all';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [scheduleMode, setScheduleMode] = useState<ScheduleMode>(() => {
|
||||||
|
if (current.download_schedule) return 'cron';
|
||||||
|
return 'interval';
|
||||||
|
});
|
||||||
|
|
||||||
|
const [cronMode, setCronMode] = useState<CronMode>(() => {
|
||||||
|
if (current.download_schedule && tryParseCronToSimple(current.download_schedule)) {
|
||||||
|
return 'simple';
|
||||||
|
}
|
||||||
|
if (current.download_schedule) return 'advanced';
|
||||||
|
return 'simple';
|
||||||
|
});
|
||||||
|
|
||||||
|
const [cronSimple, setCronSimple] = useState<CronSimpleState>(() => {
|
||||||
|
if (current.download_schedule) {
|
||||||
|
return tryParseCronToSimple(current.download_schedule) ?? DEFAULT_CRON_SIMPLE;
|
||||||
|
}
|
||||||
|
return DEFAULT_CRON_SIMPLE;
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateCronFromSimple = (partial: Partial<CronSimpleState>) => {
|
||||||
|
const next = { ...cronSimple, ...partial };
|
||||||
|
setCronSimple(next);
|
||||||
|
setValue('download_schedule', buildCronFromSimple(next));
|
||||||
|
};
|
||||||
|
|
||||||
const handleModeChange = (mode: SyncMode) => {
|
const handleModeChange = (mode: SyncMode) => {
|
||||||
setSyncMode(mode);
|
setSyncMode(mode);
|
||||||
@@ -77,41 +168,231 @@ export default function Step3() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleScheduleModeChange = (mode: ScheduleMode) => {
|
||||||
|
setScheduleMode(mode);
|
||||||
|
if (mode === 'interval') {
|
||||||
|
setValue("download_schedule", undefined);
|
||||||
|
} else {
|
||||||
|
setValue("download_interval_min", 60);
|
||||||
|
if (cronMode === 'simple') {
|
||||||
|
updateCronFromSimple(cronSimple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div className="space-y-4">
|
||||||
<FormField
|
<FormItem>
|
||||||
control={control}
|
<FormLabel className="text-base font-semibold">{t('accounts.scheduleMode')}</FormLabel>
|
||||||
name="download_interval_min"
|
<FormDescription>
|
||||||
render={({ field }) => (
|
{t('accounts.scheduleModeDescription')}
|
||||||
<FormItem>
|
</FormDescription>
|
||||||
<FormLabel>{t('accounts.downloadInterval')}</FormLabel>
|
<Select value={scheduleMode} onValueChange={(v) => handleScheduleModeChange(v as ScheduleMode)}>
|
||||||
<FormControl>
|
<SelectTrigger className="w-full">
|
||||||
<Input type="number" {...field} onChange={(e) => field.onChange(parseInt(e.target.value, 10))} />
|
<SelectValue />
|
||||||
</FormControl>
|
</SelectTrigger>
|
||||||
<FormMessage />
|
<SelectContent>
|
||||||
<FormDescription>
|
<SelectItem value="interval">{t('accounts.scheduleModeInterval')}</SelectItem>
|
||||||
{t('accounts.downloadIntervalPlaceholder')}
|
<SelectItem value="cron">{t('accounts.scheduleModeCron')}</SelectItem>
|
||||||
</FormDescription>
|
</SelectContent>
|
||||||
</FormItem>
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
{scheduleMode === 'interval' ? (
|
||||||
|
<FormField
|
||||||
|
control={control}
|
||||||
|
name="download_interval_min"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t('accounts.downloadInterval')}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input type="number" {...field} onChange={(e) => field.onChange(parseInt(e.target.value, 10))} />
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
<FormDescription>
|
||||||
|
{t('accounts.downloadIntervalPlaceholder')}
|
||||||
|
</FormDescription>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
{/* <FormLabel className="text-sm font-medium">{t('accounts.downloadSchedule')}</FormLabel> */}
|
||||||
|
<div className="flex items-center rounded-md border text-xs">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`px-2 py-1 rounded-l-md ${cronMode === 'simple' ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:text-foreground'}`}
|
||||||
|
onClick={() => setCronMode('simple')}
|
||||||
|
>
|
||||||
|
{t('accounts.cronSimple')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={`px-2 py-1 rounded-r-md ${cronMode === 'advanced' ? 'bg-primary text-primary-foreground' : 'text-muted-foreground hover:text-foreground'}`}
|
||||||
|
onClick={() => setCronMode('advanced')}
|
||||||
|
>
|
||||||
|
{t('accounts.cronAdvanced')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{cronMode === 'simple' ? (
|
||||||
|
<div className="flex flex-wrap items-end gap-3">
|
||||||
|
<FormItem className="w-[140px]">
|
||||||
|
<FormLabel className="text-xs">{t('accounts.cronFrequency')}</FormLabel>
|
||||||
|
<Select
|
||||||
|
value={cronSimple.frequency}
|
||||||
|
onValueChange={(v) => updateCronFromSimple({ frequency: v as CronFrequency })}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="daily">{t('accounts.cronDaily')}</SelectItem>
|
||||||
|
<SelectItem value="weekly">{t('accounts.cronWeekly')}</SelectItem>
|
||||||
|
<SelectItem value="monthly">{t('accounts.cronMonthly')}</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem className="w-[80px]">
|
||||||
|
<FormLabel className="text-xs">{t('accounts.cronHour')}</FormLabel>
|
||||||
|
<Select
|
||||||
|
value={String(cronSimple.hour)}
|
||||||
|
onValueChange={(v) => updateCronFromSimple({ hour: parseInt(v, 10) })}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{Array.from({ length: 24 }, (_, i) => (
|
||||||
|
<SelectItem key={i} value={String(i)}>
|
||||||
|
{String(i).padStart(2, '0')}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<span className="text-muted-foreground pb-2">:</span>
|
||||||
|
|
||||||
|
<FormItem className="w-[80px]">
|
||||||
|
<FormLabel className="text-xs">{t('accounts.cronMinute')}</FormLabel>
|
||||||
|
<Select
|
||||||
|
value={String(cronSimple.minute)}
|
||||||
|
onValueChange={(v) => updateCronFromSimple({ minute: parseInt(v, 10) })}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55].map((m) => (
|
||||||
|
<SelectItem key={m} value={String(m)}>
|
||||||
|
{String(m).padStart(2, '0')}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
{cronSimple.frequency === 'weekly' && (
|
||||||
|
<FormItem className="w-[140px]">
|
||||||
|
<FormLabel className="text-xs">{t('accounts.cronDayOfWeek')}</FormLabel>
|
||||||
|
<Select
|
||||||
|
value={String(cronSimple.dayOfWeek)}
|
||||||
|
onValueChange={(v) => updateCronFromSimple({ dayOfWeek: parseInt(v, 10) })}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="1">{t('accounts.cronMonday')}</SelectItem>
|
||||||
|
<SelectItem value="2">{t('accounts.cronTuesday')}</SelectItem>
|
||||||
|
<SelectItem value="3">{t('accounts.cronWednesday')}</SelectItem>
|
||||||
|
<SelectItem value="4">{t('accounts.cronThursday')}</SelectItem>
|
||||||
|
<SelectItem value="5">{t('accounts.cronFriday')}</SelectItem>
|
||||||
|
<SelectItem value="6">{t('accounts.cronSaturday')}</SelectItem>
|
||||||
|
<SelectItem value="0">{t('accounts.cronSunday')}</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{cronSimple.frequency === 'monthly' && (
|
||||||
|
<FormItem className="w-[90px]">
|
||||||
|
<FormLabel className="text-xs">{t('accounts.cronDayOfMonth')}</FormLabel>
|
||||||
|
<Select
|
||||||
|
value={String(cronSimple.dayOfMonth)}
|
||||||
|
onValueChange={(v) => updateCronFromSimple({ dayOfMonth: parseInt(v, 10) })}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent className="max-h-[200px]">
|
||||||
|
{Array.from({ length: 28 }, (_, i) => i + 1).map((d) => (
|
||||||
|
<SelectItem key={d} value={String(d)}>
|
||||||
|
{d}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="text-xs text-muted-foreground pb-2 font-mono">
|
||||||
|
= {buildCronFromSimple(cronSimple)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<FormField
|
||||||
|
control={control}
|
||||||
|
name="download_schedule"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
value={field.value ?? ''}
|
||||||
|
placeholder={t('accounts.downloadSchedulePlaceholder')}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t('accounts.downloadScheduleDescription')}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{cronMode === 'simple' && (
|
||||||
|
<FormDescription>{t('accounts.downloadScheduleDescription')}</FormDescription>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="text-xs text-muted-foreground mt-1 flex items-center gap-1">
|
||||||
|
<span>{t('accounts.cronTimezoneNote')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
/>
|
<FormField
|
||||||
<FormField
|
control={control}
|
||||||
control={control}
|
name="download_batch_size"
|
||||||
name="download_batch_size"
|
render={({ field }) => (
|
||||||
render={({ field }) => (
|
<FormItem>
|
||||||
<FormItem>
|
<FormLabel>{t('accounts.downloadBatchSize')}</FormLabel>
|
||||||
<FormLabel>{t('accounts.downloadBatchSize')}</FormLabel>
|
<FormControl>
|
||||||
<FormControl>
|
<Input type="number" {...field} onChange={(e) => field.onChange(parseInt(e.target.value, 10))} />
|
||||||
<Input type="number" {...field} onChange={(e) => field.onChange(parseInt(e.target.value, 10))} />
|
</FormControl>
|
||||||
</FormControl>
|
<FormMessage />
|
||||||
<FormMessage />
|
<FormDescription>
|
||||||
<FormDescription>
|
{t('accounts.downloadBatchSizeDescription')}
|
||||||
{t('accounts.downloadBatchSizeDescription')}
|
</FormDescription>
|
||||||
</FormDescription>
|
</FormItem>
|
||||||
</FormItem>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
@@ -249,29 +530,6 @@ export default function Step3() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<hr className="my-4" />
|
<hr className="my-4" />
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={control}
|
|
||||||
name="folder_limit"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>{t('accounts.folderLimit')}</FormLabel>
|
|
||||||
<FormDescription>{t('accounts.folderLimitDescription')}</FormDescription>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
placeholder={t('accounts.folderLimitPlaceholder')}
|
|
||||||
value={field.value ?? ''}
|
|
||||||
onChange={(e) => {
|
|
||||||
const value = e.target.value;
|
|
||||||
field.onChange(value === '' ? null : Number(value));
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ 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', 'folder_limit', 'sync_interval', 'sync_scope', 'sync_batch_size']}>
|
<Accordion type="multiple" defaultValue={['email', 'account_name', 'login_name', 'imap', 'date_since', '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>
|
||||||
@@ -154,11 +154,6 @@ export default function Step4() {
|
|||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
|
||||||
|
|
||||||
<AccordionItem key="folder_limit" value="folder_limit">
|
|
||||||
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.folderLimit')}:</AccordionTrigger>
|
|
||||||
<AccordionContent>{summaryData.folder_limit ?? t('accounts.notAvailable')}</AccordionContent>
|
|
||||||
</AccordionItem>
|
|
||||||
|
|
||||||
<AccordionItem key="sync_interval" value="sync_interval">
|
<AccordionItem key="sync_interval" value="sync_interval">
|
||||||
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.downloadInterval')}:</AccordionTrigger>
|
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.downloadInterval')}:</AccordionTrigger>
|
||||||
<AccordionContent>{summaryData.download_interval_min} {t('accounts.minutes')}</AccordionContent>
|
<AccordionContent>{summaryData.download_interval_min} {t('accounts.minutes')}</AccordionContent>
|
||||||
@@ -169,6 +164,11 @@ export default function Step4() {
|
|||||||
<AccordionContent>{summaryData.download_batch_size}</AccordionContent>
|
<AccordionContent>{summaryData.download_batch_size}</AccordionContent>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
|
||||||
|
<AccordionItem key="download_schedule" value="download_schedule">
|
||||||
|
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.downloadSchedule')}:</AccordionTrigger>
|
||||||
|
<AccordionContent>{summaryData.download_schedule || t('accounts.notAvailable')}</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
|
|
||||||
<AccordionItem key="auto_download_new_mailboxes" value="auto_download_new_mailboxes">
|
<AccordionItem key="auto_download_new_mailboxes" value="auto_download_new_mailboxes">
|
||||||
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.autoDownloadNewMailboxes')}:</AccordionTrigger>
|
<AccordionTrigger className="font-medium capitalize text-gray-600">{t('accounts.autoDownloadNewMailboxes')}:</AccordionTrigger>
|
||||||
<AccordionContent>{summaryData.auto_download_new_mailboxes ? t('common.yes') : t('common.no')}</AccordionContent>
|
<AccordionContent>{summaryData.auto_download_new_mailboxes ? t('common.yes') : t('common.no')}</AccordionContent>
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "متابعة",
|
"continue": "متابعة",
|
||||||
"createdAt": "تاريخ الإنشاء",
|
"createdAt": "تاريخ الإنشاء",
|
||||||
"creationFailed": "فشل الإنشاء، يرجى المحاولة مرة أخرى لاحقًا",
|
"creationFailed": "فشل الإنشاء، يرجى المحاولة مرة أخرى لاحقًا",
|
||||||
|
"cronAdvanced": "تعبير متقدم",
|
||||||
|
"cronDaily": "يومياً",
|
||||||
|
"cronDayOfMonth": "اليوم من الأسبوع",
|
||||||
|
"cronDayOfWeek": "اليوم من الأسبوع",
|
||||||
|
"cronFrequency": "التكرار",
|
||||||
|
"cronFriday": "الجمعة",
|
||||||
|
"cronHour": "الساعة",
|
||||||
|
"cronMinute": "الدقيقة",
|
||||||
|
"cronMonday": "الإثنين",
|
||||||
|
"cronMonthly": "شهرياً",
|
||||||
|
"cronSaturday": "السبت",
|
||||||
|
"cronSimple": "تعبير بسيط",
|
||||||
|
"cronSunday": "الأحد",
|
||||||
|
"cronThursday": "الخميس",
|
||||||
|
"cronTimezoneNote": "جميع الأوقات بالتوقيت المحلي للخادم.",
|
||||||
|
"cronTuesday": "الثلاثاء",
|
||||||
|
"cronWednesday": "الأربعاء",
|
||||||
|
"cronWeekly": "أسبوعياً",
|
||||||
"dateSelection": "تحديد التاريخ",
|
"dateSelection": "تحديد التاريخ",
|
||||||
"dateSince": "التاريخ منذ",
|
"dateSince": "التاريخ منذ",
|
||||||
"days": "أيام",
|
"days": "أيام",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "فشل بدء مهمة التنزيل",
|
"downloadFailed": "فشل بدء مهمة التنزيل",
|
||||||
"downloadInterval": "دورة التنزيل (بالدقائق)",
|
"downloadInterval": "دورة التنزيل (بالدقائق)",
|
||||||
"downloadIntervalPlaceholder": "أدخل الدقائق",
|
"downloadIntervalPlaceholder": "أدخل الدقائق",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "كرون من 6 حقول (ثانية-دقائق-ساعات-يوم-شهر-أسبوع) بتوقيت الخادم. يتجاوز الفاصل الزمني.",
|
||||||
|
"downloadSchedulePlaceholder": "مثال: 0 0 * * *",
|
||||||
"downloadScope": "استراتيجية التنزيل",
|
"downloadScope": "استراتيجية التنزيل",
|
||||||
"downloadScopeDescription": "اختر رسائل البريد الإلكتروني التي يجب فهرستها وتنزيلها.",
|
"downloadScopeDescription": "اختر رسائل البريد الإلكتروني التي يجب فهرستها وتنزيلها.",
|
||||||
"downloadStarted": "بدأت مهمة التنزيل",
|
"downloadStarted": "بدأت مهمة التنزيل",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "حفظ التغييرات",
|
"saveChanges": "حفظ التغييرات",
|
||||||
|
"scheduleMode": "جدولة التنزيل",
|
||||||
|
"scheduleModeCron": "تعبير Cron",
|
||||||
|
"scheduleModeDescription": "تعيين التنزيل بفواصل زمنية ثابتة أو عبر Cron.",
|
||||||
|
"scheduleModeInterval": "فواصل زمنية ثابتة",
|
||||||
"selectAccountType": "اختر نوع الحساب",
|
"selectAccountType": "اختر نوع الحساب",
|
||||||
"selectAtLeastOneFolder": "يرجى تحديد مجلد واحد على الأقل",
|
"selectAtLeastOneFolder": "يرجى تحديد مجلد واحد على الأقل",
|
||||||
"selectAuthMethod": "اختر طريقة مصادقة",
|
"selectAuthMethod": "اختر طريقة مصادقة",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "يجب أن يكون منفذ IMAP عددًا صحيحًا موجبًا",
|
"imapPortMustBePositive": "يجب أن يكون منفذ IMAP عددًا صحيحًا موجبًا",
|
||||||
"incrementalSyncMustBeAtLeast10": "يجب أن يكون فاصل المزامنة التزايدية 10 دقائق على الأقل",
|
"incrementalSyncMustBeAtLeast10": "يجب أن يكون فاصل المزامنة التزايدية 10 دقائق على الأقل",
|
||||||
"incrementalSyncMustBeNumber": "يجب أن يكون فاصل المزامنة التزايدية رقمًا",
|
"incrementalSyncMustBeNumber": "يجب أن يكون فاصل المزامنة التزايدية رقمًا",
|
||||||
|
"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 غير صالح",
|
||||||
"passwordMinLength": "يجب أن تتكون كلمة المرور من {{min}} أحرف على الأقل",
|
"passwordMinLength": "يجب أن تتكون كلمة المرور من {{min}} أحرف على الأقل",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Fortsæt",
|
"continue": "Fortsæt",
|
||||||
"createdAt": "Oprettet",
|
"createdAt": "Oprettet",
|
||||||
"creationFailed": "Oprettelse mislykkedes, prøv venligst igen senere",
|
"creationFailed": "Oprettelse mislykkedes, prøv venligst igen senere",
|
||||||
|
"cronAdvanced": "Avanceret udtryk",
|
||||||
|
"cronDaily": "Dagligt",
|
||||||
|
"cronDayOfMonth": "Ugedag",
|
||||||
|
"cronDayOfWeek": "Ugedag",
|
||||||
|
"cronFrequency": "Frekvens",
|
||||||
|
"cronFriday": "Fredag",
|
||||||
|
"cronHour": "Time",
|
||||||
|
"cronMinute": "Minut",
|
||||||
|
"cronMonday": "Mandag",
|
||||||
|
"cronMonthly": "Månedligt",
|
||||||
|
"cronSaturday": "Lørdag",
|
||||||
|
"cronSimple": "Simpelt udtryk",
|
||||||
|
"cronSunday": "Søndag",
|
||||||
|
"cronThursday": "Torsdag",
|
||||||
|
"cronTimezoneNote": "Alle tider er serverens lokale tid.",
|
||||||
|
"cronTuesday": "Tirsdag",
|
||||||
|
"cronWednesday": "Onsdag",
|
||||||
|
"cronWeekly": "Ugentligt",
|
||||||
"dateSelection": "Datovalg",
|
"dateSelection": "Datovalg",
|
||||||
"dateSince": "Dato fra",
|
"dateSince": "Dato fra",
|
||||||
"days": "Dage",
|
"days": "Dage",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Kunne ikke starte download-opgave",
|
"downloadFailed": "Kunne ikke starte download-opgave",
|
||||||
"downloadInterval": "Downloadinterval (minutter)",
|
"downloadInterval": "Downloadinterval (minutter)",
|
||||||
"downloadIntervalPlaceholder": "Indtast minutter",
|
"downloadIntervalPlaceholder": "Indtast minutter",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "6-felters Cron (sek min time dag mdr ugedag) i servertid. Tilsidesætter interval.",
|
||||||
|
"downloadSchedulePlaceholder": "F.eks.: 0 0 * * *",
|
||||||
"downloadScope": "Downloadstrategi",
|
"downloadScope": "Downloadstrategi",
|
||||||
"downloadScopeDescription": "Vælg hvilke e-mails der skal indekseres og downloades.",
|
"downloadScopeDescription": "Vælg hvilke e-mails der skal indekseres og downloades.",
|
||||||
"downloadStarted": "Download-opgave startet",
|
"downloadStarted": "Download-opgave startet",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Gem ændringer",
|
"saveChanges": "Gem ændringer",
|
||||||
|
"scheduleMode": "Planlægning af download",
|
||||||
|
"scheduleModeCron": "Cron-udtryk",
|
||||||
|
"scheduleModeDescription": "Download via faste intervaller eller Cron.",
|
||||||
|
"scheduleModeInterval": "Fast interval",
|
||||||
"selectAccountType": "Vælg kontotype",
|
"selectAccountType": "Vælg kontotype",
|
||||||
"selectAtLeastOneFolder": "Vælg venligst mindst én mappe",
|
"selectAtLeastOneFolder": "Vælg venligst mindst én mappe",
|
||||||
"selectAuthMethod": "Vælg en godkendelsesmetode",
|
"selectAuthMethod": "Vælg en godkendelsesmetode",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAP-port skal være et positivt heltal",
|
"imapPortMustBePositive": "IMAP-port skal være et positivt heltal",
|
||||||
"incrementalSyncMustBeAtLeast10": "Inkrementelt synkroniseringsinterval skal være mindst 10 minutter",
|
"incrementalSyncMustBeAtLeast10": "Inkrementelt synkroniseringsinterval skal være mindst 10 minutter",
|
||||||
"incrementalSyncMustBeNumber": "Inkrementelt synkroniseringsinterval skal være et tal",
|
"incrementalSyncMustBeNumber": "Inkrementelt synkroniseringsinterval skal være et tal",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "Adgangskoden skal være mindst {{min}} tegn lang",
|
"passwordMinLength": "Adgangskoden skal være mindst {{min}} tegn lang",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Weiter",
|
"continue": "Weiter",
|
||||||
"createdAt": "Erstellt am",
|
"createdAt": "Erstellt am",
|
||||||
"creationFailed": "Erstellung fehlgeschlagen, bitte versuchen Sie es später erneut",
|
"creationFailed": "Erstellung fehlgeschlagen, bitte versuchen Sie es später erneut",
|
||||||
|
"cronAdvanced": "Erweiterter Ausdruck",
|
||||||
|
"cronDaily": "Täglich",
|
||||||
|
"cronDayOfMonth": "Wochentag",
|
||||||
|
"cronDayOfWeek": "Wochentag",
|
||||||
|
"cronFrequency": "Häufigkeit",
|
||||||
|
"cronFriday": "Freitag",
|
||||||
|
"cronHour": "Stunde",
|
||||||
|
"cronMinute": "Minute",
|
||||||
|
"cronMonday": "Montag",
|
||||||
|
"cronMonthly": "Monatlich",
|
||||||
|
"cronSaturday": "Samstag",
|
||||||
|
"cronSimple": "Einfacher Ausdruck",
|
||||||
|
"cronSunday": "Sonntag",
|
||||||
|
"cronThursday": "Donnerstag",
|
||||||
|
"cronTimezoneNote": "Alle Zeiten nutzen Server-Ortszeit.",
|
||||||
|
"cronTuesday": "Dienstag",
|
||||||
|
"cronWednesday": "Mittwoch",
|
||||||
|
"cronWeekly": "Wöchentlich",
|
||||||
"dateSelection": "Datumsauswahl",
|
"dateSelection": "Datumsauswahl",
|
||||||
"dateSince": "Datum seit",
|
"dateSince": "Datum seit",
|
||||||
"days": "Tage",
|
"days": "Tage",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Download-Aufgabe konnte nicht gestartet werden",
|
"downloadFailed": "Download-Aufgabe konnte nicht gestartet werden",
|
||||||
"downloadInterval": "Download-Intervall (Minuten)",
|
"downloadInterval": "Download-Intervall (Minuten)",
|
||||||
"downloadIntervalPlaceholder": "Minuten eingeben",
|
"downloadIntervalPlaceholder": "Minuten eingeben",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "6-Felder-Cron (Sek Min Std Tag Mon Wochentag) in Serverzeit. Ersetzt Intervall.",
|
||||||
|
"downloadSchedulePlaceholder": "Z. B.: 0 0 * * *",
|
||||||
"downloadScope": "Download-Strategie",
|
"downloadScope": "Download-Strategie",
|
||||||
"downloadScopeDescription": "Wählen Sie aus, welche E-Mails indiziert und heruntergeladen werden sollen.",
|
"downloadScopeDescription": "Wählen Sie aus, welche E-Mails indiziert und heruntergeladen werden sollen.",
|
||||||
"downloadStarted": "Download-Aufgabe gestartet",
|
"downloadStarted": "Download-Aufgabe gestartet",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Änderungen speichern",
|
"saveChanges": "Änderungen speichern",
|
||||||
|
"scheduleMode": "Download-Zeitplan",
|
||||||
|
"scheduleModeCron": "Cron-Ausdruck",
|
||||||
|
"scheduleModeDescription": "Download nach festem Intervall oder Cron-Ausdruck.",
|
||||||
|
"scheduleModeInterval": "Festes Intervall",
|
||||||
"selectAccountType": "Kontotyp auswählen",
|
"selectAccountType": "Kontotyp auswählen",
|
||||||
"selectAtLeastOneFolder": "Wählen Sie mindestens einen Ordner aus",
|
"selectAtLeastOneFolder": "Wählen Sie mindestens einen Ordner aus",
|
||||||
"selectAuthMethod": "Authentifizierungsmethode auswählen",
|
"selectAuthMethod": "Authentifizierungsmethode auswählen",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "Der IMAP-Port muss eine positive ganze Zahl sein",
|
"imapPortMustBePositive": "Der IMAP-Port muss eine positive ganze Zahl sein",
|
||||||
"incrementalSyncMustBeAtLeast10": "Das inkrementelle Synchronisierungsintervall muss mindestens 10 Minuten betragen",
|
"incrementalSyncMustBeAtLeast10": "Das inkrementelle Synchronisierungsintervall muss mindestens 10 Minuten betragen",
|
||||||
"incrementalSyncMustBeNumber": "Das inkrementelle Synchronisierungsintervall muss eine Zahl sein",
|
"incrementalSyncMustBeNumber": "Das inkrementelle Synchronisierungsintervall muss eine Zahl sein",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "Das Passwort muss mindestens {{min}} Zeichen lang sein",
|
"passwordMinLength": "Das Passwort muss mindestens {{min}} Zeichen lang sein",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
"createdAt": "Created At",
|
"createdAt": "Created At",
|
||||||
"creationFailed": "Creation failed, please try again later",
|
"creationFailed": "Creation failed, please try again later",
|
||||||
|
"cronAdvanced": "Advanced Expression",
|
||||||
|
"cronDaily": "Daily",
|
||||||
|
"cronDayOfMonth": "Day of Week",
|
||||||
|
"cronDayOfWeek": "Day of Week",
|
||||||
|
"cronFrequency": "Frequency",
|
||||||
|
"cronFriday": "Friday",
|
||||||
|
"cronHour": "Hour",
|
||||||
|
"cronMinute": "Minute",
|
||||||
|
"cronMonday": "Monday",
|
||||||
|
"cronMonthly": "Monthly",
|
||||||
|
"cronSaturday": "Saturday",
|
||||||
|
"cronSimple": "Simple Expression",
|
||||||
|
"cronSunday": "Sunday",
|
||||||
|
"cronThursday": "Thursday",
|
||||||
|
"cronTimezoneNote": "All times use server local timezone.",
|
||||||
|
"cronTuesday": "Tuesday",
|
||||||
|
"cronWednesday": "Wednesday",
|
||||||
|
"cronWeekly": "Weekly",
|
||||||
"dateSelection": "Date Selection",
|
"dateSelection": "Date Selection",
|
||||||
"dateSince": "Date Since",
|
"dateSince": "Date Since",
|
||||||
"days": "Days",
|
"days": "Days",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Failed to start download task",
|
"downloadFailed": "Failed to start download task",
|
||||||
"downloadInterval": "Download Interval (minutes)",
|
"downloadInterval": "Download Interval (minutes)",
|
||||||
"downloadIntervalPlaceholder": "Enter minutes",
|
"downloadIntervalPlaceholder": "Enter minutes",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "6-field Cron (sec min hour day month dow) in server time. Overrides interval.",
|
||||||
|
"downloadSchedulePlaceholder": "e.g., 0 0 * * *",
|
||||||
"downloadScope": "Download Strategy",
|
"downloadScope": "Download Strategy",
|
||||||
"downloadScopeDescription": "Choose which emails should be indexed and downloaded.",
|
"downloadScopeDescription": "Choose which emails should be indexed and downloaded.",
|
||||||
"downloadStarted": "Download task started",
|
"downloadStarted": "Download task started",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Save changes",
|
"saveChanges": "Save changes",
|
||||||
|
"scheduleMode": "Download Schedule",
|
||||||
|
"scheduleModeCron": "Cron Expression",
|
||||||
|
"scheduleModeDescription": "Download via fixed intervals or Cron expressions.",
|
||||||
|
"scheduleModeInterval": "Fixed Interval",
|
||||||
"selectAccountType": "Select account type",
|
"selectAccountType": "Select account type",
|
||||||
"selectAtLeastOneFolder": "Please select at least one folder",
|
"selectAtLeastOneFolder": "Please select at least one folder",
|
||||||
"selectAuthMethod": "Select an authentication method",
|
"selectAuthMethod": "Select an authentication method",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAP port must be a positive integer",
|
"imapPortMustBePositive": "IMAP port must be a positive integer",
|
||||||
"incrementalSyncMustBeAtLeast10": "Incremental sync interval must be at least 10 minutes",
|
"incrementalSyncMustBeAtLeast10": "Incremental sync interval must be at least 10 minutes",
|
||||||
"incrementalSyncMustBeNumber": "Incremental sync interval must be a number",
|
"incrementalSyncMustBeNumber": "Incremental sync interval must be a number",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "Password must be at least {{min}} characters long",
|
"passwordMinLength": "Password must be at least {{min}} characters long",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Continuar",
|
"continue": "Continuar",
|
||||||
"createdAt": "Creado el",
|
"createdAt": "Creado el",
|
||||||
"creationFailed": "Error al crear, por favor, inténtalo de nuevo más tarde",
|
"creationFailed": "Error al crear, por favor, inténtalo de nuevo más tarde",
|
||||||
|
"cronAdvanced": "Expresión avanzada",
|
||||||
|
"cronDaily": "Diario",
|
||||||
|
"cronDayOfMonth": "Día de la semana",
|
||||||
|
"cronDayOfWeek": "Día de la semana",
|
||||||
|
"cronFrequency": "Frecuencia",
|
||||||
|
"cronFriday": "Viernes",
|
||||||
|
"cronHour": "Hora",
|
||||||
|
"cronMinute": "Minuto",
|
||||||
|
"cronMonday": "Lunes",
|
||||||
|
"cronMonthly": "Mensual",
|
||||||
|
"cronSaturday": "Sábado",
|
||||||
|
"cronSimple": "Expresión simple",
|
||||||
|
"cronSunday": "Domingo",
|
||||||
|
"cronThursday": "Jueves",
|
||||||
|
"cronTimezoneNote": "Horas en zona horaria del servidor.",
|
||||||
|
"cronTuesday": "Martes",
|
||||||
|
"cronWednesday": "Miércoles",
|
||||||
|
"cronWeekly": "Semanal",
|
||||||
"dateSelection": "Selección de fecha",
|
"dateSelection": "Selección de fecha",
|
||||||
"dateSince": "Fecha desde",
|
"dateSince": "Fecha desde",
|
||||||
"days": "Días",
|
"days": "Días",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Error al iniciar la tarea de descarga",
|
"downloadFailed": "Error al iniciar la tarea de descarga",
|
||||||
"downloadInterval": "Intervalo de descarga (minutos)",
|
"downloadInterval": "Intervalo de descarga (minutos)",
|
||||||
"downloadIntervalPlaceholder": "Ingresa los minutos",
|
"downloadIntervalPlaceholder": "Ingresa los minutos",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "Cron de 6 campos (seg min hora día mes día-sem) en hora del servidor. Anula intervalo.",
|
||||||
|
"downloadSchedulePlaceholder": "ej., 0 0 * * *",
|
||||||
"downloadScope": "Estrategia de descarga",
|
"downloadScope": "Estrategia de descarga",
|
||||||
"downloadScopeDescription": "Elija qué correos electrónicos deben indexarse y descargarse.",
|
"downloadScopeDescription": "Elija qué correos electrónicos deben indexarse y descargarse.",
|
||||||
"downloadStarted": "Tarea de descarga iniciada",
|
"downloadStarted": "Tarea de descarga iniciada",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Guardar cambios",
|
"saveChanges": "Guardar cambios",
|
||||||
|
"scheduleMode": "Programación de descarga",
|
||||||
|
"scheduleModeCron": "Expresión Cron",
|
||||||
|
"scheduleModeDescription": "Descarga por intervalos fijos o expresiones Cron.",
|
||||||
|
"scheduleModeInterval": "Intervalo fijo",
|
||||||
"selectAccountType": "Seleccionar tipo de cuenta",
|
"selectAccountType": "Seleccionar tipo de cuenta",
|
||||||
"selectAtLeastOneFolder": "Selecciona al menos una carpeta",
|
"selectAtLeastOneFolder": "Selecciona al menos una carpeta",
|
||||||
"selectAuthMethod": "Selecciona el método de autenticación",
|
"selectAuthMethod": "Selecciona el método de autenticación",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "El puerto IMAP debe ser un número entero positivo",
|
"imapPortMustBePositive": "El puerto IMAP debe ser un número entero positivo",
|
||||||
"incrementalSyncMustBeAtLeast10": "El intervalo de sincronización incremental debe ser de al menos 10 minutos",
|
"incrementalSyncMustBeAtLeast10": "El intervalo de sincronización incremental debe ser de al menos 10 minutos",
|
||||||
"incrementalSyncMustBeNumber": "El intervalo de sincronización incremental debe ser un número",
|
"incrementalSyncMustBeNumber": "El intervalo de sincronización incremental debe ser un número",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "La contraseña debe tener al menos {{min}} caracteres",
|
"passwordMinLength": "La contraseña debe tener al menos {{min}} caracteres",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Jatka",
|
"continue": "Jatka",
|
||||||
"createdAt": "Luotu",
|
"createdAt": "Luotu",
|
||||||
"creationFailed": "Luominen epäonnistui, yritä myöhemmin uudelleen",
|
"creationFailed": "Luominen epäonnistui, yritä myöhemmin uudelleen",
|
||||||
|
"cronAdvanced": "Edistynyt lauseke",
|
||||||
|
"cronDaily": "Päivittäin",
|
||||||
|
"cronDayOfMonth": "Viikonpäivä",
|
||||||
|
"cronDayOfWeek": "Viikonpäivä",
|
||||||
|
"cronFrequency": "Tiheys",
|
||||||
|
"cronFriday": "Perjantai",
|
||||||
|
"cronHour": "Tunti",
|
||||||
|
"cronMinute": "Minuutti",
|
||||||
|
"cronMonday": "Maanantai",
|
||||||
|
"cronMonthly": "Kuukausittain",
|
||||||
|
"cronSaturday": "Lauantai",
|
||||||
|
"cronSimple": "Yksinkertainen lauseke",
|
||||||
|
"cronSunday": "Sunnuntai",
|
||||||
|
"cronThursday": "Torstai",
|
||||||
|
"cronTimezoneNote": "Kaikki ajat palvelimen paikallista aikaa.",
|
||||||
|
"cronTuesday": "Tiistai",
|
||||||
|
"cronWednesday": "Keskiviikko",
|
||||||
|
"cronWeekly": "Viikoittain",
|
||||||
"dateSelection": "Päivämäärän valinta",
|
"dateSelection": "Päivämäärän valinta",
|
||||||
"dateSince": "Päivämäärä alkaen",
|
"dateSince": "Päivämäärä alkaen",
|
||||||
"days": "Päivää",
|
"days": "Päivää",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Lataustehtävän aloittaminen epäonnistui",
|
"downloadFailed": "Lataustehtävän aloittaminen epäonnistui",
|
||||||
"downloadInterval": "Latausväli (minuuttia)",
|
"downloadInterval": "Latausväli (minuuttia)",
|
||||||
"downloadIntervalPlaceholder": "Syötä minuutit",
|
"downloadIntervalPlaceholder": "Syötä minuutit",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "6-kenttäinen Cron (sek min tun pv kk vkpv) palvelimen ajassa. Korvaa aikavälin.",
|
||||||
|
"downloadSchedulePlaceholder": "esim. 0 0 * * *",
|
||||||
"downloadScope": "Latausstrategia",
|
"downloadScope": "Latausstrategia",
|
||||||
"downloadScopeDescription": "Valitse, mitkä sähköpostit indeksoidaan ja ladataan.",
|
"downloadScopeDescription": "Valitse, mitkä sähköpostit indeksoidaan ja ladataan.",
|
||||||
"downloadStarted": "Lataustehtävä aloitettu",
|
"downloadStarted": "Lataustehtävä aloitettu",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Tallenna muutokset",
|
"saveChanges": "Tallenna muutokset",
|
||||||
|
"scheduleMode": "Latauksen ajoitus",
|
||||||
|
"scheduleModeCron": "Cron-lauseke",
|
||||||
|
"scheduleModeDescription": "Lataa säännöllisin väliajoin tai Cron-lausekkeella.",
|
||||||
|
"scheduleModeInterval": "Säännöllinen väliaika",
|
||||||
"selectAccountType": "Valitse tilityyppi",
|
"selectAccountType": "Valitse tilityyppi",
|
||||||
"selectAtLeastOneFolder": "Valitse vähintään yksi kansio",
|
"selectAtLeastOneFolder": "Valitse vähintään yksi kansio",
|
||||||
"selectAuthMethod": "Valitse todennusmenetelmä",
|
"selectAuthMethod": "Valitse todennusmenetelmä",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAP-portin on oltava positiivinen kokonaisluku",
|
"imapPortMustBePositive": "IMAP-portin on oltava positiivinen kokonaisluku",
|
||||||
"incrementalSyncMustBeAtLeast10": "Lisäävän synkronoinnin välin on oltava vähintään 10 minuuttia",
|
"incrementalSyncMustBeAtLeast10": "Lisäävän synkronoinnin välin on oltava vähintään 10 minuuttia",
|
||||||
"incrementalSyncMustBeNumber": "Lisäävän synkronoinnin välin on oltava numero",
|
"incrementalSyncMustBeNumber": "Lisäävän synkronoinnin välin on oltava numero",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "Salasanan on oltava vähintään {{min}} merkkiä pitkä",
|
"passwordMinLength": "Salasanan on oltava vähintään {{min}} merkkiä pitkä",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Continuer",
|
"continue": "Continuer",
|
||||||
"createdAt": "Créé le",
|
"createdAt": "Créé le",
|
||||||
"creationFailed": "La création a échoué, veuillez réessayer plus tard",
|
"creationFailed": "La création a échoué, veuillez réessayer plus tard",
|
||||||
|
"cronAdvanced": "Expression avancée",
|
||||||
|
"cronDaily": "Chaque jour",
|
||||||
|
"cronDayOfMonth": "Jour de la semaine",
|
||||||
|
"cronDayOfWeek": "Jour de la semaine",
|
||||||
|
"cronFrequency": "Fréquence",
|
||||||
|
"cronFriday": "Vendredi",
|
||||||
|
"cronHour": "Heure",
|
||||||
|
"cronMinute": "Minute",
|
||||||
|
"cronMonday": "Lundi",
|
||||||
|
"cronMonthly": "Chaque mois",
|
||||||
|
"cronSaturday": "Samedi",
|
||||||
|
"cronSimple": "Expression simple",
|
||||||
|
"cronSunday": "Dimanche",
|
||||||
|
"cronThursday": "Jeudi",
|
||||||
|
"cronTimezoneNote": "Heures au fuseau horaire du serveur.",
|
||||||
|
"cronTuesday": "Mardi",
|
||||||
|
"cronWednesday": "Mercredi",
|
||||||
|
"cronWeekly": "Chaque semaine",
|
||||||
"dateSelection": "Sélection de Date",
|
"dateSelection": "Sélection de Date",
|
||||||
"dateSince": "Date Depuis",
|
"dateSince": "Date Depuis",
|
||||||
"days": "Jours",
|
"days": "Jours",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Échec du lancement de la tâche de téléchargement",
|
"downloadFailed": "Échec du lancement de la tâche de téléchargement",
|
||||||
"downloadInterval": "Intervalle de téléchargement (minutes)",
|
"downloadInterval": "Intervalle de téléchargement (minutes)",
|
||||||
"downloadIntervalPlaceholder": "Entrer les minutes",
|
"downloadIntervalPlaceholder": "Entrer les minutes",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "Cron à 6 champs (sec min heure jour mois jour-sem) à l'heure du serveur. Remplace l'intervalle.",
|
||||||
|
"downloadSchedulePlaceholder": "ex. 0 0 * * *",
|
||||||
"downloadScope": "Stratégie de téléchargement",
|
"downloadScope": "Stratégie de téléchargement",
|
||||||
"downloadScopeDescription": "Choisissez les e-mails à indexer et à télécharger.",
|
"downloadScopeDescription": "Choisissez les e-mails à indexer et à télécharger.",
|
||||||
"downloadStarted": "Tâche de téléchargement lancée",
|
"downloadStarted": "Tâche de téléchargement lancée",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Enregistrer les Modifications",
|
"saveChanges": "Enregistrer les Modifications",
|
||||||
|
"scheduleMode": "Planification de téléchargement",
|
||||||
|
"scheduleModeCron": "Expression Cron",
|
||||||
|
"scheduleModeDescription": "Téléchargement par intervalle fixe ou expression Cron.",
|
||||||
|
"scheduleModeInterval": "Intervalle fixe",
|
||||||
"selectAccountType": "Sélectionner le type de compte",
|
"selectAccountType": "Sélectionner le type de compte",
|
||||||
"selectAtLeastOneFolder": "Veuillez sélectionner au moins un dossier",
|
"selectAtLeastOneFolder": "Veuillez sélectionner au moins un dossier",
|
||||||
"selectAuthMethod": "Sélectionner une méthode d'authentification",
|
"selectAuthMethod": "Sélectionner une méthode d'authentification",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "Le port IMAP doit être un entier positif",
|
"imapPortMustBePositive": "Le port IMAP doit être un entier positif",
|
||||||
"incrementalSyncMustBeAtLeast10": "L'intervalle de synchronisation incrémentielle doit être d'au moins 10 minutes",
|
"incrementalSyncMustBeAtLeast10": "L'intervalle de synchronisation incrémentielle doit être d'au moins 10 minutes",
|
||||||
"incrementalSyncMustBeNumber": "L'intervalle de synchronisation incrémentielle doit être un nombre",
|
"incrementalSyncMustBeNumber": "L'intervalle de synchronisation incrémentielle doit être un nombre",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "Le mot de passe doit contenir au moins {{min}} caractères",
|
"passwordMinLength": "Le mot de passe doit contenir au moins {{min}} caractères",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Continua",
|
"continue": "Continua",
|
||||||
"createdAt": "Creato Il",
|
"createdAt": "Creato Il",
|
||||||
"creationFailed": "Creazione fallita, riprova più tardi",
|
"creationFailed": "Creazione fallita, riprova più tardi",
|
||||||
|
"cronAdvanced": "Espressione avanzata",
|
||||||
|
"cronDaily": "Ogni giorno",
|
||||||
|
"cronDayOfMonth": "Giorno della settimana",
|
||||||
|
"cronDayOfWeek": "Giorno della settimana",
|
||||||
|
"cronFrequency": "Frequenza",
|
||||||
|
"cronFriday": "Venerdì",
|
||||||
|
"cronHour": "Ora",
|
||||||
|
"cronMinute": "Minuto",
|
||||||
|
"cronMonday": "Lunedì",
|
||||||
|
"cronMonthly": "Ogni mese",
|
||||||
|
"cronSaturday": "Sabato",
|
||||||
|
"cronSimple": "Espressione semplice",
|
||||||
|
"cronSunday": "Domenica",
|
||||||
|
"cronThursday": "Giovedì",
|
||||||
|
"cronTimezoneNote": "Orari nel fuso orario del server.",
|
||||||
|
"cronTuesday": "Martedì",
|
||||||
|
"cronWednesday": "Mercoledì",
|
||||||
|
"cronWeekly": "Ogni settimana",
|
||||||
"dateSelection": "Selezione Data",
|
"dateSelection": "Selezione Data",
|
||||||
"dateSince": "Data Da",
|
"dateSince": "Data Da",
|
||||||
"days": "Giorni",
|
"days": "Giorni",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Avvio attività di download non riuscito",
|
"downloadFailed": "Avvio attività di download non riuscito",
|
||||||
"downloadInterval": "Intervallo di download (minuti)",
|
"downloadInterval": "Intervallo di download (minuti)",
|
||||||
"downloadIntervalPlaceholder": "Inserisci i minuti",
|
"downloadIntervalPlaceholder": "Inserisci i minuti",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "Cron a 6 campi (sec min ora giorno mese giorno-sett) in ora del server. Sostituisce l'intervallo.",
|
||||||
|
"downloadSchedulePlaceholder": "es. 0 0 * * *",
|
||||||
"downloadScope": "Strategia di download",
|
"downloadScope": "Strategia di download",
|
||||||
"downloadScopeDescription": "Scegli quali email indicizzare e scaricare.",
|
"downloadScopeDescription": "Scegli quali email indicizzare e scaricare.",
|
||||||
"downloadStarted": "Attività di download avviata",
|
"downloadStarted": "Attività di download avviata",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Salva Modifiche",
|
"saveChanges": "Salva Modifiche",
|
||||||
|
"scheduleMode": "Pianificazione del download",
|
||||||
|
"scheduleModeCron": "Espressione Cron",
|
||||||
|
"scheduleModeDescription": "Download a intervalli fissi o tramite espressioni Cron.",
|
||||||
|
"scheduleModeInterval": "Intervallo fisso",
|
||||||
"selectAccountType": "Seleziona tipo di account",
|
"selectAccountType": "Seleziona tipo di account",
|
||||||
"selectAtLeastOneFolder": "Seleziona almeno una cartella",
|
"selectAtLeastOneFolder": "Seleziona almeno una cartella",
|
||||||
"selectAuthMethod": "Seleziona un metodo di autenticazione",
|
"selectAuthMethod": "Seleziona un metodo di autenticazione",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "La porta IMAP deve essere un numero intero positivo",
|
"imapPortMustBePositive": "La porta IMAP deve essere un numero intero positivo",
|
||||||
"incrementalSyncMustBeAtLeast10": "L'intervallo di sincronizzazione incrementale deve essere di almeno 10 minuti",
|
"incrementalSyncMustBeAtLeast10": "L'intervallo di sincronizzazione incrementale deve essere di almeno 10 minuti",
|
||||||
"incrementalSyncMustBeNumber": "L'intervallo di sincronizzazione incrementale deve essere un numero",
|
"incrementalSyncMustBeNumber": "L'intervallo di sincronizzazione incrementale deve essere un numero",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "La password deve contenere almeno {{min}} caratteri",
|
"passwordMinLength": "La password deve contenere almeno {{min}} caratteri",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "続行",
|
"continue": "続行",
|
||||||
"createdAt": "作成日時",
|
"createdAt": "作成日時",
|
||||||
"creationFailed": "作成に失敗しました。しばらくしてからもう一度お試しください。",
|
"creationFailed": "作成に失敗しました。しばらくしてからもう一度お試しください。",
|
||||||
|
"cronAdvanced": "高度な式",
|
||||||
|
"cronDaily": "毎日",
|
||||||
|
"cronDayOfMonth": "曜日",
|
||||||
|
"cronDayOfWeek": "曜日",
|
||||||
|
"cronFrequency": "頻度",
|
||||||
|
"cronFriday": "金曜日",
|
||||||
|
"cronHour": "时",
|
||||||
|
"cronMinute": "分",
|
||||||
|
"cronMonday": "月曜日",
|
||||||
|
"cronMonthly": "毎月",
|
||||||
|
"cronSaturday": "土曜日",
|
||||||
|
"cronSimple": "簡易式",
|
||||||
|
"cronSunday": "日曜日",
|
||||||
|
"cronThursday": "木曜日",
|
||||||
|
"cronTimezoneNote": "時間はサーバーの現地時間です。",
|
||||||
|
"cronTuesday": "火曜日",
|
||||||
|
"cronWednesday": "水曜日",
|
||||||
|
"cronWeekly": "毎週",
|
||||||
"dateSelection": "日付選択",
|
"dateSelection": "日付選択",
|
||||||
"dateSince": "同期開始日",
|
"dateSince": "同期開始日",
|
||||||
"days": "日",
|
"days": "日",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "ダウンロードタスクの起動に失敗しました",
|
"downloadFailed": "ダウンロードタスクの起動に失敗しました",
|
||||||
"downloadInterval": "ダウンロード間隔 (分)",
|
"downloadInterval": "ダウンロード間隔 (分)",
|
||||||
"downloadIntervalPlaceholder": "分を入力してください",
|
"downloadIntervalPlaceholder": "分を入力してください",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "サーバー時間の6フィールドCron式(秒分時日月曜日)。設定値より優先。",
|
||||||
|
"downloadSchedulePlaceholder": "例:0 0 * * *",
|
||||||
"downloadScope": "ダウンロード戦略",
|
"downloadScope": "ダウンロード戦略",
|
||||||
"downloadScopeDescription": "インデックスとダウンロードの対象となるメールを選択してください。",
|
"downloadScopeDescription": "インデックスとダウンロードの対象となるメールを選択してください。",
|
||||||
"downloadStarted": "ダウンロードタスクを開始しました",
|
"downloadStarted": "ダウンロードタスクを開始しました",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "変更を保存",
|
"saveChanges": "変更を保存",
|
||||||
|
"scheduleMode": "ダウンロードスケジュール",
|
||||||
|
"scheduleModeCron": "Cron式",
|
||||||
|
"scheduleModeDescription": "固定間隔またはCron式でダウンロード。",
|
||||||
|
"scheduleModeInterval": "固定間隔",
|
||||||
"selectAccountType": "アカウントの種類を選択",
|
"selectAccountType": "アカウントの種類を選択",
|
||||||
"selectAtLeastOneFolder": "少なくとも1つのフォルダーを選択してください",
|
"selectAtLeastOneFolder": "少なくとも1つのフォルダーを選択してください",
|
||||||
"selectAuthMethod": "認証方式を選択",
|
"selectAuthMethod": "認証方式を選択",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAPポートは正の整数である必要があります",
|
"imapPortMustBePositive": "IMAPポートは正の整数である必要があります",
|
||||||
"incrementalSyncMustBeAtLeast10": "増分同期間隔は10分以上である必要があります",
|
"incrementalSyncMustBeAtLeast10": "増分同期間隔は10分以上である必要があります",
|
||||||
"incrementalSyncMustBeNumber": "増分同期間隔は数値である必要があります",
|
"incrementalSyncMustBeNumber": "増分同期間隔は数値である必要があります",
|
||||||
|
"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です",
|
||||||
"passwordMinLength": "パスワードは{{min}}文字以上である必要があります",
|
"passwordMinLength": "パスワードは{{min}}文字以上である必要があります",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "계속",
|
"continue": "계속",
|
||||||
"createdAt": "생성일",
|
"createdAt": "생성일",
|
||||||
"creationFailed": "생성에 실패했습니다. 나중에 다시 시도하십시오.",
|
"creationFailed": "생성에 실패했습니다. 나중에 다시 시도하십시오.",
|
||||||
|
"cronAdvanced": "고급 표현식",
|
||||||
|
"cronDaily": "매일",
|
||||||
|
"cronDayOfMonth": "요일",
|
||||||
|
"cronDayOfWeek": "요일",
|
||||||
|
"cronFrequency": "주기",
|
||||||
|
"cronFriday": "금요일",
|
||||||
|
"cronHour": "시",
|
||||||
|
"cronMinute": "분",
|
||||||
|
"cronMonday": "월요일",
|
||||||
|
"cronMonthly": "매월",
|
||||||
|
"cronSaturday": "토요일",
|
||||||
|
"cronSimple": "간단한 표현식",
|
||||||
|
"cronSunday": "일요일",
|
||||||
|
"cronThursday": "목요일",
|
||||||
|
"cronTimezoneNote": "모든 시간은 서버 현지 시간 기준입니다.",
|
||||||
|
"cronTuesday": "화요일",
|
||||||
|
"cronWednesday": "수요일",
|
||||||
|
"cronWeekly": "매주",
|
||||||
"dateSelection": "날짜 선택",
|
"dateSelection": "날짜 선택",
|
||||||
"dateSince": "동기화 시작일",
|
"dateSince": "동기화 시작일",
|
||||||
"days": "일",
|
"days": "일",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "다운로드 작업 시작 실패",
|
"downloadFailed": "다운로드 작업 시작 실패",
|
||||||
"downloadInterval": "다운로드 주기 (분)",
|
"downloadInterval": "다운로드 주기 (분)",
|
||||||
"downloadIntervalPlaceholder": "분 단위 입력",
|
"downloadIntervalPlaceholder": "분 단위 입력",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "서버 시간 기준 6필드 Cron(초 분 시 일 월 요일). 간격 설정보다 우선됨.",
|
||||||
|
"downloadSchedulePlaceholder": "예: 0 0 * * *",
|
||||||
"downloadScope": "다운로드 전략",
|
"downloadScope": "다운로드 전략",
|
||||||
"downloadScopeDescription": "색인화 및 다운로드할 이메일을 선택하십시오.",
|
"downloadScopeDescription": "색인화 및 다운로드할 이메일을 선택하십시오.",
|
||||||
"downloadStarted": "다운로드 작업 시작됨",
|
"downloadStarted": "다운로드 작업 시작됨",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "변경 사항 저장",
|
"saveChanges": "변경 사항 저장",
|
||||||
|
"scheduleMode": "다운로드 일정",
|
||||||
|
"scheduleModeCron": "Cron 표현식",
|
||||||
|
"scheduleModeDescription": "고정 간격 또는 Cron 표현식으로 다운로드.",
|
||||||
|
"scheduleModeInterval": "고정 간격",
|
||||||
"selectAccountType": "계정 유형 선택",
|
"selectAccountType": "계정 유형 선택",
|
||||||
"selectAtLeastOneFolder": "하나 이상의 폴더를 선택하십시오",
|
"selectAtLeastOneFolder": "하나 이상의 폴더를 선택하십시오",
|
||||||
"selectAuthMethod": "인증 방법 선택",
|
"selectAuthMethod": "인증 방법 선택",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAP 포트는 양의 정수여야 합니다",
|
"imapPortMustBePositive": "IMAP 포트는 양의 정수여야 합니다",
|
||||||
"incrementalSyncMustBeAtLeast10": "증분 동기화 간격은 최소 10분 이상이어야 합니다",
|
"incrementalSyncMustBeAtLeast10": "증분 동기화 간격은 최소 10분 이상이어야 합니다",
|
||||||
"incrementalSyncMustBeNumber": "증분 동기화 간격은 숫자여야 합니다",
|
"incrementalSyncMustBeNumber": "증분 동기화 간격은 숫자여야 합니다",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "비밀번호는 {{min}}자 이상이어야 합니다",
|
"passwordMinLength": "비밀번호는 {{min}}자 이상이어야 합니다",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Doorgaan",
|
"continue": "Doorgaan",
|
||||||
"createdAt": "Aangemaakt Op",
|
"createdAt": "Aangemaakt Op",
|
||||||
"creationFailed": "Aanmaken mislukt, probeer het later opnieuw",
|
"creationFailed": "Aanmaken mislukt, probeer het later opnieuw",
|
||||||
|
"cronAdvanced": "Geavanceerde expressie",
|
||||||
|
"cronDaily": "Dagelijks",
|
||||||
|
"cronDayOfMonth": "Dag van de week",
|
||||||
|
"cronDayOfWeek": "Dag van de week",
|
||||||
|
"cronFrequency": "Frequentie",
|
||||||
|
"cronFriday": "Vrijdag",
|
||||||
|
"cronHour": "Uur",
|
||||||
|
"cronMinute": "Minuut",
|
||||||
|
"cronMonday": "Maandag",
|
||||||
|
"cronMonthly": "Maandelijks",
|
||||||
|
"cronSaturday": "Zaterdag",
|
||||||
|
"cronSimple": "Simpele expressie",
|
||||||
|
"cronSunday": "Zondag",
|
||||||
|
"cronThursday": "Donderdag",
|
||||||
|
"cronTimezoneNote": "Alle tijden zijn server-lokale tijd.",
|
||||||
|
"cronTuesday": "Dinsdag",
|
||||||
|
"cronWednesday": "Woensdag",
|
||||||
|
"cronWeekly": "Wekelijks",
|
||||||
"dateSelection": "Datumselectie",
|
"dateSelection": "Datumselectie",
|
||||||
"dateSince": "Datum Sinds",
|
"dateSince": "Datum Sinds",
|
||||||
"days": "Dagen",
|
"days": "Dagen",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Downloadtaak starten mislukt",
|
"downloadFailed": "Downloadtaak starten mislukt",
|
||||||
"downloadInterval": "Download-interval (minuten)",
|
"downloadInterval": "Download-interval (minuten)",
|
||||||
"downloadIntervalPlaceholder": "Voer minuten in",
|
"downloadIntervalPlaceholder": "Voer minuten in",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "6-velds Cron (sec min uur dag maand dag-week) in servertijd. Overschrijft interval.",
|
||||||
|
"downloadSchedulePlaceholder": "bijv. 0 0 * * *",
|
||||||
"downloadScope": "Downloadstrategie",
|
"downloadScope": "Downloadstrategie",
|
||||||
"downloadScopeDescription": "Kies welke e-mails moeten worden geïndexeerd en gedownload.",
|
"downloadScopeDescription": "Kies welke e-mails moeten worden geïndexeerd en gedownload.",
|
||||||
"downloadStarted": "Downloadtaak gestart",
|
"downloadStarted": "Downloadtaak gestart",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Wijzigingen opslaan",
|
"saveChanges": "Wijzigingen opslaan",
|
||||||
|
"scheduleMode": "Downloadschema",
|
||||||
|
"scheduleModeCron": "Cron-expressie",
|
||||||
|
"scheduleModeDescription": "Downloaden via vaste intervallen o f Cron-expressies.",
|
||||||
|
"scheduleModeInterval": "Vast interval",
|
||||||
"selectAccountType": "Selecteer accounttype",
|
"selectAccountType": "Selecteer accounttype",
|
||||||
"selectAtLeastOneFolder": "Selecteer alstublieft ten minste één map",
|
"selectAtLeastOneFolder": "Selecteer alstublieft ten minste één map",
|
||||||
"selectAuthMethod": "Selecteer een authenticatiemethode",
|
"selectAuthMethod": "Selecteer een authenticatiemethode",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAP poort moet een positief geheel getal zijn",
|
"imapPortMustBePositive": "IMAP poort moet een positief geheel getal zijn",
|
||||||
"incrementalSyncMustBeAtLeast10": "Incrementaal sync interval moet ten minste 10 minuten zijn",
|
"incrementalSyncMustBeAtLeast10": "Incrementaal sync interval moet ten minste 10 minuten zijn",
|
||||||
"incrementalSyncMustBeNumber": "Incrementaal sync interval moet een nummer zijn",
|
"incrementalSyncMustBeNumber": "Incrementaal sync interval moet een nummer zijn",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "Wachtwoord moet ten minste {{min}} tekens lang zijn",
|
"passwordMinLength": "Wachtwoord moet ten minste {{min}} tekens lang zijn",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Fortsett",
|
"continue": "Fortsett",
|
||||||
"createdAt": "Opprettet",
|
"createdAt": "Opprettet",
|
||||||
"creationFailed": "Opprettelse mislyktes, prøv igjen senere",
|
"creationFailed": "Opprettelse mislyktes, prøv igjen senere",
|
||||||
|
"cronAdvanced": "Avansert uttrykk",
|
||||||
|
"cronDaily": "Daglig",
|
||||||
|
"cronDayOfMonth": "Ugedag",
|
||||||
|
"cronDayOfWeek": "Ugedag",
|
||||||
|
"cronFrequency": "Frekvens",
|
||||||
|
"cronFriday": "Fredag",
|
||||||
|
"cronHour": "Time",
|
||||||
|
"cronMinute": "Minutt",
|
||||||
|
"cronMonday": "Mandag",
|
||||||
|
"cronMonthly": "Månedlig",
|
||||||
|
"cronSaturday": "Lørdag",
|
||||||
|
"cronSimple": "Enkelt uttrykk",
|
||||||
|
"cronSunday": "Søndag",
|
||||||
|
"cronThursday": "Torsdag",
|
||||||
|
"cronTimezoneNote": "Alle klokkeslett er serverens lokaltid.",
|
||||||
|
"cronTuesday": "Tirsdag",
|
||||||
|
"cronWednesday": "Onsdag",
|
||||||
|
"cronWeekly": "Ukentlig",
|
||||||
"dateSelection": "Datovalg",
|
"dateSelection": "Datovalg",
|
||||||
"dateSince": "Dato siden",
|
"dateSince": "Dato siden",
|
||||||
"days": "Dager",
|
"days": "Dager",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Kunne ikke starte nedlastingsoppgave",
|
"downloadFailed": "Kunne ikke starte nedlastingsoppgave",
|
||||||
"downloadInterval": "Nedlastingsintervall (minutter)",
|
"downloadInterval": "Nedlastingsintervall (minutter)",
|
||||||
"downloadIntervalPlaceholder": "Skriv inn minutter",
|
"downloadIntervalPlaceholder": "Skriv inn minutter",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "6-felts Cron (sek min time dag mdr ukedag) i servertid. Overstyrer intervall.",
|
||||||
|
"downloadSchedulePlaceholder": "f.eks.: 0 0 * * *",
|
||||||
"downloadScope": "Nedlastingsstrategi",
|
"downloadScope": "Nedlastingsstrategi",
|
||||||
"downloadScopeDescription": "Velg hvilke e-poster som skal indekseres og lastes ned.",
|
"downloadScopeDescription": "Velg hvilke e-poster som skal indekseres og lastes ned.",
|
||||||
"downloadStarted": "Nedlastingsoppgave startet",
|
"downloadStarted": "Nedlastingsoppgave startet",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Lagre endringer",
|
"saveChanges": "Lagre endringer",
|
||||||
|
"scheduleMode": "Nedlastingsplan",
|
||||||
|
"scheduleModeCron": "Cron-uttrykk",
|
||||||
|
"scheduleModeDescription": "Nedlasting med faste intervaller eller Cron-uttrykk.",
|
||||||
|
"scheduleModeInterval": "Fast intervall",
|
||||||
"selectAccountType": "Velg kontotype",
|
"selectAccountType": "Velg kontotype",
|
||||||
"selectAtLeastOneFolder": "Vennligst velg minst én mappe",
|
"selectAtLeastOneFolder": "Vennligst velg minst én mappe",
|
||||||
"selectAuthMethod": "Velg en autentiseringsmetode",
|
"selectAuthMethod": "Velg en autentiseringsmetode",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAP-port må være et positivt heltall",
|
"imapPortMustBePositive": "IMAP-port må være et positivt heltall",
|
||||||
"incrementalSyncMustBeAtLeast10": "Intervall for inkrementell synkronisering må være minst 10 minutter",
|
"incrementalSyncMustBeAtLeast10": "Intervall for inkrementell synkronisering må være minst 10 minutter",
|
||||||
"incrementalSyncMustBeNumber": "Intervall for inkrementell synkronisering må være et tall",
|
"incrementalSyncMustBeNumber": "Intervall for inkrementell synkronisering må være et tall",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "Passordet må være minst {{min}} tegn langt",
|
"passwordMinLength": "Passordet må være minst {{min}} tegn langt",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Kontynuj",
|
"continue": "Kontynuj",
|
||||||
"createdAt": "Utworzono",
|
"createdAt": "Utworzono",
|
||||||
"creationFailed": "Bład tworzenia, spróbuj później",
|
"creationFailed": "Bład tworzenia, spróbuj później",
|
||||||
|
"cronAdvanced": "Zaawansowane wyrażenie",
|
||||||
|
"cronDaily": "Codziennie",
|
||||||
|
"cronDayOfMonth": "Dzień tygodnia",
|
||||||
|
"cronDayOfWeek": "Dzień tygodnia",
|
||||||
|
"cronFrequency": "Częstotliwość",
|
||||||
|
"cronFriday": "Piątek",
|
||||||
|
"cronHour": "Godzina",
|
||||||
|
"cronMinute": "Minuta",
|
||||||
|
"cronMonday": "Poniedziałek",
|
||||||
|
"cronMonthly": "Co miesiąc",
|
||||||
|
"cronSaturday": "Sobota",
|
||||||
|
"cronSimple": "Proste wyrażenie",
|
||||||
|
"cronSunday": "Niedziela",
|
||||||
|
"cronThursday": "Czwartek",
|
||||||
|
"cronTimezoneNote": "Czas według lokalnej strefy serwera.",
|
||||||
|
"cronTuesday": "Wtorek",
|
||||||
|
"cronWednesday": "Środa",
|
||||||
|
"cronWeekly": "Co tydzień",
|
||||||
"dateSelection": "Zaznaczenie daty",
|
"dateSelection": "Zaznaczenie daty",
|
||||||
"dateSince": "Od kiedy",
|
"dateSince": "Od kiedy",
|
||||||
"days": "Dni",
|
"days": "Dni",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Nie udało się uruchomić zadania pobierania",
|
"downloadFailed": "Nie udało się uruchomić zadania pobierania",
|
||||||
"downloadInterval": "Cykl pobierania (minuty)",
|
"downloadInterval": "Cykl pobierania (minuty)",
|
||||||
"downloadIntervalPlaceholder": "Wprowadź minuty",
|
"downloadIntervalPlaceholder": "Wprowadź minuty",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "6-polowy Cron (sek min godz dz msc dz-tyg) w czasie serwera. Nadpisuje interwał.",
|
||||||
|
"downloadSchedulePlaceholder": "np. 0 0 * * *",
|
||||||
"downloadScope": "Strategia pobierania",
|
"downloadScope": "Strategia pobierania",
|
||||||
"downloadScopeDescription": "Wybierz, które wiadomości e-mail mają być indeksowane i pobierane.",
|
"downloadScopeDescription": "Wybierz, które wiadomości e-mail mają być indeksowane i pobierane.",
|
||||||
"downloadStarted": "Uruchomiono zadanie pobierania",
|
"downloadStarted": "Uruchomiono zadanie pobierania",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Zapisz zmiany",
|
"saveChanges": "Zapisz zmiany",
|
||||||
|
"scheduleMode": "Harmonogram pobierania",
|
||||||
|
"scheduleModeCron": "Wyrażenie Cron",
|
||||||
|
"scheduleModeDescription": "Pobieranie w stałych odstępach lub przez wyrażenia Cron.",
|
||||||
|
"scheduleModeInterval": "Stały odstęp",
|
||||||
"selectAccountType": "Wybierz typ konta",
|
"selectAccountType": "Wybierz typ konta",
|
||||||
"selectAtLeastOneFolder": "Wybierz co najmniej jeden folder",
|
"selectAtLeastOneFolder": "Wybierz co najmniej jeden folder",
|
||||||
"selectAuthMethod": "Zaznacz metodę uwierzytelniania IMAP",
|
"selectAuthMethod": "Zaznacz metodę uwierzytelniania IMAP",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "Port IMAP musi być liczbą całkowitą dodatnią",
|
"imapPortMustBePositive": "Port IMAP musi być liczbą całkowitą dodatnią",
|
||||||
"incrementalSyncMustBeAtLeast10": "Przyrostowy interwał synchronizacji musi wynosić co najmniej 10 minut",
|
"incrementalSyncMustBeAtLeast10": "Przyrostowy interwał synchronizacji musi wynosić co najmniej 10 minut",
|
||||||
"incrementalSyncMustBeNumber": "Przyrostowy interwał synchronizacji musi być liczbą",
|
"incrementalSyncMustBeNumber": "Przyrostowy interwał synchronizacji musi być liczbą",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "Hasło musi posiadać conajmniej {{min}} znaków",
|
"passwordMinLength": "Hasło musi posiadać conajmniej {{min}} znaków",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Continuar",
|
"continue": "Continuar",
|
||||||
"createdAt": "Criado Em",
|
"createdAt": "Criado Em",
|
||||||
"creationFailed": "Falha na criação, por favor, tente novamente mais tarde.",
|
"creationFailed": "Falha na criação, por favor, tente novamente mais tarde.",
|
||||||
|
"cronAdvanced": "Expressão avançada",
|
||||||
|
"cronDaily": "Diariamente",
|
||||||
|
"cronDayOfMonth": "Dia da semana",
|
||||||
|
"cronDayOfWeek": "Dia da semana",
|
||||||
|
"cronFrequency": "Frequência",
|
||||||
|
"cronFriday": "Sexta-feira",
|
||||||
|
"cronHour": "Hora",
|
||||||
|
"cronMinute": "Minuto",
|
||||||
|
"cronMonday": "Segunda-feira",
|
||||||
|
"cronMonthly": "Mensalmente",
|
||||||
|
"cronSaturday": "Sábado",
|
||||||
|
"cronSimple": "Expressão simples",
|
||||||
|
"cronSunday": "Domingo",
|
||||||
|
"cronThursday": "Quinta-feira",
|
||||||
|
"cronTimezoneNote": "Horários no fuso horário do servidor.",
|
||||||
|
"cronTuesday": "Terça-feira",
|
||||||
|
"cronWednesday": "Quarta-feira",
|
||||||
|
"cronWeekly": "Semanalmente",
|
||||||
"dateSelection": "Seleção de Data",
|
"dateSelection": "Seleção de Data",
|
||||||
"dateSince": "Data de Início da Sincronização",
|
"dateSince": "Data de Início da Sincronização",
|
||||||
"days": "Dias",
|
"days": "Dias",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Falha ao iniciar tarefa de download",
|
"downloadFailed": "Falha ao iniciar tarefa de download",
|
||||||
"downloadInterval": "Intervalo de download (minutos)",
|
"downloadInterval": "Intervalo de download (minutos)",
|
||||||
"downloadIntervalPlaceholder": "Insira os minutos",
|
"downloadIntervalPlaceholder": "Insira os minutos",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "Cron de 6 campos (seg min hora dia mês dia-sem) na hora do servidor. Substitui o intervalo.",
|
||||||
|
"downloadSchedulePlaceholder": "ex: 0 0 * * *",
|
||||||
"downloadScope": "Estratégia de download",
|
"downloadScope": "Estratégia de download",
|
||||||
"downloadScopeDescription": "Escolha quais e-mails devem ser indexados e baixados.",
|
"downloadScopeDescription": "Escolha quais e-mails devem ser indexados e baixados.",
|
||||||
"downloadStarted": "Tarefa de download iniciada",
|
"downloadStarted": "Tarefa de download iniciada",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Salvar Alterações",
|
"saveChanges": "Salvar Alterações",
|
||||||
|
"scheduleMode": "Agendamento de download",
|
||||||
|
"scheduleModeCron": "Expressão Cron",
|
||||||
|
"scheduleModeDescription": "Download por intervalos fixos ou expressões Cron.",
|
||||||
|
"scheduleModeInterval": "Intervalo fixo",
|
||||||
"selectAccountType": "Selecionar tipo de conta",
|
"selectAccountType": "Selecionar tipo de conta",
|
||||||
"selectAtLeastOneFolder": "Por favor, selecione pelo menos uma pasta",
|
"selectAtLeastOneFolder": "Por favor, selecione pelo menos uma pasta",
|
||||||
"selectAuthMethod": "Selecionar Método de Autenticação",
|
"selectAuthMethod": "Selecionar Método de Autenticação",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "A Porta IMAP deve ser um número inteiro positivo",
|
"imapPortMustBePositive": "A Porta IMAP deve ser um número inteiro positivo",
|
||||||
"incrementalSyncMustBeAtLeast10": "O Intervalo de Sincronização Incremental deve ser de pelo menos 10 minutos",
|
"incrementalSyncMustBeAtLeast10": "O Intervalo de Sincronização Incremental deve ser de pelo menos 10 minutos",
|
||||||
"incrementalSyncMustBeNumber": "O Intervalo de Sincronização Incremental deve ser um número",
|
"incrementalSyncMustBeNumber": "O Intervalo de Sincronização Incremental deve ser um número",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "A senha deve ter pelo menos {{min}} caracteres",
|
"passwordMinLength": "A senha deve ter pelo menos {{min}} caracteres",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Продолжить",
|
"continue": "Продолжить",
|
||||||
"createdAt": "Создано",
|
"createdAt": "Создано",
|
||||||
"creationFailed": "Ошибка создания, попробуйте позже",
|
"creationFailed": "Ошибка создания, попробуйте позже",
|
||||||
|
"cronAdvanced": "Расширенное выражение",
|
||||||
|
"cronDaily": "Ежедневно",
|
||||||
|
"cronDayOfMonth": "День недели",
|
||||||
|
"cronDayOfWeek": "День недели",
|
||||||
|
"cronFrequency": "Частота",
|
||||||
|
"cronFriday": "Пятница",
|
||||||
|
"cronHour": "Час",
|
||||||
|
"cronMinute": "Минута",
|
||||||
|
"cronMonday": "Понедельник",
|
||||||
|
"cronMonthly": "Ежемесячно",
|
||||||
|
"cronSaturday": "Суббота",
|
||||||
|
"cronSimple": "Простое выражение",
|
||||||
|
"cronSunday": "Воскресенье",
|
||||||
|
"cronThursday": "Четверг",
|
||||||
|
"cronTimezoneNote": "Время по местному часовому поясу сервера.",
|
||||||
|
"cronTuesday": "Вторник",
|
||||||
|
"cronWednesday": "Среда",
|
||||||
|
"cronWeekly": "Еженедельно",
|
||||||
"dateSelection": "Выбор даты",
|
"dateSelection": "Выбор даты",
|
||||||
"dateSince": "Дата с",
|
"dateSince": "Дата с",
|
||||||
"days": "Дни",
|
"days": "Дни",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Не удалось запустить задачу загрузки",
|
"downloadFailed": "Не удалось запустить задачу загрузки",
|
||||||
"downloadInterval": "Интервал загрузки (мин.)",
|
"downloadInterval": "Интервал загрузки (мин.)",
|
||||||
"downloadIntervalPlaceholder": "Введите минуты",
|
"downloadIntervalPlaceholder": "Введите минуты",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "6-польный Cron (сек мин час день мес день-нед) по времени сервера. Меняет интервал.",
|
||||||
|
"downloadSchedulePlaceholder": "напр., 0 0 * * *",
|
||||||
"downloadScope": "Стратегия загрузки",
|
"downloadScope": "Стратегия загрузки",
|
||||||
"downloadScopeDescription": "Выберите, какие электронные письма должны быть проиндексированы и скачаны.",
|
"downloadScopeDescription": "Выберите, какие электронные письма должны быть проиндексированы и скачаны.",
|
||||||
"downloadStarted": "Задача загрузки запущена",
|
"downloadStarted": "Задача загрузки запущена",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Сохранить изменения",
|
"saveChanges": "Сохранить изменения",
|
||||||
|
"scheduleMode": "Расписание загрузки",
|
||||||
|
"scheduleModeCron": "Выражение Cron",
|
||||||
|
"scheduleModeDescription": "Загрузка с фиксированным интервалом или по Cron.",
|
||||||
|
"scheduleModeInterval": "Фиксированный интервал",
|
||||||
"selectAccountType": "Выберите тип аккаунта",
|
"selectAccountType": "Выберите тип аккаунта",
|
||||||
"selectAtLeastOneFolder": "Пожалуйста, выберите хотя бы одну папку",
|
"selectAtLeastOneFolder": "Пожалуйста, выберите хотя бы одну папку",
|
||||||
"selectAuthMethod": "Выберите метод авторизации",
|
"selectAuthMethod": "Выберите метод авторизации",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAP порт должен быть положительным целым числом",
|
"imapPortMustBePositive": "IMAP порт должен быть положительным целым числом",
|
||||||
"incrementalSyncMustBeAtLeast10": "Интервал инкрементальной синхронизации должен быть не менее 10 минут",
|
"incrementalSyncMustBeAtLeast10": "Интервал инкрементальной синхронизации должен быть не менее 10 минут",
|
||||||
"incrementalSyncMustBeNumber": "Интервал инкрементальной синхронизации должен быть числом",
|
"incrementalSyncMustBeNumber": "Интервал инкрементальной синхронизации должен быть числом",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "Пароль должен быть не менее {{min}} символов",
|
"passwordMinLength": "Пароль должен быть не менее {{min}} символов",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "Fortsätt",
|
"continue": "Fortsätt",
|
||||||
"createdAt": "Skapad",
|
"createdAt": "Skapad",
|
||||||
"creationFailed": "Skapande misslyckades, försök igen senare",
|
"creationFailed": "Skapande misslyckades, försök igen senare",
|
||||||
|
"cronAdvanced": "Avancerat uttryck",
|
||||||
|
"cronDaily": "Dagligen",
|
||||||
|
"cronDayOfMonth": "Veckodag",
|
||||||
|
"cronDayOfWeek": "Veckodag",
|
||||||
|
"cronFrequency": "Frekvens",
|
||||||
|
"cronFriday": "Fredag",
|
||||||
|
"cronHour": "Timme",
|
||||||
|
"cronMinute": "Minut",
|
||||||
|
"cronMonday": "Måndag",
|
||||||
|
"cronMonthly": "Månadsvis",
|
||||||
|
"cronSaturday": "Lördag",
|
||||||
|
"cronSimple": "Enkelt uttryck",
|
||||||
|
"cronSunday": "Söndag",
|
||||||
|
"cronThursday": "Torsdag",
|
||||||
|
"cronTimezoneNote": "Alla tider visas i serverns lokaltid.",
|
||||||
|
"cronTuesday": "Tisdag",
|
||||||
|
"cronWednesday": "Onsdag",
|
||||||
|
"cronWeekly": "Veckovis",
|
||||||
"dateSelection": "Datumsval",
|
"dateSelection": "Datumsval",
|
||||||
"dateSince": "Datum från",
|
"dateSince": "Datum från",
|
||||||
"days": "Dagar",
|
"days": "Dagar",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "Misslyckades med att starta hämtningsuppgift",
|
"downloadFailed": "Misslyckades med att starta hämtningsuppgift",
|
||||||
"downloadInterval": "Nedladdningsintervall (minuter)",
|
"downloadInterval": "Nedladdningsintervall (minuter)",
|
||||||
"downloadIntervalPlaceholder": "Ange minuter",
|
"downloadIntervalPlaceholder": "Ange minuter",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "6-fälts Cron (sek min tim dag mån veckodag) i servertid. Ersätter intervall.",
|
||||||
|
"downloadSchedulePlaceholder": "t.ex. 0 0 * * *",
|
||||||
"downloadScope": "Nedladdningsstrategi",
|
"downloadScope": "Nedladdningsstrategi",
|
||||||
"downloadScopeDescription": "Välj vilka e-postmeddelanden som ska indexeras och laddas ner.",
|
"downloadScopeDescription": "Välj vilka e-postmeddelanden som ska indexeras och laddas ner.",
|
||||||
"downloadStarted": "Hämtningsuppgift startad",
|
"downloadStarted": "Hämtningsuppgift startad",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "Spara ändringar",
|
"saveChanges": "Spara ändringar",
|
||||||
|
"scheduleMode": "Hämtningsschema",
|
||||||
|
"scheduleModeCron": "Cron-uttryck",
|
||||||
|
"scheduleModeDescription": "Hämta med fasta intervall eller Cron-uttryck.",
|
||||||
|
"scheduleModeInterval": "Fast intervall",
|
||||||
"selectAccountType": "Välj kontotyp",
|
"selectAccountType": "Välj kontotyp",
|
||||||
"selectAtLeastOneFolder": "Vänligen välj minst en mapp",
|
"selectAtLeastOneFolder": "Vänligen välj minst en mapp",
|
||||||
"selectAuthMethod": "Välj en autentiseringsmetod",
|
"selectAuthMethod": "Välj en autentiseringsmetod",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAP-port måste vara ett positivt heltal",
|
"imapPortMustBePositive": "IMAP-port måste vara ett positivt heltal",
|
||||||
"incrementalSyncMustBeAtLeast10": "Intervall för inkrementell synkronisering måste vara minst 10 minuter",
|
"incrementalSyncMustBeAtLeast10": "Intervall för inkrementell synkronisering måste vara minst 10 minuter",
|
||||||
"incrementalSyncMustBeNumber": "Intervall för inkrementell synkronisering måste vara ett tal",
|
"incrementalSyncMustBeNumber": "Intervall för inkrementell synkronisering måste vara ett tal",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "Lösenordet måste vara minst {{min}} tecken långt",
|
"passwordMinLength": "Lösenordet måste vara minst {{min}} tecken långt",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "繼續",
|
"continue": "繼續",
|
||||||
"createdAt": "建立時間",
|
"createdAt": "建立時間",
|
||||||
"creationFailed": "建立失敗,請稍後再試。",
|
"creationFailed": "建立失敗,請稍後再試。",
|
||||||
|
"cronAdvanced": "高級表達式",
|
||||||
|
"cronDaily": "每天",
|
||||||
|
"cronDayOfMonth": "星期",
|
||||||
|
"cronDayOfWeek": "星期",
|
||||||
|
"cronFrequency": "頻率",
|
||||||
|
"cronFriday": "星期五",
|
||||||
|
"cronHour": "小時",
|
||||||
|
"cronMinute": "分鐘",
|
||||||
|
"cronMonday": "星期一",
|
||||||
|
"cronMonthly": "每月",
|
||||||
|
"cronSaturday": "星期六",
|
||||||
|
"cronSimple": "简易表達式",
|
||||||
|
"cronSunday": "星期日",
|
||||||
|
"cronThursday": "星期四",
|
||||||
|
"cronTimezoneNote": "所有時間均使用伺服器在地時區。",
|
||||||
|
"cronTuesday": "星期二",
|
||||||
|
"cronWednesday": "星期三",
|
||||||
|
"cronWeekly": "每周",
|
||||||
"dateSelection": "日期選擇",
|
"dateSelection": "日期選擇",
|
||||||
"dateSince": "同步起始日期",
|
"dateSince": "同步起始日期",
|
||||||
"days": "天",
|
"days": "天",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "啟動下載任務失敗",
|
"downloadFailed": "啟動下載任務失敗",
|
||||||
"downloadInterval": "下載週期 (分鐘)",
|
"downloadInterval": "下載週期 (分鐘)",
|
||||||
"downloadIntervalPlaceholder": "請輸入分鐘數",
|
"downloadIntervalPlaceholder": "請輸入分鐘數",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "伺服器時間的 6 位 Cron 表達式(秒分時日月週),提供時覆蓋間隔設定。",
|
||||||
|
"downloadSchedulePlaceholder": "例如:0 0 * * *",
|
||||||
"downloadScope": "下載策略",
|
"downloadScope": "下載策略",
|
||||||
"downloadScopeDescription": "選擇哪些郵件應被索引和下載。",
|
"downloadScopeDescription": "選擇哪些郵件應被索引和下載。",
|
||||||
"downloadStarted": "下載任務已啟動",
|
"downloadStarted": "下載任務已啟動",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "儲存變更",
|
"saveChanges": "儲存變更",
|
||||||
|
"scheduleMode": "下載排程",
|
||||||
|
"scheduleModeCron": "Cron 表達式",
|
||||||
|
"scheduleModeDescription": "設定固定間隔或 Cron 表達式下載郵件。",
|
||||||
|
"scheduleModeInterval": "固定間隔",
|
||||||
"selectAccountType": "選擇郵件帳戶類型",
|
"selectAccountType": "選擇郵件帳戶類型",
|
||||||
"selectAtLeastOneFolder": "請至少選擇一個資料夾",
|
"selectAtLeastOneFolder": "請至少選擇一個資料夾",
|
||||||
"selectAuthMethod": "選擇驗證方法",
|
"selectAuthMethod": "選擇驗證方法",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAP 連接埠必須是正整數",
|
"imapPortMustBePositive": "IMAP 連接埠必須是正整數",
|
||||||
"incrementalSyncMustBeAtLeast10": "增量同步間隔必須至少為 10 分鐘",
|
"incrementalSyncMustBeAtLeast10": "增量同步間隔必須至少為 10 分鐘",
|
||||||
"incrementalSyncMustBeNumber": "增量同步間隔必須是數字",
|
"incrementalSyncMustBeNumber": "增量同步間隔必須是數字",
|
||||||
|
"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": "無效的網址",
|
||||||
"passwordMinLength": "密碼長度必須至少 {{min}} 個字元",
|
"passwordMinLength": "密碼長度必須至少 {{min}} 個字元",
|
||||||
|
|||||||
@@ -115,6 +115,24 @@
|
|||||||
"continue": "继续",
|
"continue": "继续",
|
||||||
"createdAt": "创建时间",
|
"createdAt": "创建时间",
|
||||||
"creationFailed": "创建失败,请稍后重试",
|
"creationFailed": "创建失败,请稍后重试",
|
||||||
|
"cronAdvanced": "高级表达式",
|
||||||
|
"cronDaily": "每天",
|
||||||
|
"cronDayOfMonth": "星期",
|
||||||
|
"cronDayOfWeek": "星期",
|
||||||
|
"cronFrequency": "频率",
|
||||||
|
"cronFriday": "星期五",
|
||||||
|
"cronHour": "小时",
|
||||||
|
"cronMinute": "分钟",
|
||||||
|
"cronMonday": "星期一",
|
||||||
|
"cronMonthly": "每月",
|
||||||
|
"cronSaturday": "星期六",
|
||||||
|
"cronSimple": "简易表达式",
|
||||||
|
"cronSunday": "星期日",
|
||||||
|
"cronThursday": "星期四",
|
||||||
|
"cronTimezoneNote": "所有时间均使用服务器本地时区。",
|
||||||
|
"cronTuesday": "星期二",
|
||||||
|
"cronWednesday": "星期三",
|
||||||
|
"cronWeekly": "每周",
|
||||||
"dateSelection": "日期选择",
|
"dateSelection": "日期选择",
|
||||||
"dateSince": "起始日期",
|
"dateSince": "起始日期",
|
||||||
"days": "天",
|
"days": "天",
|
||||||
@@ -133,6 +151,9 @@
|
|||||||
"downloadFailed": "启动下载任务失败",
|
"downloadFailed": "启动下载任务失败",
|
||||||
"downloadInterval": "下载周期 (分钟)",
|
"downloadInterval": "下载周期 (分钟)",
|
||||||
"downloadIntervalPlaceholder": "请输入分钟数",
|
"downloadIntervalPlaceholder": "请输入分钟数",
|
||||||
|
"downloadSchedule": "Cron Schedule",
|
||||||
|
"downloadScheduleDescription": "服务器时间的 6 位 Cron 表达式(秒分时日月周),提供时覆盖间隔设置。",
|
||||||
|
"downloadSchedulePlaceholder": "例如:0 0 * * *",
|
||||||
"downloadScope": "下载策略",
|
"downloadScope": "下载策略",
|
||||||
"downloadScopeDescription": "选择哪些邮件应被索引和下载。",
|
"downloadScopeDescription": "选择哪些邮件应被索引和下载。",
|
||||||
"downloadStarted": "下载任务已启动",
|
"downloadStarted": "下载任务已启动",
|
||||||
@@ -247,6 +268,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"saveChanges": "保存更改",
|
"saveChanges": "保存更改",
|
||||||
|
"scheduleMode": "下载调度",
|
||||||
|
"scheduleModeCron": "Cron 表达式",
|
||||||
|
"scheduleModeDescription": "设置固定间隔或 Cron 表达式下载邮件。",
|
||||||
|
"scheduleModeInterval": "固定间隔",
|
||||||
"selectAccountType": "选择邮件账户类型",
|
"selectAccountType": "选择邮件账户类型",
|
||||||
"selectAtLeastOneFolder": "请至少选择一个文件夹",
|
"selectAtLeastOneFolder": "请至少选择一个文件夹",
|
||||||
"selectAuthMethod": "选择认证方法",
|
"selectAuthMethod": "选择认证方法",
|
||||||
@@ -1658,6 +1683,7 @@
|
|||||||
"imapPortMustBePositive": "IMAP 端口必须是正整数",
|
"imapPortMustBePositive": "IMAP 端口必须是正整数",
|
||||||
"incrementalSyncMustBeAtLeast10": "增量同步间隔必须至少为 10 分钟",
|
"incrementalSyncMustBeAtLeast10": "增量同步间隔必须至少为 10 分钟",
|
||||||
"incrementalSyncMustBeNumber": "增量同步间隔必须是数字",
|
"incrementalSyncMustBeNumber": "增量同步间隔必须是数字",
|
||||||
|
"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",
|
||||||
"passwordMinLength": "密码长度至少为 {{min}} 个字符",
|
"passwordMinLength": "密码长度至少为 {{min}} 个字符",
|
||||||
|
|||||||
Reference in New Issue
Block a user