mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-12-25 05:34:08 -08:00
Merge branch 'master' of github.com:rmtsrc/uptime-kuma into add-home-assistant-notification
This commit is contained in:
commit
f091e92c70
|
@ -8,6 +8,7 @@
|
|||
"declaration-empty-line-before": null,
|
||||
"alpha-value-notation": "number",
|
||||
"color-function-notation": "legacy",
|
||||
"shorthand-property-no-redundant-values": null
|
||||
"shorthand-property-no-redundant-values": null,
|
||||
"color-hex-length": null,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,9 +151,9 @@ You can discuss or ask for help in [issues](https://github.com/louislam/uptime-k
|
|||
|
||||
### Subreddit
|
||||
|
||||
My Reddit account: louislamlam
|
||||
My Reddit account: [u/louislamlam](https://reddit.com/u/louislamlam).
|
||||
You can mention me if you ask a question on Reddit.
|
||||
https://www.reddit.com/r/UptimeKuma/
|
||||
[r/Uptime kuma](https://www.reddit.com/r/UptimeKuma/)
|
||||
|
||||
## Contribute
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@ const viteCompressionFilter = /\.(js|mjs|json|css|html|svg)$/i;
|
|||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
define: {
|
||||
"FRONTEND_VERSION": JSON.stringify(process.env.npm_package_version),
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
legacy({
|
||||
|
|
5
db/patch-add-clickable-status-page-link.sql
Normal file
5
db/patch-add-clickable-status-page-link.sql
Normal file
|
@ -0,0 +1,5 @@
|
|||
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
|
||||
BEGIN TRANSACTION;
|
||||
ALTER TABLE monitor_group
|
||||
ADD send_url BOOLEAN DEFAULT 0 NOT NULL;
|
||||
COMMIT;
|
|
@ -4,5 +4,5 @@ WORKDIR /app
|
|||
|
||||
# Install apprise, iputils for non-root ping, setpriv
|
||||
RUN apk add --no-cache iputils setpriv dumb-init python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib && \
|
||||
pip3 --no-cache-dir install apprise==0.9.8.3 && \
|
||||
pip3 --no-cache-dir install apprise==0.9.9 && \
|
||||
rm -rf /root/.cache
|
||||
|
|
|
@ -11,7 +11,7 @@ WORKDIR /app
|
|||
RUN apt update && \
|
||||
apt --yes --no-install-recommends install python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \
|
||||
sqlite3 iputils-ping util-linux dumb-init && \
|
||||
pip3 --no-cache-dir install apprise==0.9.8.3 && \
|
||||
pip3 --no-cache-dir install apprise==0.9.9 && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
apt --yes autoremove
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Simple docker-composer.yml
|
||||
# Simple docker-compose.yml
|
||||
# You can change your port or volume location
|
||||
|
||||
version: '3.3'
|
||||
|
|
7123
package-lock.json
generated
7123
package-lock.json
generated
File diff suppressed because it is too large
Load diff
92
package.json
92
package.json
|
@ -61,22 +61,15 @@
|
|||
"build-dist-and-restart": "npm run build && npm run start-server-dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||
"@fortawesome/free-regular-svg-icons": "~5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "~3.0.0-5",
|
||||
"@louislam/sqlite3": "~15.0.6",
|
||||
"@popperjs/core": "~2.10.2",
|
||||
"args-parser": "~1.3.0",
|
||||
"axios": "~0.26.1",
|
||||
"axios-ntlm": "^1.3.0",
|
||||
"badge-maker": "^3.3.1",
|
||||
"bcryptjs": "~2.4.3",
|
||||
"bootstrap": "5.1.3",
|
||||
"bree": "~7.1.5",
|
||||
"cacheable-lookup": "~6.0.4",
|
||||
"chardet": "^1.3.0",
|
||||
"chart.js": "~3.6.2",
|
||||
"chartjs-adapter-dayjs": "~1.0.0",
|
||||
"check-password-strength": "^2.0.5",
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"chroma-js": "^2.1.2",
|
||||
|
@ -87,7 +80,6 @@
|
|||
"express": "~4.17.3",
|
||||
"express-basic-auth": "~1.2.1",
|
||||
"express-static-gzip": "^2.1.7",
|
||||
"favico.js": "^0.3.10",
|
||||
"form-data": "~4.0.0",
|
||||
"http-graceful-shutdown": "~3.1.7",
|
||||
"http-proxy-agent": "^5.0.0",
|
||||
|
@ -102,21 +94,60 @@
|
|||
"nodemailer": "~6.6.5",
|
||||
"notp": "~2.0.3",
|
||||
"password-hash": "~1.2.2",
|
||||
"postcss-rtlcss": "~3.4.1",
|
||||
"postcss-scss": "~4.0.3",
|
||||
"prismjs": "^1.27.0",
|
||||
"pg": "^8.7.3",
|
||||
"pg-connection-string": "^2.5.0",
|
||||
"prom-client": "~13.2.0",
|
||||
"prometheus-api-metrics": "~3.2.1",
|
||||
"qrcode": "~1.5.0",
|
||||
"redbean-node": "0.1.4",
|
||||
"socket.io": "~4.4.1",
|
||||
"socket.io-client": "~4.4.1",
|
||||
"socks-proxy-agent": "^6.1.1",
|
||||
"socks-proxy-agent": "6.1.1",
|
||||
"tar": "^6.1.11",
|
||||
"tcp-ping": "~0.1.1",
|
||||
"thirty-two": "~1.0.2",
|
||||
"thirty-two": "~1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/github": "~5.0.1",
|
||||
"@babel/eslint-parser": "~7.17.0",
|
||||
"@babel/preset-env": "^7.15.8",
|
||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||
"@fortawesome/free-regular-svg-icons": "~5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "~3.0.0-5",
|
||||
"@popperjs/core": "~2.10.2",
|
||||
"@types/bootstrap": "~5.1.9",
|
||||
"@vitejs/plugin-legacy": "~1.8.2",
|
||||
"@vitejs/plugin-vue": "~2.3.3",
|
||||
"@vue/compiler-sfc": "~3.2.36",
|
||||
"aedes": "^0.46.3",
|
||||
"babel-plugin-rewire": "~1.2.0",
|
||||
"bootstrap": "5.1.3",
|
||||
"chart.js": "~3.6.2",
|
||||
"chartjs-adapter-dayjs": "~1.0.0",
|
||||
"concurrently": "^7.1.0",
|
||||
"core-js": "~3.18.3",
|
||||
"cross-env": "~7.0.3",
|
||||
"dns2": "~2.0.1",
|
||||
"eslint": "~8.14.0",
|
||||
"eslint-plugin-vue": "~8.7.1",
|
||||
"favico.js": "^0.3.10",
|
||||
"jest": "~27.2.5",
|
||||
"jest-puppeteer": "~6.0.3",
|
||||
"postcss-html": "^1.3.1",
|
||||
"postcss-rtlcss": "~3.4.1",
|
||||
"postcss-scss": "~4.0.3",
|
||||
"prismjs": "^1.27.0",
|
||||
"puppeteer": "~13.1.3",
|
||||
"qrcode": "~1.5.0",
|
||||
"rollup-plugin-visualizer": "^5.6.0",
|
||||
"sass": "~1.42.1",
|
||||
"stylelint": "~14.7.1",
|
||||
"stylelint-config-standard": "~25.0.0",
|
||||
"timezones-list": "~3.0.1",
|
||||
"typescript": "~4.4.4",
|
||||
"v-pagination-3": "~0.1.7",
|
||||
"vite": "~2.9.9",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vue": "next",
|
||||
"vue-chart-3": "3.0.9",
|
||||
"vue-confirm-dialog": "~1.0.2",
|
||||
|
@ -128,36 +159,7 @@
|
|||
"vue-qrcode": "~1.0.0",
|
||||
"vue-router": "~4.0.14",
|
||||
"vue-toastification": "~2.0.0-rc.5",
|
||||
"vuedraggable": "~4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/github": "~5.0.1",
|
||||
"@babel/eslint-parser": "~7.17.0",
|
||||
"@babel/preset-env": "^7.15.8",
|
||||
"@types/bootstrap": "~5.1.9",
|
||||
"@vitejs/plugin-legacy": "~1.8.2",
|
||||
"@vitejs/plugin-vue": "~2.3.3",
|
||||
"@vue/compiler-sfc": "~3.2.36",
|
||||
"aedes": "^0.46.3",
|
||||
"babel-plugin-rewire": "~1.2.0",
|
||||
"concurrently": "^7.1.0",
|
||||
"core-js": "~3.18.3",
|
||||
"cross-env": "~7.0.3",
|
||||
"dns2": "~2.0.1",
|
||||
"eslint": "~8.14.0",
|
||||
"eslint-plugin-vue": "~8.7.1",
|
||||
"jest": "~27.2.5",
|
||||
"jest-puppeteer": "~6.0.3",
|
||||
"npm-check-updates": "^14.1.1",
|
||||
"postcss-html": "^1.3.1",
|
||||
"puppeteer": "~13.1.3",
|
||||
"rollup-plugin-visualizer": "^5.6.0",
|
||||
"sass": "~1.42.1",
|
||||
"stylelint": "~14.7.1",
|
||||
"stylelint-config-standard": "~25.0.0",
|
||||
"typescript": "~4.4.4",
|
||||
"vite": "~2.9.9",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vuedraggable": "~4.1.0",
|
||||
"wait-on": "^6.0.1"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 893 B |
54
server/cacheable-dns-http-agent.js
Normal file
54
server/cacheable-dns-http-agent.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
const https = require("https");
|
||||
const http = require("http");
|
||||
const CacheableLookup = require("cacheable-lookup");
|
||||
|
||||
class CacheableDnsHttpAgent {
|
||||
|
||||
static cacheable = new CacheableLookup();
|
||||
|
||||
static httpAgentList = {};
|
||||
static httpsAgentList = {};
|
||||
|
||||
/**
|
||||
* Register cacheable to global agents
|
||||
*/
|
||||
static registerGlobalAgent() {
|
||||
this.cacheable.install(http.globalAgent);
|
||||
this.cacheable.install(https.globalAgent);
|
||||
}
|
||||
|
||||
static install(agent) {
|
||||
this.cacheable.install(agent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var {https.AgentOptions} agentOptions
|
||||
* @return {https.Agent}
|
||||
*/
|
||||
static getHttpsAgent(agentOptions) {
|
||||
let key = JSON.stringify(agentOptions);
|
||||
if (!(key in this.httpsAgentList)) {
|
||||
this.httpsAgentList[key] = new https.Agent(agentOptions);
|
||||
this.cacheable.install(this.httpsAgentList[key]);
|
||||
}
|
||||
return this.httpsAgentList[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* @var {http.AgentOptions} agentOptions
|
||||
* @return {https.Agents}
|
||||
*/
|
||||
static getHttpAgent(agentOptions) {
|
||||
let key = JSON.stringify(agentOptions);
|
||||
if (!(key in this.httpAgentList)) {
|
||||
this.httpAgentList[key] = new http.Agent(agentOptions);
|
||||
this.cacheable.install(this.httpAgentList[key]);
|
||||
}
|
||||
return this.httpAgentList[key];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
CacheableDnsHttpAgent,
|
||||
};
|
|
@ -58,6 +58,7 @@ class Database {
|
|||
"patch-monitor-expiry-notification.sql": true,
|
||||
"patch-status-page-footer-css.sql": true,
|
||||
"patch-added-mqtt-monitor.sql": true,
|
||||
"patch-add-clickable-status-page-link.sql": true,
|
||||
"patch-add-sqlserver-monitor.sql": true,
|
||||
"patch-add-other-auth.sql": { parents: [ "patch-monitor-basic-auth.sql" ] },
|
||||
};
|
||||
|
@ -177,7 +178,13 @@ class Database {
|
|||
} else {
|
||||
log.info("db", "Database patch is needed");
|
||||
|
||||
this.backup(version);
|
||||
try {
|
||||
this.backup(version);
|
||||
} catch (e) {
|
||||
log.error("db", e);
|
||||
log.error("db", "Unable to create a backup before patching the database. Please make sure you have enough space and permission.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Try catch anything here, if gone wrong, restore the backup
|
||||
try {
|
||||
|
@ -445,6 +452,23 @@ class Database {
|
|||
this.backupWalPath = walPath + ".bak" + version;
|
||||
fs.copyFileSync(walPath, this.backupWalPath);
|
||||
}
|
||||
|
||||
// Double confirm if all files actually backup
|
||||
if (!fs.existsSync(this.backupPath)) {
|
||||
throw new Error("Backup failed! " + this.backupPath);
|
||||
}
|
||||
|
||||
if (fs.existsSync(shmPath)) {
|
||||
if (!fs.existsSync(this.backupShmPath)) {
|
||||
throw new Error("Backup failed! " + this.backupShmPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (fs.existsSync(walPath)) {
|
||||
if (!fs.existsSync(this.backupWalPath)) {
|
||||
throw new Error("Backup failed! " + this.backupWalPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class Group extends BeanModel {
|
|||
*/
|
||||
async getMonitorList() {
|
||||
return R.convertToBeans("monitor", await R.getAll(`
|
||||
SELECT monitor.* FROM monitor, monitor_group
|
||||
SELECT monitor.*, monitor_group.send_url FROM monitor, monitor_group
|
||||
WHERE monitor.id = monitor_group.monitor_id
|
||||
AND group_id = ?
|
||||
ORDER BY monitor_group.weight
|
||||
|
|
|
@ -7,7 +7,7 @@ dayjs.extend(timezone);
|
|||
const axios = require("axios");
|
||||
const { Prometheus } = require("../prometheus");
|
||||
const { log, UP, DOWN, PENDING, flipStatus, TimeLogger } = require("../../src/util");
|
||||
const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, mqttAsync, setSetting, httpNtlm } = require("../util-server");
|
||||
const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mqttAsync, setSetting, httpNtlm } = require("../util-server");
|
||||
const { R } = require("redbean-node");
|
||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||
const { Notification } = require("../notification");
|
||||
|
@ -16,6 +16,7 @@ const { demoMode } = require("../config");
|
|||
const version = require("../../package.json").version;
|
||||
const apicache = require("../modules/apicache");
|
||||
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||
const { CacheableDnsHttpAgent } = require("../cacheable-dns-http-agent");
|
||||
|
||||
/**
|
||||
* status:
|
||||
|
@ -34,7 +35,13 @@ class Monitor extends BeanModel {
|
|||
let obj = {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
sendUrl: this.sendUrl,
|
||||
};
|
||||
|
||||
if (this.sendUrl) {
|
||||
obj.url = this.url;
|
||||
}
|
||||
|
||||
if (showTags) {
|
||||
obj.tags = await this.getTags();
|
||||
}
|
||||
|
@ -434,10 +441,13 @@ class Monitor extends BeanModel {
|
|||
"Accept": "*/*",
|
||||
"User-Agent": "Uptime-Kuma/" + version,
|
||||
},
|
||||
httpsAgent: new https.Agent({
|
||||
httpsAgent: CacheableDnsHttpAgent.getHttpsAgent({
|
||||
maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940)
|
||||
rejectUnauthorized: !this.getIgnoreTls(),
|
||||
}),
|
||||
httpAgent: CacheableDnsHttpAgent.getHttpAgent({
|
||||
maxCachedSessions: 0,
|
||||
}),
|
||||
maxRedirects: this.maxredirects,
|
||||
validateStatus: (status) => {
|
||||
return checkStatusCode(status, this.getAcceptedStatuscodes());
|
||||
|
@ -471,6 +481,14 @@ class Monitor extends BeanModel {
|
|||
|
||||
await mssqlQuery(this.databaseConnectionString, this.databaseQuery);
|
||||
|
||||
bean.msg = "";
|
||||
bean.status = UP;
|
||||
bean.ping = dayjs().valueOf() - startTime;
|
||||
} else if (this.type === "postgres") {
|
||||
let startTime = dayjs().valueOf();
|
||||
|
||||
await postgresQuery(this.databaseConnectionString, this.databaseQuery);
|
||||
|
||||
bean.msg = "";
|
||||
bean.status = UP;
|
||||
bean.ping = dayjs().valueOf() - startTime;
|
||||
|
|
|
@ -45,6 +45,8 @@ class StatusPage extends BeanModel {
|
|||
$("link[rel=icon]")
|
||||
.attr("href", statusPage.icon)
|
||||
.removeAttr("type");
|
||||
|
||||
$("link[rel=apple-touch-icon]").remove();
|
||||
}
|
||||
|
||||
const head = $("head");
|
||||
|
@ -61,6 +63,9 @@ class StatusPage extends BeanModel {
|
|||
</script>
|
||||
`);
|
||||
|
||||
// manifest.json
|
||||
$("link[rel=manifest]").attr("href", `/api/status-page/${statusPage.slug}/manifest.json`);
|
||||
|
||||
return $.root().html();
|
||||
}
|
||||
|
||||
|
|
50
server/notification-providers/alertnow.js
Normal file
50
server/notification-providers/alertnow.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const { setting } = require("../util-server");
|
||||
const { getMonitorRelativeURL, UP, DOWN } = require("../../src/util");
|
||||
|
||||
class AlertNow extends NotificationProvider {
|
||||
|
||||
name = "AlertNow";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
let textMsg = "";
|
||||
let status = "open";
|
||||
let eventType = "ERROR";
|
||||
let eventId = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
||||
|
||||
if (heartbeatJSON && heartbeatJSON.status === UP) {
|
||||
textMsg = `[${heartbeatJSON.name}] ✅ Application is back online`;
|
||||
status = "close";
|
||||
eventType = "INFO";
|
||||
eventId += `_${heartbeatJSON.name.replace(/\s/g, "")}`;
|
||||
} else if (heartbeatJSON && heartbeatJSON.status === DOWN) {
|
||||
textMsg = `[${heartbeatJSON.name}] 🔴 Application went down`;
|
||||
}
|
||||
|
||||
textMsg += ` - ${msg}`;
|
||||
|
||||
const baseURL = await setting("primaryBaseURL");
|
||||
if (baseURL && monitorJSON) {
|
||||
textMsg += ` >> ${baseURL + getMonitorRelativeURL(monitorJSON.id)}`;
|
||||
}
|
||||
|
||||
const data = {
|
||||
"summary": textMsg,
|
||||
"status": status,
|
||||
"event_type": eventType,
|
||||
"event_id": eventId,
|
||||
};
|
||||
|
||||
await axios.post(notification.alertNowWebhookURL, data);
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AlertNow;
|
43
server/notification-providers/linenotify.js
Normal file
43
server/notification-providers/linenotify.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const qs = require("qs");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
|
||||
class LineNotify extends NotificationProvider {
|
||||
|
||||
name = "LineNotify";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
let lineAPIUrl = "https://notify-api.line.me/api/notify";
|
||||
let config = {
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Authorization": "Bearer " + notification.lineNotifyAccessToken
|
||||
}
|
||||
};
|
||||
if (heartbeatJSON == null) {
|
||||
let testMessage = {
|
||||
"message": msg,
|
||||
};
|
||||
await axios.post(lineAPIUrl, qs.stringify(testMessage), config);
|
||||
} else if (heartbeatJSON["status"] === DOWN) {
|
||||
let downMessage = {
|
||||
"message": "\n[🔴 Down]\n" + "Name: " + monitorJSON["name"] + " \n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"]
|
||||
};
|
||||
await axios.post(lineAPIUrl, qs.stringify(downMessage), config);
|
||||
} else if (heartbeatJSON["status"] === UP) {
|
||||
let upMessage = {
|
||||
"message": "\n[✅ Up]\n" + "Name: " + monitorJSON["name"] + " \n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"]
|
||||
};
|
||||
await axios.post(lineAPIUrl, qs.stringify(upMessage), config);
|
||||
}
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = LineNotify;
|
|
@ -1,41 +1,43 @@
|
|||
const { R } = require("redbean-node");
|
||||
const { log } = require("../src/util");
|
||||
const Alerta = require("./notification-providers/alerta");
|
||||
const AlertNow = require("./notification-providers/alertnow");
|
||||
const AliyunSms = require("./notification-providers/aliyun-sms");
|
||||
const Apprise = require("./notification-providers/apprise");
|
||||
const Discord = require("./notification-providers/discord");
|
||||
const Gotify = require("./notification-providers/gotify");
|
||||
const Ntfy = require("./notification-providers/ntfy");
|
||||
const Line = require("./notification-providers/line");
|
||||
const LunaSea = require("./notification-providers/lunasea");
|
||||
const Mattermost = require("./notification-providers/mattermost");
|
||||
const Matrix = require("./notification-providers/matrix");
|
||||
const Octopush = require("./notification-providers/octopush");
|
||||
const PromoSMS = require("./notification-providers/promosms");
|
||||
const Bark = require("./notification-providers/bark");
|
||||
const ClickSendSMS = require("./notification-providers/clicksendsms");
|
||||
const DingDing = require("./notification-providers/dingding");
|
||||
const Discord = require("./notification-providers/discord");
|
||||
const Feishu = require("./notification-providers/feishu");
|
||||
const GoogleChat = require("./notification-providers/google-chat");
|
||||
const Gorush = require("./notification-providers/gorush");
|
||||
const Gotify = require("./notification-providers/gotify");
|
||||
const HomeAssistant = require("./notification-providers/home-assistant");
|
||||
const Line = require("./notification-providers/line");
|
||||
const LineNotify = require("./notification-providers/linenotify");
|
||||
const LunaSea = require("./notification-providers/lunasea");
|
||||
const Matrix = require("./notification-providers/matrix");
|
||||
const Mattermost = require("./notification-providers/mattermost");
|
||||
const Ntfy = require("./notification-providers/ntfy");
|
||||
const Octopush = require("./notification-providers/octopush");
|
||||
const OneBot = require("./notification-providers/onebot");
|
||||
const PagerDuty = require("./notification-providers/pagerduty");
|
||||
const PromoSMS = require("./notification-providers/promosms");
|
||||
const Pushbullet = require("./notification-providers/pushbullet");
|
||||
const PushDeer = require("./notification-providers/pushdeer");
|
||||
const Pushover = require("./notification-providers/pushover");
|
||||
const Pushy = require("./notification-providers/pushy");
|
||||
const TechulusPush = require("./notification-providers/techulus-push");
|
||||
const RocketChat = require("./notification-providers/rocket-chat");
|
||||
const SerwerSMS = require("./notification-providers/serwersms");
|
||||
const Signal = require("./notification-providers/signal");
|
||||
const Slack = require("./notification-providers/slack");
|
||||
const SMTP = require("./notification-providers/smtp");
|
||||
const Stackfield = require("./notification-providers/stackfield");
|
||||
const Teams = require("./notification-providers/teams");
|
||||
const TechulusPush = require("./notification-providers/techulus-push");
|
||||
const Telegram = require("./notification-providers/telegram");
|
||||
const Webhook = require("./notification-providers/webhook");
|
||||
const Feishu = require("./notification-providers/feishu");
|
||||
const AliyunSms = require("./notification-providers/aliyun-sms");
|
||||
const DingDing = require("./notification-providers/dingding");
|
||||
const Bark = require("./notification-providers/bark");
|
||||
const { log } = require("../src/util");
|
||||
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");
|
||||
const PushDeer = require("./notification-providers/pushdeer");
|
||||
const HomeAssistant = require("./notification-providers/home-assistant");
|
||||
|
||||
class Notification {
|
||||
|
||||
|
@ -48,42 +50,44 @@ class Notification {
|
|||
this.providerList = {};
|
||||
|
||||
const list = [
|
||||
new Apprise(),
|
||||
new Alerta(),
|
||||
new AlertNow(),
|
||||
new AliyunSms(),
|
||||
new Apprise(),
|
||||
new Bark(),
|
||||
new ClickSendSMS(),
|
||||
new DingDing(),
|
||||
new Discord(),
|
||||
new Teams(),
|
||||
new Gotify(),
|
||||
new Ntfy(),
|
||||
new Line(),
|
||||
new LunaSea(),
|
||||
new Feishu(),
|
||||
new Mattermost(),
|
||||
new GoogleChat(),
|
||||
new Gorush(),
|
||||
new Gotify(),
|
||||
new HomeAssistant(),
|
||||
new Line(),
|
||||
new LineNotify(),
|
||||
new LunaSea(),
|
||||
new Matrix(),
|
||||
new Mattermost(),
|
||||
new Ntfy(),
|
||||
new Octopush(),
|
||||
new OneBot(),
|
||||
new PagerDuty(),
|
||||
new PromoSMS(),
|
||||
new ClickSendSMS(),
|
||||
new Pushbullet(),
|
||||
new PushDeer(),
|
||||
new Pushover(),
|
||||
new Pushy(),
|
||||
new TechulusPush(),
|
||||
new RocketChat(),
|
||||
new SerwerSMS(),
|
||||
new Signal(),
|
||||
new Slack(),
|
||||
new SMTP(),
|
||||
new Stackfield(),
|
||||
new Teams(),
|
||||
new TechulusPush(),
|
||||
new Telegram(),
|
||||
new Webhook(),
|
||||
new Bark(),
|
||||
new SerwerSMS(),
|
||||
new Stackfield(),
|
||||
new WeCom(),
|
||||
new GoogleChat(),
|
||||
new PagerDuty(),
|
||||
new Gorush(),
|
||||
new Alerta(),
|
||||
new OneBot(),
|
||||
new PushDeer(),
|
||||
new HomeAssistant(),
|
||||
];
|
||||
|
||||
for (let item of list) {
|
||||
|
|
|
@ -107,4 +107,42 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
|
|||
}
|
||||
});
|
||||
|
||||
// Status page's manifest.json
|
||||
router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async (request, response) => {
|
||||
allowDevAllOrigin(response);
|
||||
let slug = request.params.slug;
|
||||
|
||||
try {
|
||||
// Get Status Page
|
||||
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
||||
slug
|
||||
]);
|
||||
|
||||
if (!statusPage) {
|
||||
response.statusCode = 404;
|
||||
response.json({
|
||||
msg: "Not Found"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Response
|
||||
response.json({
|
||||
"name": statusPage.title,
|
||||
"start_url": "/status/" + statusPage.slug,
|
||||
"display": "standalone",
|
||||
"icons": [
|
||||
{
|
||||
"src": statusPage.icon,
|
||||
"sizes": "128x128",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
send403(response, error.message);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
|
165
server/settings.js
Normal file
165
server/settings.js
Normal file
|
@ -0,0 +1,165 @@
|
|||
const { R } = require("redbean-node");
|
||||
const { log } = require("../src/util");
|
||||
|
||||
class Settings {
|
||||
|
||||
/**
|
||||
* Example:
|
||||
* {
|
||||
* key1: {
|
||||
* value: "value2",
|
||||
* timestamp: 12345678
|
||||
* },
|
||||
* key2: {
|
||||
* value: 2,
|
||||
* timestamp: 12345678
|
||||
* },
|
||||
* }
|
||||
* @type {{}}
|
||||
*/
|
||||
static cacheList = {
|
||||
|
||||
};
|
||||
|
||||
static cacheCleaner = null;
|
||||
|
||||
/**
|
||||
* Retrieve value of setting based on key
|
||||
* @param {string} key Key of setting to retrieve
|
||||
* @returns {Promise<any>} Value
|
||||
*/
|
||||
static async get(key) {
|
||||
|
||||
// Start cache clear if not started yet
|
||||
if (!Settings.cacheCleaner) {
|
||||
Settings.cacheCleaner = setInterval(() => {
|
||||
log.debug("settings", "Cache Cleaner is just started.");
|
||||
for (key in Settings.cacheList) {
|
||||
if (Date.now() - Settings.cacheList[key].timestamp > 60 * 1000) {
|
||||
log.debug("settings", "Cache Cleaner deleted: " + key);
|
||||
delete Settings.cacheList[key];
|
||||
}
|
||||
}
|
||||
|
||||
}, 60 * 1000);
|
||||
}
|
||||
|
||||
// Query from cache
|
||||
if (key in Settings.cacheList) {
|
||||
const v = Settings.cacheList[key].value;
|
||||
log.debug("settings", `Get Setting (cache): ${key}: ${v}`);
|
||||
return v;
|
||||
}
|
||||
|
||||
let value = await R.getCell("SELECT `value` FROM setting WHERE `key` = ? ", [
|
||||
key,
|
||||
]);
|
||||
|
||||
try {
|
||||
const v = JSON.parse(value);
|
||||
log.debug("settings", `Get Setting: ${key}: ${v}`);
|
||||
|
||||
Settings.cacheList[key] = {
|
||||
value: v,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
return v;
|
||||
} catch (e) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified setting to specified value
|
||||
* @param {string} key Key of setting to set
|
||||
* @param {any} value Value to set to
|
||||
* @param {?string} type Type of setting
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async set(key, value, type = null) {
|
||||
|
||||
let bean = await R.findOne("setting", " `key` = ? ", [
|
||||
key,
|
||||
]);
|
||||
if (!bean) {
|
||||
bean = R.dispense("setting");
|
||||
bean.key = key;
|
||||
}
|
||||
bean.type = type;
|
||||
bean.value = JSON.stringify(value);
|
||||
await R.store(bean);
|
||||
|
||||
Settings.deleteCache([ key ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings based on type
|
||||
* @param {string} type The type of setting
|
||||
* @returns {Promise<Bean>}
|
||||
*/
|
||||
static async getSettings(type) {
|
||||
let list = await R.getAll("SELECT `key`, `value` FROM setting WHERE `type` = ? ", [
|
||||
type,
|
||||
]);
|
||||
|
||||
let result = {};
|
||||
|
||||
for (let row of list) {
|
||||
try {
|
||||
result[row.key] = JSON.parse(row.value);
|
||||
} catch (e) {
|
||||
result[row.key] = row.value;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set settings based on type
|
||||
* @param {string} type Type of settings to set
|
||||
* @param {Object} data Values of settings
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async setSettings(type, data) {
|
||||
let keyList = Object.keys(data);
|
||||
|
||||
let promiseList = [];
|
||||
|
||||
for (let key of keyList) {
|
||||
let bean = await R.findOne("setting", " `key` = ? ", [
|
||||
key
|
||||
]);
|
||||
|
||||
if (bean == null) {
|
||||
bean = R.dispense("setting");
|
||||
bean.type = type;
|
||||
bean.key = key;
|
||||
}
|
||||
|
||||
if (bean.type === type) {
|
||||
bean.value = JSON.stringify(data[key]);
|
||||
promiseList.push(R.store(bean));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(promiseList);
|
||||
|
||||
Settings.deleteCache(keyList);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string[]} keyList
|
||||
*/
|
||||
static deleteCache(keyList) {
|
||||
for (let key of keyList) {
|
||||
delete Settings.cacheList[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Settings,
|
||||
};
|
|
@ -202,6 +202,11 @@ module.exports.statusPageSocketHandler = (socket) => {
|
|||
relationBean.weight = monitorOrder++;
|
||||
relationBean.group_id = groupBean.id;
|
||||
relationBean.monitor_id = monitor.id;
|
||||
|
||||
if (monitor.sendUrl !== undefined) {
|
||||
relationBean.send_url = monitor.sendUrl;
|
||||
}
|
||||
|
||||
await R.store(relationBean);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ const { R } = require("redbean-node");
|
|||
const { log } = require("../src/util");
|
||||
const Database = require("./database");
|
||||
const util = require("util");
|
||||
const { CacheableDnsHttpAgent } = require("./cacheable-dns-http-agent");
|
||||
|
||||
/**
|
||||
* `module.exports` (alias: `server`) should be inside this class, in order to avoid circular dependency issue.
|
||||
|
@ -71,6 +72,8 @@ class UptimeKumaServer {
|
|||
}
|
||||
}
|
||||
|
||||
CacheableDnsHttpAgent.registerGlobalAgent();
|
||||
|
||||
this.io = new Server(this.httpServer);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,10 @@ const mqtt = require("mqtt");
|
|||
const chroma = require("chroma-js");
|
||||
const { badgeConstants } = require("./config");
|
||||
const mssql = require("mssql");
|
||||
const { Client } = require("pg");
|
||||
const postgresConParse = require("pg-connection-string").parse;
|
||||
const { NtlmClient } = require("axios-ntlm");
|
||||
const { Settings } = require("./settings");
|
||||
|
||||
// From ping-lite
|
||||
exports.WIN = /^win/.test(process.platform);
|
||||
|
@ -237,10 +240,6 @@ exports.dnsResolve = function (hostname, resolverServer, resolverPort, rrtype) {
|
|||
*/
|
||||
exports.mssqlQuery = function (connectionString, query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
mssql.on("error", err => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
mssql.connect(connectionString).then(pool => {
|
||||
return pool.request()
|
||||
.query(query);
|
||||
|
@ -254,23 +253,45 @@ exports.mssqlQuery = function (connectionString, query) {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a query on Postgres
|
||||
* @param {string} connectionString The database connection string
|
||||
* @param {string} query The query to validate the database with
|
||||
* @returns {Promise<(string[]|Object[]|Object)>}
|
||||
*/
|
||||
exports.postgresQuery = function (connectionString, query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const config = postgresConParse(connectionString);
|
||||
|
||||
if (config.password === "") {
|
||||
// See https://github.com/brianc/node-postgres/issues/1927
|
||||
return reject(new Error("Password is undefined."));
|
||||
}
|
||||
|
||||
const client = new Client({ connectionString });
|
||||
|
||||
client.connect();
|
||||
|
||||
return client.query(query)
|
||||
.then(res => {
|
||||
resolve(res);
|
||||
})
|
||||
.catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
.finally(() => {
|
||||
client.end();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve value of setting based on key
|
||||
* @param {string} key Key of setting to retrieve
|
||||
* @returns {Promise<any>} Value
|
||||
*/
|
||||
exports.setting = async function (key) {
|
||||
let value = await R.getCell("SELECT `value` FROM setting WHERE `key` = ? ", [
|
||||
key,
|
||||
]);
|
||||
|
||||
try {
|
||||
const v = JSON.parse(value);
|
||||
log.debug("util", `Get Setting: ${key}: ${v}`);
|
||||
return v;
|
||||
} catch (e) {
|
||||
return value;
|
||||
}
|
||||
return await Settings.get(key);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -281,70 +302,26 @@ exports.setting = async function (key) {
|
|||
* @returns {Promise<void>}
|
||||
*/
|
||||
exports.setSetting = async function (key, value, type = null) {
|
||||
let bean = await R.findOne("setting", " `key` = ? ", [
|
||||
key,
|
||||
]);
|
||||
if (!bean) {
|
||||
bean = R.dispense("setting");
|
||||
bean.key = key;
|
||||
}
|
||||
bean.type = type;
|
||||
bean.value = JSON.stringify(value);
|
||||
await R.store(bean);
|
||||
await Settings.set(key, value, type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get settings based on type
|
||||
* @param {?string} type The type of setting
|
||||
* @param {string} type The type of setting
|
||||
* @returns {Promise<Bean>}
|
||||
*/
|
||||
exports.getSettings = async function (type) {
|
||||
let list = await R.getAll("SELECT `key`, `value` FROM setting WHERE `type` = ? ", [
|
||||
type,
|
||||
]);
|
||||
|
||||
let result = {};
|
||||
|
||||
for (let row of list) {
|
||||
try {
|
||||
result[row.key] = JSON.parse(row.value);
|
||||
} catch (e) {
|
||||
result[row.key] = row.value;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return await Settings.getSettings(type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set settings based on type
|
||||
* @param {?string} type Type of settings to set
|
||||
* @param {string} type Type of settings to set
|
||||
* @param {Object} data Values of settings
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
exports.setSettings = async function (type, data) {
|
||||
let keyList = Object.keys(data);
|
||||
|
||||
let promiseList = [];
|
||||
|
||||
for (let key of keyList) {
|
||||
let bean = await R.findOne("setting", " `key` = ? ", [
|
||||
key
|
||||
]);
|
||||
|
||||
if (bean == null) {
|
||||
bean = R.dispense("setting");
|
||||
bean.type = type;
|
||||
bean.key = key;
|
||||
}
|
||||
|
||||
if (bean.type === type) {
|
||||
bean.value = JSON.stringify(data[key]);
|
||||
promiseList.push(R.store(bean));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(promiseList);
|
||||
await Settings.setSettings(type, data);
|
||||
};
|
||||
|
||||
// ssl-checker by @dyaa
|
||||
|
@ -437,7 +414,7 @@ exports.checkCertificate = function (res) {
|
|||
|
||||
/**
|
||||
* Check if the provided status code is within the accepted ranges
|
||||
* @param {string} status The status code to check
|
||||
* @param {number} status The status code to check
|
||||
* @param {string[]} acceptedCodes An array of accepted status codes
|
||||
* @returns {boolean} True if status code within range, false otherwise
|
||||
* @throws {Error} Will throw an error if the provided status code is not a valid range string or code string
|
||||
|
|
|
@ -39,7 +39,27 @@
|
|||
<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 }}
|
||||
<a
|
||||
v-if="showLink(monitor)"
|
||||
:href="monitor.element.url"
|
||||
class="item-name"
|
||||
target="_blank"
|
||||
>
|
||||
{{ monitor.element.name }}
|
||||
</a>
|
||||
<p v-else class="item-name"> {{ monitor.element.name }} </p>
|
||||
<span
|
||||
v-if="showLink(monitor, true)"
|
||||
title="Toggle Clickable Link"
|
||||
>
|
||||
<font-awesome-icon
|
||||
v-if="editMode"
|
||||
:class="{'link-active': monitor.element.sendUrl, 'btn-link': true}"
|
||||
icon="link" class="action me-3"
|
||||
|
||||
@click="toggleLink(group.index, monitor.index)"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="showTags" class="tags">
|
||||
<Tag v-for="tag in monitor.element.tags" :key="tag" :item="tag" :size="'sm'" />
|
||||
|
@ -113,6 +133,33 @@ export default {
|
|||
removeMonitor(groupIndex, index) {
|
||||
this.$root.publicGroupList[groupIndex].monitorList.splice(index, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the value of sendUrl
|
||||
* @param {number} groupIndex Index of group monitor is member of
|
||||
* @param {number} index Index of monitor within group
|
||||
*/
|
||||
toggleLink(groupIndex, index) {
|
||||
this.$root.publicGroupList[groupIndex].monitorList[index].sendUrl = !this.$root.publicGroupList[groupIndex].monitorList[index].sendUrl;
|
||||
},
|
||||
|
||||
/**
|
||||
* Should a link to the monitor be shown?
|
||||
* Attempts to guess if a link should be shown based upon if
|
||||
* sendUrl is set and if the URL is default or not.
|
||||
* @param {Object} monitor Monitor to check
|
||||
* @param {boolean} [ignoreSendUrl=false] Should the presence of the sendUrl
|
||||
* property be ignored. This will only work in edit mode.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
showLink(monitor, ignoreSendUrl = false) {
|
||||
// We must check if there are any elements in monitorList to
|
||||
// prevent undefined errors if it hasn't been loaded yet
|
||||
if (this.$parent.editMode && ignoreSendUrl && Object.keys(this.$root.monitorList).length) {
|
||||
return this.$root.monitorList[monitor.element.id].type === "http" || this.$root.monitorList[monitor.element.id].type === "keyword";
|
||||
}
|
||||
return monitor.element.sendUrl && monitor.element.url && monitor.element.url !== "https://" && !this.editMode;
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -131,6 +178,22 @@ export default {
|
|||
min-height: 46px;
|
||||
}
|
||||
|
||||
.item-name {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
color: #bbbbbb;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.link-active {
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
.flip-list-move {
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
|
|
13
src/components/notifications/AlertNow.vue
Normal file
13
src/components/notifications/AlertNow.vue
Normal file
|
@ -0,0 +1,13 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="alertnow-webhook-url" class="form-label">{{ $t("Webhook URL") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="alertnow-webhook-url" v-model="$parent.notification.alertNowWebhookURL" type="text" class="form-control" required>
|
||||
|
||||
<div class="form-text">
|
||||
<span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}
|
||||
<i18n-t tag="p" keypath="aboutWebhooks" style="margin-top: 8px;">
|
||||
<a href="https://service.opsnow.com/docs/alertnow/en/user-guide-alertnow-en.html#standard" target="_blank">{{ $t("here") }}</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
9
src/components/notifications/LineNotify.vue
Normal file
9
src/components/notifications/LineNotify.vue
Normal file
|
@ -0,0 +1,9 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="line-notify-access-token" class="form-label">{{ $t("Access Token") }}</label>
|
||||
<input id="line-notify-access-token" v-model="$parent.notification.lineNotifyAccessToken" type="text" class="form-control" :required="true">
|
||||
</div>
|
||||
<i18n-t tag="div" keypath="wayToGetLineNotifyToken" class="form-text" style="margin-top: 8px;">
|
||||
<a href="https://notify-bot.line.me/" target="_blank">https://notify-bot.line.me/</a>
|
||||
</i18n-t>
|
||||
</template>
|
|
@ -1,39 +1,41 @@
|
|||
import STMP from "./SMTP.vue";
|
||||
import Telegram from "./Telegram.vue";
|
||||
import Alerta from "./Alerta.vue";
|
||||
import AlertNow from "./AlertNow.vue";
|
||||
import AliyunSMS from "./AliyunSms.vue";
|
||||
import Apprise from "./Apprise.vue";
|
||||
import Bark from "./Bark.vue";
|
||||
import ClickSendSMS from "./ClickSendSMS.vue";
|
||||
import DingDing from "./DingDing.vue";
|
||||
import Discord from "./Discord.vue";
|
||||
import Webhook from "./Webhook.vue";
|
||||
import Signal from "./Signal.vue";
|
||||
import Feishu from "./Feishu.vue";
|
||||
import GoogleChat from "./GoogleChat.vue";
|
||||
import Gorush from "./Gorush.vue";
|
||||
import Gotify from "./Gotify.vue";
|
||||
import HomeAssistant from "./HomeAssistant.vue";
|
||||
import Line from "./Line.vue";
|
||||
import LineNotify from "./LineNotify.vue";
|
||||
import LunaSea from "./LunaSea.vue";
|
||||
import Matrix from "./Matrix.vue";
|
||||
import Mattermost from "./Mattermost.vue";
|
||||
import Ntfy from "./Ntfy.vue";
|
||||
import Slack from "./Slack.vue";
|
||||
import RocketChat from "./RocketChat.vue";
|
||||
import Teams from "./Teams.vue";
|
||||
import Octopush from "./Octopush.vue";
|
||||
import OneBot from "./OneBot.vue";
|
||||
import PagerDuty from "./PagerDuty.vue";
|
||||
import PromoSMS from "./PromoSMS.vue";
|
||||
import Pushbullet from "./Pushbullet.vue";
|
||||
import PushDeer from "./PushDeer.vue";
|
||||
import Pushover from "./Pushover.vue";
|
||||
import Pushy from "./Pushy.vue";
|
||||
import TechulusPush from "./TechulusPush.vue";
|
||||
import Octopush from "./Octopush.vue";
|
||||
import PromoSMS from "./PromoSMS.vue";
|
||||
import ClickSendSMS from "./ClickSendSMS.vue";
|
||||
import LunaSea from "./LunaSea.vue";
|
||||
import Feishu from "./Feishu.vue";
|
||||
import Apprise from "./Apprise.vue";
|
||||
import Pushbullet from "./Pushbullet.vue";
|
||||
import Line from "./Line.vue";
|
||||
import Mattermost from "./Mattermost.vue";
|
||||
import Matrix from "./Matrix.vue";
|
||||
import AliyunSMS from "./AliyunSms.vue";
|
||||
import DingDing from "./DingDing.vue";
|
||||
import Bark from "./Bark.vue";
|
||||
import RocketChat from "./RocketChat.vue";
|
||||
import SerwerSMS from "./SerwerSMS.vue";
|
||||
import Signal from "./Signal.vue";
|
||||
import Slack from "./Slack.vue";
|
||||
import Stackfield from "./Stackfield.vue";
|
||||
import STMP from "./SMTP.vue";
|
||||
import Teams from "./Teams.vue";
|
||||
import TechulusPush from "./TechulusPush.vue";
|
||||
import Telegram from "./Telegram.vue";
|
||||
import Webhook from "./Webhook.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";
|
||||
import PushDeer from "./PushDeer.vue";
|
||||
import HomeAssistant from "./HomeAssistant.vue";
|
||||
|
||||
/**
|
||||
* Manage all notification form.
|
||||
|
@ -41,42 +43,44 @@ import HomeAssistant from "./HomeAssistant.vue";
|
|||
* @type { Record<string, any> }
|
||||
*/
|
||||
const NotificationFormList = {
|
||||
"telegram": Telegram,
|
||||
"webhook": Webhook,
|
||||
"smtp": STMP,
|
||||
"discord": Discord,
|
||||
"teams": Teams,
|
||||
"signal": Signal,
|
||||
"gotify": Gotify,
|
||||
"ntfy": Ntfy,
|
||||
"slack": Slack,
|
||||
"rocket.chat": RocketChat,
|
||||
"pushover": Pushover,
|
||||
"pushy": Pushy,
|
||||
"PushByTechulus": TechulusPush,
|
||||
"octopush": Octopush,
|
||||
"promosms": PromoSMS,
|
||||
"clicksendsms": ClickSendSMS,
|
||||
"lunasea": LunaSea,
|
||||
"Feishu": Feishu,
|
||||
"alerta": Alerta,
|
||||
"AlertNow": AlertNow,
|
||||
"AliyunSMS": AliyunSMS,
|
||||
"apprise": Apprise,
|
||||
"pushbullet": Pushbullet,
|
||||
"line": Line,
|
||||
"mattermost": Mattermost,
|
||||
"matrix": Matrix,
|
||||
"DingDing": DingDing,
|
||||
"Bark": Bark,
|
||||
"serwersms": SerwerSMS,
|
||||
"stackfield": Stackfield,
|
||||
"WeCom": WeCom,
|
||||
"clicksendsms": ClickSendSMS,
|
||||
"DingDing": DingDing,
|
||||
"discord": Discord,
|
||||
"Feishu": Feishu,
|
||||
"GoogleChat": GoogleChat,
|
||||
"PagerDuty": PagerDuty,
|
||||
"gorush": Gorush,
|
||||
"alerta": Alerta,
|
||||
"OneBot": OneBot,
|
||||
"PushDeer": PushDeer,
|
||||
"gotify": Gotify,
|
||||
"HomeAssistant": HomeAssistant,
|
||||
"line": Line,
|
||||
"LineNotify": LineNotify,
|
||||
"lunasea": LunaSea,
|
||||
"matrix": Matrix,
|
||||
"mattermost": Mattermost,
|
||||
"ntfy": Ntfy,
|
||||
"octopush": Octopush,
|
||||
"OneBot": OneBot,
|
||||
"PagerDuty": PagerDuty,
|
||||
"promosms": PromoSMS,
|
||||
"pushbullet": Pushbullet,
|
||||
"PushByTechulus": TechulusPush,
|
||||
"PushDeer": PushDeer,
|
||||
"pushover": Pushover,
|
||||
"pushy": Pushy,
|
||||
"rocket.chat": RocketChat,
|
||||
"serwersms": SerwerSMS,
|
||||
"signal": Signal,
|
||||
"slack": Slack,
|
||||
"smtp": STMP,
|
||||
"stackfield": Stackfield,
|
||||
"teams": Teams,
|
||||
"telegram": Telegram,
|
||||
"webhook": Webhook,
|
||||
"WeCom": WeCom,
|
||||
};
|
||||
|
||||
export default NotificationFormList;
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
<object class="my-4" width="200" height="200" data="/icon.svg" />
|
||||
<div class="fs-4 fw-bold">Uptime Kuma</div>
|
||||
<div>{{ $t("Version") }}: {{ $root.info.version }}</div>
|
||||
<div class="frontend-version">{{ $t("Frontend Version") }}: {{ $root.frontendVersion }}</div>
|
||||
|
||||
<div v-if="!$root.isFrontendBackendVersionMatched" class="alert alert-warning mt-4" role="alert">
|
||||
⚠️ {{ $t("Frontend Version do not match backend version!") }}
|
||||
</div>
|
||||
|
||||
<div class="my-3 update-link"><a href="https://github.com/louislam/uptime-kuma/releases" target="_blank" rel="noopener">{{ $t("Check Update On GitHub") }}</a></div>
|
||||
|
||||
|
@ -46,6 +51,16 @@ export default {
|
|||
}
|
||||
|
||||
.update-link {
|
||||
font-size: 0.9em;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.frontend-version {
|
||||
font-size: 0.9em;
|
||||
color: #cccccc;
|
||||
|
||||
.dark & {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -11,6 +11,7 @@ const languageList = {
|
|||
"es-ES": "Español",
|
||||
"eu": "Euskara",
|
||||
"fa": "Farsi",
|
||||
"pt-PT": "Português (Portugal)",
|
||||
"pt-BR": "Português (Brasileiro)",
|
||||
"fr-FR": "Français (France)",
|
||||
"hu": "Magyar",
|
||||
|
|
|
@ -81,6 +81,7 @@ library.add(
|
|||
faUndo,
|
||||
faPlusCircle,
|
||||
faAngleDown,
|
||||
faLink,
|
||||
);
|
||||
|
||||
export { FontAwesomeIcon };
|
||||
|
|
|
@ -536,4 +536,5 @@ export default {
|
|||
Domain: "Домейн",
|
||||
Workstation: "Работна станция",
|
||||
disableCloudflaredNoAuthMsg: "Тъй като сте в режим \"No Auth mode\", парола не се изисква.",
|
||||
wayToGetLineNotifyToken: "Може да получите токен код за достъп от {0}",
|
||||
};
|
||||
|
|
|
@ -465,6 +465,7 @@ export default {
|
|||
"Domain Name Expiry Notification": "Domain Name Expiry Notification",
|
||||
Proxy: "Proxy",
|
||||
"Date Created": "Date Created",
|
||||
HomeAssistant: "Home Assistant",
|
||||
onebotHttpAddress: "OneBot HTTP Address",
|
||||
onebotMessageType: "OneBot Message Type",
|
||||
onebotGroupMessage: "Group",
|
||||
|
@ -536,5 +537,5 @@ export default {
|
|||
"Domain": "Domain",
|
||||
"Workstation": "Workstation",
|
||||
disableCloudflaredNoAuthMsg: "You are in No Auth mode, password is not require.",
|
||||
HomeAssistant: "Home Assistant",
|
||||
wayToGetLineNotifyToken: "You can get an access token from {0}",
|
||||
};
|
||||
|
|
|
@ -7,8 +7,8 @@ export default {
|
|||
maxRedirectDescription: "Número máximo de direcciones a seguir. Establecer a 0 para deshabilitar.",
|
||||
acceptedStatusCodesDescription: "Seleccionar los códigos de estado que se consideran como respuesta exitosa.",
|
||||
passwordNotMatchMsg: "La contraseña repetida no coincide.",
|
||||
notificationDescription: "Por favor asigne una notificación a el/los monitor(es) para hacerlos funcional(es).",
|
||||
keywordDescription: "Palabra clave en HTML plano o respuesta JSON y es sensible a mayúsculas",
|
||||
notificationDescription: "Por favor asigna una notificación a el/los monitor(es) para hacerlos funcional(es).",
|
||||
keywordDescription: "Palabra clave en HTML plano o respuesta JSON, es sensible a mayúsculas",
|
||||
pauseDashboardHome: "Pausado",
|
||||
deleteMonitorMsg: "¿Seguro que quieres eliminar este monitor?",
|
||||
deleteNotificationMsg: "¿Seguro que quieres eliminar esta notificación para todos los monitores?",
|
||||
|
@ -35,7 +35,7 @@ export default {
|
|||
Pause: "Pausar",
|
||||
Name: "Nombre",
|
||||
Status: "Estado",
|
||||
DateTime: "Fecha y Hora",
|
||||
DateTime: "Fecha y hora",
|
||||
Message: "Mensaje",
|
||||
"No important events": "No hay eventos importantes",
|
||||
Resume: "Reanudar",
|
||||
|
@ -50,7 +50,7 @@ export default {
|
|||
"-hour": "-hora",
|
||||
Response: "Respuesta",
|
||||
Ping: "Ping",
|
||||
"Monitor Type": "Tipo de Monitor",
|
||||
"Monitor Type": "Tipo de monitor",
|
||||
Keyword: "Palabra clave",
|
||||
"Friendly Name": "Nombre sencillo",
|
||||
URL: "URL",
|
||||
|
@ -60,11 +60,11 @@ export default {
|
|||
Retries: "Reintentos",
|
||||
Advanced: "Avanzado",
|
||||
"Upside Down Mode": "Modo invertido",
|
||||
"Max. Redirects": "Redirecciones Máximas",
|
||||
"Max. Redirects": "Redirecciones máximas",
|
||||
"Accepted Status Codes": "Códigos de estado aceptados",
|
||||
Save: "Guardar",
|
||||
Notifications: "Notificaciones",
|
||||
"Not available, please setup.": "No disponible, por favor configúrelo.",
|
||||
"Not available, please setup.": "No disponible, por favor configúralo.",
|
||||
"Setup Notification": "Configurar notificación",
|
||||
Light: "Claro",
|
||||
Dark: "Oscuro",
|
||||
|
@ -82,8 +82,8 @@ export default {
|
|||
"New Password": "Nueva contraseña",
|
||||
"Repeat New Password": "Repetir nueva contraseña",
|
||||
"Update Password": "Actualizar contraseña",
|
||||
"Disable Auth": "Deshabilitar Autenticación",
|
||||
"Enable Auth": "Habilitar Autenticación",
|
||||
"Disable Auth": "Deshabilitar autenticación",
|
||||
"Enable Auth": "Habilitar autenticación",
|
||||
"disableauth.message1": "Seguro que deseas <strong>deshabilitar la autenticación</strong>?",
|
||||
"disableauth.message2": "Es para <strong>quien implementa autenticación de terceros</strong> ante Uptime Kuma como por ejemplo Cloudflare Access.",
|
||||
"Please use this option carefully!": "Por favor usar con cuidado.",
|
||||
|
@ -104,32 +104,32 @@ export default {
|
|||
Test: "Test",
|
||||
"Certificate Info": "Información del certificado",
|
||||
"Resolver Server": "Servidor de resolución",
|
||||
"Resource Record Type": "Tipo de Registro",
|
||||
"Resource Record Type": "Tipo de registro",
|
||||
"Last Result": "Último resultado",
|
||||
"Create your admin account": "Crea tu cuenta de administrador",
|
||||
"Repeat Password": "Repetir contraseña",
|
||||
respTime: "Tiempo de resp. (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
Create: "Crear",
|
||||
clearEventsMsg: "¿Está seguro de que desea eliminar todos los eventos de este monitor?",
|
||||
clearHeartbeatsMsg: "¿Está seguro de que desea eliminar todos los latidos de este monitor?",
|
||||
confirmClearStatisticsMsg: "¿Está seguro de que desea eliminar TODAS las estadísticas?",
|
||||
"Clear Data": "Borrar Datos",
|
||||
clearEventsMsg: "¿Estás seguro de que deseas eliminar todos los eventos de este monitor?",
|
||||
clearHeartbeatsMsg: "¿Estás seguro de que deseas eliminar todos los latidos de este monitor?",
|
||||
confirmClearStatisticsMsg: "¿Estás seguro de que deseas eliminar TODAS las estadísticas?",
|
||||
"Clear Data": "Borrar datos",
|
||||
Events: "Eventos",
|
||||
Heartbeats: "Latidos",
|
||||
"Auto Get": "Obtener automáticamente",
|
||||
enableDefaultNotificationDescription: "Para cada nuevo monitor, esta notificación estará habilitada de forma predeterminada. Aún puede deshabilitar la notificación por separado para cada monitor.",
|
||||
enableDefaultNotificationDescription: "Para cada nuevo monitor, esta notificación estará habilitada de forma predeterminada. Aún puedes deshabilitar la notificación por separado para cada monitor.",
|
||||
"Default enabled": "Habilitado por defecto",
|
||||
"Also apply to existing monitors": "También se aplica a monitores existentes",
|
||||
Export: "Exportar",
|
||||
Import: "Importar",
|
||||
backupDescription: "Puede hacer una copia de seguridad de todos los monitores y todas las notificaciones en un archivo JSON.",
|
||||
backupDescription: "Puedes hacer una copia de seguridad de todos los monitores y todas las notificaciones en un archivo JSON.",
|
||||
backupDescription2: "PD: el historial y los datos de eventos no están incluidos.",
|
||||
backupDescription3: "Los datos confidenciales, como los tokens de notificación, se incluyen en el archivo de exportación. Guárdelo con cuidado.",
|
||||
alertNoFile: "Seleccione un archivo para importar.",
|
||||
alertWrongFileType: "Seleccione un archivo JSON.",
|
||||
twoFAVerifyLabel: "Ingrese su token para verificar que 2FA está funcionando",
|
||||
tokenValidSettingsMsg: "¡El token es válido! Ahora puede guardar la configuración de 2FA.",
|
||||
backupDescription3: "Los datos confidenciales, como los tokens de notificación, se incluyen en el archivo de exportación. Guárdalo con cuidado.",
|
||||
alertNoFile: "Selecciona un archivo para importar.",
|
||||
alertWrongFileType: "Selecciona un archivo JSON.",
|
||||
twoFAVerifyLabel: "Ingresa tu token para verificar que 2FA está funcionando",
|
||||
tokenValidSettingsMsg: "¡El token es válido! Ahora puedes guardar la configuración de 2FA.",
|
||||
confirmEnableTwoFAMsg: "¿Estás seguro de que quieres habilitar 2FA?",
|
||||
confirmDisableTwoFAMsg: "¿Estás seguro de que quieres desactivar 2FA?",
|
||||
"Apply on all existing monitors": "Aplicar en todos los monitores existentes",
|
||||
|
@ -145,19 +145,19 @@ export default {
|
|||
"Show URI": "Mostrar URI",
|
||||
"Clear all statistics": "Borrar todas las estadísticas",
|
||||
retryCheckEverySecond: "Reintentar cada {0} segundo.",
|
||||
importHandleDescription: "Elija 'Omitir existente' si desea omitir todos los monitores o notificaciones con el mismo nombre. 'Sobrescribir' eliminará todos los monitores y notificaciones existentes.",
|
||||
confirmImportMsg: "¿Estás seguro de importar la copia de seguridad? Asegúrese de haber seleccionado la opción de importación correcta.",
|
||||
importHandleDescription: "Elige 'Omitir existente' si deseas omitir todos los monitores o notificaciones con el mismo nombre. 'Sobrescribir' eliminará todos los monitores y notificaciones existentes.",
|
||||
confirmImportMsg: "¿Estás seguro de importar la copia de seguridad? Asegúrate de haber seleccionado la opción de importación correcta.",
|
||||
"Heartbeat Retry Interval": "Intervalo de reintento de latido",
|
||||
"Import Backup": "Importar copia de seguridad",
|
||||
"Export Backup": "Exportar copia de seguridad",
|
||||
"Skip existing": "Omitir existente",
|
||||
Overwrite: "Sobrescribir",
|
||||
Options: "Opciones",
|
||||
"Keep both": "Mantén ambos",
|
||||
"Keep both": "Manténer ambos",
|
||||
Tags: "Etiquetas",
|
||||
"Add New below or Select...": "Agregar nuevo a continuación o Seleccionar...",
|
||||
"Tag with this name already exist.": "La etiqueta con este nombre ya existe.",
|
||||
"Tag with this value already exist.": "La etiqueta con este valor ya existe.",
|
||||
"Add New below or Select...": "Agregar nuevo a continuación o seleccionar...",
|
||||
"Tag with this name already exist.": "Una etiqueta con este nombre ya existe.",
|
||||
"Tag with this value already exist.": "Una etiqueta con este valor ya existe.",
|
||||
color: "color",
|
||||
"value (optional)": "valor (opcional)",
|
||||
Gray: "Gris",
|
||||
|
@ -172,17 +172,17 @@ export default {
|
|||
"Avg. Ping": "Ping promedio",
|
||||
"Avg. Response": "Respuesta promedio",
|
||||
"Entry Page": "Página de entrada",
|
||||
statusPageNothing: "No hay nada aquí, agregue un grupo o un monitor.",
|
||||
statusPageNothing: "No hay nada aquí, agrega un grupo o un monitor.",
|
||||
"No Services": "Sin servicio",
|
||||
"All Systems Operational": "Todos los sistemas están operativos",
|
||||
"Partially Degraded Service": "Servicio parcialmente degradado",
|
||||
"Degraded Service": "Servicio degradado",
|
||||
"Add Group": "Agregar Grupo",
|
||||
"Add Group": "Agregar grupo",
|
||||
"Add a monitor": "Agregar un monitor",
|
||||
"Edit Status Page": "Editar página de estado",
|
||||
"Go to Dashboard": "Ir al panel de control",
|
||||
"Status Page": "Página de estado",
|
||||
"Status Pages": "Página de estado",
|
||||
"Status Pages": "Páginas de estado",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "Email (SMTP)",
|
||||
|
@ -205,5 +205,5 @@ export default {
|
|||
clearDataOlderThan: "Mantener los datos del historial del monitor durante {0} días.",
|
||||
records: "registros",
|
||||
"One record": "Un registro",
|
||||
steamApiKeyDescription: "Para monitorear un servidor de juegos de Steam, necesita una clave Steam Web-API. Puede registrar su clave API aquí: ",
|
||||
steamApiKeyDescription: "Para monitorear un servidor de juegos de Steam, necesitas una clave Steam Web-API. Puedes registrar tu clave API aquí: ",
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@ export default {
|
|||
checkEverySecond: "{0}초마다 확인해요.",
|
||||
retryCheckEverySecond: "{0}초마다 다시 확인해요.",
|
||||
retriesDescription: "서비스가 중단된 후 알림을 보내기 전 최대 재시도 횟수",
|
||||
ignoreTLSError: "HTTPS 웹사이트에서 TLS/SSL 에러 무시하기",
|
||||
ignoreTLSError: "HTTPS 웹사이트에서 TLS/SSL 오류 무시하기",
|
||||
upsideDownModeDescription: "서버 상태를 반대로 표시해요. 서버가 작동하면 오프라인으로 표시할 거예요.",
|
||||
maxRedirectDescription: "최대 리다이렉트 횟수예요. 0을 입력하면 리다이렉트를 꺼요.",
|
||||
acceptedStatusCodesDescription: "응답 성공으로 간주할 상태 코드를 정해요.",
|
||||
|
@ -30,7 +30,7 @@ export default {
|
|||
Dashboard: "대시보드",
|
||||
"New Update": "새로운 업데이트",
|
||||
Language: "언어",
|
||||
Appearance: "외형",
|
||||
Appearance: "디스플레이",
|
||||
Theme: "테마",
|
||||
General: "일반",
|
||||
Version: "버전",
|
||||
|
@ -78,7 +78,7 @@ export default {
|
|||
Notifications: "알림",
|
||||
"Not available, please setup.": "존재하지 않아요, 새로운 거 하나 만드는 건 어때요?",
|
||||
"Setup Notification": "알림 설정",
|
||||
Light: "라이트",
|
||||
Light: "화이트",
|
||||
Dark: "다크",
|
||||
Auto: "자동",
|
||||
"Theme - Heartbeat Bar": "테마 - 하트비트 바",
|
||||
|
@ -91,7 +91,7 @@ export default {
|
|||
"Discourage search engines from indexing site": "검색 엔진 인덱싱 거부",
|
||||
"Change Password": "비밀번호 변경",
|
||||
"Current Password": "기존 비밀번호",
|
||||
"New Password": "새로운 비밀번호",
|
||||
"New Password": "새 비밀번호",
|
||||
"Repeat New Password": "새로운 비밀번호 재입력",
|
||||
"Update Password": "비밀번호 변경",
|
||||
"Disable Auth": "인증 비활성화",
|
||||
|
@ -109,14 +109,14 @@ export default {
|
|||
Password: "비밀번호",
|
||||
"Remember me": "비밀번호 기억하기",
|
||||
Login: "로그인",
|
||||
"No Monitors, please": "모니터링이 없어요,",
|
||||
"add one": "하나 추가해봐요",
|
||||
"No Monitors, please": "모니터링이 현재 없어요,",
|
||||
"add one": "한번 추가해보실레요?",
|
||||
"Notification Type": "알림 종류",
|
||||
Email: "이메일",
|
||||
Test: "테스트",
|
||||
"Certificate Info": "인증서 정보",
|
||||
"Resolver Server": "Resolver 서버",
|
||||
"Resource Record Type": "자원 레코드 유형",
|
||||
"Resource Record Type": "리소스 레코드 유형",
|
||||
"Last Result": "최근 결과",
|
||||
"Create your admin account": "관리자 계정 만들기",
|
||||
"Repeat Password": "비밀번호 재입력",
|
||||
|
@ -208,19 +208,19 @@ export default {
|
|||
smtpBCC: "숨은 참조",
|
||||
discord: "Discord",
|
||||
"Discord Webhook URL": "Discord Webhook URL",
|
||||
wayToGetDiscordURL: "서버 설정 -> 연동 -> 웹후크 보기 -> 새 웹후크에서 얻을 수 있어요.",
|
||||
wayToGetDiscordURL: "서버 설정 -> 연동 -> 웹후크 보기 -> 새 웹후크에서 얻을 수 있어요!",
|
||||
"Bot Display Name": "표시 이름",
|
||||
"Prefix Custom Message": "접두사 메시지",
|
||||
"Hello @everyone is...": "{'@'}everyone 서버 상태 알림이에요...",
|
||||
teams: "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "{0}에서 Webhook을 어떻게 만드는지 알아봐요.",
|
||||
wayToGetTeamsURL: "{0}에서 Webhook을 어떻게 만드는지 알아보세요!",
|
||||
signal: "Signal",
|
||||
Number: "숫자",
|
||||
Recipients: "받는 사람",
|
||||
needSignalAPI: "REST API를 사용하는 Signal 클라이언트가 있어야 해요.",
|
||||
wayToCheckSignalURL: "밑에 URL을 확인해 URL 설정 방법을 볼 수 있어요.",
|
||||
signalImportant: "중요: 받는 사람의 그룹과 숫자는 섞을 수 없어요!",
|
||||
signalImportant: "경고: 받는 사람의 그룹과 숫자는 섞을 수 없어요!",
|
||||
gotify: "Gotify",
|
||||
"Application Token": "애플리케이션 토큰",
|
||||
"Server URL": "서버 URL",
|
||||
|
@ -230,8 +230,8 @@ export default {
|
|||
"Channel Name": "채널 이름",
|
||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||
aboutWebhooks: "Webhook에 대한 설명: {0}",
|
||||
aboutChannelName: "Webhook 채널을 우회하려면 {0} 채널 이름칸에 채널 이름을 입력해주세요. 예: #기타-채널",
|
||||
aboutKumaURL: "Uptime Kuma URL칸을 공백으로 두면 기본적으로 Project Github 페이지로 설정해요.",
|
||||
aboutChannelName: "Webhook 채널을 무시하려면 {0} 채널 이름칸에 채널 이름을 입력해주세요. 예: #기타-채널",
|
||||
aboutKumaURL: "Uptime Kuma URL칸을 공백으로 두면 기본적으로 Github Project 페이지로 설정해요.",
|
||||
emojiCheatSheet: "이모지 목록 시트: {0}",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
|
@ -243,8 +243,8 @@ export default {
|
|||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "사용자 키",
|
||||
Device: "장치",
|
||||
"User Key": "유저 키",
|
||||
Device: "디바이스",
|
||||
"Message Title": "메시지 제목",
|
||||
"Notification Sound": "알림음",
|
||||
"More info on:": "자세한 정보: {0}",
|
||||
|
@ -254,7 +254,7 @@ export default {
|
|||
octopushTypePremium: "프리미엄 (빠름) - 알림 기능에 적합해요)",
|
||||
octopushTypeLowCost: "저렴한 요금 (느림) - 가끔 차단될 수 있어요)",
|
||||
"Check octopush prices": "{0}에서 Octopush 가격을 확인할 수 있어요.",
|
||||
octopushPhoneNumber: "휴대전화 번호 (intl format, eg : +33612345678) ",
|
||||
octopushPhoneNumber: "휴대전화 번호 (intl format, 예시: +821023456789) ",
|
||||
octopushSMSSender: "보내는 사람 이름 : 3-11개의 영숫자 및 여백공간 (a-z, A-Z, 0-9)",
|
||||
"LunaSea Device ID": "LunaSea 장치 ID",
|
||||
"Apprise URL": "Apprise URL",
|
||||
|
@ -324,17 +324,17 @@ export default {
|
|||
Content: "내용",
|
||||
Style: "스타일",
|
||||
info: "정보",
|
||||
warning: "경고",
|
||||
danger: "위험",
|
||||
warning: "주의",
|
||||
danger: "경고",
|
||||
primary: "기본",
|
||||
light: "라이트",
|
||||
light: "화이트",
|
||||
dark: "다크",
|
||||
Post: "올리기",
|
||||
Post: "게시",
|
||||
"Please input title and content": "제목과 내용을 작성해주세요.",
|
||||
Created: "생성 날짜",
|
||||
"Last Updated": "마지막 업데이트",
|
||||
Unpin: "제거",
|
||||
"Switch to Light Theme": "라이트 테마로 전환",
|
||||
"Switch to Light Theme": "화이트 테마로 전환",
|
||||
"Switch to Dark Theme": "다크 테마로 전환",
|
||||
"Show Tags": "태그 보이기",
|
||||
"Hide Tags": "태그 숨기기",
|
||||
|
@ -361,8 +361,8 @@ export default {
|
|||
topicExplanation: "모니터링할 MQTT Topic",
|
||||
successMessage: "성공 메시지",
|
||||
successMessageExplanation: "성공으로 간주되는 MQTT 메시지",
|
||||
error: "error",
|
||||
critical: "critical",
|
||||
error: "오류",
|
||||
critical: "크리티컬",
|
||||
Customize: "커스터마이즈",
|
||||
"Custom Footer": "커스텀 Footer",
|
||||
"Custom CSS": "커스텀 CSS",
|
||||
|
@ -406,7 +406,7 @@ export default {
|
|||
PhoneNumbers: "휴대전화 번호",
|
||||
TemplateCode: "템플릿 코드",
|
||||
SignName: "SignName",
|
||||
"Sms template must contain parameters: ": "Sms 템플릿은 다음과 같은 파라미터가 포함되어야 해요:",
|
||||
"Sms template must contain parameters: ": "SMS 템플릿은 다음과 같은 파라미터가 포함되어야 해요:",
|
||||
"Bark Endpoint": "Bark Endpoint",
|
||||
WebHookUrl: "웹훅 URL",
|
||||
SecretKey: "Secret Key",
|
||||
|
@ -518,14 +518,14 @@ export default {
|
|||
"Show update if available": "사용 가능한 경우에 업데이트 표시",
|
||||
"Also check beta release": "베타 릴리즈 확인",
|
||||
"Using a Reverse Proxy?": "리버스 프록시를 사용하시나요?",
|
||||
"Check how to config it for WebSocket": "웹소켓에 대한 설정 방법 확인",
|
||||
"Check how to config it for WebSocket": "웹소켓 대한 설정 방법",
|
||||
"Steam Game Server": "스팀 게임 서버",
|
||||
"Most likely causes:": "원인:",
|
||||
"The resource is no longer available.": "더이상 사용할 수 없어요.",
|
||||
"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",
|
||||
"Coming Soon": "Coming Soon...",
|
||||
wayToGetClickSendSMSToken: "{0}에서 API 사용자 이름과 키를 얻을 수 있어요.",
|
||||
};
|
||||
|
|
|
@ -90,8 +90,11 @@ export default {
|
|||
"New Password": "Nieuw wachtwoord",
|
||||
"Repeat New Password": "Herhaal nieuw wachtwoord",
|
||||
"Update Password": "Vernieuw wachtwoord",
|
||||
"Disable Auth": "Autorisatie uitschakelen",
|
||||
"Enable Auth": "Autorisatie inschakelen",
|
||||
"Disable Auth": "Authenticatie uitschakelen",
|
||||
"Enable Auth": "Authenticatie inschakelen",
|
||||
"disableauth.message1": "Weet je zeker dat je <strong>authenticatie wilt uitschakelen</strong>?",
|
||||
"disableauth.message2": "Er zijn omstandigheden waarbij je <strong>authenticatie door derden wilt implementeren</strong> voor Uptime Kuma, zoals Cloudflare Access, Authelia of andere authenticatiemechanismen.",
|
||||
"Please use this option carefully!": "Gebruik deze optie zorgvuldig!",
|
||||
Logout: "Uitloggen",
|
||||
Leave: "Vertrekken",
|
||||
"I understand, please disable": "Ik begrijp het, schakel a.u.b. uit",
|
||||
|
@ -351,7 +354,7 @@ export default {
|
|||
Discard: "Weggooien",
|
||||
Cancel: "Annuleren",
|
||||
"Powered by": "Mogelijk gemaakt door",
|
||||
shrinkDatabaseDescription: "Trigger database VACUUM voor SQLite. Als de database na 1.10.0 gemaakt is, dan is AUTO_VACUUM al aangezet en deze actie niet nodig.",
|
||||
shrinkDatabaseDescription: "Activeer database VACUUM voor SQLite. Als de database na 1.10.0 aangemaakt is, dan staat AUTO_VACUUM al aan en is deze actie niet nodig.",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
serwersmsAPIUser: "API Gebruikersnaam (incl. webapi_ prefix)",
|
||||
serwersmsAPIPassword: "API Wachtwoord",
|
||||
|
@ -386,7 +389,7 @@ export default {
|
|||
proxyDescription: "Proxies moeten worden toegewezen aan een monitor om te functioneren.",
|
||||
enableProxyDescription: "Deze proxy heeft geen effect op monitor verzoeken totdat het is geactiveerd. Je kunt tijdelijk de proxy uitschakelen voor alle monitors voor activatie status.",
|
||||
setAsDefaultProxyDescription: "Deze proxy wordt standaard aangezet voor alle nieuwe monitors. Je kunt nog steeds de proxy apart uitschakelen voor elke monitor.",
|
||||
"Certificate Chain": "Certificaat Chain",
|
||||
"Certificate Chain": "Certificaatketen",
|
||||
Valid: "Geldig",
|
||||
Invalid: "Ongeldig",
|
||||
AccessKeyId: "AccessKey ID",
|
||||
|
@ -407,7 +410,7 @@ export default {
|
|||
High: "Hoog",
|
||||
Retry: "Opnieuw",
|
||||
Topic: "Onderwerp",
|
||||
"WeCom Bot Key": "WeCom Bot Sleutel",
|
||||
"WeCom Bot Key": "WeCom Bot Key",
|
||||
"Setup Proxy": "Proxy instellen",
|
||||
"Proxy Protocol": "Proxy Protocol",
|
||||
"Proxy Server": "Proxy Server",
|
||||
|
@ -449,7 +452,6 @@ export default {
|
|||
"Issuer:": "Uitgever:",
|
||||
"Fingerprint:": "Vingerafruk:",
|
||||
"No status pages": "Geen status pagina's",
|
||||
"Domain Name Expiry Notification": "Domein Naam Verloop Notificatie",
|
||||
Proxy: "Proxy",
|
||||
"Date Created": "Datum Aangemaakt",
|
||||
onebotHttpAddress: "OneBot HTTP Adres",
|
||||
|
@ -460,6 +462,70 @@ export default {
|
|||
onebotSafetyTips: "Voor de veiligheid moet een toegangssleutel worden ingesteld",
|
||||
"PushDeer Key": "PushDeer Key",
|
||||
"Footer Text": "Footer Tekst",
|
||||
"Show Powered By": "Laat 'Mogeljik gemaakt door' zien",
|
||||
"Show Powered By": "Laat \"Mogeljik gemaakt door\" zien",
|
||||
"Domain Names": "Domein Namen",
|
||||
"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)",
|
||||
dnsPortDescription: "DNS-serverpoort. Standaard ingesteld op 53. Je kunt de poort op elk moment wijzigen.",
|
||||
error: "fout",
|
||||
critical: "kritisch",
|
||||
wayToGetPagerDutyKey: "Je kunt dit krijgen door naar Service -> Service Directory -> (Selecteer een service) -> Integraties -> Integratie toevoegen te gaan. Hier kunt u zoeken naar \"Events API V2\". Meer informatie {0}",
|
||||
"Integration Key": "Integration Key",
|
||||
"Integration URL": "Integration URL",
|
||||
"Auto resolve or acknowledged": "Automatisch oplossen of bevestigen",
|
||||
"do nothing": "niets doen",
|
||||
"auto acknowledged": "automatisch bevestigen",
|
||||
"auto resolve": "automatisch oplossen",
|
||||
Authentication: "authenticatie",
|
||||
signedInDisp: "Aangemeld als {0}",
|
||||
signedInDispDisabled: "Authenticatie uitgeschakeld.",
|
||||
"Certificate Expiry Notification": "Melding over verlopen certificaat",
|
||||
"Recipient Number": "Nummer ontvanger",
|
||||
"From Name/Number": "Van naam/nummer",
|
||||
"Leave blank to use a shared sender number.": "Laat leeg om een gedeeld afzendernummer te gebruiken.",
|
||||
endpoint: "endpoint",
|
||||
pushyAPIKey: "Secret API Key",
|
||||
pushyToken: "Device token",
|
||||
"Show update if available": "Update weergeven indien beschikbaar",
|
||||
"Also check beta release": "Controleer ook de bètaversies",
|
||||
"Using a Reverse Proxy?": "Een reverse proxy gebruiken?",
|
||||
"Check how to config it for WebSocket": "Controleer hoe je het configureert voor een WebSocket",
|
||||
"Steam Game Server": "Steam gameserver",
|
||||
"Most likely causes:": "Meest waarschijnlijke oorzaken:",
|
||||
"The resource is no longer available.": "De paginabron is niet langer beschikbaar.",
|
||||
"There might be a typing error in the address.": "Er zit een typefout in het de URL.",
|
||||
"What you can try:": "Wat je kan proberen:",
|
||||
"Retype the address.": "De URL controleren en/of opnnieuw typen.",
|
||||
"Go back to the previous page.": "Terug naar de vorige pagina.",
|
||||
"Coming Soon": "Binnenkort beschikbaar",
|
||||
wayToGetClickSendSMSToken: "Je kan een API Username en API Key krijgen vanuit {0} .",
|
||||
"Connection String": "Connection String",
|
||||
Query: "Query",
|
||||
settingsCertificateExpiry: "TLS Certificate Expiry",
|
||||
certificationExpiryDescription: "HTTPS Monitors trigger notification when TLS certificate expires in:",
|
||||
"ntfy Topic": "ntfy Topic",
|
||||
Domain: "Domein",
|
||||
Workstation: "Werkstation",
|
||||
disableCloudflaredNoAuthMsg: "De \"Geen authenticatie\" modus staat aan, wachtwoord is niet vereist.",
|
||||
};
|
||||
|
|
203
src/languages/pt-PT.js
Normal file
203
src/languages/pt-PT.js
Normal file
|
@ -0,0 +1,203 @@
|
|||
export default {
|
||||
languageName: "Português (Portugal)",
|
||||
checkEverySecond: "Verificar a cada {0} segundos.",
|
||||
retryCheckEverySecond: "Tentar novamente a cada {0} segundos.",
|
||||
retriesDescription: "Máximo de tentativas antes que o serviço seja marcado como inativo e uma notificação seja enviada",
|
||||
ignoreTLSError: "Ignorar erros TLS/SSL para sites HTTPS",
|
||||
upsideDownModeDescription: "Inverte o status de cabeça para baixo. Se o serviço estiver acessível, ele está OFFLINE.",
|
||||
maxRedirectDescription: "Número máximo de redirecionamentos a seguir. Define como 0 para desativar redirecionamentos.",
|
||||
acceptedStatusCodesDescription: "Seleciona os códigos de status que são considerados uma resposta bem-sucedida.",
|
||||
passwordNotMatchMsg: "A senha repetida não corresponde.",
|
||||
notificationDescription: "Atribuir uma notificação ao (s) monitor (es) para que funcione.",
|
||||
keywordDescription: "Pesquisa a palavra-chave em HTML simples ou resposta JSON e diferencia maiúsculas de minúsculas",
|
||||
pauseDashboardHome: "Pausa",
|
||||
deleteMonitorMsg: "Tens a certeza de que queres excluir este monitor?",
|
||||
deleteNotificationMsg: "Tens a certeza de que queres excluir esta notificação para todos os monitores?",
|
||||
resolverserverDescription: "A Cloudflare é o servidor padrão, podes alterar o servidor 'resolvedor' a qualquer momento.",
|
||||
rrtypeDescription: "Seleciona o RR-Type que queres monitorizar",
|
||||
pauseMonitorMsg: "Tens a certeza que queres fazer uma pausa?",
|
||||
enableDefaultNotificationDescription: "Para cada monitor novo esta notificação vai estar activa por padrão. Podes também desativar a notificação separadamente para cada monitor.",
|
||||
clearEventsMsg: "Tens a certeza que queres excluir todos os eventos deste monitor?",
|
||||
clearHeartbeatsMsg: "Tens a certeza de que queres excluir todos os heartbeats deste monitor?",
|
||||
confirmClearStatisticsMsg: "Tens a certeza que queres excluir TODAS as estatísticas?",
|
||||
importHandleDescription: "Escolhe 'Ignorar existente' se quiseres ignorar todos os monitores ou notificações com o mesmo nome. 'Substituir' excluirá todos os monitores e notificações existentes.",
|
||||
confirmImportMsg: "Tens a certeza que queres importar o backup? Certifica-te que selecionaste a opção de importação correta.",
|
||||
twoFAVerifyLabel: "Insire o teu token para verificares se o 2FA está a funcionar",
|
||||
tokenValidSettingsMsg: "O token é válido! Agora podes salvar as configurações do 2FA.",
|
||||
confirmEnableTwoFAMsg: "Tens a certeza de que queres habilitar 2FA?",
|
||||
confirmDisableTwoFAMsg: "Tens a certeza de que queres desativar 2FA?",
|
||||
Settings: "Configurações",
|
||||
Dashboard: "Dashboard",
|
||||
"New Update": "Nova Atualização",
|
||||
Language: "Linguagem",
|
||||
Appearance: "Aparência",
|
||||
Theme: "Tema",
|
||||
General: "Geral",
|
||||
Version: "Versão",
|
||||
"Check Update On GitHub": "Verificar atualização no Github",
|
||||
List: "Lista",
|
||||
Add: "Adicionar",
|
||||
"Add New Monitor": "Adicionar novo monitor",
|
||||
"Quick Stats": "Estatísticas rápidas",
|
||||
Up: "On",
|
||||
Down: "Off",
|
||||
Pending: "Pendente",
|
||||
Unknown: "Desconhecido",
|
||||
Pause: "Pausa",
|
||||
Name: "Nome",
|
||||
Status: "Status",
|
||||
DateTime: "Data hora",
|
||||
Message: "Mensagem",
|
||||
"No important events": "Nenhum evento importante",
|
||||
Resume: "Resumo",
|
||||
Edit: "Editar",
|
||||
Delete: "Apagar",
|
||||
Current: "Atual",
|
||||
Uptime: "Tempo de atividade",
|
||||
"Cert Exp.": "Cert Exp.",
|
||||
day: "dia | dias",
|
||||
"-day": "-dia",
|
||||
hour: "hora",
|
||||
"-hour": "-hora",
|
||||
Response: "Resposta",
|
||||
Ping: "Ping",
|
||||
"Monitor Type": "Tipo de Monitor",
|
||||
Keyword: "Palavra-Chave",
|
||||
"Friendly Name": "Nome Amigável",
|
||||
URL: "URL",
|
||||
Hostname: "Hostname",
|
||||
Port: "Porta",
|
||||
"Heartbeat Interval": "Intervalo de Heartbeats",
|
||||
Retries: "Novas tentativas",
|
||||
"Heartbeat Retry Interval": "Intervalo de repetição de Heartbeats",
|
||||
Advanced: "Avançado",
|
||||
"Upside Down Mode": "Modo de cabeça para baixo",
|
||||
"Max. Redirects": "Redirecionamento Máx.",
|
||||
"Accepted Status Codes": "Status Code Aceitáveis",
|
||||
Save: "Guardar",
|
||||
Notifications: "Notificações",
|
||||
"Not available, please setup.": "Não disponível, por favor configura.",
|
||||
"Setup Notification": "Configurar Notificação",
|
||||
Light: "Claro",
|
||||
Dark: "Escuro",
|
||||
Auto: "Auto",
|
||||
"Theme - Heartbeat Bar": "Tema - Barra de Heartbeat",
|
||||
Normal: "Normal",
|
||||
Bottom: "Inferior",
|
||||
None: "Nenhum",
|
||||
Timezone: "Fuso horário",
|
||||
"Search Engine Visibility": "Visibilidade do mecanismo de pesquisa",
|
||||
"Allow indexing": "Permitir Indexação",
|
||||
"Discourage search engines from indexing site": "Desencorajar que motores de busca indexem o site",
|
||||
"Change Password": "Mudar senha",
|
||||
"Current Password": "Senha atual",
|
||||
"New Password": "Nova Senha",
|
||||
"Repeat New Password": "Repetir Nova Senha",
|
||||
"Update Password": "Atualizar Senha",
|
||||
"Disable Auth": "Desativar Autenticação",
|
||||
"Enable Auth": "Ativar Autenticação",
|
||||
"disableauth.message1": "Tens a certeza que queres <strong>desativar a autenticação</strong>?",
|
||||
"disableauth.message2": "Isso é para <strong>alguém que tem autenticação de terceiros</strong> em frente ao 'UpTime Kuma' como o Cloudflare Access.",
|
||||
"Please use this option carefully!": "Por favor, utiliza esta opção com cuidado.",
|
||||
Logout: "Logout",
|
||||
Leave: "Sair",
|
||||
"I understand, please disable": "Eu entendo, por favor desativa.",
|
||||
Confirm: "Confirmar",
|
||||
Yes: "Sim",
|
||||
No: "Não",
|
||||
Username: "Utilizador",
|
||||
Password: "Senha",
|
||||
"Remember me": "Lembra-me",
|
||||
Login: "Autenticar",
|
||||
"No Monitors, please": "Nenhum monitor, por favor",
|
||||
"add one": "adicionar um",
|
||||
"Notification Type": "Tipo de Notificação",
|
||||
Email: "Email",
|
||||
Test: "Testar",
|
||||
"Certificate Info": "Info. do Certificado ",
|
||||
"Resolver Server": "Resolver Servidor",
|
||||
"Resource Record Type": "Tipo de registro de aplicação",
|
||||
"Last Result": "Último resultado",
|
||||
"Create your admin account": "Cria a tua conta de admin",
|
||||
"Repeat Password": "Repete a senha",
|
||||
"Import Backup": "Importar Backup",
|
||||
"Export Backup": "Exportar Backup",
|
||||
Export: "Exportar",
|
||||
Import: "Importar",
|
||||
respTime: "Tempo de Resp. (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
"Default enabled": "Padrão habilitado",
|
||||
"Apply on all existing monitors": "Aplicar em todos os monitores existentes",
|
||||
Create: "Criar",
|
||||
"Clear Data": "Limpar Dados",
|
||||
Events: "Eventos",
|
||||
Heartbeats: "Heartbeats",
|
||||
"Auto Get": "Obter Automático",
|
||||
backupDescription: "Podes fazer backup de todos os monitores e todas as notificações num arquivo JSON.",
|
||||
backupDescription2: "OBS: Os dados do histórico e do evento não estão incluídos.",
|
||||
backupDescription3: "Dados confidenciais, como tokens de notificação, estão incluídos no arquivo de exportação, mantem-no com cuidado.",
|
||||
alertNoFile: "Seleciona um arquivo para importar.",
|
||||
alertWrongFileType: "Seleciona um arquivo JSON.",
|
||||
"Clear all statistics": "Limpar todas as estatísticas",
|
||||
"Skip existing": "Saltar existente",
|
||||
Overwrite: "Sobrescrever",
|
||||
Options: "Opções",
|
||||
"Keep both": "Manter os dois",
|
||||
"Verify Token": "Verificar Token",
|
||||
"Setup 2FA": "Configurar 2FA",
|
||||
"Enable 2FA": "Ativar 2FA",
|
||||
"Disable 2FA": "Desativar 2FA",
|
||||
"2FA Settings": "Configurações do 2FA ",
|
||||
"Two Factor Authentication": "Autenticação de Dois Fatores",
|
||||
Active: "Ativo",
|
||||
Inactive: "Inativo",
|
||||
Token: "Token",
|
||||
"Show URI": "Mostrar URI",
|
||||
Tags: "Tag",
|
||||
"Add New below or Select...": "Adicionar Novo abaixo ou Selecionar ...",
|
||||
"Tag with this name already exist.": "Já existe uma etiqueta com este nome.",
|
||||
"Tag with this value already exist.": "Já existe uma etiqueta com este valor.",
|
||||
color: "cor",
|
||||
"value (optional)": "valor (opcional)",
|
||||
Gray: "Cinza",
|
||||
Red: "Vermelho",
|
||||
Orange: "Laranja",
|
||||
Green: "Verde",
|
||||
Blue: "Azul",
|
||||
Indigo: "Índigo",
|
||||
Purple: "Roxo",
|
||||
Pink: "Rosa",
|
||||
"Search...": "Pesquisa...",
|
||||
"Avg. Ping": "Ping Médio.",
|
||||
"Avg. Response": "Resposta Média. ",
|
||||
"Status Page": "Página de Status",
|
||||
"Status Pages": "Página de Status",
|
||||
"Entry Page": "Página de entrada",
|
||||
statusPageNothing: "Nada aqui, por favor, adiciona um grupo ou monitor.",
|
||||
"No Services": "Nenhum Serviço",
|
||||
"All Systems Operational": "Todos os Serviços Operacionais",
|
||||
"Partially Degraded Service": "Serviço parcialmente degradados",
|
||||
"Degraded Service": "Serviço Degradado",
|
||||
"Add Group": "Adicionar Grupo",
|
||||
"Add a monitor": "Adicionar um monitor",
|
||||
"Edit Status Page": "Editar Página de Status",
|
||||
"Go to Dashboard": "Ir para o dashboard",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "Email (SMTP)",
|
||||
discord: "Discord",
|
||||
teams: "Microsoft Teams",
|
||||
signal: "Signal",
|
||||
gotify: "Gotify",
|
||||
slack: "Slack",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
};
|
|
@ -184,8 +184,8 @@ export default {
|
|||
"Add a monitor": "Dodaj monitor",
|
||||
"Edit Status Page": "Uredi statusno stran",
|
||||
"Go to Dashboard": "Pojdi na nadzorno ploščo",
|
||||
"Status Page": "Página de Status",
|
||||
"Status Pages": "Página de Status",
|
||||
"Status Page": "Statusna stran",
|
||||
"Status Pages": "Statusne strani",
|
||||
defaultNotificationName: "Moje {notification} Obvestilo ({number})",
|
||||
here: "tukaj",
|
||||
Required: "Obvezno",
|
||||
|
|
|
@ -518,4 +518,5 @@ export default {
|
|||
"Go back to the previous page.": "กลับไปที่หน้าก่อนหน้า",
|
||||
"Coming Soon": "เร็ว ๆ นี้",
|
||||
wayToGetClickSendSMSToken: "คุณสามารถรับ API Username และ API Key ได้จาก {0}",
|
||||
wayToGetLineNotifyToken: "คุณสามารถรับ access token ได้จาก {0}",
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
languageName: "Український",
|
||||
languageName: "Українська",
|
||||
checkEverySecond: "Перевірка кожні {0} секунд",
|
||||
retriesDescription: "Максимальна кількість спроб перед позначенням сервісу як недоступного та надсиланням повідомлення",
|
||||
ignoreTLSError: "Ігнорувати помилку TLS/SSL для сайтів HTTPS",
|
||||
|
@ -7,11 +7,11 @@ export default {
|
|||
maxRedirectDescription: "Максимальна кількість перенаправлень. Поставте 0, щоб вимкнути перенаправлення.",
|
||||
acceptedStatusCodesDescription: "Виберіть коди статусів для визначення доступності сервісу.",
|
||||
passwordNotMatchMsg: "Повторення паролю не збігається.",
|
||||
notificationDescription: "Прив'яжіть повідомлення до моніторів.",
|
||||
notificationDescription: "Прив'яжіть сповіщення до моніторів.",
|
||||
keywordDescription: "Пошук слова в чистому HTML або JSON-відповіді (чутливо до регістру)",
|
||||
pauseDashboardHome: "Пауза",
|
||||
deleteMonitorMsg: "Ви дійсно хочете видалити цей монітор?",
|
||||
deleteNotificationMsg: "Ви дійсно хочете видалити це повідомлення для всіх моніторів?",
|
||||
deleteNotificationMsg: "Ви дійсно хочете видалити це сповіщення для всіх моніторів?",
|
||||
resolverserverDescription: "Cloudflare є сервером за замовчуванням. Ви завжди можете змінити цей сервер.",
|
||||
rrtypeDescription: "Виберіть тип ресурсного запису, який ви хочете відстежувати",
|
||||
pauseMonitorMsg: "Ви дійсно хочете поставити на паузу?",
|
||||
|
@ -54,7 +54,7 @@ export default {
|
|||
Keyword: "Ключове слово",
|
||||
"Friendly Name": "Ім'я",
|
||||
URL: "URL",
|
||||
Hostname: "Ім'я хоста",
|
||||
Hostname: "Адреса хоста",
|
||||
Port: "Порт",
|
||||
"Heartbeat Interval": "Частота опитування",
|
||||
Retries: "Спроб",
|
||||
|
@ -63,7 +63,7 @@ export default {
|
|||
"Max. Redirects": "Макс. кількість перенаправлень",
|
||||
"Accepted Status Codes": "Припустимі коди статусу",
|
||||
Save: "Зберегти",
|
||||
Notifications: "Повідомлення",
|
||||
Notifications: "Сповіщення",
|
||||
"Not available, please setup.": "Доступних сповіщень немає, необхідно створити.",
|
||||
"Setup Notification": "Створити сповіщення",
|
||||
Light: "Світла",
|
||||
|
@ -100,7 +100,7 @@ export default {
|
|||
"No Monitors, please": "Моніторів немає, будь ласка",
|
||||
"No Monitors": "Монітори відсутні",
|
||||
"add one": "створіть новий",
|
||||
"Notification Type": "Тип повідомлення",
|
||||
"Notification Type": "Тип сповіщення",
|
||||
Email: "Пошта",
|
||||
Test: "Перевірка",
|
||||
"Certificate Info": "Інформація про сертифікат",
|
||||
|
@ -119,7 +119,7 @@ export default {
|
|||
Events: "Події",
|
||||
Heartbeats: "Опитування",
|
||||
"Auto Get": "Авто-отримання",
|
||||
enableDefaultNotificationDescription: "Для кожного нового монітора це повідомлення буде включено за замовчуванням. Ви все ще можете відключити повідомлення в кожному моніторі окремо.",
|
||||
enableDefaultNotificationDescription: "Для кожного нового монітора це сповіщення буде включено за замовчуванням. Ви все ще можете відключити сповіщення в кожному моніторі окремо.",
|
||||
"Default enabled": "Використовувати за промовчанням",
|
||||
"Also apply to existing monitors": "Застосувати до існуючих моніторів",
|
||||
Export: "Експорт",
|
||||
|
@ -170,7 +170,7 @@ export default {
|
|||
Purple: "Пурпурний",
|
||||
Pink: "Рожевий",
|
||||
"Search...": "Пошук...",
|
||||
"Avg. Ping": "Середнє значення пінгу",
|
||||
"Avg. Ping": "Середній пінг",
|
||||
"Avg. Response": "Середній час відповіді",
|
||||
"Entry Page": "Головна сторінка",
|
||||
statusPageNothing: "Тут порожньо. Додайте групу або монітор.",
|
||||
|
@ -210,7 +210,7 @@ export default {
|
|||
"Push URL": "URL пуша",
|
||||
needPushEvery: "До цієї URL необхідно звертатися кожні {0} секунд",
|
||||
pushOptionalParams: "Опціональні параметри: {0}",
|
||||
defaultNotificationName: "Моє повідомлення {notification} ({number})",
|
||||
defaultNotificationName: "Моє сповіщення {notification} ({number})",
|
||||
here: "тут",
|
||||
Required: "Потрібно",
|
||||
"Bot Token": "Токен бота",
|
||||
|
@ -257,7 +257,7 @@ export default {
|
|||
"User Key": "Ключ користувача",
|
||||
Device: "Пристрій",
|
||||
"Message Title": "Заголовок повідомлення",
|
||||
"Notification Sound": "Звук повідомлення",
|
||||
"Notification Sound": "Звук сповіщення",
|
||||
"More info on:": "Більше інформації: {0}",
|
||||
pushoverDesc1: "Екстренний пріоритет (2) має таймуут повтору за замовчуванням 30 секунд і закінчується через 1 годину.",
|
||||
pushoverDesc2: "Якщо ви бажаєте надсилати повідомлення різним пристроям, необхідно заповнити поле Пристрій.",
|
||||
|
@ -354,7 +354,7 @@ export default {
|
|||
"No consecutive dashes --": "Заборонено використовувати тире --",
|
||||
"HTTP Options": "HTTP Опції",
|
||||
Authentication: "Аутентифікація",
|
||||
"HTTP Basic Auth": "HTTP Авторизація",
|
||||
"HTTP Basic Auth": "Базова HTTP",
|
||||
PushByTechulus: "Push by Techulus",
|
||||
clicksendsms: "ClickSend SMS",
|
||||
GoogleChat: "Google Chat (тільки Google Workspace)",
|
||||
|
@ -392,4 +392,139 @@ export default {
|
|||
alertaAlertState: "Стан алерту",
|
||||
alertaRecoverState: "Стан відновлення",
|
||||
deleteStatusPageMsg: "Дійсно хочете видалити цю сторінку статусів?",
|
||||
Proxies: "Проксі",
|
||||
default: "За замовчуванням",
|
||||
enabled: "Активно",
|
||||
setAsDefault: "Встановити за замовчуванням",
|
||||
deleteProxyMsg: "Ви впевнені, що хочете видалити цей проксі для всіх моніторів?",
|
||||
proxyDescription: "Щоб функціонувати, монітору потрібно призначити проксі.",
|
||||
enableProxyDescription: "Цей проксі не впливатиме на запити моніторингу, доки його не буде активовано. Ви можете контролювати тимчасове відключення проксі з усіх моніторів за статусом активації.",
|
||||
setAsDefaultProxyDescription: "Цей проксі буде ввімкнено за умовчанням для нових моніторів. Ви все одно можете вимкнути проксі окремо для кожного монітора.",
|
||||
Invalid: "Недійсний",
|
||||
AccessKeyId: "AccessKey ID",
|
||||
SecretAccessKey: "AccessKey Secret",
|
||||
PhoneNumbers: "PhoneNumbers",
|
||||
TemplateCode: "TemplateCode",
|
||||
SignName: "SignName",
|
||||
"Sms template must contain parameters: ": "Шаблон смс повинен містити параметри: ",
|
||||
"Bark Endpoint": "Bark Endpoint",
|
||||
WebHookUrl: "WebHookUrl",
|
||||
SecretKey: "SecretKey",
|
||||
"For safety, must use secret key": "Для безпеки необхідно використовувати секретний ключ",
|
||||
"Device Token": "Токен пристрою",
|
||||
Platform: "Платформа",
|
||||
iOS: "iOS",
|
||||
Android: "Android",
|
||||
Huawei: "Huawei",
|
||||
High: "Високий",
|
||||
Retry: "Повтор",
|
||||
Topic: "Тема",
|
||||
"WeCom Bot Key": "WeCom Bot ключ",
|
||||
"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",
|
||||
Slug: "Slug",
|
||||
"Accept characters:": "Прийняти символи:",
|
||||
startOrEndWithOnly: "Починається або закінчується лише {0}",
|
||||
"No consecutive dashes": "Немає послідовних тире",
|
||||
"The slug is already taken. Please choose another slug.": "The slug is already taken. Please choose another slug.",
|
||||
"No Proxy": "Без проксі",
|
||||
"Page Not Found": "Сторінку не знайдено",
|
||||
"Reverse Proxy": "Реверсивний проксі",
|
||||
wayToGetCloudflaredURL: "(Завантажити Cloudflare з {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 and Traefik.",
|
||||
"Please read": "Будь ласка, прочитайте",
|
||||
"Subject:": "Тема:",
|
||||
"Valid To:": "Дійсний до:",
|
||||
"Days Remaining:": "Залишилось днів:",
|
||||
"Issuer:": "Емітент:",
|
||||
"Fingerprint:": "Відбиток:",
|
||||
"No status pages": "Немає сторінок статусу",
|
||||
"Domain Name Expiry Notification": "Сповіщення про закінчення терміну дії доменного імені",
|
||||
Proxy: "Проксі",
|
||||
"Date Created": "Дата створення",
|
||||
onebotHttpAddress: "OneBot адреса HTTP",
|
||||
onebotMessageType: "OneBot тип повідомлення",
|
||||
onebotGroupMessage: "Група",
|
||||
onebotPrivateMessage: "Приватне",
|
||||
onebotUserOrGroupId: "Група/Користувач ID",
|
||||
onebotSafetyTips: "Для безпеки необхідно встановити маркер доступу",
|
||||
"PushDeer Key": "PushDeer ключ",
|
||||
"Footer Text": "Текст нижнього колонтитула",
|
||||
"Show 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": "Legacy Octopush-DM",
|
||||
"endpoint": "кінцева точка",
|
||||
octopushAPIKey: "\"Ключ API\" з облікових даних HTTP API в панелі керування",
|
||||
octopushLogin: "\"Ім'я користувача\" з облікових даних HTTP API на панелі керування",
|
||||
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": "Vibrate Only",
|
||||
"pushoversounds none": "None (silent)",
|
||||
pushyAPIKey: "Секретний ключ API",
|
||||
pushyToken: "Токен пристрою",
|
||||
"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": "Незабаром",
|
||||
wayToGetClickSendSMSToken: "Ви можете отримати ім’я користувача API та ключ API з {0} .",
|
||||
"Connection String": "Рядок підключення",
|
||||
"Query": "Запит",
|
||||
settingsCertificateExpiry: "Закінчення терміну дії сертифіката TLS",
|
||||
certificationExpiryDescription: "Запуск сповіщення для HTTPS моніторів коли до закінчення терміну дії TLS сертифіката:",
|
||||
"ntfy Topic": "ntfy Тема",
|
||||
"Domain": "Домен",
|
||||
"Workstation": "Робоча станція",
|
||||
disableCloudflaredNoAuthMsg: "Ви перебуваєте в режимі без авторизації, пароль не потрібен.",
|
||||
};
|
||||
|
|
|
@ -13,6 +13,7 @@ export default {
|
|||
pauseDashboardHome: "暫停",
|
||||
deleteMonitorMsg: "您確定要刪除此監測器嗎?",
|
||||
deleteNotificationMsg: "您確定要為所有監測器刪除此通知嗎?",
|
||||
dnsPortDescription: "DNS 伺服器連接埠。預設為 53。您可以隨時變更連接埠。",
|
||||
resolverserverDescription: "Cloudflare 為預設伺服器。您可以隨時更換解析伺服器。",
|
||||
rrtypeDescription: "選擇您想要監測的資源記錄類型",
|
||||
pauseMonitorMsg: "您確定要暫停嗎?",
|
||||
|
@ -332,6 +333,8 @@ export default {
|
|||
info: "資訊",
|
||||
warning: "警告",
|
||||
danger: "危險",
|
||||
error: "錯誤",
|
||||
critical: "嚴重",
|
||||
primary: "主要",
|
||||
light: "淺色",
|
||||
dark: "暗色",
|
||||
|
@ -372,6 +375,13 @@ export default {
|
|||
smtpDkimHashAlgo: "雜湊演算法 (選填)",
|
||||
smtpDkimheaderFieldNames: "要簽署的郵件標頭 (選填)",
|
||||
smtpDkimskipFields: "不簽署的郵件標頭 (選填)",
|
||||
wayToGetPagerDutyKey: "您可以前往服務 -> 服務目錄 -> (選取服務) -> 整合 -> 新增整合以取得。您可以搜尋 \"Events API V2\"。詳細資訊 {0}",
|
||||
"Integration Key": "整合金鑰",
|
||||
"Integration URL": "整合網址",
|
||||
"Auto resolve or acknowledged": "自動解決或認可",
|
||||
"do nothing": "不進行任何操作",
|
||||
"auto acknowledged": "自動認可",
|
||||
"auto resolve": "自動解決",
|
||||
gorush: "Gorush",
|
||||
alerta: "Alerta",
|
||||
alertaApiEndpoint: "API 端點",
|
||||
|
@ -465,4 +475,65 @@ export default {
|
|||
"Footer Text": "頁尾文字",
|
||||
"Show 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": "端",
|
||||
octopushAPIKey: "\"API key\" from HTTP API credentials in control panel",
|
||||
octopushLogin: "\"Login\" from HTTP API credentials in control panel",
|
||||
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": "Piano Bar",
|
||||
"pushoversounds siren": "Siren",
|
||||
"pushoversounds spacealarm": "Space Alarm",
|
||||
"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": "檢查 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": "即將推出",
|
||||
wayToGetClickSendSMSToken: "您可以從 {0} 取得 API 使用者名稱和金鑰。",
|
||||
"Connection String": "連線字串",
|
||||
"Query": "查詢",
|
||||
settingsCertificateExpiry: "TLS 憑證到期",
|
||||
certificationExpiryDescription: "TLS 將於 X 天後到期時觸發 HTTPS 監測器通知:",
|
||||
"ntfy Topic": "ntfy 主題",
|
||||
"Domain": "網域",
|
||||
"Workstation": "工作站",
|
||||
disableCloudflaredNoAuthMsg: "您處於無驗證模式。無須輸入密碼。",
|
||||
};
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
|
||||
<!-- Mobile Only -->
|
||||
<div v-if="$root.isMobile" style="width: 100%; height: 60px;" />
|
||||
<nav v-if="$root.isMobile" class="bottom-nav">
|
||||
<nav v-if="$root.isMobile && $root.loggedIn" class="bottom-nav">
|
||||
<router-link to="/dashboard" class="nav-link">
|
||||
<div><font-awesome-icon icon="tachometer-alt" /></div>
|
||||
{{ $t("Dashboard") }}
|
||||
|
|
|
@ -601,6 +601,28 @@ export default {
|
|||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Frontend Version
|
||||
* It should be compiled to a static value while building the frontend.
|
||||
* Please see ./config/vite.config.js, it is defined via vite.js
|
||||
* @returns {string}
|
||||
*/
|
||||
frontendVersion() {
|
||||
// eslint-disable-next-line no-undef
|
||||
return FRONTEND_VERSION;
|
||||
},
|
||||
|
||||
/**
|
||||
* Are both frontend and backend in the same version?
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isFrontendBackendVersionMatched() {
|
||||
if (!this.info.version) {
|
||||
return true;
|
||||
}
|
||||
return this.info.version === this.frontendVersion;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
<option value="sqlserver">
|
||||
SQL Server
|
||||
</option>
|
||||
<option value="postgres">
|
||||
PostgreSQL
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
@ -168,15 +171,21 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<!-- SQL Server -->
|
||||
<template v-if="monitor.type === 'sqlserver'">
|
||||
<!-- SQL Server and PostgreSQL -->
|
||||
<template v-if="monitor.type === 'sqlserver' || monitor.type === 'postgres'">
|
||||
<div class="my-3">
|
||||
<label for="sqlserverConnectionString" class="form-label">SQL Server {{ $t("Connection String") }}</label>
|
||||
<input id="sqlserverConnectionString" v-model="monitor.databaseConnectionString" type="text" class="form-control">
|
||||
<label for="sqlConnectionString" class="form-label">{{ $t("Connection String") }}</label>
|
||||
|
||||
<template v-if="monitor.type === 'sqlserver'">
|
||||
<input id="sqlConnectionString" v-model="monitor.databaseConnectionString" type="text" class="form-control" placeholder="Server=<hostname>,<port>;Database=<your database>;User Id=<your user id>;Password=<your password>;Encrypt=<true/false>;TrustServerCertificate=<Yes/No>;Connection Timeout=<int>">
|
||||
</template>
|
||||
<template v-if="monitor.type === 'postgres'">
|
||||
<input id="sqlConnectionString" v-model="monitor.databaseConnectionString" type="text" class="form-control" placeholder="postgres://username:password@host:port/database">
|
||||
</template>
|
||||
</div>
|
||||
<div class="my-3">
|
||||
<label for="sqlserverQuery" class="form-label">SQL Server {{ $t("Query") }}</label>
|
||||
<textarea id="sqlserverQuery" v-model="monitor.databaseQuery" class="form-control" placeholder="Example: select getdate()"></textarea>
|
||||
<label for="sqlQuery" class="form-label">{{ $t("Query") }}</label>
|
||||
<textarea id="sqlQuery" v-model="monitor.databaseQuery" class="form-control" placeholder="Example: select getdate()"></textarea>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -584,7 +593,6 @@ export default {
|
|||
method: "GET",
|
||||
interval: 60,
|
||||
retryInterval: this.interval,
|
||||
databaseConnectionString: "Server=<hostname>,<port>;Database=<your database>;User Id=<your user id>;Password=<your password>;Encrypt=<true/false>;TrustServerCertificate=<Yes/No>;Connection Timeout=<int>",
|
||||
maxretries: 0,
|
||||
notificationIDList: {},
|
||||
ignoreTls: false,
|
||||
|
|
Loading…
Reference in a new issue