Compare commits

...
33 changed files with 335 additions and 182 deletions
+16
View File
@@ -0,0 +1,16 @@
"""Left-rail (action sidebar) display modes.
A leaf module on purpose: forms.py, flask_app.py and model/App.py all need these, and
model/App.py seeding its default from forms.py would drag the whole form stack (~550
modules) into the model layer.
"""
from flask_babel import lazy_gettext as _l
# The complete set of left-rail modes - flask_app.get_sidebar_mode_class() maps these
# (and only these) onto body classes, so a new mode here needs a new mapping there.
MENU_SIDEBAR_ACTIONMODES = [
('expandable', _l('Expand on hover')), # Slim icon rail that expands on hover/focus
('pinned-expanded', _l('Always expanded')), # Always expanded, never collapses
('minimal', _l('Stays minimal')), # Always small, never expands
]
MENU_SIDEBAR_ACTIONMODES_DEFAULT = 'expandable'
@@ -250,7 +250,7 @@ Math: {{ 1 + 1 }}") }}
<div class="flex-wrapper" >
<div id="browser-steps-ui" class="noselect">
<div class="noselect" id="browsersteps-selector-wrapper" style="width: 100%">
<div class="noselect" id="browsersteps-selector-wrapper">
<span class="loader" >
<span id="browsersteps-click-start">
<h2 >{{ _('Click here to Start') }}</h2>
+25 -12
View File
@@ -56,6 +56,7 @@ from changedetectionio.api import (
WatchSingleHistory,
)
from changedetectionio.api.Search import Search
from changedetectionio.blueprint.menu_modes import MENU_SIDEBAR_ACTIONMODES, MENU_SIDEBAR_ACTIONMODES_DEFAULT
from changedetectionio.favicon_utils import get_favicon_mime_type
from changedetectionio.languages import (
get_available_languages,
@@ -286,20 +287,32 @@ def _filter_url(**overrides):
@app.template_global()
def get_sidebar_mode_class():
"""Body class that drives the left-rail behaviour (see parts/_action_sidebar.scss).
"""Body class(es) that drive the left-rail behaviour (see parts/_action_sidebar.scss).
'collapsed' -> slim icon rail that expands on hover/focus (actionsidebar-minimal)
'pinned' -> rail always expanded with labels visible (actionside-bar-on)
Only the modes offered by MENU_SIDEBAR_ACTIONMODES are honoured - anything else in the
datastore (a stale value from an older release, hand-edited JSON) falls back to
MENU_SIDEBAR_ACTIONMODES_DEFAULT rather than leaking through as a body class.
'expandable' -> icon-only rail, rolls out over the content on hover/focus
'pinned-expanded' -> rail always expanded, labels visible at rest
'minimal' -> icon-only rail that never expands
"""
mode = datastore.data['settings']['application'].get('ui', {}).get('sidebar_mode', 'collapsed')
# Pinned mode is permanently expanded, so it carries 'action-side-bar-expanded'
# from the start. In collapsed mode that class is toggled on hover/focus by
# static/js/sidebar.js.
return (
'actionside-bar-on action-side-bar-expanded'
if mode == 'pinned'
else 'actionsidebar-minimal'
)
# 'actionsidebar-minimal' - collapsed icon rail (hover-to-expand lives in CSS + static/js/sidebar.js)
# 'actionsidebar-no-expand' - opts that rail out of hover-to-expand
# 'actionside-bar-on' - always-open rail
# 'action-side-bar-expanded'- expanded logo/stats block
body_classes = {
'expandable': 'actionsidebar-minimal',
'pinned-expanded': 'actionside-bar-on action-side-bar-expanded',
'minimal': 'actionsidebar-minimal actionsidebar-no-expand',
}
mode = datastore.data['settings']['application'].get('ui', {}).get('sidebar_mode')
if mode not in {choice for choice, _label in MENU_SIDEBAR_ACTIONMODES} or mode not in body_classes:
mode = MENU_SIDEBAR_ACTIONMODES_DEFAULT
return body_classes[mode]
@app.template_global()
+3 -3
View File
@@ -4,6 +4,7 @@ from loguru import logger
from wtforms.widgets.core import TimeInput
from flask_babel import lazy_gettext as _l, gettext
from changedetectionio.blueprint.menu_modes import MENU_SIDEBAR_ACTIONMODES, MENU_SIDEBAR_ACTIONMODES_DEFAULT
from changedetectionio.blueprint.rss import RSS_FORMAT_TYPES, RSS_TEMPLATE_TYPE_OPTIONS, RSS_TEMPLATE_HTML_DEFAULT
from changedetectionio.llm.ui_strings import LLM_INTENT_WATCH_PLACEHOLDER
from changedetectionio.llm.evaluator import (
@@ -1164,9 +1165,8 @@ class globalSettingsApplicationUIForm(Form):
choices=[('long', _l('Long (1 minute ago)')), ('short', _l('Short (1m ago)'))],
default='long', validators=[validators.Optional()])
sidebar_mode = SelectField(_l('Navigation sidebar'),
choices=[('collapsed', _l('Collapsed icon rail (expands on hover)')),
('pinned', _l('Always expanded'))],
default='collapsed', validators=[validators.Optional()])
choices=MENU_SIDEBAR_ACTIONMODES,
default=MENU_SIDEBAR_ACTIONMODES_DEFAULT, validators=[validators.Optional()])
# datastore.data['settings']['application']..
class globalSettingsApplicationForm(commonSettingsForm):
+2 -1
View File
@@ -1,6 +1,7 @@
from os import getenv
from copy import deepcopy
from changedetectionio.blueprint.menu_modes import MENU_SIDEBAR_ACTIONMODES_DEFAULT
from changedetectionio.blueprint.rss import RSS_FORMAT_TYPES, RSS_CONTENT_FORMAT_DEFAULT
from changedetectionio.model.Tags import TagsDict
@@ -80,7 +81,7 @@ class model(dict):
'socket_io_enabled': True,
'favicons_enabled': True,
'timeago_format': 'long', # 'long' = "1 minute ago", 'short' = "1m ago"
'sidebar_mode': 'collapsed', # 'collapsed' = slim icon rail, expands on hover; 'pinned' = always expanded
'sidebar_mode': MENU_SIDEBAR_ACTIONMODES_DEFAULT, # one of blueprint.menu_modes.MENU_SIDEBAR_ACTIONMODES
},
}
}
+3 -1
View File
@@ -78,7 +78,9 @@ $(document).ready(function () {
// bootstrap it, this will trigger everything else
$('#browsersteps-img').bind('load', function () {
$('body').addClass('full-width');
console.log("Loaded background...");
console.log(`Loaded background ${this.naturalWidth}px` );
// For the UI width of the whole edit area
document.documentElement.style.setProperty('--browser-steps-max-width', `${this.naturalWidth+200}px` );
document.getElementById("browsersteps-selector-canvas");
c = document.getElementById("browsersteps-selector-canvas");
+6 -4
View File
@@ -1,13 +1,15 @@
// Left-rail expand/collapse state.
// Adds `action-side-bar-expanded` to <body> whenever the rail is showing its
// labels. In pinned mode (body.actionside-bar-on) the class is already present
// from page load; in collapsed mode (body.actionsidebar-minimal) the rail only
// expands on hover/focus, so we toggle the class to match.
// labels. In 'pinned-expanded' mode (body.actionside-bar-on) the class is already
// present from page load; in 'expandable' mode (body.actionsidebar-minimal) the rail
// only expands on hover/focus, so we toggle the class to match. 'minimal' mode is
// also the collapsed rail but carries `actionsidebar-no-expand` and never rolls out.
(function() {
'use strict';
document.addEventListener('DOMContentLoaded', function() {
if (!document.body.classList.contains('actionsidebar-minimal')) {
if (!document.body.classList.contains('actionsidebar-minimal') ||
document.body.classList.contains('actionsidebar-no-expand')) {
return;
}
@@ -115,7 +115,9 @@ window.initVisualSelector = function (opts) {
$('#selector-current-xpath, #clear-selector').hide();
})
.on('load', () => {
console.log("Loaded background...");
console.log(`Loaded background ${$selectorBackgroundElem[0].naturalWidth}px`);
// For the UI width of the whole edit area
document.documentElement.style.setProperty('--visualselector-max-width', `${$selectorBackgroundElem[0].naturalWidth}px` );
c = $selectorCanvasElem[0];
xctx = c.getContext("2d");
ctx = c.getContext("2d");
@@ -32,21 +32,27 @@ $action-sidebar-content-slot: 1100px;
// Hidden on mobile: the mobile drawer (hamburger) carries these items
display: none;
}
}
body.actionside-bar-on {
.action-sidebar {
/* width: $action-sidebar-width-expanded; // reserve enough to host the expanded inner block*/
// MINIMAL MODE: the rail's footprint in the flex row is frozen at the
// collapsed width (+ the inner block's horizontal padding, which is
// content-box). The inner block is taken out of flow (absolute, below) so
// its hover expansion rolls out ON TOP of the page content instead of
// widening this flex item and reflowing `.app-main`.
body.actionsidebar-minimal & {
flex: 0 0 auto;
width: calc(#{$action-sidebar-width-collapsed} + #{$common-gap * 2});
overflow: visible; // let the expanded inner block escape the frame
}
}
// The actual interactive item block — wraps only the items, not the whole height.
//
// Two body-level modes drive the rail's display state:
// body.actionside-bar-on → always expanded (icons + labels visible all the time)
// body.actionsidebar-minimal → icon-only collapsed rail; expands on hover/focus
// `actionside-bar-on` is the default applied in templates/base.html. Both the
// hover-to-expand width animation and the label fade-in are gated on the
// Body-level classes drive the rail's display state (emitted by
// flask_app.get_sidebar_mode_class() from the `sidebar_mode` setting):
// body.actionside-bar-on → always expanded (icons + labels visible all the time)
// body.actionsidebar-minimal → icon-only collapsed rail; expands on hover/focus
// body.actionsidebar-no-expand → alongside the above: stays collapsed, no hover-out
// Both the hover-to-expand width animation and the label fade-in are gated on the
// minimal class so that the always-expanded mode (or no mode) doesn't trigger
// a needless layout jump when the user mouses across the rail.
.action-sidebar-inner {
@@ -64,12 +70,40 @@ body.actionside-bar-on {
padding-left: $common-gap;
padding-right: $common-gap;
// Hover-to-expand only fires in minimal mode.
body.actionsidebar-minimal &:hover,
body.actionsidebar-minimal &:focus-within {
// MINIMAL MODE: lift the block out of the flex flow so growing it can't
// resize the rail (and therefore can't shift the content column). The rail
// is `position: sticky`, i.e. a positioned element, so top/left/bottom here
// anchor to it; top+bottom keep the column full-height, which the footer
// list's `margin-top: auto` still needs.
//
// Once it floats above the page it needs its own backdrop, or the content
// it rolls over would read straight through the rail's translucent 5% white.
// It can't just be a flat colour: the page background is a fixed, viewport-
// sized gradient (`body:after`), so the rail repaints that same gradient with
// `background-attachment: fixed` — which makes the viewport the positioning
// area — and lays the rail's own 5% white on top. Result: opaque, but
// pixel-identical to the translucent rail it replaces, at rest and rolled out.
body.actionsidebar-minimal & {
position: absolute;
top: 0;
left: 0;
bottom: 0;
z-index: 1;
background-color: var(--color-background-page); // fallback under the gradient
background-image:
linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05)),
var(--page-background-gradient);
background-attachment: fixed, fixed;
}
// Hover-to-expand only fires in minimal mode, and not for 'minimal' (no-expand).
body.actionsidebar-minimal:not(.actionsidebar-no-expand) &:hover,
body.actionsidebar-minimal:not(.actionsidebar-no-expand) &:focus-within {
width: $action-sidebar-width-expanded;
// Enter is smoother.
transition: width 0.22s cubic-bezier(0.2, 0.7, 0.2, 1);
// Lift it off the page while it's rolled out over the content.
box-shadow: var(--color-sidebar-shadow);
}
// Always-expanded mode: no hover gate; the rail just sits open.
@@ -250,8 +284,8 @@ ul.action-sidebar-list {
// When the inner block expands in MINIMAL mode, reveal every label/badge
// together with a smooth enter. Always-expanded mode handles labels via the
// `body.actionside-bar-on` block below — no hover gate needed there.
body.actionsidebar-minimal .action-sidebar-inner:hover,
body.actionsidebar-minimal .action-sidebar-inner:focus-within {
body.actionsidebar-minimal:not(.actionsidebar-no-expand) .action-sidebar-inner:hover,
body.actionsidebar-minimal:not(.actionsidebar-no-expand) .action-sidebar-inner:focus-within {
.action-sidebar-item {
.action-label {
opacity: 1;
@@ -79,7 +79,6 @@
width: 100%;
overflow-y: scroll;
position: relative;
height: 80vh;
> img {
position: absolute;
@@ -27,6 +27,12 @@
--color-background-gradient-first: #5ad8f7;
--color-background-gradient-second: #2f50af;
--color-background-gradient-third: #9150bf;
// The page's atmosphere gradient, shared so anything that needs to sit ON the
// page background (e.g. the left rail rolling out over content) can repaint
// an identical copy instead of approximating it with a flat colour. The
// referenced gradient stops are re-declared per theme below, so this single
// definition follows light/dark automatically.
--page-background-gradient: linear-gradient(130deg, var(--color-background-gradient-first), var(--color-background-gradient-second) 41.07%, var(--color-background-gradient-third) 84.05%);
--color-background: var(--color-white);
--color-text: var(--color-grey-200);
--color-link: #1b98f8;
@@ -1,3 +1,12 @@
body:has(#browser-steps:target) .edit-form {
max-width: min(var(--browser-steps-max-width, 1280px), 95vw);
width: 95%;
}
body:has(#visualselector:target) .edit-form {
width: 95%;
max-width: min(var(--visualselector-max-width, 1280px), 95vw);
}
#selector-wrapper {
height: 100%;
@@ -42,7 +42,8 @@
@use "parts/sub_tabs";
// Smooth transitions for theme switching
body,
// Disabled - people complained
/*body,
.pure-table,
.pure-table thead,
.pure-table td,
@@ -65,7 +66,7 @@ code,
a,
.watch-controls img {
transition: color 0.4s ease, background-color 0.4s ease, background 0.4s ease, border-color 0.4s ease, box-shadow 0.4s ease;
}
}*/
body {
color: var(--color-text);
@@ -305,7 +306,7 @@ code {
body:after {
content: "";
background: linear-gradient(130deg, var(--color-background-gradient-first), var(--color-background-gradient-second) 41.07%, var(--color-background-gradient-third) 84.05%);
background: var(--page-background-gradient);
}
body:after,
@@ -697,12 +698,12 @@ footer {
}
}
@media only screen and (max-width: 760px),
(min-device-width: 768px) and (max-device-width: $desktop-wide-breakpoint) {
.edit-form {
padding: 0.5em;
margin: 0;
width: 100%;
}
#nav-menu {
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -7,12 +7,12 @@
<li class="action-sidebar-li" id="action-sidebar-logo">
{%- if has_password and not current_user.is_authenticated -%}
<a id="cdio-logo" href="https://changedetection.io" rel="noopener">
<a id="cdio-logo" href="https://changedetection.io" rel="noopener" title="ChangeDetection.io intelligent web page change detection.">
<span id="logo-expanded"><strong>Change</strong>Detection.io</span>
<span id="logo-short"><strong>CD</strong>IO</span>
</a>
{%- else -%}
<a id="cdio-logo" href="{{url_for('watchlist.index')}}">
<a id="cdio-logo" href="{{url_for('watchlist.index')}}" title="ChangeDetection.io intelligent web page change detection.">
<span id="logo-expanded"><strong>Change</strong>Detection.io</span>
<span id="logo-short"><strong>CD</strong>IO</span>
</a>
@@ -376,6 +376,18 @@ msgstr "Znovu zkontrolovat po (minuty)"
msgid "Import"
msgstr "Importovat"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3461,14 +3473,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Kontrola zabezpečení přístupového tokenu API povolena"
@@ -382,6 +382,18 @@ msgstr "Nachprüfzeit (Minuten)"
msgid "Import"
msgstr "IMPORT"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3511,14 +3523,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Sicherheitsüberprüfung des API-Zugriffstokens aktiviert"
@@ -374,6 +374,18 @@ msgstr ""
msgid "Import"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3453,14 +3465,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr ""
@@ -374,6 +374,18 @@ msgstr ""
msgid "Import"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3453,14 +3465,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr ""
@@ -380,6 +380,18 @@ msgstr "Tiempo de revisión (minutos)"
msgid "Import"
msgstr "Importar"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3526,14 +3538,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Comprobación de seguridad del token de acceso API habilitada"
@@ -378,6 +378,18 @@ msgstr "Temps de revérification (minutes)"
msgid "Import"
msgstr "IMPORTER"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3466,14 +3478,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Contrôle de sécurité du jeton d'accès à l'API activé"
@@ -376,6 +376,18 @@ msgstr "Tempo di ricontrollo (minuti)"
msgid "Import"
msgstr "Importa"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3455,14 +3467,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Controllo sicurezza token API attivo"
@@ -378,6 +378,18 @@ msgstr "再チェック時間(分)"
msgid "Import"
msgstr "インポート"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3472,14 +3484,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "APIアクセストークンのセキュリティチェックを有効化"
@@ -376,6 +376,18 @@ msgstr "재확인 시간(분)"
msgid "Import"
msgstr "가져오기"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3463,14 +3475,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "API 액세스 토큰 보안 확인 활성화"
+13 -9
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: changedetection.io 0.60.3\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-09-04 14:11+0200\n"
"POT-Creation-Date: 2026-09-09 14:48+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -373,6 +373,18 @@ msgstr ""
msgid "Import"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3452,14 +3464,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr ""
@@ -384,6 +384,18 @@ msgstr "Czas ponownej kontroli (w minutach)"
msgid "Import"
msgstr "Importuj"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr "Zawsze rozwinięte"
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3612,14 +3624,6 @@ msgstr "Krótki (1 minuta temu)"
msgid "Navigation sidebar"
msgstr "Pasek nawigacyjny"
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr "Zwiń pasek ikon (rozwija się po najechaniu kursorem)"
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr "Zawsze rozwinięte"
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Włączono kontrolę bezpieczeństwa tokenu dostępu do API"
@@ -377,6 +377,18 @@ msgstr "Tempo de rechecagem (minutos)"
msgid "Import"
msgstr "Importar"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3503,14 +3515,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Verificação de segurança do token de acesso à API ativada"
@@ -381,6 +381,18 @@ msgstr "Время перепроверки (минуты)"
msgid "Import"
msgstr "Импорт"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3571,14 +3583,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Проверка безопасности токена доступа к API включена"
@@ -383,6 +383,18 @@ msgstr "Yeniden kontrol süresi (dakika)"
msgid "Import"
msgstr "İçe Aktar"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3506,14 +3518,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "API erişim belirteci güvenlik kontrolü etkin"
@@ -375,6 +375,18 @@ msgstr "Час перевірки (хвилини)"
msgid "Import"
msgstr "Імпорт"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3485,14 +3497,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Перевірку безпеки токена доступу API увімкнено"
@@ -379,6 +379,18 @@ msgstr "复检间隔(分钟)"
msgid "Import"
msgstr "导入"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3459,14 +3471,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "已启用 API 访问令牌安全检查"
@@ -378,6 +378,18 @@ msgstr "複查時間(分鐘)"
msgid "Import"
msgstr "匯入"
#: changedetectionio/blueprint/menu_modes.py
msgid "Expand on hover"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/blueprint/menu_modes.py
msgid "Stays minimal"
msgstr ""
#: changedetectionio/blueprint/rss/single_watch.py
#, python-format
msgid "Watch with UUID %(uuid)s not found"
@@ -3459,14 +3471,6 @@ msgstr ""
msgid "Navigation sidebar"
msgstr ""
#: changedetectionio/forms.py
msgid "Collapsed icon rail (expands on hover)"
msgstr ""
#: changedetectionio/forms.py
msgid "Always expanded"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "已啟用 API 存取權杖安全檢查"