WIP
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Has been cancelled
ChangeDetection.io App Test / lint-code (push) Has been cancelled
ChangeDetection.io App Test / lint-translations (push) Has been cancelled
ChangeDetection.io App Test / lint-template-i18n (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Test the built package works basically. (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-10 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-11 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-12 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-13 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-14 (push) Has been cancelled

This commit is contained in:
dgtlmoon
2026-06-14 13:29:39 +02:00
parent 6d2da5b3f8
commit a2d77752c0
43 changed files with 3882 additions and 646 deletions
@@ -1,4 +1,5 @@
from flask import Blueprint, render_template
from flask import Blueprint, render_template, request, jsonify, make_response
from loguru import logger
from changedetectionio import forms
from changedetectionio.auth_decorator import login_optionally_required
@@ -6,7 +7,7 @@ from changedetectionio.store import ChangeDetectionStore
def construct_blueprint(datastore: ChangeDetectionStore):
add_watch_ui_blueprint = Blueprint('add_watch_ui', __name__, template_folder="templates")
add_watch_ui_blueprint = Blueprint('add_watch_ui', __name__, template_folder="templates", static_folder="static")
@add_watch_ui_blueprint.route("/", methods=['GET'])
@login_optionally_required
@@ -24,4 +25,64 @@ def construct_blueprint(datastore: ChangeDetectionStore):
llm_intent_watch_placeholder=LLM_INTENT_WATCH_PLACEHOLDER,
)
@add_watch_ui_blueprint.route("/snapshot", methods=['GET'])
@login_optionally_required
def add_watch_ui_snapshot():
"""One-shot live fetch of an arbitrary URL for the Add Watch visual selector.
Reuses the same browser machinery as Browser Steps (browsersteps_live_ui +
the dedicated async loop) but without needing a persisted watch - we just
connect, "Goto site", grab the screenshot + xpath element data, then tear
the browser down again. Element selection then happens client-side on the
returned data, exactly like the watch Edit page's visual selector.
"""
import base64
from changedetectionio.blueprint.browser_steps import (
run_async_in_browser_loop,
_close_session_resources,
acquire_browser_for_fetcher,
)
from changedetectionio.browser_steps.browser_steps import browsersteps_live_ui
url = (request.args.get('url') or '').strip()
if not url or not url.lower().startswith(('http://', 'https://')):
return make_response('Please enter a valid http(s):// URL', 400)
# Use whatever fetcher the application is configured to use by default
# (e.g. CloakBrowser, Playwright/sockpuppet) so the preview matches real checks.
fetcher_name = datastore.data['settings']['application'].get('fetch_backend', 'html_requests')
logger.debug(f"Add-watch snapshot: fetching '{url}' using system default fetcher '{fetcher_name}'")
async def _fetch_snapshot():
keepalive_ms = 30 * 1000
browser, playwright_context = await acquire_browser_for_fetcher(
fetcher_name, proxy=None, keepalive_ms=keepalive_ms
)
stepper = browsersteps_live_ui(playwright_browser=browser, proxy=None, start_url=url)
session = {'browserstepper': stepper, 'browser': browser, 'playwright_context': playwright_context}
try:
await stepper.connect(proxy=None)
await stepper.call_action(action_name="Goto site", selector=None, optional_value=None)
return await stepper.get_current_state()
finally:
await _close_session_resources(session, label=' for add-watch snapshot')
try:
(screenshot, xpath_data) = run_async_in_browser_loop(_fetch_snapshot())
except Exception as e:
logger.error(f"Add-watch snapshot fetch failed for {url}: {e}")
if 'ECONNREFUSED' in str(e):
return make_response('Unable to start the Playwright Browser session, is sockpuppetbrowser running? '
'The live preview needs a fetcher that supports Javascript and screenshots.', 502)
return make_response(str(e).splitlines()[0] if str(e) else 'Could not fetch the page', 502)
if not screenshot:
return make_response('Could not capture a screenshot for that URL', 502)
return jsonify({
"screenshot": f"data:image/jpeg;base64,{base64.b64encode(screenshot).decode('ascii')}",
"xpath_data": xpath_data,
})
return add_watch_ui_blueprint
@@ -0,0 +1,87 @@
// Add Watch UI glue: fetch a live snapshot for the entered URL and drive the
// shared visual selector (window.initVisualSelector from visual-selector.js).
$(document).ready(() => {
const $url = $('#url');
const $go = $('#add-watch-go');
const $emptyState = $('#add-watch-empty-state');
const $spinner = $('#add-watch-spinner');
const $error = $('#add-watch-error');
const $wrapper = $('#selector-wrapper');
const $xpathRow = $('#selector-current-xpath');
const $byElement = $('#by-element-toggle');
const $clear = $('#clear-selector');
const $includeFilters = $('#include_filters');
const vs = window.initVisualSelector({
$canvas: $('#selector-canvas'),
$includeFilters: $includeFilters,
$background: $('#selector-background'),
$xpathDisplay: $('#selector-current-xpath span'),
$fetchingNotice: $('#add-watch-spinner .fetching-update-notice'),
$wrapper: $wrapper,
$clearButton: $clear,
enableSelection: false, // off until the user opts into "Select by element"
processorIsImage: false,
// The snapshot comes from the live browser-steps capture, so scale X by the page
// CSS width (browser_width) like browser-steps.js - handles device-scale-factor != 1.
scaleByBrowserWidth: true,
});
function showState(which) {
// which: 'empty' | 'loading' | 'error' | 'ready'
$emptyState.toggle(which === 'empty');
$spinner.toggle(which === 'loading');
$error.toggle(which === 'error');
const ready = which === 'ready';
$wrapper.toggle(ready);
$xpathRow.toggle(ready && $byElement.is(':checked'));
$clear.toggle(ready && $byElement.is(':checked'));
}
function fetchSnapshot() {
const url = ($url.val() || '').trim();
if (!url) {
$url.focus();
return;
}
showState('loading');
$.ajax({
url: add_watch_snapshot_url,
data: {url: url},
dataType: 'json',
}).done((data) => {
showState('ready');
vs.load({screenshotSrc: data.screenshot, xpathData: data.xpath_data});
}).fail((xhr) => {
const msg = (xhr && xhr.responseText) ? xhr.responseText : 'Could not fetch a preview for that URL.';
$error.text(msg);
showState('error');
});
}
$go.on('click', fetchSnapshot);
// Enter in the URL box should fetch a preview, not submit the whole form
$url.on('keydown', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
fetchSnapshot();
}
});
// "Select by element" toggles live hover/click element selection
$byElement.on('change', function () {
const on = $(this).is(':checked');
vs.setSelectionEnabled(on);
$xpathRow.toggle(on && $wrapper.is(':visible'));
$clear.toggle(on && $wrapper.is(':visible'));
if (!on) {
$includeFilters.val('');
}
});
showState('empty');
});
@@ -2,42 +2,94 @@
{%- block content -%}
{%- from '_helpers.html' import render_simple_field, render_field, render_nolabel_field -%}
<div class="box" id="form-quick-watch-add">
<div class="box" id="add-watch-ui">
<form class="pure-form" action="{{ url_for('ui.ui_views.form_quick_watch_add') }}" method="POST" id="new-watch-form">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" >
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<!-- Filled in by the visual selector when "Select by element" is used -->
<input type="hidden" name="include_filters" id="include_filters" value="">
<fieldset>
<legend>{{ _('Add a new web page change detection watch') }}</legend>
<div id="watch-add-wrapper-zone">
{{ render_nolabel_field(form.url, placeholder="https://...", required=true) }}
{{ render_nolabel_field(form.watch_submit_button, title=_("Watch this URL!") ) }}
{{ render_nolabel_field(form.edit_and_watch_submit_button, title=_("Edit first then Watch") ) }}
<!-- TOP : enter the URL and fetch a live preview -->
<div id="add-watch-url-row">
{{ render_nolabel_field(form.url, placeholder="https://...", required=true, class="pure-input-1") }}
<button type="button" id="add-watch-go" class="pure-button pure-button-primary">{{ _('Go') }}</button>
</div>
{% if llm_configured %}
<div id="quick-watch-llm-intent" style="margin-top: 0.5em;">
<textarea name="llm_intent"
id="quick_watch_llm_intent"
rows="2"
class="pure-input-1"
placeholder="{{ _('AI — Notify when…') }} {{ llm_intent_watch_placeholder }}"></textarea>
</div>
{% endif %}
<div id="watch-group-tag">
{{ render_field(form.tags, value='', placeholder=_("Watch group / tag"), class="transparent-field") }}
</div>
<div id="quick-watch-processor-type">
{{ render_simple_field(form.processor) }}
<div id="add-watch-panes">
<!-- LEFT : live visual-selector preview -->
<div id="add-watch-selector-pane">
<div id="add-watch-empty-state">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<strong>{{ _('Enter a URL to get started!') }}</strong>
<span>{{ _('Enter a URL in the input box above to get started.') }}</span>
</div>
<div id="add-watch-spinner" style="display: none;">
<div class="spinner"></div>
<span class="fetching-update-notice">{{ _('Fetching screenshot and element information…') }}</span>
</div>
<div id="add-watch-error" style="display: none;"></div>
<!-- The visual selector markup the shared initVisualSelector() expects -->
<div id="selector-wrapper" style="display: none;">
<img id="selector-background">
<canvas id="selector-canvas"></canvas>
</div>
<div id="selector-current-xpath" style="display: none;"><strong>{{ _('Currently:') }}</strong>&nbsp;<span class="text"></span></div>
</div>
<!-- RIGHT : options -->
<div id="add-watch-options-pane">
<div class="add-watch-option-group" id="quick-watch-processor-type">
{{ render_simple_field(form.processor) }}
</div>
<div class="add-watch-option-group" id="by-element-toggle-group">
<label class="pure-checkbox" for="by-element-toggle">
<input type="checkbox" id="by-element-toggle"> {{ _('Select by element') }}
</label>
<span class="pure-form-message-inline">{{ _('Hover & click the preview to watch just one part of the page.') }}</span>
<a id="clear-selector" class="pure-button button-secondary button-xsmall" style="display: none;">{{ _('Clear selection') }}</a>
</div>
{% if llm_configured %}
<div class="add-watch-option-group" id="quick-watch-llm-intent">
<label for="quick_watch_llm_intent"><strong>{{ _('What matters — when to notify me') }}</strong></label>
<textarea name="llm_intent"
id="quick_watch_llm_intent"
rows="4"
class="pure-input-1"
placeholder="{{ _('e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants appear. Skip review additions.') }}"></textarea>
</div>
{% endif %}
<div class="add-watch-option-group" id="watch-group-tag">
{{ render_field(form.tags, value='', placeholder=_("Watch group / tag"), class="transparent-field") }}
</div>
<div class="add-watch-option-group" id="add-watch-submit-row">
{{ render_nolabel_field(form.watch_submit_button, title=_("Watch this URL!")) }}
{{ render_nolabel_field(form.edit_and_watch_submit_button, title=_("Edit first then Watch")) }}
</div>
</div>
</div>
</fieldset>
</form>
</div>
<div class="box" id="add-watch-live-info">
<div class="add-watch-live-placeholder">
<h3>{{ _('Live activity') }}</h3>
<p class="muted">{{ _('Recent additions and live check status will appear here.') }}</p>
<div class="add-watch-live-stream" data-placeholder="true">
<em>{{ _('Waiting for activity…') }}</em>
</div>
</div>
</div>
<script>
const add_watch_snapshot_url = "{{ url_for('add_watch_ui.add_watch_ui_snapshot') }}";
</script>
<script src="{{url_for('static_content', group='js', filename='plugins.js')}}"></script>
<script src="{{url_for('static_content', group='js', filename='visual-selector.js')}}"></script>
<script src="{{url_for('add_watch_ui.static', filename='add-watch.js')}}"></script>
{%- endblock -%}
@@ -131,6 +131,47 @@ async def _close_session_resources(session_data, label=''):
logger.warning(f"Error stopping playwright context{label}: {e}")
async def acquire_browser_for_fetcher(fetcher_name, proxy=None, keepalive_ms=None):
"""Acquire a Playwright browser for the given fetcher backend.
Mirrors normal fetching: fetchers that launch their own browser (e.g. CloakBrowser)
provide get_browsersteps_browser(); otherwise we connect over CDP to the configured
Playwright/sockpuppetbrowser driver. Returns (browser, playwright_context).
"""
from changedetectionio import content_fetchers
from playwright.async_api import async_playwright
logger.debug(f"acquire_browser_for_fetcher: requested fetcher='{fetcher_name}', proxy={'yes' if proxy else 'no'}, keepalive_ms={keepalive_ms}")
browser = None
playwright_context = None
# If the fetcher has its own browser launch (runs locally rather than via CDP), use it.
fetcher_class = getattr(content_fetchers, fetcher_name, None) if fetcher_name else None
if fetcher_class and hasattr(fetcher_class, 'get_browsersteps_browser'):
logger.debug(f"acquire_browser_for_fetcher: fetcher '{fetcher_name}' provides its own browser, launching locally")
result = await fetcher_class.get_browsersteps_browser(proxy=proxy, keepalive_ms=keepalive_ms)
if result is not None:
browser, playwright_context = result
logger.info(f"acquire_browser_for_fetcher: using fetcher-specific browser for '{fetcher_name}'")
else:
logger.debug(f"acquire_browser_for_fetcher: '{fetcher_name}' returned no browser, falling back to CDP")
else:
logger.debug(f"acquire_browser_for_fetcher: fetcher '{fetcher_name}' has no get_browsersteps_browser(), using CDP")
# Default: connect to the remote Playwright/sockpuppetbrowser via CDP
if browser is None:
base_url = os.getenv('PLAYWRIGHT_DRIVER_URL', '').strip('"')
logger.debug(f"acquire_browser_for_fetcher: connecting over CDP to '{base_url}' for fetcher '{fetcher_name}'")
playwright_context = await async_playwright().start()
a = "?" if '?' not in base_url else '&'
connect_url = base_url + a + f"timeout={keepalive_ms}"
browser = await playwright_context.chromium.connect_over_cdp(connect_url, timeout=keepalive_ms)
logger.info(f"acquire_browser_for_fetcher: connected over CDP for fetcher '{fetcher_name}'")
return browser, playwright_context
def cleanup_expired_sessions():
"""Remove expired browsersteps sessions and cleanup their resources"""
global browsersteps_sessions, browsersteps_watch_to_session
@@ -222,36 +263,14 @@ def construct_blueprint(datastore: ChangeDetectionStore):
proxy['password'] = parsed.password
logger.debug(f"Browser Steps: UUID {watch_uuid} selected proxy {proxy_url}")
# Resolve the fetcher class for this watch so we can ask it to launch its own browser
# Resolve the fetcher backend for this watch so we can ask it to launch its own browser
# if it supports that (e.g. CloakBrowser, which runs locally rather than via CDP)
watch = datastore.data['watching'][watch_uuid]
from changedetectionio import content_fetchers
fetcher_name = watch.get_fetch_backend or 'system'
if fetcher_name == 'system':
fetcher_name = datastore.data['settings']['application'].get('fetch_backend', 'html_requests')
fetcher_class = getattr(content_fetchers, fetcher_name, None)
browser = None
playwright_context = None
# If the fetcher has its own browser launch for the live steps UI, use it.
# get_browsersteps_browser(proxy, keepalive_ms) returns (browser, playwright_context_or_None)
# or None to fall back to the default CDP path.
if fetcher_class and hasattr(fetcher_class, 'get_browsersteps_browser'):
result = await fetcher_class.get_browsersteps_browser(proxy=proxy, keepalive_ms=keepalive_ms)
if result is not None:
browser, playwright_context = result
logger.debug(f"Browser Steps: using fetcher-specific browser for '{fetcher_name}'")
# Default: connect to the remote Playwright/sockpuppetbrowser via CDP
if browser is None:
playwright_instance = async_playwright()
playwright_context = await playwright_instance.start()
base_url = os.getenv('PLAYWRIGHT_DRIVER_URL', '').strip('"')
a = "?" if '?' not in base_url else '&'
base_url += a + f"timeout={keepalive_ms}"
browser = await playwright_context.chromium.connect_over_cdp(base_url, timeout=keepalive_ms)
logger.debug(f"Browser Steps: using CDP connection to {base_url}")
browser, playwright_context = await acquire_browser_for_fetcher(fetcher_name, proxy=proxy, keepalive_ms=keepalive_ms)
browsersteps_start_session['browser'] = browser
browsersteps_start_session['playwright_context'] = playwright_context
@@ -288,6 +288,10 @@ nav
{{ render_field(form.application.form.pager_size) }}
<span class="pure-form-message-inline">{{ _('Number of items per page in the watch overview list, 0 to disable.') }}</span>
</div>
<div class="pure-control-group">
{{ render_field(form.application.form.ui.form.timeago_format) }}
<span class="pure-form-message-inline">{{ _('How "Last Checked" and "Last Changed" times are shown in the watch overview list.') }}</span>
</div>
</div>
<div class="tab-pane-inner" id="proxies">
+5
View File
@@ -30,6 +30,11 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe
extras = {'paused': add_paused, 'processor': processor}
if llm_intent:
extras['llm_intent'] = llm_intent
# Filters picked with the Add Watch visual selector ("by element" mode)
include_filters = [l.strip() for l in request.form.get('include_filters', '').split('\n') if l.strip()]
if include_filters:
extras['include_filters'] = include_filters
new_uuid = datastore.add_watch(url=url, tag=request.form.get('tags','').strip(), extras=extras)
if new_uuid:
@@ -220,7 +220,7 @@ window.watchOverviewI18n = {
<th style="white-space: nowrap; text-align: center;"><input style="vertical-align: middle" type="checkbox" id="check-all" > <a class="{{ 'active '+link_order if sort_attribute == 'date_created' else 'inactive' }}" href="{{url_for('watchlist.index', sort='date_created', order=link_order, tag=active_tag_uuid)}}"># <span class='arrow {{link_order}}'></span></a></th>
<th id="mute-pause">
<div>
<a class="{{ 'active '+link_order if sort_attribute == 'paused' else 'inactive' }}" href="{{url_for('watchlist.index', sort='paused', order=link_order, tag=active_tag_uuid)}}"><i data-feather="pause" style="vertical-align: bottom; width: 16px; height: 16px;"></i><span class='arrow {{link_order}}'></span></a>
<a class="{{ 'active '+link_order if sort_attribute == 'paused' else 'inactive' }}" href="{{url_for('watchlist.index', sort='paused', order=link_order, tag=active_tag_uuid)}}"><i data-feather="pause" style="width: 16px; height: 16px;"></i><span class='arrow {{link_order}}'></span></a>
<a class="{{ 'active '+link_order if sort_attribute == 'notification_muted' else 'inactive' }}" href="{{url_for('watchlist.index', sort='notification_muted', order=link_order, tag=active_tag_uuid)}}"><i data-feather="volume-2" style="width: 16px; height: 16px;"></i><span class='arrow {{link_order}}'></span></a>
</div>
</th>
@@ -350,6 +350,16 @@ window.watchOverviewI18n = {
{{ price }} {{ cur }}<!-- as string -->
{%- endif -%}
</span>
{%- set price_change_pct = restock.get_price_change_percent() -%}
{%- if price_change_pct is not none -%}
{%- set prev_price = restock.get_prev_price() -%}
{%- set prev_disp = (prev_price|format_number_locale ~ ' ' ~ cur) if prev_price is number else prev_price -%}
{%- if price_change_pct < 0 -%}
<span class="price-change down" title="{{ _('Price change since previous price (%(prev)s)', prev=prev_disp) }}">▼ {{ '%g'|format(price_change_pct) }}%</span>
{%- else -%}
<span class="price-change up" title="{{ _('Price change since previous price (%(prev)s)', prev=prev_disp) }}">▲ +{{ '%g'|format(price_change_pct) }}%</span>
{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- elif not watch.has_restock_info -%}
<span class="restock-label error">{{ _('No information') }}</span>
+6 -4
View File
@@ -268,24 +268,26 @@ def _jinja2_filter_datetime(watch_obj, format="%Y-%m-%d %H:%M:%S"):
if watch_obj['last_checked'] == 0:
return gettext('Not yet')
locale = get_timeago_locale(str(get_locale()))
short = datastore.data['settings']['application'].get('ui', {}).get('timeago_format') == 'short'
locale = get_timeago_locale(str(get_locale()), short=short)
try:
return timeago.format(int(watch_obj['last_checked']), time.time(), locale)
except:
# Fallback to English if locale not supported by timeago
return timeago.format(int(watch_obj['last_checked']), time.time(), 'en')
return timeago.format(int(watch_obj['last_checked']), time.time(), 'en_short' if short else 'en')
@app.template_filter('format_timestamp_timeago')
def _jinja2_filter_datetimestamp(timestamp, format="%Y-%m-%d %H:%M:%S"):
if not timestamp:
return gettext('Not yet')
locale = get_timeago_locale(str(get_locale()))
short = datastore.data['settings']['application'].get('ui', {}).get('timeago_format') == 'short'
locale = get_timeago_locale(str(get_locale()), short=short)
try:
return timeago.format(int(timestamp), time.time(), locale)
except:
# Fallback to English if locale not supported by timeago
return timeago.format(int(timestamp), time.time(), 'en')
return timeago.format(int(timestamp), time.time(), 'en_short' if short else 'en')
@app.template_filter('pagination_slice')
+3
View File
@@ -1074,6 +1074,9 @@ class globalSettingsApplicationUIForm(Form):
socket_io_enabled = BooleanField(_l('Realtime UI Updates Enabled'), default=True, validators=[validators.Optional()])
favicons_enabled = BooleanField(_l('Favicons Enabled'), default=True, validators=[validators.Optional()])
use_page_title_in_list = BooleanField(_l('Use page <title> in watch overview list')) #BooleanField=True
timeago_format = SelectField(_l('Relative time format'),
choices=[('long', _l('Long (1 minute ago)')), ('short', _l('Short (1m ago)'))],
default='long', validators=[validators.Optional()])
# datastore.data['settings']['application']..
class globalSettingsApplicationForm(commonSettingsForm):
+87 -2
View File
@@ -6,7 +6,7 @@ import os
from pathlib import Path
def get_timeago_locale(flask_locale):
def get_timeago_locale(flask_locale, short=False):
"""
Convert Flask-Babel locale codes to timeago library locale codes.
@@ -23,10 +23,19 @@ def get_timeago_locale(flask_locale):
Args:
flask_locale (str): Flask-Babel locale code (e.g., 'cs', 'zh', 'pt')
short (bool): Return a compact "1m ago" style locale instead of "1 minute ago".
timeago only ships 'en_short'; the other short locales are registered
by register_short_timeago_locales() below. Unsupported languages fall
back to 'en_short' so short mode is always honoured.
Returns:
str: timeago library locale code (e.g., 'en', 'zh_CN', 'pt_PT')
str: timeago library locale code (e.g., 'en', 'zh_CN', 'pt_PT', 'de_short')
"""
if short:
# Short forms are translated through the normal gettext (.po/.mo) workflow rather than
# timeago's bundled per-language tables; build + register the table for this locale.
return register_short_timeago_locale(flask_locale)
locale_map = {
'zh': 'zh_CN', # Chinese Simplified
# timeago library just hasn't been updated to use the more modern locale naming convention, before BCP 47 / RFC 5646.
@@ -45,6 +54,82 @@ def get_timeago_locale(flask_locale):
}
return locale_map.get(flask_locale, flask_locale)
# --- Short ("1m ago") timeago locales -------------------------------------------------
#
# timeago only ships 'en_short' and resolves a locale by name via
# __import__('timeago.locales.<name>'), which checks sys.modules first. So we register a table
# at runtime per locale. Rather than hard-code a table per language, the short strings are
# routed through the normal gettext (.po/.mo) workflow: the rows below are wrapped in
# lazy_gettext (_l) so `python setup.py extract_messages` picks them up, and they resolve to
# the active locale when rendered. Translators maintain the short forms in messages.po just
# like every other string.
#
# 14 rows of (past, future) following timeago's index order:
# now, Ns, 1m, Nm, 1h, Nh, 1d, Nd, 1w, Nw, 1mo, Nmo, 1yr, Nyr ('%s' = the number)
# The English source strings double as the gettext msgids.
def _build_short_timeago_rows():
from flask_babel import lazy_gettext as _l
return [
(_l('just now'), _l('right now')),
(_l('%ss ago'), _l('in %ss')),
(_l('1m ago'), _l('in 1m')),
(_l('%sm ago'), _l('in %sm')),
(_l('1h ago'), _l('in 1h')),
(_l('%sh ago'), _l('in %sh')),
(_l('1d ago'), _l('in 1d')),
(_l('%sd ago'), _l('in %sd')),
(_l('1w ago'), _l('in 1w')),
(_l('%sw ago'), _l('in %sw')),
(_l('1mo ago'), _l('in 1mo')),
(_l('%smo ago'), _l('in %smo')),
(_l('1yr ago'), _l('in 1yr')),
(_l('%syr ago'), _l('in %syr')),
]
_short_timeago_rows = None
_registered_short_locales = set()
def register_short_timeago_locale(flask_locale):
"""
Build the short timeago table for `flask_locale` from the gettext catalog and register it
under a synthetic name so timeago.format(..., <name>) can use it. Returns the locale name
to hand to timeago (falls back to the bundled 'en_short' if anything goes wrong).
The table is resolved with flask_babel.force_locale so it is correct regardless of which
locale is active, and cached per language so the gettext lookups happen only once each.
"""
name = 'cd_short_' + str(flask_locale).replace('-', '_')
if name in _registered_short_locales:
return name
try:
import sys
import types
import timeago.locales as timeago_locales
from flask_babel import force_locale
global _short_timeago_rows
if _short_timeago_rows is None:
_short_timeago_rows = _build_short_timeago_rows()
with force_locale(str(flask_locale)):
table = [[str(past), str(future)] for past, future in _short_timeago_rows]
mod_name = 'timeago.locales.' + name
mod = types.ModuleType(mod_name)
mod.LOCALE = table
sys.modules[mod_name] = mod
setattr(timeago_locales, name, mod)
_registered_short_locales.add(name)
return name
except Exception:
# Outside an app context, or any unexpected failure -> bundled English short locale.
return 'en_short'
# Language metadata: flag icon CSS class and native name
# Using flag-icons library: https://flagicons.lipis.dev/
LANGUAGE_DATA = {
+2 -1
View File
@@ -78,7 +78,8 @@ class model(dict):
'use_page_title_in_list': True,
'open_diff_in_new_tab': True,
'socket_io_enabled': True,
'favicons_enabled': True
'favicons_enabled': True,
'timeago_format': 'long', # 'long' = "1 minute ago", 'short' = "1m ago"
},
}
}
@@ -45,7 +45,8 @@ class Restock(dict):
'in_stock': None,
'price': None,
'currency': None,
'original_price': None
'original_price': None,
'prev_price': None # price at the previous check, for the watch-list up/down arrow (display only)
}
# Initialize the dictionary with default values
@@ -66,6 +67,31 @@ class Restock(dict):
super().__setitem__(key, value)
def get_prev_price(self):
"""Price at the previous check. Falls back to original_price for watches
saved before prev_price existed. Returns a float or None."""
prev = self.get('prev_price')
if prev is None:
prev = self.get('original_price')
return prev
def get_price_change_percent(self):
"""Signed % change of the current price vs the previous price, rounded to one
decimal place (e.g. -18.0, 5.3). Returns None when it can't be computed -
no/zero previous price, non-numeric values, or no change."""
try:
price = float(self.get('price'))
prev = self.get_prev_price()
prev = float(prev) if prev is not None else None
except (TypeError, ValueError):
return None
if prev is None or prev == 0:
return None
pct = round((price - prev) / prev * 100.0, 1)
return pct if pct != 0 else None
def get_price_from_history_str(history_str):
m = _price_re.search(history_str)
if not m:
@@ -86,7 +86,7 @@ SYSTEM_PROMPT = (
'No markdown, no backticks, no explanation — pure JSON only.'
)
_MAX_CONTENT_CHARS = 8_000
_MAX_CONTENT_CHARS = 20_000
def _extract_jsonld(html_content: str) -> str:
@@ -564,10 +564,14 @@ class perform_site_check(difference_detection_processor):
# Main detection method
fetched_md5 = None
# store original price if not set
if itemprop_availability and itemprop_availability.get('price') and not itemprop_availability.get('original_price'):
itemprop_availability['original_price'] = itemprop_availability.get('price')
update_obj['restock']["original_price"] = itemprop_availability.get('price')
# Original price = the price at the FIRST check. Set it once and then preserve it across
# every later check (display only) so the watch list can show "first seen" alongside the
# current price. (Previously this was re-set to the current price on every check.)
old_original_price = (watch.get('restock') or {}).get('original_price')
if old_original_price is not None:
update_obj['restock']['original_price'] = old_original_price
elif update_obj['restock'].get('price') is not None:
update_obj['restock']['original_price'] = update_obj['restock'].get('price')
if not self.fetcher.instock_data and not itemprop_availability.get('availability') and not itemprop_availability.get('price'):
raise ProcessorException(
@@ -594,6 +598,18 @@ class perform_site_check(difference_detection_processor):
logger.warning(f"Setting instock to FALSE, scraper found '{self.fetcher.instock_data}' in the body but metadata reported not-in-stock")
update_obj['restock']["in_stock"] = False
# Remember the price from *before the last actual price change* so the watch list can
# show a persistent up/down arrow. Only bump prev_price when the price really changed -
# otherwise an unchanged check would overwrite it and we'd lose the comparison point.
# Display only - not part of the snapshot/md5, so it never affects change detection.
old_restock = watch.get('restock') or {}
old_price = old_restock.get('price')
new_price = update_obj['restock'].get('price')
if new_price is not None and old_price is not None and new_price != old_price:
update_obj['restock']['prev_price'] = old_price # price moved: remember what we moved from
else:
update_obj['restock']['prev_price'] = old_restock.get('prev_price') # unchanged: keep the existing reference
# What we store in the snapshot
price = update_obj.get('restock').get('price') if update_obj.get('restock').get('price') else ""
snapshot_content = f"In Stock: {update_obj.get('restock').get('in_stock')} - Price: {price}"
+4 -5
View File
@@ -1,6 +1,5 @@
import timeago
from flask_socketio import SocketIO
from flask_babel import gettext, get_locale
from flask_babel import gettext
import time
import os
@@ -8,7 +7,6 @@ from loguru import logger
from blinker import signal
from changedetectionio import strtobool
from changedetectionio.languages import get_timeago_locale
class SignalHandler:
@@ -144,7 +142,7 @@ def handle_watch_update(socketio, **kwargs):
# Emit the watch update to all connected clients
from changedetectionio.flask_app import update_q
from changedetectionio.flask_app import _jinja2_filter_datetime
from changedetectionio.flask_app import _jinja2_filter_datetime, _jinja2_filter_datetimestamp
from changedetectionio import worker_pool
# Get list of watches that are currently running
@@ -165,7 +163,8 @@ def handle_watch_update(socketio, **kwargs):
'has_error': True if error_texts else False,
'has_favicon': True if watch.get_favicon_filename() else False,
'history_n': watch.history_n,
'last_changed_text': timeago.format(int(watch.last_changed), time.time(), get_timeago_locale(str(get_locale()))) if watch.history_n >= 2 and int(watch.last_changed) > 0 else gettext('Not yet'),
# Uses the same filter as the server-rendered list so the long/short (timeago_format) setting is honoured.
'last_changed_text': _jinja2_filter_datetimestamp(int(watch.last_changed)) if watch.history_n >= 2 and int(watch.last_changed) > 0 else gettext('Not yet'),
'last_checked': watch.get('last_checked'),
'last_checked_text': _jinja2_filter_datetime(watch),
'notification_muted': True if watch.get('notification_muted') else False,
+207 -105
View File
@@ -1,10 +1,34 @@
// Copyright (C) 2021 Leigh Morresi (dgtlmoon@gmail.com)
// All rights reserved.
// yes - this is really a hack, if you are a front-ender and want to help, please get in touch!
//
// Refactored into a reusable factory: window.initVisualSelector(opts)
// - edit.html drives it from stored screenshot + xpath-data URLs (auto-init at bottom of file)
// - the Add Watch UI drives it from inline snapshot data fetched on demand
// Both share the same hover/highlight/select core.
let runInClearMode = false;
window.initVisualSelector = function (opts) {
// ---- DOM references (passed in, no globals) ----
const $selectorCanvasElem = opts.$canvas;
const $includeFiltersElem = opts.$includeFilters;
const $selectorBackgroundElem = opts.$background;
const $selectorCurrentXpathElem = opts.$xpathDisplay; // the inner <span>
const $fetchingUpdateNoticeElem = opts.$fetchingNotice || $();
const $selectorWrapperElem = opts.$wrapper;
const $clearSelectorElem = opts.$clearButton || $();
$(document).ready(() => {
// edit.html supplies an AJAX url for the element data; the add-watch UI supplies data inline
const xpathDataUrl = opts.xpathDataUrl;
const isImageProcessor = !!opts.processorIsImage;
// Stored watch screenshots are DPR-1, so X scales by the screenshot's natural width.
// The live browser-steps capture (used by Add Watch) may render at device-scale-factor != 1,
// so its X must scale by the page's CSS width (browser_width) instead - exactly like
// browser-steps.js does. Y always scales by the screenshot's natural height.
const scaleByBrowserWidth = !!opts.scaleByBrowserWidth;
// ---- state ----
let runInClearMode = false;
let selectionEnabled = opts.enableSelection !== false;
let currentSelections = [];
let currentSelection = null;
let appendToList = false;
@@ -22,16 +46,6 @@ $(document).ready(() => {
let drawnBox = null;
let resizeHandle = null;
const HANDLE_SIZE = 8;
const isImageProcessor = $('input[value="image_ssim_diff"]').is(':checked');
// Global jQuery selectors with "Elem" appended
const $selectorCanvasElem = $('#selector-canvas');
const $includeFiltersElem = $("#include_filters");
const $selectorBackgroundElem = $("img#selector-background");
const $selectorCurrentXpathElem = $("#selector-current-xpath span");
const $fetchingUpdateNoticeElem = $('.fetching-update-notice');
const $selectorWrapperElem = $("#selector-wrapper");
// Color constants
const FILL_STYLE_HIGHLIGHT = 'rgba(205,0,0,0.35)';
@@ -40,14 +54,10 @@ $(document).ready(() => {
const FILL_STYLE_REDLINE = 'rgba(255,0,0, 0.1)';
const STROKE_STYLE_REDLINE = 'rgba(225,0,0,0.9)';
$('#visualselector-tab').click(() => {
$selectorBackgroundElem.off('load');
currentSelections = [];
bootstrapVisualSelector();
});
function clearReset() {
ctx.clearRect(0, 0, c.width, c.height);
if (ctx) {
ctx.clearRect(0, 0, c.width, c.height);
}
if ($includeFiltersElem.val().length) {
alert("Existing filters under the 'Filters & Triggers' tab were cleared.");
@@ -87,23 +97,18 @@ $(document).ready(() => {
}
});
$('#clear-selector').on('click', () => {
$clearSelectorElem.on('click', () => {
clearReset();
});
// So if they start switching between visualSelector and manual filters, stop it from rendering old filters
$('li.tab a').on('click', () => {
runInClearMode = true;
});
if (!window.location.hash || window.location.hash !== '#visualselector') {
$selectorBackgroundElem.attr('src', '');
return;
}
// ---- public: (re)load a screenshot + element data into the selector ----
// source = { screenshotSrc: <url|dataURI>, xpathData: <object|undefined> }
function load(source) {
currentSelections = [];
runInClearMode = false;
bootstrapVisualSelector();
function bootstrapVisualSelector() {
$selectorBackgroundElem
.off("load error")
.on("error", () => {
$fetchingUpdateNoticeElem.html("<strong>Ooops!</strong> The VisualSelector tool needs at least one fetched page, please unpause the watch and/or wait for the watch to complete fetching and then reload this page.")
.css('color', '#bb0000');
@@ -111,16 +116,24 @@ $(document).ready(() => {
})
.on('load', () => {
console.log("Loaded background...");
c = document.getElementById("selector-canvas");
c = $selectorCanvasElem[0];
xctx = c.getContext("2d");
ctx = c.getContext("2d");
fetchData();
if (source.xpathData) {
// Inline data (add-watch snapshot) - no extra round trip needed
applyElementData(source.xpathData);
} else {
fetchData();
}
$selectorCanvasElem.off("mousemove mousedown");
})
.attr("src", screenshot_url);
});
let s = `${$selectorBackgroundElem.attr('src')}?${new Date().getTime()}`;
$selectorBackgroundElem.attr('src', s);
// data: URIs must be used verbatim; real URLs get a cache-buster
let src = source.screenshotSrc;
if (src && src.indexOf('data:') !== 0) {
src = `${src}?${new Date().getTime()}`;
}
$selectorBackgroundElem.attr("src", src);
}
function alertIfFilterNotFound() {
@@ -139,28 +152,32 @@ $(document).ready(() => {
$fetchingUpdateNoticeElem.html("Fetching element data..");
$.ajax({
url: watch_visual_selector_data_url,
url: xpathDataUrl,
context: document.body
}).done((data) => {
$fetchingUpdateNoticeElem.html("Rendering..");
selectorData = data;
sortScrapedElementsBySize();
console.log(`Reported browser width from backend: ${data['browser_width']}`);
// Little sanity check for the user, alert them if something missing
alertIfFilterNotFound();
setScale();
reflowSelector();
// Initialize draw mode after everything is set up
initializeDrawMode();
$fetchingUpdateNoticeElem.fadeOut();
applyElementData(data);
});
}
function applyElementData(data) {
$fetchingUpdateNoticeElem.html("Rendering..");
selectorData = data;
sortScrapedElementsBySize();
console.log(`Reported browser width from backend: ${data['browser_width']}`);
// Little sanity check for the user, alert them if something missing
alertIfFilterNotFound();
setScale();
reflowSelector();
// Initialize draw mode after everything is set up
initializeDrawMode();
$fetchingUpdateNoticeElem.fadeOut();
}
function updateFiltersText() {
// Assuming currentSelections is already defined and contains the selections
let uniqueSelections = new Set(currentSelections.map(sel => (sel[0] === '/' ? `xpath:${sel.xpath}` : sel.xpath)));
@@ -184,8 +201,16 @@ $(document).ready(() => {
$selectorWrapperElem.attr('width', selectorImageRect.width);
$('#visual-selector-heading').css('max-width', selectorImageRect.width + "px")
xScale = selectorImageRect.width / selectorImage.naturalWidth;
yScale = selectorImageRect.height / selectorImage.naturalHeight;
if (scaleByBrowserWidth && selectorData && selectorData['browser_width']) {
// xpath box coords are CSS pixels (getBoundingClientRect) and the scraper reports
// browser_width = window.innerWidth (also CSS px). The screenshot is displayed with a
// preserved aspect ratio, so a single uniform factor (displayed width / page CSS width)
// maps both axes in sync, regardless of the capture's device-pixel-ratio.
xScale = yScale = selectorImageRect.width / selectorData['browser_width'];
} else {
xScale = selectorImageRect.width / selectorImage.naturalWidth;
yScale = selectorImageRect.height / selectorImage.naturalHeight;
}
ctx.strokeStyle = STROKE_STYLE_HIGHLIGHT;
ctx.fillStyle = FILL_STYLE_REDLINE;
@@ -194,8 +219,57 @@ $(document).ready(() => {
$("#selector-current-xpath").css('max-width', selectorImageRect.width);
}
function bindElementHandlers() {
// Store handler references for later use
elementHandlers.handleMouseMove = handleMouseMove.debounce(5);
elementHandlers.handleMouseDown = handleMouseDown.debounce(5);
elementHandlers.handleMouseLeave = highlightCurrentSelected.debounce(5);
$selectorCanvasElem.bind('mousemove', elementHandlers.handleMouseMove);
$selectorCanvasElem.bind('mousedown', elementHandlers.handleMouseDown);
$selectorCanvasElem.bind('mouseleave', elementHandlers.handleMouseLeave);
}
function handleMouseMove(e) {
if (!e.offsetX && !e.offsetY) {
const targetOffset = $(e.target).offset();
e.offsetX = e.pageX - targetOffset.left;
e.offsetY = e.pageY - targetOffset.top;
}
ctx.fillStyle = FILL_STYLE_HIGHLIGHT;
selectorData['size_pos'].forEach(sel => {
if (e.offsetY > sel.top * yScale && e.offsetY < sel.top * yScale + sel.height * yScale &&
e.offsetX > sel.left * yScale && e.offsetX < sel.left * yScale + sel.width * yScale) {
setCurrentSelectedText(sel.xpath);
drawHighlight(sel);
currentSelections.push(sel);
currentSelection = sel;
highlightCurrentSelected();
currentSelections.pop();
}
})
}
function setCurrentSelectedText(s) {
$selectorCurrentXpathElem[0].innerHTML = s;
}
function drawHighlight(sel) {
ctx.strokeRect(sel.left * xScale, sel.top * yScale, sel.width * xScale, sel.height * yScale);
ctx.fillRect(sel.left * xScale, sel.top * yScale, sel.width * xScale, sel.height * yScale);
}
function handleMouseDown() {
// If we are in 'appendToList' mode, grow the list, if not, just 1
currentSelections = appendToList ? [...currentSelections, currentSelection] : [currentSelection];
highlightCurrentSelected();
updateFiltersText();
}
function reflowSelector() {
$(window).resize(() => {
$(window).off('resize.visualselector').on('resize.visualselector', () => {
setScale();
highlightCurrentSelected();
});
@@ -217,57 +291,13 @@ $(document).ready(() => {
highlightCurrentSelected();
updateFiltersText();
// Store handler references for later use
elementHandlers.handleMouseMove = handleMouseMove.debounce(5);
elementHandlers.handleMouseDown = handleMouseDown.debounce(5);
elementHandlers.handleMouseLeave = highlightCurrentSelected.debounce(5);
$selectorCanvasElem.bind('mousemove', elementHandlers.handleMouseMove);
$selectorCanvasElem.bind('mousedown', elementHandlers.handleMouseDown);
$selectorCanvasElem.bind('mouseleave', elementHandlers.handleMouseLeave);
function handleMouseMove(e) {
if (!e.offsetX && !e.offsetY) {
const targetOffset = $(e.target).offset();
e.offsetX = e.pageX - targetOffset.left;
e.offsetY = e.pageY - targetOffset.top;
}
ctx.fillStyle = FILL_STYLE_HIGHLIGHT;
selectorData['size_pos'].forEach(sel => {
if (e.offsetY > sel.top * yScale && e.offsetY < sel.top * yScale + sel.height * yScale &&
e.offsetX > sel.left * yScale && e.offsetX < sel.left * yScale + sel.width * yScale) {
setCurrentSelectedText(sel.xpath);
drawHighlight(sel);
currentSelections.push(sel);
currentSelection = sel;
highlightCurrentSelected();
currentSelections.pop();
}
})
if (selectionEnabled) {
bindElementHandlers();
}
function setCurrentSelectedText(s) {
$selectorCurrentXpathElem[0].innerHTML = s;
}
function drawHighlight(sel) {
ctx.strokeRect(sel.left * xScale, sel.top * yScale, sel.width * xScale, sel.height * yScale);
ctx.fillRect(sel.left * xScale, sel.top * yScale, sel.width * xScale, sel.height * yScale);
}
function handleMouseDown() {
// If we are in 'appendToList' mode, grow the list, if not, just 1
currentSelections = appendToList ? [...currentSelections, currentSelection] : [currentSelection];
highlightCurrentSelected();
updateFiltersText();
}
}
function highlightCurrentSelected() {
if (!xctx) return;
xctx.fillStyle = FILL_STYLE_GREYED_OUT;
xctx.strokeStyle = STROKE_STYLE_REDLINE;
xctx.lineWidth = 3;
@@ -279,6 +309,29 @@ $(document).ready(() => {
});
}
// Toggle hover/click element selection on the fly (Add Watch "by element" mode)
function setSelectionEnabled(enabled) {
selectionEnabled = enabled;
if (!c) return; // not loaded yet, will respect the flag in reflowSelector
if (enabled) {
if (!drawMode) {
bindElementHandlers();
if ($selectorCurrentXpathElem.length) {
$selectorCurrentXpathElem[0].innerHTML = 'Hover over elements to select';
}
}
} else {
$selectorCanvasElem.unbind('mousemove mousedown mouseleave');
currentSelections = [];
$includeFiltersElem.val('');
highlightCurrentSelected();
if ($selectorCurrentXpathElem.length) {
$selectorCurrentXpathElem[0].innerHTML = '';
}
}
}
// ============= BOX DRAWING MODE (for image_ssim_diff processor) =============
function initializeDrawMode() {
@@ -646,4 +699,53 @@ $(document).ready(() => {
drawStartX = x;
drawStartY = y;
}
});
// ---- public API ----
return {
load: load,
clear: clearReset,
setSelectionEnabled: setSelectionEnabled,
markClearMode: function () { runInClearMode = true; }
};
};
// ---------------------------------------------------------------------------
// Auto-init for the watch Edit page (edit.html), preserving previous behaviour.
// Detected by the presence of the `screenshot_url` global that edit.html sets.
// ---------------------------------------------------------------------------
$(document).ready(() => {
if (typeof screenshot_url === 'undefined') {
return; // Not the edit page - the Add Watch UI inits the selector itself
}
const isImageProcessor = $('input[value="image_ssim_diff"]').is(':checked');
const vs = window.initVisualSelector({
$canvas: $('#selector-canvas'),
$includeFilters: $("#include_filters"),
$background: $("img#selector-background"),
$xpathDisplay: $("#selector-current-xpath span"),
$fetchingNotice: $('.fetching-update-notice'),
$wrapper: $("#selector-wrapper"),
$clearButton: $('#clear-selector'),
xpathDataUrl: watch_visual_selector_data_url,
enableSelection: true,
processorIsImage: isImageProcessor,
});
$('#visualselector-tab').click(() => {
vs.load({screenshotSrc: screenshot_url});
});
// So if they start switching between visualSelector and manual filters, stop it from rendering old filters
$('li.tab a').on('click', () => {
vs.markClearMode();
});
if (window.location.hash === '#visualselector') {
vs.load({screenshotSrc: screenshot_url});
} else {
$("img#selector-background").attr('src', '');
}
});
@@ -0,0 +1,179 @@
/* Add Watch UI - 3-pane workspace (top: URL+Go, left: live visual selector, right: options) */
#add-watch-ui {
/* TOP : URL input + Go */
#add-watch-url-row {
display: flex;
gap: 0.5rem;
align-items: stretch;
margin-bottom: 1rem;
// render_nolabel_field wraps the input in a <span>
> span {
flex: 1 1 auto;
min-width: 0;
input {
width: 100%;
}
}
#add-watch-go {
flex: 0 0 auto;
white-space: nowrap;
}
}
/* PANES */
#add-watch-panes {
display: flex;
gap: 1rem;
align-items: stretch;
@media (max-width: 900px) {
flex-direction: column;
}
}
/* LEFT : live visual-selector preview */
#add-watch-selector-pane {
flex: 1 1 62%;
min-width: 0;
min-height: 380px;
position: relative;
overflow: auto; // the pane scrolls for tall snapshots, NOT the wrapper - keeps img+canvas aligned
border: 1px solid var(--color-background-tab);
border-radius: 6px;
background: rgba(0, 0, 0, 0.15);
padding: 0.75rem;
// Transient states fill and centre over the whole pane (only one is visible at a time)
#add-watch-empty-state,
#add-watch-spinner,
#add-watch-error {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.6rem;
text-align: center;
padding: 2rem 1rem;
}
#add-watch-empty-state {
opacity: 0.8;
svg {
opacity: 0.55;
}
strong {
font-size: 1.05rem;
}
span {
font-size: 0.85rem;
opacity: 0.8;
max-width: 32ch;
}
}
#add-watch-spinner {
gap: 1.2rem;
.spinner {
font-size: 5px; // scales the em-based spinner up a little
}
.fetching-update-notice {
font-size: 0.85rem;
opacity: 0.85;
}
}
#add-watch-error {
color: #ffb4b4;
font-size: 0.9rem;
word-break: break-word;
}
// Pin the highlight canvas exactly over the screenshot. The shared selector CSS
// (parts/_visualselector.scss) positions the img absolutely + canvas in-flow inside
// an overflow-y:scroll wrapper, whose scrollbar gutter offsets the two in this
// narrower pane. Here the img drives the layout (in normal flow) and the canvas is
// overlaid on top, so they stay pixel-aligned regardless of scrollbars.
#selector-wrapper {
position: relative;
display: block;
width: 100%;
max-height: none;
overflow: visible;
text-align: left;
> img {
position: relative;
display: block;
max-width: 100%;
height: auto;
z-index: 4;
}
> canvas {
position: absolute;
top: 0;
left: 0;
max-width: none;
z-index: 5;
}
}
}
/* RIGHT : options */
#add-watch-options-pane {
flex: 0 0 34%;
min-width: 0;
display: flex;
flex-direction: column;
gap: 1.1rem;
@media (max-width: 900px) {
flex: 1 1 auto;
}
.add-watch-option-group {
label {
display: inline-block;
}
}
#by-element-toggle-group {
.pure-form-message-inline {
display: block;
margin-top: 0.25rem;
font-size: 0.8rem;
opacity: 0.8;
}
#clear-selector {
margin-top: 0.5rem;
}
}
#quick-watch-llm-intent {
label {
display: block;
margin-bottom: 0.35rem;
}
}
#add-watch-submit-row {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-top: auto; // push the create buttons to the bottom of the pane
}
}
}
@@ -20,6 +20,7 @@
@use "parts/conditions_table";
@use "parts/socket";
@use "parts/visualselector";
@use "parts/add-watch";
@use "parts/widgets";
@use "parts/diff_image";
@use "parts/modal";
@@ -210,12 +211,7 @@ body.spinner-active {
}
section.content {
@media only screen and (max-width: $desktop-wide-breakpoint) {
padding-top: 80px;
}
@media only screen and (min-width: $desktop-wide-breakpoint) {
padding-top: 100px;
}
padding-top: 80px;
padding-bottom: 1em;
flex-direction: column;
@@ -1058,6 +1054,24 @@ ul {
@extend .inline-tag;
}
/* Price up/down indicator next to the restock price, e.g. "▼ -18%" */
.price-change {
white-space: nowrap;
font-weight: 700;
font-size: 90%;
margin-left: 4px;
vertical-align: middle;
/* Price dropped = good for a shopper = green; price rose = red */
&.down {
color: var(--color-background-button-green);
}
&.up {
color: var(--color-background-button-error);
}
}
#chrome-extension-link {
img {
height: 21px;
File diff suppressed because one or more lines are too long
+15 -1
View File
@@ -25,7 +25,7 @@ except ImportError:
HAS_ORJSON = False
from ..html_tools import TRANSLATE_WHITESPACE_TABLE
from ..processors.restock_diff import Restock
from ..processors.restock_diff import Restock, get_price_from_history_str
from ..blueprint.rss import RSS_CONTENT_FORMAT_DEFAULT
from ..model import USE_SYSTEM_DEFAULT_NOTIFICATION_FORMAT_FOR_WATCH
@@ -825,3 +825,17 @@ class DatastoreUpdatesMixin:
self.data['settings']['application']['llm'] = llm
logger.info("update_32: cleaned up obsolete max_tokens_per_check / renamed max_tokens_cumulative")
def update_39(self):
for uuid, watch in self.data['watching'].items():
if watch.get('processor') != 'restock_diff':
continue
versions = list(watch.history.keys())
if versions and len(versions) >= 2:
snapshot = watch.get_history_snapshot(timestamp=versions[-2])
if snapshot:
prev_price = get_price_from_history_str(history_str=snapshot)
logger.debug(f"UUID {watch['uuid']} setting prev_price to '{prev_price}'")
watch['restock']['prev_price'] = prev_price
watch.commit()
@@ -49,6 +49,84 @@ def set_back_in_stock_response(datastore_path):
f.write(test_return_data)
return None
def set_price_response(datastore_path, price):
# JSON-LD product offer so the price + availability are extracted deterministically
# without needing a real browser (extruct parses the raw HTML).
test_return_data = """<html>
<head>
<script type="application/ld+json">
{"@context": "https://schema.org/", "@type": "Product", "name": "Test Product",
"offers": {"@type": "Offer", "priceCurrency": "USD", "price": "%s",
"availability": "https://schema.org/InStock"}}
</script>
</head>
<body>
<div id="sametext">Available!</div>
</body>
</html>
""" % price
with open(os.path.join(datastore_path, "endpoint-content.txt"), "w") as f:
f.write(test_return_data)
return None
def test_restock_price_change_direction(client, live_server, measure_memory_usage, datastore_path):
"""The watch list shows a green ▼/-% on a price drop and a red ▲/+% on a price rise,
and prev_price only moves when the price actually changes (it persists otherwise)."""
def get_restock(client):
datastore = client.application.config.get('DATASTORE')
uuid = next(iter(datastore.data['watching']))
return datastore.data['watching'][uuid]['restock']
set_price_response(datastore_path=datastore_path, price="100.00")
# JSON-LD restock data is parsed by extruct over the in-process html_requests fetcher,
# so we can hit the live server on localhost directly (no Docker browser container needed).
test_url = url_for('test_endpoint', _external=True)
client.post(
url_for("ui.ui_views.form_quick_watch_add"),
data={"url": test_url, "tags": '', 'processor': 'restock_diff', 'fetch_backend': 'html_requests'},
follow_redirects=True
)
wait_for_all_checks(client)
# First check: there is no previous price yet, so no up/down indicator should render
res = client.get(url_for("watchlist.index"))
assert b'processor-restock_diff' in res.data
assert b'price-change' not in res.data, "No price arrow should show on the very first check"
assert get_restock(client).get('prev_price') is None, "prev_price should be unset on the first check"
# Price drops 100.00 -> 82.00 => -18%, expect a green down arrow
set_price_response(datastore_path=datastore_path, price="82.00")
client.get(url_for("ui.form_watch_checknow"), follow_redirects=True)
wait_for_all_checks(client)
res = client.get(url_for("watchlist.index"))
assert b'price-change down' in res.data, "Price drop should show a down arrow"
assert ''.encode('utf-8') in res.data
assert b'-18%' in res.data, "Price drop percentage should be shown"
assert float(get_restock(client).get('prev_price')) == 100.0, "prev_price should capture the price we moved from"
# Price rises 82.00 -> 90.00 => +9.8%, expect an up arrow
set_price_response(datastore_path=datastore_path, price="90.00")
client.get(url_for("ui.form_watch_checknow"), follow_redirects=True)
wait_for_all_checks(client)
res = client.get(url_for("watchlist.index"))
assert b'price-change up' in res.data, "Price rise should show an up arrow"
assert ''.encode('utf-8') in res.data
assert b'+9.8%' in res.data, "Price rise percentage should be shown"
assert float(get_restock(client).get('prev_price')) == 82.0, "prev_price should update to the new previous price on a change"
# Re-check with NO price change - prev_price must NOT be clobbered, so the arrow persists.
client.get(url_for("ui.form_watch_checknow"), follow_redirects=True)
wait_for_all_checks(client)
res = client.get(url_for("watchlist.index"))
assert b'price-change up' in res.data, "Arrow should persist across an unchanged check"
assert b'+9.8%' in res.data, "Percentage should persist across an unchanged check"
assert float(get_restock(client).get('prev_price')) == 82.0, "prev_price must stay put when the price is unchanged"
# Add a site in paused mode, add an invalid filter, we should still have visual selector data ready
def test_restock_detection(client, live_server, measure_memory_usage, datastore_path):
@@ -23,16 +23,46 @@ msgid "Add a new web page change detection watch"
msgstr "Přidejte nové sledování zjišťování změn webové stránky"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Monitorovat tuto URL!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Přejít"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "Nejdříve upravit, poté sledovat"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "V současné době:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Vyberte podle prvku"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Jasný výběr"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -40,17 +70,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "Sledovat skupinu / Značka"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Monitorovat tuto URL!"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "Nejdříve upravit, poté sledovat"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -765,6 +791,10 @@ msgstr ""
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "Tip"
@@ -2051,26 +2081,14 @@ msgstr "pro výběr více položek."
msgid "Selection Mode:"
msgstr "Režim výběru:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Vyberte podle prvku"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "Kreslit oblast"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Jasný výběr"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "Okamžik, načítání snímku obrazovky a informací o prvku."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "V současné době:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr ""
@@ -2155,10 +2173,6 @@ msgstr "Duplikovat a upravit"
msgid "Select timestamp"
msgstr "Vybrat časové razítko"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Přejít"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "Aktuální chybový snímek obrazovky z posledního požadavku"
@@ -2452,6 +2466,11 @@ msgstr "Není skladem"
msgid "Price"
msgstr "Cena"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "Žádné informace"
@@ -3186,6 +3205,18 @@ msgstr "Povolit favikony"
msgid "Use page <title> in watch overview list"
msgstr "Použijte stránku <title> v přehledu sledování"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Kontrola zabezpečení přístupového tokenu API povolena"
@@ -3346,6 +3377,132 @@ msgstr "RegEx k extrahování"
msgid "Extract as CSV"
msgstr "Extrahujte data"
#: changedetectionio/languages.py
msgid "just now"
msgstr "právě teď"
#: changedetectionio/languages.py
msgid "right now"
msgstr "za chvíli"
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr "před %ss"
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr "za %ss"
#: changedetectionio/languages.py
msgid "1m ago"
msgstr "před 1m"
#: changedetectionio/languages.py
msgid "in 1m"
msgstr "za 1m"
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr "před %sm"
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr "za %sm"
#: changedetectionio/languages.py
msgid "1h ago"
msgstr "před 1h"
#: changedetectionio/languages.py
msgid "in 1h"
msgstr "za 1h"
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr "před %sh"
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr "za %sh"
#: changedetectionio/languages.py
msgid "1d ago"
msgstr "před 1d"
#: changedetectionio/languages.py
msgid "in 1d"
msgstr "za 1d"
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr "před %sd"
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr "za %sd"
#: changedetectionio/languages.py
msgid "1w ago"
msgstr "před 1týd"
#: changedetectionio/languages.py
msgid "in 1w"
msgstr "za 1týd"
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr "před %stýd"
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr "za %stýd"
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr "před 1měs"
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr "za 1měs"
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr "před %směs"
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr "za %směs"
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr "před 1r"
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr "za 1r"
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr "před %sr"
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr "za %sr"
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr ""
@@ -3974,6 +4131,10 @@ msgstr ""
msgid "AI"
msgstr "AI"
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4318,6 +4479,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr "Je dostupná nová verze"
@@ -23,16 +23,46 @@ msgid "Add a new web page change detection watch"
msgstr "Fügen Sie eine neue Überwachung zur Erkennung von Webseitenänderungen hinzu"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Diese URL überwachen!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Gehen"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "Bearbeiten > Überwachen"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "Momentan:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Nach Element auswählen"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Auswahl löschen"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -40,17 +70,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "Gruppe / Label"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Diese URL überwachen!"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "Bearbeiten > Überwachen"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -781,6 +807,10 @@ msgstr ""
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "Tipp"
@@ -2096,26 +2126,14 @@ msgstr "um mehrere Elemente auszuwählen."
msgid "Selection Mode:"
msgstr "Auswahlmodus:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Nach Element auswählen"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "Bereich zeichnen"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Auswahl löschen"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "Einen Moment, Screenshot und Elementinformationen abrufen."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "Momentan:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr ""
@@ -2202,10 +2220,6 @@ msgstr "Klonen und bearbeiten"
msgid "Select timestamp"
msgstr "Zeitstempel auswählen"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Gehen"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "Aktueller fehlerhafter Screenshot aus der letzten Anfrage"
@@ -2503,6 +2517,11 @@ msgstr "Nicht auf Lager"
msgid "Price"
msgstr "Preis"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "Keine Informationen"
@@ -3238,6 +3257,18 @@ msgstr "Favicons Aktiviert"
msgid "Use page <title> in watch overview list"
msgstr "Verwenden Sie die Seite <title> in der Übersichtsliste der Beobachtungen"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Sicherheitsüberprüfung des API-Zugriffstokens aktiviert"
@@ -3398,6 +3429,132 @@ msgstr "RegEx zum Extrahieren"
msgid "Extract as CSV"
msgstr "Als CSV exportieren"
#: changedetectionio/languages.py
msgid "just now"
msgstr "gerade eben"
#: changedetectionio/languages.py
msgid "right now"
msgstr "gleich"
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr "vor %ss"
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr "in %ss"
#: changedetectionio/languages.py
msgid "1m ago"
msgstr "vor 1Min"
#: changedetectionio/languages.py
msgid "in 1m"
msgstr "in 1Min"
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr "vor %sMin"
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr "in %sMin"
#: changedetectionio/languages.py
msgid "1h ago"
msgstr "vor 1Std"
#: changedetectionio/languages.py
msgid "in 1h"
msgstr "in 1Std"
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr "vor %sStd"
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr "in %sStd"
#: changedetectionio/languages.py
msgid "1d ago"
msgstr "vor 1T"
#: changedetectionio/languages.py
msgid "in 1d"
msgstr "in 1T"
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr "vor %sT"
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr "in %sT"
#: changedetectionio/languages.py
msgid "1w ago"
msgstr "vor 1Wo"
#: changedetectionio/languages.py
msgid "in 1w"
msgstr "in 1Wo"
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr "vor %sWo"
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr "in %sWo"
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr "vor 1Mon"
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr "in 1Mon"
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr "vor %sMon"
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr "in %sMon"
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr "vor 1J"
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr "in 1J"
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr "vor %sJ"
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr "in %sJ"
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr ""
@@ -4030,6 +4187,10 @@ msgstr "Suchbegriff eingeben..."
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4374,6 +4535,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -23,16 +23,46 @@ msgid "Add a new web page change detection watch"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -40,16 +70,12 @@ msgstr ""
msgid "Watch group / tag"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgid "Edit first then Watch"
msgstr ""
#: changedetectionio/blueprint/backups/__init__.py
@@ -763,6 +789,10 @@ msgstr ""
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr ""
@@ -2047,26 +2077,14 @@ msgstr ""
msgid "Selection Mode:"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr ""
@@ -2151,10 +2169,6 @@ msgstr ""
msgid "Select timestamp"
msgstr ""
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr ""
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr ""
@@ -2448,6 +2462,11 @@ msgstr ""
msgid "Price"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr ""
@@ -3180,6 +3199,18 @@ msgstr ""
msgid "Use page <title> in watch overview list"
msgstr ""
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr ""
@@ -3340,6 +3371,132 @@ msgstr ""
msgid "Extract as CSV"
msgstr ""
#: changedetectionio/languages.py
msgid "just now"
msgstr ""
#: changedetectionio/languages.py
msgid "right now"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr ""
#: changedetectionio/languages.py
msgid "1m ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1m"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr ""
#: changedetectionio/languages.py
msgid "1h ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1h"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr ""
#: changedetectionio/languages.py
msgid "1d ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1d"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr ""
#: changedetectionio/languages.py
msgid "1w ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1w"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr ""
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr ""
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr ""
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr ""
@@ -3968,6 +4125,10 @@ msgstr ""
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4312,6 +4473,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -23,16 +23,46 @@ msgid "Add a new web page change detection watch"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -40,16 +70,12 @@ msgstr ""
msgid "Watch group / tag"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgid "Edit first then Watch"
msgstr ""
#: changedetectionio/blueprint/backups/__init__.py
@@ -763,6 +789,10 @@ msgstr ""
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr ""
@@ -2047,26 +2077,14 @@ msgstr ""
msgid "Selection Mode:"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr ""
@@ -2151,10 +2169,6 @@ msgstr ""
msgid "Select timestamp"
msgstr ""
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr ""
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr ""
@@ -2448,6 +2462,11 @@ msgstr ""
msgid "Price"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr ""
@@ -3180,6 +3199,18 @@ msgstr ""
msgid "Use page <title> in watch overview list"
msgstr ""
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr ""
@@ -3340,6 +3371,132 @@ msgstr ""
msgid "Extract as CSV"
msgstr ""
#: changedetectionio/languages.py
msgid "just now"
msgstr ""
#: changedetectionio/languages.py
msgid "right now"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr ""
#: changedetectionio/languages.py
msgid "1m ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1m"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr ""
#: changedetectionio/languages.py
msgid "1h ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1h"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr ""
#: changedetectionio/languages.py
msgid "1d ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1d"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr ""
#: changedetectionio/languages.py
msgid "1w ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1w"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr ""
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr ""
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr ""
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr ""
@@ -3968,6 +4125,10 @@ msgstr ""
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4312,6 +4473,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -19,16 +19,46 @@ msgid "Add a new web page change detection watch"
msgstr "Agregar un nuevo monitor de detección de cambios en páginas web"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "¡Monitoriza esta URL!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Ir"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "Editar primero y luego monitorizar"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "Actualmente:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Seleccionar por elemento"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Borrar selección"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -36,17 +66,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "Ver grupo/etiqueta"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "¡Monitoriza esta URL!"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "Editar primero y luego monitorizar"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -799,6 +825,10 @@ msgstr "Habilitar o deshabilitar favicons junto a la lista de monitores"
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr "Número de elementos por página en la lista general de monitores, 0 para desactivar."
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "Consejo"
@@ -2110,26 +2140,14 @@ msgstr "para seleccionar varios elementos."
msgid "Selection Mode:"
msgstr "Modo de selección:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Seleccionar por elemento"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "Área de dibujo"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Borrar selección"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "Un momento, obteniendo captura de pantalla e información del elemento."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "Actualmente:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr ""
@@ -2216,10 +2234,6 @@ msgstr "Clonar y editar"
msgid "Select timestamp"
msgstr "Seleccionar marca de tiempo"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Ir"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "Captura de pantalla con error actual de la solicitud más reciente"
@@ -2519,6 +2533,11 @@ msgstr "No en stock"
msgid "Price"
msgstr "Precio"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "Sin información"
@@ -3253,6 +3272,18 @@ msgstr "Favicones habilitados"
msgid "Use page <title> in watch overview list"
msgstr "Usar <title> de la página en la lista general de monitores"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Comprobación de seguridad del token de acceso API habilitada"
@@ -3413,6 +3444,132 @@ msgstr "RegEx para extraer"
msgid "Extract as CSV"
msgstr "Extraer como CSV"
#: changedetectionio/languages.py
msgid "just now"
msgstr ""
#: changedetectionio/languages.py
msgid "right now"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr ""
#: changedetectionio/languages.py
msgid "1m ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1m"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr ""
#: changedetectionio/languages.py
msgid "1h ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1h"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr ""
#: changedetectionio/languages.py
msgid "1d ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1d"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr ""
#: changedetectionio/languages.py
msgid "1w ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1w"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr ""
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr ""
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr ""
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr "No se encontraron coincidencias al escanear todo el historial de visualización para esa expresión regular."
@@ -4045,6 +4202,10 @@ msgstr "Introduzca el término de búsqueda..."
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4398,6 +4559,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -23,16 +23,46 @@ msgid "Add a new web page change detection watch"
msgstr "Ajouter une nouvelle surveillance de détection de changement de page Web"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Surveillez cette URL !"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Aller"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "Modifier > Surveiller"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "Actuellement:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Sélectionner par élément"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Effacer la sélection"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -40,17 +70,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "Groupe / Étiquette"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Surveillez cette URL !"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "Modifier > Surveiller"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -769,6 +795,10 @@ msgstr ""
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "Astuce"
@@ -2058,26 +2088,14 @@ msgstr "pour sélectionner plusieurs éléments."
msgid "Selection Mode:"
msgstr "Mode de sélection :"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Sélectionner par élément"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "Zone de dessin"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Effacer la sélection"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "Un instant, récupération de la capture d'écran et des informations sur les éléments."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "Actuellement:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr ""
@@ -2162,10 +2180,6 @@ msgstr "Cloner et modifier"
msgid "Select timestamp"
msgstr "Sélectionnez l'horodatage"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Aller"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "Capture d'écran erronée actuelle de la demande la plus récente"
@@ -2459,6 +2473,11 @@ msgstr "Pas en stock"
msgid "Price"
msgstr "Prix"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "Aucune information"
@@ -3193,6 +3212,18 @@ msgstr "Favicons Activés"
msgid "Use page <title> in watch overview list"
msgstr "Utiliser la page <title> dans la liste de présentation des moniteurs"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
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é"
@@ -3353,6 +3384,132 @@ msgstr "RegEx à extraire"
msgid "Extract as CSV"
msgstr "Extraire des données"
#: changedetectionio/languages.py
msgid "just now"
msgstr "à l'instant"
#: changedetectionio/languages.py
msgid "right now"
msgstr "bientôt"
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr "il y a %ss"
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr "dans %ss"
#: changedetectionio/languages.py
msgid "1m ago"
msgstr "il y a 1min"
#: changedetectionio/languages.py
msgid "in 1m"
msgstr "dans 1min"
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr "il y a %smin"
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr "dans %smin"
#: changedetectionio/languages.py
msgid "1h ago"
msgstr "il y a 1h"
#: changedetectionio/languages.py
msgid "in 1h"
msgstr "dans 1h"
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr "il y a %sh"
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr "dans %sh"
#: changedetectionio/languages.py
msgid "1d ago"
msgstr "il y a 1j"
#: changedetectionio/languages.py
msgid "in 1d"
msgstr "dans 1j"
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr "il y a %sj"
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr "dans %sj"
#: changedetectionio/languages.py
msgid "1w ago"
msgstr "il y a 1sem"
#: changedetectionio/languages.py
msgid "in 1w"
msgstr "dans 1sem"
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr "il y a %ssem"
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr "dans %ssem"
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr "il y a 1mois"
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr "dans 1mois"
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr "il y a %smois"
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr "dans %smois"
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr "il y a 1an"
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr "dans 1an"
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr "il y a %sans"
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr "dans %sans"
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr ""
@@ -3983,6 +4140,10 @@ msgstr ""
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4327,6 +4488,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -23,16 +23,46 @@ msgid "Add a new web page change detection watch"
msgstr "Aggiungi un nuovo monitoraggio modifiche pagina web"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Monitora questo URL!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Vai"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "Modifica > Monitora"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -40,17 +70,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "Gruppo / Etichetta"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Monitora questo URL!"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "Modifica > Monitora"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -765,6 +791,10 @@ msgstr ""
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr ""
@@ -2049,26 +2079,14 @@ msgstr ""
msgid "Selection Mode:"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr ""
@@ -2153,10 +2171,6 @@ msgstr "Clona e Modifica"
msgid "Select timestamp"
msgstr ""
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Vai"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr ""
@@ -2450,6 +2464,11 @@ msgstr "Non disponibile"
msgid "Price"
msgstr "Prezzo"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "Nessuna informazione"
@@ -3182,6 +3201,18 @@ msgstr "Favicon attive"
msgid "Use page <title> in watch overview list"
msgstr "Usa <title> pagina nell'elenco osservati"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Controllo sicurezza token API attivo"
@@ -3342,6 +3373,132 @@ msgstr "RegEx da estrarre"
msgid "Extract as CSV"
msgstr "Estrai come CSV"
#: changedetectionio/languages.py
msgid "just now"
msgstr "proprio ora"
#: changedetectionio/languages.py
msgid "right now"
msgstr "tra poco"
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr "%ss fa"
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr "tra %ss"
#: changedetectionio/languages.py
msgid "1m ago"
msgstr "1min fa"
#: changedetectionio/languages.py
msgid "in 1m"
msgstr "tra 1min"
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr "%smin fa"
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr "tra %smin"
#: changedetectionio/languages.py
msgid "1h ago"
msgstr "1h fa"
#: changedetectionio/languages.py
msgid "in 1h"
msgstr "tra 1h"
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr "%sh fa"
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr "tra %sh"
#: changedetectionio/languages.py
msgid "1d ago"
msgstr "1g fa"
#: changedetectionio/languages.py
msgid "in 1d"
msgstr "tra 1g"
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr "%sg fa"
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr "tra %sg"
#: changedetectionio/languages.py
msgid "1w ago"
msgstr "1sett fa"
#: changedetectionio/languages.py
msgid "in 1w"
msgstr "tra 1sett"
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr "%ssett fa"
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr "tra %ssett"
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr "1mese fa"
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr "tra 1mese"
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr "%smesi fa"
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr "tra %smesi"
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr "1anno fa"
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr "tra 1anno"
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr "%sanni fa"
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr "tra %sanni"
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr ""
@@ -3970,6 +4127,10 @@ msgstr ""
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4314,6 +4475,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -24,16 +24,46 @@ msgid "Add a new web page change detection watch"
msgstr "新しいウェブページ変更検知ウォッチを追加"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "このURLをウォッチする!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "移動"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "編集してからウォッチ"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "現在:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "要素で選択"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "選択をクリア"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -41,17 +71,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "ウォッチグループ / タグ"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "このURLをウォッチする!"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "編集してからウォッチ"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -770,6 +796,10 @@ msgstr "ウォッチリスト横のファビコンを有効または無効にす
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr "ウォッチ一覧ページの1ページあたりの表示件数(0で無効化)。"
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "ヒント"
@@ -2066,26 +2096,14 @@ msgstr "を使用します。"
msgid "Selection Mode:"
msgstr "選択モード:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "要素で選択"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "エリアを描画"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "選択をクリア"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "少々お待ちください。スクリーンショットと要素情報を取得しています..."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "現在:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr "申し訳ありませんが、この機能はJavascriptとスクリーンショットをサポートするフェッチャー(playwrightなど)でのみ動作します。"
@@ -2170,10 +2188,6 @@ msgstr "複製して編集"
msgid "Select timestamp"
msgstr "タイムスタンプを選択"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "移動"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "最新のリクエストからの現在のエラースクリーンショット"
@@ -2467,6 +2481,11 @@ msgstr "在庫なし"
msgid "Price"
msgstr "価格"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "情報なし"
@@ -3199,6 +3218,18 @@ msgstr "ファビコンを有効化"
msgid "Use page <title> in watch overview list"
msgstr "ウォッチ一覧リストでページの <title> を使用"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "APIアクセストークンのセキュリティチェックを有効化"
@@ -3359,6 +3390,132 @@ msgstr "抽出する正規表現"
msgid "Extract as CSV"
msgstr "CSVとして抽出"
#: changedetectionio/languages.py
msgid "just now"
msgstr ""
#: changedetectionio/languages.py
msgid "right now"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr ""
#: changedetectionio/languages.py
msgid "1m ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1m"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr ""
#: changedetectionio/languages.py
msgid "1h ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1h"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr ""
#: changedetectionio/languages.py
msgid "1d ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1d"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr ""
#: changedetectionio/languages.py
msgid "1w ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1w"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr ""
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr ""
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr ""
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr "その正規表現についてウォッチ履歴全体をスキャンしましたが、一致するものが見つかりませんでした。"
@@ -4001,6 +4158,10 @@ msgstr "検索語を入力..."
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4355,6 +4516,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr "新しいバージョンが利用可能です"
@@ -23,34 +23,60 @@ msgid "Add a new web page change detection watch"
msgstr "새 웹페이지 변경 감지 모니터링 추가"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "이 URL 모니터링 추가"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "이동"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "편집 후 모니터링 추가"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr "AI - 다음 경우 알림"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "현재:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "요소별로 선택"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "선택 취소"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/blueprint/tags/templates/groups-overview.html
msgid "Watch group / tag"
msgstr "모니터링 그룹 / 태그"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "이 URL 모니터링 추가"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "편집 후 모니터링 추가"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -765,6 +791,10 @@ msgstr "모니터링 목록 옆 파비콘 표시 여부"
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr "모니터링 목록 페이지당 항목 수입니다. 0이면 비활성화됩니다."
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "팁"
@@ -2057,26 +2087,14 @@ msgstr "사용하세요."
msgid "Selection Mode:"
msgstr "선택 모드:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "요소별로 선택"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "그리기 영역"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "선택 취소"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "잠시만 기다려 주세요. 스크린샷과 요소 정보를 가져오는 중입니다."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "현재:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr "죄송합니다. 이 기능은 JavaScript와 스크린샷을 지원하는 가져오기 방식(예: Playwright 등)에서만 작동합니다."
@@ -2161,10 +2179,6 @@ msgstr "복제 및 편집"
msgid "Select timestamp"
msgstr "타임스탬프 선택"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "이동"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "가장 최근 요청의 현재 오류 스크린샷"
@@ -2458,6 +2472,11 @@ msgstr "재고 없음"
msgid "Price"
msgstr "가격"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "정보 없음"
@@ -3190,6 +3209,18 @@ msgstr "파비콘 활성화"
msgid "Use page <title> in watch overview list"
msgstr "모니터링 목록에 페이지 <title> 사용"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "API 액세스 토큰 보안 확인 활성화"
@@ -3350,6 +3381,132 @@ msgstr "추출할 정규식"
msgid "Extract as CSV"
msgstr "CSV로 추출"
#: changedetectionio/languages.py
msgid "just now"
msgstr "방금"
#: changedetectionio/languages.py
msgid "right now"
msgstr "곧"
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr "%s초 전"
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr "%s초 후"
#: changedetectionio/languages.py
msgid "1m ago"
msgstr "1분 전"
#: changedetectionio/languages.py
msgid "in 1m"
msgstr "1분 후"
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr "%s분 전"
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr "%s분 후"
#: changedetectionio/languages.py
msgid "1h ago"
msgstr "1시간 전"
#: changedetectionio/languages.py
msgid "in 1h"
msgstr "1시간 후"
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr "%s시간 전"
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr "%s시간 후"
#: changedetectionio/languages.py
msgid "1d ago"
msgstr "1일 전"
#: changedetectionio/languages.py
msgid "in 1d"
msgstr "1일 후"
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr "%s일 전"
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr "%s일 후"
#: changedetectionio/languages.py
msgid "1w ago"
msgstr "1주 전"
#: changedetectionio/languages.py
msgid "in 1w"
msgstr "1주 후"
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr "%s주 전"
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr "%s주 후"
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr "1개월 전"
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr "1개월 후"
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr "%s개월 전"
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr "%s개월 후"
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr "1년 전"
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr "1년 후"
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr "%s년 전"
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr "%s년 후"
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr "해당 정규식으로 모든 모니터링 기록을 검사했지만 일치하는 항목을 찾지 못했습니다."
@@ -3978,6 +4135,10 @@ msgstr "검색어를 입력하세요..."
msgid "AI"
msgstr "AI"
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr "AI - 다음 경우 알림"
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4332,6 +4493,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr "새 버전이 있습니다"
+193 -28
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: changedetection.io 0.55.7\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2026-06-03 13:26+0200\n"
"POT-Creation-Date: 2026-06-14 13:29+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"
@@ -22,16 +22,46 @@ msgid "Add a new web page change detection watch"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -39,16 +69,12 @@ msgstr ""
msgid "Watch group / tag"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgid "Edit first then Watch"
msgstr ""
#: changedetectionio/blueprint/backups/__init__.py
@@ -762,6 +788,10 @@ msgstr ""
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr ""
@@ -2046,26 +2076,14 @@ msgstr ""
msgid "Selection Mode:"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr ""
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr ""
@@ -2150,10 +2168,6 @@ msgstr ""
msgid "Select timestamp"
msgstr ""
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr ""
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr ""
@@ -2447,6 +2461,11 @@ msgstr ""
msgid "Price"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr ""
@@ -3179,6 +3198,18 @@ msgstr ""
msgid "Use page <title> in watch overview list"
msgstr ""
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr ""
@@ -3339,6 +3370,132 @@ msgstr ""
msgid "Extract as CSV"
msgstr ""
#: changedetectionio/languages.py
msgid "just now"
msgstr ""
#: changedetectionio/languages.py
msgid "right now"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr ""
#: changedetectionio/languages.py
msgid "1m ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1m"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr ""
#: changedetectionio/languages.py
msgid "1h ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1h"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr ""
#: changedetectionio/languages.py
msgid "1d ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1d"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr ""
#: changedetectionio/languages.py
msgid "1w ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1w"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr ""
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr ""
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr ""
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr ""
@@ -3967,6 +4124,10 @@ msgstr ""
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4311,6 +4472,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -24,16 +24,46 @@ msgid "Add a new web page change detection watch"
msgstr "Adicionar um novo monitoramento de detecção de mudança de página"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Monitorar esta URL!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Ir"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "Editar primeiro, depois Monitorar"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "Atualmente:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Selecionar por elemento"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Limpar seleção"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -41,17 +71,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "Grupo / Tag de monitoramento"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Monitorar esta URL!"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "Editar primeiro, depois Monitorar"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -786,6 +812,10 @@ msgstr "Ativar ou Desativar Favicons ao lado da lista de monitoramento"
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr "Número de itens por página na lista de visão geral, 0 para desativar."
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "Dica"
@@ -2095,26 +2125,14 @@ msgstr "para selecionar múltiplos itens."
msgid "Selection Mode:"
msgstr "Modo de Seleção:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Selecionar por elemento"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "Desenhar área"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Limpar seleção"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "Um momento, buscando screenshot e informações dos elementos..."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "Atualmente:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr "Desculpe, esta funcionalidade só funciona com fetchers que suportam Javascript e screenshots (como playwright, etc)."
@@ -2199,10 +2217,6 @@ msgstr "Clonar e Editar"
msgid "Select timestamp"
msgstr "Selecionar data/hora"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Ir"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "Screenshot de erro atual da solicitação mais recente"
@@ -2498,6 +2512,11 @@ msgstr "Sem estoque"
msgid "Price"
msgstr "Preço"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "Sem informações"
@@ -3230,6 +3249,18 @@ msgstr "Favicons Ativados"
msgid "Use page <title> in watch overview list"
msgstr "Usar <title> da página na lista de visão geral"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Verificação de segurança do token de acesso à API ativada"
@@ -3390,6 +3421,132 @@ msgstr "RegEx para extrair"
msgid "Extract as CSV"
msgstr "Extrair como CSV"
#: changedetectionio/languages.py
msgid "just now"
msgstr ""
#: changedetectionio/languages.py
msgid "right now"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr ""
#: changedetectionio/languages.py
msgid "1m ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1m"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr ""
#: changedetectionio/languages.py
msgid "1h ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1h"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr ""
#: changedetectionio/languages.py
msgid "1d ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1d"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr ""
#: changedetectionio/languages.py
msgid "1w ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1w"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr ""
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr ""
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr ""
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr "Nenhuma correspondência encontrada ao escanear todo o histórico de monitoramento para esse RegEx."
@@ -4020,6 +4177,10 @@ msgstr "Digite o termo de busca..."
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4370,6 +4531,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -24,16 +24,46 @@ msgid "Add a new web page change detection watch"
msgstr "Yeni bir web sayfası değişiklik tespiti izleyicisi ekle"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Bu URL'yi izle!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Git"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "Önce Düzenle sonra İzle"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "Şu anda:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Öğeye göre seç"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Seçimi temizle"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -41,17 +71,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "İzleyici grubu / etiketi"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Bu URL'yi izle!"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "Önce Düzenle sonra İzle"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -796,6 +822,10 @@ msgstr "İzleme listesinin yanındaki Favicon'ları Etkinleştir veya Devre Dı
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr "İzleyici genel bakış listesinde sayfa başına öğe sayısı, devre dışı bırakmak için 0."
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "İpucu"
@@ -2098,26 +2128,14 @@ msgstr "birden çok öğe seçmek için."
msgid "Selection Mode:"
msgstr "Seçim Modu:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Öğeye göre seç"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "Çizim alanı"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Seçimi temizle"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "Bir saniye, ekran görüntüsü ve öğe bilgileri getiriliyor.."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "Şu anda:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr ""
@@ -2204,10 +2222,6 @@ msgstr "Klonla ve Düzenle"
msgid "Select timestamp"
msgstr "Zaman damgası seç"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Git"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "En son istekten gelen mevcut hatalı ekran görüntüsü"
@@ -2501,6 +2515,11 @@ msgstr "Stokta yok"
msgid "Price"
msgstr "Fiyat"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "Bilgi yok"
@@ -3233,6 +3252,18 @@ msgstr "Favicon'lar Etkin"
msgid "Use page <title> in watch overview list"
msgstr "İzleyici genel bakış listesinde sayfa <title>'ını kullan"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "API erişim belirteci güvenlik kontrolü etkin"
@@ -3393,6 +3424,132 @@ msgstr "Çıkarılacak RegEx"
msgid "Extract as CSV"
msgstr "CSV olarak çıkar"
#: changedetectionio/languages.py
msgid "just now"
msgstr ""
#: changedetectionio/languages.py
msgid "right now"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr ""
#: changedetectionio/languages.py
msgid "1m ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1m"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr ""
#: changedetectionio/languages.py
msgid "1h ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1h"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr ""
#: changedetectionio/languages.py
msgid "1d ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1d"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr ""
#: changedetectionio/languages.py
msgid "1w ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1w"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr ""
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr ""
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr ""
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr "Tüm izleme geçmişi o RegEx için taranırken hiçbir eşleşme bulunamadı."
@@ -4025,6 +4182,10 @@ msgstr "Arama terimini girin..."
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4373,6 +4534,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -22,16 +22,46 @@ msgid "Add a new web page change detection watch"
msgstr "Додати нове завдання відстеження змін веб-сторінки"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Відстежувати цей URL!"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Перейти"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "Спочатку редагувати, потім Відстежувати"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "В даний час:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Вибір за елементом"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Очистити вибір"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -39,17 +69,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "Група / Тег відстеження"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "Відстежувати цей URL!"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "Спочатку редагувати, потім Відстежувати"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -776,6 +802,10 @@ msgstr "Увімкнути або вимкнути значки (фавікон
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr "Кількість елементів на сторінці у списку завдань, 0 для вимкнення."
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "Порада"
@@ -2079,26 +2109,14 @@ msgstr "для вибору кількох елементів."
msgid "Selection Mode:"
msgstr "Режим вибору:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "Вибір за елементом"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "Малювання області"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "Очистити вибір"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "Хвилинку, отримання скріншота та інформації про елементи..."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "В даний час:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr "Вибачте, ця функція працює лише із завантажувачами, що підтримують Javascript і скріншоти (наприклад, playwright)."
@@ -2183,10 +2201,6 @@ msgstr "Клонувати та Редагувати"
msgid "Select timestamp"
msgstr "Виберіть мітку часу"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "Перейти"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "Поточний скріншот з помилкою з останнього запиту"
@@ -2480,6 +2494,11 @@ msgstr "Немає в наявності"
msgid "Price"
msgstr "Ціна"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "Немає інформації"
@@ -3212,6 +3231,18 @@ msgstr "Фавіконки увімкнено"
msgid "Use page <title> in watch overview list"
msgstr "Використовувати <title> сторінки у списку огляду завдань"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "Перевірку безпеки токена доступу API увімкнено"
@@ -3372,6 +3403,132 @@ msgstr "RegEx для вилучення"
msgid "Extract as CSV"
msgstr "Вилучити як CSV"
#: changedetectionio/languages.py
msgid "just now"
msgstr ""
#: changedetectionio/languages.py
msgid "right now"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr ""
#: changedetectionio/languages.py
msgid "1m ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1m"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr ""
#: changedetectionio/languages.py
msgid "1h ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1h"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr ""
#: changedetectionio/languages.py
msgid "1d ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1d"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr ""
#: changedetectionio/languages.py
msgid "1w ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1w"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr ""
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr ""
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr ""
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr ""
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr ""
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr "Збігів не знайдено під час сканування всієї історії цього завдання за даним RegEx."
@@ -4002,6 +4159,10 @@ msgstr "Введіть пошуковий запит..."
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4350,6 +4511,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -23,16 +23,46 @@ msgid "Add a new web page change detection watch"
msgstr "新增网页变更监控"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "监控此 URL"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "前往"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "先编辑,再监控"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "当前:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "按元素选择"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "清除选择"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -40,17 +70,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "分组 / 标签"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "监控此 URL"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "先编辑,再监控"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -271,7 +297,8 @@ msgstr "未通过验证的 URL 会保留在文本框中。"
msgid "Copy and Paste your Distill.io watch 'export' file, this should be a JSON file."
msgstr "复制并粘贴 Distill.io 监控的“导出”文件(JSON)。"
# TN: CJK scripts degrade when italicized; emphasis is rendered with <strong> instead.
# TN: CJK scripts degrade when italicized; emphasis is rendered with <strong>
# instead.
#. CJK fonts lack native italics; allow substitution with conventional local styling. dennis-ignore: W303
#: changedetectionio/blueprint/imports/templates/import.html
msgid ""
@@ -767,6 +794,10 @@ msgstr "在监控列表中启用或禁用站点图标"
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr "监控概览列表每页数量,0 为禁用。"
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "提示"
@@ -2052,26 +2083,14 @@ msgstr "以选择多个项。"
msgid "Selection Mode:"
msgstr "选择模式:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "按元素选择"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "框选区域"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "清除选择"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "稍等,正在获取截图和元素信息.."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "当前:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr "抱歉,此功能仅适用于支持 JavaScript 和截图的抓取器(如 Playwright 等)。"
@@ -2156,10 +2175,6 @@ msgstr "克隆并编辑"
msgid "Select timestamp"
msgstr "选择时间戳"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "前往"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "最近请求的错误截图"
@@ -2453,6 +2468,11 @@ msgstr "无库存"
msgid "Price"
msgstr "价格"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "暂无信息"
@@ -3185,6 +3205,18 @@ msgstr "启用站点图标"
msgid "Use page <title> in watch overview list"
msgstr "在监控概览列表中使用页面 <title>"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "已启用 API 访问令牌安全检查"
@@ -3345,6 +3377,132 @@ msgstr "用于提取的正则表达式"
msgid "Extract as CSV"
msgstr "提取为 CSV"
#: changedetectionio/languages.py
msgid "just now"
msgstr "刚刚"
#: changedetectionio/languages.py
msgid "right now"
msgstr "一会儿"
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr "%s秒前"
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr "%s秒后"
#: changedetectionio/languages.py
msgid "1m ago"
msgstr "1分前"
#: changedetectionio/languages.py
msgid "in 1m"
msgstr "1分后"
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr "%s分前"
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr "%s分后"
#: changedetectionio/languages.py
msgid "1h ago"
msgstr "1时前"
#: changedetectionio/languages.py
msgid "in 1h"
msgstr "1时后"
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr "%s时前"
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr "%s时后"
#: changedetectionio/languages.py
msgid "1d ago"
msgstr "1天前"
#: changedetectionio/languages.py
msgid "in 1d"
msgstr "1天后"
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr "%s天前"
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr "%s天后"
#: changedetectionio/languages.py
msgid "1w ago"
msgstr "1周前"
#: changedetectionio/languages.py
msgid "in 1w"
msgstr "1周后"
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr "%s周前"
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr "%s周后"
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr "1月前"
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr "1月后"
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr "%s月前"
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr "%s月后"
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr "1年前"
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr "1年后"
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr "%s年前"
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr "%s年后"
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr "扫描全部监控历史未找到匹配该正则的内容。"
@@ -3702,7 +3860,8 @@ msgstr "更多信息"
msgid "Use <a target=\"newwindow\" href=\"%(url)s\">AppRise Notification URLs</a> for notification to just about any service!"
msgstr "使用 <a target=\"newwindow\" href=\"%(url)s\">AppRise通知URL</a>,向几乎任何服务发送通知!"
# TN: CJK scripts degrade when italicized; emphasis is rendered with <strong> instead.
# TN: CJK scripts degrade when italicized; emphasis is rendered with <strong>
# instead.
#. CJK fonts lack native italics; allow substitution with conventional local styling. dennis-ignore: W303
#: changedetectionio/templates/_common_fields.html
msgid "<i>Please read the notification services wiki here for important configuration notes</i>"
@@ -3974,6 +4133,10 @@ msgstr "输入搜索关键词..."
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4318,6 +4481,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""
@@ -23,16 +23,46 @@ msgid "Add a new web page change detection watch"
msgstr "新增網頁變更檢測任務"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "監測此 URL"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "前往"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Edit first then Watch"
msgstr "先編輯後監測"
msgid "Enter a URL to get started!"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgid "Enter a URL in the input box above to get started."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Fetching screenshot and element information…"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "目前:"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "按元素選擇"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Hover & click the preview to watch just one part of the page."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "清除選擇"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "What matters — when to notify me"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid ""
"e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants "
"appear. Skip review additions."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
@@ -40,17 +70,13 @@ msgstr ""
msgid "Watch group / tag"
msgstr "群組 / 標籤"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Watch this URL!"
msgstr "監測此 URL"
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Recent additions and live check status will appear here."
msgstr ""
#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html
msgid "Waiting for activity…"
msgstr ""
msgid "Edit first then Watch"
msgstr "先編輯後監測"
#: changedetectionio/blueprint/backups/__init__.py
msgid "A backup is already running, check back in a few minutes"
@@ -271,7 +297,8 @@ msgstr "未通過驗證的 URL 將保留在文字區塊中。"
msgid "Copy and Paste your Distill.io watch 'export' file, this should be a JSON file."
msgstr "複製並貼上您的 Distill.io 監測任務「匯出」檔案,這應該是一個 JSON 檔案。"
# TN: CJK scripts degrade when italicized; emphasis is rendered with <strong> instead.
# TN: CJK scripts degrade when italicized; emphasis is rendered with <strong>
# instead.
#. CJK fonts lack native italics; allow substitution with conventional local styling. dennis-ignore: W303
#: changedetectionio/blueprint/imports/templates/import.html
msgid ""
@@ -766,6 +793,10 @@ msgstr ""
msgid "Number of items per page in the watch overview list, 0 to disable."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "How \"Last Checked\" and \"Last Changed\" times are shown in the watch overview list."
msgstr ""
#: changedetectionio/blueprint/settings/templates/settings.html
msgid "Tip"
msgstr "提示"
@@ -2003,7 +2034,8 @@ msgid ""
"lines against all history for this watch."
msgstr "適用於內容僅會移動的網站,且您想知道何時新增了「新」內容,此功能會將新行與此監測任務的所有歷史記錄進行比較。"
# TN: CJK scripts degrade when italicized; UI label reference is wrapped in 「」 instead.
# TN: CJK scripts degrade when italicized; UI label reference is wrapped in 「」
# instead.
#. CJK fonts lack native italics; allow substitution with conventional local styling. dennis-ignore: W303
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Helps reduce changes detected caused by sites shuffling lines around, combine with <i>check unique lines</i> below."
@@ -2051,26 +2083,14 @@ msgstr "選擇多個項目。"
msgid "Selection Mode:"
msgstr "選擇模式:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Select by element"
msgstr "按元素選擇"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Draw area"
msgstr "繪製區域"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Clear selection"
msgstr "清除選擇"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "One moment, fetching screenshot and element information.."
msgstr "請稍候,正在抓取截圖和元素資訊.."
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Currently:"
msgstr "目前:"
#: changedetectionio/blueprint/ui/templates/edit.html
msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)."
msgstr "抱歉,此功能僅適用於支援 Javascript 和截圖的抓取器(如 playwright 等)。"
@@ -2155,10 +2175,6 @@ msgstr "複製並編輯"
msgid "Select timestamp"
msgstr "選擇時間戳記"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Go"
msgstr "前往"
#: changedetectionio/blueprint/ui/templates/preview.html
msgid "Current erroring screenshot from most recent request"
msgstr "最近請求的目前錯誤截圖"
@@ -2452,6 +2468,11 @@ msgstr "無庫存"
msgid "Price"
msgstr "價格"
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
#, python-format
msgid "Price change since previous price (%(prev)s)"
msgstr ""
#: changedetectionio/blueprint/watchlist/templates/watch-overview.html
msgid "No information"
msgstr "無資訊"
@@ -3184,6 +3205,18 @@ msgstr "啟用網站圖示 (Favicons)"
msgid "Use page <title> in watch overview list"
msgstr "在監測概覽列表中使用頁面 <title>"
#: changedetectionio/forms.py
msgid "Relative time format"
msgstr ""
#: changedetectionio/forms.py
msgid "Long (1 minute ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "Short (1m ago)"
msgstr ""
#: changedetectionio/forms.py
msgid "API access token security check enabled"
msgstr "已啟用 API 存取權杖安全檢查"
@@ -3344,6 +3377,132 @@ msgstr "要提取的 RegEx"
msgid "Extract as CSV"
msgstr "提取為 CSV"
#: changedetectionio/languages.py
msgid "just now"
msgstr "剛剛"
#: changedetectionio/languages.py
msgid "right now"
msgstr "一會兒"
#: changedetectionio/languages.py
#, python-format
msgid "%ss ago"
msgstr "%s秒前"
#: changedetectionio/languages.py
#, python-format
msgid "in %ss"
msgstr "%s秒後"
#: changedetectionio/languages.py
msgid "1m ago"
msgstr "1分前"
#: changedetectionio/languages.py
msgid "in 1m"
msgstr "1分後"
#: changedetectionio/languages.py
#, python-format
msgid "%sm ago"
msgstr "%s分前"
#: changedetectionio/languages.py
#, python-format
msgid "in %sm"
msgstr "%s分後"
#: changedetectionio/languages.py
msgid "1h ago"
msgstr "1時前"
#: changedetectionio/languages.py
msgid "in 1h"
msgstr "1時後"
#: changedetectionio/languages.py
#, python-format
msgid "%sh ago"
msgstr "%s時前"
#: changedetectionio/languages.py
#, python-format
msgid "in %sh"
msgstr "%s時後"
#: changedetectionio/languages.py
msgid "1d ago"
msgstr "1天前"
#: changedetectionio/languages.py
msgid "in 1d"
msgstr "1天後"
#: changedetectionio/languages.py
#, python-format
msgid "%sd ago"
msgstr "%s天前"
#: changedetectionio/languages.py
#, python-format
msgid "in %sd"
msgstr "%s天後"
#: changedetectionio/languages.py
msgid "1w ago"
msgstr "1週前"
#: changedetectionio/languages.py
msgid "in 1w"
msgstr "1週後"
#: changedetectionio/languages.py
#, python-format
msgid "%sw ago"
msgstr "%s週前"
#: changedetectionio/languages.py
#, python-format
msgid "in %sw"
msgstr "%s週後"
#: changedetectionio/languages.py
msgid "1mo ago"
msgstr "1月前"
#: changedetectionio/languages.py
msgid "in 1mo"
msgstr "1月後"
#: changedetectionio/languages.py
#, python-format
msgid "%smo ago"
msgstr "%s月前"
#: changedetectionio/languages.py
#, python-format
msgid "in %smo"
msgstr "%s月後"
#: changedetectionio/languages.py
msgid "1yr ago"
msgstr "1年前"
#: changedetectionio/languages.py
msgid "in 1yr"
msgstr "1年後"
#: changedetectionio/languages.py
#, python-format
msgid "%syr ago"
msgstr "%s年前"
#: changedetectionio/languages.py
#, python-format
msgid "in %syr"
msgstr "%s年後"
#: changedetectionio/processors/extract.py
msgid "No matches found while scanning all of the watch history for that RegEx."
msgstr "掃描此 RegEx 的所有監測歷史記錄時找不到相符項目。"
@@ -3972,6 +4131,10 @@ msgstr "輸入搜尋關鍵字 ..."
msgid "AI"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid "AI — Notify when…"
msgstr ""
#: changedetectionio/templates/edit/include_llm_intent.html
msgid ""
"Describe what you care about. The AI evaluates every detected change against this and only notifies you when it "
@@ -4316,6 +4479,10 @@ msgstr ""
msgid "In queue"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "Live activity"
msgstr ""
#: changedetectionio/templates/sidebar-nav.html
msgid "A new version is available"
msgstr ""