From 2ab172408de46fe6dfec4b5dae2672c2fe866398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=2E=20Le=C3=B3n?= Date: Sat, 21 Mar 2026 19:53:13 +0100 Subject: [PATCH 01/11] fix: correct critical errors in Spanish (es) translation (#3994) --- .../translations/es/LC_MESSAGES/messages.mo | Bin 72788 -> 76927 bytes .../translations/es/LC_MESSAGES/messages.po | 1151 +++++------------ 2 files changed, 346 insertions(+), 805 deletions(-) diff --git a/changedetectionio/translations/es/LC_MESSAGES/messages.mo b/changedetectionio/translations/es/LC_MESSAGES/messages.mo index 0895ba489a7c587f16c0323d0925b689a5832847..30687b1a761602168fab2aecbda3662ea6f6daa1 100644 GIT binary patch delta 17599 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 delta 13409 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 diff --git a/changedetectionio/translations/es/LC_MESSAGES/messages.po b/changedetectionio/translations/es/LC_MESSAGES/messages.po index c9bbfdfc1..cf2665bfb 100644 --- a/changedetectionio/translations/es/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/es/LC_MESSAGES/messages.po @@ -4,7 +4,7 @@ msgstr "" "Project-Id-Version: changedetection.io 0.53.6\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2026-02-23 03:54+0100\n" -"PO-Revision-Date: 2026-03-08 19:58+0100\n" +"PO-Revision-Date: 2026-03-20 18:13+0100\n" "Last-Translator: Adrian Gonzalez \n" "Language-Team: Español\n" "Language: es\n" @@ -13,12 +13,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "Generated-By: Babel 2.16.0\n" +"X-Generator: Poedit 3.9\n" #: changedetectionio/blueprint/backups/__init__.py msgid "A backup is already running, check back in a few minutes" -msgstr "" -"Ya se está ejecutando una copia de seguridad. Vuelve a comprobarla en unos " -"minutos." +msgstr "Ya se está ejecutando una copia de seguridad. Vuelve a comprobarla en unos minutos" #: changedetectionio/blueprint/backups/__init__.py msgid "Maximum number of backups reached, please remove some" @@ -26,9 +25,7 @@ msgstr "Se alcanzó el número máximo de copias de seguridad; elimine algunas" #: changedetectionio/blueprint/backups/__init__.py msgid "Backup building in background, check back in a few minutes." -msgstr "" -"La copia de seguridad se está creando en segundo plano. Vuelve a comprobarlo" -" en unos minutos." +msgstr "La copia de seguridad se está creando en segundo plano. Vuelve a comprobarlo en unos minutos." #: changedetectionio/blueprint/backups/__init__.py msgid "Backups were deleted." @@ -58,16 +55,13 @@ msgstr "Incluir monitores" msgid "Replace existing watches of the same UUID" msgstr "Reemplazar monitores existentes del mismo UUID" -#: changedetectionio/blueprint/backups/restore.py -#: changedetectionio/blueprint/backups/templates/backup_restore.html +#: changedetectionio/blueprint/backups/restore.py changedetectionio/blueprint/backups/templates/backup_restore.html msgid "Restore backup" msgstr "Restaurar copia de seguridad" #: changedetectionio/blueprint/backups/restore.py msgid "A restore is already running, check back in a few minutes" -msgstr "" -"Ya se está ejecutando una restauración, vuelve a comprobarlo en unos " -"minutos." +msgstr "Ya se está ejecutando una restauración, vuelve a comprobarlo en unos minutos" #: changedetectionio/blueprint/backups/restore.py msgid "No file uploaded" @@ -83,17 +77,13 @@ msgstr "Archivo zip no válido o dañado" #: changedetectionio/blueprint/backups/restore.py msgid "Restore started in background, check back in a few minutes." -msgstr "" -"La restauración comenzó en segundo plano, vuelve a comprobarlo en unos " -"minutos." +msgstr "La restauración comenzó en segundo plano, vuelve a comprobarlo en unos minutos." -#: changedetectionio/blueprint/backups/templates/backup_create.html -#: changedetectionio/blueprint/backups/templates/backup_restore.html +#: changedetectionio/blueprint/backups/templates/backup_create.html changedetectionio/blueprint/backups/templates/backup_restore.html msgid "Create" msgstr "Crear" -#: changedetectionio/blueprint/backups/templates/backup_create.html -#: changedetectionio/blueprint/backups/templates/backup_restore.html +#: changedetectionio/blueprint/backups/templates/backup_create.html changedetectionio/blueprint/backups/templates/backup_restore.html msgid "Restore" msgstr "Restaurar" @@ -102,12 +92,8 @@ msgid "A backup is running!" msgstr "¡Se está ejecutando una copia de seguridad!" #: changedetectionio/blueprint/backups/templates/backup_create.html -msgid "" -"Here you can download and request a new backup, when a backup is completed " -"you will see it listed below." -msgstr "" -"Aquí puede descargar y solicitar una nueva copia de seguridad; cuando se " -"complete una copia de seguridad, la verá en la lista a continuación." +msgid "Here you can download and request a new backup, when a backup is completed you will see it listed below." +msgstr "Aquí puede descargar y solicitar una nueva copia de seguridad; cuando se complete una copia de seguridad, la verá en la lista a continuación." #: changedetectionio/blueprint/backups/templates/backup_create.html msgid "Mb" @@ -130,20 +116,14 @@ msgid "A restore is running!" msgstr "¡Se está ejecutando una restauración!" #: changedetectionio/blueprint/backups/templates/backup_restore.html -msgid "" -"Restore a backup. Must be a .zip backup file created on/after v0.53.1 (new " -"database layout)." +msgid "Restore a backup. Must be a .zip backup file created on/after v0.53.1 (new database layout)." msgstr "" -"Restaurar una copia de seguridad. Debe ser un archivo de copia de seguridad " -".zip creado a partir de la versión 0.53.1 (nuevo diseño de base de datos)." +"Restaurar una copia de seguridad. Debe ser un archivo de copia de seguridad .zip creado a partir de la versión 0.53.1 (nuevo diseño de base de " +"datos)." #: changedetectionio/blueprint/backups/templates/backup_restore.html -msgid "" -"Note: This does not override the main application settings, only watches and" -" groups." -msgstr "" -"Nota: Esto no sobrescribe la configuración principal de la aplicación, solo " -"monitores y grupos." +msgid "Note: This does not override the main application settings, only watches and groups." +msgstr "Nota: Esto no sobrescribe la configuración principal de la aplicación, solo monitores y grupos." #: changedetectionio/blueprint/backups/templates/backup_restore.html msgid "Include all groups found in backup?" @@ -162,12 +142,8 @@ msgid "Replace any existing watches of the same UUID?" msgstr "¿Reemplazar cualquier monitor existente con el mismo UUID?" #: changedetectionio/blueprint/imports/importer.py -msgid "" -"Importing 5,000 of the first URLs from your list, the rest can be imported " -"again." -msgstr "" -"Importando 5.000 de las primeras URL de tu lista, el resto se puede importar" -" nuevamente." +msgid "Importing 5,000 of the first URLs from your list, the rest can be imported again." +msgstr "Importando 5.000 de las primeras URL de tu lista, el resto se puede importar nuevamente." #: changedetectionio/blueprint/imports/importer.py msgid "{} Imported from list in {:.2f}s, {} Skipped." @@ -187,24 +163,15 @@ msgstr "{} importado de Distill.io en {:.2f}s, {} omitido." #: changedetectionio/blueprint/imports/importer.py msgid "Unable to read export XLSX file, something wrong with the file?" -msgstr "" -"No se puede leer el archivo XLSX exportado, ¿hay algún problema con el " -"archivo?" +msgstr "No se puede leer el archivo XLSX exportado, ¿hay algún problema con el archivo?" #: changedetectionio/blueprint/imports/importer.py -msgid "" -"Error processing row number {}, URL value was incorrect, row was skipped." -msgstr "" -"Error al procesar la fila número {}, el valor de la URL era incorrecto y se " -"omitió la fila." +msgid "Error processing row number {}, URL value was incorrect, row was skipped." +msgstr "Error al procesar la fila número {}, el valor de la URL era incorrecto y se omitió la fila." #: changedetectionio/blueprint/imports/importer.py -msgid "" -"Error processing row number {}, check all cell data types are correct, row " -"was skipped." -msgstr "" -"Error al procesar la fila número {}, compruebe que todos los tipos de datos " -"de celda sean correctos; se omitió la fila." +msgid "Error processing row number {}, check all cell data types are correct, row was skipped." +msgstr "Error al procesar la fila número {}, compruebe que todos los tipos de datos de celda sean correctos; se omitió la fila." #: changedetectionio/blueprint/imports/importer.py msgid "{} imported from Wachete .xlsx in {:.2f}s" @@ -228,20 +195,15 @@ msgstr ".XLSX y Wachete" #: changedetectionio/blueprint/imports/templates/import.html msgid "Restoring changedetection.io backups is in the" -msgstr "" -"Restaurar las copias de seguridad de changetection.io se encuentra en el" +msgstr "Restaurar las copias de seguridad de changetection.io se encuentra en el" #: changedetectionio/blueprint/imports/templates/import.html msgid "backups section" msgstr "sección de copias de seguridad" #: changedetectionio/blueprint/imports/templates/import.html -msgid "" -"Enter one URL per line, and optionally add tags for each URL after a space, " -"delineated by comma (,):" -msgstr "" -"Ingrese una URL por línea y, opcionalmente, agregue etiquetas para cada URL " -"después de un espacio, delimitado por una coma (,):" +msgid "Enter one URL per line, and optionally add tags for each URL after a space, delineated by comma (,):" +msgstr "Ingrese una URL por línea y, opcionalmente, agregue etiquetas para cada URL después de un espacio, delimitado por una coma (,):" #: changedetectionio/blueprint/imports/templates/import.html msgid "Example:" @@ -252,12 +214,8 @@ msgid "URLs which do not pass validation will stay in the textarea." msgstr "Las URL que no pasen la validación permanecerán en el área de texto." #: changedetectionio/blueprint/imports/templates/import.html -msgid "" -"Copy and Paste your Distill.io watch 'export' file, this should be a JSON " -"file." -msgstr "" -"Copie y pegue el archivo de 'exportación' del monitor Distill.io, este " -"debería ser un archivo JSON." +msgid "Copy and Paste your Distill.io watch 'export' file, this should be a JSON file." +msgstr "Copie y pegue el archivo de 'exportación' del monitor Distill.io, este debería ser un archivo JSON." #: changedetectionio/blueprint/imports/templates/import.html msgid "This is" @@ -269,7 +227,7 @@ msgstr "experimental" #: changedetectionio/blueprint/imports/templates/import.html msgid "supported fields are" -msgstr "Los campos admitidos son" +msgstr "los campos admitidos son" #: changedetectionio/blueprint/imports/templates/import.html msgid "the rest (including" @@ -285,14 +243,11 @@ msgstr "¿Cómo exportar?" #: changedetectionio/blueprint/imports/templates/import.html msgid "Be sure to set your default fetcher to Chrome if required." -msgstr "" -"Asegúrese de configurar su buscador predeterminado en Chrome si es " -"necesario." +msgstr "Asegúrese de configurar su buscador predeterminado en Chrome si es necesario." #: changedetectionio/blueprint/imports/templates/import.html msgid "Table of custom column and data types mapping for the" -msgstr "" -"Tabla de asignación de tipos de datos y columnas personalizadas para el" +msgstr "Tabla de asignación de tipos de datos y columnas personalizadas para el" #: changedetectionio/blueprint/imports/templates/import.html msgid "Custom mapping" @@ -337,23 +292,16 @@ msgstr "Ver con UUID%(uuid)sextraviado" #: changedetectionio/blueprint/rss/single_watch.py #, python-format -msgid "" -"Watch %(uuid)s does not have enough history snapshots to show changes (need " -"at least 2)" -msgstr "" -"Mirar%(uuid)sno tiene suficientes instantáneas del historial para mostrar " -"los cambios (se necesitan al menos 2)" +msgid "Watch %(uuid)s does not have enough history snapshots to show changes (need at least 2)" +msgstr "Mirar%(uuid)sno tiene suficientes instantáneas del historial para mostrar los cambios (se necesitan al menos 2)" #: changedetectionio/blueprint/settings/__init__.py msgid "Password protection removed." msgstr "Se eliminó la protección con contraseña." #: changedetectionio/blueprint/settings/__init__.py -msgid "" -"Warning: Worker count ({}) is close to or exceeds available CPU cores ({})" -msgstr "" -"Advertencia: recuento de trabajadores ({} ) está cerca o excede los núcleos " -"de CPU disponibles ({} )" +msgid "Warning: Worker count ({}) is close to or exceeds available CPU cores ({})" +msgstr "Advertencia: recuento de trabajadores ({} ) está cerca o excede los núcleos de CPU disponibles ({} )" #: changedetectionio/blueprint/settings/__init__.py msgid "Worker count adjusted: {}" @@ -361,9 +309,7 @@ msgstr "Conteo de trabajadores ajustado:{}" #: changedetectionio/blueprint/settings/__init__.py msgid "Dynamic worker adjustment not supported for sync workers" -msgstr "" -"El ajuste dinámico de trabajadores no es compatible con trabajadores " -"sincronizados" +msgstr "El ajuste dinámico de trabajadores no es compatible con trabajadores sincronizados" #: changedetectionio/blueprint/settings/__init__.py msgid "Error adjusting workers: {}" @@ -377,9 +323,7 @@ msgstr "Protección con contraseña habilitada." msgid "Settings updated." msgstr "Configuración actualizada." -#: changedetectionio/blueprint/settings/__init__.py -#: changedetectionio/blueprint/ui/edit.py -#: changedetectionio/processors/extract.py +#: changedetectionio/blueprint/settings/__init__.py changedetectionio/blueprint/ui/edit.py changedetectionio/processors/extract.py msgid "An error occurred, please see below." msgstr "Se produjo un error, consulte a continuación." @@ -407,15 +351,14 @@ msgstr "Todas las notificaciones activadas." msgid "Notification debug log" msgstr "Registro de depuración de notificaciones" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/tags/templates/edit-tag.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/tags/templates/edit-tag.html #: changedetectionio/blueprint/ui/templates/edit.html msgid "General" msgstr "General" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Fetching" -msgstr "Atractivo" +msgstr "Obteniendo" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Global Filters" @@ -451,21 +394,15 @@ msgstr "Información" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Default recheck time for all watches, current system minimum is" -msgstr "" -"Tiempo de revisión predeterminado para todos los monitores, el mínimo actual" -" del sistema es" +msgstr "Tiempo de revisión predeterminado para todos los monitores, el mínimo actual del sistema es" #: changedetectionio/blueprint/settings/templates/settings.html msgid "more info" msgstr "más información" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"After this many consecutive times that the CSS/xPath filter is missing, send" -" a notification" -msgstr "" -"Después de tantas veces consecutivas que falta el filtro CSS/xPath, envíe " -"una notificación" +msgid "After this many consecutive times that the CSS/xPath filter is missing, send a notification" +msgstr "Después de tantas veces consecutivas que falta el filtro CSS/xPath, envíe una notificación" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Set to" @@ -475,14 +412,9 @@ msgstr "Empezar a" msgid "to disable" msgstr "deshabilitar" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"Limit collection of history snapshots for each watch to this number of " -"history items." -msgstr "" -"Limite la recopilación de instantáneas del historial para cada monitor a " -"esta cantidad de elementos del historial." +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html +msgid "Limit collection of history snapshots for each watch to this number of history items." +msgstr "Limite la recopilación de instantáneas del historial para cada monitor a esta cantidad de elementos del historial." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Set to empty to disable / no limit" @@ -497,21 +429,14 @@ msgid "Password is locked." msgstr "La contraseña está bloqueada." #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Allow access to the watch change history page when password is enabled (Good" -" for sharing the diff page)" +msgid "Allow access to the watch change history page when password is enabled (Good for sharing the diff page)" msgstr "" -"Permitir el acceso a la página del historial de cambios del monitor cuando " -"la contraseña está habilitada (bueno para compartir la página de " +"Permitir el acceso a la página del historial de cambios del monitor cuando la contraseña está habilitada (bueno para compartir la página de " "diferencias)" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"When a request returns no content, or the HTML does not contain any text, is" -" this considered a change?" -msgstr "" -"Cuando una solicitud no devuelve contenido o el HTML no contiene ningún " -"texto, ¿se considera esto un cambio?" +msgid "When a request returns no content, or the HTML does not contain any text, is this considered a change?" +msgstr "Cuando una solicitud no devuelve contenido o el HTML no contiene ningún texto, ¿se considera esto un cambio?" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Choose a default proxy for all watches" @@ -527,74 +452,52 @@ msgstr "token en enlaces de notificación." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Default value is the system environment variable" -msgstr "El valor predeterminado es la variable de entorno del sistema." +msgstr "El valor predeterminado es la variable de entorno del sistema" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/templates/_common_fields.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/templates/_common_fields.html msgid "read more here" msgstr "leer más aquí" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"method (default) where your watched sites don't need Javascript to render." -msgstr "" -"método (predeterminado) donde los sitios observados no necesitan Javascript " -"para renderizarse." +msgid "method (default) where your watched sites don't need Javascript to render." +msgstr "método (predeterminado) donde los sitios observados no necesitan Javascript para renderizarse." -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "Use the" msgstr "Utilice el" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "Basic" msgstr "Básico" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"method requires a network connection to a running WebDriver+Chrome server, " -"set by the ENV var" -msgstr "" -"El método requiere una conexión de red a un servidor WebDriver+Chrome en " -"ejecución, establecido por la var ENV" +msgid "method requires a network connection to a running WebDriver+Chrome server, set by the ENV var" +msgstr "este método requiere una conexión de red a un servidor WebDriver+Chrome en ejecución, configurado mediante la variable de entorno ENV" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "The" msgstr "El" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "Chrome/Javascript" msgstr "Cromo/Javascript" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"If you're having trouble waiting for the page to be fully rendered (text " -"missing etc), try increasing the 'wait' time here." +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html +msgid "If you're having trouble waiting for the page to be fully rendered (text missing etc), try increasing the 'wait' time here." msgstr "" -"Si tiene problemas para esperar a que la página se represente por completo " -"(falta texto, etc.), intente aumentar el tiempo de \"espera\" aquí." +"Si tiene problemas para esperar a que la página se represente por completo (falta texto, etc.), intente aumentar el tiempo de \"espera\" aquí." -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "This will wait" msgstr "Esto esperará" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "seconds before extracting the text." msgstr "segundos antes de extraer el texto." #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Number of concurrent workers to process watches. More workers = faster " -"processing but higher memory usage." -msgstr "" -"Número de trabajadores simultáneos para procesar monitores. Más trabajadores" -" = procesamiento más rápido pero mayor uso de memoria." +msgid "Number of concurrent workers to process watches. More workers = faster processing but higher memory usage." +msgstr "Número de trabajadores simultáneos para procesar monitores. Más trabajadores = procesamiento más rápido pero mayor uso de memoria." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Currently running:" @@ -613,109 +516,70 @@ msgid "actively processing" msgstr "procesando activamente" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Example - 3 seconds random jitter could trigger up to 3 seconds earlier or " -"up to 3 seconds later" -msgstr "" -"Ejemplo: una fluctuación aleatoria de 3 segundos podría activarse hasta 3 " -"segundos antes o hasta 3 segundos después" +msgid "Example - 3 seconds random jitter could trigger up to 3 seconds earlier or up to 3 seconds later" +msgstr "Ejemplo: una fluctuación aleatoria de 3 segundos podría activarse hasta 3 segundos antes o hasta 3 segundos después" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"For regular plain requests (not chrome based), maximum number of seconds " -"until timeout, 1-999." -msgstr "" -"Para solicitudes simples regulares (no basadas en Chrome), número máximo de " -"segundos hasta el tiempo de espera, 1-999." +msgid "For regular plain requests (not chrome based), maximum number of seconds until timeout, 1-999." +msgstr "Para solicitudes simples regulares (no basadas en Chrome), número máximo de segundos hasta el tiempo de espera, 1-999." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Applied to all requests." msgstr "Aplicado a todas las solicitudes." #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Note: Simply changing the User-Agent often does not defeat anti-robot " -"technologies, it's important to consider" -msgstr "" -"Nota: El simple hecho de cambiar el User-Agent a menudo no derrota a las " -"tecnologías anti-robots; es importante tenerlo en cuenta." +msgid "Note: Simply changing the User-Agent often does not defeat anti-robot technologies, it's important to consider" +msgstr "Nota: El simple hecho de cambiar el User-Agent a menudo no supera a las tecnologías anti-robots; es importante tenerlo en cuenta" #: changedetectionio/blueprint/settings/templates/settings.html msgid "all of the ways that the browser is detected" msgstr "todas las formas en que se detecta el navegador" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/edit.html -#: changedetectionio/templates/_common_fields.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/diff.html +#: changedetectionio/blueprint/ui/templates/edit.html changedetectionio/templates/_common_fields.html msgid "Tip:" msgstr "Consejo:" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "Connect using Bright Data and Oxylabs Proxies, find out more here." -msgstr "" -"Conéctese utilizando Bright Data y Oxylabs Proxies; obtenga más información " -"aquí." +msgstr "Conéctese utilizando Bright Data y Oxylabs Proxies; obtenga más información aquí." #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Ignore whitespace, tabs and new-lines/line-feeds when considering if a " -"change was detected." -msgstr "" -"Ignore los espacios en blanco, las tabulaciones y las nuevas líneas/avances " -"de línea al considerar si se detectó un cambio." +msgid "Ignore whitespace, tabs and new-lines/line-feeds when considering if a change was detected." +msgstr "Ignore los espacios en blanco, las tabulaciones y las nuevas líneas/avances de línea al considerar si se detectó un cambio." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Note:" msgstr "Nota:" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Changing this will change the status of your existing watches, possibly " -"trigger alerts etc." -msgstr "" -"Cambiar esto cambiará el estado de sus monitores existentes, posiblemente " -"activará alertas, etc." +msgid "Changing this will change the status of your existing watches, possibly trigger alerts etc." +msgstr "Cambiar esto cambiará el estado de sus monitores existentes, posiblemente activará alertas, etc." #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Render anchor tag content, default disabled, when enabled renders links as" +msgid "Render anchor tag content, default disabled, when enabled renders links as" msgstr "" -"Representar el contenido de la etiqueta de anclaje, deshabilitado de forma " -"predeterminada; cuando está habilitado, los enlaces se muestran como" +"Representar el contenido de la etiqueta de anclaje, deshabilitado de forma predeterminada; cuando está habilitado, los enlaces se muestran como" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Changing this could affect the content of your existing watches, possibly " -"trigger alerts etc." -msgstr "" -"Cambiar esto podría afectar el contenido de sus monitores existentes, " -"posiblemente activar alertas, etc." +msgid "Changing this could affect the content of your existing watches, possibly trigger alerts etc." +msgstr "Cambiar esto podría afectar el contenido de sus monitores existentes, posiblemente activar alertas, etc." #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Remove HTML element(s) by CSS and XPath selectors before text conversion." -msgstr "" -"Elimine los elementos HTML mediante los selectores CSS y XPath antes de la " -"conversión de texto." +msgid "Remove HTML element(s) by CSS and XPath selectors before text conversion." +msgstr "Elimine los elementos HTML mediante los selectores CSS y XPath antes de la conversión de texto." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Don't paste HTML here, use only CSS and XPath selectors" msgstr "No pegue HTML aquí, use solo selectores CSS y XPath" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Add multiple elements, CSS or XPath selectors per line to ignore multiple " -"parts of the HTML." -msgstr "" -"Agregue múltiples elementos, selectores CSS o XPath por línea para ignorar " -"múltiples partes del HTML." +msgid "Add multiple elements, CSS or XPath selectors per line to ignore multiple parts of the HTML." +msgstr "Agregue múltiples elementos, selectores CSS o XPath por línea para ignorar múltiples partes del HTML." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Note: This is applied globally in addition to the per-watch rules." -msgstr "" -"Nota: Esto se aplica globalmente además de las reglas por visualización." +msgstr "Nota: Esto se aplica globalmente además de las reglas por visualización." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Matching text will be" @@ -726,41 +590,25 @@ msgid "ignored" msgstr "ignorado" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"in the text snapshot (you can still see it but it wont trigger a change)" -msgstr "" -"en la instantánea de texto (aún puedes verla pero no activará un cambio)" +msgid "in the text snapshot (you can still see it but it wont trigger a change)" +msgstr "en la instantánea de texto (aún puedes verla pero no activará un cambio)" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/templates/edit/text-options.html -msgid "" -"Each line processed separately, any line matching will be ignored (removed " -"before creating the checksum)" -msgstr "" -"Cada línea se procesa por separado, cualquier coincidencia de líneas se " -"ignorará (se eliminará antes de crear la suma de verificación)" +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/templates/edit/text-options.html +msgid "Each line processed separately, any line matching will be ignored (removed before creating the checksum)" +msgstr "Cada línea se procesa por separado, cualquier coincidencia de líneas se ignorará (se eliminará antes de crear la suma de verificación)" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/templates/edit/text-options.html +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/templates/edit/text-options.html msgid "Regular Expression support, wrap the entire line in forward slash" -msgstr "" -"Soporte de expresión regular, ajuste toda la línea con una barra diagonal" +msgstr "Soporte de expresión regular, ajuste toda la línea con una barra diagonal" + +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/templates/edit/text-options.html +msgid "Changing this will affect the comparison checksum which may trigger an alert" +msgstr "Cambiar esto afectará la suma de verificación de comparación, lo que puede generar una alerta" #: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/templates/edit/text-options.html -msgid "" -"Changing this will affect the comparison checksum which may trigger an alert" +msgid "Remove any text that appears in the \"Ignore text\" from the output (otherwise its just ignored for change-detection)" msgstr "" -"Cambiar esto afectará la suma de verificación de comparación, lo que puede " -"generar una alerta." - -#: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Remove any text that appears in the \"Ignore text\" from the output " -"(otherwise its just ignored for change-detection)" -msgstr "" -"Elimine cualquier texto que aparezca en \"Ignorar texto\" de la salida (de " -"lo contrario, simplemente se ignorará para la detección de cambios)" +"Elimine cualquier texto que aparezca en \"Ignorar texto\" de la salida (de lo contrario, simplemente se ignorará para la detección de cambios)" #: changedetectionio/blueprint/settings/templates/settings.html msgid "API Access" @@ -788,7 +636,7 @@ msgstr "Clave API" #: changedetectionio/blueprint/settings/templates/settings.html msgid "copy" -msgstr "Copiar" +msgstr "copiar" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Regenerate API key" @@ -799,12 +647,8 @@ msgid "Chrome Extension" msgstr "Extensión de Chrome" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Easily add any web-page to your changedetection.io installation from within " -"Chrome." -msgstr "" -"Agregue fácilmente cualquier página web a su instalación de changetection.io" -" desde Chrome." +msgid "Easily add any web-page to your changedetection.io installation from within Chrome." +msgstr "Agregue fácilmente cualquier página web a su instalación de changetection.io desde Chrome." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Step 1" @@ -847,40 +691,25 @@ msgid "Chrome Webstore" msgstr "Tienda web de Chrome" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Maximum number of history snapshots to include in the watch specific RSS " -"feed." -msgstr "" -"Número máximo de instantáneas del historial que se incluirán en la fuente " -"RSS específica del monitor." +msgid "Maximum number of history snapshots to include in the watch specific RSS feed." +msgstr "Número máximo de instantáneas del historial que se incluirán en la fuente RSS específica del monitor." #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"For watching other RSS feeds - When watching RSS/Atom feeds, convert them " -"into clean text for better change detection." -msgstr "" -"Para ver otras fuentes RSS: cuando vea fuentes RSS/Atom, conviértalas en " -"texto limpio para una mejor detección de cambios." +msgid "For watching other RSS feeds - When watching RSS/Atom feeds, convert them into clean text for better change detection." +msgstr "Para ver otras fuentes RSS: cuando vea fuentes RSS/Atom, conviértalas en texto limpio para una mejor detección de cambios." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Does your reader support HTML? Set it here" msgstr "¿Su lector soporta HTML? Ponlo aquí" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"'System default' for the same template for all items, or re-use your " -"\"Notification Body\" as the template." -msgstr "" -"'Predeterminado del sistema' para la misma plantilla para todos los " -"elementos, o reutilice su \"Cuerpo de notificación\" como plantilla." +msgid "'System default' for the same template for all items, or re-use your \"Notification Body\" as the template." +msgstr "'Predeterminado del sistema' para la misma plantilla para todos los elementos, o reutilice su \"Cuerpo de notificación\" como plantilla." #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Ensure the settings below are correct, they are used to manage the time " -"schedule for checking your web page watches." +msgid "Ensure the settings below are correct, they are used to manage the time schedule for checking your web page watches." msgstr "" -"Asegúrese de que las configuraciones a continuación sean correctas, se " -"utilizan para administrar el horario para verificar las visitas a su página " +"Asegúrese de que las configuraciones a continuación sean correctas, se utilizan para administrar el horario para verificar las visitas a su página " "web." #: changedetectionio/blueprint/settings/templates/settings.html @@ -892,19 +721,14 @@ msgid "Local Time & Date in Browser:" msgstr "Hora y fecha locales en el navegador:" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"Enable this setting to open the diff page in a new tab. If disabled, the " -"diff page will open in the current tab." +msgid "Enable this setting to open the diff page in a new tab. If disabled, the diff page will open in the current tab." msgstr "" -"Habilite esta configuración para abrir la página de diferencias en una nueva" -" pestaña. Si está deshabilitado, la página de diferencias se abrirá en la " -"pestaña actual." +"Habilite esta configuración para abrir la página de diferencias en una nueva pestaña. Si está deshabilitado, la página de diferencias se abrirá en " +"la pestaña actual." #: changedetectionio/blueprint/settings/templates/settings.html msgid "Realtime UI Updates Enabled - (Restart required if this is changed)" -msgstr "" -"Actualizaciones de UI en tiempo real habilitadas: (es necesario reiniciar si" -" se cambia esto)" +msgstr "Actualizaciones de UI en tiempo real habilitadas: (es necesario reiniciar si se cambia esto)" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Enable or Disable Favicons next to the watch list" @@ -919,27 +743,19 @@ msgid "Tip" msgstr "Consejo" #: changedetectionio/blueprint/settings/templates/settings.html -msgid "" -"\"Residential\" and \"Mobile\" proxy type can be more successfull than " -"\"Data Center\" for blocked websites." -msgstr "" -"El tipo de proxy \"residencial\" y \"móvil\" puede tener más éxito que el " -"\"centro de datos\" para sitios web bloqueados." +msgid "\"Residential\" and \"Mobile\" proxy type can be more successfull than \"Data Center\" for blocked websites." +msgstr "El tipo de proxy \"residencial\" y \"móvil\" puede tener más éxito que el \"centro de datos\" para sitios web bloqueados." #: changedetectionio/blueprint/settings/templates/settings.html msgid "\"Name\" will be used for selecting the proxy in the Watch Edit settings" -msgstr "" -"\"Nombre\" se utilizará para seleccionar el proxy en la configuración de " -"edición de visualización." +msgstr "«Nombre» se utilizará para seleccionar el proxy en la configuración de edición de visualización" #: changedetectionio/blueprint/settings/templates/settings.html msgid "" -"SOCKS5 proxies with authentication are only supported with 'plain requests' " -"fetcher, for other fetchers you should whitelist the IP access instead" +"SOCKS5 proxies with authentication are only supported with 'plain requests' fetcher, for other fetchers you should whitelist the IP access instead" msgstr "" -"Los proxies SOCKS5 con autenticación solo son compatibles con el buscador de" -" 'solicitudes simples'; para otros buscadores, en su lugar, debe incluir en " -"la lista blanca el acceso IP" +"Los proxies SOCKS5 con autenticación solo son compatibles con el buscador de 'solicitudes simples'; para otros buscadores, en su lugar, debe " +"incluir en la lista blanca el acceso IP" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Uptime:" @@ -983,8 +799,7 @@ msgstr "Desvincular etiqueta de monitores en segundo plano" #: changedetectionio/blueprint/tags/__init__.py msgid "All tags deleted, clearing from watches in background" -msgstr "" -"Todas las etiquetas eliminadas, borradas de los monitores en segundo plano." +msgstr "Todas las etiquetas eliminadas, borradas de los monitores en segundo plano." #: changedetectionio/blueprint/tags/__init__.py msgid "Tag not found" @@ -994,8 +809,7 @@ msgstr "Etiqueta no encontrada" msgid "Updated" msgstr "Actualizado" -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "Filters & Triggers" msgstr "Filtros y activadores" @@ -1011,59 +825,43 @@ msgstr "agregado" msgid "to any existing watch configurations." msgstr "a cualquier configuración de monitor existente." -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "Text filtering" msgstr "Filtrado de texto" -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "Use with caution!" msgstr "¡Úselo con precaución!" -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"This will easily fill up your email storage quota or flood other storages." -msgstr "" -"Esto llenará fácilmente su cuota de almacenamiento de correo electrónico o " -"inundará otros almacenamientos." +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html +msgid "This will easily fill up your email storage quota or flood other storages." +msgstr "Esto llenará fácilmente su cuota de almacenamiento de correo electrónico o inundará otros almacenamientos." -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "Look out!" msgstr "¡Estar atento!" -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "Lookout!" msgstr "¡Estar atento!" -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "There are" msgstr "Hay" -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "system-wide notification URLs enabled" -msgstr "URL de notificación en todo el sistema habilitadas" +msgstr "URLs de notificación en todo el sistema habilitadas" -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "this form will override notification settings for this watch only" -msgstr "" -"este formulario anulará la configuración de notificaciones solo para este " -"monitor" +msgstr "este formulario anulará la configuración de notificaciones solo para este monitor" -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "an empty Notification URL list here will still send notifications." -msgstr "" -"una lista de URL de notificación vacía aquí seguirá enviando notificaciones." +msgstr "una lista de URL de notificación vacía aquí seguirá enviando notificaciones." -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "Use system defaults" msgstr "Usar los valores predeterminados del sistema" @@ -1071,18 +869,13 @@ msgstr "Usar los valores predeterminados del sistema" msgid "Add a new organisational tag" msgstr "Agregar una nueva etiqueta organizacional" -#: changedetectionio/blueprint/tags/templates/groups-overview.html -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html +#: changedetectionio/blueprint/tags/templates/groups-overview.html changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Watch group / tag" msgstr "Ver grupo/etiqueta" #: changedetectionio/blueprint/tags/templates/groups-overview.html -msgid "" -"Groups allows you to manage filters and notifications for multiple watches " -"under a single organisational tag." -msgstr "" -"Grupos le permite administrar filtros y notificaciones para múltiples " -"monitores bajo una única etiqueta organizacional." +msgid "Groups allows you to manage filters and notifications for multiple watches under a single organisational tag." +msgstr "Grupos le permite administrar filtros y notificaciones para múltiples monitores bajo una única etiqueta organizacional." #: changedetectionio/blueprint/tags/templates/groups-overview.html msgid "# Watches" @@ -1096,13 +889,11 @@ msgstr "Nombre de etiqueta/etiqueta" msgid "No website organisational tags/groups configured" msgstr "No hay etiquetas/grupos organizativos del sitio web configurados" -#: changedetectionio/blueprint/tags/templates/groups-overview.html -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html +#: changedetectionio/blueprint/tags/templates/groups-overview.html changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Edit" msgstr "Editar" -#: changedetectionio/blueprint/tags/templates/groups-overview.html -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html +#: changedetectionio/blueprint/tags/templates/groups-overview.html changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Recheck" msgstr "Vuelva a comprobar" @@ -1112,16 +903,10 @@ msgstr "¿Eliminar grupo?" #: changedetectionio/blueprint/tags/templates/groups-overview.html #, python-format -msgid "" -"

Are you sure you want to delete group " -"%(title)s?

This action cannot be undone.

" -msgstr "" -"

¿Estás seguro de que deseas eliminar el " -"grupo?%(title)s?

Esta acción no se puede " -"deshacer.

" +msgid "

Are you sure you want to delete group %(title)s?

This action cannot be undone.

" +msgstr "

¿Estás seguro de que deseas eliminar el grupo?%(title)s?

Esta acción no se puede deshacer.

" -#: changedetectionio/blueprint/tags/templates/groups-overview.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/groups-overview.html changedetectionio/blueprint/ui/templates/edit.html #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Delete" msgstr "Borrar" @@ -1137,12 +922,10 @@ msgstr "¿Desvincular grupo?" #: changedetectionio/blueprint/tags/templates/groups-overview.html #, python-format msgid "" -"

Are you sure you want to unlink all watches from group " -"%(title)s?

The tag will be kept but watches will be " -"removed from it.

" +"

Are you sure you want to unlink all watches from group %(title)s?

The tag will be kept but watches will be removed from " +"it.

" msgstr "" -"

¿Está seguro de que desea desvincular todos los monitores del " -"grupo?%(title)s?

La etiqueta se mantendrá pero se le " +"

¿Está seguro de que desea desvincular todos los monitores del grupo?%(title)s?

La etiqueta se mantendrá pero se le " "quitarán los monitores.

" #: changedetectionio/blueprint/tags/templates/groups-overview.html @@ -1153,8 +936,7 @@ msgstr "Desconectar" msgid "Keep the tag but unlink any watches" msgstr "Conserva la etiqueta pero desvincula cualquier monitor" -#: changedetectionio/blueprint/tags/templates/groups-overview.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/tags/templates/groups-overview.html changedetectionio/blueprint/ui/templates/edit.html msgid "RSS Feed for this watch" msgstr "Feed RSS para este monitor" @@ -1196,9 +978,7 @@ msgstr "{} monitores borrados/restablecidos." #: changedetectionio/blueprint/ui/__init__.py msgid "{} watches set to use default notification settings" -msgstr "" -"{} monitores configurados para usar la configuración de notificación " -"predeterminada" +msgstr "{} monitores configurados para usar la configuración de notificación predeterminada" #: changedetectionio/blueprint/ui/__init__.py msgid "{} watches were tagged" @@ -1253,30 +1033,20 @@ msgid "Queueing watches for rechecking in background..." msgstr "Poniendo monitores en cola para volver a comprobar en segundo plano..." #: changedetectionio/blueprint/ui/__init__.py -msgid "" -"Could not share, something went wrong while communicating with the share " -"server - {}" -msgstr "" -"No se pudo compartir, algo salió mal al comunicarse con el servidor " -"compartido.{}" +msgid "Could not share, something went wrong while communicating with the share server - {}" +msgstr "No se pudo compartir, algo salió mal al comunicarse con el servidor compartido.{}" #: changedetectionio/blueprint/ui/__init__.py msgid "Language set to auto-detect from browser" msgstr "Idioma configurado para detectarse automáticamente desde el navegador" -#: changedetectionio/blueprint/ui/diff.py -#: changedetectionio/blueprint/ui/preview.py +#: changedetectionio/blueprint/ui/diff.py changedetectionio/blueprint/ui/preview.py msgid "No history found for the specified link, bad link?" -msgstr "" -"No se encontró historial para el enlace especificado, ¿enlace incorrecto?" +msgstr "No se encontró historial para el enlace especificado, ¿enlace incorrecto?" #: changedetectionio/blueprint/ui/diff.py -msgid "" -"Not enough history (2 snapshots required) to show difference page for this " -"watch." -msgstr "" -"No hay suficiente historial (se requieren 2 instantáneas) para mostrar la " -"página de diferencias para este monitor." +msgid "Not enough history (2 snapshots required) to show difference page for this watch." +msgstr "No hay suficiente historial (se requieren 2 instantáneas) para mostrar la página de diferencias para este monitor." #: changedetectionio/blueprint/ui/edit.py msgid "No watches to edit" @@ -1291,9 +1061,7 @@ msgid "Switched to mode - {}." msgstr "Cambiado al modo: {}." #: changedetectionio/blueprint/ui/edit.py -msgid "" -"Could not load '{}' processor, processor plugin might be missing. Please " -"select a different processor." +msgid "Could not load '{}' processor, processor plugin might be missing. Please select a different processor." msgstr "No se pudo cargar el procesador '{}'; es posible que falte el complemento del procesador. Seleccione un procesador diferente." #: changedetectionio/blueprint/ui/edit.py @@ -1310,17 +1078,11 @@ msgstr "Monitor actualizado." #: changedetectionio/blueprint/ui/preview.py msgid "Preview unavailable - No fetch/check completed or triggers not reached" -msgstr "" -"Vista previa no disponible: no se completó la búsqueda/verificación o no se " -"alcanzaron los activadores" +msgstr "Vista previa no disponible: no se completó la búsqueda/verificación o no se alcanzaron los activadores" #: changedetectionio/blueprint/ui/templates/clear_all_history.html -msgid "" -"This will remove version history (snapshots) for ALL watches, but keep your " -"list of URLs!" -msgstr "" -"Esto eliminará el historial de versiones (instantáneas) de TODOS los " -"monitores, ¡pero mantendrá su lista de URL!" +msgid "This will remove version history (snapshots) for ALL watches, but keep your list of URLs!" +msgstr "Esto eliminará el historial de versiones (instantáneas) de TODOS los monitores, ¡pero mantendrá su lista de URL!" #: changedetectionio/blueprint/ui/templates/clear_all_history.html msgid "You may like to use the" @@ -1354,8 +1116,7 @@ msgstr "para confirmar que entiende." msgid "Clear History!" msgstr "¡Borrar historial!" -#: changedetectionio/blueprint/ui/templates/clear_all_history.html -#: changedetectionio/templates/base.html +#: changedetectionio/blueprint/ui/templates/clear_all_history.html changedetectionio/templates/base.html msgid "Cancel" msgstr "Cancelar" @@ -1389,7 +1150,7 @@ msgstr "Palabras" #: changedetectionio/blueprint/ui/templates/diff.html msgid "Lines" -msgstr "Pauta" +msgstr "Líneas" #: changedetectionio/blueprint/ui/templates/diff.html msgid "Ignore Whitespace" @@ -1403,28 +1164,23 @@ msgstr "Igual/sin cambios" msgid "Removed" msgstr "Remoto" -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/edit.html msgid "Added" msgstr "Agregado" -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/edit.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/edit.html msgid "Replaced" msgstr "Reemplazado" -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "Keyboard:" msgstr "Teclado:" -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "Previous" msgstr "Anterior" -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "Next" msgstr "Próximo" @@ -1436,23 +1192,19 @@ msgstr "Saltar a la siguiente diferencia" msgid "Jump" msgstr "Saltar" -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "Error Text" msgstr "Texto de error" -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "Error Screenshot" msgstr "Captura de pantalla de error" -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "Text" msgstr "Texto" -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "Current screenshot" msgstr "Captura de pantalla actual" @@ -1462,12 +1214,11 @@ msgstr "Extraer datos" #: changedetectionio/blueprint/ui/templates/diff.html msgid "seconds ago." -msgstr "Hace segundos." +msgstr "hace unos segundos." -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "seconds ago" -msgstr "hace segundos" +msgstr "hace unos segundos" #: changedetectionio/blueprint/ui/templates/diff.html msgid "Current error-ing screenshot from most recent request" @@ -1479,7 +1230,7 @@ msgstr "Consejo profesional: puedes habilitar" #: changedetectionio/blueprint/ui/templates/diff.html msgid "\"share access when password is enabled\"" -msgstr "\"compartir acceso cuando la contraseña está habilitada\"" +msgstr "«compartir acceso cuando la contraseña está habilitada»" #: changedetectionio/blueprint/ui/templates/diff.html msgid "from settings." @@ -1493,35 +1244,25 @@ msgstr "Ir a instantánea única" msgid "Highlight text to share or add to ignore lists." msgstr "Resalte el texto para compartir o agregar a las listas de ignorados." -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html -msgid "" -"For now, Differences are performed on text, not graphically, only the latest" -" screenshot is available." -msgstr "" -"Por ahora, las diferencias se realizan en texto, no gráficamente, solo está " -"disponible la última captura de pantalla." +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html +msgid "For now, Differences are performed on text, not graphically, only the latest screenshot is available." +msgstr "Por ahora, las diferencias se realizan en texto, no gráficamente, solo está disponible la última captura de pantalla." -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "Current screenshot from most recent request" msgstr "Captura de pantalla actual de la solicitud más reciente" -#: changedetectionio/blueprint/ui/templates/diff.html -#: changedetectionio/blueprint/ui/templates/preview.html +#: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "No screenshot available just yet! Try rechecking the page." -msgstr "" -"¡Aún no hay captura de pantalla disponible! Intente volver a revisar la " -"página." +msgstr "¡Aún no hay captura de pantalla disponible! Intente volver a revisar la página." #: changedetectionio/blueprint/ui/templates/diff.html msgid "Screenshot requires Playwright/WebDriver enabled" -msgstr "" -"La captura de pantalla requiere que Playwright/WebDriver esté habilitado" +msgstr "La captura de pantalla requiere que Playwright/WebDriver esté habilitado" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Request" -msgstr "Pedido" +msgstr "Petición" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Browser Steps" @@ -1541,8 +1282,7 @@ msgstr "Estadísticas" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Some sites use JavaScript to create the content, for this you should" -msgstr "" -"Algunos sitios utilizan JavaScript para crear el contenido, para ello debes" +msgstr "Algunos sitios utilizan JavaScript para crear el contenido, para ello debes" #: changedetectionio/blueprint/ui/templates/edit.html msgid "use the Chrome/WebDriver Fetcher" @@ -1550,7 +1290,7 @@ msgstr "utilizar el buscador de Chrome/WebDriver" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Variables are supported in the URL" -msgstr "Las variables son compatibles con la URL." +msgstr "Las variables son compatibles con la URL" #: changedetectionio/blueprint/ui/templates/edit.html msgid "help and examples here" @@ -1558,17 +1298,11 @@ msgstr "ayuda y ejemplos aquí" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Organisational tag/group name used in the main listing page" -msgstr "" -"Etiqueta organizativa/nombre de grupo utilizado en la página principal del " -"listado" +msgstr "Etiqueta organizativa/nombre de grupo utilizado en la página principal del listado" #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"Automatically uses the page title if found, you can also use your own " -"title/description here" -msgstr "" -"Utiliza automáticamente el título de la página si la encuentra, también " -"puede usar su propio título/descripción aquí" +msgid "Automatically uses the page title if found, you can also use your own title/description here" +msgstr "Utiliza automáticamente el título de la página si la encuentra, también puede usar su propio título/descripción aquí" #: changedetectionio/blueprint/ui/templates/edit.html msgid "The interval/amount of time between each check." @@ -1576,32 +1310,23 @@ msgstr "El intervalo/cantidad de tiempo entre cada verificación." #: changedetectionio/blueprint/ui/templates/edit.html msgid "" -"Sends a notification when the filter can no longer be seen on the page, good" -" for knowing when the page changed and your filter will not work anymore." +"Sends a notification when the filter can no longer be seen on the page, good for knowing when the page changed and your filter will not work " +"anymore." msgstr "" -"Envía una notificación cuando el filtro ya no se puede ver en la página, lo " -"cual es bueno para saber cuándo cambió la página y su filtro ya no " +"Envía una notificación cuando el filtro ya no se puede ver en la página, lo cual es bueno para saber cuándo cambió la página y su filtro ya no " "funcionará." #: changedetectionio/blueprint/ui/templates/edit.html msgid "Set to empty to use system settings default" -msgstr "" -"Establecer en vacío para usar la configuración predeterminada del sistema" +msgstr "Establecer en vacío para usar la configuración predeterminada del sistema" #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"method (default) where your watched site doesn't need Javascript to render." -msgstr "" -"método (predeterminado) donde su sitio observado no necesita Javascript para" -" renderizarse." +msgid "method (default) where your watched site doesn't need Javascript to render." +msgstr "método (predeterminado) donde su sitio observado no necesita Javascript para renderizarse." #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"method requires a network connection to a running WebDriver+Chrome server, " -"set by the ENV var 'WEBDRIVER_URL'." -msgstr "" -"El método requiere una conexión de red a un servidor WebDriver+Chrome en " -"ejecución, establecido por la variable ENV 'WEBDRIVER_URL'." +msgid "method requires a network connection to a running WebDriver+Chrome server, set by the ENV var 'WEBDRIVER_URL'." +msgstr "el método requiere una conexión de red a un servidor WebDriver+Chrome en ejecución, establecido por la variable ENV 'WEBDRIVER_URL'." #: changedetectionio/blueprint/ui/templates/edit.html msgid "Check/Scan all" @@ -1620,37 +1345,28 @@ msgid "Show advanced options" msgstr "Mostrar opciones avanzadas" #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"Run this code before performing change detection, handy for filling in " -"fields and other actions" -msgstr "" -"Ejecute este código antes de realizar la detección de cambios, útil para " -"completar campos y otras acciones." +msgid "Run this code before performing change detection, handy for filling in fields and other actions" +msgstr "Ejecute este código antes de realizar la detección de cambios, útil para completar campos y otras acciones" #: changedetectionio/blueprint/ui/templates/edit.html msgid "More help and examples here" -msgstr "Más ayuda y ejemplos aquí." +msgstr "Más ayuda y ejemplos aquí" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Variables are supported in the request body" -msgstr "Las variables se admiten en el cuerpo de la solicitud." +msgstr "Las variables se admiten en el cuerpo de la solicitud" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Variables are supported in the request header values" -msgstr "" -"Las variables se admiten en los valores del encabezado de la solicitud." +msgstr "Las variables se admiten en los valores del encabezado de la solicitud" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Alert! Extra headers file found and will be added to this watch!" -msgstr "" -"¡Alerta! ¡Se encontró un archivo de encabezados adicional que se agregará a " -"este monitor!" +msgstr "¡Alerta! ¡Se encontró un archivo de encabezados adicional que se agregará a este monitor!" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Headers can be also read from a file in your data-directory" -msgstr "" -"Los encabezados también se pueden leer desde un archivo en su directorio de " -"datos" +msgstr "Los encabezados también se pueden leer desde un archivo en su directorio de datos" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Read more here" @@ -1666,8 +1382,7 @@ msgstr "Activar el buscador de texto" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Please wait, first browser step can take a little time to load.." -msgstr "" -"Espere, el primer paso del navegador puede tardar un poco en cargarse." +msgstr "Espere, el primer paso del navegador puede tardar un poco en cargarse." #: changedetectionio/blueprint/ui/templates/edit.html msgid "Click here to Start" @@ -1682,19 +1397,13 @@ msgid "Press \"Play\" to start." msgstr "Presione \"Reproducir\" para comenzar." #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"Visual Selector data is not ready, watch needs to be checked atleast once." -msgstr "" -"Los datos del selector visual no están listos; es necesario revisar el " -"monitor al menos una vez." +msgid "Visual Selector data is not ready, watch needs to be checked atleast once." +msgstr "Los datos del selector visual no están listos; es necesario revisar el monitor al menos una vez." #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"Sorry, this functionality only works with fetchers that support interactive " -"Javascript (so far only Playwright based fetchers)" +msgid "Sorry, this functionality only works with fetchers that support interactive Javascript (so far only Playwright based fetchers)" msgstr "" -"Lo sentimos, esta funcionalidad solo funciona con buscadores que admiten " -"Javascript interactivo (hasta ahora solo buscadores basados ​​en Playwright)" +"Lo sentimos, esta funcionalidad solo funciona con buscadores que admiten Javascript interactivo (hasta ahora solo buscadores basados ​​en Playwright)" #: changedetectionio/blueprint/ui/templates/edit.html msgid "to one that supports interactive Javascript." @@ -1709,12 +1418,8 @@ msgid "Set the fetch method" msgstr "Establecer el método de recuperación" #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"Use the verify (✓) button to test if a condition passes against the current " -"snapshot." -msgstr "" -"Utilice el botón de verificación ( ✓ ) para probar si una condición se " -"cumple con la instantánea actual." +msgid "Use the verify (✓) button to test if a condition passes against the current snapshot." +msgstr "Utilice el botón de verificación ( ✓ ) para probar si una condición se cumple con la instantánea actual." #: changedetectionio/blueprint/ui/templates/edit.html msgid "Read a quick tutorial about" @@ -1734,21 +1439,15 @@ msgstr "Consejos profesionales:" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Use the preview page to see your filters and triggers highlighted." -msgstr "" -"Utilice la página de vista previa para ver sus filtros y activadores " -"resaltados." +msgstr "Utilice la página de vista previa para ver sus filtros y activadores resaltados." #: changedetectionio/blueprint/ui/templates/edit.html msgid "Limit trigger/ignore/block/extract to;" msgstr "Limitar activación/ignorar/bloquear/extraer a;" #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"Note: Depending on the length and similarity of the text on each line, the " -"algorithm may consider an" -msgstr "" -"Nota: Dependiendo de la extensión y similitud del texto en cada línea, el " -"algoritmo puede considerar una" +msgid "Note: Depending on the length and similarity of the text on each line, the algorithm may consider an" +msgstr "Nota: Dependiendo de la extensión y similitud del texto en cada línea, el algoritmo puede considerar una" #: changedetectionio/blueprint/ui/templates/edit.html msgid "instead of" @@ -1760,7 +1459,7 @@ msgstr "reemplazo" #: changedetectionio/blueprint/ui/templates/edit.html msgid "for example." -msgstr "Por ejemplo." +msgstr "por ejemplo." #: changedetectionio/blueprint/ui/templates/edit.html msgid "addition" @@ -1776,8 +1475,7 @@ msgstr "cuando esté interesado en contenido nuevo." #: changedetectionio/blueprint/ui/templates/edit.html msgid "When content is merely moved in a list, it will also trigger an" -msgstr "" -"Cuando el contenido simplemente se mueve en una lista, también activará una" +msgstr "Cuando el contenido simplemente se mueve en una lista, también activará una" #: changedetectionio/blueprint/ui/templates/edit.html msgid "consider enabling" @@ -1789,21 +1487,15 @@ msgstr "Solo se activa cuando aparecen líneas únicas" #: changedetectionio/blueprint/ui/templates/edit.html msgid "" -"Good for websites that just move the content around, and you want to know " -"when NEW content is added, compares new lines against all history for this " -"watch." +"Good for websites that just move the content around, and you want to know when NEW content is added, compares new lines against all history for " +"this watch." msgstr "" -"Bueno para sitios web que simplemente mueven el contenido y desea saber " -"cuándo se agrega contenido NUEVO, compara nuevas líneas con todo el " +"Bueno para sitios web que simplemente mueven el contenido y desea saber cuándo se agrega contenido NUEVO, compara nuevas líneas con todo el " "historial de este monitor." #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"Helps reduce changes detected caused by sites shuffling lines around, " -"combine with" -msgstr "" -"Ayuda a reducir los cambios detectados causados ​​por sitios que cambian las" -" líneas, combinar con" +msgid "Helps reduce changes detected caused by sites shuffling lines around, combine with" +msgstr "Ayuda a reducir los cambios detectados causados ​​por sitios que cambian las líneas, combinar con" #: changedetectionio/blueprint/ui/templates/edit.html msgid "check unique lines" @@ -1815,8 +1507,7 @@ msgstr "abajo." #: changedetectionio/blueprint/ui/templates/edit.html msgid "Remove any whitespace before and after each line of text" -msgstr "" -"Elimine cualquier espacio en blanco antes y después de cada línea de texto." +msgstr "Eliminar cualquier espacio en blanco antes y después de cada línea de texto" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Loading..." @@ -1831,13 +1522,9 @@ msgid "text" msgstr "texto" #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"elements that will be used for the change detection. It automatically fills-" -"in the filters in the \"CSS/JSONPath/JQ/XPath Filters\" box of the" +msgid "elements that will be used for the change detection. It automatically fills-in the filters in the \"CSS/JSONPath/JQ/XPath Filters\" box of the" msgstr "" -"elementos que se utilizarán para la detección de cambios. Completa " -"automáticamente los filtros en el cuadro \"Filtros CSS/JSONPath/JQ/XPath\" " -"del" +"elementos que se utilizarán para la detección de cambios. Completa automáticamente los filtros en el cuadro \"Filtros CSS/JSONPath/JQ/XPath\" del" #: changedetectionio/blueprint/ui/templates/edit.html msgid "tab. Use" @@ -1869,17 +1556,14 @@ 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." +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)." +msgid "Sorry, this functionality only works with fetchers that support Javascript and screenshots (such as playwright etc)." msgstr "Lo sentimos, esta funcionalidad solo funciona con métodos de obtención que admiten JavaScript y capturas de pantalla (como Playwright, etc.)." #: changedetectionio/blueprint/ui/templates/edit.html @@ -1939,12 +1623,8 @@ msgid "Are you sure you want to clear all history for:" msgstr "¿Está seguro de que desea borrar todo el historial de:" #: changedetectionio/blueprint/ui/templates/edit.html -msgid "" -"This will remove all snapshots and previous versions. This action cannot be " -"undone." -msgstr "" -"Esto eliminará todas las instantáneas y versiones anteriores. Esta acción no" -" se puede deshacer." +msgid "This will remove all snapshots and previous versions. This action cannot be undone." +msgstr "Esto eliminará todas las instantáneas y versiones anteriores. Esta acción no se puede deshacer." #: changedetectionio/blueprint/ui/templates/edit.html msgid "Clear History" @@ -1967,12 +1647,8 @@ msgid "Current erroring screenshot from most recent request" msgstr "Captura de pantalla con error actual de la solicitud más reciente" #: changedetectionio/blueprint/ui/templates/preview.html -msgid "" -"Screenshot requires a Content Fetcher ( Sockpuppetbrowser, selenium, etc ) " -"that supports screenshots." -msgstr "" -"La captura de pantalla requiere un buscador de contenido (Sockpuppetbrowser," -" selenium, etc.) que admita capturas de pantalla." +msgid "Screenshot requires a Content Fetcher ( Sockpuppetbrowser, selenium, etc ) that supports screenshots." +msgstr "La captura de pantalla requiere un buscador de contenido (Sockpuppetbrowser, selenium, etc.) que admita capturas de pantalla." #: changedetectionio/blueprint/ui/views.py msgid "Warning, URL {} already exists" @@ -1987,8 +1663,7 @@ msgid "Watch added." msgstr "Monitor añadido." #: changedetectionio/blueprint/watchlist/__init__.py -msgid "" -"displaying {start} - {end} {record_name} in total {total}" +msgid "displaying {start} - {end} {record_name} in total {total}" msgstr "mostrando{start} - {end} {record_name}en total{total}" #: changedetectionio/blueprint/watchlist/__init__.py @@ -1996,11 +1671,8 @@ msgid "records" msgstr "archivos" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "" -"Changedetection.io can monitor more than just web-pages! See our plugins!" -msgstr "" -"¡Changedetection.io puede monitorear más que solo páginas web! ¡Vea nuestros" -" complementos!" +msgid "Changedetection.io can monitor more than just web-pages! See our plugins!" +msgstr "¡Changedetection.io puede monitorear más que solo páginas web! ¡Vea nuestros complementos!" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "More info" @@ -2059,16 +1731,12 @@ msgid "Clear Histories" msgstr "Borrar historiales" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "" -"

Are you sure you want to clear history for the selected items?

This" -" action cannot be undone.

" -msgstr "" -"

¿Está seguro de que desea borrar el historial de los elementos " -"seleccionados?

Esta acción no se puede deshacer.

" +msgid "

Are you sure you want to clear history for the selected items?

This action cannot be undone.

" +msgstr "

¿Está seguro de que desea borrar el historial de los elementos seleccionados?

Esta acción no se puede deshacer.

" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "OK" -msgstr "DE ACUERDO" +msgstr "OK" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Clear/reset history" @@ -2079,12 +1747,8 @@ msgid "Delete Watches?" msgstr "¿Eliminar monitores?" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "" -"

Are you sure you want to delete the selected watches?

This" -" action cannot be undone.

" -msgstr "" -"

¿Está seguro de que desea eliminar los monitores " -"seleccionados?

Esta acción no se puede deshacer.

" +msgid "

Are you sure you want to delete the selected watches?

This action cannot be undone.

" +msgstr "

¿Está seguro de que desea eliminar los monitores seleccionados?

Esta acción no se puede deshacer.

" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Queued size" @@ -2092,7 +1756,7 @@ msgstr "Tamaño de la cola" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Searching" -msgstr "Búsqueda" +msgstr "Buscando" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "All" @@ -2116,15 +1780,11 @@ msgstr "Último" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Changed" -msgstr "Cambió" +msgstr "Cambiadp" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "" -"No web page change detection watches configured, please add a URL in the box" -" above, or" -msgstr "" -"No hay monitores de detección de cambios de página web configuradas; agregue" -" una URL en el cuadro de arriba, o" +msgid "No web page change detection watches configured, please add a URL in the box above, or" +msgstr "No hay monitores de detección de cambios de página web configuradas; agregue una URL en el cuadro de arriba, o" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "import a list" @@ -2150,8 +1810,7 @@ msgstr "Precio" msgid "No information" msgstr "Sin información" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -#: changedetectionio/templates/base.html +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/templates/base.html msgid "Checking now" msgstr "Comprobando ahora" @@ -2193,8 +1852,7 @@ msgstr "Vuelva a comprobar todo" msgid "in '%(title)s'" msgstr "en '%(title)s'" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -#: changedetectionio/flask_app.py changedetectionio/realtime/socket_server.py +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/flask_app.py changedetectionio/realtime/socket_server.py msgid "Not yet" msgstr "Aún no" @@ -2254,10 +1912,9 @@ msgstr "minutos" msgid "second" msgstr "segundo" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/flask_app.py +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/flask_app.py msgid "seconds" -msgstr "artículos de segunda clase" +msgstr "segundos" #: changedetectionio/flask_app.py msgid "Already logged in" @@ -2272,20 +1929,12 @@ msgid "Incorrect password" msgstr "Contraseña incorrecta" #: changedetectionio/forms.py -msgid "" -"At least one time interval (weeks, days, hours, minutes, or seconds) must be" -" specified." -msgstr "" -"Se debe especificar al menos un intervalo de tiempo (semanas, días, horas, " -"minutos o segundos)." +msgid "At least one time interval (weeks, days, hours, minutes, or seconds) must be specified." +msgstr "Se debe especificar al menos un intervalo de tiempo (semanas, días, horas, minutos o segundos)." #: changedetectionio/forms.py -msgid "" -"At least one time interval (weeks, days, hours, minutes, or seconds) must be" -" specified when not using global settings." -msgstr "" -"Se debe especificar al menos un intervalo de tiempo (semanas, días, horas, " -"minutos o segundos) cuando no se utilice la configuración global." +msgid "At least one time interval (weeks, days, hours, minutes, or seconds) must be specified when not using global settings." +msgstr "Se debe especificar al menos un intervalo de tiempo (semanas, días, horas, minutos o segundos) cuando no se utilice la configuración global." #: changedetectionio/forms.py msgid "Invalid time format. Use HH:MM." @@ -2349,7 +1998,7 @@ msgstr "Semanas" #: changedetectionio/forms.py msgid "Should contain zero or more seconds" -msgstr "Debe contener cero o más segundos." +msgstr "Debe contener cero o más segundos" #: changedetectionio/forms.py msgid "Days" @@ -2365,14 +2014,11 @@ msgstr "Minutos" #: changedetectionio/forms.py msgid "Seconds" -msgstr "Artículos de segunda clase" +msgstr "Segundos" #: changedetectionio/forms.py -msgid "" -"Notification Body and Title is required when a Notification URL is used" -msgstr "" -"Se requiere el cuerpo y el título de la notificación cuando se utiliza una " -"URL de notificación" +msgid "Notification Body and Title is required when a Notification URL is used" +msgstr "Se requiere el cuerpo y el título de la notificación cuando se utiliza una URL de notificación" #: changedetectionio/forms.py #, python-format @@ -2407,8 +2053,7 @@ msgstr "Valor vacío no permitido." msgid "Invalid value." msgstr "Valor no válido." -#: changedetectionio/blueprint/imports/templates/import.html -#: changedetectionio/forms.py +#: changedetectionio/blueprint/imports/templates/import.html changedetectionio/forms.py msgid "URL" msgstr "URL" @@ -2458,11 +2103,11 @@ msgstr "Zona horaria predeterminada para el programador de verificación de moni #: changedetectionio/forms.py msgid "Wait seconds before extracting text" -msgstr "Espere unos segundos antes de extraer el texto." +msgstr "Segundos de espera antes de extraer el texto" #: changedetectionio/forms.py msgid "Should contain one or more seconds" -msgstr "Debe contener uno o más segundos." +msgstr "Debe contener uno o más segundos" #: changedetectionio/forms.py msgid "URLs" @@ -2498,9 +2143,7 @@ msgstr "Tiempo entre comprobaciones" #: changedetectionio/forms.py msgid "Use global settings for time between check and scheduler." -msgstr "" -"Utilice la configuración global para el tiempo entre la verificación y el " -"programador." +msgstr "Utilice la configuración global para el tiempo entre la verificación y el programador." #: changedetectionio/forms.py msgid "CSS/JSONPath/JQ/XPath Filters" @@ -2514,8 +2157,7 @@ msgstr "Eliminar elementos" msgid "Extract text" msgstr "Extraer texto" -#: changedetectionio/blueprint/imports/templates/import.html -#: changedetectionio/forms.py +#: changedetectionio/blueprint/imports/templates/import.html changedetectionio/forms.py msgid "Title" msgstr "Título" @@ -2533,16 +2175,13 @@ msgstr "Método de solicitud" #: changedetectionio/forms.py msgid "Ignore status codes (process non-2xx status codes as normal)" -msgstr "" -"Ignorar códigos de estado (procesar códigos de estado que no sean 2xx como " -"de costumbre)" +msgstr "Ignorar códigos de estado (procesar códigos de estado que no sean 2xx como de costumbre)" #: changedetectionio/forms.py msgid "Only trigger when unique lines appear in all history" msgstr "Solo se activa cuando aparecen líneas únicas en todo el historial" -#: changedetectionio/blueprint/ui/templates/edit.html -#: changedetectionio/forms.py +#: changedetectionio/blueprint/ui/templates/edit.html changedetectionio/forms.py msgid "Remove duplicate lines of text" msgstr "Eliminar líneas de texto duplicadas" @@ -2582,33 +2221,28 @@ msgstr "Bloquear la detección de cambios mientras el texto coincide" msgid "Execute JavaScript before change detection" msgstr "Ejecute JavaScript antes de la detección de cambios" -#: changedetectionio/blueprint/tags/templates/groups-overview.html -#: changedetectionio/forms.py +#: changedetectionio/blueprint/tags/templates/groups-overview.html changedetectionio/forms.py msgid "Save" -msgstr "Ahorrar" +msgstr "Guardar" #: changedetectionio/forms.py msgid "Proxy" -msgstr "Apoderado" +msgstr "Proxy" #: changedetectionio/forms.py msgid "Send a notification when the filter can no longer be found on the page" -msgstr "" -"Enviar una notificación cuando el filtro ya no se pueda encontrar en la " -"página" +msgstr "Enviar una notificación cuando el filtro ya no se pueda encontrar en la página" #: changedetectionio/forms.py msgid "Muted" -msgstr "Apagado" +msgstr "Silenciado" #: changedetectionio/forms.py msgid "On" -msgstr "En" +msgstr "On" -#: changedetectionio/blueprint/settings/templates/settings.html -#: changedetectionio/blueprint/tags/templates/edit-tag.html -#: changedetectionio/blueprint/ui/templates/edit.html -#: changedetectionio/forms.py +#: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/tags/templates/edit-tag.html +#: changedetectionio/blueprint/ui/templates/edit.html changedetectionio/forms.py msgid "Notifications" msgstr "Notificaciones" @@ -2618,7 +2252,7 @@ msgstr "Adjunte captura de pantalla a la notificación (cuando sea posible)" #: changedetectionio/forms.py msgid "Match" -msgstr "Fósforo" +msgstr "Coincidencia" #: changedetectionio/forms.py msgid "Match all of the following" @@ -2638,9 +2272,7 @@ msgstr "Número de elementos del historial por monitor que se deben conservar" #: changedetectionio/forms.py msgid "Body must be empty when Request Method is set to GET" -msgstr "" -"El cuerpo debe estar vacío cuando el método de solicitud está configurado en" -" GET" +msgstr "El cuerpo debe estar vacío cuando el método de solicitud está configurado en GET" #: changedetectionio/forms.py #, python-format @@ -2667,8 +2299,7 @@ msgstr "URL de proxy" #: changedetectionio/forms.py msgid "Proxy URLs must start with http://, https:// or socks5://" -msgstr "" -"Las URL de proxy deben comenzar con http://, https:// o calcetines5://" +msgstr "Las URL de proxy deben comenzar con http://, https:// o socks5://" #: changedetectionio/forms.py msgid "Browser connection URL" @@ -2754,8 +2385,7 @@ msgstr "Ignorar texto" msgid "Ignore whitespace" msgstr "Ignorar espacios en blanco" -#: changedetectionio/forms.py -#: changedetectionio/processors/image_ssim_diff/forms.py +#: changedetectionio/forms.py changedetectionio/processors/image_ssim_diff/forms.py msgid "Must be between 0 and 100" msgstr "Debe estar entre 0 y 100" @@ -2765,7 +2395,7 @@ msgstr "Contraseña" #: changedetectionio/forms.py msgid "Pager size" -msgstr "Tamaño del buscapersonas" +msgstr "Tamaño del paginador" #: changedetectionio/forms.py msgid "Should be atleast zero (disabled)" @@ -2793,9 +2423,7 @@ msgstr "Representar el contenido de la etiqueta de anclaje" #: changedetectionio/forms.py msgid "Allow anonymous access to watch history page when password is enabled" -msgstr "" -"Permitir el acceso anónimo a la página del historial de visualización cuando" -" la contraseña esté habilitada" +msgstr "Permitir el acceso anónimo a la página del historial de visualización cuando la contraseña esté habilitada" #: changedetectionio/forms.py msgid "Hide muted watches from RSS feed" @@ -2803,7 +2431,7 @@ msgstr "Ocultar monitores silenciados del feed RSS" #: changedetectionio/forms.py msgid "Enable RSS reader mode " -msgstr "Habilitar el modo lector RSS" +msgstr "Habilitar el modo lector RSS " #: changedetectionio/forms.py msgid "Number of changes to show in watch RSS feed" @@ -2811,13 +2439,11 @@ msgstr "Número de cambios que se mostrarán en la fuente RSS del monitor" #: changedetectionio/forms.py msgid "Should contain zero or more attempts" -msgstr "Debe contener cero o más intentos." +msgstr "Debe contener cero o más intentos" #: changedetectionio/forms.py -msgid "" -"Number of times the filter can be missing before sending a notification" -msgstr "" -"Número de veces que puede faltar el filtro antes de enviar una notificación" +msgid "Number of times the filter can be missing before sending a notification" +msgstr "Número de veces que puede faltar el filtro antes de enviar una notificación" #: changedetectionio/forms.py msgid "RegEx to extract" @@ -2828,16 +2454,12 @@ msgid "Extract as CSV" msgstr "Extraer como CSV" #: 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." +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." #: changedetectionio/processors/image_ssim_diff/difference.py msgid "Not enough history to compare. Need at least 2 snapshots." -msgstr "" -"No hay suficiente historia para comparar. Necesita al menos 2 instantáneas." +msgstr "No hay suficiente historia para comparar. Necesita al menos 2 instantáneas." #: changedetectionio/processors/image_ssim_diff/difference.py msgid "Failed to load screenshots: {}" @@ -2853,9 +2475,7 @@ msgstr "El valor del cuadro delimitador es demasiado largo" #: changedetectionio/processors/image_ssim_diff/forms.py msgid "Bounding box must be in format: x,y,width,height (integers only)" -msgstr "" -"El cuadro delimitador debe tener el formato: x,y,ancho,alto (solo números " -"enteros)" +msgstr "El cuadro delimitador debe tener el formato: x,y,ancho,alto (solo números enteros)" #: changedetectionio/processors/image_ssim_diff/forms.py msgid "Bounding box values must be non-negative" @@ -2906,11 +2526,8 @@ msgid "Visual / Image screenshot change detection" msgstr "Detección de cambios de captura de pantalla visual/imagen" #: changedetectionio/processors/image_ssim_diff/processor.py -msgid "" -"Compares screenshots using fast OpenCV algorithm, 10-100x faster than SSIM" -msgstr "" -"Compara capturas de pantalla utilizando el rápido algoritmo OpenCV, entre 10" -" y 100 veces más rápido que SSIM" +msgid "Compares screenshots using fast OpenCV algorithm, 10-100x faster than SSIM" +msgstr "Compara capturas de pantalla utilizando el rápido algoritmo OpenCV, entre 10 y 100 veces más rápido que SSIM" #: changedetectionio/processors/restock_diff/forms.py msgid "Re-stock detection" @@ -2959,8 +2576,7 @@ msgstr "Reabastecimiento y detección de precios" #: changedetectionio/processors/restock_diff/processor.py msgid "Re-stock & Price detection for pages with a SINGLE product" -msgstr "" -"Reabastecimiento y detección de precios para páginas con un ÚNICO producto" +msgstr "Reabastecimiento y detección de precios para páginas con un ÚNICO producto" #: changedetectionio/processors/restock_diff/processor.py msgid "Detects if the product goes back to in-stock" @@ -2972,7 +2588,7 @@ msgstr "Cambios en el texto/HTML, JSON y PDF de la página web" #: changedetectionio/processors/text_json_diff/processor.py msgid "Detects all text changes where possible" -msgstr "Detecta todos los cambios de texto siempre que sea posible." +msgstr "Detecta todos los cambios de texto siempre que sea posible" #: changedetectionio/store/__init__.py msgid "Error fetching metadata for {}" @@ -2980,26 +2596,19 @@ msgstr "Error al obtener metadatos para{}" #: changedetectionio/store/__init__.py msgid "Watch protocol is not permitted or invalid URL format" -msgstr "" -"El protocolo de visualización no está permitido o el formato de URL no es " -"válido" +msgstr "El protocolo de visualización no está permitido o el formato de URL no es válido" #: changedetectionio/store/__init__.py msgid "Watch limit reached ({}/{} watches). Cannot add more watches." -msgstr "" -"Límite de visualización alcanzado ({} /{} monitores). No se pueden agregar " -"más monitores." +msgstr "Límite de visualización alcanzado ({} /{} monitores). No se pueden agregar más monitores." #: changedetectionio/templates/_common_fields.html msgid "Body for all notifications — You can use" msgstr "Cuerpo de todas las notificaciones: puedes utilizar" #: changedetectionio/templates/_common_fields.html -msgid "" -"templating in the notification title, body and URL, and tokens from below." -msgstr "" -"plantillas en el título, el cuerpo y la URL de la notificación, y tokens " -"desde abajo." +msgid "templating in the notification title, body and URL, and tokens from below." +msgstr "plantillas en el título, el cuerpo y la URL de la notificación, y tokens desde abajo." #: changedetectionio/templates/_common_fields.html msgid "Show token/placeholders" @@ -3007,7 +2616,7 @@ msgstr "Mostrar token/marcadores de posición" #: changedetectionio/templates/_common_fields.html msgid "Token" -msgstr "Simbólico" +msgstr "Token" #: changedetectionio/templates/_common_fields.html msgid "Description" @@ -3026,11 +2635,8 @@ msgid "The UUID of the watch." msgstr "El UUID del monitor." #: changedetectionio/templates/_common_fields.html -msgid "" -"The page title of the watch, uses if not set, falls back to URL" -msgstr "" -"El título de la página del monitor, utiliza<title>si no se establece, vuelve" -" a la URL" +msgid "The page title of the watch, uses <title> if not set, falls back to URL" +msgstr "El título de la página del monitor, utiliza<title>si no se establece, vuelve a la URL" #: changedetectionio/templates/_common_fields.html msgid "The watch group / tag" @@ -3058,39 +2664,35 @@ msgstr "Sin prefijo ni colores (añadidos)" #: changedetectionio/templates/_common_fields.html msgid "The diff output - only changes and additions" -msgstr "La salida del diferencial: solo cambios y adiciones" +msgstr "La salida de la comparación - solo cambios y adiciones" #: changedetectionio/templates/_common_fields.html msgid "The diff output - only changes and additions —" -msgstr "La salida del diferencial (solo cambios y adiciones)" +msgstr "La salida de la comparación - solo cambios y adiciones —" #: changedetectionio/templates/_common_fields.html msgid "The diff output - only changes and removals" -msgstr "La salida del diferencial: solo cambios y eliminaciones" +msgstr "La salida de la comparación - solo cambios y eliminaciones" #: changedetectionio/templates/_common_fields.html msgid "The diff output - only changes and removals —" -msgstr "La salida del diferencial (solo cambios y eliminaciones)" +msgstr "La salida de la comparación - solo cambios y eliminaciones —" #: changedetectionio/templates/_common_fields.html msgid "The diff output - full difference output" -msgstr "La salida diff - salida de diferencia completa" +msgstr "La salida de la comparación - salida de diferencia completa" #: changedetectionio/templates/_common_fields.html msgid "The diff output - full difference output —" -msgstr "La salida diff - salida de diferencia completa -" +msgstr "La salida de la comparación - salida de diferencia completa -" #: changedetectionio/templates/_common_fields.html msgid "The diff output - patch in unified format" -msgstr "La salida diff - parche en formato unificado" +msgstr "La salida de la comparación - parche en formato unificado" #: changedetectionio/templates/_common_fields.html -msgid "" -"The current snapshot text contents value, useful when combined with JSON or " -"CSS filters" -msgstr "" -"El valor del contenido del texto de la instantánea actual, útil cuando se " -"combina con filtros JSON o CSS" +msgid "The current snapshot text contents value, useful when combined with JSON or CSS filters" +msgstr "El valor del contenido del texto de la instantánea actual, útil cuando se combina con filtros JSON o CSS" #: changedetectionio/templates/_common_fields.html msgid "Text that tripped the trigger from filters" @@ -3106,15 +2708,11 @@ msgstr "y" #: changedetectionio/templates/_common_fields.html msgid "depend on how the difference algorithm perceives the change." -msgstr "Depende de cómo el algoritmo de diferencia percibe el cambio." +msgstr "depende de cómo el algoritmo de diferencia percibe el cambio." #: changedetectionio/templates/_common_fields.html -msgid "" -"For example, an addition or removal could be perceived as a change in some " -"cases." -msgstr "" -"Por ejemplo, una adición o eliminación podría percibirse como un cambio en " -"algunos casos." +msgid "For example, an addition or removal could be perceived as a change in some cases." +msgstr "Por ejemplo, una adición o eliminación podría percibirse como un cambio en algunos casos." #: changedetectionio/templates/_common_fields.html msgid "More Here" @@ -3129,15 +2727,10 @@ msgid "for notification to just about any service!" msgstr "para notificar a casi cualquier servicio!" #: changedetectionio/templates/_common_fields.html -msgid "" -"Please read the notification services wiki here for important configuration " -"notes" -msgstr "" -"Lea la wiki de servicios de notificación aquí para obtener notas de " -"configuración importantes." +msgid "Please read the notification services wiki here for important configuration notes" +msgstr "Lea la wiki de servicios de notificación aquí para obtener notas de configuración importantes" -#: changedetectionio/templates/_common_fields.html -#: changedetectionio/templates/edit/text-options.html +#: changedetectionio/templates/_common_fields.html changedetectionio/templates/edit/text-options.html msgid "Use" msgstr "Usar" @@ -3162,18 +2755,12 @@ msgid "of notification text, including the title." msgstr "del texto de la notificación, incluido el título." #: changedetectionio/templates/_common_fields.html -msgid "" -"bots can't send messages to other bots, so you should specify chat ID of " -"non-bot user." -msgstr "" -"Los bots no pueden enviar mensajes a otros bots, por lo que debes " -"especificar el ID de chat de un usuario que no sea un bot." +msgid "bots can't send messages to other bots, so you should specify chat ID of non-bot user." +msgstr "Los bots no pueden enviar mensajes a otros bots, por lo que debes especificar el ID de chat de un usuario que no sea un bot." #: changedetectionio/templates/_common_fields.html msgid "only supports very limited HTML and can fail when extra tags are sent," -msgstr "" -"solo admite HTML muy limitado y puede fallar cuando se envían etiquetas " -"adicionales," +msgstr "solo admite HTML muy limitado y puede fallar cuando se envían etiquetas adicionales," #: changedetectionio/templates/_common_fields.html msgid "(or use plaintext/markdown format)" @@ -3221,7 +2808,7 @@ msgstr "Tratamiento.." #: changedetectionio/templates/_common_fields.html msgid "Title for all notifications" -msgstr "Título para todas las notificaciones." +msgstr "Título para todas las notificaciones" #: changedetectionio/templates/_common_fields.html msgid "For JSON payloads, use" @@ -3237,23 +2824,19 @@ msgstr "Codificación de URL, uso" #: changedetectionio/templates/_common_fields.html msgid "for example -" -msgstr "Por ejemplo -" +msgstr "por ejemplo -" #: changedetectionio/templates/_common_fields.html msgid "Regular-expression replace, use" msgstr "Reemplazo de expresión regular, uso" #: changedetectionio/templates/_common_fields.html -msgid "" -"For a complete reference of all Jinja2 built-in filters, users can refer to " -"the" -msgstr "" -"Para obtener una referencia completa de todos los filtros integrados de " -"Jinja2, los usuarios pueden consultar el" +msgid "For a complete reference of all Jinja2 built-in filters, users can refer to the" +msgstr "Para obtener una referencia completa de todos los filtros integrados de Jinja2, los usuarios pueden consultar el" #: changedetectionio/templates/_common_fields.html msgid "Format for all notifications" -msgstr "Formato para todas las notificaciones." +msgstr "Formato para todas las notificaciones" #: changedetectionio/templates/_helpers.html msgid "Entry" @@ -3261,7 +2844,7 @@ msgstr "Entrada" #: changedetectionio/templates/_helpers.html msgid "Actions" -msgstr "Comportamiento" +msgstr "Acciones" #: changedetectionio/templates/_helpers.html msgid "Add a row/rule after" @@ -3276,9 +2859,7 @@ msgid "Verify this rule against current snapshot" msgstr "Verifique esta regla con la instantánea actual" #: changedetectionio/templates/_helpers.html -msgid "" -"Error - This watch needs Chrome (with playwright/sockpuppetbrowser), but " -"Chrome based fetching is not enabled." +msgid "Error - This watch needs Chrome (with playwright/sockpuppetbrowser), but Chrome based fetching is not enabled." msgstr "Error: este monitor necesita Chrome (con playwright/sockpuppetbrowser), pero la obtención basada en Chrome no está habilitada." #: changedetectionio/templates/_helpers.html @@ -3286,11 +2867,8 @@ msgid "Alternatively try our" msgstr "Alternativamente prueba nuestro" #: changedetectionio/templates/_helpers.html -msgid "" -"very affordable subscription based service which has all this setup for you" -msgstr "" -"Servicio basado en suscripción muy asequible que tiene toda esta " -"configuración para usted." +msgid "very affordable subscription based service which has all this setup for you" +msgstr "servicio basado en suscripción muy asequible que tiene toda esta configuración para usted." #: changedetectionio/templates/_helpers.html msgid "You may need to" @@ -3310,7 +2888,7 @@ msgstr "en el" #: changedetectionio/templates/_helpers.html msgid "file" -msgstr "archivo" +msgstr "fichero" #: changedetectionio/templates/_helpers.html msgid "Set a hourly/week day schedule" @@ -3333,12 +2911,8 @@ msgid "Reset" msgstr "Reiniciar" #: changedetectionio/templates/_helpers.html -msgid "" -"Warning, one or more of your 'days' has a duration that would extend into " -"the next day." -msgstr "" -"Advertencia, uno o más de sus 'días' tienen una duración que se extendería " -"hasta el día siguiente." +msgid "Warning, one or more of your 'days' has a duration that would extend into the next day." +msgstr "Advertencia, uno o más de sus 'días' tienen una duración que se extendería hasta el día siguiente." #: changedetectionio/templates/_helpers.html msgid "This could have unintended consequences." @@ -3357,9 +2931,7 @@ msgid "First confirm/save your Time Zone Settings" msgstr "Primero confirme/guarde su configuración de zona horaria" #: changedetectionio/templates/_helpers.html -msgid "" -"Triggers a change if this text appears, AND something changed in the " -"document." +msgid "Triggers a change if this text appears, AND something changed in the document." msgstr "Activa un cambio si aparece este texto Y algo cambia en el documento." #: changedetectionio/templates/_helpers.html @@ -3376,8 +2948,7 @@ msgstr "Texto ignorado" #: changedetectionio/templates/_helpers.html msgid "No change-detection will occur because this text exists." -msgstr "" -"No se producirá ninguna detección de cambios porque este texto existe." +msgstr "No se producirá ninguna detección de cambios porque este texto existe." #: changedetectionio/templates/_helpers.html msgid "Blocked text" @@ -3400,12 +2971,8 @@ msgid "Auto-detect from browser" msgstr "Detectar automáticamente desde el navegador" #: changedetectionio/templates/base.html -msgid "" -"Language support is in beta, please help us improve by opening a PR on " -"GitHub with any updates." -msgstr "" -"El soporte de idiomas está en versión beta. Ayúdenos a mejorar abriendo un " -"PR en GitHub con cualquier actualización." +msgid "Language support is in beta, please help us improve by opening a PR on GitHub with any updates." +msgstr "El soporte de idiomas está en versión beta. Ayúdenos a mejorar abriendo un PR en GitHub con cualquier actualización." #: changedetectionio/templates/base.html msgid "Search" @@ -3424,21 +2991,14 @@ msgid "Enter search term..." msgstr "Introduzca el término de búsqueda..." #: changedetectionio/templates/edit/text-options.html -msgid "" -"Text to wait for before triggering a change/notification, all text and regex" -" are tested case-insensitive." +msgid "Text to wait for before triggering a change/notification, all text and regex are tested case-insensitive." msgstr "" -"Texto a esperar antes de activar un cambio/notificación, todo el texto y las" -" expresiones regulares se prueban sin distinguir entre mayúsculas y " +"Texto a esperar antes de activar un cambio/notificación, todo el texto y las expresiones regulares se prueban sin distinguir entre mayúsculas y " "minúsculas." #: changedetectionio/templates/edit/text-options.html -msgid "" -"Trigger text is processed from the result-text that comes out of any " -"CSS/JSON Filters for this monitor" -msgstr "" -"El texto de activación se procesa a partir del texto de resultado que surge " -"de cualquier filtro CSS/JSON para este monitor." +msgid "Trigger text is processed from the result-text that comes out of any CSS/JSON Filters for this monitor" +msgstr "El texto de activación se procesa a partir del texto de resultado que surge de cualquier filtro CSS/JSON para este monitor" #: changedetectionio/templates/edit/text-options.html msgid "Each line is processed separately (think of each line as \"OR\")" @@ -3446,9 +3006,7 @@ msgstr "Cada línea se procesa por separado (piense en cada línea como \"O\")" #: changedetectionio/templates/edit/text-options.html msgid "Note: Wrap in forward slash / to use regex example:" -msgstr "" -"Nota: incluya una barra diagonal / para usar el ejemplo de expresiones " -"regulares:" +msgstr "Nota: incluya una barra diagonal / para usar el ejemplo de expresiones regulares:" #: changedetectionio/templates/edit/text-options.html msgid "You can also use" @@ -3463,43 +3021,28 @@ msgid "\"Page text\" - with Contains, Starts With, Not Contains and many more" msgstr "\"Texto de página\": contiene, comienza con, no contiene y muchos más" #: changedetectionio/templates/edit/text-options.html -msgid "" -"Matching text will be ignored in the text snapshot (you can still see it but" -" it wont trigger a change)" -msgstr "" -"El texto coincidente se ignorará en la instantánea del texto (aún podrás " -"verlo pero no activará un cambio)" +msgid "Matching text will be ignored in the text snapshot (you can still see it but it wont trigger a change)" +msgstr "El texto coincidente se ignorará en la instantánea del texto (aún podrás verlo pero no activará un cambio)" #: changedetectionio/templates/edit/text-options.html msgid "" -"Block change-detection while this text is on the page, all text and regex " -"are tested case-insensitive, good for waiting for when a product is " +"Block change-detection while this text is on the page, all text and regex are tested case-insensitive, good for waiting for when a product is " "available again" msgstr "" -"Bloquear la detección de cambios mientras este texto está en la página, todo" -" el texto y las expresiones regulares se prueban sin distinguir entre " -"mayúsculas y minúsculas, lo cual es bueno para esperar a que un producto " -"vuelva a estar disponible" +"Bloquear la detección de cambios mientras este texto está en la página, todo el texto y las expresiones regulares se prueban sin distinguir entre " +"mayúsculas y minúsculas, lo cual es bueno para esperar a que un producto vuelva a estar disponible" #: changedetectionio/templates/edit/text-options.html -msgid "" -"Block text is processed from the result-text that comes out of any CSS/JSON " -"Filters for this monitor" -msgstr "" -"El texto del bloque se procesa a partir del texto resultante que surge de " -"cualquier filtro CSS/JSON para este monitor." +msgid "Block text is processed from the result-text that comes out of any CSS/JSON Filters for this monitor" +msgstr "El texto del bloque se procesa a partir del texto resultante que surge de cualquier filtro CSS/JSON para este monitor" #: changedetectionio/templates/edit/text-options.html msgid "All lines here must not exist (think of each line as \"OR\")" msgstr "Todas las líneas aquí no deben existir (piense en cada línea como \"O\")" #: changedetectionio/templates/edit/text-options.html -msgid "" -"Extracts text in the final output (line by line) after other filters using " -"regular expressions or string match:" -msgstr "" -"Extrae texto en la salida final (línea por línea) después de otros filtros " -"usando expresiones regulares o coincidencia de cadenas:" +msgid "Extracts text in the final output (line by line) after other filters using regular expressions or string match:" +msgstr "Extrae texto en la salida final (línea por línea) después de otros filtros usando expresiones regulares o coincidencia de cadenas:" #: changedetectionio/templates/edit/text-options.html msgid "Regular expression - example" @@ -3507,7 +3050,7 @@ msgstr "Expresión regular - ejemplo" #: changedetectionio/templates/edit/text-options.html msgid "Don't forget to consider the white-space at the start of a line" -msgstr "No olvides considerar el espacio en blanco al comienzo de una línea." +msgstr "No olvides considerar el espacio en blanco al comienzo de una línea" #: changedetectionio/templates/edit/text-options.html msgid "type flags (more" @@ -3575,8 +3118,7 @@ msgstr "Silenciar notificaciones" #: changedetectionio/templates/menu.html msgid "Notifications are muted - click to unmute" -msgstr "" -"Las notificaciones están silenciadas: haga clic para activar el silencio" +msgstr "Las notificaciones están silenciadas: haga clic para activar el silencio" #: changedetectionio/templates/menu.html msgid "EDIT" @@ -3617,4 +3159,3 @@ msgstr "No" #: changedetectionio/widgets/ternary_boolean.py msgid "Main settings" msgstr "Configuraciones principales" - From c4b890f4fa7beb3eb6780515ba03198ca1300987 Mon Sep 17 00:00:00 2001 From: dgtlmoon <dgtlmoon@gmail.com> Date: Sat, 21 Mar 2026 20:18:05 +0100 Subject: [PATCH 02/11] `last_error` should be cleared if page content was the same and there was no error (#3997) --- changedetectionio/tests/test_backend.py | 25 +++++++++++++++++++++++++ changedetectionio/worker.py | 3 +++ 2 files changed, 28 insertions(+) diff --git a/changedetectionio/tests/test_backend.py b/changedetectionio/tests/test_backend.py index c523999d3..d0713133c 100644 --- a/changedetectionio/tests/test_backend.py +++ b/changedetectionio/tests/test_backend.py @@ -422,3 +422,28 @@ def test_plaintext_even_if_xml_content_and_can_apply_filters(client, live_server assert b'<foobar' not in res.data res = delete_all_watches(client) + + +def test_last_error_cleared_on_same_checksum(client, live_server, datastore_path): + """last_error should be cleared even when content is unchanged (checksumFromPreviousCheckWasTheSame path)""" + set_original_response(datastore_path=datastore_path) + + uuid = client.application.config.get('DATASTORE').add_watch(url=url_for('test_endpoint', _external=True)) + + # First check - establishes baseline checksum + client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) + wait_for_all_checks(client) + + # Inject a stale last_error directly (simulates a prior failed check) + datastore = client.application.config.get('DATASTORE') + datastore.update_watch(uuid=uuid, update_obj={'last_error': 'Some previous error'}) + assert datastore.data['watching'][uuid].get('last_error') == 'Some previous error' + + # Second check - same content, so checksumFromPreviousCheckWasTheSame will fire + client.get(url_for("ui.form_watch_checknow"), follow_redirects=True) + wait_for_all_checks(client) + + # last_error must be cleared even though no change was detected + assert datastore.data['watching'][uuid].get('last_error') == False + + delete_all_watches(client) diff --git a/changedetectionio/worker.py b/changedetectionio/worker.py index 7d04c3eb9..41bcd29cb 100644 --- a/changedetectionio/worker.py +++ b/changedetectionio/worker.py @@ -284,6 +284,9 @@ async def async_update_worker(worker_id, q, notification_q, app, datastore, exec logger.debug(f'[{uuid}] - checksumFromPreviousCheckWasTheSame - Checksum from previous check was the same, nothing todo here.') # Reset the edited flag since we successfully completed the check watch.reset_watch_edited_flag() + # Page was fetched successfully - clear any previous error state + datastore.update_watch(uuid=uuid, update_obj={'last_error': False}) + cleanup_error_artifacts(uuid, datastore) except content_fetchers_exceptions.BrowserConnectError as e: datastore.update_watch(uuid=uuid, From 17002b5b230f2de36b9fb1ab6b63a678e5fd1d95 Mon Sep 17 00:00:00 2001 From: dgtlmoon <dgtlmoon@gmail.com> Date: Tue, 24 Mar 2026 09:32:34 +0100 Subject: [PATCH 03/11] UI - Settings - Dont let 'password' field autocomplete (chrome) --- changedetectionio/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changedetectionio/forms.py b/changedetectionio/forms.py index 8c87d6bf8..06a49b653 100644 --- a/changedetectionio/forms.py +++ b/changedetectionio/forms.py @@ -1005,7 +1005,7 @@ class globalSettingsApplicationForm(commonSettingsForm): render_kw={"placeholder": "0.1", "style": "width: 8em;"} ) - password = SaltyPasswordField(_l('Password')) + password = SaltyPasswordField(_l('Password'), render_kw={"autocomplete": "new-password"}) pager_size = IntegerField(_l('Pager size'), render_kw={"style": "width: 5em;"}, validators=[validators.NumberRange(min=0, From 65517a9c74a0cbe1a4661314470b28131ef5557f Mon Sep 17 00:00:00 2001 From: dgtlmoon <dgtlmoon@gmail.com> Date: Thu, 26 Mar 2026 09:31:41 +0100 Subject: [PATCH 04/11] CVE-2026-33981 - Environment Variable Disclosure via jq env Builtin in Include Filters --- changedetectionio/forms.py | 2 ++ changedetectionio/html_tools.py | 48 +++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/changedetectionio/forms.py b/changedetectionio/forms.py index 06a49b653..e9a72c37e 100644 --- a/changedetectionio/forms.py +++ b/changedetectionio/forms.py @@ -667,9 +667,11 @@ class ValidateCSSJSONXPATHInput(object): # `jq` requires full compilation in windows and so isn't generally available raise ValidationError("jq not support not found") + from changedetectionio.html_tools import validate_jq_expression input = line.replace('jq:', '') try: + validate_jq_expression(input) jq.compile(input) except (ValueError) as e: message = field.gettext('\'%s\' is not a valid jq expression. (%s)') diff --git a/changedetectionio/html_tools.py b/changedetectionio/html_tools.py index 6175282de..500df0c98 100644 --- a/changedetectionio/html_tools.py +++ b/changedetectionio/html_tools.py @@ -4,6 +4,7 @@ from loguru import logger from typing import List import html import json +import os import re # HTML added to be sure each result matching a filter (.example) gets converted to a new line by Inscriptis @@ -13,6 +14,45 @@ PERL_STYLE_REGEX = r'^/(.*?)/([a-z]*)?$' TITLE_RE = re.compile(r"<title[^>]*>(.*?)", re.I | re.S) META_CS = re.compile(r']+charset=["\']?\s*([a-z0-9_\-:+.]+)', re.I) + +# jq builtins that can leak sensitive data or cause harm when user-supplied expressions are executed. +# env/$ENV reads all process environment variables (passwords, API keys, etc.) +# include/import can read arbitrary files from disk +# input/inputs reads beyond the supplied JSON data +# debug/stderr leaks data to stderr +# halt/halt_error terminates the process (DoS) +_JQ_BLOCKED_PATTERNS = [ + (re.compile(r'\benv\b'), 'env (reads environment variables)'), + (re.compile(r'\$ENV\b'), '$ENV (reads environment variables)'), + (re.compile(r'\binclude\b'), 'include (reads files from disk)'), + (re.compile(r'\bimport\b'), 'import (reads files from disk)'), + (re.compile(r'\binputs?\b'), 'input/inputs (reads beyond provided data)'), + (re.compile(r'\bdebug\b'), 'debug (leaks data to stderr)'), + (re.compile(r'\bstderr\b'), 'stderr (leaks data to stderr)'), + (re.compile(r'\bhalt(?:_error)?\b'), 'halt/halt_error (terminates the process)'), + (re.compile(r'\$__loc__\b'), '$__loc__ (leaks file path information)'), + (re.compile(r'\bbuiltins\b'), 'builtins (enumerates available functions)'), + (re.compile(r'\bmodulemeta\b'), 'modulemeta (leaks module information)'), + (re.compile(r'\$JQ_BUILD_CONFIGURATION\b'), '$JQ_BUILD_CONFIGURATION (leaks build information)'), +] + +def validate_jq_expression(expression: str) -> None: + """Raise ValueError if the jq expression uses any dangerous builtin. + + User-supplied jq expressions are executed server-side. Without this check, + builtins like `env` expose every process environment variable (SALTED_PASS, + proxy credentials, API keys, etc.) as watch output. + """ + from changedetectionio.strtobool import strtobool + if strtobool(os.getenv('JQ_ALLOW_RISKY_EXPRESSIONS', 'false')): + return + + for pattern, description in _JQ_BLOCKED_PATTERNS: + if pattern.search(expression): + msg = f"jq expression uses disallowed builtin: {description}" + logger.critical(f"Security: blocked jq expression containing '{description}' - expression: {expression!r}") + raise ValueError(msg) + META_CT = re.compile(r']+http-equiv=["\']?content-type["\']?[^>]*content=["\'][^>]*charset=([a-z0-9_\-:+.]+)', re.I) # 'price' , 'lowPrice', 'highPrice' are usually under here @@ -378,12 +418,16 @@ def _parse_json(json_data, json_filter): raise Exception("jq not support not found") if json_filter.startswith("jq:"): - jq_expression = jq.compile(json_filter.removeprefix("jq:")) + expr = json_filter.removeprefix("jq:") + validate_jq_expression(expr) + jq_expression = jq.compile(expr) match = jq_expression.input(json_data).all() return _get_stripped_text_from_json_match(match) if json_filter.startswith("jqraw:"): - jq_expression = jq.compile(json_filter.removeprefix("jqraw:")) + expr = json_filter.removeprefix("jqraw:") + validate_jq_expression(expr) + jq_expression = jq.compile(expr) match = jq_expression.input(json_data).all() return '\n'.join(str(item) for item in match) From dadc804567a51f803cd6715f7885c11a247915f6 Mon Sep 17 00:00:00 2001 From: dgtlmoon Date: Thu, 26 Mar 2026 09:43:03 +0100 Subject: [PATCH 05/11] Security: XPath json-doc() Arbitrary File Read Bypass ( Similar fix as CVE-2026-29039 ) --- changedetectionio/html_tools.py | 6 ++++++ changedetectionio/tests/test_xpath_selector.py | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/changedetectionio/html_tools.py b/changedetectionio/html_tools.py index 500df0c98..f029ad7a3 100644 --- a/changedetectionio/html_tools.py +++ b/changedetectionio/html_tools.py @@ -70,6 +70,12 @@ _DEFAULT_UNSAFE_XPATH3_FUNCTIONS = [ 'unparsed-text-available', 'doc', 'doc-available', + 'json-doc', + 'json-doc-available', + 'collection', # XPath 2.0+: loads XML node collections from arbitrary URIs + 'uri-collection', # XPath 3.0+: enumerates URIs from resource collections + 'transform', # XPath 3.1: XSLT transformation (currently raises, block proactively) + 'load-xquery-module', # XPath 3.1: loads XQuery modules (currently raises, block proactively) 'environment-variable', 'available-environment-variables', ] diff --git a/changedetectionio/tests/test_xpath_selector.py b/changedetectionio/tests/test_xpath_selector.py index 1e4e601c6..88ce48f0e 100644 --- a/changedetectionio/tests/test_xpath_selector.py +++ b/changedetectionio/tests/test_xpath_selector.py @@ -610,6 +610,11 @@ def test_xpath_blocked_functions_unit(): "unparsed-text-available('file:///etc/passwd')", "doc('file:///etc/passwd')", "doc-available('file:///etc/passwd')", + "json-doc('file:///datastore/changedetection.json')", + "collection('file:///datastore/')", + "uri-collection('file:///datastore/')", + "transform(map{})", + "load-xquery-module('foo')", "environment-variable('PATH')", "available-environment-variables()", ] From f37e448411e36a3bfb3869dccbc2d5af33ccc585 Mon Sep 17 00:00:00 2001 From: Jaroslav Lichtblau Date: Thu, 26 Mar 2026 09:45:23 +0100 Subject: [PATCH 06/11] fix: Czech translation strings updated (#4008) --- .../translations/cs/LC_MESSAGES/messages.po | 128 +++++++++--------- 1 file changed, 63 insertions(+), 65 deletions(-) diff --git a/changedetectionio/translations/cs/LC_MESSAGES/messages.po b/changedetectionio/translations/cs/LC_MESSAGES/messages.po index 204e1867c..43a6c456b 100644 --- a/changedetectionio/translations/cs/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/cs/LC_MESSAGES/messages.po @@ -369,7 +369,7 @@ msgstr "Protokol ladění oznámení" #: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/tags/templates/edit-tag.html #: changedetectionio/blueprint/ui/templates/edit.html msgid "General" -msgstr "Generál" +msgstr "Obecné" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Fetching" @@ -393,7 +393,7 @@ msgstr "RSS" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Backups" -msgstr "Backups" +msgstr "Zálohy" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Time & Date" @@ -409,7 +409,7 @@ msgstr "Info" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Default recheck time for all watches, current system minimum is" -msgstr "Výchozí čas opětovné kontroly pro všechny monitory, aktuální systémové minimum je" +msgstr "Výchozí čas opětovné kontroly pro všechna sledování, aktuální systémové minimum je" #: changedetectionio/blueprint/settings/templates/settings.html msgid "more info" @@ -445,9 +445,7 @@ msgstr "" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Allow access to the watch change history page when password is enabled (Good for sharing the diff page)" -msgstr "" -"Povolit přístup na stránku historie změn monitoru, když je povoleno heslo (Vhodné pro sdílení stránky rozdílů)Povolit" -" anonymní přístup na stránku historie sledování, když je povoleno heslo" +msgstr "Povolit přístup na stránku historie změn monitoru, když je povoleno heslo (Vhodné pro sdílení stránky rozdílů)" #: changedetectionio/blueprint/settings/templates/settings.html msgid "When a request returns no content, or the HTML does not contain any text, is this considered a change?" @@ -455,7 +453,7 @@ msgstr "" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Choose a default proxy for all watches" -msgstr "Vyberte výchozí proxy pro všechny monitory" +msgstr "Vyberte výchozí proxy pro všechna sledování" #: changedetectionio/blueprint/settings/templates/settings.html msgid "Base URL used for the" @@ -479,7 +477,7 @@ msgstr "" #: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "Use the" -msgstr "Použijte" +msgstr "Použít" #: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "Basic" @@ -505,7 +503,7 @@ msgstr "" #: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "This will wait" -msgstr "Tohle počká" +msgstr "Toto počká" #: changedetectionio/blueprint/settings/templates/settings.html changedetectionio/blueprint/ui/templates/edit.html msgid "seconds before extracting the text." @@ -865,7 +863,7 @@ msgstr "povoleny adresy URL pro upozornění v celém systému" #: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "this form will override notification settings for this watch only" -msgstr "tento formulář přepíše nastavení oznámení pouze pro tyto monitory" +msgstr "tento formulář přepíše nastavení oznámení pouze pro tato sledování" #: changedetectionio/blueprint/tags/templates/edit-tag.html changedetectionio/blueprint/ui/templates/edit.html msgid "an empty Notification URL list here will still send notifications." @@ -882,7 +880,7 @@ msgstr "Přidejte novou značku organizace" #: changedetectionio/blueprint/tags/templates/groups-overview.html #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Watch group / tag" -msgstr "Skupina / Značka" +msgstr "Sledovat skupinu / Značka" #: changedetectionio/blueprint/tags/templates/groups-overview.html msgid "Groups allows you to manage filters and notifications for multiple watches under a single organisational tag." @@ -890,15 +888,15 @@ msgstr "" #: changedetectionio/blueprint/tags/templates/groups-overview.html msgid "# Watches" -msgstr "# monitorů" +msgstr "# Sledování" #: changedetectionio/blueprint/tags/templates/groups-overview.html msgid "Tag / Label name" -msgstr "Název štítku / štítku" +msgstr "Tag / Název štítku" #: changedetectionio/blueprint/tags/templates/groups-overview.html msgid "No website organisational tags/groups configured" -msgstr "Žádné skupiny/značky" +msgstr "Žádné skupiny/značky zatím nebyly nastaveny" #: changedetectionio/blueprint/tags/templates/groups-overview.html #: changedetectionio/blueprint/watchlist/templates/watch-overview.html @@ -908,7 +906,7 @@ msgstr "Upravit" #: changedetectionio/blueprint/tags/templates/groups-overview.html #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Recheck" -msgstr "Znovu zkontrolujte" +msgstr "Znovu zkontrolovat" #: changedetectionio/blueprint/tags/templates/groups-overview.html msgid "Delete Group?" @@ -922,7 +920,7 @@ msgstr "" #: changedetectionio/blueprint/tags/templates/groups-overview.html changedetectionio/blueprint/ui/templates/edit.html #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Delete" -msgstr "Vymazat" +msgstr "Smazat" #: changedetectionio/blueprint/tags/templates/groups-overview.html msgid "Deletes and removes tag" @@ -945,36 +943,36 @@ msgstr "Odpojit" #: changedetectionio/blueprint/tags/templates/groups-overview.html msgid "Keep the tag but unlink any watches" -msgstr "Ponechte štítek, ale odpojte všechny monitory" +msgstr "Ponechte štítek, ale odpojte všechna sledování" #: changedetectionio/blueprint/tags/templates/groups-overview.html changedetectionio/blueprint/ui/templates/edit.html msgid "RSS Feed for this watch" -msgstr "RSS kanál pro tyto monitory" +msgstr "RSS kanál pro toto sledování" #: changedetectionio/blueprint/ui/__init__.py #, python-brace-format msgid "{} watches deleted" -msgstr "" +msgstr "{} sledování smazáno" #: changedetectionio/blueprint/ui/__init__.py #, python-brace-format msgid "{} watches paused" -msgstr "{} monitorů pozastaveno" +msgstr "{} sledování pozastaveno" #: changedetectionio/blueprint/ui/__init__.py #, python-brace-format msgid "{} watches unpaused" -msgstr "" +msgstr "{} sledování opět spuštěno" #: changedetectionio/blueprint/ui/__init__.py #, python-brace-format msgid "{} watches updated" -msgstr "" +msgstr "{} sledování aktualizováno" #: changedetectionio/blueprint/ui/__init__.py #, python-brace-format msgid "{} watches muted" -msgstr "{} monitorů ztlumeno" +msgstr "{} sledování ztlumeno" #: changedetectionio/blueprint/ui/__init__.py #, python-brace-format @@ -1013,7 +1011,7 @@ msgstr "Sledujte tuto adresu URL!" #: changedetectionio/blueprint/ui/__init__.py #, python-brace-format msgid "Cleared snapshot history for watch {}" -msgstr "Historie snímků vymazána pro monitor {}" +msgstr "Historie snímků vymazána pro sledování {}" #: changedetectionio/blueprint/ui/__init__.py msgid "History clearing started in background" @@ -1030,7 +1028,7 @@ msgstr "" #: changedetectionio/blueprint/ui/__init__.py msgid "Deleted." -msgstr "Vymazat" +msgstr "Smazáno" #: changedetectionio/blueprint/ui/__init__.py msgid "Cloned, you are editing the new watch." @@ -1047,7 +1045,7 @@ msgstr "" #: changedetectionio/blueprint/ui/__init__.py #, python-brace-format msgid "Queued {} watches for rechecking ({} already queued or running)." -msgstr "Do fronty přidáno {} monitorů k opětovné kontrole ({} již ve frontě nebo běží)." +msgstr "Do fronty přidáno {} sledování k opětovné kontrole ({} již ve frontě nebo běží)." #: changedetectionio/blueprint/ui/__init__.py #, python-brace-format @@ -1056,7 +1054,7 @@ msgstr "Do fronty přidáno {} sledování k opětovné kontrole." #: changedetectionio/blueprint/ui/__init__.py msgid "Queueing watches for rechecking in background..." -msgstr "Přidávání monitorů do fronty pro opětovnou kontrolu na pozadí..." +msgstr "Přidává se sledování do fronty pro opětovnou kontrolu na pozadí..." #: changedetectionio/blueprint/ui/__init__.py #, python-brace-format @@ -1105,7 +1103,7 @@ msgstr "" #: changedetectionio/blueprint/ui/edit.py msgid "Updated watch." -msgstr "Smazat monitory?" +msgstr "Sledování aktualizováno." #: changedetectionio/blueprint/ui/preview.py msgid "Preview unavailable - No fetch/check completed or triggers not reached" @@ -1121,7 +1119,7 @@ msgstr "Možná budete chtít použít" #: changedetectionio/blueprint/ui/templates/clear_all_history.html msgid "BACKUP" -msgstr "BACKUP" +msgstr "ZÁLOHA" #: changedetectionio/blueprint/ui/templates/clear_all_history.html msgid "link first." @@ -1161,11 +1159,11 @@ msgstr "Sdílet jako obrázek" #: changedetectionio/blueprint/ui/templates/diff-offscreen-options.html msgid "Ignore any lines matching" -msgstr "Ignorujte všechny odpovídající řádky" +msgstr "Ignorovat všechny odpovídající řádky" #: changedetectionio/blueprint/ui/templates/diff-offscreen-options.html msgid "Ignore any lines matching excluding digits" -msgstr "Ignorujte všechny odpovídající řádky kromě číslic" +msgstr "Ignorovat všechny odpovídající řádky kromě číslic" #: changedetectionio/blueprint/ui/templates/diff.html msgid "From" @@ -1185,7 +1183,7 @@ msgstr "Řádky" #: changedetectionio/blueprint/ui/templates/diff.html msgid "Ignore Whitespace" -msgstr "Ignorujte mezery" +msgstr "Ignorovat mezery" #: changedetectionio/blueprint/ui/templates/diff.html msgid "Same/non-changed" @@ -1209,7 +1207,7 @@ msgstr "Klávesnice:" #: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "Previous" -msgstr "Náhled" +msgstr "Předchozí" #: changedetectionio/blueprint/ui/templates/diff.html changedetectionio/blueprint/ui/templates/preview.html msgid "Next" @@ -1241,7 +1239,7 @@ msgstr "Aktuální snímek obrazovky" #: changedetectionio/blueprint/ui/templates/diff.html msgid "Extract Data" -msgstr "Extrahujte data" +msgstr "Extrahovat data" #: changedetectionio/blueprint/ui/templates/diff.html msgid "seconds ago." @@ -1269,7 +1267,7 @@ msgstr "NASTAVENÍ" #: changedetectionio/blueprint/ui/templates/diff.html msgid "Goto single snapshot" -msgstr "Přejít na jeden snímek" +msgstr "Přejít na samotný snímek" #: changedetectionio/blueprint/ui/templates/diff.html msgid "Highlight text to share or add to ignore lists." @@ -1359,15 +1357,15 @@ msgstr "" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Check/Scan all" -msgstr "Znovu zkontrolujte vše" +msgstr "Vše znovu zkontrolovat" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Choose a proxy for this watch" -msgstr "RSS kanál pro tyto monitory" +msgstr "Vybrat proxy pro toto sledování" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Using the current global default settings" -msgstr "Použití aktuálního globálního výchozího nastavení" +msgstr "Aktuálně je použito globální výchozí nastavení" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Show advanced options" @@ -1391,7 +1389,7 @@ msgstr "Proměnné jsou podporovány v hodnotách hlavičky požadavku" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Alert! Extra headers file found and will be added to this watch!" -msgstr "Upozornění! Byl nalezen další soubor záhlaví a bude přidán do těchto monitorů!" +msgstr "Upozornění! Byl nalezen další soubor záhlaví a bude přidán do těchto sledování!" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Headers can be also read from a file in your data-directory" @@ -1427,7 +1425,7 @@ msgstr "" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Visual Selector data is not ready, watch needs to be checked atleast once." -msgstr "Data Visual Selector nejsou připravena, monitory je třeba alespoň jednou zkontrolovat." +msgstr "Data Visual Selector nejsou připravena, sledování je třeba alespoň jednou zkontrolovat." #: changedetectionio/blueprint/ui/templates/edit.html msgid "" @@ -1633,11 +1631,11 @@ msgstr "" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Delete Watch?" -msgstr "Smazat monitory?" +msgstr "Smazat sledování?" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Are you sure you want to delete the watch for:" -msgstr "Opravdu chcete smazat monitory pro:" +msgstr "Opravdu chcete smazat sledování pro:" #: changedetectionio/blueprint/ui/templates/edit.html msgid "This action cannot be undone." @@ -1661,15 +1659,15 @@ msgstr "Vymazat historii" #: changedetectionio/blueprint/ui/templates/edit.html msgid "Clone & Edit" -msgstr "Klonovat a upravovat" +msgstr "Duplikovat a upravit" #: changedetectionio/blueprint/ui/templates/preview.html msgid "Select timestamp" -msgstr "Vyberte časové razítko" +msgstr "Vybrat časové razítko" #: changedetectionio/blueprint/ui/templates/preview.html msgid "Go" -msgstr "Jít" +msgstr "Přejít" #: changedetectionio/blueprint/ui/templates/preview.html msgid "Current erroring screenshot from most recent request" @@ -1715,7 +1713,7 @@ msgstr "" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Add a new web page change detection watch" -msgstr "Přidejte nové monitory zjišťování změn webové stránky" +msgstr "Přidejte nové sledování zjišťování změn webové stránky" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Watch this URL!" @@ -1723,7 +1721,7 @@ msgstr "Monitorovat tuto URL!" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Edit first then Watch" -msgstr "Upravit a monitorovat" +msgstr "Nejdříve upravit, poté sledovat" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Pause" @@ -1747,7 +1745,7 @@ msgstr "Štítek" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Mark viewed" -msgstr "Mark zobrazil" +msgstr "Označit jako shlédnuté" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Use default notification" @@ -1775,7 +1773,7 @@ msgstr "Vymazat/resetovat historii" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Delete Watches?" -msgstr "Smazat monitory?" +msgstr "Smazat sledování?" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "

Are you sure you want to delete the selected watches?

This action cannot be undone.

" @@ -1823,7 +1821,7 @@ msgstr "importovat seznam" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Detecting restock and price" -msgstr "Detekce zásob a ceny" +msgstr "Kontrola zásob a ceny" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "In stock" @@ -1876,7 +1874,7 @@ msgstr "Nepřečtený" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Recheck all" -msgstr "Znovu zkontrolujte vše" +msgstr "Znovu zkontrolovat vše" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html #, python-format @@ -2026,7 +2024,7 @@ msgstr "neděle" #: changedetectionio/forms.py msgid "Weeks" -msgstr "týdny" +msgstr "Týdny" #: changedetectionio/forms.py msgid "Should contain zero or more seconds" @@ -2046,7 +2044,7 @@ msgstr "Minuty" #: changedetectionio/forms.py msgid "Seconds" -msgstr "sekundy" +msgstr "Sekundy" #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" @@ -2151,7 +2149,7 @@ msgstr "Nahrajte soubor .xlsx" #: changedetectionio/forms.py msgid "Must be .xlsx file!" -msgstr "Musí to být soubor .xlsx!" +msgstr "Musí být soubor .xlsx!" #: changedetectionio/forms.py msgid "File mapping" @@ -2175,7 +2173,7 @@ msgstr "Interval mezi kontrolami" #: changedetectionio/forms.py msgid "Use global settings for time between check and scheduler." -msgstr "Použijte globální nastavení pro čas mezi kontrolou a plánovačem." +msgstr "Použít globální nastavení pro čas mezi kontrolou a plánovačem." #: changedetectionio/forms.py msgid "CSS/JSONPath/JQ/XPath Filters" @@ -2284,7 +2282,7 @@ msgstr "Připojte snímek obrazovky k oznámení (pokud je to možné)" #: changedetectionio/forms.py msgid "Match" -msgstr "# monitory" +msgstr "Shoda" #: changedetectionio/forms.py msgid "Match all of the following" @@ -2355,11 +2353,11 @@ msgstr "Výchozí proxy" #: changedetectionio/forms.py msgid "Random jitter seconds ± check" -msgstr "Náhodné jitter sekundy ± kontrola" +msgstr "Náhodný rozptyl kontrol ± sekund" #: changedetectionio/forms.py msgid "Number of fetch workers" -msgstr "Počet pracovníků aportů" +msgstr "Počet procesů kontrol" #: changedetectionio/forms.py msgid "Should be between 1 and 50" @@ -2367,15 +2365,15 @@ msgstr "Mělo by být mezi 1 a 50" #: changedetectionio/forms.py msgid "Requests timeout in seconds" -msgstr "Požaduje časový limit v sekundách" +msgstr "Časový limit vypršení kontrol v sekundách" #: changedetectionio/forms.py msgid "Should be between 1 and 999" -msgstr "Mělo by být mezi 1 a 999" +msgstr "Nastavit mezi 1 a 999" #: changedetectionio/forms.py msgid "Default User-Agent overrides" -msgstr "Výchozí přepisy User-Agent" +msgstr "Změna výchozího nastavení hodnoty User-Agent" #: changedetectionio/forms.py msgid "Both a name, and a Proxy URL is required." @@ -2387,11 +2385,11 @@ msgstr "Otevřete stránku „Historie“ na nové kartě" #: changedetectionio/forms.py msgid "Realtime UI Updates Enabled" -msgstr "Aktualizace v reálném čase offline" +msgstr "Aktualizace UI v reálném čase" #: changedetectionio/forms.py msgid "Favicons Enabled" -msgstr "zvážit povolení" +msgstr "Povolit favikony" #: changedetectionio/forms.py msgid "Use page in watch overview list" @@ -2427,7 +2425,7 @@ msgstr "Heslo" #: changedetectionio/forms.py msgid "Pager size" -msgstr "Velikost pageru" +msgstr "Počet položek na stránku" #: changedetectionio/forms.py msgid "Should be atleast zero (disabled)" @@ -2459,7 +2457,7 @@ msgstr "Povolit anonymní přístup na stránku historie sledování, když je p #: changedetectionio/forms.py msgid "Hide muted watches from RSS feed" -msgstr "Skrýt ztlumené monitory ze zdroje RSS" +msgstr "Skrýt ztlumená sledování pro RSS zdroje" #: changedetectionio/forms.py msgid "Enable RSS reader mode " From 05fc88510843059ff7ca74af72c86e01edd8bfae Mon Sep 17 00:00:00 2001 From: dgtlmoon <dgtlmoon@gmail.com> Date: Thu, 26 Mar 2026 09:47:02 +0100 Subject: [PATCH 07/11] Translations - recompiling --- .../translations/cs/LC_MESSAGES/messages.mo | Bin 33415 -> 33660 bytes .../translations/es/LC_MESSAGES/messages.mo | Bin 76927 -> 72812 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/changedetectionio/translations/cs/LC_MESSAGES/messages.mo b/changedetectionio/translations/cs/LC_MESSAGES/messages.mo index 03d1fcba86628cbb1ca00b2617a9d773848f7f73..2794de778071d285f08cb998b49400871d512ab2 100644 GIT binary patch delta 9262 zcmZwL3tW{|y2tT%BZA-+74QP`5~8T6cp)<tQA@m~;yt{?Mz&nt8)0vhox0Uhr;C-d z)6pqQ?c_u=rhc%-yrczWC(}VIyBtkVHqAJVIp!&?Q+j@X-gjoSP9Hve*LwH6*Lv2o zp0(80t`7NeO-SIgwxJsg{`=Zt7;*S`YxVy9-;Z4kBZBTvXkvJRVf4ln?1?k5JFY~1 zwHn*w>(~TOU^t#ajsGd?{cD(H7y%=}v|bp6ZTMh3>cu(O1FKL2zJLm3A2!9eusObi zv+)DW#I!_f;zihjz7IR$6Ig)NcrQlXq0a+`F_T6|9+Y8Ud=&fOe(aAIQ3J&hZWyLx zC=NxfYy>Kxv3NI5LVk=#`K1NCf-Uf4RL1^{1F=n4K4*U8UK)DAgPFJ#$+mF_3D!7+ zDR={0V)tajNX2xF!90w@DvZa+P?@Yo1-u`%HE-IUL<Roe7*Gl?(rAU>+8=~=vjS>? z{1_eirGYb11J6SZ=&=o;0(jEyZ$kyT2Q}_t+Y_jO&!QImKi$Z`269jl?Jx?7!AQ3I z<54d@fX%QJBhiPNa0QOUUt?$d5H;}?Ovjt3RHu`^wpfh4aGBk&P9gsq@E{Kq=}`>D z)2Jf+FVuk7aX5ytq1waI7>0{bpD(dpgIdtj*bM&zV{s=c)Agu8Pa?4ymjX1jm(h%> zKt`fceIG_(2`V6;tsj+<07m2EsN&p?n&<#(i{8gb`~nroW#q@W&M$pGi8N@zfixO= zFdX&833h)j>Wjs8zXFxQ6}CatvD|^m)B#jRK1Kz6&hCGK;q<>kO?VYUFoad}{eaPw zhW5S_YQ=qU2;PMzda*BVKn+xn8t6DS#WQyQb5sCVusL2w)ktV>>v+eYGLVMK)NCB8 z^It(jFYd+`_!erQKOsNHX?`gap?$2CwnSy3Cu*g`Fbzi{SA|i53Ahnk;cKY(>QNKF zi(CQ5=NQ5KMi|RW!8WKB4z~LvP+u%YWypiw@FCR7U&ct>ZTAnLGWaGc;A7YlKfu=b zIqF{d29=>Gq7G=FcpADQlWa3kdvrhQW}JfxtP+)(<*12PBR|HI{8CjPv7eto1^gxI z`#+!-(!QUSxsIrLQ~QyBebAo=au90bp%{h3@h;59R`@7tWt%Yyx1+Ayy*L9eBXb#} zxwkd(V$_zdN8O~)p%!uk6~H_F$-f3V!GkP3k8Lq!fOWivppI8IDs{!E8|)F(UT(#9 zxDS=;_pk?kiWIsL%I%}~(oo}%K`rnp)K&%q_JjR6m<NY28LuHfMm*P;iBnK1uRx`G z8S0d5M%BQFsLY&4t?VM|SYAdgsKuRz!H<!^uS}eQs)@jFXecGWLk+MCHNZYp<ZqxR zK8;G{dAolJQ|Mnqy>AY(-s^^1NE&K_VpPreQAM{BGjScVB?03E4ei-Kun8uz;o7TY zRODG0i#ez*C`ax2di(SDP#HOgs*(Ri?R_Ls=y_Mv0y9wojKLV3hP`$EOK7y=!Di&U z#>=RIE@0zvL9HZ;S!E(>z<#JbAB-I_3zb19YJy_adn-|ydjvJ^MpR%gVpE;}H)&|# zqo{#CLVe*1YQP()0K?gE^*f+WOCq+%ZWxV2P?^j|rF<23z(-J9xE&SHA5in{#ek~6 zj)o>Ujf(Iu_6y&kNk43;HF0+wO+O8_!o{fXKY<ElD{A6b?dJzk<DEdAlC!8SxPsc^ zpLG9rrjanrx`2kD`ZMqjEXS_60d-~Ww?F?3wc;O8wb3TSx^h$S9{OWYD_@7o*bY>Y z?m`9fDk{+b%pm`q5Tk(yD!#DcRwg1*DeH_%buwxtJyGusMrB|ars6d0iz`uq?LmG2 zD5{80Vmy9<+JcZw!x)E=0U8>3I<n11J}TnpQK@<fHNalf#79v99Yd|C0hO`SsEg$r zRAArQwisc(mxNt--UBt?7)-{%Od5)487eiaQ4?%N)x>kC3uYH8fc>Zd-$1>06xmMW zJyc2~Mq1;wLG?SJPDui)Mta-NM<VkEjIlHnQ8ucWa#0hNqxP^8m4PRblW1(WpP#|* z^uI*~9zV*OxF7P!7>xSfQq;IlVh`Mgci=JXrStzaje$JqbdU8Hgh{9r`cZqd9+U74 z#-aZ8py%<ZEht1y;6@#*6}C^I0^Ewq@H?oQXh3D~Q*1o{7idry#zoYg_ZV#roQ_TC z4?$J=aMT1dQSTL?R$hTkaV=`#b*Kz%M1B7g)O~Um!|-pY%v{07KmS9stQABeKSmtC z^o4v3#YLz+thAp$jM}pGs7!6eaQq|cy~7xS$5HP!pe8<ts;MtgHFYhE{A(p4W2_fj zp;8o&nz%cLV=DH<fvEQ%Kn+}Cf9|)Rud@43*!_*Dg=|M{;Vx7WzK_ZH*D>sWGa9YN zS`)^iQW}R8w2_8-u^ba{6Q<!l)VaTiy0T*^2-QX!ns^^}M>lF~Hexq?7PX*S)D|2I z&`?S~Llx0w9Dt7TRv_u97suis9Q;)bmEwr|tbk%Mh5jH^pt-2(UW2NYYSfBfN7cd! zjKouDV&E(dT|76iCk~!yWg;IHX%T9`MW~ECjXIX6u_a!{2>c1PfbdC%F$+6l4wj>~ z@;K@SJcYW5{()6G|E(u;`|;orR0_{wC;Sl=P;9o9x{=5&Z4{yQ@+DM&@1ausf!+TU zwZhNQLB=kjQh#}h_1F2Bsa9t0!2vq|(`aPz!mqFgHlT{;2b_)J)2zQ2%tu{7&!RGR z8rxwM(W{?~T`?D1<7(RtwlAUreifCuLz4N8V>Fb)Pf!D1K%Mt%*a}<Euxg+SrqS<* ziI|7liic4XZow$rX?qyk&_8MWx&8dAZPS_LU)38+LlN~uO*kC21rxCk7NI8Egza$; zHpjP7fuBN6d<Mti*Qh^~22%)nJ{`4n1-3g-Tm9!*<i9_Sko)aww;gLc7ge>3P%HPL zR=NY{;cGYqqjRhaCL8tnEL0{7ZI_~s`BT^lH=}B1Zw~p7p|PI_{qQ8}I5lD8RYa-S zc)U=V$wlp<$96GB(+{9d$p+Nc?8DCZDQd#+P~%0-v5Z5F+dV)-5l^<wwJk&K-3pAu z^{AqJ1!M7m?fa+zzCx|oG1s~mqET0FI&uh%p{T$!Y)7NECNPnPQj?2uScJ;R8vBJU zIEwx*?1fixGA59JeXk5Pa20C8m8b>%3bo=*wlAO-^a}RG!+5vO|KIEf$q(?a96p$g zdhrF@y{LieQN`GRn(!v-W(?1@R?-P|(WIibvLEV3oR2!zkD%VKLB01jcGmenMq>aE z{(?$zXQy@3rJ(x7cqcAKRr@R01@~b(euN6BWuCS2XjH8vqrN}Tb_6PbiI{*+Z2bR! zD`|A(!S7L3S&!ZE7!Jg%7=kJDt)l9MN_7@0pozA#Pyyv(5^h3e@*sA=<EYyC5*6?b z3@D<oeCt6+)WC^$KLs^$8md?ZpfYhU>U&F3D|`}7d=@#{#v$}#jLSN<kKrBk52Egw zbEq1)<Rbst+YSq?Jx)RuPam9!8K{ZZp{o3OOu|=DDf|RgwBKVq#uQkA4MdHbh1%LF zn2Bpp890i=@LU1=uNB4@T7RCK7*78_%)se*7d~x!993LlMOGkpp;j^nb!yh4&i!-P z6!+U6K?V3W>OS}aN8rr>4Xt!Uv9;2tPyuX5U9m4?D87cOkpmckAEGjI4x8Z>OvWEj z6PqR0d)<&@W~8BtvIHa1kIHmlH4QE&V*?JxD>xQ=m0DM?54+N@Lhbo;sMPO4ZN*6( zjo+dI9J<ij>lvt`t3n0#Ycz2mYMf7ytq2%@w?7DVTU(Hf+UqH(Jt{=4bO$PseW;u6 zEVjfesEpjSjqq4ka68mW(@`~&iOSSm+XaoX{~j8B_+SZYpx>b)-(&kOYM=|YU!wx} z9>cI@nYCr@Q8f^Ux*rDMD4c?NZzHDQ7Sud%V>t604K%cpk5L1Ei3;EcY=i9<S$4(V z^waJBd>l^Siz=?Yr~po(R(uhgV_3PhfVQa2#-rXJfPvODvT10KoT%zti`vWWs4pDE z9(W3S;*WN}dxiB^t8CPYm!Qu1Z|weloJ#)_)T!vrrJ#VuqB1(&%l_+&xjazS2XH8^ zMeS7`DuCmtlwClbhD+EMzriNh)Mr(91S-G|n2MuN3o1i>|1s3W8&LCZ^^t!~beIP@ z_zt$fq)O|iOGABLfO=kr+L~pki8rDG`Yr0%J&zjrMby1ghbA6HZQWl{@5L;(Y9TH_ zBZ>$2qN;r+Dia$}DcgdY=yg<$9Ks|#W<S4-s*$U9KXi$8aWzAYn}zN1e$=>b)ccj# z4g+gxXy9k;7phSc@4;w1j>^CVRMGq$yJ2LNb?*D2j^z^Uk6TcmH=w?E4YSbjTi+jp zF?1K;ojU)^XsBrRVqg3SGcf!?{#Apcu@f%GIk*}1{&$#w9hX{LHyBl1Pov)7iXHI) zY9Sw@j`>%p40KwijIjT`XeiPFsB=0L2jeJI(JVvl*;>?AtV8YbdQ@t6qf%RsjTytn zVnr3(C7guU(Sc)@TU#>@8_)k78YUm)qXJlss_w^eG(L}t_)GiqYp5-|fhx)tEJ71? z#Ln0im5EGL4NO2yJP-A~T)XeafF6|5(8SBJ6|P3@(bK4je~-%0LDazYn20A)E4_*x z@F&!JF)OTq5>T1xiMnU{qsAMF+QO+T$iF74<N?KCtV5-`4t1>FMSbB<I04UN8ungk zO*jwlqQ4kbe7jK@xPWnZ6MJFYD(jE!F{ttVXyS@hd|NBp#)DYgX<LsfqO*7}UdIH? zc*v^ac@NdR+vQBJ@O)RP%j?Py{&w7~ZVxUq7dyT43tbha&t2y9Rk-qvTc4HXJ9)L{ z%DCN*=2J^u`JT$!ZSLBgH7`$i!qL3qmIs*=qi%Z;%$am3SUS1k)|Z0!WEVx})UKQ` ziT{(AQ&#tk*T|{eR_ZCNs(CXzCNy?N{Wh2BcY7**roY7F_Lh4}J(W&x@ayTL`#Q~A zW;13~<&`_VW?8vsNtJ$^UXRyv>l-z*XN27zPvOk?cK7(oN{dP~rs*_&W#!JwqMA)J z_c+3G7S=uEb_Uz{W5dltPrlpZ4d&cGzU6I`26x?`>zEph%8BoBODMyQsSBNc2K>b{ z66Fa_&bg!6cxx%nU{%ihT_(DU^XoU)?yPj#0eDl*GLN^mx^aNu+}STgG{#5Xox$&C zC$^dFsq~Z<dCdg`OH!(WL+89UXi}bQzPq;C$SU>ZkwJFETu@Z%Ew3^r*Kc+e*Y5QG zt6{oXg>#|D>#jW%Oq#noZriP)HYRV%)TyRFzuZ&o3LcreA-Zw?g)YB~;l>uYJ>`v? z&@eAGcygXu^V+=c9k(Z@=Jnk5j)X~mx3g{?ffhSU*owl^+Uk6_kA)di$*8j?FE7GT z<DTE(h&4%9?aqa!+m%;UT19*nUT3AtT{FxT6Vl2v-&Ik+%e1$@##L~{(P^@$Zk>zW zrX1?uaFsN!$XiZ+OM(N6zG<!{=g%+n_-l6tQ;V+!mz5+2N0t<}HY;4WE;abal4S#a zRwl;8+HKnJ+Cyf!$6w~HD*flo=39ICeu>YWA9R&A+&z7)S!tHL8gpH}(5zeMtZ*4Q zzbMuJ=TVJ!q2G~M_qelyvvbHSEm}y9Dyz!MDR%AKKUW&&8RVe6GRjh$P}()_vV)HB ziH)f#s=2c~GNi>cXMx$*Bw)X*vL@R*!4cy1)NJ)V7Sie8$Ix_^czw>&B7fsK_4Ene zy`;Da)ewAXNo}K^s^y6zct;DVd&VqwkyT&)8%3O+f`8RgaK)17n(qGAw;!O42R~@t zIFpLK#8+12_60jEecUmv=EbGwo3wWR>;SG`@vvjaEr-Ia;GF18=zh8Nx!+srTj=`5 f^WeZ$Q!{?{sz-N*SyASz-{$4O{$i-xS8x0uHS5pg delta 8982 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 diff --git a/changedetectionio/translations/es/LC_MESSAGES/messages.mo b/changedetectionio/translations/es/LC_MESSAGES/messages.mo index 30687b1a761602168fab2aecbda3662ea6f6daa1..c730a19ba89506702d07465aadca31406a1a4dc3 100644 GIT binary patch delta 12595 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 delta 16764 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 GkNY2+YSEei From 4ba5f6a003b79df52eb4fa8862e71bd32feac2fe Mon Sep 17 00:00:00 2001 From: dgtlmoon <dgtlmoon@gmail.com> Date: Thu, 26 Mar 2026 09:50:02 +0100 Subject: [PATCH 08/11] 0.54.7 --- changedetectionio/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changedetectionio/__init__.py b/changedetectionio/__init__.py index e734556c5..8a0cc8862 100644 --- a/changedetectionio/__init__.py +++ b/changedetectionio/__init__.py @@ -2,7 +2,7 @@ # Read more https://github.com/dgtlmoon/changedetection.io/wiki # Semver means never use .01, or 00. Should be .1. -__version__ = '0.54.6' +__version__ = '0.54.7' from changedetectionio.strtobool import strtobool from json.decoder import JSONDecodeError From f8236848ba52b3338bb9b6332056a4b8275db3f5 Mon Sep 17 00:00:00 2001 From: dgtlmoon <dgtlmoon@gmail.com> Date: Thu, 26 Mar 2026 19:23:51 +0100 Subject: [PATCH 09/11] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index d15b1dece..6a7ef19c4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,7 +28,7 @@ services: # - PLAYWRIGHT_DRIVER_URL=ws://browser-sockpuppet-chrome:3000 # # - # Alternative WebDriver/selenium URL, do not use "'s or 's! (old, deprecated, does not support screenshots very well) + # Alternative WebDriver/selenium URL, do not use "'s or 's! (old, deprecated, does not support screenshots very well, cant detect 404/403/non-200s etc) # - WEBDRIVER_URL=http://browser-selenium-chrome:4444/wd/hub # # WebDriver proxy settings webdriver_proxyType, webdriver_ftpProxy, webdriver_noProxy, From 9a10353d615f1be7d55f7789a9ffc2d9bdd7ed73 Mon Sep 17 00:00:00 2001 From: dgtlmoon <dgtlmoon@gmail.com> Date: Thu, 26 Mar 2026 22:24:35 +0100 Subject: [PATCH 10/11] Update docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 6a7ef19c4..0fba35146 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,7 +28,7 @@ services: # - PLAYWRIGHT_DRIVER_URL=ws://browser-sockpuppet-chrome:3000 # # - # Alternative WebDriver/selenium URL, do not use "'s or 's! (old, deprecated, does not support screenshots very well, cant detect 404/403/non-200s etc) + # Alternative WebDriver/selenium URL, do not use "'s or 's! (old, deprecated, does not support screenshots very well, Can't handle custom headers etc) # - WEBDRIVER_URL=http://browser-selenium-chrome:4444/wd/hub # # WebDriver proxy settings webdriver_proxyType, webdriver_ftpProxy, webdriver_noProxy, From 0ad4090d688924ea8e2c4b403b79827ce1bdf589 Mon Sep 17 00:00:00 2001 From: dgtlmoon <dgtlmoon@gmail.com> Date: Fri, 27 Mar 2026 12:28:13 +0100 Subject: [PATCH 11/11] Extendable theme pluggy implementation for main theme/template `<head>` section (#4011) --- .../test-stack-reusable-workflow.yml | 4 + changedetectionio/flask_app.py | 5 ++ changedetectionio/pluggy_interface.py | 76 ++++++++++++++++- changedetectionio/templates/base.html | 4 + .../tests/plugins/test_html_head_extras.py | 83 +++++++++++++++++++ 5 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 changedetectionio/tests/plugins/test_html_head_extras.py diff --git a/.github/workflows/test-stack-reusable-workflow.yml b/.github/workflows/test-stack-reusable-workflow.yml index 959b4c657..67cb0535e 100644 --- a/.github/workflows/test-stack-reusable-workflow.yml +++ b/.github/workflows/test-stack-reusable-workflow.yml @@ -587,6 +587,10 @@ jobs: run: | docker run -e EXTRA_PACKAGES=changedetection.io-osint-processor test-changedetectionio bash -c 'cd changedetectionio;pytest -vvv -s tests/plugins/test_processor.py::test_check_plugin_processor' + - name: Plugin get_html_head_extras hook injects into base.html + run: | + docker run test-changedetectionio bash -c 'cd changedetectionio;pytest -vvv -s tests/plugins/test_html_head_extras.py' + # Container startup tests container-tests: runs-on: ubuntu-latest diff --git a/changedetectionio/flask_app.py b/changedetectionio/flask_app.py index 2809ed01c..eb962b122 100644 --- a/changedetectionio/flask_app.py +++ b/changedetectionio/flask_app.py @@ -212,6 +212,11 @@ def _is_safe_valid_url(test_url): from .validate_url import is_safe_valid_url return is_safe_valid_url(test_url) +@app.template_global('get_html_head_extras') +def _get_html_head_extras(): + from .pluggy_interface import collect_html_head_extras + return collect_html_head_extras() + @app.template_filter('format_number_locale') def _jinja2_filter_format_number_locale(value: float) -> str: diff --git a/changedetectionio/pluggy_interface.py b/changedetectionio/pluggy_interface.py index 07cd46727..1e7f40d85 100644 --- a/changedetectionio/pluggy_interface.py +++ b/changedetectionio/pluggy_interface.py @@ -174,6 +174,64 @@ class ChangeDetectionSpec: """ pass + @hookspec + def get_html_head_extras(): + """Return HTML to inject into the <head> of every page via base.html. + + Plugins can use this to add <script>, <style>, or <link> tags that should + be present on all pages. Return a raw HTML string or None. + + IMPORTANT: Always use Flask's url_for() for any src/href URLs so that + sub-path deployments (nginx reverse proxy with USE_X_SETTINGS / X-Forwarded-Prefix) + work correctly. This hook is called inside a request context so url_for() is + always available. + + For small amounts of CSS/JS, return them inline — no file-serving needed:: + + from changedetectionio.pluggy_interface import hookimpl + + @hookimpl + def get_html_head_extras(self): + return ( + '<style>.my-module-banner { color: red; }</style>\\n' + '<script>console.log("my_module_content loaded");</script>' + ) + + For larger assets, register your own lightweight Flask routes in the plugin + module and point to them with url_for() so the sub-path prefix is handled + automatically:: + + from flask import url_for, Response + from changedetectionio.pluggy_interface import hookimpl + from changedetectionio.flask_app import app as _app + + MY_CSS = ".my-module-example { color: red; }" + MY_JS = "console.log('my_module_content loaded');" + + @_app.route('/my_module_content/css') + def my_module_content_css(): + return Response(MY_CSS, mimetype='text/css', + headers={'Cache-Control': 'max-age=3600'}) + + @_app.route('/my_module_content/js') + def my_module_content_js(): + return Response(MY_JS, mimetype='application/javascript', + headers={'Cache-Control': 'max-age=3600'}) + + @hookimpl + def get_html_head_extras(self): + css = url_for('my_module_content_css') + js = url_for('my_module_content_js') + return ( + f'<link rel="stylesheet" href="{css}">\\n' + f'<script src="{js}" defer></script>' + ) + + Returns: + str or None: Raw HTML string to inject inside <head>, or None + """ + pass + # Set up Plugin Manager plugin_manager = pluggy.PluginManager(PLUGIN_NAMESPACE) @@ -606,4 +664,20 @@ def apply_update_finalize(update_handler, watch, datastore, processing_exception except Exception as e: # Don't let plugin errors crash the worker logger.error(f"Error in update_finalize hook: {e}") - logger.exception(f"update_finalize hook exception details:") \ No newline at end of file + logger.exception(f"update_finalize hook exception details:") + + +def collect_html_head_extras(): + """Collect and combine HTML head extras from all plugins. + + Called from a Flask template global so it always runs inside a request context. + This means url_for() works correctly in plugin implementations, including when the + app is deployed under a sub-path via USE_X_SETTINGS / X-Forwarded-Prefix (ProxyFix + sets SCRIPT_NAME so url_for() automatically prepends the prefix). + + Returns: + str: Combined HTML string to inject inside <head>, or empty string + """ + results = plugin_manager.hook.get_html_head_extras() + parts = [r for r in results if r] + return "\n".join(parts) if parts else "" \ No newline at end of file diff --git a/changedetectionio/templates/base.html b/changedetectionio/templates/base.html index aa49b8a1b..b323155f8 100644 --- a/changedetectionio/templates/base.html +++ b/changedetectionio/templates/base.html @@ -45,6 +45,10 @@ <script src="{{url_for('static_content', group='js', filename='socket.io.min.js')}}"></script> <script src="{{url_for('static_content', group='js', filename='realtime.js')}}" defer></script> {% endif %} + {%- set _html_head_extras = get_html_head_extras() -%} + {%- if _html_head_extras %} + {{ _html_head_extras | safe }} + {%- endif %} </head> <body class="{{extra_classes}}"> diff --git a/changedetectionio/tests/plugins/test_html_head_extras.py b/changedetectionio/tests/plugins/test_html_head_extras.py new file mode 100644 index 000000000..84cebb81c --- /dev/null +++ b/changedetectionio/tests/plugins/test_html_head_extras.py @@ -0,0 +1,83 @@ +"""Test that plugins can inject HTML into base.html <head> via get_html_head_extras hookimpl.""" +import pytest +from flask import url_for, Response + +from changedetectionio.pluggy_interface import hookimpl, plugin_manager + +_MY_JS = "console.log('my_module_content loaded');" +_MY_CSS = ".my-module-example { color: red; }" + + +class _HeadExtrasPlugin: + """Test plugin that injects tags pointing at its own Flask routes.""" + + @hookimpl + def get_html_head_extras(self): + css_url = url_for('test_plugin_my_module_content_css') + js_url = url_for('test_plugin_my_module_content_js') + return ( + f'<link rel="stylesheet" id="test-head-extra-css" href="{css_url}">\n' + f'<script id="test-head-extra-js" src="{js_url}" defer></script>' + ) + + +@pytest.fixture(scope='module') +def plugin_routes(live_server): + """Register plugin asset routes once per module (Flask routes can't be added twice).""" + app = live_server.app + + @app.route('/test-plugin/my_module_content/css') + def test_plugin_my_module_content_css(): + return Response(_MY_CSS, mimetype='text/css', + headers={'Cache-Control': 'max-age=3600'}) + + @app.route('/test-plugin/my_module_content/js') + def test_plugin_my_module_content_js(): + return Response(_MY_JS, mimetype='application/javascript', + headers={'Cache-Control': 'max-age=3600'}) + + +@pytest.fixture +def head_extras_plugin(plugin_routes): + """Register the hookimpl for one test then unregister it — function-scoped for clean isolation.""" + plugin = _HeadExtrasPlugin() + plugin_manager.register(plugin, name="test_head_extras") + yield plugin + plugin_manager.unregister(name="test_head_extras") + + +def test_plugin_html_injected_into_head(client, live_server, measure_memory_usage, datastore_path, head_extras_plugin): + """get_html_head_extras output must appear inside <head> in the rendered page.""" + res = client.get(url_for("watchlist.index"), follow_redirects=True) + assert res.status_code == 200 + assert b'id="test-head-extra-css"' in res.data, "Plugin <link> tag missing from rendered page" + assert b'id="test-head-extra-js"' in res.data, "Plugin <script> tag missing from rendered page" + + head_end = res.data.find(b'</head>') + assert head_end != -1 + for marker in (b'id="test-head-extra-css"', b'id="test-head-extra-js"'): + pos = res.data.find(marker) + assert pos != -1 and pos < head_end, f"{marker} must appear before </head>" + + +def test_plugin_js_route_returns_correct_content(client, live_server, measure_memory_usage, datastore_path, plugin_routes): + """The plugin-registered JS route must return JS with the right Content-Type.""" + res = client.get(url_for('test_plugin_my_module_content_js')) + assert res.status_code == 200 + assert 'javascript' in res.content_type + assert _MY_JS.encode() in res.data + + +def test_plugin_css_route_returns_correct_content(client, live_server, measure_memory_usage, datastore_path, plugin_routes): + """The plugin-registered CSS route must return CSS with the right Content-Type.""" + res = client.get(url_for('test_plugin_my_module_content_css')) + assert res.status_code == 200 + assert 'css' in res.content_type + assert _MY_CSS.encode() in res.data + + +def test_no_extras_without_plugin(client, live_server, measure_memory_usage, datastore_path): + """With no hookimpl registered the markers must not appear (isolation check).""" + res = client.get(url_for("watchlist.index"), follow_redirects=True) + assert b'id="test-head-extra-css"' not in res.data + assert b'id="test-head-extra-js"' not in res.data