Merge branch 'master' into feature/locale_on_status_page

This commit is contained in:
Wampie Driessen 2023-08-10 11:50:44 +02:00 committed by GitHub
commit f6e7da67fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 899 additions and 590 deletions

View file

@ -18,6 +18,7 @@ README.md
.vscode
.eslint*
.stylelint*
/.devcontainer
/.github
yarn.lock
app.json
@ -35,6 +36,7 @@ tsconfig.json
/extra/healthcheck
extra/exe-builder
### .gitignore content (commented rules are duplicated)
#node_modules

View file

@ -0,0 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE monitor
ADD gamedig_given_port_only BOOLEAN default 1 not null;
COMMIT;

1017
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "uptime-kuma",
"version": "1.22.1",
"version": "1.23.0-beta.1",
"license": "MIT",
"repository": {
"type": "git",

View file

@ -80,6 +80,7 @@ class Database {
"patch-add-certificate-expiry-status-page.sql": true,
"patch-monitor-oauth-cc.sql": true,
"patch-add-timeout-monitor.sql": true,
"patch-add-gamedig-given-port.sql": true,
"patch-status-page-locale-selector.sql": true,
};

View file

@ -135,6 +135,7 @@ class Monitor extends BeanModel {
radiusCalledStationId: this.radiusCalledStationId,
radiusCallingStationId: this.radiusCallingStationId,
game: this.game,
gamedigGivenPortOnly: this.getGameDigGivenPortOnly(),
httpBodyEncoding: this.httpBodyEncoding,
jsonPath: this.jsonPath,
expectedValue: this.expectedValue,
@ -280,6 +281,10 @@ class Monitor extends BeanModel {
return JSON.parse(this.accepted_statuscodes_json);
}
getGameDigGivenPortOnly() {
return Boolean(this.gamedigGivenPortOnly);
}
/**
* Start monitor
* @param {Server} io Socket server instance
@ -429,7 +434,7 @@ class Monitor extends BeanModel {
const options = {
url: this.url,
method: (this.method || "get").toLowerCase(),
timeout: this.timeout,
timeout: this.timeout * 1000,
headers: {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"User-Agent": "Uptime-Kuma/" + version,
@ -649,7 +654,7 @@ class Monitor extends BeanModel {
}
let res = await axios.get(steamApiUrl, {
timeout: this.timeout,
timeout: this.timeout * 1000,
headers: {
"Accept": "*/*",
"User-Agent": "Uptime-Kuma/" + version,
@ -687,7 +692,7 @@ class Monitor extends BeanModel {
type: this.game,
host: this.hostname,
port: this.port,
givenPortOnly: true,
givenPortOnly: this.getGameDigGivenPortOnly(),
});
bean.msg = state.name;

View file

@ -49,7 +49,7 @@ if (! process.env.NODE_ENV) {
}
log.info("server", "Node Env: " + process.env.NODE_ENV);
log.info("server", "Inside Container: " + process.env.UPTIME_KUMA_IS_CONTAINER === "1");
log.info("server", "Inside Container: " + (process.env.UPTIME_KUMA_IS_CONTAINER === "1"));
log.info("server", "Importing Node libraries");
const fs = require("fs");
@ -641,6 +641,10 @@ let needSetup = false;
let notificationIDList = monitor.notificationIDList;
delete monitor.notificationIDList;
// Ensure status code ranges are strings
if (!monitor.accepted_statuscodes.every((code) => typeof code === "string")) {
throw new Error("Accepted status codes are not all strings");
}
monitor.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes);
delete monitor.accepted_statuscodes;
@ -706,6 +710,11 @@ let needSetup = false;
removeGroupChildren = true;
}
// Ensure status code ranges are strings
if (!monitor.accepted_statuscodes.every((code) => typeof code === "string")) {
throw new Error("Accepted status codes are not all strings");
}
bean.name = monitor.name;
bean.description = monitor.description;
bean.parent = monitor.parent;
@ -775,6 +784,7 @@ let needSetup = false;
bean.kafkaProducerAllowAutoTopicCreation = monitor.kafkaProducerAllowAutoTopicCreation;
bean.kafkaProducerSaslOptions = JSON.stringify(monitor.kafkaProducerSaslOptions);
bean.kafkaProducerMessage = monitor.kafkaProducerMessage;
bean.gamedigGivenPortOnly = monitor.gamedigGivenPortOnly;
bean.validate();

View file

@ -720,7 +720,6 @@ exports.checkCertificate = function (res) {
* @param {number} status The status code to check
* @param {string[]} acceptedCodes An array of accepted status codes
* @returns {boolean} True if status code within range, false otherwise
* @throws {Error} Will throw an error if the provided status code is not a valid range string or code string
*/
exports.checkStatusCode = function (status, acceptedCodes) {
if (acceptedCodes == null || acceptedCodes.length === 0) {
@ -728,6 +727,11 @@ exports.checkStatusCode = function (status, acceptedCodes) {
}
for (const codeRange of acceptedCodes) {
if (typeof codeRange !== "string") {
log.error("monitor", `Accepted status code not a string. ${codeRange} is of type ${typeof codeRange}`);
continue;
}
const codeRangeSplit = codeRange.split("-").map(string => parseInt(string));
if (codeRangeSplit.length === 1) {
if (status === codeRangeSplit[0]) {
@ -738,7 +742,8 @@ exports.checkStatusCode = function (status, acceptedCodes) {
return true;
}
} else {
throw new Error("Invalid status code range");
log.error("monitor", `${codeRange} is not a valid status code range`);
continue;
}
}

View file

@ -5,15 +5,24 @@
v-for="(beat, index) in shortBeatList"
:key="index"
class="beat"
:class="{ 'empty' : (beat === 0), 'down' : (beat.status === 0), 'pending' : (beat.status === 2), 'maintenance' : (beat.status === 3) }"
:class="{ 'empty': (beat === 0), 'down': (beat.status === 0), 'pending': (beat.status === 2), 'maintenance': (beat.status === 3) }"
:style="beatStyle"
:title="getBeatTitle(beat)"
/>
</div>
<div
v-if="size !== 'small' && beatList.length > 4 && $root.styleElapsedTime !== 'none'"
class="d-flex justify-content-between align-items-center word" :style="timeStyle"
>
<div>{{ timeSinceFirstBeat }} ago</div>
<div v-if="$root.styleElapsedTime === 'with-line'" class="connecting-line"></div>
<div>{{ timeSinceLastBeat }}</div>
</div>
</div>
</template>
<script>
import dayjs from "dayjs";
export default {
props: {
@ -56,8 +65,30 @@ export default {
}
},
/**
* Calculates the amount of beats of padding needed to fill the length of shortBeatList.
*
* @return {number} The amount of beats of padding needed to fill the length of shortBeatList.
*/
numPadding() {
if (!this.beatList) {
return 0;
}
let num = this.beatList.length - this.maxBeat;
if (this.move) {
num = num - 1;
}
if (num > 0) {
return 0;
}
return -1 * num;
},
shortBeatList() {
if (! this.beatList) {
if (!this.beatList) {
return [];
}
@ -115,6 +146,53 @@ export default {
};
},
/**
* Returns the style object for positioning the time element.
* @return {Object} The style object containing the CSS properties for positioning the time element.
*/
timeStyle() {
return {
"margin-left": this.numPadding * (this.beatWidth + this.beatMargin * 2) + "px",
};
},
/**
* Calculates the time elapsed since the first valid beat.
*
* @return {string} The time elapsed in minutes or hours.
*/
timeSinceFirstBeat() {
const firstValidBeat = this.shortBeatList.at(this.numPadding);
const minutes = dayjs().diff(dayjs.utc(firstValidBeat?.time), "minutes");
if (minutes > 60) {
return (minutes / 60).toFixed(0) + "h";
} else {
return minutes + "m";
}
},
/**
* Calculates the elapsed time since the last valid beat was registered.
*
* @return {string} The elapsed time in a minutes, hours or "now".
*/
timeSinceLastBeat() {
const lastValidBeat = this.shortBeatList.at(-1);
const seconds = dayjs().diff(dayjs.utc(lastValidBeat?.time), "seconds");
let tolerance = 60 * 2; // default for when monitorList not available
if (this.$root.monitorList[this.monitorId] != null) {
tolerance = this.$root.monitorList[this.monitorId].interval * 2;
}
if (seconds < tolerance) {
return "now";
} else if (seconds < 60 * 60) {
return (seconds / 60).toFixed(0) + "m ago";
} else {
return (seconds / 60 / 60).toFixed(0) + "h ago";
}
}
},
watch: {
beatList: {
@ -133,14 +211,14 @@ export default {
},
beforeMount() {
if (this.heartbeatList === null) {
if (! (this.monitorId in this.$root.heartbeatList)) {
if (!(this.monitorId in this.$root.heartbeatList)) {
this.$root.heartbeatList[this.monitorId] = [];
}
}
},
mounted() {
if (this.size === "small") {
if (this.size !== "big") {
this.beatWidth = 5;
this.beatHeight = 16;
this.beatMargin = 2;
@ -151,11 +229,11 @@ export default {
const actualWidth = this.beatWidth * window.devicePixelRatio;
const actualMargin = this.beatMargin * window.devicePixelRatio;
if (! Number.isInteger(actualWidth)) {
if (!Number.isInteger(actualWidth)) {
this.beatWidth = Math.round(actualWidth) / window.devicePixelRatio;
}
if (! Number.isInteger(actualMargin)) {
if (!Number.isInteger(actualMargin)) {
this.beatMargin = Math.round(actualMargin) / window.devicePixelRatio;
}
@ -229,4 +307,21 @@ export default {
}
}
.word {
color: #aaa;
font-size: 12px;
}
.connecting-line {
flex-grow: 1;
height: 1px;
background-color: #ededed;
margin-left: 10px;
margin-right: 10px;
margin-top: 2px;
.dark & {
background-color: #333;
}
}
</style>

View file

@ -71,7 +71,7 @@
</div>
</div>
<div :key="$root.userHeartbeatBar" class="col-3 col-md-4">
<HeartbeatBar size="small" :monitor-id="monitor.element.id" />
<HeartbeatBar size="mid" :monitor-id="monitor.element.id" />
</div>
</div>
</div>

View file

@ -112,6 +112,53 @@
</div>
</div>
</div>
<!-- Timeline -->
<div class="my-4">
<label class="form-label">{{ $t("styleElapsedTime") }}</label>
<div>
<div class="btn-group" role="group">
<input
id="styleElapsedTimeShowNoLine"
v-model="$root.styleElapsedTime"
type="radio"
class="btn-check"
name="styleElapsedTime"
autocomplete="off"
value="no-line"
/>
<label class="btn btn-outline-primary" for="styleElapsedTimeShowNoLine">
{{ $t("styleElapsedTimeShowNoLine") }}
</label>
<input
id="styleElapsedTimeShowWithLine"
v-model="$root.styleElapsedTime"
type="radio"
class="btn-check"
name="styleElapsedTime"
autocomplete="off"
value="with-line"
/>
<label class="btn btn-outline-primary" for="styleElapsedTimeShowWithLine">
{{ $t("styleElapsedTimeShowWithLine") }}
</label>
<input
id="styleElapsedTimeNone"
v-model="$root.styleElapsedTime"
type="radio"
class="btn-check"
name="styleElapsedTime"
autocomplete="off"
value="none"
/>
<label class="btn btn-outline-primary" for="styleElapsedTimeNone">
{{ $t("None") }}
</label>
</div>
</div>
</div>
</div>
</template>

View file

@ -822,5 +822,21 @@
"Secret AccessKey": "Таен ключ за достъп",
"Session Token": "Токен за сесия",
"tailscalePingWarning": "За да използвате Tailscale Ping монитор, трябва да инсталирате Uptime Kuma без Docker и също така да инсталирате Tailscale клиент на вашия сървър.",
"Server URL should not contain the nfty topic": "URL адресът на сървъра не трябва да съдържа nfty темата"
"Server URL should not contain the nfty topic": "URL адресът на сървъра не трябва да съдържа nfty темата",
"FlashDuty Severity": "Степен на тежест",
"showCertificateExpiry": "Показвай изтичащ сертификат",
"noOrBadCertificate": "Няма/лош сертификат",
"Select": "Избери",
"selectedMonitorCount": "Избрано: {0}",
"wayToGetFlashDutyKey": "Можете да отидете на страница 'Channel -> (Select a Channel) -> Integrations -> Add a new integration' и да добавите 'Custom Event', за да получите 'push' адрес и да копирате ключа за интегриране в адреса. За повече информация, моля посетете",
"PushDeer Server": "PushDeer сървър",
"pushDeerServerDescription": "Оставете празно, за да използвате официалния сървър",
"Check/Uncheck": "Постави/Премахни отметка",
"Request Timeout": "Време за изтичане на заявката",
"timeoutAfter": "Времето изтича след {0} секунди",
"styleElapsedTime": "Изминало време под лентата с проверки",
"styleElapsedTimeShowNoLine": "Покажи (без ред)",
"gamedigGuessPort": "Gamedig: Познай порт",
"gamedigGuessPortDescription": "Портът, използван от Valve Server Query Protocol, може да е различен от клиентския порт. Опитайте това, ако мониторът не може да се свърже с вашия сървър.",
"styleElapsedTimeShowWithLine": "Покажи (с ред)"
}

View file

@ -827,5 +827,15 @@
"Check/Uncheck": "Vybrat/Zrušit výběr",
"showCertificateExpiry": "Zobrazit vypršení platnosti certifikátu",
"pushDeerServerDescription": "Chcete-li používat oficiální server, ponechte prázdné",
"noOrBadCertificate": "Žádný/Vadný certifikát"
"noOrBadCertificate": "Žádný/Vadný certifikát",
"nostrRelays": "Relé Nostr",
"FlashDuty Severity": "Závažnost",
"PushDeer Server": "Server PushDeer",
"wayToGetFlashDutyKey": "Můžete přejít na stránku Kanál -> (Vyberte kanál) -> Integrace -> Přidat novou integraci, přidat \"Vlastní událost\" a získat adresu pro odeslání, zkopírovat klíč integrace do adresy. Další informace naleznete na adrese",
"Request Timeout": "Časový limit požadavku",
"timeoutAfter": "Vypršení časového limitu po {0} sekundách",
"styleElapsedTime": "Čas uplynulý pod pruhem poslední odpovědi",
"styleElapsedTimeShowWithLine": "Zobrazit (s linkou)",
"gamedigGuessPortDescription": "Port používaný protokolem Valve Server Query Protocol se může lišit od portu klienta. Pokud se monitor nemůže připojit k serveru, zkuste to.",
"styleElapsedTimeShowNoLine": "Zobrazit (bez linky)"
}

View file

@ -814,5 +814,6 @@
"Badge Duration (in hours)": "Badge Dauer (in Stunden)",
"Badge Preview": "Badge Vorschau",
"tailscalePingWarning": "Um den Tailscale Ping Monitor nutzen zu können, musst du Uptime Kuma ohne Docker installieren und den Tailscale Client auf dem Server installieren.",
"Server URL should not contain the nfty topic": "Die Server-URL sollte das nfty-Thema nicht enthalten"
"Server URL should not contain the nfty topic": "Die Server-URL sollte das nfty-Thema nicht enthalten",
"pushDeerServerDescription": "Leer lassen, um den offiziellen Server zu verwenden"
}

View file

@ -817,5 +817,6 @@
"Json Query": "Json-Abfrage",
"jsonQueryDescription": "Führe eine JSON-Abfrage gegen die Antwort durch und prüfe den erwarteten Wert (der Rückgabewert wird zum Vergleich in eine Zeichenkette umgewandelt). Auf <a href='https://jsonata.org/'>jsonata.org</a> findest du die Dokumentation zur Abfragesprache. <a href='https://try.jsonata.org/'>Hier</a> kannst du Abfragen üben.",
"tailscalePingWarning": "Um den Tailscale Ping Monitor nutzen zu können, musst du Uptime Kuma ohne Docker installieren und den Tailscale Client auf dem Server installieren.",
"Server URL should not contain the nfty topic": "Die Server-URL sollte das nfty-Thema nicht enthalten"
"Server URL should not contain the nfty topic": "Die Server-URL sollte das nfty-Thema nicht enthalten",
"pushDeerServerDescription": "Leer lassen, um den offiziellen Server zu verwenden"
}

View file

@ -87,6 +87,9 @@
"Dark": "Dark",
"Auto": "Auto",
"Theme - Heartbeat Bar": "Theme - Heartbeat Bar",
"styleElapsedTime": "Elapsed time under the heartbeat bar",
"styleElapsedTimeShowNoLine": "Show (No Line)",
"styleElapsedTimeShowWithLine": "Show (With Line)",
"Normal": "Normal",
"Bottom": "Bottom",
"None": "None",
@ -803,5 +806,7 @@
"nostrRecipients": "Recipients Public Keys (npub)",
"nostrRecipientsHelp": "npub format, one per line",
"showCertificateExpiry": "Show Certificate Expiry",
"noOrBadCertificate": "No/Bad Certificate"
"noOrBadCertificate": "No/Bad Certificate",
"gamedigGuessPort": "Gamedig: Guess Port",
"gamedigGuessPortDescription": "The port used by Valve Server Query Protocol may be different from the client port. Try this if the monitor cannot connect to your server."
}

View file

@ -270,7 +270,7 @@
"Display Timezone": "Mostrar Zona Horaria",
"Server Timezone": "Servidor de Zona Horaria",
"statusPageMaintenanceEndDate": "Finaliza",
"Enable DNS Cache": "Habilitar Cache DNS",
"Enable DNS Cache": "Habilitar Cache DNS de monitores HTTP(s)",
"No Maintenance": "Sin Mantenimiento",
"weekdayShortSun": "Dom",
"dayOfWeek": "Día de la Semana",
@ -389,7 +389,7 @@
"emojiCheatSheet": "Hoja de trucos Emoji: {0}",
"webhookJsonDesc": "{0} es bueno para cualquier servidor HTTP moderno como Express.js",
"webhookFormDataDesc": "{multipart} es bueno para PHP. El JSON deberá analizarse con {decodeFunction}",
"webhookAdditionalHeadersDesc": "Establece encabezados adicionales enviados con el webhook.",
"webhookAdditionalHeadersDesc": "Establece encabezados adicionales enviados con el webhook. Cada cabecera debe definirse como una clave/valor JSON.",
"appriseInstalled": "Apprise está instalado.",
"successMessage": "Mensaje de éxito",
"Pick Accepted Status Codes...": "Seleccione Códigos de Estado Aceptados…",
@ -588,8 +588,8 @@
"GoogleChat": "Chat de Google (sólo Google Workspace)",
"Kook": "Kook",
"wayToGetKookBotToken": "Crea aplicación y obtén tu token de bot en {0}",
"wayToGetKookGuildID": "Activa 'Modo Desarrollador' en los ajustes de Kook, y haz click derecho en la unión para obtener su ID",
"Guild ID": "ID de Gremio",
"wayToGetKookGuildID": "Activa 'Modo Desarrollador' en los ajustes de Kook, y haz click derecho en el grupo para obtener su ID",
"Guild ID": "ID de grupo",
"User Key": "Key de Usuario",
"octopushTypePremium": "Premium (Rápido - recomendado para alertas)",
"octopushTypeLowCost": "Bajo Coste (Lento - algunas veces bloqueado por operador)",
@ -653,7 +653,7 @@
"gorush": "Gorush",
"squadcast": "Squadcast",
"Maintenance Time Window of a Day": "Ventana de tiempo de mantenimiento de un día",
"Effective Date Range": "Rango de Fecha Efectivo",
"Effective Date Range": "Rango de Fecha Efectivo (Opcional)",
"Free Mobile User Identifier": "Identificador de Usuario de Free Mobile",
"Gateway Type": "Tipo de Puerta de Enlace",
"SMSManager": "SMSManager",
@ -696,7 +696,7 @@
"High": "Alto",
"alertaApiEndpoint": "Endpoint API",
"Body Encoding": "Codificación del cuerpo",
"Expiry date": "Fecha de expiración",
"Expiry date": "Fecha de vencimiento",
"Expiry": "Expiración",
"API Keys": "Claves API",
"Key Added": "Clave añadida",
@ -749,7 +749,22 @@
"statusPageRefreshIn": "Reinicio en: {0}",
"twilioAuthToken": "Token de Autentificación",
"ntfyUsernameAndPassword": "Nombre de Usuario y Contraseña",
"ntfyAuthenticationMethod": "Método de Autentificación",
"ntfyAuthenticationMethod": "Método de Autenticación",
"Cannot connect to the socket server": "No se puede conectar al servidor socket",
"Reconnecting...": "Reconectando..."
"Reconnecting...": "Reconectando...",
"Select": "Seleccionar",
"chromeExecutableAutoDetect": "Auto Detectar",
"Edit Maintenance": "Editar mantenimiento",
"pushoverMessageTtl": "Mensaje TTL (segundos)",
"Notify Channel": "Canal de notificación",
"Show Clickable Link Description": "Si está marcado, todos los que tienen acceso a esta página de estado pueden tener acceso a la URL del monitor.",
"webhookBodyCustomOption": "Cuerpo Personalizado",
"selectedMonitorCount": "Seleccionado: {0}",
"Check/Uncheck": "Marcar/Desmarcar",
"Invert Keyword": "Invertir palabra clave",
"filterActive": "Activo",
"filterActivePaused": "Pausado",
"Home": "Inicio",
"Expected Value": "Valor esperado",
"Json Query": "Consulta Json"
}

View file

@ -829,5 +829,14 @@
"PushDeer Server": "PushDeer Server",
"showCertificateExpiry": "Afficher l'expiration du certificat",
"noOrBadCertificate": "Pas/Mauvais certificat",
"pushDeerServerDescription": "Laissez le champ vide pour utiliser le serveur officiel"
"pushDeerServerDescription": "Laissez le champ vide pour utiliser le serveur officiel",
"FlashDuty Severity": "Gravité",
"wayToGetFlashDutyKey": "Vous pouvez aller dans Canal -> (Sélectionner un canal) -> Intégrations -> Ajouter une nouvelle page d'intégration, ajouter un \"événement personnalisé\" pour obtenir une adresse push, copier la clé d'intégration dans l'adresse. Pour plus d'informations, veuillez visiter",
"Request Timeout": "Délai d'expiration de la demande",
"timeoutAfter": "Délai dépassé après {0} secondes",
"gamedigGuessPort": "Gamedig: Devinez le port",
"gamedigGuessPortDescription": "Le port utilisé par Valve Server Query Protocol peut être différent du port client. Essayez ceci si la sonde ne peut pas se connecter à votre serveur.",
"styleElapsedTimeShowNoLine": "Afficher (pas de ligne)",
"styleElapsedTimeShowWithLine": "Afficher (avec ligne)",
"styleElapsedTime": "Temps écoulé sous la barre d'état"
}

View file

@ -448,7 +448,7 @@
"Backup": "Backup",
"About": "O skrypcie",
"wayToGetCloudflaredURL": "(Pobierz cloudflared z {0})",
"cloudflareWebsite": "Strona Cloudflare",
"cloudflareWebsite": "strona Cloudflare",
"Message:": "Wiadomość:",
"Don't know how to get the token? Please read the guide:": "Nie wiesz jak uzyksać token? Przeczytaj proszę poradnik:",
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Bieżące połączenie może zostać utracone, jeśli aktualnie łączysz się przez tunel Cloudflare. Czy na pewno chcesz to przerwać? Wpisz swoje aktualne hasło, aby je potwierdzić.",
@ -613,7 +613,7 @@
"You can divide numbers with": "Możesz dzielić liczby przez",
"or": "lub",
"recurringInterval": "odstęp czasu",
"Recurring": "powtarzający się",
"Recurring": "Powtarzający się",
"strategyManual": "Aktywowany/dezaktywowany ręcznie",
"warningTimezone": "Używa strefy czasowej serwera",
"weekdayShortMon": "pon",
@ -623,8 +623,8 @@
"weekdayShortFri": "pt",
"weekdayShortSat": "sob",
"weekdayShortSun": "niedz",
"dayOfWeek": "Dzień tygodnia",
"dayOfMonth": "Dzień miesiąca",
"dayOfWeek": "dzień tygodnia",
"dayOfMonth": "dzień miesiąca",
"lastDay": "Ostatni dzień",
"lastDay1": "Ostatni dzień miesiąca",
"lastDay2": "2. ostatni dzień miesiąca",
@ -646,7 +646,7 @@
"confirmDeleteTagMsg": "Czy na pewno chcesz usunąć ten tag? Monitory powiązane z tym tagiem nie zostaną usunięte.",
"Kook": "Kook",
"Enable TLS": "Włącz TLS",
"webhookAdditionalHeadersDesc": "Ustawia dodatkowe nagłówki wysyłane z webhookiem.",
"webhookAdditionalHeadersDesc": "Ustawia dodatkowe nagłówki wysyłane z webhookiem. Każdy nagłówek powinien być zdefiniowany jako klucz/wartość JSON.",
"dnsCacheDescription": "Może nie działać w niektórych środowiskach IPv6, wyłącz ją, jeśli napotkasz jakiekolwiek problemy.",
"wayToGetKookBotToken": "Utwórz aplikację i uzyskaj swój token bota na {0}",
"wayToGetKookGuildID": "Włącz 'Developer Mode' w ustawieniach Kook'a i kliknij prawym przyciskiem myszy na gildię, aby uzyskać jej ID",
@ -659,7 +659,7 @@
"Disable": "Wyłącz",
"Date and Time": "Data i czas",
"IconUrl": "URL ikony",
"Enable DNS Cache": "Włącz pamięć podręczną DNS",
"Enable DNS Cache": "Włącz pamięć podręczną DNS dla monitorów HTTP",
"Single Maintenance Window": "Pojedyncze okno konserwacji",
"Effective Date Range": "Zakres dat obowiązywania (opcjonalnie)",
"Schedule Maintenance": "Planowanie konserwacji",
@ -730,7 +730,7 @@
"twilioToNumber": "Do numeru",
"lunaseaTarget": "Cel",
"twilioAccountSID": "SID konta",
"twilioAuthToken": "Token autoryzacyjny",
"twilioAuthToken": "Token autoryzacji / klucz Api Secret",
"apiKeyAddedMsg": "Twój klucz API został dodany. Prosimy o zanotowanie go, ponieważ nie będzie on już więcej pokazywany.",
"telegramMessageThreadID": "(Opcjonalne) ID wątku wiadomości",
"telegramMessageThreadIDDescription": "Opcjonalny Unikalny identyfikator dla docelowego wątku wiadomości (tematu) forum; tylko dla supergrup forum",
@ -748,7 +748,7 @@
"sameAsServerTimezone": "Tak jak strefa czasowa serwera",
"endDateTime": "Data/godzina zakończenia",
"cronExpression": "Wyrażenie Cron",
"ntfyAuthenticationMethod": "Metoda Uwierzytelnienia",
"ntfyAuthenticationMethod": "Metoda uwierzytelniania",
"ntfyUsernameAndPassword": "Nazwa użytkownika i hasło",
"noGroupMonitorMsg": "Niedostępna. Stwórz najpierw grupę monitorów.",
"Close": "Zamknij",
@ -769,17 +769,74 @@
"Monitor Setting": "{0} Ustawienia monitora",
"Badge Duration": "Czas trwania odznaki",
"Badge Label": "Etykieta odznaki",
"Badge Suffix": "Sufiks odznaki",
"Badge Suffix": "Sufiks wartości odznaki",
"chromeExecutable": "Plik wykonywalny Chrome/Chromium",
"chromeExecutableAutoDetect": "Automatyczne wykrywanie",
"chromeExecutableDescription": "W przypadku użytkowników Dockera, jeśli Chromium nie jest jeszcze zainstalowane, instalacja i wyświetlenie wyniku testu może potrwać kilka minut. Zajmuje 1 GB miejsca na dysku.",
"chromeExecutableAutoDetect": "Wykryj automatycznie",
"chromeExecutableDescription": "W przypadku użytkowników Dockera, jeśli Chromium nie jest jeszcze zainstalowany, instalacja i wyświetlenie wyniku testu może zająć kilka minut. Zajmuje 1 GB miejsca na dysku.",
"Edit Maintenance": "Edycja konserwacji",
"Badge Type": "Typ odznaki",
"Badge Prefix": "Prefiks odznaki",
"Badge Prefix": "Prefiks wartości odznaki",
"Badge Color": "Kolor odznaki",
"Badge Label Color": "Kolor etykiety Odznaki",
"Badge Label Prefix": "Prefiks etykiety identyfikatora",
"Badge Pending Color": "Oczekujący kolor odznaki",
"Badge Maintenance Color": "Kolor utrzymania odznaki",
"Badge URL": "Adres URL odznaki"
"Badge URL": "Adres URL odznaki",
"gamedigGuessPort": "Gamedig: Port Guess",
"filterActive": "Aktywny",
"webhookCustomBodyDesc": "Definiuje niestandardową treść HTTP dla żądania. Akceptowane są zmienne szablonowe {msg}, {heartbeat}, {monitor}.",
"Select": "Wybierz",
"aboutNotifyChannel": "Powiadomienie kanału wywoła powiadomienie na komputerze lub urządzeniu mobilnym dla wszystkich członków kanału, niezależnie od tego, czy ich dostępność jest ustawiona jako aktywna, czy nie.",
"twilioApiKey": "Klucz API (opcjonalnie)",
"styleElapsedTime": "Czas, który upłynął pod paskiem bicia serca",
"tailscalePingWarning": "Aby korzystać z monitora Tailscale Ping, należy zainstalować Uptime Kuma bez Dockera, a także zainstalować klienta Tailscale na serwerze.",
"invertKeywordDescription": "Słowo kluczowe powinno być raczej nieobecne niż obecne.",
"jsonQueryDescription": "Wykonaj zapytanie json względem odpowiedzi i sprawdź oczekiwaną wartość (wartość zwracana zostanie przekonwertowana na ciąg znaków do porównania). Sprawdź <a href='https://jsonata.org/'>jsonata.org</a>, aby uzyskać dokumentację dotyczącą języka zapytań. Plac zabaw można znaleźć <a href='https://try.jsonata.org/'>tutaj</a>.",
"Server URL should not contain the nfty topic": "Adres URL serwera nie powinien zawierać tematu nfty",
"Badge Duration (in hours)": "Czas trwania odznaki (w godzinach)",
"Enter the list of brokers": "Wprowadź listę brokerów",
"Enable Kafka Producer Auto Topic Creation": "Włącz automatyczne tworzenie tematów w producencie Kafka",
"showCertificateExpiry": "Pokaż wygaśnięcie certyfikatu",
"gamedigGuessPortDescription": "Port używany przez Valve Server Query Protocol może różnić się od portu klienta. Spróbuj tego, jeśli monitor nie może połączyć się z serwerem.",
"Secret AccessKey": "Tajny klucz AccessKey",
"wayToGetFlashDutyKey": "Możesz przejść do Channel -> (Select a Channel) -> Integrations -> Add a new integration' page, dodać \"Custom Event\", aby uzyskać adres push, skopiować klucz integracji w adresie. Więcej informacji można znaleźć na stronie",
"Badge Down Color": "Kolor odznaki Offline",
"Notify Channel": "Powiadom kanał",
"Request Timeout": "Limit czasu żądania",
"timeoutAfter": "Przekroczenie limitu czasu po {0} sekundach",
"styleElapsedTimeShowNoLine": "Pokaż (bez linii)",
"styleElapsedTimeShowWithLine": "Pokaż (z linią)",
"filterActivePaused": "Wstrzymany",
"webhookBodyCustomOption": "Niestandardowa treść",
"webhookBodyPresetOption": "Wstępne ustawienie - {0}",
"selectedMonitorCount": "Wybrano: {0}",
"Check/Uncheck": "Zaznacz/Odznacz",
"PushDeer Server": "Serwer PushDeer",
"pushDeerServerDescription": "Pozostaw puste, aby korzystać z oficjalnego serwera",
"Badge Preview": "Podgląd odznaki",
"Kafka Brokers": "Broker Kafka",
"Press Enter to add broker": "Naciśnij Enter, aby dodać brokera",
"Kafka Topic Name": "Nazwa tematu Kafka",
"Kafka Producer Message": "Wiadomość producenta Kafka",
"Enable Kafka SSL": "Włącz Kafka SSL",
"Kafka SASL Options": "Opcje SASL Kafki",
"Mechanism": "Mechanizm",
"Pick a SASL Mechanism...": "Wybierz mechanizm SASL...",
"nostrRelaysHelp": "Jeden adres URL przekaźnika w wierszu",
"nostrRecipients": "Klucze publiczne odbiorców (npub)",
"nostrRecipientsHelp": "format npub, po jednym w wierszu",
"Authorization Identity": "Identyfikacja autoryzacji",
"AccessKey Id": "Identyfikator klucza AccessKey",
"Session Token": "Token sesji",
"Request Body": "Treść żądania",
"FlashDuty Severity": "Poziom istotności",
"nostrRelays": "Przekaźniki Nostr",
"nostrSender": "Prywatny klucz nadawcy (nsec)",
"Badge Up Color": "Kolor odznaki Online",
"Badge Down Days": "Odznaka dni offline",
"Badge Warn Days": "Odznaka dni z ostrzeżeniem",
"noOrBadCertificate": "Brak/zły certyfikat",
"Invert Keyword": "Odwróć słowo kluczowe",
"Expected Value": "Oczekiwana wartość",
"Json Query": "Zapytanie Json"
}

35
src/lang/pt.json Normal file
View file

@ -0,0 +1,35 @@
{
"Settings": "Definições",
"Help": "Ajuda",
"New Update": "Nova actualização",
"Language": "Linguagem",
"Appearance": "Aspecto",
"Theme": "Tema",
"General": "Geral",
"Game": "Jogo",
"Version": "Versão",
"List": "Lista",
"Add": "Adicionar",
"Quick Stats": "Estatísticas rápidas",
"Up": "Acima",
"Down": "Abaixo",
"Pending": "Pendente",
"statusMaintenance": "Manutenção",
"Maintenance": "Manutenção",
"Unknown": "Desconhecido",
"Reconnecting...": "Reconectando...",
"pauseDashboardHome": "Pausa",
"Pause": "Pausa",
"Name": "Nome",
"Status": "Estado",
"Message": "Mensagem",
"Resume": "Retomar",
"Edit": "Editar",
"Delete": "Remover",
"Current": "Actual",
"Uptime": "Tempo de atividade",
"day": "dia | dias",
"languageName": "Português",
"Primary Base URL": "URL base primário",
"No important events": "Nenhum evento importante"
}

View file

@ -817,5 +817,21 @@
"Enable Kafka Producer Auto Topic Creation": "Kafka Üreticisi Otomatik Başlık Oluşturmayı Etkinleştir",
"AccessKey Id": "Erişim Anahtarı Kimliği",
"tailscalePingWarning": "Tailscale Ping monitörünü kullanabilmek için Docker olmadan Uptime Kuma kurmanız ve ayrıca sunucunuza Tailscale client kurmanız gerekmektedir.",
"Server URL should not contain the nfty topic": "Sunucu URL'si nfty konusunu içermemelidir"
"Server URL should not contain the nfty topic": "Sunucu URL'si nfty konusunu içermemelidir",
"FlashDuty Severity": "Önem derecesi",
"nostrRelays": "Nostr röleleri",
"nostrRelaysHelp": "Satır başına bir geçiş URL'si",
"nostrSender": "Gönderen Özel Anahtarı (nsec)",
"nostrRecipients": "Alıcıların Genel Anahtarları (npub)",
"nostrRecipientsHelp": "npub biçimi, her satıra bir tane",
"showCertificateExpiry": "Sertifika Geçerlilik Süresini Göster",
"noOrBadCertificate": "Sertifika Yok/Geçersiz",
"Select": "Seç",
"PushDeer Server": "PushDeer Sunucusu",
"wayToGetFlashDutyKey": "Kanal -> (Bir Kanal Seçin) -> Entegrasyonlar -> Yeni entegrasyon ekle sayfasına gidebilir, bir push adresi almak için bir 'Özel Etkinlik' ekleyebilir, adresteki Entegrasyon Anahtarını kopyalayabilirsiniz. Daha fazla bilgi için lütfen ziyaret edin",
"selectedMonitorCount": "Seçildi: {0}",
"Check/Uncheck": "İşaretle/İşareti Kaldır",
"pushDeerServerDescription": "Resmi sunucuyu kullanmak için boş bırakın",
"Request Timeout": "İstek zaman aşımına uğradı",
"timeoutAfter": "{0} saniye sonra zaman aşımı"
}

View file

@ -823,5 +823,26 @@
"Enter the list of brokers": "Введіть список брокерів",
"Kafka Producer Message": "Повідомлення Kafka Producer",
"tailscalePingWarning": "Для того, щоб використовувати монітор Tailscale Ping, вам потрібно встановити Uptime Kuma без Docker, а також встановити клієнт Tailscale на вашому сервері.",
"Server URL should not contain the nfty topic": "URL-адреса сервера не повинна містити тему nfty"
"Server URL should not contain the nfty topic": "URL-адреса сервера не повинна містити тему nfty",
"FlashDuty Severity": "Серйозність",
"nostrRelays": "Реле Nostr",
"nostrRelaysHelp": "Одна URL-адреса реле в рядку",
"nostrSender": "Приватний ключ відправника (nsec)",
"nostrRecipients": "Відкриті ключі одержувачів (npub)",
"showCertificateExpiry": "Показати термін дії сертифікату",
"noOrBadCertificate": "Відсутність/поганий сертифікат",
"Select": "Вибрати",
"selectedMonitorCount": "Вибрано: {0}",
"wayToGetFlashDutyKey": "Ви можете перейти на сторінку \"Канал -> (Виберіть канал) -> Інтеграції -> Додати нову інтеграцію\", додати \"Користувацьку подію\", щоб отримати пуш-адресу, скопіювати ключ інтеграції в адресу. Для отримання додаткової інформації, будь ласка, відвідайте",
"nostrRecipientsHelp": "Формат npub, по одному в рядку",
"Check/Uncheck": "Встановити/зняти галочку",
"PushDeer Server": "Сервер PushDeer",
"pushDeerServerDescription": "Залиште порожнім, щоб використовувати офіційний сервер",
"Request Timeout": "Таймаут запиту",
"timeoutAfter": "Таймаут через {0} секунд",
"styleElapsedTime": "Час, що минув під індикатором серцебиття",
"gamedigGuessPort": "Gamedig: Вгадати порт",
"gamedigGuessPortDescription": "Порт, що використовується протоколом запитів до сервера Valve, може відрізнятися від порту клієнта. Спробуйте це, якщо монітор не може підключитися до вашого сервера.",
"styleElapsedTimeShowWithLine": "Показати (з лінією)",
"styleElapsedTimeShowNoLine": "Показати (без лінії)"
}

View file

@ -830,5 +830,10 @@
"selectedMonitorCount": "已选:{0}",
"noOrBadCertificate": "无证书或证书错误",
"showCertificateExpiry": "显示证书有效期",
"FlashDuty Severity":"严重程度"
"FlashDuty Severity": "严重程度",
"Check/Uncheck": "选中/取消选中",
"pushDeerServerDescription": "留空则使用官方服务器",
"PushDeer Server": "PushDeer 服务器",
"timeoutAfter": "{0} 秒后超时",
"Request Timeout": "请求超时"
}

View file

@ -5,6 +5,7 @@ export default {
system: (window.matchMedia("(prefers-color-scheme: dark)").matches) ? "dark" : "light",
userTheme: localStorage.theme,
userHeartbeatBar: localStorage.heartbeatBarTheme,
styleElapsedTime: localStorage.styleElapsedTime,
statusPageTheme: "light",
forceStatusPageTheme: false,
path: "",
@ -22,6 +23,11 @@ export default {
this.userHeartbeatBar = "normal";
}
// Default Elapsed Time Style
if (!this.styleElapsedTime) {
this.styleElapsedTime = "no-line";
}
document.body.classList.add(this.theme);
this.updateThemeColorMeta();
},
@ -68,6 +74,10 @@ export default {
localStorage.theme = to;
},
styleElapsedTime(to, from) {
localStorage.styleElapsedTime = to;
},
theme(to, from) {
document.body.classList.remove(from);
document.body.classList.add(this.theme);

View file

@ -455,6 +455,16 @@
</div>
</div>
<div v-if="monitor.type === 'gamedig'" class="my-3 form-check">
<input id="gamedig-guess-port" v-model="monitor.gamedigGivenPortOnly" :true-value="false" :false-value="true" class="form-check-input" type="checkbox">
<label class="form-check-label" for="gamedig-guess-port">
{{ $t("gamedigGuessPort") }}
</label>
<div class="form-text">
{{ $t("gamedigGuessPortDescription") }}
</div>
</div>
<!-- Ping packet size -->
<div v-if="monitor.type === 'ping'" class="my-3">
<label for="packet-size" class="form-label">{{ $t("Packet Size") }}</label>
@ -870,6 +880,7 @@ const monitorDefaults = {
kafkaProducerSaslOptions: {
mechanism: "None",
},
gamedigGivenPortOnly: true,
};
export default {