From 3dda5938f2180c4af2b9edd6f165c196c707da1c Mon Sep 17 00:00:00 2001 From: Raphael Bernhart <mail@raphaelbernhart.at> Date: Fri, 21 Jan 2022 15:39:49 +0100 Subject: [PATCH 01/59] =?UTF-8?q?=F0=9F=92=84=20Add=20condition=20to=20div?= =?UTF-8?q?=20tag=20for=20styling=20reasons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/PublicGroupList.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PublicGroupList.vue b/src/components/PublicGroupList.vue index f30edcef..bd68e94e 100644 --- a/src/components/PublicGroupList.vue +++ b/src/components/PublicGroupList.vue @@ -41,7 +41,7 @@ <Uptime :monitor="monitor.element" type="24" :pill="true" /> {{ monitor.element.name }} </div> - <div class="tags"> + <div v-if="monitor.element.tags.length" class="tags"> <Tag v-for="tag in monitor.element.tags" :key="tag" :item="tag" :size="'sm'" /> </div> </div> From c57b2c4d287ac1ac9242ca3bc99a72236bc0606c Mon Sep 17 00:00:00 2001 From: Raphael Bernhart <mail@raphaelbernhart.at> Date: Fri, 21 Jan 2022 17:13:24 +0100 Subject: [PATCH 02/59] =?UTF-8?q?=F0=9F=92=84=20Fix=20spacing=20to=20get?= =?UTF-8?q?=20pixel=20perfectness?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/app.scss | 2 +- src/components/PublicGroupList.vue | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/assets/app.scss b/src/assets/app.scss index cec64467..f4d99462 100644 --- a/src/assets/app.scss +++ b/src/assets/app.scss @@ -339,7 +339,7 @@ textarea.form-control { .item { display: block; text-decoration: none; - padding: 13px 15px 10px 15px; + padding: 15px; border-radius: 10px; transition: all ease-in-out 0.15s; diff --git a/src/components/PublicGroupList.vue b/src/components/PublicGroupList.vue index bd68e94e..334282d8 100644 --- a/src/components/PublicGroupList.vue +++ b/src/components/PublicGroupList.vue @@ -33,8 +33,8 @@ <template #item="monitor"> <div class="item"> <div class="row"> - <div class="col-9 col-md-8 small-padding"> - <div class="info"> + <div class="col-9 col-md-8 small-padding d-flex align-items-center flex-wrap"> + <div class="info d-flex align-items-center gap-3 w-100"> <font-awesome-icon v-if="editMode" icon="arrows-alt-v" class="action drag me-3" /> <font-awesome-icon v-if="editMode" icon="times" class="action remove me-3" @click="removeMonitor(group.index, monitor.index)" /> @@ -45,7 +45,7 @@ <Tag v-for="tag in monitor.element.tags" :key="tag" :item="tag" :size="'sm'" /> </div> </div> - <div :key="$root.userHeartbeatBar" class="col-3 col-md-4"> + <div :key="$root.userHeartbeatBar" class="col-3 col-md-4 d-flex align-items-center"> <HeartbeatBar size="small" :monitor-id="monitor.element.id" /> </div> </div> From cd19b9fc49965732a4dd1def35fd695587101165 Mon Sep 17 00:00:00 2001 From: Raphael Bernhart <mail@raphaelbernhart.at> Date: Fri, 21 Jan 2022 17:13:38 +0100 Subject: [PATCH 03/59] =?UTF-8?q?=F0=9F=92=AB=20Improve=20hearbeat=20anima?= =?UTF-8?q?tion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/HeartbeatBar.vue | 47 +++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue index be0b122e..7143e716 100644 --- a/src/components/HeartbeatBar.vue +++ b/src/components/HeartbeatBar.vue @@ -1,6 +1,6 @@ <template> <div ref="wrap" class="wrap" :style="wrapStyle"> - <div class="hp-bar-big" :style="barStyle"> + <div class="hp-bar-big d-flex" :style="barStyle"> <div v-for="(beat, index) in shortBeatList" :key="index" @@ -8,7 +8,11 @@ :class="{ 'empty' : (beat === 0), 'down' : (beat.status === 0), 'pending' : (beat.status === 2) }" :style="beatStyle" :title="getBeatTitle(beat)" - /> + @mouseenter="toggleActivateSibling" + @mouseleave="toggleActivateSibling" + > + <div class="beat-inner" /> + </div> </div> </div> </template> @@ -168,9 +172,30 @@ export default { getBeatTitle(beat) { return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : ``); + }, + // Toggling the activeSibling class on hover over the current hover item + toggleActivateSibling(e) { + // Variable definition + const element = e.target; + const previous = element.previousSibling; + const next = element.nextSibling; + + // Return if the hovered element has empty class + if (element.classList.contains("empty")) { + return; + } + + // Check if Previous Sibling is heartbar element and doesn't have the empty class + if (previous.children && !previous.classList.contains("empty")) { + previous.classList.toggle("active-sibling"); + } + // Check if Next Sibling is heartbar element and doesn't have the empty class + if (next.children && next.classList.contains("empty")) { + next.classList.toggle("active-sibling"); + } } }, -} +}; </script> <style lang="scss" scoped> @@ -184,9 +209,10 @@ export default { .hp-bar-big { .beat { - display: inline-block; background-color: $primary; border-radius: $border-radius; + display: inline-block; + transition: all ease 0.6s; &.empty { background-color: aliceblue; @@ -200,11 +226,22 @@ export default { background-color: $warning; } + .beat-inner { + border-radius: $border-radius; + display: inline-block; + height: 100%; + width: 5px; + } + &:not(.empty):hover { - transition: all ease-in-out 0.15s; + transition: all ease 0.15s; opacity: 0.8; transform: scale(var(--hover-scale)); } + &.active-sibling { + transform: scale(1.3); + transition: all ease 0.15s; + } } } From 0313acd4c5bef4fce5c01cc6a7e7d6fe27439150 Mon Sep 17 00:00:00 2001 From: Raphael Bernhart <mail@raphaelbernhart.at> Date: Fri, 21 Jan 2022 17:22:30 +0100 Subject: [PATCH 04/59] =?UTF-8?q?=F0=9F=90=9B=20Fix=20bug=20where=20a=20co?= =?UTF-8?q?ndition=20was=20wrong-false?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/HeartbeatBar.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue index 7143e716..d7f352cc 100644 --- a/src/components/HeartbeatBar.vue +++ b/src/components/HeartbeatBar.vue @@ -190,7 +190,7 @@ export default { previous.classList.toggle("active-sibling"); } // Check if Next Sibling is heartbar element and doesn't have the empty class - if (next.children && next.classList.contains("empty")) { + if (next.children && !next.classList.contains("empty")) { next.classList.toggle("active-sibling"); } } From dd3992063eb680ba6233b146a6b1c7a879d6e031 Mon Sep 17 00:00:00 2001 From: Raphael Bernhart <48283236+raphaelbernhart@users.noreply.github.com> Date: Sat, 22 Jan 2022 13:59:36 +0100 Subject: [PATCH 05/59] Apply suggestions from code review Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com> --- src/components/HeartbeatBar.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue index d7f352cc..bbc7a40f 100644 --- a/src/components/HeartbeatBar.vue +++ b/src/components/HeartbeatBar.vue @@ -173,6 +173,7 @@ export default { getBeatTitle(beat) { return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : ``); }, + // Toggling the activeSibling class on hover over the current hover item toggleActivateSibling(e) { // Variable definition @@ -189,6 +190,7 @@ export default { if (previous.children && !previous.classList.contains("empty")) { previous.classList.toggle("active-sibling"); } + // Check if Next Sibling is heartbar element and doesn't have the empty class if (next.children && !next.classList.contains("empty")) { next.classList.toggle("active-sibling"); @@ -238,6 +240,7 @@ export default { opacity: 0.8; transform: scale(var(--hover-scale)); } + &.active-sibling { transform: scale(1.3); transition: all ease 0.15s; From ce7d8c38c522a6f6b77a5bd19ce5e800f4769b5d Mon Sep 17 00:00:00 2001 From: jordanbertasso <36979824+jordanbertasso@users.noreply.github.com> Date: Sun, 10 Apr 2022 21:43:52 +1000 Subject: [PATCH 06/59] [empty commit] pull request for issue #1448 From 0961c6d9b3b73db5446faa77bbd1173be6b4e979 Mon Sep 17 00:00:00 2001 From: jordanbertasso <36979824+jordanbertasso@users.noreply.github.com> Date: Sun, 10 Apr 2022 21:45:07 +1000 Subject: [PATCH 07/59] Check for ping and port type in discord notifs --- server/notification-providers/discord.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/server/notification-providers/discord.js b/server/notification-providers/discord.js index 881ad211..39eeef5a 100644 --- a/server/notification-providers/discord.js +++ b/server/notification-providers/discord.js @@ -24,14 +24,17 @@ class Discord extends NotificationProvider { let url; - if (monitorJSON["type"] === "port") { - url = monitorJSON["hostname"]; - if (monitorJSON["port"]) { - url += ":" + monitorJSON["port"]; - } - - } else { - url = monitorJSON["url"]; + switch (monitorJSON["type"]) { + case "port": + case "ping": + url = monitorJSON["hostname"]; + if (monitorJSON["port"]) { + url += ":" + monitorJSON["port"]; + } + break; + default: + url = monitorJSON["url"]; + break; } // If heartbeatJSON is not null, we go into the normal alerting loop. From 1b1e0f6dd942d25c4b97a549ef6f1b28870b95d5 Mon Sep 17 00:00:00 2001 From: jordanbertasso <36979824+jordanbertasso@users.noreply.github.com> Date: Sun, 10 Apr 2022 21:45:19 +1000 Subject: [PATCH 08/59] Add Discord tests --- test/backend.spec.js | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/test/backend.spec.js b/test/backend.spec.js index bbfc6897..7c02d342 100644 --- a/test/backend.spec.js +++ b/test/backend.spec.js @@ -1,5 +1,9 @@ -const { genSecret, sleep } = require("../src/util"); +const { genSecret, sleep, DOWN } = require("../src/util"); const utilServerRewire = require("../server/util-server"); +const Discord = require("../server/notification-providers/discord"); +const axios = require("axios"); + +jest.mock("axios"); describe("Test parseCertificateInfo", () => { it("should handle undefined", async () => { @@ -164,3 +168,41 @@ describe("Test reset-password", () => { }, 120000); }); +describe("Test Discord Notification Provider", () => { + const sendNotification = async (type) => { + const discordProvider = new Discord(); + + axios.post.mockResolvedValue({}); + + await discordProvider.send( + { + discordUsername: "Uptime Kuma", + discordWebhookUrl: "https://discord.com", + }, + "test message", + { + type, + hostname: "discord.com" + (type === "port" ? ":1337" : ""), + }, + { + status: DOWN, + } + ); + }; + + it("should send hostname for ping monitors", async () => { + await sendNotification("ping"); + + expect(axios.post.mock.lastCall[1].embeds[0].fields[1].value).toBe( + "discord.com" + ); + }); + + it("should send hostname for port monitors", async () => { + await sendNotification("port"); + + expect(axios.post.mock.lastCall[1].embeds[0].fields[1].value).toBe( + "discord.com:1337" + ); + }); +}); From e38742a2d0d4846cd72df127833dd6dcf87ba28d Mon Sep 17 00:00:00 2001 From: Matthew Nickson <mnickson@sidingsmedia.com> Date: Mon, 11 Apr 2022 19:58:31 +0100 Subject: [PATCH 09/59] [empty commit] pull request for #1059 From 2638d68c97d4c06a2d4f2545e4bc2a5b74eef9da Mon Sep 17 00:00:00 2001 From: jordanbertasso <36979824+jordanbertasso@users.noreply.github.com> Date: Tue, 12 Apr 2022 09:52:07 +1000 Subject: [PATCH 10/59] Cover dns and steam types in Discord notifs --- server/notification-providers/discord.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/notification-providers/discord.js b/server/notification-providers/discord.js index 39eeef5a..c5b95c60 100644 --- a/server/notification-providers/discord.js +++ b/server/notification-providers/discord.js @@ -25,8 +25,10 @@ class Discord extends NotificationProvider { let url; switch (monitorJSON["type"]) { - case "port": + case "dns": case "ping": + case "port": + case "steam": url = monitorJSON["hostname"]; if (monitorJSON["port"]) { url += ":" + monitorJSON["port"]; From 0765f0509065692085becffd506f65349d35175f Mon Sep 17 00:00:00 2001 From: jordanbertasso <36979824+jordanbertasso@users.noreply.github.com> Date: Tue, 12 Apr 2022 09:52:16 +1000 Subject: [PATCH 11/59] Update Discord tests --- test/backend.spec.js | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/test/backend.spec.js b/test/backend.spec.js index 7c02d342..27aaf9e2 100644 --- a/test/backend.spec.js +++ b/test/backend.spec.js @@ -169,7 +169,7 @@ describe("Test reset-password", () => { }); describe("Test Discord Notification Provider", () => { - const sendNotification = async (type) => { + const sendNotification = async (hostname, port, type) => { const discordProvider = new Discord(); axios.post.mockResolvedValue({}); @@ -182,7 +182,8 @@ describe("Test Discord Notification Provider", () => { "test message", { type, - hostname: "discord.com" + (type === "port" ? ":1337" : ""), + hostname, + port, }, { status: DOWN, @@ -190,19 +191,41 @@ describe("Test Discord Notification Provider", () => { ); }; - it("should send hostname for ping monitors", async () => { - await sendNotification("ping"); + it("should send hostname for dns monitors", async () => { + const hostname = "discord.com"; + await sendNotification(hostname, null, "dns"); expect(axios.post.mock.lastCall[1].embeds[0].fields[1].value).toBe( - "discord.com" + hostname + ); + }); + + it("should send hostname for ping monitors", async () => { + const hostname = "discord.com"; + await sendNotification(hostname, null, "ping"); + + expect(axios.post.mock.lastCall[1].embeds[0].fields[1].value).toBe( + hostname ); }); it("should send hostname for port monitors", async () => { - await sendNotification("port"); + const hostname = "discord.com"; + const port = 1337; + await sendNotification(hostname, port, "port"); expect(axios.post.mock.lastCall[1].embeds[0].fields[1].value).toBe( - "discord.com:1337" + `${hostname}:${port}` + ); + }); + + it("should send hostname for steam monitors", async () => { + const hostname = "discord.com"; + const port = 1337; + await sendNotification(hostname, port, "steam"); + + expect(axios.post.mock.lastCall[1].embeds[0].fields[1].value).toBe( + `${hostname}:${port}` ); }); }); From b893d50e450dd9bfbe956cceafd9398df1236274 Mon Sep 17 00:00:00 2001 From: Matthew Nickson <mnickson@sidingsmedia.com> Date: Wed, 13 Apr 2022 21:02:19 +0100 Subject: [PATCH 12/59] Implement specify Port for DNS Monitor #1059 This commit should fully implement #1059. When the user selects the DNS monitor option, a new input box has been added below the resolver address allowing the user to implement the port to access the resolver on. This uses the same `monitor.port` as the TCP monitor but a monitor has been added to prefill the port value to the default of `53` if the value in this field has not already been set. This is then cleared if the user selects a different monitor type and has not changed the port value. A translation has also been added explaining what this field does in order to reduce any confusion. JSDoc documentation has also been added to the `dnsResolve` function in `util-server.js`. Signed-off-by: Matthew Nickson <mnickson@sidingsmedia.com> --- server/model/monitor.js | 2 +- server/util-server.js | 12 ++++++++++-- src/languages/en.js | 1 + src/pages/EditMonitor.vue | 18 ++++++++++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index c4441d63..682fd72e 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -249,7 +249,7 @@ class Monitor extends BeanModel { let startTime = dayjs().valueOf(); let dnsMessage = ""; - let dnsRes = await dnsResolve(this.hostname, this.dns_resolve_server, this.dns_resolve_type); + let dnsRes = await dnsResolve(this.hostname, this.dns_resolve_server, this.port, this.dns_resolve_type); bean.ping = dayjs().valueOf() - startTime; if (this.dns_resolve_type == "A" || this.dns_resolve_type == "AAAA" || this.dns_resolve_type == "TXT") { diff --git a/server/util-server.js b/server/util-server.js index 2264ebea..ad30f610 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -89,9 +89,17 @@ exports.pingAsync = function (hostname, ipv6 = false) { }); }; -exports.dnsResolve = function (hostname, resolver_server, rrtype) { +/** + * Resolves a given record using the specified DNS server + * @param {string} hostname The hostname of the record to lookup + * @param {string} resolver_server The DNS server to use + * @param {string} resolver_port The port the DNS server is listening on + * @param {string} rrtype The type of record to request + * @returns {Promise} Promise object represents DNS lookup result + */ +exports.dnsResolve = function (hostname, resolver_server, resolver_port, rrtype) { const resolver = new Resolver(); - resolver.setServers([resolver_server]); + resolver.setServers([`${resolver_server}:${resolver_port}`]); return new Promise((resolve, reject) => { if (rrtype == "PTR") { resolver.reverse(hostname, (err, records) => { diff --git a/src/languages/en.js b/src/languages/en.js index 47513466..3f7f7c7e 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -14,6 +14,7 @@ export default { deleteMonitorMsg: "Are you sure want to delete this monitor?", deleteNotificationMsg: "Are you sure want to delete this notification for all monitors?", resoverserverDescription: "Cloudflare is the default server. You can change the resolver server anytime.", + dnsPortDescription: "DNS server port. Defaults to 53. You can change the port at any time.", rrtypeDescription: "Select the RR type you want to monitor", pauseMonitorMsg: "Are you sure want to pause?", enableDefaultNotificationDescription: "This notification will be enabled by default for new monitors. You can still disable the notification separately for each monitor.", diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 4b6a920c..f52eac8f 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -91,6 +91,15 @@ </div> </div> + <!-- Port --> + <div class="my-3"> + <label for="port" class="form-label">{{ $t("Port") }}</label> + <input id="port" v-model="monitor.port" type="number" class="form-control" required min="0" max="65535" step="1"> + <div class="form-text"> + {{ $t("dnsPortDescription") }} + </div> + </div> + <div class="my-3"> <label for="dns_resolve_type" class="form-label">{{ $t("Resource Record Type") }}</label> @@ -386,6 +395,15 @@ export default { this.monitor.pushToken = genSecret(10); } } + + // Set default port for DNS if not already defined + if (! this.monitor.port || this.monitor.port === "53") { + if (this.monitor.type === "dns") { + this.monitor.port = "53"; + } else { + this.monitor.port = ""; + } + } } }, From a680331dd77902a160e7876f650f5204e26d0499 Mon Sep 17 00:00:00 2001 From: Matthew Nickson <mnickson@sidingsmedia.com> Date: Fri, 15 Apr 2022 19:59:32 +0100 Subject: [PATCH 13/59] Fixes issue with ::1 port 5300 requests Now the address is wrapped in `[]` in order to prevent ::1 port 5300 being interpreted as ::1:5300. Wrapping the IPv4 address in `[]` does seem to have any effect on correct domain name resolution. In order to prevent issues if a user inputs an address with brackets, they are removed from the string if present before being re-added when it is passed to `setServers`. I have also removed the JSDoc comment as this will be added in a seperate PR Signed-off-by: Matthew Nickson <mnickson@sidingsmedia.com> --- server/util-server.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/server/util-server.js b/server/util-server.js index 367f4ffb..f7c0ce02 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -88,17 +88,12 @@ exports.pingAsync = function (hostname, ipv6 = false) { }); }; -/** - * Resolves a given record using the specified DNS server - * @param {string} hostname The hostname of the record to lookup - * @param {string} resolver_server The DNS server to use - * @param {string} resolver_port The port the DNS server is listening on - * @param {string} rrtype The type of record to request - * @returns {Promise} Promise object represents DNS lookup result - */ exports.dnsResolve = function (hostname, resolver_server, resolver_port, rrtype) { const resolver = new Resolver(); - resolver.setServers([`${resolver_server}:${resolver_port}`]); + // Remove brackets from IPv6 addresses so we can re-add them to + // prevent issues with ::1:5300 (::1 port 5300) + resolver_server = resolver_server.replace("[", "").replace("]", ""); + resolver.setServers([`[${resolver_server}]:${resolver_port}`]); return new Promise((resolve, reject) => { if (rrtype == "PTR") { resolver.reverse(hostname, (err, records) => { From 39df4eea926f49452c0592ad6056ac2e27ef013f Mon Sep 17 00:00:00 2001 From: Aram Akhavan <github@aram.nubmail.ca> Date: Mon, 28 Mar 2022 14:28:50 -0700 Subject: [PATCH 14/59] Ssynchronize push monitor heartbeats to api calls Includes a 1s buffer time to allow the push url to be called before the monitor is checked --- package-lock.json | 44 ++++++++++++++++----------------- package.json | 4 +-- server/model/monitor.js | 47 ++++++++++++++++++++---------------- server/routers/api-router.js | 7 +++--- 4 files changed, 54 insertions(+), 48 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9bc402c0..4f35ad4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,7 @@ "check-password-strength": "^2.0.5", "command-exists": "~1.2.9", "compare-versions": "~3.6.0", - "dayjs": "~1.10.8", + "dayjs": "^1.11.0", "express": "~4.17.3", "express-basic-auth": "~1.2.1", "favico.js": "^0.3.10", @@ -49,7 +49,7 @@ "prom-client": "~13.2.0", "prometheus-api-metrics": "~3.2.1", "qrcode": "~1.5.0", - "redbean-node": "0.1.3", + "redbean-node": "0.1.4", "socket.io": "~4.4.1", "socket.io-client": "~4.4.1", "socks-proxy-agent": "^6.1.1", @@ -5658,9 +5658,9 @@ } }, "node_modules/dayjs": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.8.tgz", - "integrity": "sha512-wbNwDfBHHur9UOzNUjeKUOJ0fCb0a52Wx0xInmQ7Y8FstyajiV1NmK1e00cxsr9YrE9r7yAChE0VvpuY5Rnlow==" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.0.tgz", + "integrity": "sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug==" }, "node_modules/debug": { "version": "4.3.4", @@ -13939,15 +13939,15 @@ } }, "node_modules/redbean-node": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/redbean-node/-/redbean-node-0.1.3.tgz", - "integrity": "sha512-itAouTnNK12QXy10DxScFRDv/R3Zt1sZw+tfUQCsBALxDDCNXVUdkNTgClouUwbTDG1YMQkeoD1Je9ujN7u3yg==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/redbean-node/-/redbean-node-0.1.4.tgz", + "integrity": "sha512-c1U6wnTeWS0c44tn9hkJWzjGgckLNJ8sN1E2bxnnnQsULOfvEVFLf8dLMjqhyyMrZ1L1mp8UvV4OfhRtH/ZrgQ==", "dependencies": { - "@types/node": "^14.17.7", + "@types/node": "^14.18.12", "await-lock": "^2.1.0", - "dayjs": "^1.10.6", - "glob": "^7.1.7", - "knex": "^0.95.9", + "dayjs": "^1.11.0", + "glob": "^7.2.0", + "knex": "^0.95.15", "lodash": "^4.17.21" } }, @@ -20965,9 +20965,9 @@ "dev": true }, "dayjs": { - "version": "1.10.8", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.8.tgz", - "integrity": "sha512-wbNwDfBHHur9UOzNUjeKUOJ0fCb0a52Wx0xInmQ7Y8FstyajiV1NmK1e00cxsr9YrE9r7yAChE0VvpuY5Rnlow==" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.0.tgz", + "integrity": "sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug==" }, "debug": { "version": "4.3.4", @@ -27229,15 +27229,15 @@ } }, "redbean-node": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/redbean-node/-/redbean-node-0.1.3.tgz", - "integrity": "sha512-itAouTnNK12QXy10DxScFRDv/R3Zt1sZw+tfUQCsBALxDDCNXVUdkNTgClouUwbTDG1YMQkeoD1Je9ujN7u3yg==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/redbean-node/-/redbean-node-0.1.4.tgz", + "integrity": "sha512-c1U6wnTeWS0c44tn9hkJWzjGgckLNJ8sN1E2bxnnnQsULOfvEVFLf8dLMjqhyyMrZ1L1mp8UvV4OfhRtH/ZrgQ==", "requires": { - "@types/node": "^14.17.7", + "@types/node": "^14.18.12", "await-lock": "^2.1.0", - "dayjs": "^1.10.6", - "glob": "^7.1.7", - "knex": "^0.95.9", + "dayjs": "^1.11.0", + "glob": "^7.2.0", + "knex": "^0.95.15", "lodash": "^4.17.21" }, "dependencies": { diff --git a/package.json b/package.json index 8a8bd1eb..3ca2e6f5 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "check-password-strength": "^2.0.5", "command-exists": "~1.2.9", "compare-versions": "~3.6.0", - "dayjs": "~1.10.8", + "dayjs": "^1.11.0", "express": "~4.17.3", "express-basic-auth": "~1.2.1", "favico.js": "^0.3.10", @@ -99,7 +99,7 @@ "prom-client": "~13.2.0", "prometheus-api-metrics": "~3.2.1", "qrcode": "~1.5.0", - "redbean-node": "0.1.3", + "redbean-node": "0.1.4", "socket.io": "~4.4.1", "socket.io-client": "~4.4.1", "socks-proxy-agent": "^6.1.1", diff --git a/server/model/monitor.js b/server/model/monitor.js index 2abf4be3..d1107a37 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -173,7 +173,7 @@ class Monitor extends BeanModel { let bean = R.dispense("heartbeat"); bean.monitor_id = this.id; - bean.time = R.isoDateTime(dayjs.utc()); + bean.time = R.isoDateTimeMillis(dayjs.utc()); bean.status = DOWN; if (this.isUpsideDown()) { @@ -348,25 +348,30 @@ class Monitor extends BeanModel { bean.msg = dnsMessage; bean.status = UP; } else if (this.type === "push") { // Type: Push - const time = R.isoDateTime(dayjs.utc().subtract(this.interval, "second")); - - let heartbeatCount = await R.count("heartbeat", " monitor_id = ? AND time > ? ", [ - this.id, - time - ]); - - log.debug("monitor", "heartbeatCount" + heartbeatCount + " " + time); - - if (heartbeatCount <= 0) { - // Fix #922, since previous heartbeat could be inserted by api, it should get from database - previousBeat = await Monitor.getPreviousHeartbeat(this.id); - - throw new Error("No heartbeat in the time window"); - } else { - // No need to insert successful heartbeat for push type, so end here - retries = 0; - this.heartbeatInterval = setTimeout(beat, beatInterval * 1000); - return; + log.debug(`[${this.name}] Checking monitor at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`); + const bufferTime = 1000; // 1s buffer to accommodate clock differences + // Fix #922, since previous heartbeat could be inserted by api, it should get from database + previousBeat = await Monitor.getPreviousHeartbeat(this.id); + //If the previous beat was nonexistent, down or pending we use the regular + // beatInterval/retryInterval in the setTimeout further below + if (previousBeat) { + const msSinceLastBeat = dayjs.utc().valueOf() - dayjs.utc(previousBeat.time).valueOf(); + log.debug(`[${this.name}] msSinceLastBeat = ${msSinceLastBeat}`); + if (previousBeat.status !== UP || msSinceLastBeat > beatInterval * 1000 + bufferTime) { + throw new Error("No heartbeat in the time window"); + } else { + let timeout = beatInterval * 1000 - msSinceLastBeat; + if (timeout < 0) { + timeout = bufferTime; + } else { + timeout += bufferTime; + } + // No need to insert successful heartbeat for push type, so end here + retries = 0; + log.debug(`[${this.name}] timeout = ${timeout}`); + this.heartbeatInterval = setTimeout(beat, timeout); + return; + } } } else if (this.type === "steam") { @@ -694,7 +699,7 @@ class Monitor extends BeanModel { } else { // Handle new monitor with only one beat, because the beat's duration = 0 - let status = parseInt(await R.getCell("SELECT `status` FROM heartbeat WHERE monitor_id = ?", [monitorID])); + let status = parseInt(await R.getCell("SELECT `status` FROM heartbeat WHERE monitor_id = ?", [ monitorID ])); if (status === UP) { uptime = 1; diff --git a/server/routers/api-router.js b/server/routers/api-router.js index 578655e2..fa594c4e 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -55,7 +55,7 @@ router.get("/api/push/:pushToken", async (request, response) => { let duration = 0; let bean = R.dispense("heartbeat"); - bean.time = R.isoDateTime(dayjs.utc()); + bean.time = R.isoDateTimeMillis(dayjs.utc()); if (previousHeartbeat) { isFirstBeat = false; @@ -63,8 +63,9 @@ router.get("/api/push/:pushToken", async (request, response) => { duration = dayjs(bean.time).diff(dayjs(previousHeartbeat.time), "second"); } - log.debug("router", "PreviousStatus: " + previousStatus); - log.debug("router", "Current Status: " + status); + log.debug(`/api/push/ called at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`); + log.debug("PreviousStatus: " + previousStatus); + log.debug("Current Status: " + status); bean.important = Monitor.isImportantBeat(isFirstBeat, previousStatus, status); bean.monitor_id = monitor.id; From 45da7c543193d6a355305830b1c9c8122b030941 Mon Sep 17 00:00:00 2001 From: AnnAngela-work <naganjue@vip.qq.com> Date: Fri, 29 Apr 2022 20:17:15 +0800 Subject: [PATCH 15/59] Improve translation work --- src/components/notifications/ClickSendSMS.vue | 12 ++--- src/components/notifications/Line.vue | 2 +- src/components/notifications/Octopush.vue | 10 ++-- src/components/notifications/PromoSMS.vue | 4 +- src/components/notifications/Pushover.vue | 45 +++++++++-------- src/components/notifications/Pushy.vue | 4 +- src/components/notifications/TechulusPush.vue | 2 +- src/components/settings/About.vue | 4 +- src/languages/en.js | 50 +++++++++++++++++++ src/languages/zh-CN.js | 50 +++++++++++++++++++ src/layouts/Layout.vue | 2 +- src/pages/EditMonitor.vue | 2 +- src/pages/NotFound.vue | 12 ++--- src/pages/StatusPage.vue | 2 +- 14 files changed, 151 insertions(+), 50 deletions(-) diff --git a/src/components/notifications/ClickSendSMS.vue b/src/components/notifications/ClickSendSMS.vue index 4fbb2f41..09d3201c 100644 --- a/src/components/notifications/ClickSendSMS.vue +++ b/src/components/notifications/ClickSendSMS.vue @@ -1,12 +1,12 @@ <template> <div class="mb-3"> - <label for="clicksendsms-login" class="form-label">API Username</label> + <label for="clicksendsms-login" class="form-label">{{ $t("API Username") }}</label> <div class="form-text"> {{ $t("apiCredentials") }} <a href="http://dashboard.clicksend.com/account/subaccounts" target="_blank">{{ $t("here") }}</a> </div> <input id="clicksendsms-login" v-model="$parent.notification.clicksendsmsLogin" type="text" class="form-control" required> - <label for="clicksendsms-key" class="form-label">API Key</label> + <label for="clicksendsms-key" class="form-label">{{ $t("API Key") }}</label> <HiddenInput id="clicksendsms-key" v-model="$parent.notification.clicksendsmsPassword" :required="true" autocomplete="one-time-code"></HiddenInput> </div> <div class="mb-3"> @@ -16,15 +16,15 @@ </div> </div> <div class="mb-3"> - <label for="clicksendsms-to-number" class="form-label">Recipient Number</label> + <label for="clicksendsms-to-number" class="form-label">{{ $t("Recipient Number") }}</label> <input id="clicksendsms-to-number" v-model="$parent.notification.clicksendsmsToNumber" type="text" minlength="8" maxlength="14" class="form-control" required> </div> <div class="mb-3"> - <label for="clicksendsms-sender-name" class="form-label">From Name/Number - - <a href="https://help.clicksend.com/article/4kgj7krx00-what-is-a-sender-id-or-sender-number" target="_blank">More Info</a> + <label for="clicksendsms-sender-name" class="form-label">{{ $t("From Name/Number") }} - + <i18n-t tag="span" keypath="Read more:"><a href="https://help.clicksend.com/article/4kgj7krx00-what-is-a-sender-id-or-sender-number" target="_blank">https://help.clicksend.com/article/4kgj7krx00-what-is-a-sender-id-or-sender-number</a></i18n-t> </label> <input id="clicksendsms-sender-name" v-model="$parent.notification.clicksendsmsSenderName" type="text" minlength="3" maxlength="11" class="form-control"> - <div class="form-text">Leave blank to use a shared sender number.</div> + <div class="form-text">{{ $t("Leave blank to use a shared sender number.") }}</div> </div> </template> <script> diff --git a/src/components/notifications/Line.vue b/src/components/notifications/Line.vue index cb52c0c1..34ceb4ac 100644 --- a/src/components/notifications/Line.vue +++ b/src/components/notifications/Line.vue @@ -7,7 +7,7 @@ <b>{{ $t("Basic Settings") }}</b> </i18n-t> <div class="mb-3" style="margin-top: 12px;"> - <label for="line-user-id" class="form-label">User ID</label> + <label for="line-user-id" class="form-label">{{ $t("User ID") }}</label> <input id="line-user-id" v-model="$parent.notification.lineUserID" type="text" class="form-control" required> </div> <i18n-t tag="div" keypath="lineDevConsoleTo" class="form-text"> diff --git a/src/components/notifications/Octopush.vue b/src/components/notifications/Octopush.vue index 37629d39..7d5fe469 100644 --- a/src/components/notifications/Octopush.vue +++ b/src/components/notifications/Octopush.vue @@ -1,18 +1,18 @@ <template> <div class="mb-3"> - <label for="octopush-version" class="form-label">Octopush API Version</label> + <label for="octopush-version" class="form-label">{{ $t("Octopush API Version") }}</label> <select id="octopush-version" v-model="$parent.notification.octopushVersion" class="form-select"> - <option value="2">Octopush (endpoint: api.octopush.com)</option> - <option value="1">Legacy Octopush-DM (endpoint: www.octopush-dm.com)</option> + <option value="2">{{ $t("octopush") }} ({{ $t("endpoint") }}: api.octopush.com)</option> + <option value="1">{{ $t("Legacy Octopush-DM") }} ({{ $t("endpoint") }}: www.octopush-dm.com)</option> </select> <div class="form-text"> {{ $t("octopushLegacyHint") }} </div> </div> <div class="mb-3"> - <label for="octopush-key" class="form-label">API KEY</label> + <label for="octopush-key" class="form-label">{{ $t("octopushAPIKey") }}</label> <HiddenInput id="octopush-key" v-model="$parent.notification.octopushAPIKey" :required="true" autocomplete="one-time-code"></HiddenInput> - <label for="octopush-login" class="form-label">API LOGIN</label> + <label for="octopush-login" class="form-label">{{ $t("octopushLogin") }}</label> <input id="octopush-login" v-model="$parent.notification.octopushLogin" type="text" class="form-control" required> </div> <div class="mb-3"> diff --git a/src/components/notifications/PromoSMS.vue b/src/components/notifications/PromoSMS.vue index 61e61a93..c11ed559 100644 --- a/src/components/notifications/PromoSMS.vue +++ b/src/components/notifications/PromoSMS.vue @@ -1,8 +1,8 @@ <template> <div class="mb-3"> - <label for="promosms-login" class="form-label">API LOGIN</label> + <label for="promosms-login" class="form-label">{{$("promosmsLogin")}}</label> <input id="promosms-login" v-model="$parent.notification.promosmsLogin" type="text" class="form-control" required> - <label for="promosms-key" class="form-label">API PASSWORD</label> + <label for="promosms-key" class="form-label">{{$("promosmsPassword")}}</label> <HiddenInput id="promosms-key" v-model="$parent.notification.promosmsPassword" :required="true" autocomplete="one-time-code"></HiddenInput> </div> <div class="mb-3"> diff --git a/src/components/notifications/Pushover.vue b/src/components/notifications/Pushover.vue index ee6276dd..83261deb 100644 --- a/src/components/notifications/Pushover.vue +++ b/src/components/notifications/Pushover.vue @@ -18,28 +18,29 @@ </select> <label for="pushover-sound" class="form-label">{{ $t("Notification Sound") }}</label> <select id="pushover-sound" v-model="$parent.notification.pushoversounds" class="form-select"> - <option>pushover</option> - <option>bike</option> - <option>bugle</option> - <option>cashregister</option> - <option>classical</option> - <option>cosmic</option> - <option>falling</option> - <option>gamelan</option> - <option>incoming</option> - <option>intermission</option> - <option>mechanical</option> - <option>pianobar</option> - <option>siren</option> - <option>spacealarm</option> - <option>tugboat</option> - <option>alien</option> - <option>climb</option> - <option>persistent</option> - <option>echo</option> - <option>updown</option> - <option>vibrate</option> - <option>none</option> + <option>{{ $t("pushoversounds pushover") }}</option> + <option>{{ $t("pushoversounds bike") }}</option> + <option>{{ $t("pushoversounds bugle") }}</option> + <option>{{ $t("pushoversounds cashregister") }}</option> + <option>{{ $t("pushoversounds classical") }}</option> + <option>{{ $t("pushoversounds cosmic") }}</option> + <option>{{ $t("pushoversounds falling") }}</option> + <option>{{ $t("pushoversounds gamelan") }}</option> + <option>{{ $t("pushoversounds incoming") }}</option> + <option>{{ $t("pushoversounds intermission") }}</option> + <option>{{ $t("pushoversounds magic") }}</option> + <option>{{ $t("pushoversounds mechanical") }}</option> + <option>{{ $t("pushoversounds pianobar") }}</option> + <option>{{ $t("pushoversounds siren") }}</option> + <option>{{ $t("pushoversounds spacealarm") }}</option> + <option>{{ $t("pushoversounds tugboat") }}</option> + <option>{{ $t("pushoversounds alien") }}</option> + <option>{{ $t("pushoversounds climb") }}</option> + <option>{{ $t("pushoversounds persistent") }}</option> + <option>{{ $t("pushoversounds echo") }}</option> + <option>{{ $t("pushoversounds updown") }}</option> + <option>{{ $t("pushoversounds vibrate") }}</option> + <option>{{ $t("pushoversounds none") }}</option> </select> <div class="form-text"> <span style="color: red;"><sup>*</sup></span>{{ $t("Required") }} diff --git a/src/components/notifications/Pushy.vue b/src/components/notifications/Pushy.vue index 26f404d2..3537eb4f 100644 --- a/src/components/notifications/Pushy.vue +++ b/src/components/notifications/Pushy.vue @@ -1,11 +1,11 @@ <template> <div class="mb-3"> - <label for="pushy-app-token" class="form-label">API_KEY</label> + <label for="pushy-app-token" class="form-label">{{ $t("pushyAPIKey") }}</label> <HiddenInput id="pushy-app-token" v-model="$parent.notification.pushyAPIKey" :required="true" autocomplete="one-time-code"></HiddenInput> </div> <div class="mb-3"> - <label for="pushy-user-key" class="form-label">USER_TOKEN</label> + <label for="pushy-user-key" class="form-label">{{ $t("pushyToken") }}</label> <div class="input-group mb-3"> <HiddenInput id="pushy-user-key" v-model="$parent.notification.pushyToken" :required="true" autocomplete="one-time-code"></HiddenInput> </div> diff --git a/src/components/notifications/TechulusPush.vue b/src/components/notifications/TechulusPush.vue index 918f8be6..86d4e5fe 100644 --- a/src/components/notifications/TechulusPush.vue +++ b/src/components/notifications/TechulusPush.vue @@ -1,6 +1,6 @@ <template> <div class="mb-3"> - <label for="push-api-key" class="form-label">API_KEY</label> + <label for="push-api-key" class="form-label">{{ $t("API Key") }}</label> <HiddenInput id="push-api-key" v-model="$parent.notification.pushAPIKey" :required="true" autocomplete="one-time-code"></HiddenInput> </div> diff --git a/src/components/settings/About.vue b/src/components/settings/About.vue index b4d7b659..a71e38af 100644 --- a/src/components/settings/About.vue +++ b/src/components/settings/About.vue @@ -9,11 +9,11 @@ <div class="mt-1"> <div class="form-check"> - <label><input v-model="settings.checkUpdate" type="checkbox" @change="saveSettings()" /> Show update if available</label> + <label><input v-model="settings.checkUpdate" type="checkbox" @change="saveSettings()" /> {{ $t("Show update if available") }}</label> </div> <div class="form-check"> - <label><input v-model="settings.checkBeta" type="checkbox" :disabled="!settings.checkUpdate" @change="saveSettings()" /> Also check beta release</label> + <label><input v-model="settings.checkBeta" type="checkbox" :disabled="!settings.checkUpdate" @change="saveSettings()" /> {{ $t("Also check beta release") }}</label> </div> </div> </div> diff --git a/src/languages/en.js b/src/languages/en.js index ab73ce35..ad97cbef 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -464,4 +464,54 @@ export default { "Domain Names": "Domain Names", signedInDisp: "Signed in as {0}", signedInDispDisabled: "Auth Disabled.", + "Certificate Expiry Notification": "Certificate Expiry Notification", + "API Username": "API Username", + "API Key": "API Key", + "Recipient Number": "Recipient Number", + "From Name/Number": "From Name/Number", + "Leave blank to use a shared sender number.": "Leave blank to use a shared sender number.", + "Octopush API Version": "Octopush API Version", + "Legacy Octopush-DM": "Legacy Octopush-DM", + "endpoint": "endpoint", + octopushAPIKey: "\"API key\" from HTTP API credentials in control panel", + octopushLogin: "\"Login\" from HTTP API credentials in control panel", + promosmsLogin: "API Login Name", + promosmsPassword: "API Password", + "pushoversounds pushover": "Pushover (default)", + "pushoversounds bike": "Bike", + "pushoversounds bugle": "Bugle", + "pushoversounds cashregister": "Cash Register", + "pushoversounds classical": "Classical", + "pushoversounds cosmic": "Cosmic", + "pushoversounds falling": "Falling", + "pushoversounds gamelan": "Gamelan", + "pushoversounds incoming": "Incoming", + "pushoversounds intermission": "Intermission", + "pushoversounds magic": "Magic", + "pushoversounds mechanical": "Mechanical", + "pushoversounds pianobar": "Piano Bar", + "pushoversounds siren": "Siren", + "pushoversounds spacealarm": "Space Alarm", + "pushoversounds tugboat": "Tug Boat", + "pushoversounds alien": "Alien Alarm (long)", + "pushoversounds climb": "Climb (long)", + "pushoversounds persistent": "Persistent (long)", + "pushoversounds echo": "Pushover Echo (long)", + "pushoversounds updown": "Up Down (long)", + "pushoversounds vibrate": "Vibrate Only", + "pushoversounds none": "None (silent)", + pushyAPIKey: "Secret API Key", + pushyToken: "Device token", + "Show update if available": "Show update if available", + "Also check beta release": "Also check beta release", + "Using a Reverse Proxy?": "Using a Reverse Proxy?", + "Check how to config it for WebSocket": "Check how to config it for WebSocket", + "Steam Game Server": "Steam Game Server", + "Most likely causes:": "Most likely causes:", + "The resource is no longer available.": "The resource is no longer available.", + "There might be a typing error in the address.": "There might be a typing error in the address.", + "What you can try:": "What you can try:", + "Retype the address.": "Retype the address.", + "Go back to the previous page.": "Go back to the previous page.", + "Coming Soon": "Coming Soon", }; diff --git a/src/languages/zh-CN.js b/src/languages/zh-CN.js index f50f50f1..9e5fcba1 100644 --- a/src/languages/zh-CN.js +++ b/src/languages/zh-CN.js @@ -469,4 +469,54 @@ export default { "Footer Text": "底部自定义文本", "Show Powered By": "显示 Powered By", "Domain Names": "域名", + "Certificate Expiry Notification": "证书到期时通知", + "API Username": "API 凭证 Username", + "API Key": "API 凭证 Key", + "Recipient Number": "收件人手机号码", + "From Name/Number": "发件人名称/手机号码", + "Leave blank to use a shared sender number.": "留空以使用平台共享的发件人手机号码", + "Octopush API Version": "Octopush API 版本", + "Legacy Octopush-DM": "旧版本 Octopush-DM", + "endpoint": "接入点", + octopushAPIKey: "控制台 HTTP API credentials 里的 \"API key\"", + octopushLogin: "控制台 HTTP API credentials 里的 \"Login\"", + promosmsLogin: "API 登录名", + promosmsPassword: "API 密码", + "pushoversounds pushover": "Pushover(默认)", + "pushoversounds bike": "Bike", + "pushoversounds bugle": "Bugle", + "pushoversounds cashregister": "Cash Register", + "pushoversounds classical": "Classical", + "pushoversounds cosmic": "Cosmic", + "pushoversounds falling": "Falling", + "pushoversounds gamelan": "Gamelan", + "pushoversounds incoming": "Incoming", + "pushoversounds intermission": "Intermission", + "pushoversounds magic": "Magic", + "pushoversounds mechanical": "Mechanical", + "pushoversounds pianobar": "Piano Bar", + "pushoversounds siren": "Siren", + "pushoversounds spacealarm": "Space Alarm", + "pushoversounds tugboat": "Tug Boat", + "pushoversounds alien": "Alien Alarm(长铃声)", + "pushoversounds climb": "Climb(长铃声)", + "pushoversounds persistent": "Persistent(长铃声)", + "pushoversounds echo": "Pushover Echo(长铃声)", + "pushoversounds updown": "Up Down(长铃声)", + "pushoversounds vibrate": "仅震动", + "pushoversounds none": "无(禁音)", + pushyAPIKey: "API 密钥", + pushyToken: "设备 Token", + "Show update if available": "有更新时通知", + "Also check beta release": "一并检查 Beta 版更新", + "Using a Reverse Proxy?": "正在使用反向代理?", + "Check how to config it for WebSocket": "查看如何将反向代理与 WebSocket 一起使用", + "Steam Game Server": "Steam 游戏服务器", + "Most likely causes:": "最可能的原因:", + "The resource is no longer available.": "您所请求的资源已不再可用;", + "There might be a typing error in the address.": "您输入的地址可能有误。", + "What you can try:": "您可以尝试以下操作:", + "Retype the address.": "重新输入地址;", + "Go back to the previous page.": "返回到上一页面。", + "Coming Soon": "即将推出", }; diff --git a/src/layouts/Layout.vue b/src/layouts/Layout.vue index 7f9598bf..38addb37 100644 --- a/src/layouts/Layout.vue +++ b/src/layouts/Layout.vue @@ -4,7 +4,7 @@ <div class="container-fluid"> {{ $root.connectionErrorMsg }} <div v-if="$root.showReverseProxyGuide"> - Using a Reverse Proxy? <a href="https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy" target="_blank">Check how to config it for WebSocket</a> + {{ $t("Using a Reverse Proxy?") }} <a href="https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy" target="_blank">{{ $t("Check how to config it for WebSocket") }}</a> </div> </div> </div> diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 39c114ad..0a753410 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -30,7 +30,7 @@ Push </option> <option value="steam"> - Steam Game Server + {{ $t("Steam Game Server") }} </option> <option value="mqtt"> MQTT diff --git a/src/pages/NotFound.vue b/src/pages/NotFound.vue index 16ba8a55..410c16a8 100644 --- a/src/pages/NotFound.vue +++ b/src/pages/NotFound.vue @@ -22,16 +22,16 @@ </div> <div class="guide"> - Most likely causes: + {{ $t("Most likely causes:") }} <ul> - <li>The resource is no longer available.</li> - <li>There might be a typing error in the address.</li> + <li>{{ $t("The resource is no longer available.") }}</li> + <li>{{ $t("There might be a typing error in the address.") }}</li> </ul> - What you can try:<br /> + {{ $t("What you can try:") }}<br /> <ul> - <li>Retype the address.</li> - <li><a href="#" class="go-back" @click="goBack()">Go back to the previous page.</a></li> + <li>{{ $t("Retype the address.") }}</li> + <li><a href="#" class="go-back" @click="goBack()">{{ $t("Go back to the previous page.") }}</a></li> </ul> </div> </div> diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index 8cda7ebb..546aa942 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -45,7 +45,7 @@ </div> <div v-if="false" class="my-3"> - <label for="password" class="form-label">{{ $t("Password") }} <sup>Coming Soon</sup></label> + <label for="password" class="form-label">{{ $t("Password") }} <sup>{{ $t("Coming Soon") }}</sup></label> <input id="password" v-model="config.password" disabled type="password" autocomplete="new-password" class="form-control"> </div> From 7dd5f5ea0dad64b7b65628a8f44b4fe2bbad9845 Mon Sep 17 00:00:00 2001 From: AnnAngela-work <naganjue@vip.qq.com> Date: Fri, 29 Apr 2022 20:26:56 +0800 Subject: [PATCH 16/59] Improve translation --- src/components/notifications/ClickSendSMS.vue | 7 +++---- src/languages/en.js | 1 + src/languages/zh-CN.js | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/notifications/ClickSendSMS.vue b/src/components/notifications/ClickSendSMS.vue index 09d3201c..dbd4d0aa 100644 --- a/src/components/notifications/ClickSendSMS.vue +++ b/src/components/notifications/ClickSendSMS.vue @@ -1,10 +1,9 @@ <template> <div class="mb-3"> <label for="clicksendsms-login" class="form-label">{{ $t("API Username") }}</label> - <div class="form-text"> - {{ $t("apiCredentials") }} + <i18n-t tag="div" class="form-text" keypath="wayToGetClickSendSMSToken"> <a href="http://dashboard.clicksend.com/account/subaccounts" target="_blank">{{ $t("here") }}</a> - </div> + </i18n-t> <input id="clicksendsms-login" v-model="$parent.notification.clicksendsmsLogin" type="text" class="form-control" required> <label for="clicksendsms-key" class="form-label">{{ $t("API Key") }}</label> <HiddenInput id="clicksendsms-key" v-model="$parent.notification.clicksendsmsPassword" :required="true" autocomplete="one-time-code"></HiddenInput> @@ -21,7 +20,7 @@ </div> <div class="mb-3"> <label for="clicksendsms-sender-name" class="form-label">{{ $t("From Name/Number") }} - - <i18n-t tag="span" keypath="Read more:"><a href="https://help.clicksend.com/article/4kgj7krx00-what-is-a-sender-id-or-sender-number" target="_blank">https://help.clicksend.com/article/4kgj7krx00-what-is-a-sender-id-or-sender-number</a></i18n-t> + <a href="https://help.clicksend.com/article/4kgj7krx00-what-is-a-sender-id-or-sender-number" target="_blank">{{ $t("Read more") }}</a> </label> <input id="clicksendsms-sender-name" v-model="$parent.notification.clicksendsmsSenderName" type="text" minlength="3" maxlength="11" class="form-control"> <div class="form-text">{{ $t("Leave blank to use a shared sender number.") }}</div> diff --git a/src/languages/en.js b/src/languages/en.js index ad97cbef..af6ec32b 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -514,4 +514,5 @@ export default { "Retype the address.": "Retype the address.", "Go back to the previous page.": "Go back to the previous page.", "Coming Soon": "Coming Soon", + wayToGetClickSendSMSToken: "You can get API Username and API Key from {0} .", }; diff --git a/src/languages/zh-CN.js b/src/languages/zh-CN.js index 9e5fcba1..691ec120 100644 --- a/src/languages/zh-CN.js +++ b/src/languages/zh-CN.js @@ -441,7 +441,7 @@ export default { "No Proxy": "无代理", "HTTP Basic Auth": "HTTP 基础身份验证", "New Status Page": "新的状态页", - "Page Not Found": "状态页未找到", + "Page Not Found": "未找到该页面", "Reverse Proxy": "反向代理", "Subject:": "颁发给:", "Valid To:": "有效期至:", @@ -519,4 +519,5 @@ export default { "Retype the address.": "重新输入地址;", "Go back to the previous page.": "返回到上一页面。", "Coming Soon": "即将推出", + wayToGetClickSendSMSToken: "您可以从 {0} 获取 API 凭证 Username 和 凭证 Key。", }; From e82fc1df61f800098315f5937e667ae810e523b9 Mon Sep 17 00:00:00 2001 From: AnnAngela-work <naganjue@vip.qq.com> Date: Fri, 29 Apr 2022 20:31:36 +0800 Subject: [PATCH 17/59] Match up en lang file --- src/languages/zh-CN.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/languages/zh-CN.js b/src/languages/zh-CN.js index 691ec120..52050a46 100644 --- a/src/languages/zh-CN.js +++ b/src/languages/zh-CN.js @@ -88,7 +88,7 @@ export default { Dark: "黑暗", Auto: "自动", "Theme - Heartbeat Bar": "主题 - 心跳栏", - Normal: "正常", // 此处还供 Gorush 的通知优先级功能使用,不应翻译为“正常显示” + Normal: "正常", Bottom: "靠下", None: "不显示", Timezone: "时区", @@ -398,11 +398,9 @@ export default { Invalid: "无效", AccessKeyId: "AccessKey ID", SecretAccessKey: "AccessKey Secret", - /* 以下为阿里云短信服务 API Dysms#SendSms 的参数 */ PhoneNumbers: "PhoneNumbers", TemplateCode: "TemplateCode", SignName: "SignName", - /* 以上为阿里云短信服务 API Dysms#SendSms 的参数 */ "Bark Endpoint": "Bark 接入点", "Device Token": "Apple Device Token", Platform: "平台", @@ -477,7 +475,7 @@ export default { "Leave blank to use a shared sender number.": "留空以使用平台共享的发件人手机号码", "Octopush API Version": "Octopush API 版本", "Legacy Octopush-DM": "旧版本 Octopush-DM", - "endpoint": "接入点", + endpoint: "接入点", octopushAPIKey: "控制台 HTTP API credentials 里的 \"API key\"", octopushLogin: "控制台 HTTP API credentials 里的 \"Login\"", promosmsLogin: "API 登录名", @@ -520,4 +518,6 @@ export default { "Go back to the previous page.": "返回到上一页面。", "Coming Soon": "即将推出", wayToGetClickSendSMSToken: "您可以从 {0} 获取 API 凭证 Username 和 凭证 Key。", + signedInDisp: "当前用户: {0}", + signedInDispDisabled: "已禁用身份验证", }; From 65ea2e6aeb1ecb1bb626be36f176e48a78e9408d Mon Sep 17 00:00:00 2001 From: AnnAngela <naganjue@vip.qq.com> Date: Fri, 29 Apr 2022 21:42:48 +0800 Subject: [PATCH 18/59] Update src/components/notifications/PromoSMS.vue Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com> --- src/components/notifications/PromoSMS.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/notifications/PromoSMS.vue b/src/components/notifications/PromoSMS.vue index c11ed559..29192aab 100644 --- a/src/components/notifications/PromoSMS.vue +++ b/src/components/notifications/PromoSMS.vue @@ -1,6 +1,6 @@ <template> <div class="mb-3"> - <label for="promosms-login" class="form-label">{{$("promosmsLogin")}}</label> + <label for="promosms-login" class="form-label">{{ $("promosmsLogin") }}</label> <input id="promosms-login" v-model="$parent.notification.promosmsLogin" type="text" class="form-control" required> <label for="promosms-key" class="form-label">{{$("promosmsPassword")}}</label> <HiddenInput id="promosms-key" v-model="$parent.notification.promosmsPassword" :required="true" autocomplete="one-time-code"></HiddenInput> From 5a069b278deafc766e37b1ef989920e993bf1c58 Mon Sep 17 00:00:00 2001 From: AnnAngela <naganjue@vip.qq.com> Date: Fri, 29 Apr 2022 21:42:54 +0800 Subject: [PATCH 19/59] Update src/components/notifications/PromoSMS.vue Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com> --- src/components/notifications/PromoSMS.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/notifications/PromoSMS.vue b/src/components/notifications/PromoSMS.vue index 29192aab..91b4d96d 100644 --- a/src/components/notifications/PromoSMS.vue +++ b/src/components/notifications/PromoSMS.vue @@ -2,7 +2,7 @@ <div class="mb-3"> <label for="promosms-login" class="form-label">{{ $("promosmsLogin") }}</label> <input id="promosms-login" v-model="$parent.notification.promosmsLogin" type="text" class="form-control" required> - <label for="promosms-key" class="form-label">{{$("promosmsPassword")}}</label> + <label for="promosms-key" class="form-label">{{ $("promosmsPassword") }}</label> <HiddenInput id="promosms-key" v-model="$parent.notification.promosmsPassword" :required="true" autocomplete="one-time-code"></HiddenInput> </div> <div class="mb-3"> From c114c053d633243f6343e52360c2e5a4b8e6f062 Mon Sep 17 00:00:00 2001 From: Adam Stachowicz <adam.stachowicz@fingo.info> Date: Sat, 30 Apr 2022 03:51:14 +0200 Subject: [PATCH 20/59] Fix ESLint warnings and errors --- src/components/CountUp.vue | 5 ++++- src/components/Datetime.vue | 5 ++++- src/components/Status.vue | 5 ++++- src/components/Uptime.vue | 10 ++++++++-- src/pages/StatusPage.vue | 40 ++++++++++++++++++------------------- 5 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/components/CountUp.vue b/src/components/CountUp.vue index 41edc4a0..df1d1ac6 100644 --- a/src/components/CountUp.vue +++ b/src/components/CountUp.vue @@ -10,7 +10,10 @@ import { sleep } from "../util.ts"; export default { props: { - value: [ String, Number ], + value: { + type: [ String, Number ], + default: 0, + }, time: { type: Number, default: 0.3, diff --git a/src/components/Datetime.vue b/src/components/Datetime.vue index ed38c434..fa68d02c 100644 --- a/src/components/Datetime.vue +++ b/src/components/Datetime.vue @@ -13,7 +13,10 @@ dayjs.extend(relativeTime); export default { props: { - value: String, + value: { + type: String, + default: null, + }, dateOnly: { type: Boolean, default: false, diff --git a/src/components/Status.vue b/src/components/Status.vue index a3916adc..1985d851 100644 --- a/src/components/Status.vue +++ b/src/components/Status.vue @@ -5,7 +5,10 @@ <script> export default { props: { - status: Number, + status: { + type: Number, + default: 0, + } }, computed: { diff --git a/src/components/Uptime.vue b/src/components/Uptime.vue index 3a63c6d0..487d62b7 100644 --- a/src/components/Uptime.vue +++ b/src/components/Uptime.vue @@ -5,8 +5,14 @@ <script> export default { props: { - monitor: Object, - type: String, + monitor: { + type: Object, + default: null, + }, + type: { + type: String, + default: null, + }, pill: { type: Boolean, default: false, diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index 8cda7ebb..34c71e06 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -104,15 +104,16 @@ <!-- Uploader --> <!-- url="/api/status-page/upload-logo" --> - <ImageCropUpload v-model="showImageCropUpload" - field="img" - :width="128" - :height="128" - :langType="$i18n.locale" - img-format="png" - :noCircle="true" - :noSquare="false" - @crop-success="cropSuccess" + <ImageCropUpload + v-model="showImageCropUpload" + field="img" + :width="128" + :height="128" + :langType="$i18n.locale" + img-format="png" + :noCircle="true" + :noSquare="false" + @crop-success="cropSuccess" /> <!-- Title --> @@ -273,7 +274,7 @@ {{ $t("deleteStatusPageMsg") }} </Confirm> - <component is="style" v-if="config.customCSS" type="text/css"> + <component :is="style" v-if="config.customCSS" type="text/css"> {{ config.customCSS }} </component> </div> @@ -281,22 +282,21 @@ <script> import axios from "axios"; -import PublicGroupList from "../components/PublicGroupList.vue"; -import ImageCropUpload from "vue-image-crop-upload"; -import { STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_PARTIAL_DOWN, UP } from "../util.ts"; -import { useToast } from "vue-toastification"; import dayjs from "dayjs"; import Favico from "favico.js"; -import { getResBaseURL } from "../util-frontend"; -import Confirm from "../components/Confirm.vue"; -// import Prism Editor -import { PrismEditor } from "vue-prism-editor"; -import "vue-prism-editor/dist/prismeditor.min.css"; // import the styles somewhere - // import highlighting library (you can use any library you want just return html string) import { highlight, languages } from "prismjs/components/prism-core"; import "prismjs/components/prism-css"; import "prismjs/themes/prism-tomorrow.css"; // import syntax highlighting styles +import ImageCropUpload from "vue-image-crop-upload"; +// import Prism Editor +import { PrismEditor } from "vue-prism-editor"; +import "vue-prism-editor/dist/prismeditor.min.css"; // import the styles somewhere +import { useToast } from "vue-toastification"; +import Confirm from "../components/Confirm.vue"; +import PublicGroupList from "../components/PublicGroupList.vue"; +import { getResBaseURL } from "../util-frontend"; +import { STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_PARTIAL_DOWN, UP } from "../util.ts"; const toast = useToast(); From 069d3765f0b582a35237857431bf47a11456946f Mon Sep 17 00:00:00 2001 From: Adam Stachowicz <adam.stachowicz@fingo.info> Date: Mon, 2 May 2022 01:13:17 +0200 Subject: [PATCH 21/59] Revert change for StatusPage --- src/pages/StatusPage.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index 34c71e06..1a64d0fa 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -274,7 +274,7 @@ {{ $t("deleteStatusPageMsg") }} </Confirm> - <component :is="style" v-if="config.customCSS" type="text/css"> + <component is="style" v-if="config.customCSS" type="text/css"> {{ config.customCSS }} </component> </div> From bc174c33257009cae257ccd303135ca2ebb54fbf Mon Sep 17 00:00:00 2001 From: Clemens Wolff <clemens@justamouse.com> Date: Mon, 2 May 2022 11:00:14 -0400 Subject: [PATCH 22/59] Extract child process args into variable --- server/notification-providers/apprise.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/notification-providers/apprise.js b/server/notification-providers/apprise.js index 2d795d4e..5e73a47c 100644 --- a/server/notification-providers/apprise.js +++ b/server/notification-providers/apprise.js @@ -6,7 +6,8 @@ class Apprise extends NotificationProvider { name = "apprise"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let s = childProcess.spawnSync("apprise", [ "-vv", "-b", msg, notification.appriseURL ]); + let args = [ "-vv", "-b", msg, notification.appriseURL ]; + let s = childProcess.spawnSync("apprise", args); let output = (s.stdout) ? s.stdout.toString() : "ERROR: maybe apprise not found"; From f9004bcbed4c8fe4d4ce17dd3c6dd0677bf3b49b Mon Sep 17 00:00:00 2001 From: Clemens Wolff <clemens@justamouse.com> Date: Mon, 2 May 2022 11:00:31 -0400 Subject: [PATCH 23/59] Add optional title to apprise notification --- server/notification-providers/apprise.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/notification-providers/apprise.js b/server/notification-providers/apprise.js index 5e73a47c..76e1e3c2 100644 --- a/server/notification-providers/apprise.js +++ b/server/notification-providers/apprise.js @@ -1,12 +1,23 @@ const NotificationProvider = require("./notification-provider"); const childProcess = require("child_process"); +/** + * If you use an apprise backend that requires the notification title to + * be set (such as for example messaging a Zulip Stream), you can use this + * environment variable to configure the title. + */ +const { APPRISE_NOTIFICATION_TITLE } = process.env; + class Apprise extends NotificationProvider { name = "apprise"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { let args = [ "-vv", "-b", msg, notification.appriseURL ]; + if (APPRISE_NOTIFICATION_TITLE) { + args.push("-t"); + args.push(APPRISE_NOTIFICATION_TITLE); + } let s = childProcess.spawnSync("apprise", args); let output = (s.stdout) ? s.stdout.toString() : "ERROR: maybe apprise not found"; From 4b9dc2890d078f46dc89860a61700d74674e7068 Mon Sep 17 00:00:00 2001 From: Clemens Wolff <clemens@justamouse.com> Date: Mon, 2 May 2022 11:16:08 -0400 Subject: [PATCH 24/59] Convert let to const --- server/notification-providers/apprise.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/notification-providers/apprise.js b/server/notification-providers/apprise.js index 76e1e3c2..acbc0567 100644 --- a/server/notification-providers/apprise.js +++ b/server/notification-providers/apprise.js @@ -13,14 +13,14 @@ class Apprise extends NotificationProvider { name = "apprise"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let args = [ "-vv", "-b", msg, notification.appriseURL ]; + const args = [ "-vv", "-b", msg, notification.appriseURL ]; if (APPRISE_NOTIFICATION_TITLE) { args.push("-t"); args.push(APPRISE_NOTIFICATION_TITLE); } - let s = childProcess.spawnSync("apprise", args); + const s = childProcess.spawnSync("apprise", args); - let output = (s.stdout) ? s.stdout.toString() : "ERROR: maybe apprise not found"; + const output = (s.stdout) ? s.stdout.toString() : "ERROR: maybe apprise not found"; if (output) { From e0a0a5db4cde0e86e0591fc60d61c58c36b6847a Mon Sep 17 00:00:00 2001 From: MrEddX <66828538+MrEddX@users.noreply.github.com> Date: Thu, 5 May 2022 22:46:34 +0300 Subject: [PATCH 25/59] Update bg-BG.js Translation Fixes --- src/languages/bg-BG.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/languages/bg-BG.js b/src/languages/bg-BG.js index 03fd288b..94553bd0 100644 --- a/src/languages/bg-BG.js +++ b/src/languages/bg-BG.js @@ -12,15 +12,15 @@ export default { keywordDescription: "Търси ключова дума в чист html или JSON отговор - чувствителна е към регистъра", pauseDashboardHome: "Пауза", deleteMonitorMsg: "Наистина ли желаете да изтриете този монитор?", - deleteNotificationMsg: "Наистина ли желаете да изтриете това известяване за всички монитори?", + deleteNotificationMsg: "Наистина ли желаете да изтриете това известие за всички монитори?", resolverserverDescription: "Cloudflare е сървърът по подразбиране, но можете да го промените по всяко време.", rrtypeDescription: "Изберете ресурсния запис, който желаете да наблюдавате", pauseMonitorMsg: "Наистина ли желаете да поставите в режим пауза?", - enableDefaultNotificationDescription: "За всеки нов монитор това известяване ще бъде активирано по подразбиране. Можете да го изключите за всеки отделен монитор.", + enableDefaultNotificationDescription: "За всеки нов монитор това известие ще бъде активирано по подразбиране. Можете да го изключите за всеки отделен монитор.", clearEventsMsg: "Наистина ли желаете да изтриете всички събития за този монитор?", clearHeartbeatsMsg: "Наистина ли желаете да изтриете всички записи за честотни проверки на този монитор?", confirmClearStatisticsMsg: "Наистина ли желаете да изтриете всички статистически данни?", - importHandleDescription: "Изберете 'Пропусни съществуващите', ако желаете да пропуснете всеки монитор или известяване със същото име. 'Презапис' ще изтрие всеки съществуващ монитор и известяване.", + importHandleDescription: "Изберете 'Пропусни съществуващите', ако желаете да пропуснете всеки монитор или известие със същото име. 'Презапис' ще изтрие всеки съществуващ монитор и известие.", confirmImportMsg: "Сигурни ли сте, че желаете импортирането на архива? Моля, уверете се, че сте избрали правилната опция за импортиране.", twoFAVerifyLabel: "Моля, въведете вашия токен код, за да проверите дали 2FA работи", tokenValidSettingsMsg: "Токен кодът е валиден! Вече можете да запазите настройките за 2FA.", @@ -76,9 +76,9 @@ export default { "Max. Redirects": "Макс. брой пренасочвания", "Accepted Status Codes": "Допустими статус кодове", Save: "Запази", - Notifications: "Известявания", + Notifications: "Известия", "Not available, please setup.": "Не са налични. Моля, настройте.", - "Setup Notification": "Настрой известяване", + "Setup Notification": "Настрой известие", Light: "Светла", Dark: "Тъмна", Auto: "Автоматично", @@ -109,7 +109,7 @@ export default { Login: "Вход", "No Monitors, please": "Все още няма монитори. Моля, добавете поне ", "add one": "един.", - "Notification Type": "Тип известяване", + "Notification Type": "Тип известие", Email: "Имейл", Test: "Тест", "Certificate Info": "Информация за сертификат", @@ -131,9 +131,9 @@ export default { Events: "Събития", Heartbeats: "Проверки", "Auto Get": "Авт. попълване", - backupDescription: "Можете да архивирате всички монитори и всички известявания в JSON файл.", + backupDescription: "Можете да архивирате всички монитори и всички известия в JSON файл.", backupDescription2: "PS: Имайте предвид, че данните за история и събития няма да бъдат включени.", - backupDescription3: "Чувствителни данни, като токен кодове за известяване, се съдържат в експортирания файл. Моля, бъдете внимателни с неговото съхранение.", + backupDescription3: "Чувствителни данни, като токен кодове за известия, се съдържат в експортирания файл. Моля, бъдете внимателни с неговото съхранение.", alertNoFile: "Моля, изберете файл за импортиране.", alertWrongFileType: "Моля, изберете JSON файл.", "Clear all statistics": "Изтрий цялата статистика", @@ -202,7 +202,7 @@ export default { "Push URL": "Генериран Push URL адрес", needPushEvery: "Необходимо е да извършвате заявка към този URL адрес на всеки {0} секунди", pushOptionalParams: "Допълнителни, но не задължителни параметри: {0}", - defaultNotificationName: "Моето {notification} известяване ({number})", + defaultNotificationName: "Моето {notification} известие ({number})", here: "тук", Required: "Задължително поле", "Bot Token": "Бот токен", @@ -252,7 +252,7 @@ export default { "Notification Sound": "Звуков сигнал", "More info on:": "Повече информация на: {0}", pushoverDesc1: "Приоритет Спешно (2) по подразбиране изчаква 30 секунди между повторните опити и изтича след 1 час.", - pushoverDesc2: "Ако желаете да изпратите известявания до различни устройства, попълнете полето Устройство.", + pushoverDesc2: "Ако желаете да изпратите известия до различни устройства, попълнете полето Устройство.", "SMS Type": "SMS тип", octopushTypePremium: "Премиум (Бърз - препоръчителен в случай на тревога)", octopushTypeLowCost: "Евтин (Бавен - понякога бива блокиран от оператора)", @@ -275,7 +275,7 @@ export default { lineDevConsoleTo: "Line - Конзола за разработчици - {0}", "Basic Settings": "Основни настройки", "User ID": "Потребител ID", - "Messaging API": "API за известяване", + "Messaging API": "API за съобщаване", wayToGetLineChannelToken: "Необходимо е първо да посетите {0}, за да създадете (Messaging API) за доставчик и канал, след което може да вземете токен кода за канал и потребителско ID от споменатите по-горе елементи на менюто.", "Icon URL": "URL адрес за иконка", aboutIconURL: "Може да предоставите линк към картинка в поле \"URL Адрес за иконка\" за да отмените картинката на профила по подразбиране. Няма да се използва, ако вече сте настроили емотикон.", @@ -291,7 +291,7 @@ export default { matrixHomeserverURL: "Сървър URL адрес (започва с http(s):// и порт по желание)", "Internal Room Id": "ID на вътрешна стая", matrixDesc1: "Може да намерите \"ID на вътрешна стая\" в разширените настройки на стаята във вашия Matrix клиент. Примерен изглед: !QMdRCpUIfLwsfjxye6:home.server.", - matrixDesc2: "Силно препоръчваме да създадете НОВ потребител и да НЕ използвате токен кодът на вашия личен Matrix потребирел, т.к. той позволява пълен достъп до вашия акаунт и всички стаи към които сте се присъединили. Вместо това създайте нов потребител и го поканете само в стаята, където желаете да получавате известяванията. Токен код за достъп ще получите изпълнявайки {0}", + matrixDesc2: "Силно препоръчваме да създадете НОВ потребител и да НЕ използвате токен кодът на вашия личен Matrix потребирел, т.к. той позволява пълен достъп до вашия акаунт и всички стаи към които сте се присъединили. Вместо това създайте нов потребител и го поканете само в стаята, където желаете да получавате известията. Токен код за достъп ще получите изпълнявайки {0}", Method: "Метод", Body: "Съобщение", Headers: "Хедъри", @@ -449,7 +449,7 @@ export default { Customize: "Персонализирай", "Custom Footer": "Персонализиран долен колонтитул", "Custom CSS": "Потребителски CSS", - "Domain Name Expiry Notification": "Известяване при изтичащ домейн", + "Domain Name Expiry Notification": "Известие при изтичащ домейн", Proxy: "Прокси", "Date Created": "Дата на създаване", onebotHttpAddress: "OneBot HTTP адрес", From bb7d67f717d6a8f0a541fb18e6bfa6bc7b281b09 Mon Sep 17 00:00:00 2001 From: Aram Akhavan <github@aram.nubmail.ca> Date: Fri, 6 May 2022 09:58:05 -0700 Subject: [PATCH 26/59] Apply suggestions from code review Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com> --- server/model/monitor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index d1107a37..1bde1cb7 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -350,9 +350,9 @@ class Monitor extends BeanModel { } else if (this.type === "push") { // Type: Push log.debug(`[${this.name}] Checking monitor at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`); const bufferTime = 1000; // 1s buffer to accommodate clock differences - // Fix #922, since previous heartbeat could be inserted by api, it should get from database + // Fix #922, since previous heartbeat could be inserted by API, it should get from database previousBeat = await Monitor.getPreviousHeartbeat(this.id); - //If the previous beat was nonexistent, down or pending we use the regular + // If the previous beat was nonexistent, down or pending we use the regular // beatInterval/retryInterval in the setTimeout further below if (previousBeat) { const msSinceLastBeat = dayjs.utc().valueOf() - dayjs.utc(previousBeat.time).valueOf(); From cd3fbc80b44a11cc62ee1b4194d16ebd541745a5 Mon Sep 17 00:00:00 2001 From: Aram Akhavan <github@aram.nubmail.ca> Date: Fri, 6 May 2022 16:05:24 -0700 Subject: [PATCH 27/59] Add first parameter back to logging in api router --- server/routers/api-router.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/routers/api-router.js b/server/routers/api-router.js index fa594c4e..75729f17 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -63,9 +63,9 @@ router.get("/api/push/:pushToken", async (request, response) => { duration = dayjs(bean.time).diff(dayjs(previousHeartbeat.time), "second"); } - log.debug(`/api/push/ called at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`); - log.debug("PreviousStatus: " + previousStatus); - log.debug("Current Status: " + status); + log.debug("router", `/api/push/ called at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`); + log.debug("router", "PreviousStatus: " + previousStatus); + log.debug("router", "Current Status: " + status); bean.important = Monitor.isImportantBeat(isFirstBeat, previousStatus, status); bean.monitor_id = monitor.id; From b6803717462963104648fc61da62e7717a95090d Mon Sep 17 00:00:00 2001 From: Clemens Wolff <clemens@justamouse.com> Date: Sat, 7 May 2022 11:00:57 -0400 Subject: [PATCH 28/59] Make apprise notification title configurable in UI --- server/notification-providers/apprise.js | 11 ++--------- src/components/notifications/Apprise.vue | 3 +++ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/server/notification-providers/apprise.js b/server/notification-providers/apprise.js index acbc0567..887afbf5 100644 --- a/server/notification-providers/apprise.js +++ b/server/notification-providers/apprise.js @@ -1,22 +1,15 @@ const NotificationProvider = require("./notification-provider"); const childProcess = require("child_process"); -/** - * If you use an apprise backend that requires the notification title to - * be set (such as for example messaging a Zulip Stream), you can use this - * environment variable to configure the title. - */ -const { APPRISE_NOTIFICATION_TITLE } = process.env; - class Apprise extends NotificationProvider { name = "apprise"; async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { const args = [ "-vv", "-b", msg, notification.appriseURL ]; - if (APPRISE_NOTIFICATION_TITLE) { + if (notification.title) { args.push("-t"); - args.push(APPRISE_NOTIFICATION_TITLE); + args.push(notification.title); } const s = childProcess.spawnSync("apprise", args); diff --git a/src/components/notifications/Apprise.vue b/src/components/notifications/Apprise.vue index c10e23cf..7432554c 100644 --- a/src/components/notifications/Apprise.vue +++ b/src/components/notifications/Apprise.vue @@ -8,6 +8,9 @@ <a href="https://github.com/caronc/apprise/wiki#notification-services" target="_blank">https://github.com/caronc/apprise/wiki#notification-services</a> </i18n-t> </div> + + <label for="title" class="form-label">{{ $t("Title") }}</label> + <input id="title" v-model="$parent.notification.title" type="text" class="form-control"> </div> <div class="mb-3"> <i18n-t tag="p" keypath="Status:"> From d344914ca0d5cb53ff7fd5884a00a9e7015c3dcf Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Mon, 9 May 2022 13:47:19 +0800 Subject: [PATCH 29/59] Update docker-compose.yml --- docker/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index a6499ef9..f01f0ea5 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -8,7 +8,7 @@ services: image: louislam/uptime-kuma:1 container_name: uptime-kuma volumes: - - ./uptime-kuma:/app/data + - ./uptime-kuma-data:/app/data ports: - - 3001:3001 + - 3001:3001 # <Host Port>:<Container Port> restart: always From 9f493bbec7a00c66295ca58e274c951dd465470d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Kr=C3=BDda?= <karel.kryda@gmail.com> Date: Mon, 9 May 2022 21:02:29 +0200 Subject: [PATCH 30/59] clone master branch --- CNAME | 2 +- public/icon.svg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CNAME b/CNAME index a5348b07..40f0b545 100644 --- a/CNAME +++ b/CNAME @@ -1 +1 @@ -git.kuma.pet \ No newline at end of file +git.kuma.pet; diff --git a/public/icon.svg b/public/icon.svg index 825c344e..9c0bc6ca 100644 --- a/public/icon.svg +++ b/public/icon.svg @@ -1,3 +1,3 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 640 640" width="640" height="640"><defs><path d="M407.55 916.24C471.25 916.24 522.89 967.88 522.89 1031.57C522.89 1113.88 522.89 1245.44 522.89 1327.74C522.89 1391.44 471.25 1443.08 407.55 1443.08C325.25 1443.08 193.68 1443.08 111.38 1443.08C47.69 1443.08 -3.95 1391.44 -3.95 1327.74C-3.95 1245.44 -3.95 1113.88 -3.95 1031.57C-3.95 967.88 47.69 916.24 111.38 916.24C193.68 916.24 325.25 916.24 407.55 916.24Z" id="a1LdTs1gvU"></path><linearGradient id="gradientcoH7TNh19" gradientUnits="userSpaceOnUse" x1="256.07" y1="1132.14" x2="609.11" y2="1480.42"><stop style="stop-color: #c2efd2;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #8ff0e5;stop-opacity: 1" offset="100%"></stop></linearGradient><path d="M-467.41 394.63C-467.41 554.76 -597.42 684.76 -757.55 684.76C-917.68 684.76 -1047.69 554.76 -1047.69 394.63C-1047.69 234.5 -917.68 104.49 -757.55 104.49C-597.42 104.49 -467.41 234.5 -467.41 394.63Z" id="a1uaEBd4xM"></path><path d="M-96.99 -586.14C-57.24 -619.85 -5.79 -604.75 19.26 -580.46C31.43 -568.66 56.57 -546.36 40.97 -491.67C32.76 -462.87 10.41 -436.4 -26.05 -412.27C-15.07 -377.85 -5.6 -344.76 2.36 -313C14.29 -265.36 13.55 -189.67 -26.05 -155.4C-67.27 -119.73 -166.91 -104.09 -234.24 -103.09C-301.57 -102.1 -406.19 -113.09 -461.6 -155.4C-517.01 -197.7 -512.24 -257.07 -498.04 -313C-488.58 -350.28 -476.43 -383.38 -461.6 -412.27C-505.54 -441.3 -530.54 -467.76 -536.6 -491.67C-545.68 -527.54 -530.93 -565.61 -501.12 -586.14C-471.31 -606.67 -435.18 -606.9 -400.45 -586.14C-377.3 -572.3 -354.79 -542.13 -332.92 -495.62C-287.85 -505.25 -254.96 -509.57 -234.24 -508.6C-214.74 -507.68 -186.57 -503.36 -149.72 -495.62C-135.81 -537.95 -118.23 -568.12 -96.99 -586.14Z" id="f8p7QlEjN3"></path><linearGradient id="gradienta4Tg99ZOOp" gradientUnits="userSpaceOnUse" x1="-440.25" y1="-388.59" x2="-100.49" y2="-147.33"><stop style="stop-color: #5cdd8b;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #7ae6a1;stop-opacity: 1" offset="100%"></stop></linearGradient><path d="M-86.03 -10.69C-61.35 -10.69 -41.34 9.32 -41.34 34.01C-41.34 119.07 -41.34 329.58 -41.34 414.65C-41.34 439.33 -61.35 459.34 -86.03 459.34C-136.01 459.34 -241.25 459.34 -291.23 459.34C-315.92 459.34 -335.93 439.33 -335.93 414.65C-335.93 329.58 -335.93 119.07 -335.93 34.01C-335.93 9.32 -315.92 -10.69 -291.23 -10.69C-241.25 -10.69 -136.01 -10.69 -86.03 -10.69Z" id="d32ZZRxd1S"></path><linearGradient id="gradientb1JxIe4xUm" gradientUnits="userSpaceOnUse" x1="-791.65" y1="-33.27" x2="892.1" y2="418.94"><stop style="stop-color: #5cdd8b;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #5ae98f;stop-opacity: 1" offset="100%"></stop></linearGradient><path d="M-257.95 458.12C-247.92 449.62 -234.93 453.43 -228.61 459.56C-225.54 462.54 -219.19 468.17 -223.13 481.97C-225.2 489.24 -230.84 495.92 -240.05 502.01C-237.27 510.7 -234.88 519.06 -232.88 527.07C-229.86 539.1 -230.05 558.21 -240.05 566.86C-250.45 575.86 -275.6 579.81 -292.6 580.06C-309.6 580.31 -336.01 577.54 -349.99 566.86C-363.98 556.18 -362.77 541.19 -359.19 527.07C-356.8 517.66 -353.73 509.31 -349.99 502.01C-361.08 494.69 -367.39 488.01 -368.92 481.97C-371.22 472.92 -367.49 463.31 -359.97 458.12C-352.44 452.94 -343.32 452.88 -334.56 458.12C-328.71 461.62 -323.03 469.23 -317.51 480.97C-306.13 478.54 -297.83 477.45 -292.6 477.7C-287.68 477.93 -280.56 479.02 -271.26 480.97C-267.75 470.29 -263.32 462.67 -257.95 458.12Z" id="b19LRRbPrG"></path><path d="M490.4 235.64C544.09 358.38 544.09 435.34 490.4 466.5C409.85 513.24 199.96 527.49 139.54 455.64C99.26 407.74 99.26 334.4 139.54 235.64C180.5 168.18 238.71 134.45 314.17 134.45C389.64 134.45 448.38 168.18 490.4 235.64Z" id="bN5StdyPU"></path><linearGradient id="gradientb1HT15TsY0" gradientUnits="userSpaceOnUse" x1="259.78" y1="261.15" x2="463.85" y2="456.49"><stop style="stop-color: #5cdd8b;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #86e6a9;stop-opacity: 1" offset="100%"></stop></linearGradient><path d="M393.81 -775.89C428.26 -748.09 439.99 -725.54 429 -708.22C412.51 -682.24 353.16 -646.07 324.5 -657.93C305.39 -665.83 294.22 -687.32 290.97 -722.41C292.69 -748.43 304.61 -767.19 326.73 -778.69C348.85 -790.19 371.21 -789.26 393.81 -775.89Z" id="arh6miPP2"></path><linearGradient id="gradientc2g6rBSAiq" gradientUnits="userSpaceOnUse" x1="330.1" y1="-733.26" x2="419.69" y2="-707.1"><stop style="stop-color: #5cdd8b;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #86e6a9;stop-opacity: 1" offset="100%"></stop></linearGradient><path d="M675.36 -369.24C669.97 -325.31 657.02 -303.43 636.51 -303.61C605.74 -303.87 543.67 -335.15 538.59 -365.74C535.2 -386.14 547.54 -406.99 575.61 -428.29C598.61 -440.58 620.83 -440.37 642.29 -427.67C663.74 -414.97 674.77 -395.49 675.36 -369.24Z" id="a2VENFzCvL"></path><linearGradient id="gradientc18GuJy4sZ" gradientUnits="userSpaceOnUse" x1="605.5" y1="-400.8" x2="630.64" y2="-310.92"><stop style="stop-color: #5cdd8b;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #86e6a9;stop-opacity: 1" offset="100%"></stop></linearGradient></defs><g><g><g><use xlink:href="#a1LdTs1gvU" opacity="1" fill="url(#gradientcoH7TNh19)"></use></g><g><use xlink:href="#a1uaEBd4xM" opacity="1" fill="#ebf0ed" fill-opacity="1"></use></g><g><use xlink:href="#f8p7QlEjN3" opacity="1" fill="url(#gradienta4Tg99ZOOp)"></use><g><use xlink:href="#f8p7QlEjN3" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="98" stroke-opacity="0.57"></use></g></g><g><use xlink:href="#d32ZZRxd1S" opacity="1" fill="url(#gradientb1JxIe4xUm)"></use><g><use xlink:href="#d32ZZRxd1S" opacity="1" fill-opacity="0" stroke="#f2f2f2" stroke-width="60" stroke-opacity="0.51"></use></g></g><g><use xlink:href="#b19LRRbPrG" opacity="1" fill="#d8ad9a" fill-opacity="1"></use><g><use xlink:href="#b19LRRbPrG" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="17" stroke-opacity="1"></use></g></g><g><use xlink:href="#bN5StdyPU" opacity="1" fill="url(#gradientb1HT15TsY0)"></use><g><use xlink:href="#bN5StdyPU" opacity="1" fill-opacity="0" stroke="#f2f2f2" stroke-width="200" stroke-opacity="0.51"></use></g></g><g><use xlink:href="#arh6miPP2" opacity="1" fill="url(#gradientc2g6rBSAiq)"></use></g><g><use xlink:href="#a2VENFzCvL" opacity="1" fill="url(#gradientc18GuJy4sZ)"></use></g></g></g></svg> \ No newline at end of file +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="0 0 640 640" width="640" height="640"><defs><path d="M407.55 916.24C471.25 916.24 522.89 967.88 522.89 1031.57C522.89 1113.88 522.89 1245.44 522.89 1327.74C522.89 1391.44 471.25 1443.08 407.55 1443.08C325.25 1443.08 193.68 1443.08 111.38 1443.08C47.69 1443.08 -3.95 1391.44 -3.95 1327.74C-3.95 1245.44 -3.95 1113.88 -3.95 1031.57C-3.95 967.88 47.69 916.24 111.38 916.24C193.68 916.24 325.25 916.24 407.55 916.24Z" id="a1LdTs1gvU"></path><linearGradient id="gradientcoH7TNh19" gradientUnits="userSpaceOnUse" x1="256.07" y1="1132.14" x2="609.11" y2="1480.42"><stop style="stop-color: #c2efd2;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #8ff0e5;stop-opacity: 1" offset="100%"></stop></linearGradient><path d="M-467.41 394.63C-467.41 554.76 -597.42 684.76 -757.55 684.76C-917.68 684.76 -1047.69 554.76 -1047.69 394.63C-1047.69 234.5 -917.68 104.49 -757.55 104.49C-597.42 104.49 -467.41 234.5 -467.41 394.63Z" id="a1uaEBd4xM"></path><path d="M-96.99 -586.14C-57.24 -619.85 -5.79 -604.75 19.26 -580.46C31.43 -568.66 56.57 -546.36 40.97 -491.67C32.76 -462.87 10.41 -436.4 -26.05 -412.27C-15.07 -377.85 -5.6 -344.76 2.36 -313C14.29 -265.36 13.55 -189.67 -26.05 -155.4C-67.27 -119.73 -166.91 -104.09 -234.24 -103.09C-301.57 -102.1 -406.19 -113.09 -461.6 -155.4C-517.01 -197.7 -512.24 -257.07 -498.04 -313C-488.58 -350.28 -476.43 -383.38 -461.6 -412.27C-505.54 -441.3 -530.54 -467.76 -536.6 -491.67C-545.68 -527.54 -530.93 -565.61 -501.12 -586.14C-471.31 -606.67 -435.18 -606.9 -400.45 -586.14C-377.3 -572.3 -354.79 -542.13 -332.92 -495.62C-287.85 -505.25 -254.96 -509.57 -234.24 -508.6C-214.74 -507.68 -186.57 -503.36 -149.72 -495.62C-135.81 -537.95 -118.23 -568.12 -96.99 -586.14Z" id="f8p7QlEjN3"></path><linearGradient id="gradienta4Tg99ZOOp" gradientUnits="userSpaceOnUse" x1="-440.25" y1="-388.59" x2="-100.49" y2="-147.33"><stop style="stop-color: #5cdd8b;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #7ae6a1;stop-opacity: 1" offset="100%"></stop></linearGradient><path d="M-86.03 -10.69C-61.35 -10.69 -41.34 9.32 -41.34 34.01C-41.34 119.07 -41.34 329.58 -41.34 414.65C-41.34 439.33 -61.35 459.34 -86.03 459.34C-136.01 459.34 -241.25 459.34 -291.23 459.34C-315.92 459.34 -335.93 439.33 -335.93 414.65C-335.93 329.58 -335.93 119.07 -335.93 34.01C-335.93 9.32 -315.92 -10.69 -291.23 -10.69C-241.25 -10.69 -136.01 -10.69 -86.03 -10.69Z" id="d32ZZRxd1S"></path><linearGradient id="gradientb1JxIe4xUm" gradientUnits="userSpaceOnUse" x1="-791.65" y1="-33.27" x2="892.1" y2="418.94"><stop style="stop-color: #5cdd8b;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #5ae98f;stop-opacity: 1" offset="100%"></stop></linearGradient><path d="M-257.95 458.12C-247.92 449.62 -234.93 453.43 -228.61 459.56C-225.54 462.54 -219.19 468.17 -223.13 481.97C-225.2 489.24 -230.84 495.92 -240.05 502.01C-237.27 510.7 -234.88 519.06 -232.88 527.07C-229.86 539.1 -230.05 558.21 -240.05 566.86C-250.45 575.86 -275.6 579.81 -292.6 580.06C-309.6 580.31 -336.01 577.54 -349.99 566.86C-363.98 556.18 -362.77 541.19 -359.19 527.07C-356.8 517.66 -353.73 509.31 -349.99 502.01C-361.08 494.69 -367.39 488.01 -368.92 481.97C-371.22 472.92 -367.49 463.31 -359.97 458.12C-352.44 452.94 -343.32 452.88 -334.56 458.12C-328.71 461.62 -323.03 469.23 -317.51 480.97C-306.13 478.54 -297.83 477.45 -292.6 477.7C-287.68 477.93 -280.56 479.02 -271.26 480.97C-267.75 470.29 -263.32 462.67 -257.95 458.12Z" id="b19LRRbPrG"></path><path d="M490.4 235.64C544.09 358.38 544.09 435.34 490.4 466.5C409.85 513.24 199.96 527.49 139.54 455.64C99.26 407.74 99.26 334.4 139.54 235.64C180.5 168.18 238.71 134.45 314.17 134.45C389.64 134.45 448.38 168.18 490.4 235.64Z" id="bN5StdyPU"></path><linearGradient id="gradientb1HT15TsY0" gradientUnits="userSpaceOnUse" x1="259.78" y1="261.15" x2="463.85" y2="456.49"><stop style="stop-color: #5cdd8b;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #86e6a9;stop-opacity: 1" offset="100%"></stop></linearGradient><path d="M393.81 -775.89C428.26 -748.09 439.99 -725.54 429 -708.22C412.51 -682.24 353.16 -646.07 324.5 -657.93C305.39 -665.83 294.22 -687.32 290.97 -722.41C292.69 -748.43 304.61 -767.19 326.73 -778.69C348.85 -790.19 371.21 -789.26 393.81 -775.89Z" id="arh6miPP2"></path><linearGradient id="gradientc2g6rBSAiq" gradientUnits="userSpaceOnUse" x1="330.1" y1="-733.26" x2="419.69" y2="-707.1"><stop style="stop-color: #5cdd8b;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #86e6a9;stop-opacity: 1" offset="100%"></stop></linearGradient><path d="M675.36 -369.24C669.97 -325.31 657.02 -303.43 636.51 -303.61C605.74 -303.87 543.67 -335.15 538.59 -365.74C535.2 -386.14 547.54 -406.99 575.61 -428.29C598.61 -440.58 620.83 -440.37 642.29 -427.67C663.74 -414.97 674.77 -395.49 675.36 -369.24Z" id="a2VENFzCvL"></path><linearGradient id="gradientc18GuJy4sZ" gradientUnits="userSpaceOnUse" x1="605.5" y1="-400.8" x2="630.64" y2="-310.92"><stop style="stop-color: #5cdd8b;stop-opacity: 1" offset="0%"></stop><stop style="stop-color: #86e6a9;stop-opacity: 1" offset="100%"></stop></linearGradient></defs><g><g><g><use xlink:href="#a1LdTs1gvU" opacity="1" fill="url(#gradientcoH7TNh19)"></use></g><g><use xlink:href="#a1uaEBd4xM" opacity="1" fill="#ebf0ed" fill-opacity="1"></use></g><g><use xlink:href="#f8p7QlEjN3" opacity="1" fill="url(#gradienta4Tg99ZOOp)"></use><g><use xlink:href="#f8p7QlEjN3" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="98" stroke-opacity="0.57"></use></g></g><g><use xlink:href="#d32ZZRxd1S" opacity="1" fill="url(#gradientb1JxIe4xUm)"></use><g><use xlink:href="#d32ZZRxd1S" opacity="1" fill-opacity="0" stroke="#f2f2f2" stroke-width="60" stroke-opacity="0.51"></use></g></g><g><use xlink:href="#b19LRRbPrG" opacity="1" fill="#d8ad9a" fill-opacity="1"></use><g><use xlink:href="#b19LRRbPrG" opacity="1" fill-opacity="0" stroke="#ffffff" stroke-width="17" stroke-opacity="1"></use></g></g><g><use xlink:href="#bN5StdyPU" opacity="1" fill="url(#gradientb1HT15TsY0)"></use><g><use xlink:href="#bN5StdyPU" opacity="1" fill-opacity="0" stroke="#f2f2f2" stroke-width="200" stroke-opacity="0.51"></use></g></g><g><use xlink:href="#arh6miPP2" opacity="1" fill="url(#gradientc2g6rBSAiq)"></use></g><g><use xlink:href="#a2VENFzCvL" opacity="1" fill="url(#gradientc18GuJy4sZ)"></use></g></g></g></svg> From 7acbfd24749e00c5a17ccb3af74408baf0c1e85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Kr=C3=BDda?= <karel.kryda@gmail.com> Date: Mon, 9 May 2022 21:05:10 +0200 Subject: [PATCH 31/59] eslint fixes too much --- CNAME | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CNAME b/CNAME index 40f0b545..44250516 100644 --- a/CNAME +++ b/CNAME @@ -1 +1 @@ -git.kuma.pet; +git.kuma.pet From 7da9f139c1bd91c80dd880c8b97c0981576c0749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Kr=C3=BDda?= <karel.kryda@gmail.com> Date: Mon, 9 May 2022 21:10:12 +0200 Subject: [PATCH 32/59] Bug fix --- server/model/monitor.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index f2d16524..eaafb775 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -182,7 +182,7 @@ class Monitor extends BeanModel { // undefined if not https let tlsInfo = undefined; - if (!previousBeat) { + if (!previousBeat || this.type === "push") { previousBeat = await R.findOne("heartbeat", " monitor_id = ? ORDER BY time DESC", [ this.id, ]); @@ -377,9 +377,6 @@ class Monitor extends BeanModel { log.debug("monitor", "heartbeatCount" + heartbeatCount + " " + time); if (heartbeatCount <= 0) { - // Fix #922, since previous heartbeat could be inserted by api, it should get from database - previousBeat = await Monitor.getPreviousHeartbeat(this.id); - throw new Error("No heartbeat in the time window"); } else { // No need to insert successful heartbeat for push type, so end here From 0cf395dfc342a350295cea73e3584bd14671b64d Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Sat, 14 May 2022 14:06:35 +0800 Subject: [PATCH 33/59] Fix merge issue --- src/components/HeartbeatBar.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue index a36c5d1c..deb2bc23 100644 --- a/src/components/HeartbeatBar.vue +++ b/src/components/HeartbeatBar.vue @@ -171,7 +171,7 @@ export default { }, getBeatTitle(beat) { - return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : ``); + return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : ""); }, // Toggling the activeSibling class on hover over the current hover item From 92a43e1f305b86e58f61ebc91cf8bc3380581520 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Sat, 14 May 2022 14:11:43 +0800 Subject: [PATCH 34/59] Make the sibling beats a bit smaller --- src/components/HeartbeatBar.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue index deb2bc23..10b1f761 100644 --- a/src/components/HeartbeatBar.vue +++ b/src/components/HeartbeatBar.vue @@ -242,7 +242,7 @@ export default { } &.active-sibling { - transform: scale(1.3); + transform: scale(1.15); transition: all ease 0.15s; } } From cec052183434f98edac6da6c81232a680050addc Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Sat, 14 May 2022 14:36:40 +0800 Subject: [PATCH 35/59] [Discord] Fix ping type should no port, update better naming --- server/notification-providers/discord.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/server/notification-providers/discord.js b/server/notification-providers/discord.js index c981d59d..77b04d9d 100644 --- a/server/notification-providers/discord.js +++ b/server/notification-providers/discord.js @@ -22,20 +22,22 @@ class Discord extends NotificationProvider { return okMsg; } - let url; + let address; switch (monitorJSON["type"]) { - case "dns": case "ping": + address = monitorJSON["hostname"]; + break; case "port": + case "dns": case "steam": - url = monitorJSON["hostname"]; + address = monitorJSON["hostname"]; if (monitorJSON["port"]) { - url += ":" + monitorJSON["port"]; + address += ":" + monitorJSON["port"]; } break; default: - url = monitorJSON["url"]; + address = monitorJSON["url"]; break; } @@ -53,8 +55,8 @@ class Discord extends NotificationProvider { value: monitorJSON["name"], }, { - name: "Service URL", - value: url, + name: "Service URL / Address", + value: address, }, { name: "Time (UTC)", @@ -89,7 +91,7 @@ class Discord extends NotificationProvider { }, { name: "Service URL", - value: url.startsWith("http") ? "[Visit Service](" + url + ")" : url, + value: address.startsWith("http") ? "[Visit Service](" + address + ")" : address, }, { name: "Time (UTC)", From 4178b003a2fbd2cfea07cc990e610ba006c747ca Mon Sep 17 00:00:00 2001 From: AnnAngela <naganjue@vip.qq.com> Date: Sat, 14 May 2022 15:27:55 +0800 Subject: [PATCH 36/59] fix `value` --- src/components/notifications/Pushover.vue | 46 +++++++++++------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/components/notifications/Pushover.vue b/src/components/notifications/Pushover.vue index 83261deb..4bf6edb3 100644 --- a/src/components/notifications/Pushover.vue +++ b/src/components/notifications/Pushover.vue @@ -18,29 +18,29 @@ </select> <label for="pushover-sound" class="form-label">{{ $t("Notification Sound") }}</label> <select id="pushover-sound" v-model="$parent.notification.pushoversounds" class="form-select"> - <option>{{ $t("pushoversounds pushover") }}</option> - <option>{{ $t("pushoversounds bike") }}</option> - <option>{{ $t("pushoversounds bugle") }}</option> - <option>{{ $t("pushoversounds cashregister") }}</option> - <option>{{ $t("pushoversounds classical") }}</option> - <option>{{ $t("pushoversounds cosmic") }}</option> - <option>{{ $t("pushoversounds falling") }}</option> - <option>{{ $t("pushoversounds gamelan") }}</option> - <option>{{ $t("pushoversounds incoming") }}</option> - <option>{{ $t("pushoversounds intermission") }}</option> - <option>{{ $t("pushoversounds magic") }}</option> - <option>{{ $t("pushoversounds mechanical") }}</option> - <option>{{ $t("pushoversounds pianobar") }}</option> - <option>{{ $t("pushoversounds siren") }}</option> - <option>{{ $t("pushoversounds spacealarm") }}</option> - <option>{{ $t("pushoversounds tugboat") }}</option> - <option>{{ $t("pushoversounds alien") }}</option> - <option>{{ $t("pushoversounds climb") }}</option> - <option>{{ $t("pushoversounds persistent") }}</option> - <option>{{ $t("pushoversounds echo") }}</option> - <option>{{ $t("pushoversounds updown") }}</option> - <option>{{ $t("pushoversounds vibrate") }}</option> - <option>{{ $t("pushoversounds none") }}</option> + <option value="pushover">{{ $t("pushoversounds pushover") }}</option> + <option value="bike">{{ $t("pushoversounds bike") }}</option> + <option value="bugle">{{ $t("pushoversounds bugle") }}</option> + <option value="cashregister">{{ $t("pushoversounds cashregister") }}</option> + <option value="classical">{{ $t("pushoversounds classical") }}</option> + <option value="cosmic">{{ $t("pushoversounds cosmic") }}</option> + <option value="falling">{{ $t("pushoversounds falling") }}</option> + <option value="gamelan">{{ $t("pushoversounds gamelan") }}</option> + <option value="incoming">{{ $t("pushoversounds incoming") }}</option> + <option value="intermission">{{ $t("pushoversounds intermission") }}</option> + <option value="magic">{{ $t("pushoversounds magic") }}</option> + <option value="mechanical">{{ $t("pushoversounds mechanical") }}</option> + <option value="pianobar">{{ $t("pushoversounds pianobar") }}</option> + <option value="siren">{{ $t("pushoversounds siren") }}</option> + <option value="spacealarm">{{ $t("pushoversounds spacealarm") }}</option> + <option value="tugboat">{{ $t("pushoversounds tugboat") }}</option> + <option value="alien">{{ $t("pushoversounds alien") }}</option> + <option value="climb">{{ $t("pushoversounds climb") }}</option> + <option value="persistent">{{ $t("pushoversounds persistent") }}</option> + <option value="echo">{{ $t("pushoversounds echo") }}</option> + <option value="updown">{{ $t("pushoversounds updown") }}</option> + <option value="vibrate">{{ $t("pushoversounds vibrate") }}</option> + <option value="none">{{ $t("pushoversounds none") }}</option> </select> <div class="form-text"> <span style="color: red;"><sup>*</sup></span>{{ $t("Required") }} From 398219f847571619bbb3e7124bf27e7915874a69 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Tue, 17 May 2022 01:03:51 +0800 Subject: [PATCH 37/59] Update to 1.16.0-beta.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e9b7003b..1ba25baf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uptime-kuma", - "version": "1.15.1", + "version": "1.16.0-beta.0", "license": "MIT", "repository": { "type": "git", From 175556f9fc0ae5411440451d1ba7ab7d310172f8 Mon Sep 17 00:00:00 2001 From: Alexis Lefebvre <alexislefebvre@users.noreply.github.com> Date: Mon, 16 May 2022 20:30:16 +0200 Subject: [PATCH 38/59] s/cros/CORS --- src/pages/StatusPage.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index 00857db5..22608116 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -688,7 +688,7 @@ export default { }, statusPageLogoLoaded(eventPayload) { - // Remark: may not work in dev, due to cros + // Remark: may not work in dev, due to CORS favicon.image(eventPayload.target); }, From 9fc5a3329f7db09733c40c27726fb3b05e903c6f Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Wed, 18 May 2022 20:16:50 +0800 Subject: [PATCH 39/59] Revert #1208, due to the break animation --- src/assets/app.scss | 2 +- src/components/HeartbeatBar.vue | 47 +++--------------------------- src/components/PublicGroupList.vue | 8 ++--- 3 files changed, 9 insertions(+), 48 deletions(-) diff --git a/src/assets/app.scss b/src/assets/app.scss index 8eaff499..c3f2fa79 100644 --- a/src/assets/app.scss +++ b/src/assets/app.scss @@ -367,7 +367,7 @@ textarea.form-control { .item { display: block; text-decoration: none; - padding: 15px; + padding: 13px 15px 10px 15px; border-radius: 10px; transition: all ease-in-out 0.15s; diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue index 10b1f761..ce888a98 100644 --- a/src/components/HeartbeatBar.vue +++ b/src/components/HeartbeatBar.vue @@ -1,6 +1,6 @@ <template> <div ref="wrap" class="wrap" :style="wrapStyle"> - <div class="hp-bar-big d-flex" :style="barStyle"> + <div class="hp-bar-big" :style="barStyle"> <div v-for="(beat, index) in shortBeatList" :key="index" @@ -8,11 +8,7 @@ :class="{ 'empty' : (beat === 0), 'down' : (beat.status === 0), 'pending' : (beat.status === 2) }" :style="beatStyle" :title="getBeatTitle(beat)" - @mouseenter="toggleActivateSibling" - @mouseleave="toggleActivateSibling" - > - <div class="beat-inner" /> - </div> + /> </div> </div> </template> @@ -174,28 +170,6 @@ export default { return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : ""); }, - // Toggling the activeSibling class on hover over the current hover item - toggleActivateSibling(e) { - // Variable definition - const element = e.target; - const previous = element.previousSibling; - const next = element.nextSibling; - - // Return if the hovered element has empty class - if (element.classList.contains("empty")) { - return; - } - - // Check if Previous Sibling is heartbar element and doesn't have the empty class - if (previous.children && !previous.classList.contains("empty")) { - previous.classList.toggle("active-sibling"); - } - - // Check if Next Sibling is heartbar element and doesn't have the empty class - if (next.children && !next.classList.contains("empty")) { - next.classList.toggle("active-sibling"); - } - } }, }; </script> @@ -211,10 +185,9 @@ export default { .hp-bar-big { .beat { + display: inline-block; background-color: $primary; border-radius: $border-radius; - display: inline-block; - transition: all ease 0.6s; &.empty { background-color: aliceblue; @@ -228,23 +201,11 @@ export default { background-color: $warning; } - .beat-inner { - border-radius: $border-radius; - display: inline-block; - height: 100%; - width: 5px; - } - &:not(.empty):hover { - transition: all ease 0.15s; + transition: all ease-in-out 0.15s; opacity: 0.8; transform: scale(var(--hover-scale)); } - - &.active-sibling { - transform: scale(1.15); - transition: all ease 0.15s; - } } } diff --git a/src/components/PublicGroupList.vue b/src/components/PublicGroupList.vue index 4d0ada5c..98c0b7ff 100644 --- a/src/components/PublicGroupList.vue +++ b/src/components/PublicGroupList.vue @@ -33,19 +33,19 @@ <template #item="monitor"> <div class="item"> <div class="row"> - <div class="col-9 col-md-8 small-padding d-flex align-items-center flex-wrap"> - <div class="info d-flex align-items-center gap-3 w-100"> + <div class="col-9 col-md-8 small-padding"> + <div class="info"> <font-awesome-icon v-if="editMode" icon="arrows-alt-v" class="action drag me-3" /> <font-awesome-icon v-if="editMode" icon="times" class="action remove me-3" @click="removeMonitor(group.index, monitor.index)" /> <Uptime :monitor="monitor.element" type="24" :pill="true" /> {{ monitor.element.name }} </div> - <div v-if="showTags && monitor.element.tags.length > 0" class="tags"> + <div v-if="showTag" class="tags"> <Tag v-for="tag in monitor.element.tags" :key="tag" :item="tag" :size="'sm'" /> </div> </div> - <div :key="$root.userHeartbeatBar" class="col-3 col-md-4 d-flex align-items-center"> + <div :key="$root.userHeartbeatBar" class="col-3 col-md-4"> <HeartbeatBar size="small" :monitor-id="monitor.element.id" /> </div> </div> From 4c3aa20eb0720088894f828a17fcb17a1a6f38fb Mon Sep 17 00:00:00 2001 From: MrEddX <66828538+MrEddX@users.noreply.github.com> Date: Wed, 18 May 2022 22:18:58 +0300 Subject: [PATCH 40/59] Update bg-BG.js Added new fields --- src/languages/bg-BG.js | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/languages/bg-BG.js b/src/languages/bg-BG.js index 94553bd0..6297062a 100644 --- a/src/languages/bg-BG.js +++ b/src/languages/bg-BG.js @@ -464,4 +464,55 @@ export default { "Domain Names": "Домейни", signedInDisp: "Вписан като {0}", signedInDispDisabled: "Удостоверяването е изключено.", + "Certificate Expiry Notification": "Известие за изтичане валидността на сертификата", + "API Username": "API Потребител", + "API Key": "API Ключ", + "Recipient Number": "Номер на получателя", + "From Name/Number": "От Име/Номер", + "Leave blank to use a shared sender number.": "Оставете празно, за да използвате споделен номер на подател.", + "Octopush API Version": "Octopush API версия", + "Legacy Octopush-DM": "Octopush-DM старa версия", + endpoint: "крайна точка", + octopushAPIKey: "\"API ключ\" от HTTP API удостоверяване в контролния панел", + octopushLogin: "\"Вписване\" от HTTP API удостоверяване в контролния панел", + promosmsLogin: "API Потребителско име", + promosmsPassword: "API Парола", + "pushoversounds pushover": "Pushover (по подразбиране)", + "pushoversounds bike": "Велосипед", + "pushoversounds bugle": "Тромпет", + "pushoversounds cashregister": "Касов апарат", + "pushoversounds classical": "Класическа музика", + "pushoversounds cosmic": "Космически", + "pushoversounds falling": "Падащ", + "pushoversounds gamelan": "Игра в мрежа", + "pushoversounds incoming": "Входящ", + "pushoversounds intermission": "Прекъсване", + "pushoversounds magic": "Магия", + "pushoversounds mechanical": "Механичен", + "pushoversounds pianobar": "Пиано бар", + "pushoversounds siren": "Сирена", + "pushoversounds spacealarm": "Космическа аларма", + "pushoversounds tugboat": "Буксир", + "pushoversounds alien": "Извънземна аларма (дълъг)", + "pushoversounds climb": "Изкачване (дълъг)", + "pushoversounds persistent": "Постоянен (дълъг)", + "pushoversounds echo": "Pushover ехо (дълъг)", + "pushoversounds updown": "Горе долу (дълъг)", + "pushoversounds vibrate": "Само вибрация", + "pushoversounds none": "Без (тих)", + pushyAPIKey: "Таен API ключ", + pushyToken: "Токен на устройство", + "Show update if available": "Покажи актуализация, ако е налична", + "Also check beta release": "Проверявай и за бета версии", + "Using a Reverse Proxy?": "Използвате ревърс прокси?", + "Check how to config it for WebSocket": "Проверете как да го конфигурирате за WebSocket", + "Steam Game Server": "Steam Game сървър", + "Most likely causes:": "Най-вероятни причини:", + "The resource is no longer available.": "Ресурсът вече не е наличен.", + "There might be a typing error in the address.": "Възможно е да е допусната грешка при изписването на адреса.", + "What you can try:": "Може да опитате:", + "Retype the address.": "Повторно въвеждане на адреса.", + "Go back to the previous page.": "Да се върнете към предишната страница.", + "Coming Soon": "Очаквайте скоро", + wayToGetClickSendSMSToken: "Може да получите API потребителско име и API ключ от {0} .", }; From 93e5023eadf5752e36cc02097f91867065c49574 Mon Sep 17 00:00:00 2001 From: Yoswaris Lawpaiboon <22832362+kiznick@users.noreply.github.com> Date: Thu, 19 May 2022 19:44:59 +0700 Subject: [PATCH 41/59] Translate to Thai ! --- src/components/settings/Security.vue | 6 + src/i18n.js | 1 + src/languages/th-TH.js | 518 +++++++++++++++++++++++++++ 3 files changed, 525 insertions(+) create mode 100644 src/languages/th-TH.js diff --git a/src/components/settings/Security.vue b/src/components/settings/Security.vue index 87bb745a..17e161a9 100644 --- a/src/components/settings/Security.vue +++ b/src/components/settings/Security.vue @@ -234,6 +234,12 @@ <p>Vui lòng <strong>cẩn thận</strong>.</p> </template> + <template v-else-if="$i18n.locale === 'th-TH' "> + <p>คุณต้องการที่จะ <strong>ปิดใช้งานระบบรับรองความถูกต้องใช่หรือไม่</strong>?</p> + <p>ระบบนี้ถูกออกแบบมาเพื่อการใช้งานกับระบบรับรองความถูกต้องของบุคคลที่สามเช่น Cloudflare Access, Authelia หรือวิธีการอื่น ๆ</p> + <p>โปรดใช้ความระมัดระวังในการเลือกใช้งานระบบนี้ !</p> + </template> + <!-- English (en) --> <template v-else> <p>Are you sure want to <strong>disable authentication</strong>?</p> diff --git a/src/i18n.js b/src/i18n.js index 83a31991..82e95d3d 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -31,6 +31,7 @@ const languageList = { "vi-VN": "Tiếng Việt", "zh-TW": "繁體中文 (台灣)", "uk-UA": "Український", + "th-TH": "ไทย", }; let messages = { diff --git a/src/languages/th-TH.js b/src/languages/th-TH.js new file mode 100644 index 00000000..b313deb0 --- /dev/null +++ b/src/languages/th-TH.js @@ -0,0 +1,518 @@ +export default { + languageName: "ไทย", + checkEverySecond: "ตรวจสอบทุก {0} วินาที", + retryCheckEverySecond: "ลองใหม่ทุก {0} วินาที", + retriesDescription: "จำนวนครั้งสูงสุดที่จะลองก่อนบริการถูกระบุว่าไม่สามารถใช้งานได้และส่งการแจ้งเตือน", + ignoreTLSError: "ไม่สนใจข้อผิดพลาด TLS/SSL สำหรับเว็บไซต์ HTTPS", + upsideDownModeDescription: "กลับด้านสถานะ เช่น ถ้าบริการสามารถใช้งานได้จะถูกเปลี่ยนเป็นใช้งานไม่ได้", + maxRedirectDescription: "จำนวนครั้งสูงสุดที่จะเปลี่ยนเส้นทาง, ตั่งเป็น 0 เพื่อปิดการเปลี่ยนเส้นทาง", + acceptedStatusCodesDescription: "เลือกรหัสสถานะที่ถือว่าการตอบกลับสำเร็จ", + passwordNotMatchMsg: "รหัสผ่านไม่ตรงกัน", + notificationDescription: "การแจ้งเตือนต้องกำหนดให้มอนิเตอร์เพื่อให้สามารถใช้งานได้", + keywordDescription: "ค้นหาคำสำคัญใน HTML หรือ JSON ของการตอบกลับ, คำสำคัญต้องคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่", + pauseDashboardHome: "หยุดชั่วคราว", + deleteMonitorMsg: "คุณแน่ใจหรือไม่ที่จะลบมอนิเตอร์?", + deleteNotificationMsg: "คุณแน่ใจหรือไม่ที่จะลบการแจ้งเตือนสำหรับมอนิเตอร์ทั้งหมด?", + resolverserverDescription: "Cloudflare เป็นเซิร์ฟเวอร์ค้นหาเริ่มต้น, คุณสามารถเปลี่ยนเซิร์ฟเวอร์ได้ตลอดเวลา", + rrtypeDescription: "เลือกประเภท DNS Record ที่คุณต้องการจะมอนิเตอร์", + pauseMonitorMsg: "คุณแน่ใจหรือไม่ที่จะหยุดมอนิเตอร์ชั่วคราว?", + enableDefaultNotificationDescription: "การแจ้งเตือนนี้จะถูกเปิดโดนค่าเริ่มต้นสำหรับมอนิเตอร์ใหม่, คุณสามารถปิดการแจ้งเตือนสำหรับแต่ละมอนิเตอร์ได้", + clearEventsMsg: "คุณแน่ใจหรือไม่ที่จะลบเหตุการณ์ทั้งหมดสำหรับมอนิเตอร์นี้?", + clearHeartbeatsMsg: "คุณแน่ใจหรือไม่ที่จะลบประวัติการตรวจสอบทั้งหมดสำหรับมอนิเตอร์นี้?", + confirmClearStatisticsMsg: "คุณแน่ใจหรือไม่ที่จะลบสถิติทั้งหมด?", + importHandleDescription: "เลือก \"ข้ามรายการที่มีอยู่แล้ว\" ถ้าคุณต้องการข้ามทุกมอนิเตอร์หรือการแจ้งเตือนที่มีชื่อซ้ำกัน, \"เขียนทับ\" จะลบทุกมอนิเตอร์หรือการแจ้งเตือนที่มีชื่อซ้ำกัน", + confirmImportMsg: "คุณแน่ใจหรือไม่ที่จะนำเข้าข้อมูลสำรอง, กรุณาตรวจสอบว่าคุณเลือกข้อมูลที่ถูกต้อง", + twoFAVerifyLabel: "โปรดกรอกกุญแจ 2FA ของคุณเพื่อยืนยัน:", + tokenValidSettingsMsg: "กุญแจถูกต้อง, ตอนนี้คุณสามารถบันทึกการตั้งค่า 2FA ของคุณได้แล้ว", + confirmEnableTwoFAMsg: "คุณแน่ใจหรือไม่ที่จะเปิดใช้งาน 2FA?", + confirmDisableTwoFAMsg: "คุณแน่ใจหรือไม่ที่จะปิดใช้งาน 2FA?", + Settings: "การตั่งค่า", + Dashboard: "แผงควบคุม", + "New Update": "อัพเดทใหม่", + Language: "ภาษา", + Appearance: "รูปร่าง", + Theme: "หน้าตา", + General: "ทั่วไป", + "Primary Base URL": "URL หลัก", + Version: "เวอร์ชั่น", + "Check Update On GitHub": "ตรวจสอบการอัปเดตบน GitHub", + List: "รายการ", + Add: "เพิ่ม", + "Add New Monitor": "เพิ่มมอนิเตอร์ใหม่", + "Quick Stats": "สถิติด่วน", + Up: "ใช้งานได้", + Down: "ไม่สามารถใช้งานได้", + Pending: "รอดำเนินการ", + Unknown: "ไม่ทราบ", + Pause: "หยุดชั่วคราว", + Name: "ชื่อ", + Status: "สถานะ", + DateTime: "วันที่และเวลา", + Message: "ข้อความ", + "No important events": "ไม่มีกิจกรรมที่สำคัญ", + Resume: "ดำเนินการต่อ", + Edit: "แก้ไข", + Delete: "ลบ", + Current: "ปัจจุบัน", + Uptime: "เวลาที่ใช้งาน", + "Cert Exp.": "วันหมดอายุใบรับรอง", + days: "วัน", + day: "วัน", + "-day": "-วัน", + hour: "ชั่วโมง", + "-hour": "-ชั่วโมง", + Response: "การตอบสนอง", + Ping: "การตอบสนอง", + "Monitor Type": "ประเภทมอนิเตอร์", + Keyword: "คำสำคัญ", + "Friendly Name": "ชื่อที่เป็นมิตร", + URL: "URL", + Hostname: "ชื่อโฮสต์", + Port: "พอร์ต", + "Heartbeat Interval": "ระยะห่างระหว่างการทดสอบ", + Retries: "จำนวนครั้งที่จะลองใหม่", + "Heartbeat Retry Interval": "ระยะห่างระหว่างการทดสอบใหม่หลังจากไม่สำเร็จ", + Advanced: "ขั้นสูง", + "Upside Down Mode": "โหมดกลับด้าน", + "Max. Redirects": "จำนวนการเปลี่ยนเส้นทางสูงสุด", + "Accepted Status Codes": "รหัสสถานะที่ยอมรับ", + "Push URL": "URL เป้าหมาย", + needPushEvery: "คุณควรเรียก URL นี้ทุก {0} วินาที", + pushOptionalParams: "ตัวแปรเสริม: {0}", + Save: "บันทึก", + Notifications: "การแจ้งเตือน", + "Not available, please setup.": "ไม่พร้อมใช้งาน, กรุณาตั้งค่า", + "Setup Notification": "ตั้งค่าการแจ้งเตือน", + Light: "สว่าง", + Dark: "มืด", + Auto: "อัตโนมัติ", + "Theme - Heartbeat Bar": "หน้าตา - แถบการตอบสนอง", + Normal: "ปกติ", + Bottom: "ด้านล่าง", + None: "ไม่มี", + Timezone: "เขตเวลา", + "Search Engine Visibility": "การมองเห็นของเครื่องมือค้นหา", + "Allow indexing": "อนุญาตให้สร้างดัชนี", + "Discourage search engines from indexing site": "ปฏิเสธเครื่องมือค้นหาไม่ให้สร้างดัชนีของเว็บไซต์", + "Change Password": "เปลี่ยนรหัสผ่าน", + "Current Password": "รหัสผ่านปัจจุบัน", + "New Password": "รหัสผ่านใหม่", + "Repeat New Password": "ยืนยันรหัสผ่านใหม่", + "Update Password": "อัพเดทรหัสผ่าน", + "Disable Auth": "ปิดใช้งานการตรวจสอบสิทธิ์", + "Enable Auth": "เปิดใช้งานการตรวจสอบสิทธิ์", + Logout: "ออกจากระบบ", + Leave: "ออก", + "I understand, please disable": "ฉันเข้าใจแล้ว, กรุณาปิดการใช้งาน", + Confirm: "ยืนยัน", + Yes: "ใช่", + No: "ไม่", + Username: "ชื่อผู้ใช้", + Password: "รหัสผ่าน", + "Remember me": "คงอยู่ในระบบ", + Login: "เข้าสู่ระบบ", + "No Monitors, please": "ไม่มีมอนิเตอร์, กรุณา", + "add one": "สร้าง", + "Notification Type": "ประเภทการแจ้งเตือน", + Email: "อีเมล", + Test: "ทดสอบ", + "Certificate Info": "ข้อมูลใบรับรอง", + "Resolver Server": "เซิร์ฟเวอร์ทีค้นหา", + "Resource Record Type": "ประเภท DNS Record", + "Last Result": "ผลล่าสุด", + "Create your admin account": "สร้างบัญชีผู้ดูแลระบบ", + "Repeat Password": "ยืนยันรหัสผ่าน", + "Import Backup": "นำเข้าข้อมูลสำรอง", + "Export Backup": "ส่งออกข้อมูลสำรอง", + Export: "ส่งออก", + Import: "นำเข้า", + respTime: "ระยะเวลาการตอบสนอง (ms)", + notAvailableShort: "ไม่สามารถใช้งานได้", + "Default enabled": "เปิดใช้งานโดยค่าเริ่มต้น", + "Apply on all existing monitors": "ใช้กับมอนิเตอร์ทั้งหมด", + Create: "สร้าง", + "Clear Data": "ล้างข้อมูล", + Events: "เหตุการณ์", + Heartbeats: "ประวัติการตรวจสอบ", + "Auto Get": "ดึงอัตโนมัติ", + backupDescription: "คุณสามารถสำรองข้อมูลการแจ้งเตือนและมอนิเตอร์ทั้งหมดได้ในไฟล์ JSON", + backupDescription2: "หมายเหตุ : ประวัติและข้อมูลกิจกรรมจะไม่ถูกสำรอง", + backupDescription3: "ข้อมูลที่ละเอียดอ่อนเช่นกุญแจการแจ้งเตือนจะรวมอยู่ในไฟล์ข้อมูลสำรอง, โปรดเก็บข้อมูลสำรองอย่างปลอดภัย", + alertNoFile: "กรุณาเลือกไฟล์ที่จะใช้งาน", + alertWrongFileType: "กรุณาเลือกไฟล์ที่เป็น JSON", + "Clear all statistics": "ล้างข้อมูลสถิติทั้งหมด", + "Skip existing": "ข้ามรายการที่มีอยู่แล้ว", + Overwrite: "เขียนทับ", + Options: "ตัวเลือก", + "Keep both": "เก็บทั้งสอง", + "Verify Token": "ยืนยันกุญแจ", + "Setup 2FA": "ติดตั้ง 2FA", + "Enable 2FA": "เปิดใช้งาน 2FA", + "Disable 2FA": "ปิดใช้งาน 2FA", + "2FA Settings": "ตั่งค่า 2FA", + "Two Factor Authentication": "การตรวจสอบสิทธิ์สองปัจจัย", + Active: "ใช้งาน", + Inactive: "ไม่ใช้งาน", + Token: "กุญแจ", + "Show URI": "แสดง URI", + Tags: "แท็ก", + "Add New below or Select...": "เพิ่มใหม่ด้านล่างหรือเลือก...", + "Tag with this name already exist.": "แท็กที่มีชื่อนี้มีอยู่แล้ว", + "Tag with this value already exist.": "แท็กที่มีข้อมูลนี้มีอยู่แล้ว", + color: "สี", + "value (optional)": "ข้อมูล (ไม่จำเป็น)", + Gray: "เทา", + Red: "แดง", + Orange: "ส้ม", + Green: "เขียว", + Blue: "น้ำเงิน", + Indigo: "ม่วง", + Purple: "ม่วง", + Pink: "ชมพู", + "Search...": "ค้นหา...", + "Avg. Ping": "ค่า Ping เฉลี่ย", + "Avg. Response": "ค่า Response เฉลี่ย", + "Entry Page": "หน้าต้อนรับ", + statusPageNothing: "ไม่มีอะไรตรงนี้ !, กรุณาเพิ่มกลุ่มหรือมอนิเตอร์", + "No Services": "ไม่มีบริการ", + "All Systems Operational": "บริการทั้งหมดทำงานได้ปกติ", + "Partially Degraded Service": "บริการมีปัญหาบางส่วน", + "Degraded Service": "บริการมีปัญหา", + "Add Group": "เพิ่มกลุ่ม", + "Add a monitor": "เพิ่มมอนิเตอร์", + "Edit Status Page": "แก้ไขหน้าสถานะ", + "Go to Dashboard": "ไปที่หน้าควบคุม", + "Status Page": "หน้าสถานะ", + "Status Pages": "หน้าสถานะ", + defaultNotificationName: "การแจ้งเตือน {notification} ของฉัน ({number})", + here: "ที่นี่", + Required: "ต้องการ", + telegram: "Telegram", + "Bot Token": "กุญแจของบอท", + wayToGetTelegramToken: "คุณสามารถรับกุญแจได้จาก {0}.", + "Chat ID": "ไอดีแชท", + supportTelegramChatID: "รองรับ แชทส่วนตัว, แชทกลุ่ม, ไอดีแชท", + wayToGetTelegramChatID: "คุณสามารถรับ ID แชทของคุณได้โดยส่งข้อความไปยังบอทและไปที่ URL นี้เพื่อดู chat_id :", + "YOUR BOT TOKEN HERE": "กุญแจของบอทของคุณที่นี่", + chatIDNotFound: "ไม่พบไอดีแชท, กรุณาส่งข้อความไปที่บอท", + webhook: "Webhook", + "Post URL": "URL โพสต์", + "Content Type": "ประเภทเนื้อหา", + webhookJsonDesc: "{0} ดีสำหรับเซิร์ฟเวอร์ HTTP สมัยใหม่เช่น Express.js", + webhookFormDataDesc: "{multipart} ดีสำหรับ PHP, JSON จะต้องถูกประมวลผลด้วย {decodeFunction}", + smtp: "Email (SMTP)", + secureOptionNone: "None / STARTTLS (25, 587)", + secureOptionTLS: "TLS (465)", + "Ignore TLS Error": "Ignore TLS Error", + "From Email": "From Email", + emailCustomSubject: "Custom Subject", + "To Email": "To Email", + smtpCC: "CC", + smtpBCC: "BCC", + discord: "Discord", + "Discord Webhook URL": "Discord Webhook URL", + wayToGetDiscordURL: "คุณสามารถรับได้โดยการไปที่ Server Settings -> Integrations -> Create Webhook", + "Bot Display Name": "ชื่อบอท", + "Prefix Custom Message": "คำนำหน้าข้อความที่กำหนดเอง", + "Hello @everyone is...": "สวัสดี {'@'}everyone นี่...", + teams: "Microsoft Teams", + "Webhook URL": "Webhook URL", + wayToGetTeamsURL: "คุณสามารถเรียนรู้วิธีการสร้าง Webhook URL {0}", + signal: "Signal", + Number: "หมายเลข", + Recipients: "ผู้รับ", + needSignalAPI: "คุณต้องมี Signal Client ที่มี Rest APIl", + wayToCheckSignalURL: "คุณสามารถตรวจสอบ URL นี้เพื่อดูวิธีตั้งค่า :", + signalImportant: "สำคัญ: คุณไม่สามารถผสมกลุ่มและตัวเลขในผู้รับได้!", + gotify: "Gotify", + "Application Token": "กุญแจของแอพพลิเคชั่น", + "Server URL": "Server URL", + Priority: "ลำดับความสำคัญ", + slack: "Slack", + "Icon Emoji": "Icon Emoji", + "Channel Name": "ชื่อห้อง", + "Uptime Kuma URL": "Uptime Kuma URL", + aboutWebhooks: "ข้อมูลเพิ่มเติมสำหรับ Webhooks : {0}", + aboutChannelName: "ใส่ชื่อห้องบน {0} ในช่องชื่อห้องถ้าต้องการที่จะข้าม Webhook, เช่น: #ช่องอื่นๆ", + aboutKumaURL: "ถ้าคุณไม่ใส่ข้อมูลในช่อง Uptime Kuma URL ค่าเริ่มต้นจะเป็นจะเป็น Uptime Kuma Github", + emojiCheatSheet: "ตาราง Emoji : {0}", + "rocket.chat": "Rocket.Chat", + pushover: "Pushover", + pushy: "Pushy", + PushByTechulus: "Push by Techulus", + octopush: "Octopush", + promosms: "PromoSMS", + clicksendsms: "ClickSend SMS", + lunasea: "LunaSea", + apprise: "Apprise (รองรับการแจ้งเตือนมากกว่า 50 บริการ)", + GoogleChat: "Google Chat (Google Workspace only)", + pushbullet: "Pushbullet", + line: "Line Messenger", + mattermost: "Mattermost", + "User Key": "กุญแจผู้ใช้งาน", + Device: "อุปกรณ์", + "Message Title": "หัวข้อข้อความ", + "Notification Sound": "เสียงแจ้งเตือน", + "More info on:": "ข้อมูลเพิ่มเติม : {0}", + pushoverDesc1: "ลำดับความสำตคญฉุกเฉิน (2) มีการหมดเวลาเริ่มต้น 30 วินาทีระหว่างลองใหม่และจะหมดอายุหลังจาก 1 ชั่วโมง", + pushoverDesc2: "ถ้าคุณต้องการจะส่งการแจ้งเตือนไปยังอุปกรณ์อื่น ๆ สามารถกำหนดได้ที่ช่องอุปกรณ์", + "SMS Type": "ประเภท SMS", + octopushTypePremium: "พรีเมี่ยม (เร็ว - แนะนำสำหรับการแจ้งเตือน)", + octopushTypeLowCost: "ต้นทุนต่ำ (ช้า - บางครั้งจะถูกบล็อกโดยผู้ให้บริการ)", + checkPrice: "ตรวจสอบราคาของ {0} :", + apiCredentials: "ข้อมูลการตรวจสอบสิทธิ์ API", + octopushLegacyHint: "คุณใช้เวอร์ชันดั้งเดิมของ Octopush (2011 - 2020) หรือเวอร์ชันใหม่หรือไม่?", + "Check octopush prices": "ตรวจสอบราคาของ Octopush {0}", + octopushPhoneNumber: "หมายเลขโทรศัพท์ (รูปแบบสากล เช่น +33612345678) ", + octopushSMSSender: "ชื่อผู้ส่ง SMS : ความยาว 3 - 11 ตัวอักษร, ตัวเลข และช่องว่าง (a-zA-Z0-9 )", + "LunaSea Device ID": "ไอดีอุปกรณ์ LunaSea", + "Apprise URL": "Apprise URL", + "Example:": "ตัวอย่าง : {0}", + "Read more:": "อ่านเพิ่มเติม : {0}", + "Status:": "สถานะ : {0}", + "Read more": "อ่านเพิ่มเติม", + appriseInstalled: "Apprise ถูกติดตั่งแล้ว", + appriseNotInstalled: "Apprise ยังไม่ถูกติดตั่ง {0}", + "Access Token": "กุญแจการเข้าถึง", + "Channel access token": "กุญแจการเข้าถึงของช่อง", + "Line Developers Console": "Line Developers Console", + lineDevConsoleTo: "Line Developers Console - {0}", + "Basic Settings": "การตั้งค่าพื้นฐาน", + "User ID": "ไอดีผู้ใช้", + "Messaging API": "Messaging API", + wayToGetLineChannelToken: "ขั้นแรกให้เข้า {0} สร้างผู้ให้บริการและช่องทาง (Messaging API) จากนั้นคุณจะได้รับกุญแจการเข้าถึงช่องและไอดีผู้ใช้จากรายการเมนูที่กล่าวถึงข้างต้น", + "Icon URL": "Icon URL", + aboutIconURL: "คุณสามารถระบุลิงก์ไปยังรูปภาพใน \"URL ไอคอน\" เพื่อแทนที่รูปภาพโปรไฟล์เริ่มต้น จะไม่ถูกใช้หากมีการตั้งค่า Icon Emoji", + aboutMattermostChannelName: "คุณลบล้างช่องเริ่มต้นที่ Webhook โพสต์ได้ด้วยการป้อนชื่อช่องลงในช่อง \"ชื่อช่อง\" ต้องเปิดใช้งานในการตั้งค่า Mattermost Webhook เช่น #ช่องอื่นๆ", + matrix: "Matrix", + promosmsTypeEco: "SMS ECO - ราคาถูก แต่ช้าและมักจะโอเวอร์โหลด จำกัดเฉพาะผู้รับโปแลนด์", + promosmsTypeFlash: "SMS FLASH - ข้อความจะแสดงบนอุปกรณ์ของผู้รับโดยอัตโนมัติ จำกัดเฉพาะผู้รับโปแลนด์", + promosmsTypeFull: "SMS FULL - SMS ระดับพรีเมียม คุณสามารถใช้ชื่อผู้ส่งของคุณได้ (คุณต้องลงทะเบียนชื่อก่อน) เชื่อถือได้สำหรับการแจ้งเตือน", + promosmsTypeSpeed: "SMS SPEED - ลำดับความสำคัญสูงสุดในระบบ รวดเร็วและเชื่อถือได้ แต่มีค่าใช้จ่ายสูง (ประมาณสองเท่าของราคาเต็ม SMS)", + promosmsPhoneNumber: "หมายเลขโทรศัพท์ (สำหรับผู้รับโปแลนด์ คุณสามารถข้ามรหัสพื้นที่ได้)", + promosmsSMSSender: "ชื่อผู้ส่ง SMS : ชื่อที่ลงทะเบียนล่วงหน้าหรือหนึ่งในค่าเริ่มต้น: InfoSMS, ข้อมูล SMS, MaxSMS, INFO, SMS", + "Feishu WebHookUrl": "Feishu WebHookURL", + matrixHomeserverURL: "URL ของโฮมเซิร์ฟเวอร์ (พร้อม http(s):// และพอร์ตเสริม)", + "Internal Room Id": "รหัสห้องภายใน", + matrixDesc1: "คุณค้นหารหัสห้องภายในได้โดยดูในส่วนขั้นสูงของการตั้งค่าห้องในไคลเอ็นต์ Matrix มันควรจะมีลักษณะเช่น !PMdRCpsIfLwsfjIye6:kiznick.server.", + matrixDesc2: "ขอแนะนำเป็นอย่างยิ่งให้คุณสร้างผู้ใช้ใหม่และอย่าใช้โทเค็นการเข้าถึงของผู้ใช้ Matrix ของคุณเอง เนื่องจากจะทำให้สามารถเข้าถึงบัญชีของคุณและห้องทั้งหมดที่คุณเข้าร่วมได้อย่างเต็มที่ ให้สร้างผู้ใช้ใหม่และเชิญเฉพาะห้องที่คุณต้องการรับการแจ้งเตือนแทน คุณสามารถรับโทเค็นเพื่อการเข้าถึงได้โดยเรียกใช้ {0}", + Method: "วิธี", + Body: "เนื้อหา", + Headers: "ส่วนหัว", + PushUrl: "Push URL", + HeadersInvalidFormat: "เนื้อหาคำขอส่วนหัวไม่ใช่ JSON ที่ถูกต้อง :", + BodyInvalidFormat: "เนื้อหาคำขอไม่ใช่ JSON ที่ถูกต้อง : ", + "Monitor History": "ประวัติมอนิเตอร์", + clearDataOlderThan: "เก็บข้อมูลมอนิเตอร์ {0} วัน", + PasswordsDoNotMatch: "รหัสผ่านไม่ตรงกัน", + records: "บันทึก", + "One record": "หนึ่งบันทึก", + steamApiKeyDescription: "สำหรับการมอนิเตอร์ Steam Game Server คุณต้องมี Steam Web-API key, คุณสามารถรสมัครได้จากที่นี่ : ", + "Current User": "ผู้ใช้ปัจจุบัน", + topic: "หัวข้อ", + topicExplanation: "MQTT หัวข้อที่จะมอนิเตอร์", + successMessage: "ข้อความที่จะถือว่าประสบความสำเร็จ", + successMessageExplanation: "MQTT ข้อความที่จะถือว่าประสบความสำเร็จ", + recent: "ล่าสุด", + Done: "สำเร็จ", + Info: "ข้อมูล", + Security: "ความปลอดภัย", + "Steam API Key": "Steam API Key", + "Shrink Database": "ย่อฐานข้อมูล", + "Pick a RR-Type...": "เลือกชนิด DNS Record", + "Pick Accepted Status Codes...": "เลือกสถานะที่ยอมรับ...", + Default: "ค่าเริ่มต้น", + "HTTP Options": "ตัวเลือก HTTP", + "Create Incident": "สร้างเหตุการณ์", + Title: "หัวข้อ", + Content: "เนื้อหา", + Style: "สไตล์", + info: "ข้อมูล", + warning: "แจ้งเตือน", + danger: "อันตราย", + primary: "หลัก", + light: "สว่าง", + dark: "มืด", + Post: "โพสต์", + "Please input title and content": "กรุณาใส่ชื่อและเนื้อหา", + Created: "สร้าง", + "Last Updated": "อัพเดทล่าสุด", + Unpin: "เลิกตรึง", + "Switch to Light Theme": "เปลี่ยนเป็นแบบสว่าง", + "Switch to Dark Theme": "เปลี่ยนเป็นแบบมืด", + "Show Tags": "แสดงแท็ก", + "Hide Tags": "ซ่อนแท็ก", + Description: "รายละเอียด", + "No monitors available.": "ไม่มีมอนิเตอร์ที่สามารถใช้งานได้", + "Add one": "เพิ่ม", + "No Monitors": "ไม่มีมอนิเตอร์", + "Untitled Group": "กลุ่มที่ไม่มีชื่อ", + Services: "บริการ", + Discard: "ทิ้ง", + Cancel: "ยกเลิก", + "Powered by": "ขับเคลื่อนโดย", + shrinkDatabaseDescription: "ทริกเกอร์ฐานข้อมูล VACUUM สำหรับ SQLite หากฐานข้อมูลของคุณถูกสร้างขึ้นหลังจาก 1.10.0 แสดงว่า AUTO_VACUUM เปิดใช้งานอยู่แล้วและไม่จำเป็นต้องดำเนินการนี้", + serwersms: "SerwerSMS.pl", + serwersmsAPIUser: "API Username (incl. webapi_ prefix)", + serwersmsAPIPassword: "API Password", + serwersmsPhoneNumber: "หมายเลขโทรศัพท์", + serwersmsSenderName: "ชื่อผู้ส่ง SMS (ลงทะเบียนผ่านหน้าควบคุม)", + stackfield: "Stackfield", + Customize: "ปรับแต่ง", + "Custom Footer": "ส่วนท้ายที่กำหนดเอง", + "Custom CSS": "CSS ที่กำหนดเอง", + smtpDkimSettings: "ตั่งค่า DKIM", + smtpDkimDesc: "โปรดดู Nodemailer DKIM {0} สำหรับการใช้งาน", + documentation: "เอกสาร", + smtpDkimDomain: "ชื่อโดเมน", + smtpDkimKeySelector: "Key Selector", + smtpDkimPrivateKey: "Private Key", + smtpDkimHashAlgo: "อัลกอริทึมแฮช (ไม่บังคับ)", + smtpDkimheaderFieldNames: "คีย์ส่วนหัวเพื่อลงชื่อ (ไม่บังคับ)", + smtpDkimskipFields: "Header Keys ไม่ต้องเซ็น (ไม่บังคับ)", + gorush: "Gorush", + alerta: "Alerta", + alertaApiEndpoint: "API Endpoint", + alertaEnvironment: "Environment", + alertaApiKey: "กุญแจ API", + alertaAlertState: "แจ้งเตือนสถานะ", + alertaRecoverState: "กู้คืนสถานะ", + deleteStatusPageMsg: "คุณแน่ใจหรือไม่ว่าต้องการลบหน้าสถานะนี้", + Proxies: "พร็อกซี", + default: "ค่าเริ่มต้น", + enabled: "เปิดใช้งาน", + setAsDefault: "ตั่งเป็นค่าเริ่มต้น", + deleteProxyMsg: "คุณแน่ใจหรือไม่ว่าต้องการลบพร็อกซีสำหรับมอนิเตอร์ทั้งหมด?", + proxyDescription: "พร็อกซีจะต้องตั่งค่าให้มอนิเตอร์เพื่อให้ใช้งานได้", + enableProxyDescription: "พร็อกซีนี้จะไม่ส่งผลต่อมอนิเตอร์จนกว่าจะเปิดใช้งาน คุณสามารถควบคุมการปิดใช้งานพร็อกซีชั่วคราวจากมอนิเตอร์ทั้งหมดได้โดยสถานะการเปิดใช้งาน", + setAsDefaultProxyDescription: "พร็อกซีนี้จะถูกเปิดโดนค่าเริ่มต้นสำหรับมอนิเตอร์ใหม่, คุณสามารถปิดการแจ้งเตือนสำหรับแต่ละมอนิเตอร์ได้", + "Certificate Chain": "ห่วงโซ่ใบรับรอง", + Valid: "ถูกต้อง", + Invalid: "ไม่ถูกต้อง", + AccessKeyId: "กุญแจสิทธิ ID", + SecretAccessKey: "กุญแจสิทธิ Secret", + PhoneNumbers: "PhoneNumbers", + TemplateCode: "รหัสเทมเพลต", + SignName: "ป้ายชื่อ", + "Sms template must contain parameters: ": "เทมเพลต SMS ต้องมีพารามิเตอร์ : ", + "Bark Endpoint": "Bark Endpoint", + WebHookUrl: "WebHookUrl", + SecretKey: "SecretKey", + "For safety, must use secret key": "เพื่อความปลอดภัย จำเป็นต้องตั่งค่ากุญแจการเข้าถึง", + "Device Token": "Device Token", + Platform: "แพลตฟอร์ม", + iOS: "iOS", + Android: "Android", + Huawei: "Huawei", + High: "สูง", + Retry: "ลองใหม่", + Topic: "หัวข้อ", + "WeCom Bot Key": "WeCom Bot Key", + "Setup Proxy": "ติดตั้งพร็อกซี่", + "Proxy Protocol": "โปรโตคอลพร็อกซี่", + "Proxy Server": "พร็อกซีเซิร์ฟ", + "Proxy server has authentication": "พร็อกซีเซิร์ฟเวอร์มีการตรวจสอบสิทธิ์", + User: "ผู้ใช้", + Installed: "ติดตั้งแล้ว", + "Not installed": "ไม่ได้ติดตั้ง", + Running: "กำลังทำงาน", + "Not running": "ไม่ได้ทำงาน", + "Remove Token": "ลบกุญแจ", + Start: "เริ่ม", + Stop: "หยุด", + "Uptime Kuma": "Uptime Kuma", + "Add New Status Page": "เพิ่มหน้าสถานะใหม่", + Slug: "ชื่อ", + "Accept characters:": "ตัวอักษรที่ใช้งานได้ :", + startOrEndWithOnly: "เริ่มหรือจบด้วย {0} เท่านั้น", + "No consecutive dashes": "ไม่มีขีดกลางติดต่อกัน", + Next: "ต่อไป", + "The slug is already taken. Please choose another slug.": "ชื่อนี้ถูกใช้งานไปแล้ว กรุณาใช้ชื่ออื่น", + "No Proxy": "ไม่มีพร็อกซี่", + "HTTP Basic Auth": "HTTP Basic Auth", + "New Status Page": "หน้าสถานะใหม่", + "Page Not Found": "ไม่พบหน้านี้", + "Reverse Proxy": "พร็อกซีย้อนกลับ", + Backup: "สำรอง", + About: "เกี่ยวกับ", + wayToGetCloudflaredURL: "(ดาวโหลด cloudflared จาก {0})", + cloudflareWebsite: "เว็บไซต์ Cloudflare", + "Message:": "ข้อความ :", + "Don't know how to get the token? Please read the guide:": "ไม่รู้วิธีการรับกุญแจ?, กรุณาอ่านคู่มือ", + "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.": "การเชื่อมต่อปัจุบันอาจขาดหายหากคุณกำลังเชื่อมต่อ Cloudflare Tunnel คุณแน่ใจหรือไม่ที่จะหยุด, พิมรหัสผ่านของคุณเพื่อยืนยัน", + "Other Software": "ซอฟต์แวร์อื่น ๆ ", + "For example: nginx, Apache and Traefik.": "เช่น: nginx, Apache และ Traefik", + "Please read": "กรุณาอ่าน", + "Subject:": "เรื่อง :", + "Valid To:": "ถูกต้องถึง :", + "Days Remaining:": "จำนวนวันที่เหลือ :", + "Issuer:": "ผู้ออก :", + "Fingerprint:": "ลายนิ้วมือ :", + "No status pages": "ไม่มีหน้าสถานะ", + "Domain Name Expiry Notification": "แจ้งเตือนการหมดอายุโดเมน", + Proxy: "Proxy", + "Date Created": "วันที่สร้าง", + onebotHttpAddress: "ที่อยู่ HTTP OneBot ", + onebotMessageType: "ชนิดข้อความ OneBot", + onebotGroupMessage: "กลุ่ม", + onebotPrivateMessage: "ส่วนตัว", + onebotUserOrGroupId: "กลุ่ม / ไอดีผู้ใช้", + onebotSafetyTips: "เพื่อความปลอดภัย จำเป็นต้องตั่งค่ากุญแจการเข้าถึง", + "PushDeer Key": "กุญแจ PushDeer", + "Footer Text": "ข้อความส่วนท้าย", + "Show Powered By": "แสดงข้อความ \"ขับเคลื่อนโดย\"", + "Domain Names": "Domain Names", + signedInDisp: "เข้าใช้งานในฐานะ {0}", + signedInDispDisabled: "ปิดการตรวจสอบสิทธิ์", + "Certificate Expiry Notification": "แจ้งเตือนการรับรองหมดอายุ", + "API Username": "API Username", + "API Key": "API Key", + "Recipient Number": "หมายเลขผู้รับ", + "From Name/Number": "จาก ชื่อ / หมายเลข", + "Leave blank to use a shared sender number.": "ไม่ต้องกรอกเพื่อใช้ชื่อผู้ส่งร่วมกัน", + "Octopush API Version": "Octopush API Version", + "Legacy Octopush-DM": "Legacy Octopush-DM", + endpoint: "endpoint", + octopushAPIKey: "\"API key\" จากข้อมูลรับรอง HTTP API ในแผงควบคุม", + octopushLogin: "\"Login\" จากข้อมูลรับรอง HTTP API ในแผงควบคุม", + promosmsLogin: "API Login Name", + promosmsPassword: "API Password", + "pushoversounds pushover": "Pushover (default)", + "pushoversounds bike": "Bike", + "pushoversounds bugle": "Bugle", + "pushoversounds cashregister": "Cash Register", + "pushoversounds classical": "Classical", + "pushoversounds cosmic": "Cosmic", + "pushoversounds falling": "Falling", + "pushoversounds gamelan": "Gamelan", + "pushoversounds incoming": "Incoming", + "pushoversounds intermission": "Intermission", + "pushoversounds magic": "Magic", + "pushoversounds mechanical": "Mechanical", + "pushoversounds pianobar": "Piano Bar", + "pushoversounds siren": "Siren", + "pushoversounds spacealarm": "Space Alarm", + "pushoversounds tugboat": "Tug Boat", + "pushoversounds alien": "Alien Alarm (long)", + "pushoversounds climb": "Climb (long)", + "pushoversounds persistent": "Persistent (long)", + "pushoversounds echo": "Pushover Echo (long)", + "pushoversounds updown": "Up Down (long)", + "pushoversounds vibrate": "Vibrate Only", + "pushoversounds none": "None (silent)", + pushyAPIKey: "Secret API Key", + pushyToken: "Device token", + "Show update if available": "แสดงการอัปเดตถ้ามี", + "Also check beta release": "ตรวจสอบรุ่นเบต้า", + "Using a Reverse Proxy?": "ใช้ Reverse Proxy?", + "Check how to config it for WebSocket": "ตรวจสอบวิธีการตั่งค่าสำหรับ WebSocket", + "Steam Game Server": "Steam Game Server", + "Most likely causes:": "สาเหตุที่เป็นไปได้มากที่สุด :", + "The resource is no longer available.": "ทรัพยากรไม่สามารถใช้งานได้อีกต่อไป", + "There might be a typing error in the address.": "อาจมีข้อผิดพลาดในการพิมพ์ที่อยู่", + "What you can try:": "สิ่งที่คุณสามารถลอง :", + "Retype the address.": "พิมพ์ที่อยู่อีกครั้ง", + "Go back to the previous page.": "กลับไปที่หน้าก่อนหน้า", + "Coming Soon": "เร็ว ๆ นี้", + wayToGetClickSendSMSToken: "คุณสามารถรับ API Username และ API Key ได้จาก {0}", +}; From 751e5ac4779819946c3d39cbaaa78a4dbc8e2c3b Mon Sep 17 00:00:00 2001 From: MrEddX <66828538+MrEddX@users.noreply.github.com> Date: Thu, 19 May 2022 20:32:01 +0300 Subject: [PATCH 42/59] Bulgarian Translation Updated Translation --- src/components/settings/Security.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/settings/Security.vue b/src/components/settings/Security.vue index 87bb745a..8deade63 100644 --- a/src/components/settings/Security.vue +++ b/src/components/settings/Security.vue @@ -206,7 +206,7 @@ <template v-else-if="$i18n.locale === 'bg-BG' "> <p>Сигурни ли сте, че желаете да <strong>изключите удостоверяването</strong>?</p> - <p>Използва се в случаите, когато <strong>има настроен алтернативен метод за удостоверяване</strong> преди Uptime Kuma, например Cloudflare Access.</p> + <p>Използва се в случаите, когато <strong>има настроен алтернативен метод за удостоверяване</strong> преди Uptime Kuma, например Cloudflare Access, Authelia или друг механизъм за удостоверяване.</p> <p>Моля, използвайте с повишено внимание.</p> </template> From 9d87f8d3902db8aa64ae649035df5c0fc1418fc8 Mon Sep 17 00:00:00 2001 From: Yoswaris Lawpaiboon <22832362+kiznick@users.noreply.github.com> Date: Fri, 20 May 2022 19:16:37 +0700 Subject: [PATCH 43/59] Update th-TH.js --- src/languages/th-TH.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/languages/th-TH.js b/src/languages/th-TH.js index b313deb0..70138ff4 100644 --- a/src/languages/th-TH.js +++ b/src/languages/th-TH.js @@ -26,7 +26,7 @@ export default { tokenValidSettingsMsg: "กุญแจถูกต้อง, ตอนนี้คุณสามารถบันทึกการตั้งค่า 2FA ของคุณได้แล้ว", confirmEnableTwoFAMsg: "คุณแน่ใจหรือไม่ที่จะเปิดใช้งาน 2FA?", confirmDisableTwoFAMsg: "คุณแน่ใจหรือไม่ที่จะปิดใช้งาน 2FA?", - Settings: "การตั่งค่า", + Settings: "การตั้งค่า", Dashboard: "แผงควบคุม", "New Update": "อัพเดทใหม่", Language: "ภาษา", @@ -149,7 +149,7 @@ export default { "Setup 2FA": "ติดตั้ง 2FA", "Enable 2FA": "เปิดใช้งาน 2FA", "Disable 2FA": "ปิดใช้งาน 2FA", - "2FA Settings": "ตั่งค่า 2FA", + "2FA Settings": "ตั้งค่า 2FA", "Two Factor Authentication": "การตรวจสอบสิทธิ์สองปัจจัย", Active: "ใช้งาน", Inactive: "ไม่ใช้งาน", @@ -361,7 +361,7 @@ export default { Customize: "ปรับแต่ง", "Custom Footer": "ส่วนท้ายที่กำหนดเอง", "Custom CSS": "CSS ที่กำหนดเอง", - smtpDkimSettings: "ตั่งค่า DKIM", + smtpDkimSettings: "ตั้งค่า DKIM", smtpDkimDesc: "โปรดดู Nodemailer DKIM {0} สำหรับการใช้งาน", documentation: "เอกสาร", smtpDkimDomain: "ชื่อโดเมน", @@ -383,7 +383,7 @@ export default { enabled: "เปิดใช้งาน", setAsDefault: "ตั่งเป็นค่าเริ่มต้น", deleteProxyMsg: "คุณแน่ใจหรือไม่ว่าต้องการลบพร็อกซีสำหรับมอนิเตอร์ทั้งหมด?", - proxyDescription: "พร็อกซีจะต้องตั่งค่าให้มอนิเตอร์เพื่อให้ใช้งานได้", + proxyDescription: "พร็อกซีจะต้องตั้งค่าให้มอนิเตอร์เพื่อให้ใช้งานได้", enableProxyDescription: "พร็อกซีนี้จะไม่ส่งผลต่อมอนิเตอร์จนกว่าจะเปิดใช้งาน คุณสามารถควบคุมการปิดใช้งานพร็อกซีชั่วคราวจากมอนิเตอร์ทั้งหมดได้โดยสถานะการเปิดใช้งาน", setAsDefaultProxyDescription: "พร็อกซีนี้จะถูกเปิดโดนค่าเริ่มต้นสำหรับมอนิเตอร์ใหม่, คุณสามารถปิดการแจ้งเตือนสำหรับแต่ละมอนิเตอร์ได้", "Certificate Chain": "ห่วงโซ่ใบรับรอง", @@ -398,7 +398,7 @@ export default { "Bark Endpoint": "Bark Endpoint", WebHookUrl: "WebHookUrl", SecretKey: "SecretKey", - "For safety, must use secret key": "เพื่อความปลอดภัย จำเป็นต้องตั่งค่ากุญแจการเข้าถึง", + "For safety, must use secret key": "เพื่อความปลอดภัย จำเป็นต้องตั้งค่ากุญแจการเข้าถึง", "Device Token": "Device Token", Platform: "แพลตฟอร์ม", iOS: "iOS", @@ -457,7 +457,7 @@ export default { onebotGroupMessage: "กลุ่ม", onebotPrivateMessage: "ส่วนตัว", onebotUserOrGroupId: "กลุ่ม / ไอดีผู้ใช้", - onebotSafetyTips: "เพื่อความปลอดภัย จำเป็นต้องตั่งค่ากุญแจการเข้าถึง", + onebotSafetyTips: "เพื่อความปลอดภัย จำเป็นต้องตั้งค่ากุญแจการเข้าถึง", "PushDeer Key": "กุญแจ PushDeer", "Footer Text": "ข้อความส่วนท้าย", "Show Powered By": "แสดงข้อความ \"ขับเคลื่อนโดย\"", @@ -505,7 +505,7 @@ export default { "Show update if available": "แสดงการอัปเดตถ้ามี", "Also check beta release": "ตรวจสอบรุ่นเบต้า", "Using a Reverse Proxy?": "ใช้ Reverse Proxy?", - "Check how to config it for WebSocket": "ตรวจสอบวิธีการตั่งค่าสำหรับ WebSocket", + "Check how to config it for WebSocket": "ตรวจสอบวิธีการตั้งค่าสำหรับ WebSocket", "Steam Game Server": "Steam Game Server", "Most likely causes:": "สาเหตุที่เป็นไปได้มากที่สุด :", "The resource is no longer available.": "ทรัพยากรไม่สามารถใช้งานได้อีกต่อไป", From f23baf9c2241284fed55b2b47a88c5efe7970574 Mon Sep 17 00:00:00 2001 From: DasCanard <mail@dascanard.xyz> Date: Tue, 24 May 2022 23:14:27 +0200 Subject: [PATCH 44/59] Added Push Monitor to Discord Notifications --- server/notification-providers/discord.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/notification-providers/discord.js b/server/notification-providers/discord.js index 77b04d9d..28ead7b7 100644 --- a/server/notification-providers/discord.js +++ b/server/notification-providers/discord.js @@ -55,8 +55,8 @@ class Discord extends NotificationProvider { value: monitorJSON["name"], }, { - name: "Service URL / Address", - value: address, + name: monitorJSON["type"] === "push" ? "Service Type" : "Service URL", + value: monitorJSON["type"] === "push" ? "Heartbeat" : address, }, { name: "Time (UTC)", @@ -90,8 +90,8 @@ class Discord extends NotificationProvider { value: monitorJSON["name"], }, { - name: "Service URL", - value: address.startsWith("http") ? "[Visit Service](" + address + ")" : address, + name: monitorJSON["type"] === "push" ? "Service Type" : "Service URL", + value: monitorJSON["type"] === "push" ? "Heartbeat" : address.startsWith("http") ? "[Visit Service](" + address + ")" : address, }, { name: "Time (UTC)", @@ -99,7 +99,7 @@ class Discord extends NotificationProvider { }, { name: "Ping", - value: heartbeatJSON["ping"] + "ms", + value: heartbeatJSON["ping"] == null ? "N/A" : heartbeatJSON["ping"] + " ms", }, ], }], From 5830f1e0b5c0bced9904e2db67af875d0d224422 Mon Sep 17 00:00:00 2001 From: Marc Hagen <hello@marchagen.nl> Date: Wed, 16 Feb 2022 23:09:22 +0100 Subject: [PATCH 45/59] [feat] Adding PagerDuty notification --- server/notification-providers/pagerduty.js | 113 +++++++++++++++++++++ server/notification.js | 2 + src/components/notifications/PagerDuty.vue | 40 ++++++++ src/components/notifications/index.js | 2 + src/languages/en.js | 9 ++ 5 files changed, 166 insertions(+) create mode 100644 server/notification-providers/pagerduty.js create mode 100644 src/components/notifications/PagerDuty.vue diff --git a/server/notification-providers/pagerduty.js b/server/notification-providers/pagerduty.js new file mode 100644 index 00000000..86e9a099 --- /dev/null +++ b/server/notification-providers/pagerduty.js @@ -0,0 +1,113 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); +const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util"); +const { setting } = require("../util-server"); +let successMessage = "Sent Successfully."; + +class PagerDuty extends NotificationProvider { + name = "PagerDuty"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + try { + if (heartbeatJSON == null) { + const title = "Uptime Kuma Alert"; + const monitor = { + type: "ping", + url: "Uptime Kuma Test Button", + }; + return this.postNotification(notification, title, msg, monitor); + } + + if (heartbeatJSON.status === UP) { + const title = "Uptime Kuma Monitor ✅ Up"; + const eventAction = notification.pagerdutyAutoResolve || null; + + return this.postNotification(notification, title, heartbeatJSON.msg, monitorJSON, eventAction); + } + + if (heartbeatJSON.status === DOWN) { + const title = "Uptime Kuma Monitor 🔴 Down"; + return this.postNotification(notification, title, heartbeatJSON.msg, monitorJSON, "trigger"); + } + } catch (error) { + this.throwGeneralAxiosError(error); + } + } + + /** + * Check if result is successful, result code should be in range 2xx + * @param {Object} result Axios response object + * @throws {Error} The status code is not in range 2xx + */ + checkResult(result) { + if (result.status == null) { + throw new Error("PagerDuty notification failed with invalid response!"); + } + if (result.status < 200 || result.status >= 300) { + throw new Error("PagerDuty notification failed with status code " + result.status); + } + } + + /** + * Send the message + * @param {BeanModel} notification Message title + * @param {string} title Message title + * @param {string} body Message + * @param {Object} monitorInfo Monitor details (For Up/Down only) + * @param {?string} eventAction Action event for PagerDuty (trigger, acknowledge, resolve) + * @returns {string} + */ + async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") { + + if (eventAction == null) { + return "No action required"; + } + + let monitorUrl; + if (monitorInfo.type === "port") { + monitorUrl = monitorInfo.hostname; + if (monitorInfo.port) { + monitorUrl += ":" + monitorInfo.port; + } + } else if (monitorInfo.hostname != null) { + monitorUrl = monitorInfo.hostname; + } else { + monitorUrl = monitorInfo.url; + } + + const options = { + method: "POST", + url: notification.pagerdutyIntegrationUrl, + headers: { "Content-Type": "application/json" }, + data: { + payload: { + summary: `[${title}] [${monitorInfo.name}] ${body}`, + severity: notification.pagerdutyPriority || "warning", + source: monitorUrl, + }, + routing_key: notification.pagerdutyIntegrationKey, + event_action: eventAction, + dedup_key: "Uptime Kuma/" + monitorInfo.id, + } + }; + + const baseURL = await setting("primaryBaseURL"); + if (baseURL && monitorInfo) { + options.client = "Uptime Kuma"; + options.client_url = baseURL + getMonitorRelativeURL(monitorInfo.id); + } + + let result = await axios.request(options); + this.checkResult(result); + if (result.statusText != null) { + return "PagerDuty notification succeed: " + result.statusText; + } + + return successMessage; + } +} + +module.exports = PagerDuty; diff --git a/server/notification.js b/server/notification.js index 269e9444..d0b6f40d 100644 --- a/server/notification.js +++ b/server/notification.js @@ -29,6 +29,7 @@ const SerwerSMS = require("./notification-providers/serwersms"); const Stackfield = require("./notification-providers/stackfield"); const WeCom = require("./notification-providers/wecom"); const GoogleChat = require("./notification-providers/google-chat"); +const PagerDuty = require("./notification-providers/pagerduty"); const Gorush = require("./notification-providers/gorush"); const Alerta = require("./notification-providers/alerta"); const OneBot = require("./notification-providers/onebot"); @@ -74,6 +75,7 @@ class Notification { new Stackfield(), new WeCom(), new GoogleChat(), + new PagerDuty(), new Gorush(), new Alerta(), new OneBot(), diff --git a/src/components/notifications/PagerDuty.vue b/src/components/notifications/PagerDuty.vue new file mode 100644 index 00000000..73f60443 --- /dev/null +++ b/src/components/notifications/PagerDuty.vue @@ -0,0 +1,40 @@ +<template> + <div class="mb-3"> + <label for="pagerduty-integration-key" class="form-label">{{ $t("Integration Key") }}</label> + <HiddenInput id="pagerduty-integration-key" v-model="$parent.notification.pagerdutyIntegrationKey" :required="true" autocomplete="false"></HiddenInput> + <i18n-t tag="div" keypath="wayToGetPagerDutyKey" class="form-text"> + <a href="https://support.pagerduty.com/docs/services-and-integrations" target="_blank">{{ $t("here") }}</a> + </i18n-t> + </div> + <div class="mb-3"> + <label for="pagerduty-integration-url" class="form-label">{{ $t("Integration URL") }}</label> + <input id="pagerduty-integration-url" v-model="$parent.notification.pagerdutyIntegrationUrl" type="text" class="form-control" autocomplete="false" value="https://events.pagerduty.com/v2/enqueue"> + </div> + <div class="mb-3"> + <label for="pagerduty-priority" class="form-label">{{ $t("Priority") }}</label> + <select id="pagerduty-priority" v-model="$parent.notification.pagerdutyPriority" class="form-select"> + <option value="info">{{ $t("info") }}</option> + <option value="warning" selected="selected">{{ $t("warning") }}</option> + <option value="error">{{ $t("error") }}</option> + <option value="critical">{{ $t("critical") }}</option> + </select> + </div> + <div class="mb-3"> + <label for="pagerduty-resolve" class="form-label">{{ $t("Auto resolve or acknowledged") }}</label> + <select id="pagerduty-resolve" v-model="$parent.notification.pagerdutyAutoResolve" class="form-select"> + <option value="0" selected="selected">{{ $t("do nothing") }}</option> + <option value="acknowledge">{{ $t("auto acknowledged") }}</option> + <option value="resolve">{{ $t("auto resolve") }}</option> + </select> + </div> +</template> + +<script> +import HiddenInput from "../HiddenInput.vue"; + +export default { + components: { + HiddenInput, + }, +}; +</script> diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js index 496d35fa..37beb24d 100644 --- a/src/components/notifications/index.js +++ b/src/components/notifications/index.js @@ -27,6 +27,7 @@ import SerwerSMS from "./SerwerSMS.vue"; import Stackfield from "./Stackfield.vue"; import WeCom from "./WeCom.vue"; import GoogleChat from "./GoogleChat.vue"; +import PagerDuty from "./PagerDuty.vue"; import Gorush from "./Gorush.vue"; import Alerta from "./Alerta.vue"; import OneBot from "./OneBot.vue"; @@ -67,6 +68,7 @@ const NotificationFormList = { "stackfield": Stackfield, "WeCom": WeCom, "GoogleChat": GoogleChat, + "PagerDuty": PagerDuty, "gorush": Gorush, "alerta": Alerta, "OneBot": OneBot, diff --git a/src/languages/en.js b/src/languages/en.js index d634e545..aa6737dd 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -331,6 +331,8 @@ export default { info: "info", warning: "warning", danger: "danger", + error: "error", + critical: "critical", primary: "primary", light: "light", dark: "dark", @@ -371,6 +373,13 @@ export default { smtpDkimHashAlgo: "Hash Algorithm (Optional)", smtpDkimheaderFieldNames: "Header Keys to sign (Optional)", smtpDkimskipFields: "Header Keys not to sign (Optional)", + wayToGetPagerDutyKey: "You can get this by going to Service -> Service Directory -> (Select a service) -> Integrations -> Add integration. Here you can search for \"Events API V2\". More info {0}", + "Integration Key": "Integration Key", + "Integration URL": "Integration URL", + "Auto resolve or acknowledged": "Auto resolve or acknowledged", + "do nothing": "do nothing", + "auto acknowledged": "auto acknowledged", + "auto resolve": "auto resolve", gorush: "Gorush", alerta: "Alerta", alertaApiEndpoint: "API Endpoint", From 5566b038c84792a7f59502e050d5eafa89641fd3 Mon Sep 17 00:00:00 2001 From: burakurer <58211081+burakurer@users.noreply.github.com> Date: Wed, 25 May 2022 17:35:05 +0300 Subject: [PATCH 46/59] Update tr-TR.js --- src/languages/tr-TR.js | 399 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 383 insertions(+), 16 deletions(-) diff --git a/src/languages/tr-TR.js b/src/languages/tr-TR.js index 0edd6020..08cafa2c 100644 --- a/src/languages/tr-TR.js +++ b/src/languages/tr-TR.js @@ -1,6 +1,7 @@ export default { languageName: "Türkçe", checkEverySecond: "{0} Saniyede bir kontrol et.", + retryCheckEverySecond: "{0} Saniyede bir dene.", retriesDescription: "Servisin kapalı olarak işaretlenmeden ve bir bildirim gönderilmeden önce maksimum yeniden deneme sayısı", ignoreTLSError: "HTTPS web siteleri için TLS/SSL hatasını yoksay", upsideDownModeDescription: "Servisin durumunu tersine çevirir. Servis çalışıyorsa kapalı olarak işaretler.", @@ -12,12 +13,20 @@ export default { pauseDashboardHome: "Durdur", deleteMonitorMsg: "Servisi silmek istediğinden emin misin?", deleteNotificationMsg: "Bu bildirimi tüm servisler için silmek istediğinden emin misin?", + dnsPortDescription: "DNS sunucusu bağlantı noktası. Varsayılan değer 53'tür. Bağlantı noktasını istediğiniz zaman değiştirebilirsiniz.", resolverserverDescription: "Cloudflare varsayılan sunucudur, çözümleyici sunucusunu istediğiniz zaman değiştirebilirsiniz.", rrtypeDescription: "İzlemek istediğiniz servisin RR-Tipini seçin", pauseMonitorMsg: "Durdurmak istediğinden emin misin?", + enableDefaultNotificationDescription: "Bu bildirim her yeni serviste aktif olacaktır. Bildirimi servisler için ayrı ayrı deaktive edebilirsiniz. ", clearEventsMsg: "Bu servisin bütün kayıtlarını silmek istediğinden emin misin?", clearHeartbeatsMsg: "Bu servis için tüm sağlık durumunu silmek istediğinden emin misin?", confirmClearStatisticsMsg: "Tüm istatistikleri silmek istediğinden emin misin?", + importHandleDescription: "Aynı isimdeki bütün servisleri ve bildirimleri atlamak için 'Var olanı atla' seçiniz. 'Üzerine yaz' var olan bütün servisleri ve bildirimleri silecektir. ", + confirmImportMsg: "Yedeği içeri aktarmak istediğinize emin misiniz? Lütfen doğru içeri aktarma seçeneğini seçtiğinizden emin olunuz. ", + twoFAVerifyLabel: "Lütfen tokeni yazarak 2FA doğrulamanın çalıştığından emin olunuz.", + tokenValidSettingsMsg: "Token geçerli! Şimdi 2FA ayarlarını kaydedebilirsiniz. ", + confirmEnableTwoFAMsg: "2FA'ı etkinleştirmek istediğinizden emin misiniz?", + confirmDisableTwoFAMsg: "2FA'ı devre dışı bırakmak istediğinize emin misiniz?", Settings: "Ayarlar", Dashboard: "Panel", "New Update": "Yeni Güncelleme", @@ -25,6 +34,7 @@ export default { Appearance: "Görünüm", Theme: "Tema", General: "Genel", + "Primary Base URL": "Birincil Temel URL", Version: "Versiyon", "Check Update On GitHub": "GitHub'da Güncellemeyi Kontrol Edin", List: "Liste", @@ -62,10 +72,14 @@ export default { Port: "Port", "Heartbeat Interval": "Servis Test Aralığı", Retries: "Yeniden deneme", + "Heartbeat Retry Interval": "Sağlık Durumları Tekrar Deneme Sıklığı", Advanced: "Gelişmiş", "Upside Down Mode": "Ters/Düz Modu", "Max. Redirects": "Maksimum Yönlendirme", "Accepted Status Codes": "Kabul Edilen Durum Kodları", + "Push URL": "Push URL", + needPushEvery: "Bu URL'yi her {0} saniyede bir aramalısınız.", + pushOptionalParams: "İsteğe bağlı parametreler: {0}", Save: "Kaydet", Notifications: "Bildirimler", "Not available, please setup.": "Atanmış bildirim yöntemi yok. Ayarlardan belirleyebilirsiniz.", @@ -109,28 +123,19 @@ export default { "Last Result": "En son sonuçlar", "Create your admin account": "Yönetici hesabınızı oluşturun", "Repeat Password": "Şifrenizi tekrar girin", - respTime: "Cevap Süresi (ms)", - notAvailableShort: "N/A", - Create: "Yarat", - "Clear Data": "Verileri Temizle", - Events: "Olaylar", - Heartbeats: "Sağlık Durumları", - "Auto Get": "Otomatik Al", - retryCheckEverySecond: "{0} Saniyede bir dene.", - enableDefaultNotificationDescription: "Bu bildirim her yeni serviste aktif olacaktır. Bildirimi servisler için ayrı ayrı deaktive edebilirsiniz. ", - importHandleDescription: "Aynı isimdeki bütün servisleri ve bildirimleri atlamak için 'Var olanı atla' seçiniz. 'Üzerine yaz' var olan bütün servisleri ve bildirimleri silecektir. ", - confirmImportMsg: "Yedeği içeri aktarmak istediğinize emin misiniz? Lütfen doğru içeri aktarma seçeneğini seçtiğinizden emin olunuz. ", - twoFAVerifyLabel: "Lütfen tokeni yazarak 2FA doğrulamanın çalıştığından emin olunuz.", - tokenValidSettingsMsg: "Token geçerli! Şimdi 2FA ayarlarını kaydedebilirsiniz. ", - confirmEnableTwoFAMsg: "2FA'ı etkinleştirmek istediğinizden emin misiniz?", - confirmDisableTwoFAMsg: "2FA'ı devre dışı bırakmak istediğinize emin misiniz?", - "Heartbeat Retry Interval": "Sağlık Durumları Tekrar Deneme Sıklığı", "Import Backup": "Yedeği içe aktar", "Export Backup": "Yedeği dışa aktar", Export: "Dışa aktar", Import: "İçe aktar", + respTime: "Cevap Süresi (ms)", + notAvailableShort: "N/A", "Default enabled": "Varsayılan etkinleştirilmiş", "Apply on all existing monitors": "Var olan bütün servislere uygula", + Create: "Oluştur", + "Clear Data": "Verileri Temizle", + Events: "Olaylar", + Heartbeats: "Sağlık Durumları", + "Auto Get": "Otomatik Al", backupDescription: "Bütün servisleri ve bildirimleri JSON dosyasına yedekleyebilirsiniz.", backupDescription2: "Not: Geçmiş ve etkinlik verileri içinde değildir.", backupDescription3: "Dışa aktarma dosyasında bildirim tokeni gibi hassas veriler bulunur, dikkatli bir şekilde saklayınız.", @@ -149,4 +154,366 @@ export default { "Two Factor Authentication": "İki Faktörlü Kimlik Doğrulama (2FA)", Active: "Aktif", Inactive: "İnaktif", + Token: "Token", + "Show URI": "URI'yi göster", + Tags: "Etiketler", + "Add New below or Select...": "Aşağıya Yeni Ekle veya Seç...", + "Tag with this name already exist.": "Bu ada sahip etiket zaten var.", + "Tag with this value already exist.": "Bu değere sahip etiket zaten var.", + color: "renk", + "value (optional)": "değer (isteğe bağlı)", + Gray: "Gri", + Red: "Kırmızı", + Orange: "Turuncu", + Green: "Yeşil", + Blue: "Mavi", + Indigo: "Çivit mavisi", + Purple: "Mor", + Pink: "Pembe", + "Search...": "Ara...", + "Avg. Ping": "Ortalama Ping", + "Avg. Response": "Ortalama Cevap Süresi", + "Entry Page": "Giriş Sayfası", + statusPageNothing: "Burada hiçbir şey yok, lütfen bir grup veya servis ekleyin.", + "No Services": "Hizmet Yok", + "All Systems Operational": "Tüm Sistemler Operasyonel", + "Partially Degraded Service": "Kısmen Bozulmuş Hizmet", + "Degraded Service": "Bozulmuş Hizmet", + "Add Group": "Grup Ekle", + "Add a monitor": "Servis Ekle", + "Edit Status Page": "Durum Sayfasını Düzenle", + "Go to Dashboard": "Panele Git", + "Status Page": "Durum Sayfası", + "Status Pages": "Durum Sayfaları", + defaultNotificationName: "My {notification} Alert ({number})", + here: "burada", + Required: "Gerekli", + telegram: "Telegram", + "Bot Token": "Bot Token", + wayToGetTelegramToken: "{0} adresinden bir token alabilirsiniz.", + "Chat ID": "Chat ID", + supportTelegramChatID: "Doğrudan Sohbet / Grup / Kanalın Sohbet Kimliğini Destekleyin", + wayToGetTelegramChatID: "Bot'a bir mesaj göndererek ve chat_id'yi görüntülemek için bu URL'ye giderek sohbet kimliğinizi alabilirsiniz:", + "YOUR BOT TOKEN HERE": "BOT TOKENİNİZ BURADA", + chatIDNotFound: "Chat ID bulunamadı; lütfen önce bu bota bir mesaj gönderin", + webhook: "Webhook", + "Post URL": "Post URL", + "Content Type": "Content Type", + webhookJsonDesc: "{0}, Express.js gibi tüm modern HTTP sunucuları için iyidir", + webhookFormDataDesc: "{multipart} PHP için iyidir. JSON'un {decodeFunction} ile ayrıştırılması gerekecek", + smtp: "E-mail (SMTP)", + secureOptionNone: "Hiçbiri / STARTTLS (25, 587)", + secureOptionTLS: "TLS (465)", + "Ignore TLS Error": "TLS Hatasını Yoksay", + "From Email": "E-postadan", + emailCustomSubject: "Özel Konu", + "To Email": "E-postaya", + smtpCC: "CC", + smtpBCC: "BCC", + discord: "Discord", + "Discord Webhook URL": "Discord Webhook URL", + wayToGetDiscordURL: "Bunu Sunucu Ayarları -> Entegrasyonlar -> Webhook Oluştur'a giderek alabilirsiniz.", + "Bot Display Name": "Botun Görünecek Adı", + "Prefix Custom Message": "Önek Özel Mesaj", + "Hello @everyone is...": "Merhaba {'@'}everyone ...", + teams: "Microsoft Teams", + "Webhook URL": "Webhook URL", + wayToGetTeamsURL: "Bir webhook URL'sinin nasıl oluşturulacağını öğrenebilirsiniz {0}.", + signal: "Signal", + Number: "Numara", + Recipients: "Alıcılar", + needSignalAPI: "REST API ile bir signal istemciniz olması gerekiyor.", + wayToCheckSignalURL: "Nasıl kurulacağını görmek için bu URL'yi kontrol edebilirsiniz:", + signalImportant: "ÖNEMLİ: Alıcılarda grupları ve sayıları karıştıramazsınız!", + gotify: "Gotify", + "Application Token": "Uygulama Tokeni", + "Server URL": "Sunucu URL", + Priority: "Öncelik", + slack: "Slack", + "Icon Emoji": "İkon Emoji", + "Channel Name": "Kanal Adı", + "Uptime Kuma URL": "Uptime Kuma URL", + aboutWebhooks: "Webhook hakkında daha fazla bilgi: {0}", + aboutChannelName: "Webhook kanalını atlamak istiyorsanız, {0} Kanal Adı alanına kanal adını girin. Ör: #diğer-kanal", + aboutKumaURL: "Uptime Kuma URL alanını boş bırakırsanız, varsayılan olarak Project GitHub sayfası olur.", + emojiCheatSheet: "Emoji cheat sheet: {0}", + "rocket.chat": "Rocket.Chat", + pushover: "Pushover", + pushy: "Pushy", + PushByTechulus: "Push by Techulus", + octopush: "Octopush", + promosms: "PromoSMS", + clicksendsms: "ClickSend SMS", + lunasea: "LunaSea", + apprise: "Apprise (50'den fazla Bildirim hizmetini destekler)", + GoogleChat: "Google Chat (sadece Google Workspace)", + pushbullet: "Pushbullet", + line: "Line Messenger", + mattermost: "Mattermost", + "User Key": "Kullancı Anahtarı", + Device: "Cihaz", + "Message Title": "Mesaj Başlığı", + "Notification Sound": "Bilgilendirme sesi", + "More info on:": "Daha fazla bilgi: {0}", + pushoverDesc1: "Acil durum önceliği (2), yeniden denemeler arasında varsayılan olarak 30 saniyelik bir zaman aşımına sahiptir ve 1 saat sonra sona erecektir.", + pushoverDesc2: "Farklı cihazlara bildirim göndermek istiyorsanız Cihaz alanını doldurunuz.", + "SMS Type": "SMS Tipi", + octopushTypePremium: "Premium (Hızlı - uyarı için önerilir)", + octopushTypeLowCost: "Düşük Maliyet (Yavaş - bazen operatör tarafından engellenir)", + checkPrice: "{0} fiyatlarını kontrol edin:", + apiCredentials: "API kimlik bilgileri", + octopushLegacyHint: "Octopush'un (2011-2020) eski sürümünü mü yoksa yeni sürümünü mü kullanıyorsunuz?", + "Check octopush prices": "Octopush fiyatlarını kontrol edin {0}.", + octopushPhoneNumber: "Telefon numarası (uluslararası biçim, örneğin: +33612345678) ", + octopushSMSSender: "SMS Gönderici Adı : 3-11 alfanümerik karakter ve boşluk (a-zA-Z0-9)", + "LunaSea Device ID": "LunaSea Cihaz ID", + "Apprise URL": "Apprise URL", + "Example:": "Örnek: {0}", + "Read more:": "Daha fazla oku: {0}", + "Status:": "Durum: {0}", + "Read more": "Daha fazla oku", + appriseInstalled: "Apprise yüklendi.", + appriseNotInstalled: "Appris yüklü değil. {0}", + "Access Token": "Erişim Tokeni", + "Channel access token": "Kanal erişim tokeni", + "Line Developers Console": "Line Geliştirici Konsolu", + lineDevConsoleTo: "Line Geliştirici Konsolu - {0}", + "Basic Settings": "Temel Ayarlar", + "User ID": "Kullanıcı ID", + "Messaging API": "Messaging API", + wayToGetLineChannelToken: "Önce {0}'e erişin, bir sağlayıcı ve kanal (Messaging API) oluşturun, ardından yukarıda belirtilen menü öğelerinden kanal erişim tokenini ve kullanıcı id alabilirsiniz.", + "Icon URL": "Simge URL", + aboutIconURL: "Varsayılan profil resmini geçersiz kılmak için \"Simge URL\" bölümünde bir resme bağlantı sağlayabilirsiniz. Simge Emojisi ayarlanmışsa kullanılmayacaktır.", + aboutMattermostChannelName: "Kanal adını \"Kanal Adı\" alanına girerek Webhook'un gönderi yaptığı varsayılan kanalı geçersiz kılabilirsiniz. Bunun Mattermost Webhook ayarlarında etkinleştirilmesi gerekir. Ör: #diğer-kanal", + matrix: "Matrix", + promosmsTypeEco: "SMS ECO - ucuz ama yavaş ve genellikle aşırı yüklü. Yalnızca Polonyalı alıcılarla sınırlıdır.", + promosmsTypeFlash: "SMS FLASH - Mesaj, alıcı cihazda otomatik olarak gösterilecektir. Yalnızca Polonyalı alıcılarla sınırlıdır.", + promosmsTypeFull: "SMS FULL - Premium SMS katmanı, Gönderici Adınızı kullanabilirsiniz (Önce adınızı kaydetmeniz gerekir). Uyarılar için güvenilir.", + promosmsTypeSpeed: "SMS HIZI - Sistemde en yüksek öncelik. Çok hızlı ve güvenilir ancak maliyetli (SMS FULL fiyatının yaklaşık iki katı).", + promosmsPhoneNumber: "Telefon numarası (Polonyalı alıcı için Alan kodlarını atlayabilirsiniz)", + promosmsSMSSender: "SMS Gönderici Adı : Ön kayıtlı ad veya varsayılanlardan biri: InfoSMS, SMS Info, MaxSMS, INFO, SMS", + "Feishu WebHookUrl": "Feishu WebHookURL", + matrixHomeserverURL: "Homeserver URL (http(s):// ve isteğe bağlı olarak bağlantı noktası ile)", + "Internal Room Id": "Internal Room ID", + matrixDesc1: "Internal Room ID'sini, Matrix istemcinizdeki oda ayarlarının gelişmiş bölümüne bakarak bulabilirsiniz. !QMdRCpUIfLwsfjxye6:home.server gibi görünmelidir.", + matrixDesc2: "Hesabınıza ve katıldığınız tüm odalara tam erişime izin vereceğinden, yeni bir kullanıcı oluşturmanız ve kendi Matrix kullanıcınızın erişim belirtecini kullanmamanız şiddetle tavsiye edilir. Bunun yerine, yeni bir kullanıcı oluşturun ve onu yalnızca bildirimi almak istediğiniz odaya davet edin. {0} komutunu çalıştırarak erişim tokenini alabilirsiniz.", + Method: "Yöntem", + Body: "Gövde", + Headers: "Başlıklar", + PushUrl: "Push URL", + HeadersInvalidFormat: "İstek başlıkları geçerli JSON değil:", + BodyInvalidFormat: "İstek gövdesi geçerli JSON değil:", + "Monitor History": "Servis Geçmişi", + clearDataOlderThan: "{0} gün boyunca izleme geçmişi verilerini saklayın.", + PasswordsDoNotMatch: "Parolalar uyuşmuyor.", + records: "kayıtlar", + "One record": "Bir Kayıt", + steamApiKeyDescription: "Bir Steam Oyun Sunucusunu izlemek için bir Steam Web-API anahtarına ihtiyacınız vardır. API anahtarınızı buradan kaydedebilirsiniz: ", + "Current User": "Şu anki kullanıcı", + topic: "Başlık", + topicExplanation: "İzlenecek MQTT servisi", + successMessage: "Başarılı Mesaj", + successMessageExplanation: "Başarılı olarak kabul edilecek MQTT mesajı", + recent: "Son", + Done: "Tamamlandı", + Info: "Bilgi", + Security: "Güvenlik", + "Steam API Key": "Steam API Anahtarı", + "Shrink Database": "Veritabanını Küçült", + "Pick a RR-Type...": "Bir RR-Tipi seçin...", + "Pick Accepted Status Codes...": "Kabul Edilen Durum Kodlarını Seçin...", + Default: "Varsayılan", + "HTTP Options": "HTTP Ayarları", + "Create Incident": "Olay Oluştur", + Title: "Başlık", + Content: "İçerik", + Style: "Stil", + info: "info", + warning: "warning", + danger: "danger", + primary: "primary", + light: "light", + dark: "dark", + Post: "Post", + "Please input title and content": "Lütfen başlık ve içerik girin", + Created: "Oluşturuldu", + "Last Updated": "Son Güncelleme", + Unpin: "Unpin", + "Switch to Light Theme": "Açık Temaya Geç", + "Switch to Dark Theme": "Karanlık Temaya Geç", + "Show Tags": "Etiketleri Göster", + "Hide Tags": "Etiketleri Gizle", + Description: "Açıklama", + "No monitors available.": "Kullanılabilir servis yok.", + "Add one": "Bir tane ekle", + "No Monitors": "Servis Yok", + "Untitled Group": "Adsız Grup", + Services: "Hizmetler", + Discard: "İptal Et", + Cancel: "İptal Et", + "Powered by": "Powered by", + shrinkDatabaseDescription: "SQLite için veritabanı VACUUM'unu tetikleyin. Veritabanınız 1.10.0'dan sonra oluşturulduysa, AUTO_VACUUM zaten etkinleştirilmiştir ve bu eyleme gerek yoktur.", + serwersms: "SerwerSMS.pl", + serwersmsAPIUser: "API Kullanıcı Adı (webapi_ öneki dahil)", + serwersmsAPIPassword: "API Şifre", + serwersmsPhoneNumber: "Telefon numarası", + serwersmsSenderName: "SMS Gönderici Adı (müşteri portalı üzerinden kayıtlı)", + stackfield: "Stackfield", + Customize: "Özelleştirme", + "Custom Footer": "Özel Altbilgi", + "Custom CSS": "Özel CSS", + smtpDkimSettings: "DKIM Ayarları", + smtpDkimDesc: "Kullanım için lütfen Nodemailer DKIM'e {0} bakın.", + documentation: "belgeler", + smtpDkimDomain: "Alan adı", + smtpDkimKeySelector: "Anahtar Seçici", + smtpDkimPrivateKey: "Özel anahtar", + smtpDkimHashAlgo: "Hash Algoritması (Opsiyonel)", + smtpDkimheaderFieldNames: "İmzalanacak Başlık Anahtarları (Opsiyonel)", + smtpDkimskipFields: "İmzalamayacak Başlık Anahtarları (Opsiyonel)", + gorush: "Gorush", + alerta: "Alerta", + alertaApiEndpoint: "API Endpoint", + alertaEnvironment: "Environment", + alertaApiKey: "API Key", + alertaAlertState: "Uyarı Durumu", + alertaRecoverState: "Kurtarma Durumu", + deleteStatusPageMsg: "Bu durum sayfasını silmek istediğinizden emin misiniz?", + Proxies: "Proxy'ler", + default: "Varsayılan", + enabled: "Etkinleştirilmiş", + setAsDefault: "Varsayılan Olarak Ayarla", + deleteProxyMsg: "Bu proxy'yi tüm servisler için silmek istediğinizden emin misiniz?", + proxyDescription: "Proxy'lerin çalışması için bir servise atanması gerekir.", + enableProxyDescription: "Bu proxy, etkinleştirilene kadar izleme isteklerini etkilemeyecektir. Aktivasyon durumuna göre proxy'yi tüm servislerden geçici olarak devre dışı bırakabilirsiniz.", + setAsDefaultProxyDescription: "Bu proxy, yeni servisler için varsayılan olarak etkinleştirilecektir. Yine de proxy'yi her servis için ayrı ayrı devre dışı bırakabilirsiniz.", + "Certificate Chain": "Sertifika Zinciri", + Valid: "Geçerli", + Invalid: "Geçersiz", + AccessKeyId: "AccessKey ID", + SecretAccessKey: "AccessKey Secret", + PhoneNumbers: "PhoneNumbers", + TemplateCode: "TemplateCode", + SignName: "SignName", + "Sms template must contain parameters: ": "Sms şablonu parametreleri içermelidir:", + "Bark Endpoint": "Bark Endpoint", + WebHookUrl: "WebHookUrl", + SecretKey: "SecretKey", + "For safety, must use secret key": "Güvenlik için gizli anahtar kullanılmalıdır", + "Device Token": "Cihaz Tokeni", + Platform: "Platform", + iOS: "iOS", + Android: "Android", + Huawei: "Huawei", + High: "High", + Retry: "Retry", + Topic: "Topic", + "WeCom Bot Key": "WeCom Bot Key", + "Setup Proxy": "Proxy kur", + "Proxy Protocol": "Proxy Protokolü", + "Proxy Server": "Proxy Sunucusu", + "Proxy server has authentication": "Proxy sunucusunun kimlik doğrulaması var", + User: "Kullanıcı", + Installed: "Yüklenmiş", + "Not installed": "Yüklü değil", + Running: "Çalışıyor", + "Not running": "Çalışmıyor", + "Remove Token": "Tokeni Kaldır", + Start: "Başlat", + Stop: "Durdur", + "Uptime Kuma": "Uptime Kuma", + "Add New Status Page": "Yeni Durum Sayfası Ekle", + Slug: "Slug", + "Accept characters:": "Kabul edilen karakterler:", + startOrEndWithOnly: "Yalnızca {0} ile başlayın veya bitirin", + "No consecutive dashes": "Ardışık tire yok", + Next: "Sonraki", + "The slug is already taken. Please choose another slug.": "Slug zaten alındı. Lütfen başka bir slug seçin.", + "No Proxy": "Proxy Yok", + "HTTP Basic Auth": "HTTP Temel Yetkilendirme", + "New Status Page": "Yeni Durum Sayfası", + "Page Not Found": "Sayfa bulunamadı", + "Reverse Proxy": "Ters Proxy", + Backup: "Yedek", + About: "Hakkında", + wayToGetCloudflaredURL: "(Cloudflared'i {0} adresinden indirin)", + cloudflareWebsite: "Cloudflare Website", + "Message:": "Mesaj:", + "Don't know how to get the token? Please read the guide:": "Tokeni nasıl alacağınızı bilmiyor musunuz? Lütfen kılavuzu okuyun:", + "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.": "Halihazırda Cloudflare Tüneli üzerinden bağlanıyorsanız mevcut bağlantı kesilebilir. Durdurmak istediğinden emin misin? Onaylamak için mevcut şifrenizi yazın.", + "Other Software": "Diğer Yazılımlar", + "For example: nginx, Apache and Traefik.": "Örneğin: nginx, Apache ve Traefik.", + "Please read": "Lütfen oku", + "Subject:": "Başlık:", + "Valid To:": "Geçerlilik:", + "Days Remaining:": "Kalan günler:", + "Issuer:": "Veren:", + "Fingerprint:": "Parmak izi:", + "No status pages": "Durum sayfası yok", + "Domain Name Expiry Notification": "Alan Adı Sona Erme Bildirimi", + Proxy: "Proxy", + "Date Created": "Tarih Oluşturuldu", + onebotHttpAddress: "OneBot HTTP Adresi", + onebotMessageType: "OneBot Mesaj Türü", + onebotGroupMessage: "Grup", + onebotPrivateMessage: "Özel", + onebotUserOrGroupId: "Grup/Kullanıcı Kimliği", + onebotSafetyTips: "Güvenlik için erişim tokeni ayarlamalısınız", + "PushDeer Key": "PushDeer Anahtarı", + "Footer Text": "Altbilgi metni", + "Show Powered By": "\"Powered by\" kısmını göster", + "Domain Names": "Alan isimleri", + signedInDisp: "{0} olarak oturum açıldı", + signedInDispDisabled: "Yetkilendirme Devre Dışı.", + "Certificate Expiry Notification": "Sertifika Sona Erme Bildirimi", + "API Username": "API Kullanıc Adı", + "API Key": "API Anahtarı", + "Recipient Number": "Alıcı Numarası", + "From Name/Number": "İsimden/Numaradan", + "Leave blank to use a shared sender number.": "Paylaşılan bir gönderen numarası kullanmak için boş bırakın.", + "Octopush API Version": "Octopush API Sürümü", + "Legacy Octopush-DM": "Eski Octopush-DM", + "endpoint": "endpoint", + octopushAPIKey: "Kontrol panelindeki HTTP API kimlik bilgilerinden \"API Key\"", + octopushLogin: "Kontrol panelindeki HTTP API kimlik bilgilerinden \"Login\"", + promosmsLogin: "API Oturum Açma Adı", + promosmsPassword: "API Şifresi", + "pushoversounds pushover": "Pushover (varsayılan)", + "pushoversounds bike": "Bisiklet", + "pushoversounds bugle": "Boru", + "pushoversounds cashregister": "Yazar kasa", + "pushoversounds classical": "Klasik", + "pushoversounds cosmic": "Kozmik", + "pushoversounds falling": "Düşme", + "pushoversounds gamelan": "Oyun Alanı", + "pushoversounds incoming": "Gelen", + "pushoversounds intermission": "Ara", + "pushoversounds magic": "Büyü", + "pushoversounds mechanical": "Mekanik", + "pushoversounds pianobar": "Piano", + "pushoversounds siren": "Siren", + "pushoversounds spacealarm": "Uzay Alarmı", + "pushoversounds tugboat": "Römorkör", + "pushoversounds alien": "Uzaylı Alarmı (uzun)", + "pushoversounds climb": "Tırmanış (uzun)", + "pushoversounds persistent": "Sürekli (uzun)", + "pushoversounds echo": "Pushover Yankı (uzun)", + "pushoversounds updown": "Yukarı Aşağı (uzun)", + "pushoversounds vibrate": "Sadece titreşim", + "pushoversounds none": "Yok (sessiz)", + pushyAPIKey: "Gizli API Anahtarı", + pushyToken: "Cihaz tokeni", + "Show update if available": "Varsa güncellemeyi göster", + "Also check beta release": "Ayrıca beta sürümünü kontrol edin", + "Using a Reverse Proxy?": "Ters Proxy mi Kullanıyorsunuz?", + "Check how to config it for WebSocket": "WebSocket için nasıl yapılandırılacağını kontrol edin", + "Steam Game Server": "Steam Oyun Sunucusu", + "Most likely causes:": "En olası nedenler:", + "The resource is no longer available.": "Kaynak artık mevcut değil.", + "There might be a typing error in the address.": "Adreste bir yazım hatası olabilir.", + "What you can try:": "Ne deneyebilirsin:", + "Retype the address.": "Adresi tekrar yazın.", + "Go back to the previous page.": "Bir önceki sayfaya geri git.", + "Coming Soon": "Yakında gelecek", + wayToGetClickSendSMSToken: "API Kullanıcı Adı ve API Anahtarını {0} adresinden alabilirsiniz.", }; From 0a8c922abf0b5919d4b6df83b08de133f164eb4d Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Wed, 25 May 2022 23:34:47 +0800 Subject: [PATCH 47/59] Fix default value of pagerduty-integration-url --- src/components/notifications/PagerDuty.vue | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/notifications/PagerDuty.vue b/src/components/notifications/PagerDuty.vue index 73f60443..059a9aef 100644 --- a/src/components/notifications/PagerDuty.vue +++ b/src/components/notifications/PagerDuty.vue @@ -8,7 +8,7 @@ </div> <div class="mb-3"> <label for="pagerduty-integration-url" class="form-label">{{ $t("Integration URL") }}</label> - <input id="pagerduty-integration-url" v-model="$parent.notification.pagerdutyIntegrationUrl" type="text" class="form-control" autocomplete="false" value="https://events.pagerduty.com/v2/enqueue"> + <input id="pagerduty-integration-url" v-model="$parent.notification.pagerdutyIntegrationUrl" type="text" class="form-control" autocomplete="false"> </div> <div class="mb-3"> <label for="pagerduty-priority" class="form-label">{{ $t("Priority") }}</label> @@ -36,5 +36,10 @@ export default { components: { HiddenInput, }, + mounted() { + if (typeof this.$parent.notification.pagerdutyIntegrationUrl === "undefined") { + this.$parent.notification.pagerdutyIntegrationUrl = "https://events.pagerduty.com/v2/enqueue"; + } + } }; </script> From 334cb57fed1aed6a3c616e48edc36b68dfe89c1e Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Thu, 26 May 2022 19:32:52 +0800 Subject: [PATCH 48/59] Update to 1.16.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 1ba25baf..806eff07 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uptime-kuma", - "version": "1.16.0-beta.0", + "version": "1.16.0", "license": "MIT", "repository": { "type": "git", @@ -39,7 +39,7 @@ "build-docker-nightly-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly-alpine --target nightly . --push", "build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain", "upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain", - "setup": "git checkout 1.15.1 && npm ci --production && npm run download-dist", + "setup": "git checkout 1.16.0 && npm ci --production && npm run download-dist", "download-dist": "node extra/download-dist.js", "mark-as-nightly": "node extra/mark-as-nightly.js", "reset-password": "node extra/reset-password.js", From ab4edf20928763f415d28865f5e4754cf6546196 Mon Sep 17 00:00:00 2001 From: Aram Akhavan <github@aram.nubmail.ca> Date: Thu, 26 May 2022 21:45:56 -0700 Subject: [PATCH 49/59] Fix log.debug calls --- server/model/monitor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 1bde1cb7..b5b20f54 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -348,7 +348,7 @@ class Monitor extends BeanModel { bean.msg = dnsMessage; bean.status = UP; } else if (this.type === "push") { // Type: Push - log.debug(`[${this.name}] Checking monitor at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`); + log.debug("monitor", `[${this.name}] Checking monitor at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`); const bufferTime = 1000; // 1s buffer to accommodate clock differences // Fix #922, since previous heartbeat could be inserted by API, it should get from database previousBeat = await Monitor.getPreviousHeartbeat(this.id); @@ -368,7 +368,7 @@ class Monitor extends BeanModel { } // No need to insert successful heartbeat for push type, so end here retries = 0; - log.debug(`[${this.name}] timeout = ${timeout}`); + log.debug("monitor", `[${this.name}] timeout = ${timeout}`); this.heartbeatInterval = setTimeout(beat, timeout); return; } From edd9bf38872ac0fd0825178cc59ce339b1caf83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20I=CC=87pek?= <developer@furkanipek.com.tr> Date: Fri, 27 May 2022 12:39:07 +0300 Subject: [PATCH 50/59] Update tr-TR.js --- src/languages/tr-TR.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/languages/tr-TR.js b/src/languages/tr-TR.js index 08cafa2c..8f4e6b81 100644 --- a/src/languages/tr-TR.js +++ b/src/languages/tr-TR.js @@ -515,5 +515,14 @@ export default { "Retype the address.": "Adresi tekrar yazın.", "Go back to the previous page.": "Bir önceki sayfaya geri git.", "Coming Soon": "Yakında gelecek", - wayToGetClickSendSMSToken: "API Kullanıcı Adı ve API Anahtarını {0} adresinden alabilirsiniz.", + wayToGetClickSendSMSToken: 'API Kullanıcı Adı ve API Anahtarını {0} adresinden alabilirsiniz.', + error: 'hata', + critical: 'kritik', + wayToGetPagerDutyKey: 'Bunu şuraya giderek alabilirsiniz: Servis -> Servis Dizini -> (Bir servis seçin) -> Entegrasyonlar -> Entegrasyon ekle. Burada "Events API V2" için arama yapabilirsiniz. Daha fazla bilgi {0}', + 'Integration Key': 'Entegrasyon Anahtarı', + 'Integration URL': 'Entegrasyon URL', + 'Auto resolve or acknowledged': 'Otomatik çözümleme veya onaylama', + 'do nothing': 'hiçbir şey yapma', + 'auto acknowledged': 'otomatik onaylama', + 'auto resolve': 'otomatik çözümleme' }; From 46dae99695b58b8b9942d16c3d8250381b1c8607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20I=CC=87pek?= <developer@furkanipek.com.tr> Date: Fri, 27 May 2022 12:51:41 +0300 Subject: [PATCH 51/59] Update tr-TR.js --- src/languages/tr-TR.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/languages/tr-TR.js b/src/languages/tr-TR.js index 8f4e6b81..b8eccf66 100644 --- a/src/languages/tr-TR.js +++ b/src/languages/tr-TR.js @@ -515,14 +515,14 @@ export default { "Retype the address.": "Adresi tekrar yazın.", "Go back to the previous page.": "Bir önceki sayfaya geri git.", "Coming Soon": "Yakında gelecek", - wayToGetClickSendSMSToken: 'API Kullanıcı Adı ve API Anahtarını {0} adresinden alabilirsiniz.', - error: 'hata', - critical: 'kritik', - wayToGetPagerDutyKey: 'Bunu şuraya giderek alabilirsiniz: Servis -> Servis Dizini -> (Bir servis seçin) -> Entegrasyonlar -> Entegrasyon ekle. Burada "Events API V2" için arama yapabilirsiniz. Daha fazla bilgi {0}', - 'Integration Key': 'Entegrasyon Anahtarı', - 'Integration URL': 'Entegrasyon URL', - 'Auto resolve or acknowledged': 'Otomatik çözümleme veya onaylama', - 'do nothing': 'hiçbir şey yapma', - 'auto acknowledged': 'otomatik onaylama', - 'auto resolve': 'otomatik çözümleme' + wayToGetClickSendSMSToken: "API Kullanıcı Adı ve API Anahtarını {0} adresinden alabilirsiniz.", + error: "hata", + critical: "kritik", + wayToGetPagerDutyKey: "Bunu şuraya giderek alabilirsiniz: Servis -> Servis Dizini -> (Bir servis seçin) -> Entegrasyonlar -> Entegrasyon ekle. Burada "Events API V2" için arama yapabilirsiniz. Daha fazla bilgi {0}", + "Integration Key": "Entegrasyon Anahtarı", + "Integration URL": "Entegrasyon URL", + "Auto resolve or acknowledged": "Otomatik çözümleme veya onaylama", + "do nothing": "hiçbir şey yapma", + "auto acknowledged": "otomatik onaylama", + "auto resolve": "otomatik çözümleme" }; From ef9f66fad9e6571e1724628d327be0b66ac204e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20I=CC=87pek?= <developer@furkanipek.com.tr> Date: Fri, 27 May 2022 15:02:40 +0300 Subject: [PATCH 52/59] Update tr-TR.js --- src/languages/tr-TR.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/tr-TR.js b/src/languages/tr-TR.js index b8eccf66..96753740 100644 --- a/src/languages/tr-TR.js +++ b/src/languages/tr-TR.js @@ -518,7 +518,7 @@ export default { wayToGetClickSendSMSToken: "API Kullanıcı Adı ve API Anahtarını {0} adresinden alabilirsiniz.", error: "hata", critical: "kritik", - wayToGetPagerDutyKey: "Bunu şuraya giderek alabilirsiniz: Servis -> Servis Dizini -> (Bir servis seçin) -> Entegrasyonlar -> Entegrasyon ekle. Burada "Events API V2" için arama yapabilirsiniz. Daha fazla bilgi {0}", + wayToGetPagerDutyKey: "Bunu şuraya giderek alabilirsiniz: Servis -> Servis Dizini -> (Bir servis seçin) -> Entegrasyonlar -> Entegrasyon ekle. Burada \"Events API V2\" için arama yapabilirsiniz. Daha fazla bilgi {0}", "Integration Key": "Entegrasyon Anahtarı", "Integration URL": "Entegrasyon URL", "Auto resolve or acknowledged": "Otomatik çözümleme veya onaylama", From 107a44885c7df42e107dd40585aa08aa3747514f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20I=CC=87pek?= <developer@furkanipek.com.tr> Date: Fri, 27 May 2022 15:05:09 +0300 Subject: [PATCH 53/59] Update tr-TR.js --- src/languages/tr-TR.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/tr-TR.js b/src/languages/tr-TR.js index 96753740..4904bdb7 100644 --- a/src/languages/tr-TR.js +++ b/src/languages/tr-TR.js @@ -524,5 +524,5 @@ export default { "Auto resolve or acknowledged": "Otomatik çözümleme veya onaylama", "do nothing": "hiçbir şey yapma", "auto acknowledged": "otomatik onaylama", - "auto resolve": "otomatik çözümleme" + "auto resolve": "otomatik çözümleme", }; From 10e16782b1ebc3c73da60db9ceb83d33ebfdec82 Mon Sep 17 00:00:00 2001 From: dhfhfk <dhfhfk1203@gmail.com> Date: Sat, 28 May 2022 17:10:40 +0900 Subject: [PATCH 54/59] Update ko-KR.js --- src/languages/ko-KR.js | 879 ++++++++++++++++++++++++----------------- 1 file changed, 526 insertions(+), 353 deletions(-) diff --git a/src/languages/ko-KR.js b/src/languages/ko-KR.js index ccb5df1d..41612070 100644 --- a/src/languages/ko-KR.js +++ b/src/languages/ko-KR.js @@ -1,355 +1,528 @@ export default { - languageName: "한국어", - checkEverySecond: "{0}초마다 확인해요.", - retryCheckEverySecond: "{0}초마다 다시 확인해요.", - retriesDescription: "서비스가 중단된 후 알림을 보내기 전 최대 재시도 횟수", - ignoreTLSError: "HTTPS 웹사이트에서 TLS/SSL 에러 무시하기", - upsideDownModeDescription: "서버 상태를 반대로 표시해요. 서버가 작동하면 오프라인으로 표시할 거예요.", - maxRedirectDescription: "최대 리다이렉트 횟수예요. 0을 입력하면 리다이렉트를 꺼요.", - acceptedStatusCodesDescription: "응답 성공으로 간주할 상태 코드를 정해요.", - passwordNotMatchMsg: "비밀번호 재입력이 일치하지 않아요.", - notificationDescription: "모니터링에 알림을 설정할 수 있어요.", - keywordDescription: "HTML 이나 JSON에서 대소문자를 구분해 키워드를 검색해요.", - pauseDashboardHome: "일시 정지", - deleteMonitorMsg: "정말 이 모니터링을 삭제할까요?", - deleteNotificationMsg: "정말 이 알림을 모든 모니터링에서 삭제할까요?", - resolverserverDescription: "Cloudflare가 기본 서버예요, 원한다면 언제나 다른 Resolver 서버로 변경할 수 있어요.", - rrtypeDescription: "모니터링할 RR-Type을 선택해요.", - pauseMonitorMsg: "정말 이 모니터링을 일시 정지할까요?", - enableDefaultNotificationDescription: "새로 추가하는 모든 모니터링에 이 알림을 기본적으로 활성화해요. 각 모니터에 대해 별도로 알림을 비활성화할 수 있어요.", - clearEventsMsg: "정말 이 모니터링에 대한 모든 이벤트를 삭제할까요?", - clearHeartbeatsMsg: "정말 이 모니터링에 대한 모든 하트비트를 삭제할까요?", - confirmClearStatisticsMsg: "정말 모든 통계를 삭제할까요?", - importHandleDescription: "이름이 같은 모든 모니터링이나 알림을 건너뛰려면 '기존값 건너뛰기'를 선택해주세요. '덮어쓰기'는 기존의 모든 모니터링과 알림을 삭제해요.", - confirmImportMsg: "정말 백업을 가져올까요? 가져오기 옵션을 제대로 설정했는지 다시 확인해주세요.", - twoFAVerifyLabel: "토큰을 입력해 2단계 인증이 작동하는지 확인해주세요.", - tokenValidSettingsMsg: "토큰이 유효해요! 이제 2단계 인증 설정을 저장할 수 있어요.", - confirmEnableTwoFAMsg: "정말 2단계 인증을 활성화할까요?", - confirmDisableTwoFAMsg: "정말 2단계 인증을 비활성화할까요?", - Settings: "설정", - Dashboard: "대시보드", - "New Update": "새로운 업데이트", - Language: "언어", - Appearance: "외형", - Theme: "테마", - General: "일반", - Version: "버전", - "Check Update On GitHub": "깃허브에서 업데이트 확인", - List: "목록", - Add: "추가", - "Add New Monitor": "새로운 모니터링 추가하기", - "Quick Stats": "간단한 정보", - Up: "온라인", - Down: "오프라인", - Pending: "대기 중", - Unknown: "알 수 없음", - Pause: "일시 정지", - Name: "이름", - Status: "상태", - DateTime: "날짜", - Message: "메시지", - "No important events": "중요 이벤트 없음", - Resume: "재개", - Edit: "수정", - Delete: "삭제", - Current: "현재", - Uptime: "업타임", - "Cert Exp.": "인증서 만료", - days: "일", - day: "일", - "-day": "-일", - hour: "시간", - "-hour": "-시간", - Response: "응답", - Ping: "핑", - "Monitor Type": "모니터링 종류", - Keyword: "키워드", - "Friendly Name": "이름", - URL: "URL", - Hostname: "호스트네임", - Port: "포트", - "Heartbeat Interval": "하트비트 주기", - Retries: "재시도", - "Heartbeat Retry Interval": "하트비드 재시도 주기", - Advanced: "고급", - "Upside Down Mode": "상태 반전 모드", - "Max. Redirects": "최대 리다이렉트", - "Accepted Status Codes": "응답 성공 상태 코드", - Save: "저장", - Notifications: "알림", - "Not available, please setup.": "존재하지 않아요, 새로운 거 하나 만드는 건 어때요?", - "Setup Notification": "알림 설정", - Light: "라이트", - Dark: "다크", - Auto: "자동", - "Theme - Heartbeat Bar": "테마 - 하트비트 바", - Normal: "기본값", - Bottom: "가운데", - None: "없애기", - Timezone: "시간대", - "Search Engine Visibility": "검색 엔진 활성화", - "Allow indexing": "인덱싱 허용", - "Discourage search engines from indexing site": "검색 엔진 인덱싱 거부", - "Change Password": "비밀번호 변경", - "Current Password": "기존 비밀번호", - "New Password": "새로운 비밀번호", - "Repeat New Password": "새로운 비밀번호 재입력", - "Update Password": "비밀번호 변경", - "Disable Auth": "인증 비활성화", - "Enable Auth": "인증 활성화", - Logout: "로그아웃", - Leave: "나가기", - "I understand, please disable": "기능에 대해 이해했으니 꺼주세요.", - Confirm: "확인", - Yes: "확인", - No: "취소", - Username: "이름", - Password: "비밀번호", - "Remember me": "비밀번호 기억하기", - Login: "로그인", - "No Monitors, please": "모니터링이 없어요,", - "add one": "하나 추가해봐요", - "Notification Type": "알림 종류", - Email: "이메일", - Test: "테스트", - "Certificate Info": "인증서 정보", - "Resolver Server": "Resolver 서버", - "Resource Record Type": "자원 레코드 유형", - "Last Result": "최근 결과", - "Create your admin account": "관리자 계정 만들기", - "Repeat Password": "비밀번호 재입력", - "Import Backup": "백업 가져오기", - "Export Backup": "백업 내보내기", - Export: "내보내기", - Import: "가져오기", - respTime: "응답 시간 (ms)", - notAvailableShort: "N/A", - "Default enabled": "기본 알림으로 설정", - "Apply on all existing monitors": "기존 모니터링에 모두 적용하기", - Create: "생성하기", - "Clear Data": "데이터 삭제", - Events: "이벤트", - Heartbeats: "하트비트", - "Auto Get": "자동 Get", - backupDescription: "모든 모니터링과 알림을 JSON 파일 형식에 저장할 수 있어요.", - backupDescription2: "히스토리와 이벤트 데이터는 포함되어 있지 않아요.", - backupDescription3: "알림 토큰과 같은 보안 데이터가 내보내기 파일에 포함되어 있으므로 관리에 주의해주세요.", - alertNoFile: "가져오기를 하기 위해 파일을 선택해주세요.", - alertWrongFileType: "JSON 파일을 선택해주세요.", - "Clear all statistics": "모든 통계치 삭제", - "Skip existing": "기존값 건너뛰기", - Overwrite: "덮어쓰기", - Options: "옵션", - "Keep both": "두개 모두 보존", - "Verify Token": "토큰 검증", - "Setup 2FA": "2단계 인증 설정하기", - "Enable 2FA": "2단계 인증 활성화", - "Disable 2FA": "2단계 인증 비활성화", - "2FA Settings": "2단계 인증 설정", - "Two Factor Authentication": "2단계 인증", - Active: "활성화", - Inactive: "비활성화", - Token: "토큰", - "Show URI": "URI 보기", - Tags: "태그", - "Add New below or Select...": "아래 새롭게 추가 또는 선택...", - "Tag with this name already exist.": "같은 태그 이름이 이미 존재해요.", - "Tag with this value already exist.": "같은 값을 가진 태그가 이미 존재해요.", - color: "색상", - "value (optional)": "값 (선택)", - Gray: "회색", - Red: "빨간색", - Orange: "주황색", - Green: "초록색", - Blue: "파란색", - Indigo: "남색", - Purple: "보라색", - Pink: "핑크색", - "Search...": "검색...", - "Avg. Ping": "평균 핑", - "Avg. Response": "평균 응답", - "Entry Page": "첫 페이지", - statusPageNothing: "아무것도 없어요. 새로운 그룹 또는 모니터링을 추가해주세요.", - "No Services": "서비스 없음", - "All Systems Operational": "모든 시스템 정상", - "Partially Degraded Service": "일부 시스템 비정상", - "Degraded Service": "모든 시스템 비정상", - "Add Group": "그룹 추가", - "Add a monitor": "모니터링 추가", - "Edit Status Page": "상태 페이지 수정", - "Go to Dashboard": "대시보드로 가기", - "Status Page": "상태 페이지", - "Status Pages": "상태 페이지", - defaultNotificationName: "내 {notification} 알림 ({number})", - here: "여기", - Required: "필수", - telegram: "Telegram", - "Bot Token": "봇 토큰", - wayToGetTelegramToken: "토큰은 여기서 얻을 수 있어요: {0}.", - "Chat ID": "채팅 ID", - supportTelegramChatID: "Direct Chat / Group / Channel's Chat ID를 지원해요.", - wayToGetTelegramChatID: "봇에 메시지를 보내 채팅 ID를 얻고 밑에 URL로 이동해 chat_id를 볼 수 있어요.", - "YOUR BOT TOKEN HERE": "여기에 BOT 토큰을 적어주세요.", - chatIDNotFound: "채팅 ID를 찾을 수 없어요. 먼저 봇에게 메시지를 보내주세요.", - webhook: "Webhook", - "Post URL": "Post URL", - "Content Type": "Content Type", - webhookJsonDesc: "{0}은 express.js와 같은 최신 HTTP 서버에 적합해요.", - webhookFormDataDesc: "{multipart}은 PHP에 적합해요. {decodeFunction}를 기준으로 json을 디코딩하면 되어요.", - smtp: "Email (SMTP)", - secureOptionNone: "없음 / STARTTLS (25, 587)", - secureOptionTLS: "TLS (465)", - "Ignore TLS Error": "TLS 에러 무시하기", - "From Email": "보내는 이메일", - "To Email": "받는 이메일", - smtpCC: "참조", - smtpBCC: "숨은 참조", - discord: "Discord", - "Discord Webhook URL": "Discord Webhook URL", - wayToGetDiscordURL: "서버 설정 -> 연동 -> 웹후크 보기 -> 새 웹후크에서 얻을 수 있어요.", - "Bot Display Name": "표시 이름", - "Prefix Custom Message": "접두사 메시지", - "Hello @everyone is...": "{'@'}everyone 서버 상태 알림이에요...", - teams: "Microsoft Teams", - "Webhook URL": "Webhook URL", - wayToGetTeamsURL: "{0}에서 Webhook을 어떻게 만드는지 알아봐요.", - signal: "Signal", - Number: "숫자", - Recipients: "받는 사람", - needSignalAPI: "REST API를 사용하는 Signal 클라이언트가 있어야 해요.", - wayToCheckSignalURL: "밑에 URL을 확인해 URL 설정 방법을 볼 수 있어요.", - signalImportant: "중요: 받는 사람의 그룹과 숫자는 섞을 수 없어요!", - gotify: "Gotify", - "Application Token": "애플리케이션 토큰", - "Server URL": "서버 URL", - Priority: "Priority", - slack: "Slack", - "Icon Emoji": "아이콘 이모지", - "Channel Name": "채널 이름", - "Uptime Kuma URL": "Uptime Kuma URL", - aboutWebhooks: "Webhook에 대한 설명: {0}", - aboutChannelName: "Webhook 채널을 우회하려면 {0} 채널 이름칸에 채널 이름을 입력해주세요. 예: #기타-채널", - aboutKumaURL: "Uptime Kuma URL칸을 공백으로 두면 기본적으로 Project Github 페이지로 설정해요.", - emojiCheatSheet: "이모지 목록 시트: {0}", - "rocket.chat": "Rocket.chat", - pushover: "Pushover", - pushy: "Pushy", - octopush: "Octopush", - promosms: "PromoSMS", - lunasea: "LunaSea", - apprise: "Apprise (50개 이상 알림 서비스)", - pushbullet: "Pushbullet", - line: "Line Messenger", - mattermost: "Mattermost", - "User Key": "사용자 키", - Device: "장치", - "Message Title": "메시지 제목", - "Notification Sound": "알림음", - "More info on:": "자세한 정보: {0}", - pushoverDesc1: "긴급 우선 순위 (2)는 재시도 사이에 기본적으로 30초의 타임아웃이 있고, 1시간 후에 만료되어요.", - pushoverDesc2: "다른 장치에 알림을 보내려면 장치칸을 입력해주세요.", - "SMS Type": "SMS 종류", - octopushTypePremium: "프리미엄 (빠름) - 알림 기능에 적합해요)", - octopushTypeLowCost: "저렴한 요금 (느림) - 가끔 차단될 수 있어요)", - "Check octopush prices": "{0}에서 Octopush 가격을 확인할 수 있어요.", - octopushPhoneNumber: "휴대전화 번호 (intl format, eg : +33612345678) ", - octopushSMSSender: "보내는 사람 이름 : 3-11개의 영숫자 및 여백공간 (a-z, A-Z, 0-9)", - "LunaSea Device ID": "LunaSea 장치 ID", - "Apprise URL": "Apprise URL", - "Example:": "예: {0}", - "Read more:": "더 보기: {0}", - "Status:": "상태: {0}", - "Read more": "더 보기", - appriseInstalled: "Apprise가 설치되어있어요.", - appriseNotInstalled: "Apprise가 설치되어있지 않아요. {0}", - "Access Token": "액세스 토큰", - "Channel access token": "채널 액세스 토큰", - "Line Developers Console": "Line 개발자 콘솔", - lineDevConsoleTo: "Line 개발자 콘솔 - {0}", - "Basic Settings": "기본 설정 메뉴", - "User ID": "사용자 ID", - "Messaging API": "Messaging API 메뉴", - wayToGetLineChannelToken: "먼저 {0}에 액세스하고, 공급자 및 채널 (Messaging API)을 만든 다음, 각 메뉴 밑에 언급된 메뉴에서 채널 액세스 토큰과 사용자 ID를 얻을 수 있어요.", - "Icon URL": "아이콘 URL", - aboutIconURL: "\"아이콘 URL\"에 사진 링크를 입력해 프로필 사진을 설정할 수 있어요. 아이콘 이모지가 설정되어 있으면 적용되지 않을 거예요.", - aboutMattermostChannelName: "채널 이름을 입력하면 Webhook이 게시할 기본 채널을 재설정할 수 있어요. 이 설정은 Mattermost 웹훅 설정에서 활성화해야 해요. 예: #기타-채널", - matrix: "Matrix", - promosmsTypeEco: "SMS ECO - 저렴하지만 느리고 가끔 과부하에 걸려요. 폴란드 수신자만 사용할 수 있어요. ", - promosmsTypeFlash: "SMS FLASH - 메시지가 받는 사람 장치에 자동으로 표시되어요. 폴란드 수신자만 사용할 수 있어요.", - promosmsTypeFull: "SMS FULL - SMS 프리미엄 티어, 보내는 사람 이름을 먼저 등록해야 해요. 알림 기능에 적합해요.", - promosmsTypeSpeed: "SMS SPEED - 시스템에서 가장 높은 우선순위예요. 매우 빠르고 신뢰할 수 있지만 비용이 많이 들어요 (SMS 전체 가격의 약 두 배).", - promosmsPhoneNumber: "전화 번호 (폴란드 수신자라면 지역번호를 적지 않아도 되어요.)", - promosmsSMSSender: "SMS 보내는 사람 이름 : 미리 등록된 이름 혹은 기본값 중 하나예요: InfoSMS, SMS Info, MaxSMS, INFO, SMS", - "Primary Base URL": "기본 URL", - "Push URL": "Push URL", - needPushEvery: "이 URL을 {0} 초 마다 호출할 수 있어요.", - pushOptionalParams: "선택적 파라미터: {0}", - emailCustomSubject: "커스텀 주제", - clicksendsms: "ClickSend SMS", - checkPrice: "{0} 가격 확인:", - apiCredentials: "API 인증정보", - octopushLegacyHint: "Octopush 레거시 버전 (2011-2020) 을 사용하시나요? 아니면 새 버전을 사용하시나요?", - "Feishu WebHookUrl": "Feishu WebHookURL", - matrixHomeserverURL: "Homeserver URL (http(s):// 와 함께 적어주세요. 그리고 포트 번호는 선택적 입니다.)", - "Internal Room Id": "내부 방 ID", - matrixDesc1: "Matrix 클라이언트 방 설정의 고급 섹션에서 내부 방 ID를 찾을 수 있어요. 내부 방 ID는 이렇게 생겼답니다: !QMdRCpUIfLwsfjxye6:home.server.", - matrixDesc2: "사용자의 모든 방에 대한 엑세스가 허용될 수 있어서 새로운 사용자를 만들고 원하는 방에만 초대한 후 엑세스 토큰을 사용하는 것이 좋아요. {0} 이 명령어를 통해 엑세스 토큰을 얻을 수 있어요.", - Method: "Method", - Body: "Body", - Headers: "Headers", - PushUrl: "Push URL", - HeadersInvalidFormat: "요청 Headers의 JSON 형식이 올바르지 않아요: ", - BodyInvalidFormat: "요청 Body의 JSON 형식이 올바르지 않아요: ", - "Monitor History": "모니터링 기록", - clearDataOlderThan: "모니터링 기록을 {0}일 동안 저장해요.", - PasswordsDoNotMatch: "비밀번호가 일치하지 않아요.", - records: "records", - "One record": "One record", - steamApiKeyDescription: "스팀 게임 서버를 모니터링하려면 Steam Web API 키가 필요해요. API 키는 하단 사이트에서 등록할 수 있어요: ", - "Current User": "현재 사용자", - recent: "최근", - Done: "완료", - Info: "정보", - Security: "보안", - "Steam API Key": "Steam API Key", - "Shrink Database": "데이터베이스 축소", - "Pick a RR-Type...": "RR-Type을 골라주세요...", - "Pick Accepted Status Codes...": "상태 코드를 골라주세요...", - Default: "기본", - "HTTP Options": "HTTP 옵션", - "Create Incident": "인시던트 만들기", - Title: "제목", - Content: "내용", - Style: "스타일", - info: "정보", - warning: "경고", - danger: "위험", - primary: "기본", - light: "라이트", - dark: "다크", - Post: "올리기", - "Please input title and content": "제목과 내용을 작성해주세요.", - Created: "생성 날짜", - "Last Updated": "마지막 업데이트", - Unpin: "제거", - "Switch to Light Theme": "라이트 테마로 전환", - "Switch to Dark Theme": "다크 테마로 전환", - "Show Tags": "태그 보이기", - "Hide Tags": "태그 숨기기", - Description: "설명", - "No monitors available.": "모니터링이 없어요.", - "Add one": "추가하기", - "No Monitors": "모니터링 없음", - "Untitled Group": "이름없는 그룹", - Services: "서비스", - Discard: "취소", - Cancel: "취소", - "Powered by": "Powered by", - shrinkDatabaseDescription: "SQLite 데이터베이스 VACUUM을 트리거해요. 만약 데이터베이스가 1.10.0 버전 이후에 생성되었다면 AUTO_VACUUM이 설정되어 있어 이 작업은 필요 없을 거에요.", - serwersms: "SerwerSMS.pl", - serwersmsAPIUser: "API Usename (webapi_ 접두사 포함)", - serwersmsAPIPassword: "API 비밀번호", - serwersmsPhoneNumber: "휴대전화 번호", - serwersmsSenderName: "보내는 사람 이름 (customer portal를 통해 가입된 정보)", - stackfield: "Stackfield", + languageName: "한국어", + checkEverySecond: "{0}초마다 확인해요.", + retryCheckEverySecond: "{0}초마다 다시 확인해요.", + retriesDescription: "서비스가 중단된 후 알림을 보내기 전 최대 재시도 횟수", + ignoreTLSError: "HTTPS 웹사이트에서 TLS/SSL 에러 무시하기", + upsideDownModeDescription: "서버 상태를 반대로 표시해요. 서버가 작동하면 오프라인으로 표시할 거예요.", + maxRedirectDescription: "최대 리다이렉트 횟수예요. 0을 입력하면 리다이렉트를 꺼요.", + acceptedStatusCodesDescription: "응답 성공으로 간주할 상태 코드를 정해요.", + passwordNotMatchMsg: "비밀번호 재입력이 일치하지 않아요.", + notificationDescription: "모니터링에 알림을 설정할 수 있어요.", + keywordDescription: "HTML 이나 JSON에서 대소문자를 구분해 키워드를 검색해요.", + pauseDashboardHome: "일시 정지", + deleteMonitorMsg: "정말 이 모니터링을 삭제할까요?", + deleteNotificationMsg: "정말 이 알림을 모든 모니터링에서 삭제할까요?", + resolverserverDescription: "Cloudflare가 기본 서버예요, 원한다면 언제나 다른 Resolver 서버로 변경할 수 있어요.", + rrtypeDescription: "모니터링할 RR-Type을 선택해요.", + pauseMonitorMsg: "정말 이 모니터링을 일시 정지할까요?", + enableDefaultNotificationDescription: "새로 추가하는 모든 모니터링에 이 알림을 기본적으로 활성화해요. 각 모니터에 대해 별도로 알림을 비활성화할 수 있어요.", + clearEventsMsg: "정말 이 모니터링에 대한 모든 이벤트를 삭제할까요?", + clearHeartbeatsMsg: "정말 이 모니터링에 대한 모든 하트비트를 삭제할까요?", + confirmClearStatisticsMsg: "정말 모든 통계를 삭제할까요?", + importHandleDescription: "이름이 같은 모든 모니터링이나 알림을 건너뛰려면 '기존값 건너뛰기'를 선택해주세요. '덮어쓰기'는 기존의 모든 모니터링과 알림을 삭제해요.", + confirmImportMsg: "정말 백업을 가져올까요? 가져오기 옵션을 제대로 설정했는지 다시 확인해주세요.", + twoFAVerifyLabel: "토큰을 입력해 2단계 인증이 작동하는지 확인해주세요.", + tokenValidSettingsMsg: "토큰이 유효해요! 이제 2단계 인증 설정을 저장할 수 있어요.", + confirmEnableTwoFAMsg: "정말 2단계 인증을 활성화할까요?", + confirmDisableTwoFAMsg: "정말 2단계 인증을 비활성화할까요?", + Settings: "설정", + Dashboard: "대시보드", + "New Update": "새로운 업데이트", + Language: "언어", + Appearance: "외형", + Theme: "테마", + General: "일반", + Version: "버전", + "Check Update On GitHub": "깃허브에서 업데이트 확인", + List: "목록", + Add: "추가", + "Add New Monitor": "새로운 모니터링 추가하기", + "Quick Stats": "간단한 정보", + Up: "온라인", + Down: "오프라인", + Pending: "대기 중", + Unknown: "알 수 없음", + Pause: "일시 정지", + Name: "이름", + Status: "상태", + DateTime: "날짜", + Message: "메시지", + "No important events": "중요 이벤트 없음", + Resume: "재개", + Edit: "수정", + Delete: "삭제", + Current: "현재", + Uptime: "업타임", + "Cert Exp.": "인증서 만료", + days: "일", + day: "일", + "-day": "-일", + hour: "시간", + "-hour": "-시간", + Response: "응답", + Ping: "핑", + "Monitor Type": "모니터링 종류", + Keyword: "키워드", + "Friendly Name": "이름", + URL: "URL", + Hostname: "호스트네임", + Port: "포트", + "Heartbeat Interval": "하트비트 주기", + Retries: "재시도", + "Heartbeat Retry Interval": "하트비드 재시도 주기", + Advanced: "고급", + "Upside Down Mode": "상태 반전 모드", + "Max. Redirects": "최대 리다이렉트", + "Accepted Status Codes": "응답 성공 상태 코드", + Save: "저장", + Notifications: "알림", + "Not available, please setup.": "존재하지 않아요, 새로운 거 하나 만드는 건 어때요?", + "Setup Notification": "알림 설정", + Light: "라이트", + Dark: "다크", + Auto: "자동", + "Theme - Heartbeat Bar": "테마 - 하트비트 바", + Normal: "기본값", + Bottom: "가운데", + None: "없애기", + Timezone: "시간대", + "Search Engine Visibility": "검색 엔진 활성화", + "Allow indexing": "인덱싱 허용", + "Discourage search engines from indexing site": "검색 엔진 인덱싱 거부", + "Change Password": "비밀번호 변경", + "Current Password": "기존 비밀번호", + "New Password": "새로운 비밀번호", + "Repeat New Password": "새로운 비밀번호 재입력", + "Update Password": "비밀번호 변경", + "Disable Auth": "인증 비활성화", + "Enable Auth": "인증 활성화", + Logout: "로그아웃", + Leave: "나가기", + "I understand, please disable": "기능에 대해 이해했으니 꺼주세요.", + Confirm: "확인", + Yes: "확인", + No: "취소", + Username: "이름", + Password: "비밀번호", + "Remember me": "비밀번호 기억하기", + Login: "로그인", + "No Monitors, please": "모니터링이 없어요,", + "add one": "하나 추가해봐요", + "Notification Type": "알림 종류", + Email: "이메일", + Test: "테스트", + "Certificate Info": "인증서 정보", + "Resolver Server": "Resolver 서버", + "Resource Record Type": "자원 레코드 유형", + "Last Result": "최근 결과", + "Create your admin account": "관리자 계정 만들기", + "Repeat Password": "비밀번호 재입력", + "Import Backup": "백업 가져오기", + "Export Backup": "백업 내보내기", + Export: "내보내기", + Import: "가져오기", + respTime: "응답 시간 (ms)", + notAvailableShort: "N/A", + "Default enabled": "기본 알림으로 설정", + "Apply on all existing monitors": "기존 모니터링에 모두 적용하기", + Create: "생성하기", + "Clear Data": "데이터 삭제", + Events: "이벤트", + Heartbeats: "하트비트", + "Auto Get": "자동 Get", + backupDescription: "모든 모니터링과 알림을 JSON 파일 형식에 저장할 수 있어요.", + backupDescription2: "히스토리와 이벤트 데이터는 포함되어 있지 않아요.", + backupDescription3: "알림 토큰과 같은 보안 데이터가 내보내기 파일에 포함되어 있으므로 관리에 주의해주세요.", + alertNoFile: "가져오기를 하기 위해 파일을 선택해주세요.", + alertWrongFileType: "JSON 파일을 선택해주세요.", + "Clear all statistics": "모든 통계치 삭제", + "Skip existing": "기존값 건너뛰기", + Overwrite: "덮어쓰기", + Options: "옵션", + "Keep both": "두개 모두 보존", + "Verify Token": "토큰 검증", + "Setup 2FA": "2단계 인증 설정하기", + "Enable 2FA": "2단계 인증 활성화", + "Disable 2FA": "2단계 인증 비활성화", + "2FA Settings": "2단계 인증 설정", + "Two Factor Authentication": "2단계 인증", + Active: "활성화", + Inactive: "비활성화", + Token: "토큰", + "Show URI": "URI 보기", + Tags: "태그", + "Add New below or Select...": "아래 새롭게 추가 또는 선택...", + "Tag with this name already exist.": "같은 태그 이름이 이미 존재해요.", + "Tag with this value already exist.": "같은 값을 가진 태그가 이미 존재해요.", + color: "색상", + "value (optional)": "값 (선택)", + Gray: "회색", + Red: "빨간색", + Orange: "주황색", + Green: "초록색", + Blue: "파란색", + Indigo: "남색", + Purple: "보라색", + Pink: "핑크색", + "Search...": "검색...", + "Avg. Ping": "평균 핑", + "Avg. Response": "평균 응답", + "Entry Page": "첫 페이지", + statusPageNothing: "아무것도 없어요. 새로운 그룹 또는 모니터링을 추가해주세요.", + "No Services": "서비스 없음", + "All Systems Operational": "모든 시스템 정상", + "Partially Degraded Service": "일부 시스템 비정상", + "Degraded Service": "모든 시스템 비정상", + "Add Group": "그룹 추가", + "Add a monitor": "모니터링 추가", + "Edit Status Page": "상태 페이지 수정", + "Go to Dashboard": "대시보드로 가기", + "Status Page": "상태 페이지", + "Status Pages": "상태 페이지", + defaultNotificationName: "내 {notification} 알림 ({number})", + here: "여기", + Required: "필수", + telegram: "Telegram", + "Bot Token": "봇 토큰", + wayToGetTelegramToken: "토큰은 여기서 얻을 수 있어요: {0}.", + "Chat ID": "채팅 ID", + supportTelegramChatID: "개인 채팅 / 그룹 / 채널의 ID를 지원해요.", + wayToGetTelegramChatID: "봇에 메시지를 보내 채팅 ID를 얻고 밑에 URL로 이동해 chat_id를 볼 수 있어요.", + "YOUR BOT TOKEN HERE": "봇 토큰", + chatIDNotFound: "채팅 ID를 찾을 수 없어요. 먼저 봇에게 메시지를 보내주세요.", + webhook: "Webhook", + "Post URL": "Post URL", + "Content Type": "Content Type", + webhookJsonDesc: "{0}은 express.js와 같은 최신 HTTP 서버에 적합해요.", + webhookFormDataDesc: "{multipart}은 PHP에 적합해요. {decodeFunction}를 기준으로 json을 디코딩하면 되어요.", + smtp: "Email (SMTP)", + secureOptionNone: "없음 / STARTTLS (25, 587)", + secureOptionTLS: "TLS (465)", + "Ignore TLS Error": "TLS 에러 무시하기", + "From Email": "보내는 이메일", + "To Email": "받는 이메일", + smtpCC: "참조", + smtpBCC: "숨은 참조", + discord: "Discord", + "Discord Webhook URL": "Discord Webhook URL", + wayToGetDiscordURL: "서버 설정 -> 연동 -> 웹후크 보기 -> 새 웹후크에서 얻을 수 있어요.", + "Bot Display Name": "표시 이름", + "Prefix Custom Message": "접두사 메시지", + "Hello @everyone is...": "{'@'}everyone 서버 상태 알림이에요...", + teams: "Microsoft Teams", + "Webhook URL": "Webhook URL", + wayToGetTeamsURL: "{0}에서 Webhook을 어떻게 만드는지 알아봐요.", + signal: "Signal", + Number: "숫자", + Recipients: "받는 사람", + needSignalAPI: "REST API를 사용하는 Signal 클라이언트가 있어야 해요.", + wayToCheckSignalURL: "밑에 URL을 확인해 URL 설정 방법을 볼 수 있어요.", + signalImportant: "중요: 받는 사람의 그룹과 숫자는 섞을 수 없어요!", + gotify: "Gotify", + "Application Token": "애플리케이션 토큰", + "Server URL": "서버 URL", + Priority: "Priority", + slack: "Slack", + "Icon Emoji": "아이콘 이모지", + "Channel Name": "채널 이름", + "Uptime Kuma URL": "Uptime Kuma URL", + aboutWebhooks: "Webhook에 대한 설명: {0}", + aboutChannelName: "Webhook 채널을 우회하려면 {0} 채널 이름칸에 채널 이름을 입력해주세요. 예: #기타-채널", + aboutKumaURL: "Uptime Kuma URL칸을 공백으로 두면 기본적으로 Project Github 페이지로 설정해요.", + emojiCheatSheet: "이모지 목록 시트: {0}", + "rocket.chat": "Rocket.chat", + pushover: "Pushover", + pushy: "Pushy", + octopush: "Octopush", + promosms: "PromoSMS", + lunasea: "LunaSea", + apprise: "Apprise (50개 이상 알림 서비스)", + pushbullet: "Pushbullet", + line: "Line Messenger", + mattermost: "Mattermost", + "User Key": "사용자 키", + Device: "장치", + "Message Title": "메시지 제목", + "Notification Sound": "알림음", + "More info on:": "자세한 정보: {0}", + pushoverDesc1: "긴급 우선 순위 (2)는 재시도 사이에 기본적으로 30초의 타임아웃이 있고, 1시간 후에 만료되어요.", + pushoverDesc2: "다른 장치에 알림을 보내려면 장치칸을 입력해주세요.", + "SMS Type": "SMS 종류", + octopushTypePremium: "프리미엄 (빠름) - 알림 기능에 적합해요)", + octopushTypeLowCost: "저렴한 요금 (느림) - 가끔 차단될 수 있어요)", + "Check octopush prices": "{0}에서 Octopush 가격을 확인할 수 있어요.", + octopushPhoneNumber: "휴대전화 번호 (intl format, eg : +33612345678) ", + octopushSMSSender: "보내는 사람 이름 : 3-11개의 영숫자 및 여백공간 (a-z, A-Z, 0-9)", + "LunaSea Device ID": "LunaSea 장치 ID", + "Apprise URL": "Apprise URL", + "Example:": "예: {0}", + "Read more:": "더 보기: {0}", + "Status:": "상태: {0}", + "Read more": "더 보기", + appriseInstalled: "Apprise가 설치되어있어요.", + appriseNotInstalled: "Apprise가 설치되어있지 않아요. {0}", + "Access Token": "액세스 토큰", + "Channel access token": "채널 액세스 토큰", + "Line Developers Console": "Line 개발자 콘솔", + lineDevConsoleTo: "Line 개발자 콘솔 - {0}", + "Basic Settings": "기본 설정 메뉴", + "User ID": "사용자 ID", + "Messaging API": "Messaging API 메뉴", + wayToGetLineChannelToken: "먼저 {0}에 액세스하고, 공급자 및 채널 (Messaging API)을 만든 다음, 각 메뉴 밑에 언급된 메뉴에서 채널 액세스 토큰과 사용자 ID를 얻을 수 있어요.", + "Icon URL": "아이콘 URL", + aboutIconURL: "\"아이콘 URL\"에 사진 링크를 입력해 프로필 사진을 설정할 수 있어요. 아이콘 이모지가 설정되어 있으면 적용되지 않을 거예요.", + aboutMattermostChannelName: "채널 이름을 입력하면 Webhook이 게시할 기본 채널을 재설정할 수 있어요. 이 설정은 Mattermost 웹훅 설정에서 활성화해야 해요. 예: #기타-채널", + matrix: "Matrix", + promosmsTypeEco: "SMS ECO - 저렴하지만 느리고 가끔 과부하에 걸려요. 폴란드 수신자만 사용할 수 있어요. ", + promosmsTypeFlash: "SMS FLASH - 메시지가 받는 사람 장치에 자동으로 표시되어요. 폴란드 수신자만 사용할 수 있어요.", + promosmsTypeFull: "SMS FULL - SMS 프리미엄 티어, 보내는 사람 이름을 먼저 등록해야 해요. 알림 기능에 적합해요.", + promosmsTypeSpeed: "SMS SPEED - 시스템에서 가장 높은 우선순위예요. 매우 빠르고 신뢰할 수 있지만 비용이 많이 들어요 (SMS 전체 가격의 약 두 배).", + promosmsPhoneNumber: "전화 번호 (폴란드 수신자라면 지역번호를 적지 않아도 되어요.)", + promosmsSMSSender: "SMS 보내는 사람 이름 : 미리 등록된 이름 혹은 기본값 중 하나예요: InfoSMS, SMS Info, MaxSMS, INFO, SMS", + "Primary Base URL": "기본 URL", + "Push URL": "Push URL", + needPushEvery: "이 URL을 {0} 초 마다 호출할 수 있어요.", + pushOptionalParams: "선택적 파라미터: {0}", + emailCustomSubject: "커스텀 주제", + clicksendsms: "ClickSend SMS", + checkPrice: "{0} 가격 확인:", + apiCredentials: "API 인증정보", + octopushLegacyHint: "Octopush 레거시 버전 (2011-2020) 을 사용하시나요? 아니면 새 버전을 사용하시나요?", + "Feishu WebHookUrl": "Feishu WebHookURL", + matrixHomeserverURL: "Homeserver URL (http(s):// 와 함께 적어주세요. 그리고 포트 번호는 선택적 입니다.)", + "Internal Room Id": "내부 방 ID", + matrixDesc1: "Matrix 클라이언트 방 설정의 고급 섹션에서 내부 방 ID를 찾을 수 있어요. 내부 방 ID는 이렇게 생겼답니다: !QMdRCpUIfLwsfjxye6:home.server.", + matrixDesc2: "사용자의 모든 방에 대한 엑세스가 허용될 수 있어서 새로운 사용자를 만들고 원하는 방에만 초대한 후 엑세스 토큰을 사용하는 것이 좋아요. {0} 이 명령어를 통해 엑세스 토큰을 얻을 수 있어요.", + Method: "Method", + Body: "Body", + Headers: "Headers", + PushUrl: "Push URL", + HeadersInvalidFormat: "요청 Headers의 JSON 형식이 올바르지 않아요: ", + BodyInvalidFormat: "요청 Body의 JSON 형식이 올바르지 않아요: ", + "Monitor History": "모니터링 기록", + clearDataOlderThan: "모니터링 기록을 {0}일 동안 저장해요.", + PasswordsDoNotMatch: "비밀번호가 일치하지 않아요.", + records: "records", + "One record": "One record", + steamApiKeyDescription: "스팀 게임 서버를 모니터링하려면 Steam Web API 키가 필요해요. API 키는 하단 웹사이트에서 등록할 수 있어요: ", + "Current User": "현재 사용자", + recent: "최근", + Done: "완료", + Info: "정보", + Security: "보안", + "Steam API Key": "스팀 API 키", + "Shrink Database": "데이터베이스 축소", + "Pick a RR-Type...": "RR-Type을 골라주세요...", + "Pick Accepted Status Codes...": "상태 코드를 골라주세요...", + Default: "기본", + "HTTP Options": "HTTP 옵션", + "Create Incident": "인시던트 만들기", + Title: "제목", + Content: "내용", + Style: "스타일", + info: "정보", + warning: "경고", + danger: "위험", + primary: "기본", + light: "라이트", + dark: "다크", + Post: "올리기", + "Please input title and content": "제목과 내용을 작성해주세요.", + Created: "생성 날짜", + "Last Updated": "마지막 업데이트", + Unpin: "제거", + "Switch to Light Theme": "라이트 테마로 전환", + "Switch to Dark Theme": "다크 테마로 전환", + "Show Tags": "태그 보이기", + "Hide Tags": "태그 숨기기", + Description: "설명", + "No monitors available.": "모니터링이 없어요.", + "Add one": "추가하기", + "No Monitors": "모니터링 없음", + "Untitled Group": "이름없는 그룹", + Services: "서비스", + Discard: "취소", + Cancel: "취소", + "Powered by": "Powered by", + shrinkDatabaseDescription: "SQLite 데이터베이스 VACUUM을 트리거해요. 만약 데이터베이스가 1.10.0 버전 이후에 생성되었다면 AUTO_VACUUM이 설정되어 있어 이 작업은 필요 없을 거에요.", + serwersms: "SerwerSMS.pl", + serwersmsAPIUser: "API Usename (webapi_ 접두사 포함)", + serwersmsAPIPassword: "API 비밀번호", + serwersmsPhoneNumber: "휴대전화 번호", + serwersmsSenderName: "보내는 사람 이름 (customer portal를 통해 가입된 정보)", + stackfield: "Stackfield", + dnsPortDescription: "DNS 서버 포트, 기본값은 53 이에요. 포트는 언제나 변경할 수 있어요.", + PushByTechulus: "Push by Techulus", + GoogleChat: "Google Chat (Google Workspace only)", + topic: "Topic", + topicExplanation: "모니터링할 MQTT Topic", + successMessage: "성공 메시지", + successMessageExplanation: "성공으로 간주되는 MQTT 메시지", + error: "error", + critical: "critical", + Customize: "커스터마이즈", + "Custom Footer": "커스텀 Footer", + "Custom CSS": "커스텀 CSS", + smtpDkimSettings: "DKIM 설정", + smtpDkimDesc: "사용 방법은 DKIM {0}를 참조하세요.", + documentation: "문서", + smtpDkimDomain: "도메인 이름", + smtpDkimKeySelector: "Key Selector", + smtpDkimPrivateKey: "Private Key", + smtpDkimHashAlgo: "해시 알고리즘 (선택)", + smtpDkimheaderFieldNames: "서명할 헤더 키 (선택)", + smtpDkimskipFields: "서명하지 않을 헤더 키 (선택)", + wayToGetPagerDutyKey: "Service -> Service Directory -> (서비스 선택) -> Integrations -> Add integration. 에서 찾을 수 있어요. 자세히 알아보려면 {0}에서 \"Events API V2\"를 검색해봐요.", + "Integration Key": "Integration 키", + "Integration URL": "Integration URL", + "Auto resolve or acknowledged": "자동 해결 혹은 승인", + "do nothing": "아무것도 하지 않기", + "auto acknowledged": "자동 승인 (acknowledged)", + "auto resolve": "자동 해결 (resolve)", + gorush: "Gorush", + alerta: "Alerta", + alertaApiEndpoint: "API Endpoint", + alertaEnvironment: "환경변수", + alertaApiKey: "API 키", + alertaAlertState: "경고 상태", + alertaRecoverState: "해결된 상태", + deleteStatusPageMsg: "정말 이 상태 페이지를 삭제할까요?", + Proxies: "프록시", + default: "Default", + enabled: "활성화", + setAsDefault: "기본 프록시로 설정", + deleteProxyMsg: "정말 이 프록시를 모든 모니터링에서 삭제할까요?", + proxyDescription: "프록시가 작동하려면 모니터에 할당되어야 해요.", + enableProxyDescription: "이 프록시는 활성화될 때까지 영향을 미치지 않아요. 활성화 상태에 따라 모든 모니터에서 프록시를 일시정지할 수 있어요.", + setAsDefaultProxyDescription: "새로 추가하는 모든 모니터링에 이 프록시를 기본적으로 활성화해요. 각 모니터에 대해 별도로 프록시를 비활성화할 수 있어요.", + "Certificate Chain": "인증서 체인", + Valid: "유효", + Invalid: "유효하지 않음", + AccessKeyId: "AccessKey ID", + SecretAccessKey: "AccessKey Secret", + PhoneNumbers: "휴대전화 번호", + TemplateCode: "템플릿 코드", + SignName: "SignName", + "Sms template must contain parameters: ": "Sms 템플릿은 다음과 같은 파라미터가 포함되어야 해요:", + "Bark Endpoint": "Bark Endpoint", + WebHookUrl: "웹훅 URL", + SecretKey: "Secret Key", + "For safety, must use secret key": "안전을 위해 꼭 Secret Key를 사용하세요.", + "Device Token": "기기 Token", + Platform: "플랫폼", + iOS: "iOS", + Android: "Android", + Huawei: "Huawei", + High: "High", + Retry: "재시도", + Topic: "Topic", + "WeCom Bot Key": "WeCom Bot Key", + "Setup Proxy": "프록시 설정", + "Proxy Protocol": "프록시 프로토콜", + "Proxy Server": "프록시 서버", + "Proxy server has authentication": "프록시 서버에 인증 절차가 있음", + User: "사용자", + Installed: "설치됨", + "Not installed": "설치되어 있지 않음", + Running: "작동 중", + "Not running": "작동하고 있지 않음", + "Remove Token": "토큰 삭제", + Start: "시작", + Stop: "정지", + "Uptime Kuma": "Uptime Kuma", + "Add New Status Page": "새로운 상태 페이지 만들기", + Slug: "주소", + "Accept characters:": "허용되는 문자열:", + startOrEndWithOnly: "{0}로 시작하거나 끝나야 해요.", + "No consecutive dashes": "연속되는 대시는 허용되지 않아요", + Next: "다음", + "The slug is already taken. Please choose another slug.": "이미 존재하는 주소에요. 다른 주소를 사용해 주세요.", + "No Proxy": "프록시 없음", + "HTTP Basic Auth": "HTTP 인증", + "New Status Page": "새로운 상태 페이지", + "Page Not Found": "페이지를 찾을 수 없어요", + "Reverse Proxy": "리버스 프록시", + Backup: "백업", + About: "정보", + wayToGetCloudflaredURL: "({0}에서 Cloudflare 다운로드 하기)", + cloudflareWebsite: "Cloudflare 웹사이트", + "Message:": "메시지:", + "Don't know how to get the token? Please read the guide:": "토큰을 얻는 방법은 이 가이드를 확인해주세요:", + "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.": "Cloudflare Tunnel를 연결하면 현재 연결이 끊길 수 있어요. 정말 중지할까요? 비밀번호를 입력해 확인하세요.", + "Other Software": "다른 소프트웨어", + "For example: nginx, Apache and Traefik.": "nginx, Apache, Traefik 등을 사용할 수 있어요.", + "Please read": "이 문서를 참조하세요:", + "Subject:": "Subject:", + "Valid To:": "Valid To:", + "Days Remaining:": "남은 일수:", + "Issuer:": "Issuer:", + "Fingerprint:": "Fingerprint:", + "No status pages": "상태 페이지 없음", + "Domain Name Expiry Notification": "도메인 이름 만료 알림", + Proxy: "프록시", + "Date Created": "생성된 날짜", + onebotHttpAddress: "OneBot HTTP 주소", + onebotMessageType: "OneBot 메시지 종류", + onebotGroupMessage: "그룹 메시지", + onebotPrivateMessage: "개인 메시지", + onebotUserOrGroupId: "그룹/사용자 ID", + onebotSafetyTips: "안전을 위해 Access 토큰을 설정하세요.", + "PushDeer Key": "PushDeer 키", + "Footer Text": "Footer 문구", + "Show Powered By": "Powered By 문구 표시하기", + "Domain Names": "도메인 이름", + signedInDisp: "{0} 로그인됨", + signedInDispDisabled: "인증 비활성화됨.", + "Certificate Expiry Notification": "인증서 만료 알림", + "API Username": "API 사용자 이름", + "API Key": "API 키", + "Recipient Number": "받는 사람 번호", + "From Name/Number": "발신자 이름/번호", + "Leave blank to use a shared sender number.": "공유 발신자 번호를 사용하려면 공백으로 두세요.", + "Octopush API Version": "Octopush API 버전", + "Legacy Octopush-DM": "레거시 Octopush-DM", + endpoint: "endpoint", + octopushAPIKey: "제어판 HTTP API credentials 에서 \"API key\"", + octopushLogin: "제어판 HTTP API credentials 에서 \"Login\"", + promosmsLogin: "API 로그인 이름", + promosmsPassword: "API 비밀번호", + "pushoversounds pushover": "Pushover (기본)", + "pushoversounds bike": "Bike", + "pushoversounds bugle": "Bugle", + "pushoversounds cashregister": "Cash Register", + "pushoversounds classical": "Classical", + "pushoversounds cosmic": "Cosmic", + "pushoversounds falling": "Falling", + "pushoversounds gamelan": "Gamelan", + "pushoversounds incoming": "Incoming", + "pushoversounds intermission": "Intermission", + "pushoversounds magic": "Magic", + "pushoversounds mechanical": "Mechanical", + "pushoversounds pianobar": "Piano Bar", + "pushoversounds siren": "Siren", + "pushoversounds spacealarm": "Space Alarm", + "pushoversounds tugboat": "Tug Boat", + "pushoversounds alien": "Alien Alarm (long)", + "pushoversounds climb": "Climb (long)", + "pushoversounds persistent": "Persistent (long)", + "pushoversounds echo": "Pushover Echo (long)", + "pushoversounds updown": "Up Down (long)", + "pushoversounds vibrate": "진동만", + "pushoversounds none": "없음 (무음)", + pushyAPIKey: "비밀 API 키", + pushyToken: "기기 토큰", + "Show update if available": "사용 가능한 경우에 업데이트 표시", + "Also check beta release": "베타 릴리즈 확인", + "Using a Reverse Proxy?": "리버스 프록시를 사용하시나요?", + "Check how to config it for WebSocket": "웹소켓에 대한 설정 방법 확인", + "Steam Game Server": "스팀 게임 서버", + "Most likely causes:": "원인:", + "The resource is no longer available.": "더이상 사용할 수 없어요.", + "There might be a typing error in the address.": "주소에 오탈자가 있을 수 있어요.", + "What you can try:": "해결 방법:", + "Retype the address.": "주소 다시 입력하기", + "Go back to the previous page.": "이전 페이지로 돌아가기", + "Coming Soon": "Coming Soon", + wayToGetClickSendSMSToken: "{0}에서 API 사용자 이름과 키를 얻을 수 있어요.", }; From e25d406fa5a16085ed75fefc786f68da1c56c564 Mon Sep 17 00:00:00 2001 From: dhfhfk <dhfhfk1203@gmail.com> Date: Sat, 28 May 2022 17:12:40 +0900 Subject: [PATCH 55/59] Eslint --- src/languages/ko-KR.js | 1052 ++++++++++++++++++++-------------------- 1 file changed, 526 insertions(+), 526 deletions(-) diff --git a/src/languages/ko-KR.js b/src/languages/ko-KR.js index 41612070..da034167 100644 --- a/src/languages/ko-KR.js +++ b/src/languages/ko-KR.js @@ -1,528 +1,528 @@ export default { - languageName: "한국어", - checkEverySecond: "{0}초마다 확인해요.", - retryCheckEverySecond: "{0}초마다 다시 확인해요.", - retriesDescription: "서비스가 중단된 후 알림을 보내기 전 최대 재시도 횟수", - ignoreTLSError: "HTTPS 웹사이트에서 TLS/SSL 에러 무시하기", - upsideDownModeDescription: "서버 상태를 반대로 표시해요. 서버가 작동하면 오프라인으로 표시할 거예요.", - maxRedirectDescription: "최대 리다이렉트 횟수예요. 0을 입력하면 리다이렉트를 꺼요.", - acceptedStatusCodesDescription: "응답 성공으로 간주할 상태 코드를 정해요.", - passwordNotMatchMsg: "비밀번호 재입력이 일치하지 않아요.", - notificationDescription: "모니터링에 알림을 설정할 수 있어요.", - keywordDescription: "HTML 이나 JSON에서 대소문자를 구분해 키워드를 검색해요.", - pauseDashboardHome: "일시 정지", - deleteMonitorMsg: "정말 이 모니터링을 삭제할까요?", - deleteNotificationMsg: "정말 이 알림을 모든 모니터링에서 삭제할까요?", - resolverserverDescription: "Cloudflare가 기본 서버예요, 원한다면 언제나 다른 Resolver 서버로 변경할 수 있어요.", - rrtypeDescription: "모니터링할 RR-Type을 선택해요.", - pauseMonitorMsg: "정말 이 모니터링을 일시 정지할까요?", - enableDefaultNotificationDescription: "새로 추가하는 모든 모니터링에 이 알림을 기본적으로 활성화해요. 각 모니터에 대해 별도로 알림을 비활성화할 수 있어요.", - clearEventsMsg: "정말 이 모니터링에 대한 모든 이벤트를 삭제할까요?", - clearHeartbeatsMsg: "정말 이 모니터링에 대한 모든 하트비트를 삭제할까요?", - confirmClearStatisticsMsg: "정말 모든 통계를 삭제할까요?", - importHandleDescription: "이름이 같은 모든 모니터링이나 알림을 건너뛰려면 '기존값 건너뛰기'를 선택해주세요. '덮어쓰기'는 기존의 모든 모니터링과 알림을 삭제해요.", - confirmImportMsg: "정말 백업을 가져올까요? 가져오기 옵션을 제대로 설정했는지 다시 확인해주세요.", - twoFAVerifyLabel: "토큰을 입력해 2단계 인증이 작동하는지 확인해주세요.", - tokenValidSettingsMsg: "토큰이 유효해요! 이제 2단계 인증 설정을 저장할 수 있어요.", - confirmEnableTwoFAMsg: "정말 2단계 인증을 활성화할까요?", - confirmDisableTwoFAMsg: "정말 2단계 인증을 비활성화할까요?", - Settings: "설정", - Dashboard: "대시보드", - "New Update": "새로운 업데이트", - Language: "언어", - Appearance: "외형", - Theme: "테마", - General: "일반", - Version: "버전", - "Check Update On GitHub": "깃허브에서 업데이트 확인", - List: "목록", - Add: "추가", - "Add New Monitor": "새로운 모니터링 추가하기", - "Quick Stats": "간단한 정보", - Up: "온라인", - Down: "오프라인", - Pending: "대기 중", - Unknown: "알 수 없음", - Pause: "일시 정지", - Name: "이름", - Status: "상태", - DateTime: "날짜", - Message: "메시지", - "No important events": "중요 이벤트 없음", - Resume: "재개", - Edit: "수정", - Delete: "삭제", - Current: "현재", - Uptime: "업타임", - "Cert Exp.": "인증서 만료", - days: "일", - day: "일", - "-day": "-일", - hour: "시간", - "-hour": "-시간", - Response: "응답", - Ping: "핑", - "Monitor Type": "모니터링 종류", - Keyword: "키워드", - "Friendly Name": "이름", - URL: "URL", - Hostname: "호스트네임", - Port: "포트", - "Heartbeat Interval": "하트비트 주기", - Retries: "재시도", - "Heartbeat Retry Interval": "하트비드 재시도 주기", - Advanced: "고급", - "Upside Down Mode": "상태 반전 모드", - "Max. Redirects": "최대 리다이렉트", - "Accepted Status Codes": "응답 성공 상태 코드", - Save: "저장", - Notifications: "알림", - "Not available, please setup.": "존재하지 않아요, 새로운 거 하나 만드는 건 어때요?", - "Setup Notification": "알림 설정", - Light: "라이트", - Dark: "다크", - Auto: "자동", - "Theme - Heartbeat Bar": "테마 - 하트비트 바", - Normal: "기본값", - Bottom: "가운데", - None: "없애기", - Timezone: "시간대", - "Search Engine Visibility": "검색 엔진 활성화", - "Allow indexing": "인덱싱 허용", - "Discourage search engines from indexing site": "검색 엔진 인덱싱 거부", - "Change Password": "비밀번호 변경", - "Current Password": "기존 비밀번호", - "New Password": "새로운 비밀번호", - "Repeat New Password": "새로운 비밀번호 재입력", - "Update Password": "비밀번호 변경", - "Disable Auth": "인증 비활성화", - "Enable Auth": "인증 활성화", - Logout: "로그아웃", - Leave: "나가기", - "I understand, please disable": "기능에 대해 이해했으니 꺼주세요.", - Confirm: "확인", - Yes: "확인", - No: "취소", - Username: "이름", - Password: "비밀번호", - "Remember me": "비밀번호 기억하기", - Login: "로그인", - "No Monitors, please": "모니터링이 없어요,", - "add one": "하나 추가해봐요", - "Notification Type": "알림 종류", - Email: "이메일", - Test: "테스트", - "Certificate Info": "인증서 정보", - "Resolver Server": "Resolver 서버", - "Resource Record Type": "자원 레코드 유형", - "Last Result": "최근 결과", - "Create your admin account": "관리자 계정 만들기", - "Repeat Password": "비밀번호 재입력", - "Import Backup": "백업 가져오기", - "Export Backup": "백업 내보내기", - Export: "내보내기", - Import: "가져오기", - respTime: "응답 시간 (ms)", - notAvailableShort: "N/A", - "Default enabled": "기본 알림으로 설정", - "Apply on all existing monitors": "기존 모니터링에 모두 적용하기", - Create: "생성하기", - "Clear Data": "데이터 삭제", - Events: "이벤트", - Heartbeats: "하트비트", - "Auto Get": "자동 Get", - backupDescription: "모든 모니터링과 알림을 JSON 파일 형식에 저장할 수 있어요.", - backupDescription2: "히스토리와 이벤트 데이터는 포함되어 있지 않아요.", - backupDescription3: "알림 토큰과 같은 보안 데이터가 내보내기 파일에 포함되어 있으므로 관리에 주의해주세요.", - alertNoFile: "가져오기를 하기 위해 파일을 선택해주세요.", - alertWrongFileType: "JSON 파일을 선택해주세요.", - "Clear all statistics": "모든 통계치 삭제", - "Skip existing": "기존값 건너뛰기", - Overwrite: "덮어쓰기", - Options: "옵션", - "Keep both": "두개 모두 보존", - "Verify Token": "토큰 검증", - "Setup 2FA": "2단계 인증 설정하기", - "Enable 2FA": "2단계 인증 활성화", - "Disable 2FA": "2단계 인증 비활성화", - "2FA Settings": "2단계 인증 설정", - "Two Factor Authentication": "2단계 인증", - Active: "활성화", - Inactive: "비활성화", - Token: "토큰", - "Show URI": "URI 보기", - Tags: "태그", - "Add New below or Select...": "아래 새롭게 추가 또는 선택...", - "Tag with this name already exist.": "같은 태그 이름이 이미 존재해요.", - "Tag with this value already exist.": "같은 값을 가진 태그가 이미 존재해요.", - color: "색상", - "value (optional)": "값 (선택)", - Gray: "회색", - Red: "빨간색", - Orange: "주황색", - Green: "초록색", - Blue: "파란색", - Indigo: "남색", - Purple: "보라색", - Pink: "핑크색", - "Search...": "검색...", - "Avg. Ping": "평균 핑", - "Avg. Response": "평균 응답", - "Entry Page": "첫 페이지", - statusPageNothing: "아무것도 없어요. 새로운 그룹 또는 모니터링을 추가해주세요.", - "No Services": "서비스 없음", - "All Systems Operational": "모든 시스템 정상", - "Partially Degraded Service": "일부 시스템 비정상", - "Degraded Service": "모든 시스템 비정상", - "Add Group": "그룹 추가", - "Add a monitor": "모니터링 추가", - "Edit Status Page": "상태 페이지 수정", - "Go to Dashboard": "대시보드로 가기", - "Status Page": "상태 페이지", - "Status Pages": "상태 페이지", - defaultNotificationName: "내 {notification} 알림 ({number})", - here: "여기", - Required: "필수", - telegram: "Telegram", - "Bot Token": "봇 토큰", - wayToGetTelegramToken: "토큰은 여기서 얻을 수 있어요: {0}.", - "Chat ID": "채팅 ID", - supportTelegramChatID: "개인 채팅 / 그룹 / 채널의 ID를 지원해요.", - wayToGetTelegramChatID: "봇에 메시지를 보내 채팅 ID를 얻고 밑에 URL로 이동해 chat_id를 볼 수 있어요.", - "YOUR BOT TOKEN HERE": "봇 토큰", - chatIDNotFound: "채팅 ID를 찾을 수 없어요. 먼저 봇에게 메시지를 보내주세요.", - webhook: "Webhook", - "Post URL": "Post URL", - "Content Type": "Content Type", - webhookJsonDesc: "{0}은 express.js와 같은 최신 HTTP 서버에 적합해요.", - webhookFormDataDesc: "{multipart}은 PHP에 적합해요. {decodeFunction}를 기준으로 json을 디코딩하면 되어요.", - smtp: "Email (SMTP)", - secureOptionNone: "없음 / STARTTLS (25, 587)", - secureOptionTLS: "TLS (465)", - "Ignore TLS Error": "TLS 에러 무시하기", - "From Email": "보내는 이메일", - "To Email": "받는 이메일", - smtpCC: "참조", - smtpBCC: "숨은 참조", - discord: "Discord", - "Discord Webhook URL": "Discord Webhook URL", - wayToGetDiscordURL: "서버 설정 -> 연동 -> 웹후크 보기 -> 새 웹후크에서 얻을 수 있어요.", - "Bot Display Name": "표시 이름", - "Prefix Custom Message": "접두사 메시지", - "Hello @everyone is...": "{'@'}everyone 서버 상태 알림이에요...", - teams: "Microsoft Teams", - "Webhook URL": "Webhook URL", - wayToGetTeamsURL: "{0}에서 Webhook을 어떻게 만드는지 알아봐요.", - signal: "Signal", - Number: "숫자", - Recipients: "받는 사람", - needSignalAPI: "REST API를 사용하는 Signal 클라이언트가 있어야 해요.", - wayToCheckSignalURL: "밑에 URL을 확인해 URL 설정 방법을 볼 수 있어요.", - signalImportant: "중요: 받는 사람의 그룹과 숫자는 섞을 수 없어요!", - gotify: "Gotify", - "Application Token": "애플리케이션 토큰", - "Server URL": "서버 URL", - Priority: "Priority", - slack: "Slack", - "Icon Emoji": "아이콘 이모지", - "Channel Name": "채널 이름", - "Uptime Kuma URL": "Uptime Kuma URL", - aboutWebhooks: "Webhook에 대한 설명: {0}", - aboutChannelName: "Webhook 채널을 우회하려면 {0} 채널 이름칸에 채널 이름을 입력해주세요. 예: #기타-채널", - aboutKumaURL: "Uptime Kuma URL칸을 공백으로 두면 기본적으로 Project Github 페이지로 설정해요.", - emojiCheatSheet: "이모지 목록 시트: {0}", - "rocket.chat": "Rocket.chat", - pushover: "Pushover", - pushy: "Pushy", - octopush: "Octopush", - promosms: "PromoSMS", - lunasea: "LunaSea", - apprise: "Apprise (50개 이상 알림 서비스)", - pushbullet: "Pushbullet", - line: "Line Messenger", - mattermost: "Mattermost", - "User Key": "사용자 키", - Device: "장치", - "Message Title": "메시지 제목", - "Notification Sound": "알림음", - "More info on:": "자세한 정보: {0}", - pushoverDesc1: "긴급 우선 순위 (2)는 재시도 사이에 기본적으로 30초의 타임아웃이 있고, 1시간 후에 만료되어요.", - pushoverDesc2: "다른 장치에 알림을 보내려면 장치칸을 입력해주세요.", - "SMS Type": "SMS 종류", - octopushTypePremium: "프리미엄 (빠름) - 알림 기능에 적합해요)", - octopushTypeLowCost: "저렴한 요금 (느림) - 가끔 차단될 수 있어요)", - "Check octopush prices": "{0}에서 Octopush 가격을 확인할 수 있어요.", - octopushPhoneNumber: "휴대전화 번호 (intl format, eg : +33612345678) ", - octopushSMSSender: "보내는 사람 이름 : 3-11개의 영숫자 및 여백공간 (a-z, A-Z, 0-9)", - "LunaSea Device ID": "LunaSea 장치 ID", - "Apprise URL": "Apprise URL", - "Example:": "예: {0}", - "Read more:": "더 보기: {0}", - "Status:": "상태: {0}", - "Read more": "더 보기", - appriseInstalled: "Apprise가 설치되어있어요.", - appriseNotInstalled: "Apprise가 설치되어있지 않아요. {0}", - "Access Token": "액세스 토큰", - "Channel access token": "채널 액세스 토큰", - "Line Developers Console": "Line 개발자 콘솔", - lineDevConsoleTo: "Line 개발자 콘솔 - {0}", - "Basic Settings": "기본 설정 메뉴", - "User ID": "사용자 ID", - "Messaging API": "Messaging API 메뉴", - wayToGetLineChannelToken: "먼저 {0}에 액세스하고, 공급자 및 채널 (Messaging API)을 만든 다음, 각 메뉴 밑에 언급된 메뉴에서 채널 액세스 토큰과 사용자 ID를 얻을 수 있어요.", - "Icon URL": "아이콘 URL", - aboutIconURL: "\"아이콘 URL\"에 사진 링크를 입력해 프로필 사진을 설정할 수 있어요. 아이콘 이모지가 설정되어 있으면 적용되지 않을 거예요.", - aboutMattermostChannelName: "채널 이름을 입력하면 Webhook이 게시할 기본 채널을 재설정할 수 있어요. 이 설정은 Mattermost 웹훅 설정에서 활성화해야 해요. 예: #기타-채널", - matrix: "Matrix", - promosmsTypeEco: "SMS ECO - 저렴하지만 느리고 가끔 과부하에 걸려요. 폴란드 수신자만 사용할 수 있어요. ", - promosmsTypeFlash: "SMS FLASH - 메시지가 받는 사람 장치에 자동으로 표시되어요. 폴란드 수신자만 사용할 수 있어요.", - promosmsTypeFull: "SMS FULL - SMS 프리미엄 티어, 보내는 사람 이름을 먼저 등록해야 해요. 알림 기능에 적합해요.", - promosmsTypeSpeed: "SMS SPEED - 시스템에서 가장 높은 우선순위예요. 매우 빠르고 신뢰할 수 있지만 비용이 많이 들어요 (SMS 전체 가격의 약 두 배).", - promosmsPhoneNumber: "전화 번호 (폴란드 수신자라면 지역번호를 적지 않아도 되어요.)", - promosmsSMSSender: "SMS 보내는 사람 이름 : 미리 등록된 이름 혹은 기본값 중 하나예요: InfoSMS, SMS Info, MaxSMS, INFO, SMS", - "Primary Base URL": "기본 URL", - "Push URL": "Push URL", - needPushEvery: "이 URL을 {0} 초 마다 호출할 수 있어요.", - pushOptionalParams: "선택적 파라미터: {0}", - emailCustomSubject: "커스텀 주제", - clicksendsms: "ClickSend SMS", - checkPrice: "{0} 가격 확인:", - apiCredentials: "API 인증정보", - octopushLegacyHint: "Octopush 레거시 버전 (2011-2020) 을 사용하시나요? 아니면 새 버전을 사용하시나요?", - "Feishu WebHookUrl": "Feishu WebHookURL", - matrixHomeserverURL: "Homeserver URL (http(s):// 와 함께 적어주세요. 그리고 포트 번호는 선택적 입니다.)", - "Internal Room Id": "내부 방 ID", - matrixDesc1: "Matrix 클라이언트 방 설정의 고급 섹션에서 내부 방 ID를 찾을 수 있어요. 내부 방 ID는 이렇게 생겼답니다: !QMdRCpUIfLwsfjxye6:home.server.", - matrixDesc2: "사용자의 모든 방에 대한 엑세스가 허용될 수 있어서 새로운 사용자를 만들고 원하는 방에만 초대한 후 엑세스 토큰을 사용하는 것이 좋아요. {0} 이 명령어를 통해 엑세스 토큰을 얻을 수 있어요.", - Method: "Method", - Body: "Body", - Headers: "Headers", - PushUrl: "Push URL", - HeadersInvalidFormat: "요청 Headers의 JSON 형식이 올바르지 않아요: ", - BodyInvalidFormat: "요청 Body의 JSON 형식이 올바르지 않아요: ", - "Monitor History": "모니터링 기록", - clearDataOlderThan: "모니터링 기록을 {0}일 동안 저장해요.", - PasswordsDoNotMatch: "비밀번호가 일치하지 않아요.", - records: "records", - "One record": "One record", - steamApiKeyDescription: "스팀 게임 서버를 모니터링하려면 Steam Web API 키가 필요해요. API 키는 하단 웹사이트에서 등록할 수 있어요: ", - "Current User": "현재 사용자", - recent: "최근", - Done: "완료", - Info: "정보", - Security: "보안", - "Steam API Key": "스팀 API 키", - "Shrink Database": "데이터베이스 축소", - "Pick a RR-Type...": "RR-Type을 골라주세요...", - "Pick Accepted Status Codes...": "상태 코드를 골라주세요...", - Default: "기본", - "HTTP Options": "HTTP 옵션", - "Create Incident": "인시던트 만들기", - Title: "제목", - Content: "내용", - Style: "스타일", - info: "정보", - warning: "경고", - danger: "위험", - primary: "기본", - light: "라이트", - dark: "다크", - Post: "올리기", - "Please input title and content": "제목과 내용을 작성해주세요.", - Created: "생성 날짜", - "Last Updated": "마지막 업데이트", - Unpin: "제거", - "Switch to Light Theme": "라이트 테마로 전환", - "Switch to Dark Theme": "다크 테마로 전환", - "Show Tags": "태그 보이기", - "Hide Tags": "태그 숨기기", - Description: "설명", - "No monitors available.": "모니터링이 없어요.", - "Add one": "추가하기", - "No Monitors": "모니터링 없음", - "Untitled Group": "이름없는 그룹", - Services: "서비스", - Discard: "취소", - Cancel: "취소", - "Powered by": "Powered by", - shrinkDatabaseDescription: "SQLite 데이터베이스 VACUUM을 트리거해요. 만약 데이터베이스가 1.10.0 버전 이후에 생성되었다면 AUTO_VACUUM이 설정되어 있어 이 작업은 필요 없을 거에요.", - serwersms: "SerwerSMS.pl", - serwersmsAPIUser: "API Usename (webapi_ 접두사 포함)", - serwersmsAPIPassword: "API 비밀번호", - serwersmsPhoneNumber: "휴대전화 번호", - serwersmsSenderName: "보내는 사람 이름 (customer portal를 통해 가입된 정보)", - stackfield: "Stackfield", - dnsPortDescription: "DNS 서버 포트, 기본값은 53 이에요. 포트는 언제나 변경할 수 있어요.", - PushByTechulus: "Push by Techulus", - GoogleChat: "Google Chat (Google Workspace only)", - topic: "Topic", - topicExplanation: "모니터링할 MQTT Topic", - successMessage: "성공 메시지", - successMessageExplanation: "성공으로 간주되는 MQTT 메시지", - error: "error", - critical: "critical", - Customize: "커스터마이즈", - "Custom Footer": "커스텀 Footer", - "Custom CSS": "커스텀 CSS", - smtpDkimSettings: "DKIM 설정", - smtpDkimDesc: "사용 방법은 DKIM {0}를 참조하세요.", - documentation: "문서", - smtpDkimDomain: "도메인 이름", - smtpDkimKeySelector: "Key Selector", - smtpDkimPrivateKey: "Private Key", - smtpDkimHashAlgo: "해시 알고리즘 (선택)", - smtpDkimheaderFieldNames: "서명할 헤더 키 (선택)", - smtpDkimskipFields: "서명하지 않을 헤더 키 (선택)", - wayToGetPagerDutyKey: "Service -> Service Directory -> (서비스 선택) -> Integrations -> Add integration. 에서 찾을 수 있어요. 자세히 알아보려면 {0}에서 \"Events API V2\"를 검색해봐요.", - "Integration Key": "Integration 키", - "Integration URL": "Integration URL", - "Auto resolve or acknowledged": "자동 해결 혹은 승인", - "do nothing": "아무것도 하지 않기", - "auto acknowledged": "자동 승인 (acknowledged)", - "auto resolve": "자동 해결 (resolve)", - gorush: "Gorush", - alerta: "Alerta", - alertaApiEndpoint: "API Endpoint", - alertaEnvironment: "환경변수", - alertaApiKey: "API 키", - alertaAlertState: "경고 상태", - alertaRecoverState: "해결된 상태", - deleteStatusPageMsg: "정말 이 상태 페이지를 삭제할까요?", - Proxies: "프록시", - default: "Default", - enabled: "활성화", - setAsDefault: "기본 프록시로 설정", - deleteProxyMsg: "정말 이 프록시를 모든 모니터링에서 삭제할까요?", - proxyDescription: "프록시가 작동하려면 모니터에 할당되어야 해요.", - enableProxyDescription: "이 프록시는 활성화될 때까지 영향을 미치지 않아요. 활성화 상태에 따라 모든 모니터에서 프록시를 일시정지할 수 있어요.", - setAsDefaultProxyDescription: "새로 추가하는 모든 모니터링에 이 프록시를 기본적으로 활성화해요. 각 모니터에 대해 별도로 프록시를 비활성화할 수 있어요.", - "Certificate Chain": "인증서 체인", - Valid: "유효", - Invalid: "유효하지 않음", - AccessKeyId: "AccessKey ID", - SecretAccessKey: "AccessKey Secret", - PhoneNumbers: "휴대전화 번호", - TemplateCode: "템플릿 코드", - SignName: "SignName", - "Sms template must contain parameters: ": "Sms 템플릿은 다음과 같은 파라미터가 포함되어야 해요:", - "Bark Endpoint": "Bark Endpoint", - WebHookUrl: "웹훅 URL", - SecretKey: "Secret Key", - "For safety, must use secret key": "안전을 위해 꼭 Secret Key를 사용하세요.", - "Device Token": "기기 Token", - Platform: "플랫폼", - iOS: "iOS", - Android: "Android", - Huawei: "Huawei", - High: "High", - Retry: "재시도", - Topic: "Topic", - "WeCom Bot Key": "WeCom Bot Key", - "Setup Proxy": "프록시 설정", - "Proxy Protocol": "프록시 프로토콜", - "Proxy Server": "프록시 서버", - "Proxy server has authentication": "프록시 서버에 인증 절차가 있음", - User: "사용자", - Installed: "설치됨", - "Not installed": "설치되어 있지 않음", - Running: "작동 중", - "Not running": "작동하고 있지 않음", - "Remove Token": "토큰 삭제", - Start: "시작", - Stop: "정지", - "Uptime Kuma": "Uptime Kuma", - "Add New Status Page": "새로운 상태 페이지 만들기", - Slug: "주소", - "Accept characters:": "허용되는 문자열:", - startOrEndWithOnly: "{0}로 시작하거나 끝나야 해요.", - "No consecutive dashes": "연속되는 대시는 허용되지 않아요", - Next: "다음", - "The slug is already taken. Please choose another slug.": "이미 존재하는 주소에요. 다른 주소를 사용해 주세요.", - "No Proxy": "프록시 없음", - "HTTP Basic Auth": "HTTP 인증", - "New Status Page": "새로운 상태 페이지", - "Page Not Found": "페이지를 찾을 수 없어요", - "Reverse Proxy": "리버스 프록시", - Backup: "백업", - About: "정보", - wayToGetCloudflaredURL: "({0}에서 Cloudflare 다운로드 하기)", - cloudflareWebsite: "Cloudflare 웹사이트", - "Message:": "메시지:", - "Don't know how to get the token? Please read the guide:": "토큰을 얻는 방법은 이 가이드를 확인해주세요:", - "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.": "Cloudflare Tunnel를 연결하면 현재 연결이 끊길 수 있어요. 정말 중지할까요? 비밀번호를 입력해 확인하세요.", - "Other Software": "다른 소프트웨어", - "For example: nginx, Apache and Traefik.": "nginx, Apache, Traefik 등을 사용할 수 있어요.", - "Please read": "이 문서를 참조하세요:", - "Subject:": "Subject:", - "Valid To:": "Valid To:", - "Days Remaining:": "남은 일수:", - "Issuer:": "Issuer:", - "Fingerprint:": "Fingerprint:", - "No status pages": "상태 페이지 없음", - "Domain Name Expiry Notification": "도메인 이름 만료 알림", - Proxy: "프록시", - "Date Created": "생성된 날짜", - onebotHttpAddress: "OneBot HTTP 주소", - onebotMessageType: "OneBot 메시지 종류", - onebotGroupMessage: "그룹 메시지", - onebotPrivateMessage: "개인 메시지", - onebotUserOrGroupId: "그룹/사용자 ID", - onebotSafetyTips: "안전을 위해 Access 토큰을 설정하세요.", - "PushDeer Key": "PushDeer 키", - "Footer Text": "Footer 문구", - "Show Powered By": "Powered By 문구 표시하기", - "Domain Names": "도메인 이름", - signedInDisp: "{0} 로그인됨", - signedInDispDisabled: "인증 비활성화됨.", - "Certificate Expiry Notification": "인증서 만료 알림", - "API Username": "API 사용자 이름", - "API Key": "API 키", - "Recipient Number": "받는 사람 번호", - "From Name/Number": "발신자 이름/번호", - "Leave blank to use a shared sender number.": "공유 발신자 번호를 사용하려면 공백으로 두세요.", - "Octopush API Version": "Octopush API 버전", - "Legacy Octopush-DM": "레거시 Octopush-DM", - endpoint: "endpoint", - octopushAPIKey: "제어판 HTTP API credentials 에서 \"API key\"", - octopushLogin: "제어판 HTTP API credentials 에서 \"Login\"", - promosmsLogin: "API 로그인 이름", - promosmsPassword: "API 비밀번호", - "pushoversounds pushover": "Pushover (기본)", - "pushoversounds bike": "Bike", - "pushoversounds bugle": "Bugle", - "pushoversounds cashregister": "Cash Register", - "pushoversounds classical": "Classical", - "pushoversounds cosmic": "Cosmic", - "pushoversounds falling": "Falling", - "pushoversounds gamelan": "Gamelan", - "pushoversounds incoming": "Incoming", - "pushoversounds intermission": "Intermission", - "pushoversounds magic": "Magic", - "pushoversounds mechanical": "Mechanical", - "pushoversounds pianobar": "Piano Bar", - "pushoversounds siren": "Siren", - "pushoversounds spacealarm": "Space Alarm", - "pushoversounds tugboat": "Tug Boat", - "pushoversounds alien": "Alien Alarm (long)", - "pushoversounds climb": "Climb (long)", - "pushoversounds persistent": "Persistent (long)", - "pushoversounds echo": "Pushover Echo (long)", - "pushoversounds updown": "Up Down (long)", - "pushoversounds vibrate": "진동만", - "pushoversounds none": "없음 (무음)", - pushyAPIKey: "비밀 API 키", - pushyToken: "기기 토큰", - "Show update if available": "사용 가능한 경우에 업데이트 표시", - "Also check beta release": "베타 릴리즈 확인", - "Using a Reverse Proxy?": "리버스 프록시를 사용하시나요?", - "Check how to config it for WebSocket": "웹소켓에 대한 설정 방법 확인", - "Steam Game Server": "스팀 게임 서버", - "Most likely causes:": "원인:", - "The resource is no longer available.": "더이상 사용할 수 없어요.", - "There might be a typing error in the address.": "주소에 오탈자가 있을 수 있어요.", - "What you can try:": "해결 방법:", - "Retype the address.": "주소 다시 입력하기", - "Go back to the previous page.": "이전 페이지로 돌아가기", - "Coming Soon": "Coming Soon", - wayToGetClickSendSMSToken: "{0}에서 API 사용자 이름과 키를 얻을 수 있어요.", + languageName: "한국어", + checkEverySecond: "{0}초마다 확인해요.", + retryCheckEverySecond: "{0}초마다 다시 확인해요.", + retriesDescription: "서비스가 중단된 후 알림을 보내기 전 최대 재시도 횟수", + ignoreTLSError: "HTTPS 웹사이트에서 TLS/SSL 에러 무시하기", + upsideDownModeDescription: "서버 상태를 반대로 표시해요. 서버가 작동하면 오프라인으로 표시할 거예요.", + maxRedirectDescription: "최대 리다이렉트 횟수예요. 0을 입력하면 리다이렉트를 꺼요.", + acceptedStatusCodesDescription: "응답 성공으로 간주할 상태 코드를 정해요.", + passwordNotMatchMsg: "비밀번호 재입력이 일치하지 않아요.", + notificationDescription: "모니터링에 알림을 설정할 수 있어요.", + keywordDescription: "HTML 이나 JSON에서 대소문자를 구분해 키워드를 검색해요.", + pauseDashboardHome: "일시 정지", + deleteMonitorMsg: "정말 이 모니터링을 삭제할까요?", + deleteNotificationMsg: "정말 이 알림을 모든 모니터링에서 삭제할까요?", + resolverserverDescription: "Cloudflare가 기본 서버예요, 원한다면 언제나 다른 Resolver 서버로 변경할 수 있어요.", + rrtypeDescription: "모니터링할 RR-Type을 선택해요.", + pauseMonitorMsg: "정말 이 모니터링을 일시 정지할까요?", + enableDefaultNotificationDescription: "새로 추가하는 모든 모니터링에 이 알림을 기본적으로 활성화해요. 각 모니터에 대해 별도로 알림을 비활성화할 수 있어요.", + clearEventsMsg: "정말 이 모니터링에 대한 모든 이벤트를 삭제할까요?", + clearHeartbeatsMsg: "정말 이 모니터링에 대한 모든 하트비트를 삭제할까요?", + confirmClearStatisticsMsg: "정말 모든 통계를 삭제할까요?", + importHandleDescription: "이름이 같은 모든 모니터링이나 알림을 건너뛰려면 '기존값 건너뛰기'를 선택해주세요. '덮어쓰기'는 기존의 모든 모니터링과 알림을 삭제해요.", + confirmImportMsg: "정말 백업을 가져올까요? 가져오기 옵션을 제대로 설정했는지 다시 확인해주세요.", + twoFAVerifyLabel: "토큰을 입력해 2단계 인증이 작동하는지 확인해주세요.", + tokenValidSettingsMsg: "토큰이 유효해요! 이제 2단계 인증 설정을 저장할 수 있어요.", + confirmEnableTwoFAMsg: "정말 2단계 인증을 활성화할까요?", + confirmDisableTwoFAMsg: "정말 2단계 인증을 비활성화할까요?", + Settings: "설정", + Dashboard: "대시보드", + "New Update": "새로운 업데이트", + Language: "언어", + Appearance: "외형", + Theme: "테마", + General: "일반", + Version: "버전", + "Check Update On GitHub": "깃허브에서 업데이트 확인", + List: "목록", + Add: "추가", + "Add New Monitor": "새로운 모니터링 추가하기", + "Quick Stats": "간단한 정보", + Up: "온라인", + Down: "오프라인", + Pending: "대기 중", + Unknown: "알 수 없음", + Pause: "일시 정지", + Name: "이름", + Status: "상태", + DateTime: "날짜", + Message: "메시지", + "No important events": "중요 이벤트 없음", + Resume: "재개", + Edit: "수정", + Delete: "삭제", + Current: "현재", + Uptime: "업타임", + "Cert Exp.": "인증서 만료", + days: "일", + day: "일", + "-day": "-일", + hour: "시간", + "-hour": "-시간", + Response: "응답", + Ping: "핑", + "Monitor Type": "모니터링 종류", + Keyword: "키워드", + "Friendly Name": "이름", + URL: "URL", + Hostname: "호스트네임", + Port: "포트", + "Heartbeat Interval": "하트비트 주기", + Retries: "재시도", + "Heartbeat Retry Interval": "하트비드 재시도 주기", + Advanced: "고급", + "Upside Down Mode": "상태 반전 모드", + "Max. Redirects": "최대 리다이렉트", + "Accepted Status Codes": "응답 성공 상태 코드", + Save: "저장", + Notifications: "알림", + "Not available, please setup.": "존재하지 않아요, 새로운 거 하나 만드는 건 어때요?", + "Setup Notification": "알림 설정", + Light: "라이트", + Dark: "다크", + Auto: "자동", + "Theme - Heartbeat Bar": "테마 - 하트비트 바", + Normal: "기본값", + Bottom: "가운데", + None: "없애기", + Timezone: "시간대", + "Search Engine Visibility": "검색 엔진 활성화", + "Allow indexing": "인덱싱 허용", + "Discourage search engines from indexing site": "검색 엔진 인덱싱 거부", + "Change Password": "비밀번호 변경", + "Current Password": "기존 비밀번호", + "New Password": "새로운 비밀번호", + "Repeat New Password": "새로운 비밀번호 재입력", + "Update Password": "비밀번호 변경", + "Disable Auth": "인증 비활성화", + "Enable Auth": "인증 활성화", + Logout: "로그아웃", + Leave: "나가기", + "I understand, please disable": "기능에 대해 이해했으니 꺼주세요.", + Confirm: "확인", + Yes: "확인", + No: "취소", + Username: "이름", + Password: "비밀번호", + "Remember me": "비밀번호 기억하기", + Login: "로그인", + "No Monitors, please": "모니터링이 없어요,", + "add one": "하나 추가해봐요", + "Notification Type": "알림 종류", + Email: "이메일", + Test: "테스트", + "Certificate Info": "인증서 정보", + "Resolver Server": "Resolver 서버", + "Resource Record Type": "자원 레코드 유형", + "Last Result": "최근 결과", + "Create your admin account": "관리자 계정 만들기", + "Repeat Password": "비밀번호 재입력", + "Import Backup": "백업 가져오기", + "Export Backup": "백업 내보내기", + Export: "내보내기", + Import: "가져오기", + respTime: "응답 시간 (ms)", + notAvailableShort: "N/A", + "Default enabled": "기본 알림으로 설정", + "Apply on all existing monitors": "기존 모니터링에 모두 적용하기", + Create: "생성하기", + "Clear Data": "데이터 삭제", + Events: "이벤트", + Heartbeats: "하트비트", + "Auto Get": "자동 Get", + backupDescription: "모든 모니터링과 알림을 JSON 파일 형식에 저장할 수 있어요.", + backupDescription2: "히스토리와 이벤트 데이터는 포함되어 있지 않아요.", + backupDescription3: "알림 토큰과 같은 보안 데이터가 내보내기 파일에 포함되어 있으므로 관리에 주의해주세요.", + alertNoFile: "가져오기를 하기 위해 파일을 선택해주세요.", + alertWrongFileType: "JSON 파일을 선택해주세요.", + "Clear all statistics": "모든 통계치 삭제", + "Skip existing": "기존값 건너뛰기", + Overwrite: "덮어쓰기", + Options: "옵션", + "Keep both": "두개 모두 보존", + "Verify Token": "토큰 검증", + "Setup 2FA": "2단계 인증 설정하기", + "Enable 2FA": "2단계 인증 활성화", + "Disable 2FA": "2단계 인증 비활성화", + "2FA Settings": "2단계 인증 설정", + "Two Factor Authentication": "2단계 인증", + Active: "활성화", + Inactive: "비활성화", + Token: "토큰", + "Show URI": "URI 보기", + Tags: "태그", + "Add New below or Select...": "아래 새롭게 추가 또는 선택...", + "Tag with this name already exist.": "같은 태그 이름이 이미 존재해요.", + "Tag with this value already exist.": "같은 값을 가진 태그가 이미 존재해요.", + color: "색상", + "value (optional)": "값 (선택)", + Gray: "회색", + Red: "빨간색", + Orange: "주황색", + Green: "초록색", + Blue: "파란색", + Indigo: "남색", + Purple: "보라색", + Pink: "핑크색", + "Search...": "검색...", + "Avg. Ping": "평균 핑", + "Avg. Response": "평균 응답", + "Entry Page": "첫 페이지", + statusPageNothing: "아무것도 없어요. 새로운 그룹 또는 모니터링을 추가해주세요.", + "No Services": "서비스 없음", + "All Systems Operational": "모든 시스템 정상", + "Partially Degraded Service": "일부 시스템 비정상", + "Degraded Service": "모든 시스템 비정상", + "Add Group": "그룹 추가", + "Add a monitor": "모니터링 추가", + "Edit Status Page": "상태 페이지 수정", + "Go to Dashboard": "대시보드로 가기", + "Status Page": "상태 페이지", + "Status Pages": "상태 페이지", + defaultNotificationName: "내 {notification} 알림 ({number})", + here: "여기", + Required: "필수", + telegram: "Telegram", + "Bot Token": "봇 토큰", + wayToGetTelegramToken: "토큰은 여기서 얻을 수 있어요: {0}.", + "Chat ID": "채팅 ID", + supportTelegramChatID: "개인 채팅 / 그룹 / 채널의 ID를 지원해요.", + wayToGetTelegramChatID: "봇에 메시지를 보내 채팅 ID를 얻고 밑에 URL로 이동해 chat_id를 볼 수 있어요.", + "YOUR BOT TOKEN HERE": "봇 토큰", + chatIDNotFound: "채팅 ID를 찾을 수 없어요. 먼저 봇에게 메시지를 보내주세요.", + webhook: "Webhook", + "Post URL": "Post URL", + "Content Type": "Content Type", + webhookJsonDesc: "{0}은 express.js와 같은 최신 HTTP 서버에 적합해요.", + webhookFormDataDesc: "{multipart}은 PHP에 적합해요. {decodeFunction}를 기준으로 json을 디코딩하면 되어요.", + smtp: "Email (SMTP)", + secureOptionNone: "없음 / STARTTLS (25, 587)", + secureOptionTLS: "TLS (465)", + "Ignore TLS Error": "TLS 에러 무시하기", + "From Email": "보내는 이메일", + "To Email": "받는 이메일", + smtpCC: "참조", + smtpBCC: "숨은 참조", + discord: "Discord", + "Discord Webhook URL": "Discord Webhook URL", + wayToGetDiscordURL: "서버 설정 -> 연동 -> 웹후크 보기 -> 새 웹후크에서 얻을 수 있어요.", + "Bot Display Name": "표시 이름", + "Prefix Custom Message": "접두사 메시지", + "Hello @everyone is...": "{'@'}everyone 서버 상태 알림이에요...", + teams: "Microsoft Teams", + "Webhook URL": "Webhook URL", + wayToGetTeamsURL: "{0}에서 Webhook을 어떻게 만드는지 알아봐요.", + signal: "Signal", + Number: "숫자", + Recipients: "받는 사람", + needSignalAPI: "REST API를 사용하는 Signal 클라이언트가 있어야 해요.", + wayToCheckSignalURL: "밑에 URL을 확인해 URL 설정 방법을 볼 수 있어요.", + signalImportant: "중요: 받는 사람의 그룹과 숫자는 섞을 수 없어요!", + gotify: "Gotify", + "Application Token": "애플리케이션 토큰", + "Server URL": "서버 URL", + Priority: "Priority", + slack: "Slack", + "Icon Emoji": "아이콘 이모지", + "Channel Name": "채널 이름", + "Uptime Kuma URL": "Uptime Kuma URL", + aboutWebhooks: "Webhook에 대한 설명: {0}", + aboutChannelName: "Webhook 채널을 우회하려면 {0} 채널 이름칸에 채널 이름을 입력해주세요. 예: #기타-채널", + aboutKumaURL: "Uptime Kuma URL칸을 공백으로 두면 기본적으로 Project Github 페이지로 설정해요.", + emojiCheatSheet: "이모지 목록 시트: {0}", + "rocket.chat": "Rocket.chat", + pushover: "Pushover", + pushy: "Pushy", + octopush: "Octopush", + promosms: "PromoSMS", + lunasea: "LunaSea", + apprise: "Apprise (50개 이상 알림 서비스)", + pushbullet: "Pushbullet", + line: "Line Messenger", + mattermost: "Mattermost", + "User Key": "사용자 키", + Device: "장치", + "Message Title": "메시지 제목", + "Notification Sound": "알림음", + "More info on:": "자세한 정보: {0}", + pushoverDesc1: "긴급 우선 순위 (2)는 재시도 사이에 기본적으로 30초의 타임아웃이 있고, 1시간 후에 만료되어요.", + pushoverDesc2: "다른 장치에 알림을 보내려면 장치칸을 입력해주세요.", + "SMS Type": "SMS 종류", + octopushTypePremium: "프리미엄 (빠름) - 알림 기능에 적합해요)", + octopushTypeLowCost: "저렴한 요금 (느림) - 가끔 차단될 수 있어요)", + "Check octopush prices": "{0}에서 Octopush 가격을 확인할 수 있어요.", + octopushPhoneNumber: "휴대전화 번호 (intl format, eg : +33612345678) ", + octopushSMSSender: "보내는 사람 이름 : 3-11개의 영숫자 및 여백공간 (a-z, A-Z, 0-9)", + "LunaSea Device ID": "LunaSea 장치 ID", + "Apprise URL": "Apprise URL", + "Example:": "예: {0}", + "Read more:": "더 보기: {0}", + "Status:": "상태: {0}", + "Read more": "더 보기", + appriseInstalled: "Apprise가 설치되어있어요.", + appriseNotInstalled: "Apprise가 설치되어있지 않아요. {0}", + "Access Token": "액세스 토큰", + "Channel access token": "채널 액세스 토큰", + "Line Developers Console": "Line 개발자 콘솔", + lineDevConsoleTo: "Line 개발자 콘솔 - {0}", + "Basic Settings": "기본 설정 메뉴", + "User ID": "사용자 ID", + "Messaging API": "Messaging API 메뉴", + wayToGetLineChannelToken: "먼저 {0}에 액세스하고, 공급자 및 채널 (Messaging API)을 만든 다음, 각 메뉴 밑에 언급된 메뉴에서 채널 액세스 토큰과 사용자 ID를 얻을 수 있어요.", + "Icon URL": "아이콘 URL", + aboutIconURL: "\"아이콘 URL\"에 사진 링크를 입력해 프로필 사진을 설정할 수 있어요. 아이콘 이모지가 설정되어 있으면 적용되지 않을 거예요.", + aboutMattermostChannelName: "채널 이름을 입력하면 Webhook이 게시할 기본 채널을 재설정할 수 있어요. 이 설정은 Mattermost 웹훅 설정에서 활성화해야 해요. 예: #기타-채널", + matrix: "Matrix", + promosmsTypeEco: "SMS ECO - 저렴하지만 느리고 가끔 과부하에 걸려요. 폴란드 수신자만 사용할 수 있어요. ", + promosmsTypeFlash: "SMS FLASH - 메시지가 받는 사람 장치에 자동으로 표시되어요. 폴란드 수신자만 사용할 수 있어요.", + promosmsTypeFull: "SMS FULL - SMS 프리미엄 티어, 보내는 사람 이름을 먼저 등록해야 해요. 알림 기능에 적합해요.", + promosmsTypeSpeed: "SMS SPEED - 시스템에서 가장 높은 우선순위예요. 매우 빠르고 신뢰할 수 있지만 비용이 많이 들어요 (SMS 전체 가격의 약 두 배).", + promosmsPhoneNumber: "전화 번호 (폴란드 수신자라면 지역번호를 적지 않아도 되어요.)", + promosmsSMSSender: "SMS 보내는 사람 이름 : 미리 등록된 이름 혹은 기본값 중 하나예요: InfoSMS, SMS Info, MaxSMS, INFO, SMS", + "Primary Base URL": "기본 URL", + "Push URL": "Push URL", + needPushEvery: "이 URL을 {0} 초 마다 호출할 수 있어요.", + pushOptionalParams: "선택적 파라미터: {0}", + emailCustomSubject: "커스텀 주제", + clicksendsms: "ClickSend SMS", + checkPrice: "{0} 가격 확인:", + apiCredentials: "API 인증정보", + octopushLegacyHint: "Octopush 레거시 버전 (2011-2020) 을 사용하시나요? 아니면 새 버전을 사용하시나요?", + "Feishu WebHookUrl": "Feishu WebHookURL", + matrixHomeserverURL: "Homeserver URL (http(s):// 와 함께 적어주세요. 그리고 포트 번호는 선택적 입니다.)", + "Internal Room Id": "내부 방 ID", + matrixDesc1: "Matrix 클라이언트 방 설정의 고급 섹션에서 내부 방 ID를 찾을 수 있어요. 내부 방 ID는 이렇게 생겼답니다: !QMdRCpUIfLwsfjxye6:home.server.", + matrixDesc2: "사용자의 모든 방에 대한 엑세스가 허용될 수 있어서 새로운 사용자를 만들고 원하는 방에만 초대한 후 엑세스 토큰을 사용하는 것이 좋아요. {0} 이 명령어를 통해 엑세스 토큰을 얻을 수 있어요.", + Method: "Method", + Body: "Body", + Headers: "Headers", + PushUrl: "Push URL", + HeadersInvalidFormat: "요청 Headers의 JSON 형식이 올바르지 않아요: ", + BodyInvalidFormat: "요청 Body의 JSON 형식이 올바르지 않아요: ", + "Monitor History": "모니터링 기록", + clearDataOlderThan: "모니터링 기록을 {0}일 동안 저장해요.", + PasswordsDoNotMatch: "비밀번호가 일치하지 않아요.", + records: "records", + "One record": "One record", + steamApiKeyDescription: "스팀 게임 서버를 모니터링하려면 Steam Web API 키가 필요해요. API 키는 하단 웹사이트에서 등록할 수 있어요: ", + "Current User": "현재 사용자", + recent: "최근", + Done: "완료", + Info: "정보", + Security: "보안", + "Steam API Key": "스팀 API 키", + "Shrink Database": "데이터베이스 축소", + "Pick a RR-Type...": "RR-Type을 골라주세요...", + "Pick Accepted Status Codes...": "상태 코드를 골라주세요...", + Default: "기본", + "HTTP Options": "HTTP 옵션", + "Create Incident": "인시던트 만들기", + Title: "제목", + Content: "내용", + Style: "스타일", + info: "정보", + warning: "경고", + danger: "위험", + primary: "기본", + light: "라이트", + dark: "다크", + Post: "올리기", + "Please input title and content": "제목과 내용을 작성해주세요.", + Created: "생성 날짜", + "Last Updated": "마지막 업데이트", + Unpin: "제거", + "Switch to Light Theme": "라이트 테마로 전환", + "Switch to Dark Theme": "다크 테마로 전환", + "Show Tags": "태그 보이기", + "Hide Tags": "태그 숨기기", + Description: "설명", + "No monitors available.": "모니터링이 없어요.", + "Add one": "추가하기", + "No Monitors": "모니터링 없음", + "Untitled Group": "이름없는 그룹", + Services: "서비스", + Discard: "취소", + Cancel: "취소", + "Powered by": "Powered by", + shrinkDatabaseDescription: "SQLite 데이터베이스 VACUUM을 트리거해요. 만약 데이터베이스가 1.10.0 버전 이후에 생성되었다면 AUTO_VACUUM이 설정되어 있어 이 작업은 필요 없을 거에요.", + serwersms: "SerwerSMS.pl", + serwersmsAPIUser: "API Usename (webapi_ 접두사 포함)", + serwersmsAPIPassword: "API 비밀번호", + serwersmsPhoneNumber: "휴대전화 번호", + serwersmsSenderName: "보내는 사람 이름 (customer portal를 통해 가입된 정보)", + stackfield: "Stackfield", + dnsPortDescription: "DNS 서버 포트, 기본값은 53 이에요. 포트는 언제나 변경할 수 있어요.", + PushByTechulus: "Push by Techulus", + GoogleChat: "Google Chat (Google Workspace only)", + topic: "Topic", + topicExplanation: "모니터링할 MQTT Topic", + successMessage: "성공 메시지", + successMessageExplanation: "성공으로 간주되는 MQTT 메시지", + error: "error", + critical: "critical", + Customize: "커스터마이즈", + "Custom Footer": "커스텀 Footer", + "Custom CSS": "커스텀 CSS", + smtpDkimSettings: "DKIM 설정", + smtpDkimDesc: "사용 방법은 DKIM {0}를 참조하세요.", + documentation: "문서", + smtpDkimDomain: "도메인 이름", + smtpDkimKeySelector: "Key Selector", + smtpDkimPrivateKey: "Private Key", + smtpDkimHashAlgo: "해시 알고리즘 (선택)", + smtpDkimheaderFieldNames: "서명할 헤더 키 (선택)", + smtpDkimskipFields: "서명하지 않을 헤더 키 (선택)", + wayToGetPagerDutyKey: "Service -> Service Directory -> (서비스 선택) -> Integrations -> Add integration. 에서 찾을 수 있어요. 자세히 알아보려면 {0}에서 \"Events API V2\"를 검색해봐요.", + "Integration Key": "Integration 키", + "Integration URL": "Integration URL", + "Auto resolve or acknowledged": "자동 해결 혹은 승인", + "do nothing": "아무것도 하지 않기", + "auto acknowledged": "자동 승인 (acknowledged)", + "auto resolve": "자동 해결 (resolve)", + gorush: "Gorush", + alerta: "Alerta", + alertaApiEndpoint: "API Endpoint", + alertaEnvironment: "환경변수", + alertaApiKey: "API 키", + alertaAlertState: "경고 상태", + alertaRecoverState: "해결된 상태", + deleteStatusPageMsg: "정말 이 상태 페이지를 삭제할까요?", + Proxies: "프록시", + default: "Default", + enabled: "활성화", + setAsDefault: "기본 프록시로 설정", + deleteProxyMsg: "정말 이 프록시를 모든 모니터링에서 삭제할까요?", + proxyDescription: "프록시가 작동하려면 모니터에 할당되어야 해요.", + enableProxyDescription: "이 프록시는 활성화될 때까지 영향을 미치지 않아요. 활성화 상태에 따라 모든 모니터에서 프록시를 일시정지할 수 있어요.", + setAsDefaultProxyDescription: "새로 추가하는 모든 모니터링에 이 프록시를 기본적으로 활성화해요. 각 모니터에 대해 별도로 프록시를 비활성화할 수 있어요.", + "Certificate Chain": "인증서 체인", + Valid: "유효", + Invalid: "유효하지 않음", + AccessKeyId: "AccessKey ID", + SecretAccessKey: "AccessKey Secret", + PhoneNumbers: "휴대전화 번호", + TemplateCode: "템플릿 코드", + SignName: "SignName", + "Sms template must contain parameters: ": "Sms 템플릿은 다음과 같은 파라미터가 포함되어야 해요:", + "Bark Endpoint": "Bark Endpoint", + WebHookUrl: "웹훅 URL", + SecretKey: "Secret Key", + "For safety, must use secret key": "안전을 위해 꼭 Secret Key를 사용하세요.", + "Device Token": "기기 Token", + Platform: "플랫폼", + iOS: "iOS", + Android: "Android", + Huawei: "Huawei", + High: "High", + Retry: "재시도", + Topic: "Topic", + "WeCom Bot Key": "WeCom Bot Key", + "Setup Proxy": "프록시 설정", + "Proxy Protocol": "프록시 프로토콜", + "Proxy Server": "프록시 서버", + "Proxy server has authentication": "프록시 서버에 인증 절차가 있음", + User: "사용자", + Installed: "설치됨", + "Not installed": "설치되어 있지 않음", + Running: "작동 중", + "Not running": "작동하고 있지 않음", + "Remove Token": "토큰 삭제", + Start: "시작", + Stop: "정지", + "Uptime Kuma": "Uptime Kuma", + "Add New Status Page": "새로운 상태 페이지 만들기", + Slug: "주소", + "Accept characters:": "허용되는 문자열:", + startOrEndWithOnly: "{0}로 시작하거나 끝나야 해요.", + "No consecutive dashes": "연속되는 대시는 허용되지 않아요", + Next: "다음", + "The slug is already taken. Please choose another slug.": "이미 존재하는 주소에요. 다른 주소를 사용해 주세요.", + "No Proxy": "프록시 없음", + "HTTP Basic Auth": "HTTP 인증", + "New Status Page": "새로운 상태 페이지", + "Page Not Found": "페이지를 찾을 수 없어요", + "Reverse Proxy": "리버스 프록시", + Backup: "백업", + About: "정보", + wayToGetCloudflaredURL: "({0}에서 Cloudflare 다운로드 하기)", + cloudflareWebsite: "Cloudflare 웹사이트", + "Message:": "메시지:", + "Don't know how to get the token? Please read the guide:": "토큰을 얻는 방법은 이 가이드를 확인해주세요:", + "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.": "Cloudflare Tunnel를 연결하면 현재 연결이 끊길 수 있어요. 정말 중지할까요? 비밀번호를 입력해 확인하세요.", + "Other Software": "다른 소프트웨어", + "For example: nginx, Apache and Traefik.": "nginx, Apache, Traefik 등을 사용할 수 있어요.", + "Please read": "이 문서를 참조하세요:", + "Subject:": "Subject:", + "Valid To:": "Valid To:", + "Days Remaining:": "남은 일수:", + "Issuer:": "Issuer:", + "Fingerprint:": "Fingerprint:", + "No status pages": "상태 페이지 없음", + "Domain Name Expiry Notification": "도메인 이름 만료 알림", + Proxy: "프록시", + "Date Created": "생성된 날짜", + onebotHttpAddress: "OneBot HTTP 주소", + onebotMessageType: "OneBot 메시지 종류", + onebotGroupMessage: "그룹 메시지", + onebotPrivateMessage: "개인 메시지", + onebotUserOrGroupId: "그룹/사용자 ID", + onebotSafetyTips: "안전을 위해 Access 토큰을 설정하세요.", + "PushDeer Key": "PushDeer 키", + "Footer Text": "Footer 문구", + "Show Powered By": "Powered By 문구 표시하기", + "Domain Names": "도메인 이름", + signedInDisp: "{0} 로그인됨", + signedInDispDisabled: "인증 비활성화됨.", + "Certificate Expiry Notification": "인증서 만료 알림", + "API Username": "API 사용자 이름", + "API Key": "API 키", + "Recipient Number": "받는 사람 번호", + "From Name/Number": "발신자 이름/번호", + "Leave blank to use a shared sender number.": "공유 발신자 번호를 사용하려면 공백으로 두세요.", + "Octopush API Version": "Octopush API 버전", + "Legacy Octopush-DM": "레거시 Octopush-DM", + endpoint: "endpoint", + octopushAPIKey: "제어판 HTTP API credentials 에서 \"API key\"", + octopushLogin: "제어판 HTTP API credentials 에서 \"Login\"", + promosmsLogin: "API 로그인 이름", + promosmsPassword: "API 비밀번호", + "pushoversounds pushover": "Pushover (기본)", + "pushoversounds bike": "Bike", + "pushoversounds bugle": "Bugle", + "pushoversounds cashregister": "Cash Register", + "pushoversounds classical": "Classical", + "pushoversounds cosmic": "Cosmic", + "pushoversounds falling": "Falling", + "pushoversounds gamelan": "Gamelan", + "pushoversounds incoming": "Incoming", + "pushoversounds intermission": "Intermission", + "pushoversounds magic": "Magic", + "pushoversounds mechanical": "Mechanical", + "pushoversounds pianobar": "Piano Bar", + "pushoversounds siren": "Siren", + "pushoversounds spacealarm": "Space Alarm", + "pushoversounds tugboat": "Tug Boat", + "pushoversounds alien": "Alien Alarm (long)", + "pushoversounds climb": "Climb (long)", + "pushoversounds persistent": "Persistent (long)", + "pushoversounds echo": "Pushover Echo (long)", + "pushoversounds updown": "Up Down (long)", + "pushoversounds vibrate": "진동만", + "pushoversounds none": "없음 (무음)", + pushyAPIKey: "비밀 API 키", + pushyToken: "기기 토큰", + "Show update if available": "사용 가능한 경우에 업데이트 표시", + "Also check beta release": "베타 릴리즈 확인", + "Using a Reverse Proxy?": "리버스 프록시를 사용하시나요?", + "Check how to config it for WebSocket": "웹소켓에 대한 설정 방법 확인", + "Steam Game Server": "스팀 게임 서버", + "Most likely causes:": "원인:", + "The resource is no longer available.": "더이상 사용할 수 없어요.", + "There might be a typing error in the address.": "주소에 오탈자가 있을 수 있어요.", + "What you can try:": "해결 방법:", + "Retype the address.": "주소 다시 입력하기", + "Go back to the previous page.": "이전 페이지로 돌아가기", + "Coming Soon": "Coming Soon", + wayToGetClickSendSMSToken: "{0}에서 API 사용자 이름과 키를 얻을 수 있어요.", }; From 30858ab038a4d4d18de2a653c1a4af19e3784c02 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Sat, 28 May 2022 23:08:14 +0800 Subject: [PATCH 56/59] Fix rollback issue of 9fc5a33 and one issue of #1694 --- src/components/PublicGroupList.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PublicGroupList.vue b/src/components/PublicGroupList.vue index 98c0b7ff..df94eec9 100644 --- a/src/components/PublicGroupList.vue +++ b/src/components/PublicGroupList.vue @@ -41,7 +41,7 @@ <Uptime :monitor="monitor.element" type="24" :pill="true" /> {{ monitor.element.name }} </div> - <div v-if="showTag" class="tags"> + <div v-if="showTags" class="tags"> <Tag v-for="tag in monitor.element.tags" :key="tag" :item="tag" :size="'sm'" /> </div> </div> From 7f46223d684aa7d68a5d9270dd0e5f32d095e762 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Sat, 28 May 2022 23:22:44 +0800 Subject: [PATCH 57/59] Fix another log.debug call --- server/model/monitor.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 0d2e8e2e..ee7b4f43 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -374,7 +374,9 @@ class Monitor extends BeanModel { // beatInterval/retryInterval in the setTimeout further below if (previousBeat) { const msSinceLastBeat = dayjs.utc().valueOf() - dayjs.utc(previousBeat.time).valueOf(); - log.debug(`[${this.name}] msSinceLastBeat = ${msSinceLastBeat}`); + + log.debug("monitor", `[${this.name}] msSinceLastBeat = ${msSinceLastBeat}`); + if (previousBeat.status !== UP || msSinceLastBeat > beatInterval * 1000 + bufferTime) { throw new Error("No heartbeat in the time window"); } else { From ea10d89f51fbba6d15ec9f4e4794817de5d85bc8 Mon Sep 17 00:00:00 2001 From: Aram Akhavan <github@aram.nubmail.ca> Date: Sat, 28 May 2022 19:57:45 -0700 Subject: [PATCH 58/59] show correct down message for first tick --- server/model/monitor.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index ee7b4f43..643d34a6 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -370,13 +370,13 @@ class Monitor extends BeanModel { log.debug("monitor", `[${this.name}] Checking monitor at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`); const bufferTime = 1000; // 1s buffer to accommodate clock differences - // If the previous beat was nonexistent, down or pending we use the regular - // beatInterval/retryInterval in the setTimeout further below if (previousBeat) { const msSinceLastBeat = dayjs.utc().valueOf() - dayjs.utc(previousBeat.time).valueOf(); log.debug("monitor", `[${this.name}] msSinceLastBeat = ${msSinceLastBeat}`); + // If the previous beat was down or pending we use the regular + // beatInterval/retryInterval in the setTimeout further below if (previousBeat.status !== UP || msSinceLastBeat > beatInterval * 1000 + bufferTime) { throw new Error("No heartbeat in the time window"); } else { @@ -392,6 +392,8 @@ class Monitor extends BeanModel { this.heartbeatInterval = setTimeout(beat, timeout); return; } + } else { + throw new Error("No heartbeat in the time window"); } } else if (this.type === "steam") { From 857e88b27efbfe343826b86d2c6df3b47fe7d8d0 Mon Sep 17 00:00:00 2001 From: Louis Lam <louislam@users.noreply.github.com> Date: Sun, 29 May 2022 12:47:07 +0800 Subject: [PATCH 59/59] Update to 1.16.1 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2732e97d..0dbcc820 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uptime-kuma", - "version": "1.16.0", + "version": "1.16.1", "license": "MIT", "repository": { "type": "git", @@ -39,7 +39,7 @@ "build-docker-nightly-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly-alpine --target nightly . --push", "build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain", "upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain", - "setup": "git checkout 1.16.0 && npm ci --production && npm run download-dist", + "setup": "git checkout 1.16.1 && npm ci --production && npm run download-dist", "download-dist": "node extra/download-dist.js", "mark-as-nightly": "node extra/mark-as-nightly.js", "reset-password": "node extra/reset-password.js",