diff --git a/static/i18n.js b/static/i18n.js index 65dd33e6..7be8cf44 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -1,4 +1,4 @@ -// ── i18n: locale bundles and t() helper ────────────────────────────────────── +// ── i18n: locale bundles and t() helper ────────────────────────────────────── // To add a new language: add an entry to LOCALES below with all keys translated. // The language code must match a valid BCP 47 tag (used for speech recognition). // Keys missing in a non-English locale fall back to English automatically. @@ -3247,13 +3247,13 @@ const LOCALES = { cron_name_label: 'Nome', cron_name_placeholder: 'Opzionale', cron_schedule_label: 'Pianificazione', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: 'Preimpostazione', + cron_schedule_preset_hourly: 'Ogni ora', + cron_schedule_preset_daily: 'Ogni giorno', + cron_schedule_preset_weekdays: 'Giorni feriali', + cron_schedule_preset_weekly: 'Ogni settimana', + cron_schedule_preset_monthly: 'Ogni mese', + cron_schedule_preset_custom: 'Personalizzato', cron_schedule_hint: 'Usa \'every 1h\' o un\'espressione cron per job ricorrenti. Durate semplici come \'30m\' vengono eseguite una volta sola.', cron_schedule_once_warning: 'Forme di durata come \'30m\' vengono eseguite una volta e rimosse dopo l\'esecuzione. Usa \'every 30m\' per mantenere un job ricorrente.', cron_prompt_label: 'Prompt', @@ -4919,13 +4919,13 @@ const LOCALES = { cron_name_label: '名前', cron_name_placeholder: '任意', cron_schedule_label: 'スケジュール', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: 'プリセット', + cron_schedule_preset_hourly: '毎時', + cron_schedule_preset_daily: '毎日', + cron_schedule_preset_weekdays: '平日', + cron_schedule_preset_weekly: '毎週', + cron_schedule_preset_monthly: '毎月', + cron_schedule_preset_custom: 'カスタム', cron_schedule_hint: "繰り返し実行には 'every 1h' または Cron 式を使います。'30m' のような期間だけの指定は 1 回だけ実行されます。", cron_schedule_once_warning: "'30m' のような期間指定は 1 回だけ実行され、実行後に削除されます。繰り返すには 'every 30m' を使ってください。", cron_prompt_label: 'プロンプト', @@ -6233,13 +6233,13 @@ const LOCALES = { cron_name_label: 'Имя', cron_name_placeholder: 'Необязательно', cron_schedule_label: 'Расписание', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: 'Предустановка', + cron_schedule_preset_hourly: 'Ежечасно', + cron_schedule_preset_daily: 'Ежедневно', + cron_schedule_preset_weekdays: 'По будням', + cron_schedule_preset_weekly: 'Еженедельно', + cron_schedule_preset_monthly: 'Ежемесячно', + cron_schedule_preset_custom: 'Пользовательский', cron_schedule_hint: "Для повторяющихся заданий используйте 'every 1h' или cron-выражение. Простые интервалы вроде '30m' выполняются один раз.", cron_schedule_once_warning: "Интервалы вроде '30m' выполняются один раз и удаляются после запуска. Используйте 'every 30m' для повторяющегося задания.", cron_prompt_label: 'Запрос', @@ -7824,13 +7824,13 @@ const LOCALES = { cron_name_label: 'Nombre', cron_name_placeholder: 'Opcional', cron_schedule_label: 'Programación', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: 'Preajuste', + cron_schedule_preset_hourly: 'Cada hora', + cron_schedule_preset_daily: 'Diario', + cron_schedule_preset_weekdays: 'Días laborables', + cron_schedule_preset_weekly: 'Semanal', + cron_schedule_preset_monthly: 'Mensual', + cron_schedule_preset_custom: 'Personalizado', cron_schedule_hint: "Usa 'every 1h' o una expresión cron para trabajos recurrentes. Duraciones como '30m' se ejecutan una sola vez.", cron_schedule_once_warning: "Las duraciones como '30m' se ejecutan una vez y se eliminan después de correr. Usa 'every 30m' para mantener un trabajo recurrente.", cron_prompt_label: 'Prompt', @@ -9097,13 +9097,13 @@ const LOCALES = { cron_duplicated: 'Aufgabe dupliziert (pausiert)', cron_name_placeholder: 'Optional', cron_schedule_label: 'Zeitplan', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: 'Voreinstellung', + cron_schedule_preset_hourly: 'Stündlich', + cron_schedule_preset_daily: 'Täglich', + cron_schedule_preset_weekdays: 'Wochentage', + cron_schedule_preset_weekly: 'Wöchentlich', + cron_schedule_preset_monthly: 'Monatlich', + cron_schedule_preset_custom: 'Benutzerdefiniert', cron_schedule_hint: "Für wiederkehrende Aufgaben 'every 1h' oder einen Cron-Ausdruck verwenden. Reine Dauern wie '30m' laufen einmal.", cron_schedule_once_warning: "Dauerangaben wie '30m' laufen einmal und werden nach der Ausführung entfernt. Verwende 'every 30m' für eine wiederkehrende Aufgabe.", cron_prompt_label: 'Prompt', @@ -11042,13 +11042,13 @@ const LOCALES = { cron_name_label: '名称', cron_name_placeholder: '可选', cron_schedule_label: '计划', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: '预设', + cron_schedule_preset_hourly: '每小时', + cron_schedule_preset_daily: '每天', + cron_schedule_preset_weekdays: '工作日', + cron_schedule_preset_weekly: '每周', + cron_schedule_preset_monthly: '每月', + cron_schedule_preset_custom: '自定义', cron_schedule_hint: "循环任务请用 'every 1h' 或 Cron 表达式。像 '30m' 这样的裸时长只会运行一次。", cron_schedule_once_warning: "像 '30m' 这样的时长写法只会运行一次,并在运行后移除。要保留循环任务,请使用 'every 30m'。", cron_prompt_label: '提示词', @@ -13008,13 +13008,13 @@ const LOCALES = { cron_name_label: '任務名稱', cron_name_placeholder: '選填', cron_schedule_label: '排程', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: '預設', + cron_schedule_preset_hourly: '每小時', + cron_schedule_preset_daily: '每天', + cron_schedule_preset_weekdays: '工作日', + cron_schedule_preset_weekly: '每週', + cron_schedule_preset_monthly: '每月', + cron_schedule_preset_custom: '自訂', cron_schedule_hint: '週期性任務請用「every 1h」或 Cron 表示式。像「30m」這樣的裸時長只會執行一次。', cron_schedule_once_warning: '像「30m」這樣的時長寫法只會執行一次,並在執行後移除。要保留週期性任務,請使用「every 30m」。', cron_prompt_label: '提示', @@ -14413,13 +14413,13 @@ const LOCALES = { cron_name_label: 'Nome', cron_name_placeholder: 'Opcional', cron_schedule_label: 'Agendamento', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: 'Predefinição', + cron_schedule_preset_hourly: 'A cada hora', + cron_schedule_preset_daily: 'Diário', + cron_schedule_preset_weekdays: 'Dias úteis', + cron_schedule_preset_weekly: 'Semanal', + cron_schedule_preset_monthly: 'Mensal', + cron_schedule_preset_custom: 'Personalizado', cron_schedule_hint: "Use 'every 1h' ou uma expressão Cron para tarefas recorrentes. Durações como '30m' rodam uma vez.", cron_schedule_once_warning: "Durações como '30m' rodam uma vez e são removidas após executar. Use 'every 30m' para manter uma tarefa recorrente.", cron_prompt_label: 'Prompt', @@ -17801,13 +17801,13 @@ const LOCALES = { cron_name_label: 'Nom', cron_name_placeholder: 'Facultatif', cron_schedule_label: 'Planification', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: 'Préréglage', + cron_schedule_preset_hourly: 'Toutes les heures', + cron_schedule_preset_daily: 'Quotidien', + cron_schedule_preset_weekdays: 'Jours ouvrés', + cron_schedule_preset_weekly: 'Hebdomadaire', + cron_schedule_preset_monthly: 'Mensuel', + cron_schedule_preset_custom: 'Personnalisé', cron_schedule_hint: "Utilisez 'every 1h' ou une expression cron pour les tâches récurrentes. Les durées simples comme '30m' s'exécutent une fois.", cron_schedule_once_warning: "Les formes de durée comme '30m' s'exécutent une fois et sont supprimées après l'exécution. Utilisez 'every 30m' pour conserver une tâche récurrente.", cron_prompt_label: 'Invite', @@ -19373,13 +19373,13 @@ const LOCALES = { cron_name_label: 'İsim', cron_name_placeholder: 'İsteğe bağlı', cron_schedule_label: 'Takvim', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: 'Ön ayar', + cron_schedule_preset_hourly: 'Saatlik', + cron_schedule_preset_daily: 'Günlük', + cron_schedule_preset_weekdays: 'Hafta içi', + cron_schedule_preset_weekly: 'Haftalık', + cron_schedule_preset_monthly: 'Aylık', + cron_schedule_preset_custom: 'Özel', cron_schedule_hint: "Use 'every 1h' or a cron expression for recurring jobs. Bare durations like '30m' run once.", cron_schedule_once_warning: "Duration forms like '30m' run once and are removed after running. Use 'every 30m' to keep a recurring job.", cron_prompt_label: 'Çabuk', @@ -21125,13 +21125,13 @@ const LOCALES = { cron_name_label: 'Nazwa', cron_name_placeholder: 'Opcjonalnie', cron_schedule_label: 'Harmonogram', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: 'Ustawienie wstępne', + cron_schedule_preset_hourly: 'Co godzinę', + cron_schedule_preset_daily: 'Codziennie', + cron_schedule_preset_weekdays: 'Dni robocze', + cron_schedule_preset_weekly: 'Co tydzień', + cron_schedule_preset_monthly: 'Co miesiąc', + cron_schedule_preset_custom: 'Niestandardowe', cron_schedule_hint: "Użyj 'every 1h' lub wyrażenia cron dla zadań cyklicznych. Same formy czasu trwania, jak '30m', zostaną uruchomione tylko raz.", cron_schedule_once_warning: 'Formy czasu trwania, takie jak \'30m\', są uruchamiane raz i usuwane po uruchomieniu. Użyj \'every 30m\', aby utrzymać zadanie cykliczne.', cron_prompt_label: 'Monit', @@ -22631,13 +22631,13 @@ const LOCALES = { cron_name_label: 'Tên', cron_name_placeholder: 'Tùy chọn', cron_schedule_label: 'Lịch chạy', - cron_schedule_preset_label: 'Preset', - cron_schedule_preset_hourly: 'Hourly', - cron_schedule_preset_daily: 'Daily', - cron_schedule_preset_weekdays: 'Weekdays', - cron_schedule_preset_weekly: 'Weekly', - cron_schedule_preset_monthly: 'Monthly', - cron_schedule_preset_custom: 'Custom', + cron_schedule_preset_label: 'Cài đặt sẵn', + cron_schedule_preset_hourly: 'Hàng giờ', + cron_schedule_preset_daily: 'Hàng ngày', + cron_schedule_preset_weekdays: 'Ngày trong tuần', + cron_schedule_preset_weekly: 'Hàng tuần', + cron_schedule_preset_monthly: 'Hàng tháng', + cron_schedule_preset_custom: 'Tùy chỉnh', cron_schedule_hint: "Dùng 'every 1h' hoặc biểu thức cron cho job lặp lại. Các khoảng thời gian đơn như '30m' chỉ chạy một lần.", cron_schedule_once_warning: "Các dạng thời lượng như '30m' chỉ chạy một lần và sẽ bị xóa sau khi chạy. Dùng 'every 30m' để giữ job lặp lại.", cron_prompt_label: 'Prompt', diff --git a/static/panels.js b/static/panels.js index 88868313..f78b6413 100644 --- a/static/panels.js +++ b/static/panels.js @@ -506,8 +506,12 @@ function _applyCronSchedulePresetSelection() { if (!presetEl || !scheduleEl) return; const presetId = presetEl.value; const preset = CRON_SCHEDULE_PRESETS.find((entry) => entry.id === presetId); - if (preset && preset.value) scheduleEl.value = preset.value; - _syncCronSchedulePresetAndWarning(); + if (preset && preset.value) { + scheduleEl.value = preset.value; + _syncCronSchedulePresetAndWarning(); + return; + } + _syncCronScheduleWarning(); } function _initCronSchedulePresetControls() { diff --git a/tests/test_issue2031_cron_once_visibility.py b/tests/test_issue2031_cron_once_visibility.py index f6614a92..3ea70781 100644 --- a/tests/test_issue2031_cron_once_visibility.py +++ b/tests/test_issue2031_cron_once_visibility.py @@ -35,7 +35,7 @@ def _cron_schedule_save_source() -> str: pytest.fail("saveCronForm is missing") end = src.find("// Back-compat aliases for any stale callers", start) if end < 0: - end = len(src) + pytest.fail("saveCronForm boundary marker is missing") return src[start:end] @@ -156,6 +156,11 @@ elements.cronFormSchedulePreset.dispatchEvent('change'); const presetWriteValue = elements.cronFormSchedule.value; const selectAfterPresetWrite = elements.cronFormSchedulePreset.value; +elements.cronFormSchedulePreset.value = "custom"; +elements.cronFormSchedulePreset.dispatchEvent('change'); +const preservedExactPresetValue = elements.cronFormSchedule.value; +const selectAfterExactPresetCustom = elements.cronFormSchedulePreset.value; + elements.cronFormSchedule.value = "advanced: cron expression"; elements.cronFormSchedule.dispatchEvent('input'); elements.cronFormSchedulePreset.value = "custom"; @@ -170,6 +175,8 @@ console.log(JSON.stringify({ warningAfterOnce, presetWriteValue, selectAfterPresetWrite, + preservedExactPresetValue, + selectAfterExactPresetCustom, preservedCustomValue, selectAfterCustom, })); @@ -182,6 +189,8 @@ console.log(JSON.stringify({ assert result["warningAfterOnce"] == "" assert result["presetWriteValue"] == "every 1h" assert result["selectAfterPresetWrite"] == "hourly" + assert result["preservedExactPresetValue"] == "every 1h" + assert result["selectAfterExactPresetCustom"] == "custom" assert result["preservedCustomValue"] == "advanced: cron expression" assert result["selectAfterCustom"] == "custom"