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 .vscode
.eslint* .eslint*
.stylelint* .stylelint*
/.devcontainer
/.github /.github
yarn.lock yarn.lock
app.json app.json
@ -35,6 +36,7 @@ tsconfig.json
/extra/healthcheck /extra/healthcheck
extra/exe-builder extra/exe-builder
### .gitignore content (commented rules are duplicated) ### .gitignore content (commented rules are duplicated)
#node_modules #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", "name": "uptime-kuma",
"version": "1.22.1", "version": "1.23.0-beta.1",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"type": "git", "type": "git",

View file

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

View file

@ -135,6 +135,7 @@ class Monitor extends BeanModel {
radiusCalledStationId: this.radiusCalledStationId, radiusCalledStationId: this.radiusCalledStationId,
radiusCallingStationId: this.radiusCallingStationId, radiusCallingStationId: this.radiusCallingStationId,
game: this.game, game: this.game,
gamedigGivenPortOnly: this.getGameDigGivenPortOnly(),
httpBodyEncoding: this.httpBodyEncoding, httpBodyEncoding: this.httpBodyEncoding,
jsonPath: this.jsonPath, jsonPath: this.jsonPath,
expectedValue: this.expectedValue, expectedValue: this.expectedValue,
@ -280,6 +281,10 @@ class Monitor extends BeanModel {
return JSON.parse(this.accepted_statuscodes_json); return JSON.parse(this.accepted_statuscodes_json);
} }
getGameDigGivenPortOnly() {
return Boolean(this.gamedigGivenPortOnly);
}
/** /**
* Start monitor * Start monitor
* @param {Server} io Socket server instance * @param {Server} io Socket server instance
@ -429,7 +434,7 @@ class Monitor extends BeanModel {
const options = { const options = {
url: this.url, url: this.url,
method: (this.method || "get").toLowerCase(), method: (this.method || "get").toLowerCase(),
timeout: this.timeout, timeout: this.timeout * 1000,
headers: { 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", "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, "User-Agent": "Uptime-Kuma/" + version,
@ -649,7 +654,7 @@ class Monitor extends BeanModel {
} }
let res = await axios.get(steamApiUrl, { let res = await axios.get(steamApiUrl, {
timeout: this.timeout, timeout: this.timeout * 1000,
headers: { headers: {
"Accept": "*/*", "Accept": "*/*",
"User-Agent": "Uptime-Kuma/" + version, "User-Agent": "Uptime-Kuma/" + version,
@ -687,7 +692,7 @@ class Monitor extends BeanModel {
type: this.game, type: this.game,
host: this.hostname, host: this.hostname,
port: this.port, port: this.port,
givenPortOnly: true, givenPortOnly: this.getGameDigGivenPortOnly(),
}); });
bean.msg = state.name; 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", "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"); log.info("server", "Importing Node libraries");
const fs = require("fs"); const fs = require("fs");
@ -641,6 +641,10 @@ let needSetup = false;
let notificationIDList = monitor.notificationIDList; let notificationIDList = monitor.notificationIDList;
delete 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); monitor.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes);
delete monitor.accepted_statuscodes; delete monitor.accepted_statuscodes;
@ -706,6 +710,11 @@ let needSetup = false;
removeGroupChildren = true; 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.name = monitor.name;
bean.description = monitor.description; bean.description = monitor.description;
bean.parent = monitor.parent; bean.parent = monitor.parent;
@ -775,6 +784,7 @@ let needSetup = false;
bean.kafkaProducerAllowAutoTopicCreation = monitor.kafkaProducerAllowAutoTopicCreation; bean.kafkaProducerAllowAutoTopicCreation = monitor.kafkaProducerAllowAutoTopicCreation;
bean.kafkaProducerSaslOptions = JSON.stringify(monitor.kafkaProducerSaslOptions); bean.kafkaProducerSaslOptions = JSON.stringify(monitor.kafkaProducerSaslOptions);
bean.kafkaProducerMessage = monitor.kafkaProducerMessage; bean.kafkaProducerMessage = monitor.kafkaProducerMessage;
bean.gamedigGivenPortOnly = monitor.gamedigGivenPortOnly;
bean.validate(); bean.validate();

View file

@ -720,7 +720,6 @@ exports.checkCertificate = function (res) {
* @param {number} status The status code to check * @param {number} status The status code to check
* @param {string[]} acceptedCodes An array of accepted status codes * @param {string[]} acceptedCodes An array of accepted status codes
* @returns {boolean} True if status code within range, false otherwise * @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) { exports.checkStatusCode = function (status, acceptedCodes) {
if (acceptedCodes == null || acceptedCodes.length === 0) { if (acceptedCodes == null || acceptedCodes.length === 0) {
@ -728,6 +727,11 @@ exports.checkStatusCode = function (status, acceptedCodes) {
} }
for (const codeRange of 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)); const codeRangeSplit = codeRange.split("-").map(string => parseInt(string));
if (codeRangeSplit.length === 1) { if (codeRangeSplit.length === 1) {
if (status === codeRangeSplit[0]) { if (status === codeRangeSplit[0]) {
@ -738,7 +742,8 @@ exports.checkStatusCode = function (status, acceptedCodes) {
return true; return true;
} }
} else { } 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" v-for="(beat, index) in shortBeatList"
:key="index" :key="index"
class="beat" 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" :style="beatStyle"
:title="getBeatTitle(beat)" :title="getBeatTitle(beat)"
/> />
</div> </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> </div>
</template> </template>
<script> <script>
import dayjs from "dayjs";
export default { export default {
props: { 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() { shortBeatList() {
if (! this.beatList) { if (!this.beatList) {
return []; 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: { watch: {
beatList: { beatList: {
@ -133,14 +211,14 @@ export default {
}, },
beforeMount() { beforeMount() {
if (this.heartbeatList === null) { if (this.heartbeatList === null) {
if (! (this.monitorId in this.$root.heartbeatList)) { if (!(this.monitorId in this.$root.heartbeatList)) {
this.$root.heartbeatList[this.monitorId] = []; this.$root.heartbeatList[this.monitorId] = [];
} }
} }
}, },
mounted() { mounted() {
if (this.size === "small") { if (this.size !== "big") {
this.beatWidth = 5; this.beatWidth = 5;
this.beatHeight = 16; this.beatHeight = 16;
this.beatMargin = 2; this.beatMargin = 2;
@ -151,11 +229,11 @@ export default {
const actualWidth = this.beatWidth * window.devicePixelRatio; const actualWidth = this.beatWidth * window.devicePixelRatio;
const actualMargin = this.beatMargin * window.devicePixelRatio; const actualMargin = this.beatMargin * window.devicePixelRatio;
if (! Number.isInteger(actualWidth)) { if (!Number.isInteger(actualWidth)) {
this.beatWidth = Math.round(actualWidth) / window.devicePixelRatio; this.beatWidth = Math.round(actualWidth) / window.devicePixelRatio;
} }
if (! Number.isInteger(actualMargin)) { if (!Number.isInteger(actualMargin)) {
this.beatMargin = Math.round(actualMargin) / window.devicePixelRatio; 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> </style>

View file

@ -71,7 +71,7 @@
</div> </div>
</div> </div>
<div :key="$root.userHeartbeatBar" class="col-3 col-md-4"> <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> </div>
</div> </div>

View file

@ -112,6 +112,53 @@
</div> </div>
</div> </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> </div>
</template> </template>

View file

@ -822,5 +822,21 @@
"Secret AccessKey": "Таен ключ за достъп", "Secret AccessKey": "Таен ключ за достъп",
"Session Token": "Токен за сесия", "Session Token": "Токен за сесия",
"tailscalePingWarning": "За да използвате Tailscale Ping монитор, трябва да инсталирате Uptime Kuma без Docker и също така да инсталирате Tailscale клиент на вашия сървър.", "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", "Check/Uncheck": "Vybrat/Zrušit výběr",
"showCertificateExpiry": "Zobrazit vypršení platnosti certifikátu", "showCertificateExpiry": "Zobrazit vypršení platnosti certifikátu",
"pushDeerServerDescription": "Chcete-li používat oficiální server, ponechte prázdné", "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 Duration (in hours)": "Badge Dauer (in Stunden)",
"Badge Preview": "Badge Vorschau", "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.", "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", "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.", "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.", "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", "Dark": "Dark",
"Auto": "Auto", "Auto": "Auto",
"Theme - Heartbeat Bar": "Theme - Heartbeat Bar", "Theme - Heartbeat Bar": "Theme - Heartbeat Bar",
"styleElapsedTime": "Elapsed time under the heartbeat bar",
"styleElapsedTimeShowNoLine": "Show (No Line)",
"styleElapsedTimeShowWithLine": "Show (With Line)",
"Normal": "Normal", "Normal": "Normal",
"Bottom": "Bottom", "Bottom": "Bottom",
"None": "None", "None": "None",
@ -803,5 +806,7 @@
"nostrRecipients": "Recipients Public Keys (npub)", "nostrRecipients": "Recipients Public Keys (npub)",
"nostrRecipientsHelp": "npub format, one per line", "nostrRecipientsHelp": "npub format, one per line",
"showCertificateExpiry": "Show Certificate Expiry", "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", "Display Timezone": "Mostrar Zona Horaria",
"Server Timezone": "Servidor de Zona Horaria", "Server Timezone": "Servidor de Zona Horaria",
"statusPageMaintenanceEndDate": "Finaliza", "statusPageMaintenanceEndDate": "Finaliza",
"Enable DNS Cache": "Habilitar Cache DNS", "Enable DNS Cache": "Habilitar Cache DNS de monitores HTTP(s)",
"No Maintenance": "Sin Mantenimiento", "No Maintenance": "Sin Mantenimiento",
"weekdayShortSun": "Dom", "weekdayShortSun": "Dom",
"dayOfWeek": "Día de la Semana", "dayOfWeek": "Día de la Semana",
@ -389,7 +389,7 @@
"emojiCheatSheet": "Hoja de trucos Emoji: {0}", "emojiCheatSheet": "Hoja de trucos Emoji: {0}",
"webhookJsonDesc": "{0} es bueno para cualquier servidor HTTP moderno como Express.js", "webhookJsonDesc": "{0} es bueno para cualquier servidor HTTP moderno como Express.js",
"webhookFormDataDesc": "{multipart} es bueno para PHP. El JSON deberá analizarse con {decodeFunction}", "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.", "appriseInstalled": "Apprise está instalado.",
"successMessage": "Mensaje de éxito", "successMessage": "Mensaje de éxito",
"Pick Accepted Status Codes...": "Seleccione Códigos de Estado Aceptados…", "Pick Accepted Status Codes...": "Seleccione Códigos de Estado Aceptados…",
@ -588,8 +588,8 @@
"GoogleChat": "Chat de Google (sólo Google Workspace)", "GoogleChat": "Chat de Google (sólo Google Workspace)",
"Kook": "Kook", "Kook": "Kook",
"wayToGetKookBotToken": "Crea aplicación y obtén tu token de bot en {0}", "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", "wayToGetKookGuildID": "Activa 'Modo Desarrollador' en los ajustes de Kook, y haz click derecho en el grupo para obtener su ID",
"Guild ID": "ID de Gremio", "Guild ID": "ID de grupo",
"User Key": "Key de Usuario", "User Key": "Key de Usuario",
"octopushTypePremium": "Premium (Rápido - recomendado para alertas)", "octopushTypePremium": "Premium (Rápido - recomendado para alertas)",
"octopushTypeLowCost": "Bajo Coste (Lento - algunas veces bloqueado por operador)", "octopushTypeLowCost": "Bajo Coste (Lento - algunas veces bloqueado por operador)",
@ -653,7 +653,7 @@
"gorush": "Gorush", "gorush": "Gorush",
"squadcast": "Squadcast", "squadcast": "Squadcast",
"Maintenance Time Window of a Day": "Ventana de tiempo de mantenimiento de un día", "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", "Free Mobile User Identifier": "Identificador de Usuario de Free Mobile",
"Gateway Type": "Tipo de Puerta de Enlace", "Gateway Type": "Tipo de Puerta de Enlace",
"SMSManager": "SMSManager", "SMSManager": "SMSManager",
@ -696,7 +696,7 @@
"High": "Alto", "High": "Alto",
"alertaApiEndpoint": "Endpoint API", "alertaApiEndpoint": "Endpoint API",
"Body Encoding": "Codificación del cuerpo", "Body Encoding": "Codificación del cuerpo",
"Expiry date": "Fecha de expiración", "Expiry date": "Fecha de vencimiento",
"Expiry": "Expiración", "Expiry": "Expiración",
"API Keys": "Claves API", "API Keys": "Claves API",
"Key Added": "Clave añadida", "Key Added": "Clave añadida",
@ -749,7 +749,22 @@
"statusPageRefreshIn": "Reinicio en: {0}", "statusPageRefreshIn": "Reinicio en: {0}",
"twilioAuthToken": "Token de Autentificación", "twilioAuthToken": "Token de Autentificación",
"ntfyUsernameAndPassword": "Nombre de Usuario y Contraseña", "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", "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", "PushDeer Server": "PushDeer Server",
"showCertificateExpiry": "Afficher l'expiration du certificat", "showCertificateExpiry": "Afficher l'expiration du certificat",
"noOrBadCertificate": "Pas/Mauvais 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", "Backup": "Backup",
"About": "O skrypcie", "About": "O skrypcie",
"wayToGetCloudflaredURL": "(Pobierz cloudflared z {0})", "wayToGetCloudflaredURL": "(Pobierz cloudflared z {0})",
"cloudflareWebsite": "Strona Cloudflare", "cloudflareWebsite": "strona Cloudflare",
"Message:": "Wiadomość:", "Message:": "Wiadomość:",
"Don't know how to get the token? Please read the guide:": "Nie wiesz jak uzyksać token? Przeczytaj proszę poradnik:", "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ć.", "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", "You can divide numbers with": "Możesz dzielić liczby przez",
"or": "lub", "or": "lub",
"recurringInterval": "odstęp czasu", "recurringInterval": "odstęp czasu",
"Recurring": "powtarzający się", "Recurring": "Powtarzający się",
"strategyManual": "Aktywowany/dezaktywowany ręcznie", "strategyManual": "Aktywowany/dezaktywowany ręcznie",
"warningTimezone": "Używa strefy czasowej serwera", "warningTimezone": "Używa strefy czasowej serwera",
"weekdayShortMon": "pon", "weekdayShortMon": "pon",
@ -623,8 +623,8 @@
"weekdayShortFri": "pt", "weekdayShortFri": "pt",
"weekdayShortSat": "sob", "weekdayShortSat": "sob",
"weekdayShortSun": "niedz", "weekdayShortSun": "niedz",
"dayOfWeek": "Dzień tygodnia", "dayOfWeek": "dzień tygodnia",
"dayOfMonth": "Dzień miesiąca", "dayOfMonth": "dzień miesiąca",
"lastDay": "Ostatni dzień", "lastDay": "Ostatni dzień",
"lastDay1": "Ostatni dzień miesiąca", "lastDay1": "Ostatni dzień miesiąca",
"lastDay2": "2. 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.", "confirmDeleteTagMsg": "Czy na pewno chcesz usunąć ten tag? Monitory powiązane z tym tagiem nie zostaną usunięte.",
"Kook": "Kook", "Kook": "Kook",
"Enable TLS": "Włącz TLS", "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.", "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}", "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", "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", "Disable": "Wyłącz",
"Date and Time": "Data i czas", "Date and Time": "Data i czas",
"IconUrl": "URL ikony", "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", "Single Maintenance Window": "Pojedyncze okno konserwacji",
"Effective Date Range": "Zakres dat obowiązywania (opcjonalnie)", "Effective Date Range": "Zakres dat obowiązywania (opcjonalnie)",
"Schedule Maintenance": "Planowanie konserwacji", "Schedule Maintenance": "Planowanie konserwacji",
@ -730,7 +730,7 @@
"twilioToNumber": "Do numeru", "twilioToNumber": "Do numeru",
"lunaseaTarget": "Cel", "lunaseaTarget": "Cel",
"twilioAccountSID": "SID konta", "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.", "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", "telegramMessageThreadID": "(Opcjonalne) ID wątku wiadomości",
"telegramMessageThreadIDDescription": "Opcjonalny Unikalny identyfikator dla docelowego wątku wiadomości (tematu) forum; tylko dla supergrup forum", "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", "sameAsServerTimezone": "Tak jak strefa czasowa serwera",
"endDateTime": "Data/godzina zakończenia", "endDateTime": "Data/godzina zakończenia",
"cronExpression": "Wyrażenie Cron", "cronExpression": "Wyrażenie Cron",
"ntfyAuthenticationMethod": "Metoda Uwierzytelnienia", "ntfyAuthenticationMethod": "Metoda uwierzytelniania",
"ntfyUsernameAndPassword": "Nazwa użytkownika i hasło", "ntfyUsernameAndPassword": "Nazwa użytkownika i hasło",
"noGroupMonitorMsg": "Niedostępna. Stwórz najpierw grupę monitorów.", "noGroupMonitorMsg": "Niedostępna. Stwórz najpierw grupę monitorów.",
"Close": "Zamknij", "Close": "Zamknij",
@ -769,17 +769,74 @@
"Monitor Setting": "{0} Ustawienia monitora", "Monitor Setting": "{0} Ustawienia monitora",
"Badge Duration": "Czas trwania odznaki", "Badge Duration": "Czas trwania odznaki",
"Badge Label": "Etykieta odznaki", "Badge Label": "Etykieta odznaki",
"Badge Suffix": "Sufiks odznaki", "Badge Suffix": "Sufiks wartości odznaki",
"chromeExecutable": "Plik wykonywalny Chrome/Chromium", "chromeExecutable": "Plik wykonywalny Chrome/Chromium",
"chromeExecutableAutoDetect": "Automatyczne wykrywanie", "chromeExecutableAutoDetect": "Wykryj automatycznie",
"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.", "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", "Edit Maintenance": "Edycja konserwacji",
"Badge Type": "Typ odznaki", "Badge Type": "Typ odznaki",
"Badge Prefix": "Prefiks odznaki", "Badge Prefix": "Prefiks wartości odznaki",
"Badge Color": "Kolor odznaki", "Badge Color": "Kolor odznaki",
"Badge Label Color": "Kolor etykiety Odznaki", "Badge Label Color": "Kolor etykiety Odznaki",
"Badge Label Prefix": "Prefiks etykiety identyfikatora", "Badge Label Prefix": "Prefiks etykiety identyfikatora",
"Badge Pending Color": "Oczekujący kolor odznaki", "Badge Pending Color": "Oczekujący kolor odznaki",
"Badge Maintenance Color": "Kolor utrzymania 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", "Enable Kafka Producer Auto Topic Creation": "Kafka Üreticisi Otomatik Başlık Oluşturmayı Etkinleştir",
"AccessKey Id": "Erişim Anahtarı Kimliği", "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.", "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": "Введіть список брокерів", "Enter the list of brokers": "Введіть список брокерів",
"Kafka Producer Message": "Повідомлення Kafka Producer", "Kafka Producer Message": "Повідомлення Kafka Producer",
"tailscalePingWarning": "Для того, щоб використовувати монітор Tailscale Ping, вам потрібно встановити Uptime Kuma без Docker, а також встановити клієнт Tailscale на вашому сервері.", "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}", "selectedMonitorCount": "已选:{0}",
"noOrBadCertificate": "无证书或证书错误", "noOrBadCertificate": "无证书或证书错误",
"showCertificateExpiry": "显示证书有效期", "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", system: (window.matchMedia("(prefers-color-scheme: dark)").matches) ? "dark" : "light",
userTheme: localStorage.theme, userTheme: localStorage.theme,
userHeartbeatBar: localStorage.heartbeatBarTheme, userHeartbeatBar: localStorage.heartbeatBarTheme,
styleElapsedTime: localStorage.styleElapsedTime,
statusPageTheme: "light", statusPageTheme: "light",
forceStatusPageTheme: false, forceStatusPageTheme: false,
path: "", path: "",
@ -22,6 +23,11 @@ export default {
this.userHeartbeatBar = "normal"; this.userHeartbeatBar = "normal";
} }
// Default Elapsed Time Style
if (!this.styleElapsedTime) {
this.styleElapsedTime = "no-line";
}
document.body.classList.add(this.theme); document.body.classList.add(this.theme);
this.updateThemeColorMeta(); this.updateThemeColorMeta();
}, },
@ -68,6 +74,10 @@ export default {
localStorage.theme = to; localStorage.theme = to;
}, },
styleElapsedTime(to, from) {
localStorage.styleElapsedTime = to;
},
theme(to, from) { theme(to, from) {
document.body.classList.remove(from); document.body.classList.remove(from);
document.body.classList.add(this.theme); document.body.classList.add(this.theme);

View file

@ -455,6 +455,16 @@
</div> </div>
</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 --> <!-- Ping packet size -->
<div v-if="monitor.type === 'ping'" class="my-3"> <div v-if="monitor.type === 'ping'" class="my-3">
<label for="packet-size" class="form-label">{{ $t("Packet Size") }}</label> <label for="packet-size" class="form-label">{{ $t("Packet Size") }}</label>
@ -870,6 +880,7 @@ const monitorDefaults = {
kafkaProducerSaslOptions: { kafkaProducerSaslOptions: {
mechanism: "None", mechanism: "None",
}, },
gamedigGivenPortOnly: true,
}; };
export default { export default {