1
0
mirror of https://github.com/louislam/uptime-kuma.git synced 2024-12-22 22:13:20 +02:00

Merge branch 'master' into 1.23.14-to-2.0.0

# Conflicts:
#	package-lock.json
This commit is contained in:
Louis Lam 2024-09-29 22:12:25 +08:00
commit 030bb1c0b8
130 changed files with 6023 additions and 837 deletions

View File

@ -1,28 +0,0 @@
# Codespaces
You can modifiy Uptime Kuma in your browser without setting up a local development.
![image](https://github.com/louislam/uptime-kuma/assets/1336778/31d9f06d-dd0b-4405-8e0d-a96586ee4595)
1. Click `Code` -> `Create codespace on master`
2. Wait a few minutes until you see there are two exposed ports
3. Go to the `3000` url, see if it is working
![image](https://github.com/louislam/uptime-kuma/assets/1336778/909b2eb4-4c5e-44e4-ac26-6d20ed856e7f)
## Frontend
Since the frontend is using [Vite.js](https://vitejs.dev/), all changes in this area will be hot-reloaded.
You don't need to restart the frontend, unless you try to add a new frontend dependency.
## Backend
The backend does not automatically hot-reload.
You will need to restart the backend after changing something using these steps:
1. Click `Terminal`
2. Click `Codespaces: server-dev` in the right panel
3. Press `Ctrl + C` to stop the server
4. Press `Up` to run `npm run start-server-dev`
![image](https://github.com/louislam/uptime-kuma/assets/1336778/e0c0a350-fe46-4588-9f37-e053c85834d1)

View File

@ -1,23 +0,0 @@
{
"image": "mcr.microsoft.com/devcontainers/javascript-node:dev-18-bookworm",
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"updateContentCommand": "npm ci",
"postCreateCommand": "",
"postAttachCommand": {
"frontend-dev": "npm run start-frontend-devcontainer",
"server-dev": "npm run start-server-dev",
"open-port": "gh codespace ports visibility 3001:public -c $CODESPACE_NAME"
},
"customizations": {
"vscode": {
"extensions": [
"streetsidesoftware.code-spell-checker",
"dbaeumer.vscode-eslint",
"GitHub.copilot-chat"
]
}
},
"forwardPorts": [3000, 3001]
}

View File

@ -17,7 +17,6 @@ README.md
.vscode
.eslint*
.stylelint*
/.devcontainer
/.github
yarn.lock
app.json

View File

@ -9,7 +9,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v8
- uses: actions/stale@v9
with:
stale-issue-message: |-
We are clearing up our old `help`-issues and your issue has been open for 60 days with no activity.
@ -21,7 +21,7 @@ jobs:
exempt-issue-labels: 'News,Medium,High,discussion,bug,doc,feature-request'
exempt-issue-assignees: 'louislam'
operations-per-run: 200
- uses: actions/stale@v8
- uses: actions/stale@v9
with:
stale-issue-message: |-
This issue was marked as `cannot-reproduce` by a maintainer.

View File

@ -127,7 +127,7 @@ Different guidelines exist for different types of pull requests (PRs):
- `server/monitor-types/MONITORING_TYPE.js` is the core of each monitor.
the `async check(...)`-function should:
- throw an error for each fault that is detected with an actionable error message
- in the happy-path, you should set `heartbeat.msg` to a successfull message and set `heartbeat.status = UP`
- in the happy-path, you should set `heartbeat.msg` to a successful message and set `heartbeat.status = UP`
- `server/uptime-kuma-server.js` is where the monitoring backend needs to be registered.
*If you have an idea how we can skip this step, we would love to hear about it ^^*
- `src/pages/EditMonitor.vue` is the shared frontend users interact with.
@ -236,12 +236,6 @@ The goal is to make the Uptime Kuma installation as easy as installing a mobile
- IDE that supports [`ESLint`](https://eslint.org/) and EditorConfig (I am using [`IntelliJ IDEA`](https://www.jetbrains.com/idea/))
- A SQLite GUI tool (f.ex. [`SQLite Expert Personal`](https://www.sqliteexpert.com/download.html) or [`DBeaver Community`](https://dbeaver.io/download/))
### GitHub Codespaces
If you don't want to setup an local environment, you can now develop on GitHub Codespaces, read more:
https://github.com/louislam/uptime-kuma/tree/master/.devcontainer
## Git Branches
- `master`: 2.X.X development. If you want to add a new feature, your pull request should base on this.

View File

@ -1,11 +1,11 @@
import { defineConfig, devices } from "@playwright/test";
const port = 30001;
const url = `http://localhost:${port}`;
export const url = `http://localhost:${port}`;
export default defineConfig({
// Look for test files in the "tests" directory, relative to this configuration file.
testDir: "../test/e2e",
testDir: "../test/e2e/specs",
outputDir: "../private/playwright-test-results",
fullyParallel: false,
locale: "en-US",
@ -40,9 +40,15 @@ export default defineConfig({
// Configure projects for major browsers.
projects: [
{
name: "chromium",
name: "run-once setup",
testMatch: /setup-process\.once\.js/,
use: { ...devices["Desktop Chrome"] },
},
{
name: "specs",
use: { ...devices["Desktop Chrome"] },
dependencies: [ "run-once setup" ],
},
/*
{
name: "firefox",
@ -52,7 +58,7 @@ export default defineConfig({
// Run your local dev server before starting the tests.
webServer: {
command: `node extra/remove-playwright-test-data.js && node server/server.js --port=${port} --data-dir=./data/playwright-test`,
command: `node extra/remove-playwright-test-data.js && cross-env NODE_ENV=development node server/server.js --port=${port} --data-dir=./data/playwright-test`,
url,
reuseExistingServer: false,
cwd: "../",

View File

@ -0,0 +1,16 @@
exports.up = function (knex) {
return knex.schema
.alterTable("monitor", function (table) {
table.string("snmp_oid").defaultTo(null);
table.enum("snmp_version", [ "1", "2c", "3" ]).defaultTo("2c");
table.string("json_path_operator").defaultTo(null);
});
};
exports.down = function (knex) {
return knex.schema.alterTable("monitor", function (table) {
table.dropColumn("snmp_oid");
table.dropColumn("snmp_version");
table.dropColumn("json_path_operator");
});
};

View File

@ -0,0 +1,13 @@
exports.up = function (knex) {
return knex.schema
.alterTable("monitor", function (table) {
table.boolean("cache_bust").notNullable().defaultTo(false);
});
};
exports.down = function (knex) {
return knex.schema
.alterTable("monitor", function (table) {
table.dropColumn("cache_bust");
});
};

View File

@ -0,0 +1,12 @@
exports.up = function (knex) {
return knex.schema
.alterTable("monitor", function (table) {
table.text("conditions").notNullable().defaultTo("[]");
});
};
exports.down = function (knex) {
return knex.schema.alterTable("monitor", function (table) {
table.dropColumn("conditions");
});
};

View File

@ -27,9 +27,7 @@
"build": "vite build --config ./config/vite.config.js",
"test": "npm run test-backend && npm run test-e2e",
"test-with-build": "npm run build && npm test",
"test-backend": "node test/backend-test-entry.js",
"test-backend:14": "cross-env TEST_BACKEND=1 NODE_OPTIONS=\"--experimental-abortcontroller --no-warnings\" node--test test/backend-test",
"test-backend:18": "cross-env TEST_BACKEND=1 node --test test/backend-test",
"test-backend": "cross-env TEST_BACKEND=1 node --test test/backend-test",
"test-e2e": "playwright test --config ./config/playwright.config.js",
"test-e2e-ui": "playwright test --config ./config/playwright.config.js --ui --ui-port=51063",
"playwright-codegen": "playwright codegen localhost:3000 --save-storage=./private/e2e-auth.json",
@ -89,13 +87,14 @@
"command-exists": "~1.2.9",
"compare-versions": "~3.6.0",
"compression": "~1.7.4",
"croner": "~6.0.5",
"croner": "~8.1.0",
"dayjs": "~1.11.5",
"dev-null": "^0.1.1",
"dotenv": "~16.0.3",
"express": "~4.21.0",
"express-basic-auth": "~1.2.1",
"express-static-gzip": "~2.1.7",
"feed": "^4.2.2",
"form-data": "~4.0.0",
"gamedig": "^4.2.0",
"html-escaper": "^3.0.3",
@ -113,12 +112,14 @@
"knex": "^2.4.2",
"limiter": "~2.1.0",
"liquidjs": "^10.7.0",
"marked": "^14.0.0",
"mitt": "~3.0.1",
"mongodb": "~4.17.1",
"mqtt": "~4.3.7",
"mssql": "~11.0.0",
"mysql2": "~3.9.6",
"nanoid": "~3.3.4",
"net-snmp": "^3.11.2",
"node-cloudflared-tunnel": "~1.0.9",
"node-radius-client": "~1.0.0",
"nodemailer": "~6.9.13",
@ -177,7 +178,6 @@
"eslint-plugin-vue": "~8.7.1",
"favico.js": "~0.3.10",
"get-port-please": "^3.1.1",
"marked": "~4.2.5",
"node-ssh": "~13.1.0",
"postcss-html": "~1.5.0",
"postcss-rtlcss": "~3.7.2",

View File

@ -1,7 +1,6 @@
const basicAuth = require("express-basic-auth");
const passwordHash = require("./password-hash");
const { R } = require("redbean-node");
const { setting } = require("./util-server");
const { log } = require("../src/util");
const { loginRateLimiter, apiRateLimiter } = require("./rate-limiter");
const { Settings } = require("./settings");
@ -139,7 +138,7 @@ exports.basicAuth = async function (req, res, next) {
challenge: true,
});
const disabledAuth = await setting("disableAuth");
const disabledAuth = await Settings.get("disableAuth");
if (!disabledAuth) {
middleware(req, res, next);

View File

@ -1,7 +1,7 @@
const { setSetting, setting } = require("./util-server");
const axios = require("axios");
const compareVersions = require("compare-versions");
const { log } = require("../src/util");
const { Settings } = require("./settings");
exports.version = require("../package.json").version;
exports.latestVersion = null;
@ -14,7 +14,7 @@ let interval;
exports.startInterval = () => {
let check = async () => {
if (await setting("checkUpdate") === false) {
if (await Settings.get("checkUpdate") === false) {
return;
}
@ -28,7 +28,7 @@ exports.startInterval = () => {
res.data.slow = "1000.0.0";
}
let checkBeta = await setting("checkBeta");
let checkBeta = await Settings.get("checkBeta");
if (checkBeta && res.data.beta) {
if (compareVersions.compare(res.data.beta, res.data.slow, ">")) {
@ -57,7 +57,7 @@ exports.startInterval = () => {
* @returns {Promise<void>}
*/
exports.enableCheckUpdate = async (value) => {
await setSetting("checkUpdate", value);
await Settings.set("checkUpdate", value);
clearInterval(interval);

View File

@ -6,8 +6,8 @@ const { R } = require("redbean-node");
const { UptimeKumaServer } = require("./uptime-kuma-server");
const server = UptimeKumaServer.getInstance();
const io = server.io;
const { setting } = require("./util-server");
const checkVersion = require("./check-version");
const { Settings } = require("./settings");
const Database = require("./database");
/**
@ -158,8 +158,8 @@ async function sendInfo(socket, hideVersion = false) {
version,
latestVersion,
isContainer,
primaryBaseURL: await Settings.get("primaryBaseURL"),
dbType,
primaryBaseURL: await setting("primaryBaseURL"),
serverTimezone: await server.getTimezone(),
serverTimezoneOffset: server.getTimezoneOffset(),
});
@ -213,6 +213,32 @@ async function sendRemoteBrowserList(socket) {
return list;
}
/**
* Send list of monitor types to client
* @param {Socket} socket Socket.io socket instance
* @returns {Promise<void>}
*/
async function sendMonitorTypeList(socket) {
const result = Object.entries(UptimeKumaServer.monitorTypeList).map(([ key, type ]) => {
return [ key, {
supportsConditions: type.supportsConditions,
conditionVariables: type.conditionVariables.map(v => {
return {
id: v.id,
operators: v.operators.map(o => {
return {
id: o.id,
caption: o.caption,
};
}),
};
}),
}];
});
io.to(socket.userID).emit("monitorTypeList", Object.fromEntries(result));
}
module.exports = {
sendNotificationList,
sendImportantHeartbeatList,
@ -222,4 +248,5 @@ module.exports = {
sendInfo,
sendDockerHostList,
sendRemoteBrowserList,
sendMonitorTypeList,
};

View File

@ -1,11 +1,11 @@
const fs = require("fs");
const { R } = require("redbean-node");
const { setSetting, setting } = require("./util-server");
const { log, sleep } = require("../src/util");
const knex = require("knex");
const path = require("path");
const { EmbeddedMariaDB } = require("./embedded-mariadb");
const mysql = require("mysql2/promise");
const { Settings } = require("./settings");
/**
* Database & App Data Folder
@ -420,7 +420,7 @@ class Database {
* @deprecated
*/
static async patchSqlite() {
let version = parseInt(await setting("database_version"));
let version = parseInt(await Settings.get("database_version"));
if (! version) {
version = 0;
@ -445,7 +445,7 @@ class Database {
log.info("db", `Patching ${sqlFile}`);
await Database.importSQLFile(sqlFile);
log.info("db", `Patched ${sqlFile}`);
await setSetting("database_version", i);
await Settings.set("database_version", i);
}
} catch (ex) {
await Database.close();
@ -471,7 +471,7 @@ class Database {
*/
static async patchSqlite2() {
log.debug("db", "Database Patch 2.0 Process");
let databasePatchedFiles = await setting("databasePatchedFiles");
let databasePatchedFiles = await Settings.get("databasePatchedFiles");
if (! databasePatchedFiles) {
databasePatchedFiles = {};
@ -499,7 +499,7 @@ class Database {
process.exit(1);
}
await setSetting("databasePatchedFiles", databasePatchedFiles);
await Settings.set("databasePatchedFiles", databasePatchedFiles);
}
/**
@ -512,27 +512,27 @@ class Database {
// Fix 1.13.0 empty slug bug
await R.exec("UPDATE status_page SET slug = 'empty-slug-recover' WHERE TRIM(slug) = ''");
let title = await setting("title");
let title = await Settings.get("title");
if (title) {
console.log("Migrating Status Page");
log.info("database", "Migrating Status Page");
let statusPageCheck = await R.findOne("status_page", " slug = 'default' ");
if (statusPageCheck !== null) {
console.log("Migrating Status Page - Skip, default slug record is already existing");
log.info("database", "Migrating Status Page - Skip, default slug record is already existing");
return;
}
let statusPage = R.dispense("status_page");
statusPage.slug = "default";
statusPage.title = title;
statusPage.description = await setting("description");
statusPage.icon = await setting("icon");
statusPage.theme = await setting("statusPageTheme");
statusPage.published = !!await setting("statusPagePublished");
statusPage.search_engine_index = !!await setting("searchEngineIndex");
statusPage.show_tags = !!await setting("statusPageTags");
statusPage.description = await Settings.get("description");
statusPage.icon = await Settings.get("icon");
statusPage.theme = await Settings.get("statusPageTheme");
statusPage.published = !!await Settings.get("statusPagePublished");
statusPage.search_engine_index = !!await Settings.get("searchEngineIndex");
statusPage.show_tags = !!await Settings.get("statusPageTags");
statusPage.password = null;
if (!statusPage.title) {
@ -560,13 +560,13 @@ class Database {
await R.exec("DELETE FROM setting WHERE type = 'statusPage'");
// Migrate Entry Page if it is status page
let entryPage = await setting("entryPage");
let entryPage = await Settings.get("entryPage");
if (entryPage === "statusPage") {
await setSetting("entryPage", "statusPage-default", "general");
await Settings.set("entryPage", "statusPage-default", "general");
}
console.log("Migrating Status Page - Done");
log.info("database", "Migrating Status Page - Done");
}
}

View File

@ -1,7 +1,7 @@
const { R } = require("redbean-node");
const { log } = require("../../src/util");
const { setSetting, setting } = require("../util-server");
const Database = require("../database");
const { Settings } = require("../settings");
const DEFAULT_KEEP_PERIOD = 180;
@ -11,11 +11,11 @@ const DEFAULT_KEEP_PERIOD = 180;
*/
const clearOldData = async () => {
let period = await setting("keepDataPeriodDays");
let period = await Settings.get("keepDataPeriodDays");
// Set Default Period
if (period == null) {
await setSetting("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general");
await Settings.set("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general");
period = DEFAULT_KEEP_PERIOD;
}
@ -25,7 +25,7 @@ const clearOldData = async () => {
parsedPeriod = parseInt(period);
} catch (_) {
log.warn("clearOldData", "Failed to parse setting, resetting to default..");
await setSetting("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general");
await Settings.set("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general");
parsedPeriod = DEFAULT_KEEP_PERIOD;
}

View File

@ -239,19 +239,7 @@ class Maintenance extends BeanModel {
this.beanMeta.status = "under-maintenance";
clearTimeout(this.beanMeta.durationTimeout);
// Check if duration is still in the window. If not, use the duration from the current time to the end of the window
let duration;
if (customDuration > 0) {
duration = customDuration;
} else if (this.end_date) {
let d = dayjs(this.end_date).diff(dayjs(), "second");
if (d < this.duration) {
duration = d * 1000;
}
} else {
duration = this.duration * 1000;
}
let duration = this.inferDuration(customDuration);
UptimeKumaServer.getInstance().sendMaintenanceListByUserID(this.user_id);
@ -263,9 +251,21 @@ class Maintenance extends BeanModel {
};
// Create Cron
this.beanMeta.job = new Cron(this.cron, {
timezone: await this.getTimezone(),
}, startEvent);
if (this.strategy === "recurring-interval") {
// For recurring-interval, Croner needs to have interval and startAt
const startDate = dayjs(this.startDate);
const [ hour, minute ] = this.startTime.split(":");
const startDateTime = startDate.hour(hour).minute(minute);
this.beanMeta.job = new Cron(this.cron, {
timezone: await this.getTimezone(),
interval: this.interval_day * 24 * 60 * 60,
startAt: startDateTime.toISOString(),
}, startEvent);
} else {
this.beanMeta.job = new Cron(this.cron, {
timezone: await this.getTimezone(),
}, startEvent);
}
// Continue if the maintenance is still in the window
let runningTimeslot = this.getRunningTimeslot();
@ -311,6 +311,24 @@ class Maintenance extends BeanModel {
}
}
/**
* Calculate the maintenance duration
* @param {number} customDuration - The custom duration in milliseconds.
* @returns {number} The inferred duration in milliseconds.
*/
inferDuration(customDuration) {
// Check if duration is still in the window. If not, use the duration from the current time to the end of the window
if (customDuration > 0) {
return customDuration;
} else if (this.end_date) {
let d = dayjs(this.end_date).diff(dayjs(), "second");
if (d < this.duration) {
return d * 1000;
}
}
return this.duration * 1000;
}
/**
* Stop the maintenance
* @returns {void}
@ -395,10 +413,8 @@ class Maintenance extends BeanModel {
} else if (!this.strategy.startsWith("recurring-")) {
this.cron = "";
} else if (this.strategy === "recurring-interval") {
let array = this.start_time.split(":");
let hour = parseInt(array[0]);
let minute = parseInt(array[1]);
this.cron = minute + " " + hour + " */" + this.interval_day + " * *";
// For intervals, the pattern is calculated in the run function as the interval-option is set
this.cron = "* * * * *";
this.duration = this.calcDuration();
log.debug("maintenance", "Cron: " + this.cron);
log.debug("maintenance", "Duration: " + this.duration);

View File

@ -2,9 +2,9 @@ const dayjs = require("dayjs");
const axios = require("axios");
const { Prometheus } = require("../prometheus");
const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND,
SQL_DATETIME_FORMAT
SQL_DATETIME_FORMAT, evaluateJsonQuery
} = require("../../src/util");
const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, setSetting, httpNtlm, radius, grpcQuery,
const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, mssqlQuery, postgresQuery, mysqlQuery, httpNtlm, radius, grpcQuery,
redisPingAsync, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal
} = require("../util-server");
const { R } = require("redbean-node");
@ -17,7 +17,6 @@ const apicache = require("../modules/apicache");
const { UptimeKumaServer } = require("../uptime-kuma-server");
const { DockerHost } = require("../docker");
const Gamedig = require("gamedig");
const jsonata = require("jsonata");
const jwt = require("jsonwebtoken");
const crypto = require("crypto");
const { UptimeCalculator } = require("../uptime-calculator");
@ -25,6 +24,7 @@ const { CookieJar } = require("tough-cookie");
const { HttpsCookieAgent } = require("http-cookie-agent/http");
const https = require("https");
const http = require("http");
const { Settings } = require("../settings");
const rootCertificates = rootCertificatesFingerprints();
@ -160,7 +160,12 @@ class Monitor extends BeanModel {
kafkaProducerAllowAutoTopicCreation: this.getKafkaProducerAllowAutoTopicCreation(),
kafkaProducerMessage: this.kafkaProducerMessage,
screenshot,
cacheBust: this.getCacheBust(),
remote_browser: this.remote_browser,
snmpOid: this.snmpOid,
jsonPathOperator: this.jsonPathOperator,
snmpVersion: this.snmpVersion,
conditions: JSON.parse(this.conditions),
};
if (includeSensitiveData) {
@ -293,6 +298,14 @@ class Monitor extends BeanModel {
return Boolean(this.grpcEnableTls);
}
/**
* Parse to boolean
* @returns {boolean} if cachebusting is enabled
*/
getCacheBust() {
return Boolean(this.cacheBust);
}
/**
* Get accepted status codes
* @returns {object} Accepted status codes
@ -334,7 +347,7 @@ class Monitor extends BeanModel {
let previousBeat = null;
let retries = 0;
this.prometheus = new Prometheus(this);
this.prometheus = await Prometheus.createAndInitMetrics(this);
const beat = async () => {
@ -498,6 +511,14 @@ class Monitor extends BeanModel {
options.data = bodyValue;
}
if (this.cacheBust) {
const randomFloatString = Math.random().toString(36);
const cacheBust = randomFloatString.substring(2);
options.params = {
uptime_kuma_cachebuster: cacheBust,
};
}
if (this.proxy_id) {
const proxy = await R.load("proxy", this.proxy_id);
@ -598,25 +619,15 @@ class Monitor extends BeanModel {
} else if (this.type === "json-query") {
let data = res.data;
// convert data to object
if (typeof data === "string" && res.headers["content-type"] !== "application/json") {
try {
data = JSON.parse(data);
} catch (_) {
// Failed to parse as JSON, just process it as a string
}
}
const { status, response } = await evaluateJsonQuery(data, this.jsonPath, this.jsonPathOperator, this.expectedValue);
let expression = jsonata(this.jsonPath);
let result = await expression.evaluate(data);
if (result.toString() === this.expectedValue) {
bean.msg += ", expected value is found";
if (status) {
bean.status = UP;
bean.msg = `JSON query passes (comparing ${response} ${this.jsonPathOperator} ${this.expectedValue})`;
} else {
throw new Error(bean.msg + ", but value is not equal to expected value, value was: [" + result + "]");
throw new Error(`JSON query does not pass (comparing ${response} ${this.jsonPathOperator} ${this.expectedValue})`);
}
}
} else if (this.type === "port") {
@ -662,7 +673,7 @@ class Monitor extends BeanModel {
} else if (this.type === "steam") {
const steamApiUrl = "https://api.steampowered.com/IGameServersService/GetServerList/v1/";
const steamAPIKey = await setting("steamAPIKey");
const steamAPIKey = await Settings.get("steamAPIKey");
const filter = `addr\\${this.hostname}:${this.port}`;
if (!steamAPIKey) {
@ -988,7 +999,7 @@ class Monitor extends BeanModel {
await R.store(bean);
log.debug("monitor", `[${this.name}] prometheus.update`);
this.prometheus?.update(bean, tlsInfo);
await this.prometheus?.update(bean, tlsInfo);
previousBeat = bean;
@ -1369,11 +1380,12 @@ class Monitor extends BeanModel {
return;
}
let notifyDays = await setting("tlsExpiryNotifyDays");
let notifyDays = await Settings.get("tlsExpiryNotifyDays");
if (notifyDays == null || !Array.isArray(notifyDays)) {
// Reset Default
await setSetting("tlsExpiryNotifyDays", [ 7, 14, 21 ], "general");
await Settings.set("tlsExpiryNotifyDays", [ 7, 14, 21 ], "general");
notifyDays = [ 7, 14, 21 ];
await Settings.set("tlsExpiryNotifyDays", notifyDays, "general");
}
if (Array.isArray(notifyDays)) {

View File

@ -4,6 +4,11 @@ const cheerio = require("cheerio");
const { UptimeKumaServer } = require("../uptime-kuma-server");
const jsesc = require("jsesc");
const googleAnalytics = require("../google-analytics");
const { marked } = require("marked");
const { Feed } = require("feed");
const config = require("../config");
const { STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_MAINTENANCE, STATUS_PAGE_PARTIAL_DOWN, UP, MAINTENANCE, DOWN } = require("../../src/util");
class StatusPage extends BeanModel {
@ -13,6 +18,24 @@ class StatusPage extends BeanModel {
*/
static domainMappingList = { };
/**
* Handle responses to RSS pages
* @param {Response} response Response object
* @param {string} slug Status page slug
* @returns {Promise<void>}
*/
static async handleStatusPageRSSResponse(response, slug) {
let statusPage = await R.findOne("status_page", " slug = ? ", [
slug
]);
if (statusPage) {
response.send(await StatusPage.renderRSS(statusPage, slug));
} else {
response.status(404).send(UptimeKumaServer.getInstance().indexHTML);
}
}
/**
* Handle responses to status page
* @param {Response} response Response object
@ -38,6 +61,38 @@ class StatusPage extends BeanModel {
}
}
/**
* SSR for RSS feed
* @param {statusPage} statusPage object
* @param {slug} slug from router
* @returns {Promise<string>} the rendered html
*/
static async renderRSS(statusPage, slug) {
const { heartbeats, statusDescription } = await StatusPage.getRSSPageData(statusPage);
let proto = config.isSSL ? "https" : "http";
let host = `${proto}://${config.hostname || "localhost"}:${config.port}/status/${slug}`;
const feed = new Feed({
title: "uptime kuma rss feed",
description: `current status: ${statusDescription}`,
link: host,
language: "en", // optional, used only in RSS 2.0, possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
updated: new Date(), // optional, default = today
});
heartbeats.forEach(heartbeat => {
feed.addItem({
title: `${heartbeat.name} is down`,
description: `${heartbeat.name} has been down since ${heartbeat.time}`,
id: heartbeat.monitorID,
date: new Date(heartbeat.time),
});
});
return feed.rss2();
}
/**
* SSR for status pages
* @param {string} indexHTML HTML page to render
@ -46,7 +101,11 @@ class StatusPage extends BeanModel {
*/
static async renderHTML(indexHTML, statusPage) {
const $ = cheerio.load(indexHTML);
const description155 = statusPage.description?.substring(0, 155) ?? "";
const description155 = marked(statusPage.description ?? "")
.replace(/<[^>]+>/gm, "")
.trim()
.substring(0, 155);
$("title").text(statusPage.title);
$("meta[name=description]").attr("content", description155);
@ -93,6 +152,109 @@ class StatusPage extends BeanModel {
return $.root().html();
}
/**
* @param {heartbeats} heartbeats from getRSSPageData
* @returns {number} status_page constant from util.ts
*/
static overallStatus(heartbeats) {
if (heartbeats.length === 0) {
return -1;
}
let status = STATUS_PAGE_ALL_UP;
let hasUp = false;
for (let beat of heartbeats) {
if (beat.status === MAINTENANCE) {
return STATUS_PAGE_MAINTENANCE;
} else if (beat.status === UP) {
hasUp = true;
} else {
status = STATUS_PAGE_PARTIAL_DOWN;
}
}
if (! hasUp) {
status = STATUS_PAGE_ALL_DOWN;
}
return status;
}
/**
* @param {number} status from overallStatus
* @returns {string} description
*/
static getStatusDescription(status) {
if (status === -1) {
return "No Services";
}
if (status === STATUS_PAGE_ALL_UP) {
return "All Systems Operational";
}
if (status === STATUS_PAGE_PARTIAL_DOWN) {
return "Partially Degraded Service";
}
if (status === STATUS_PAGE_ALL_DOWN) {
return "Degraded Service";
}
// TODO: show the real maintenance information: title, description, time
if (status === MAINTENANCE) {
return "Under maintenance";
}
return "?";
}
/**
* Get all data required for RSS
* @param {StatusPage} statusPage Status page to get data for
* @returns {object} Status page data
*/
static async getRSSPageData(statusPage) {
// get all heartbeats that correspond to this statusPage
const config = await statusPage.toPublicJSON();
// Public Group List
const showTags = !!statusPage.show_tags;
const list = await R.find("group", " public = 1 AND status_page_id = ? ORDER BY weight ", [
statusPage.id
]);
let heartbeats = [];
for (let groupBean of list) {
let monitorGroup = await groupBean.toPublicJSON(showTags, config?.showCertificateExpiry);
for (const monitor of monitorGroup.monitorList) {
const heartbeat = await R.findOne("heartbeat", "monitor_id = ? ORDER BY time DESC", [ monitor.id ]);
if (heartbeat) {
heartbeats.push({
...monitor,
status: heartbeat.status,
time: heartbeat.time
});
}
}
}
// calculate RSS feed description
let status = StatusPage.overallStatus(heartbeats);
let statusDescription = StatusPage.getStatusDescription(status);
// keep only DOWN heartbeats in the RSS feed
heartbeats = heartbeats.filter(heartbeat => heartbeat.status === DOWN);
return {
heartbeats,
statusDescription
};
}
/**
* Get all status page data in one call
* @param {StatusPage} statusPage Status page to get data for

View File

@ -1,5 +1,6 @@
let url = require("url");
let MemoryCache = require("./memory-cache");
const { log } = require("../../../src/util");
let t = {
ms: 1,
@ -90,24 +91,6 @@ function ApiCache() {
instances.push(this);
this.id = instances.length;
/**
* Logs a message to the console if the `DEBUG` environment variable is set.
* @param {string} a The first argument to log.
* @param {string} b The second argument to log.
* @param {string} c The third argument to log.
* @param {string} d The fourth argument to log, and so on... (optional)
*
* Generated by Trelent
*/
function debug(a, b, c, d) {
let arr = ["\x1b[36m[apicache]\x1b[0m", a, b, c, d].filter(function (arg) {
return arg !== undefined;
});
let debugEnv = process.env.DEBUG && process.env.DEBUG.split(",").indexOf("apicache") !== -1;
return (globalOptions.debug || debugEnv) && console.log.apply(null, arr);
}
/**
* Returns true if the given request and response should be logged.
* @param {Object} request The HTTP request object.
@ -146,7 +129,7 @@ function ApiCache() {
let groupName = req.apicacheGroup;
if (groupName) {
debug("group detected \"" + groupName + "\"");
log.debug("apicache", `group detected "${groupName}"`);
let group = (index.groups[groupName] = index.groups[groupName] || []);
group.unshift(key);
}
@ -212,7 +195,7 @@ function ApiCache() {
redis.hset(key, "duration", duration);
redis.expire(key, duration / 1000, expireCallback || function () {});
} catch (err) {
debug("[apicache] error in redis.hset()");
log.debug("apicache", `error in redis.hset(): ${err}`);
}
} else {
memCache.add(key, value, duration, expireCallback);
@ -320,10 +303,10 @@ function ApiCache() {
// display log entry
let elapsed = new Date() - req.apicacheTimer;
debug("adding cache entry for \"" + key + "\" @ " + strDuration, logDuration(elapsed));
debug("_apicache.headers: ", res._apicache.headers);
debug("res.getHeaders(): ", getSafeHeaders(res));
debug("cacheObject: ", cacheObject);
log.debug("apicache", `adding cache entry for "${key}" @ ${strDuration} ${logDuration(elapsed)}`);
log.debug("apicache", `_apicache.headers: ${JSON.stringify(res._apicache.headers)}`);
log.debug("apicache", `res.getHeaders(): ${JSON.stringify(getSafeHeaders(res))}`);
log.debug("apicache", `cacheObject: ${JSON.stringify(cacheObject)}`);
}
}
@ -402,10 +385,10 @@ function ApiCache() {
let redis = globalOptions.redisClient;
if (group) {
debug("clearing group \"" + target + "\"");
log.debug("apicache", `clearing group "${target}"`);
group.forEach(function (key) {
debug("clearing cached entry for \"" + key + "\"");
log.debug("apicache", `clearing cached entry for "${key}"`);
clearTimeout(timers[key]);
delete timers[key];
if (!globalOptions.redisClient) {
@ -414,7 +397,7 @@ function ApiCache() {
try {
redis.del(key);
} catch (err) {
console.log("[apicache] error in redis.del(\"" + key + "\")");
log.info("apicache", "error in redis.del(\"" + key + "\")");
}
}
index.all = index.all.filter(doesntMatch(key));
@ -422,7 +405,7 @@ function ApiCache() {
delete index.groups[target];
} else if (target) {
debug("clearing " + (isAutomatic ? "expired" : "cached") + " entry for \"" + target + "\"");
log.debug("apicache", `clearing ${isAutomatic ? "expired" : "cached"} entry for "${target}"`);
clearTimeout(timers[target]);
delete timers[target];
// clear actual cached entry
@ -432,7 +415,7 @@ function ApiCache() {
try {
redis.del(target);
} catch (err) {
console.log("[apicache] error in redis.del(\"" + target + "\")");
log.error("apicache", "error in redis.del(\"" + target + "\")");
}
}
@ -449,7 +432,7 @@ function ApiCache() {
}
});
} else {
debug("clearing entire index");
log.debug("apicache", "clearing entire index");
if (!redis) {
memCache.clear();
@ -461,7 +444,7 @@ function ApiCache() {
try {
redis.del(key);
} catch (err) {
console.log("[apicache] error in redis.del(\"" + key + "\")");
log.error("apicache", `error in redis.del("${key}"): ${err}`);
}
});
}
@ -528,7 +511,7 @@ function ApiCache() {
/**
* Get index of a group
* @param {string} group
* @param {string} group
* @returns {number}
*/
this.getIndex = function (group) {
@ -543,9 +526,9 @@ function ApiCache() {
* Express middleware
* @param {(string|number)} strDuration Duration to cache responses
* for.
* @param {function(Object, Object):boolean} middlewareToggle
* @param {function(Object, Object):boolean} middlewareToggle
* @param {Object} localOptions Options for APICache
* @returns
* @returns
*/
this.middleware = function cache(strDuration, middlewareToggle, localOptions) {
let duration = instance.getDuration(strDuration);
@ -752,7 +735,7 @@ function ApiCache() {
*/
let cache = function (req, res, next) {
function bypass() {
debug("bypass detected, skipping cache.");
log.debug("apicache", "bypass detected, skipping cache.");
return next();
}
@ -805,7 +788,7 @@ function ApiCache() {
// send if cache hit from memory-cache
if (cached) {
let elapsed = new Date() - req.apicacheTimer;
debug("sending cached (memory-cache) version of", key, logDuration(elapsed));
log.debug("apicache", `sending cached (memory-cache) version of ${key} ${logDuration(elapsed)}`);
perf.hit(key);
return sendCachedResponse(req, res, cached, middlewareToggle, next, duration);
@ -817,7 +800,7 @@ function ApiCache() {
redis.hgetall(key, function (err, obj) {
if (!err && obj && obj.response) {
let elapsed = new Date() - req.apicacheTimer;
debug("sending cached (redis) version of", key, logDuration(elapsed));
log.debug("apicache", "sending cached (redis) version of "+ key+" "+ logDuration(elapsed));
perf.hit(key);
return sendCachedResponse(
@ -859,7 +842,7 @@ function ApiCache() {
/**
* Process options
* @param {Object} options
* @param {Object} options
* @returns {Object}
*/
this.options = function (options) {
@ -873,7 +856,7 @@ function ApiCache() {
}
if (globalOptions.trackPerformance) {
debug("WARNING: using trackPerformance flag can cause high memory usage!");
log.debug("apicache", "WARNING: using trackPerformance flag can cause high memory usage!");
}
return this;

View File

@ -0,0 +1,71 @@
const { ConditionExpressionGroup, ConditionExpression, LOGICAL } = require("./expression");
const { operatorMap } = require("./operators");
/**
* @param {ConditionExpression} expression Expression to evaluate
* @param {object} context Context to evaluate against; These are values for variables in the expression
* @returns {boolean} Whether the expression evaluates true or false
* @throws {Error}
*/
function evaluateExpression(expression, context) {
/**
* @type {import("./operators").ConditionOperator|null}
*/
const operator = operatorMap.get(expression.operator) || null;
if (operator === null) {
throw new Error("Unexpected expression operator ID '" + expression.operator + "'. Expected one of [" + operatorMap.keys().join(",") + "]");
}
if (!Object.prototype.hasOwnProperty.call(context, expression.variable)) {
throw new Error("Variable missing in context: " + expression.variable);
}
return operator.test(context[expression.variable], expression.value);
}
/**
* @param {ConditionExpressionGroup} group Group of expressions to evaluate
* @param {object} context Context to evaluate against; These are values for variables in the expression
* @returns {boolean} Whether the group evaluates true or false
* @throws {Error}
*/
function evaluateExpressionGroup(group, context) {
if (!group.children.length) {
throw new Error("ConditionExpressionGroup must contain at least one child.");
}
let result = null;
for (const child of group.children) {
let childResult;
if (child instanceof ConditionExpression) {
childResult = evaluateExpression(child, context);
} else if (child instanceof ConditionExpressionGroup) {
childResult = evaluateExpressionGroup(child, context);
} else {
throw new Error("Invalid child type in ConditionExpressionGroup. Expected ConditionExpression or ConditionExpressionGroup");
}
if (result === null) {
result = childResult; // Initialize result with the first child's result
} else if (child.andOr === LOGICAL.OR) {
result = result || childResult;
} else if (child.andOr === LOGICAL.AND) {
result = result && childResult;
} else {
throw new Error("Invalid logical operator in child of ConditionExpressionGroup. Expected 'and' or 'or'. Got '" + group.andOr + "'");
}
}
if (result === null) {
throw new Error("ConditionExpressionGroup did not result in a boolean.");
}
return result;
}
module.exports = {
evaluateExpression,
evaluateExpressionGroup,
};

View File

@ -0,0 +1,111 @@
/**
* @readonly
* @enum {string}
*/
const LOGICAL = {
AND: "and",
OR: "or",
};
/**
* Recursively processes an array of raw condition objects and populates the given parent group with
* corresponding ConditionExpression or ConditionExpressionGroup instances.
* @param {Array} conditions Array of raw condition objects, where each object represents either a group or an expression.
* @param {ConditionExpressionGroup} parentGroup The parent group to which the instantiated ConditionExpression or ConditionExpressionGroup objects will be added.
* @returns {void}
*/
function processMonitorConditions(conditions, parentGroup) {
conditions.forEach(condition => {
const andOr = condition.andOr === LOGICAL.OR ? LOGICAL.OR : LOGICAL.AND;
if (condition.type === "group") {
const group = new ConditionExpressionGroup([], andOr);
// Recursively process the group's children
processMonitorConditions(condition.children, group);
parentGroup.children.push(group);
} else if (condition.type === "expression") {
const expression = new ConditionExpression(condition.variable, condition.operator, condition.value, andOr);
parentGroup.children.push(expression);
}
});
}
class ConditionExpressionGroup {
/**
* @type {ConditionExpressionGroup[]|ConditionExpression[]} Groups and/or expressions to test
*/
children = [];
/**
* @type {LOGICAL} Connects group result with previous group/expression results
*/
andOr;
/**
* @param {ConditionExpressionGroup[]|ConditionExpression[]} children Groups and/or expressions to test
* @param {LOGICAL} andOr Connects group result with previous group/expression results
*/
constructor(children = [], andOr = LOGICAL.AND) {
this.children = children;
this.andOr = andOr;
}
/**
* @param {Monitor} monitor Monitor instance
* @returns {ConditionExpressionGroup|null} A ConditionExpressionGroup with the Monitor's conditions
*/
static fromMonitor(monitor) {
const conditions = JSON.parse(monitor.conditions);
if (conditions.length === 0) {
return null;
}
const root = new ConditionExpressionGroup();
processMonitorConditions(conditions, root);
return root;
}
}
class ConditionExpression {
/**
* @type {string} ID of variable
*/
variable;
/**
* @type {string} ID of operator
*/
operator;
/**
* @type {string} Value to test with the operator
*/
value;
/**
* @type {LOGICAL} Connects expression result with previous group/expression results
*/
andOr;
/**
* @param {string} variable ID of variable to test against
* @param {string} operator ID of operator to test the variable with
* @param {string} value Value to test with the operator
* @param {LOGICAL} andOr Connects expression result with previous group/expression results
*/
constructor(variable, operator, value, andOr = LOGICAL.AND) {
this.variable = variable;
this.operator = operator;
this.value = value;
this.andOr = andOr;
}
}
module.exports = {
LOGICAL,
ConditionExpressionGroup,
ConditionExpression,
};

View File

@ -0,0 +1,318 @@
class ConditionOperator {
id = undefined;
caption = undefined;
/**
* @type {mixed} variable
* @type {mixed} value
*/
test(variable, value) {
throw new Error("You need to override test()");
}
}
const OP_STR_EQUALS = "equals";
const OP_STR_NOT_EQUALS = "not_equals";
const OP_CONTAINS = "contains";
const OP_NOT_CONTAINS = "not_contains";
const OP_STARTS_WITH = "starts_with";
const OP_NOT_STARTS_WITH = "not_starts_with";
const OP_ENDS_WITH = "ends_with";
const OP_NOT_ENDS_WITH = "not_ends_with";
const OP_NUM_EQUALS = "num_equals";
const OP_NUM_NOT_EQUALS = "num_not_equals";
const OP_LT = "lt";
const OP_GT = "gt";
const OP_LTE = "lte";
const OP_GTE = "gte";
/**
* Asserts a variable is equal to a value.
*/
class StringEqualsOperator extends ConditionOperator {
id = OP_STR_EQUALS;
caption = "equals";
/**
* @inheritdoc
*/
test(variable, value) {
return variable === value;
}
}
/**
* Asserts a variable is not equal to a value.
*/
class StringNotEqualsOperator extends ConditionOperator {
id = OP_STR_NOT_EQUALS;
caption = "not equals";
/**
* @inheritdoc
*/
test(variable, value) {
return variable !== value;
}
}
/**
* Asserts a variable contains a value.
* Handles both Array and String variable types.
*/
class ContainsOperator extends ConditionOperator {
id = OP_CONTAINS;
caption = "contains";
/**
* @inheritdoc
*/
test(variable, value) {
if (Array.isArray(variable)) {
return variable.includes(value);
}
return variable.indexOf(value) !== -1;
}
}
/**
* Asserts a variable does not contain a value.
* Handles both Array and String variable types.
*/
class NotContainsOperator extends ConditionOperator {
id = OP_NOT_CONTAINS;
caption = "not contains";
/**
* @inheritdoc
*/
test(variable, value) {
if (Array.isArray(variable)) {
return !variable.includes(value);
}
return variable.indexOf(value) === -1;
}
}
/**
* Asserts a variable starts with a value.
*/
class StartsWithOperator extends ConditionOperator {
id = OP_STARTS_WITH;
caption = "starts with";
/**
* @inheritdoc
*/
test(variable, value) {
return variable.startsWith(value);
}
}
/**
* Asserts a variable does not start with a value.
*/
class NotStartsWithOperator extends ConditionOperator {
id = OP_NOT_STARTS_WITH;
caption = "not starts with";
/**
* @inheritdoc
*/
test(variable, value) {
return !variable.startsWith(value);
}
}
/**
* Asserts a variable ends with a value.
*/
class EndsWithOperator extends ConditionOperator {
id = OP_ENDS_WITH;
caption = "ends with";
/**
* @inheritdoc
*/
test(variable, value) {
return variable.endsWith(value);
}
}
/**
* Asserts a variable does not end with a value.
*/
class NotEndsWithOperator extends ConditionOperator {
id = OP_NOT_ENDS_WITH;
caption = "not ends with";
/**
* @inheritdoc
*/
test(variable, value) {
return !variable.endsWith(value);
}
}
/**
* Asserts a numeric variable is equal to a value.
*/
class NumberEqualsOperator extends ConditionOperator {
id = OP_NUM_EQUALS;
caption = "equals";
/**
* @inheritdoc
*/
test(variable, value) {
return variable === Number(value);
}
}
/**
* Asserts a numeric variable is not equal to a value.
*/
class NumberNotEqualsOperator extends ConditionOperator {
id = OP_NUM_NOT_EQUALS;
caption = "not equals";
/**
* @inheritdoc
*/
test(variable, value) {
return variable !== Number(value);
}
}
/**
* Asserts a variable is less than a value.
*/
class LessThanOperator extends ConditionOperator {
id = OP_LT;
caption = "less than";
/**
* @inheritdoc
*/
test(variable, value) {
return variable < Number(value);
}
}
/**
* Asserts a variable is greater than a value.
*/
class GreaterThanOperator extends ConditionOperator {
id = OP_GT;
caption = "greater than";
/**
* @inheritdoc
*/
test(variable, value) {
return variable > Number(value);
}
}
/**
* Asserts a variable is less than or equal to a value.
*/
class LessThanOrEqualToOperator extends ConditionOperator {
id = OP_LTE;
caption = "less than or equal to";
/**
* @inheritdoc
*/
test(variable, value) {
return variable <= Number(value);
}
}
/**
* Asserts a variable is greater than or equal to a value.
*/
class GreaterThanOrEqualToOperator extends ConditionOperator {
id = OP_GTE;
caption = "greater than or equal to";
/**
* @inheritdoc
*/
test(variable, value) {
return variable >= Number(value);
}
}
const operatorMap = new Map([
[ OP_STR_EQUALS, new StringEqualsOperator ],
[ OP_STR_NOT_EQUALS, new StringNotEqualsOperator ],
[ OP_CONTAINS, new ContainsOperator ],
[ OP_NOT_CONTAINS, new NotContainsOperator ],
[ OP_STARTS_WITH, new StartsWithOperator ],
[ OP_NOT_STARTS_WITH, new NotStartsWithOperator ],
[ OP_ENDS_WITH, new EndsWithOperator ],
[ OP_NOT_ENDS_WITH, new NotEndsWithOperator ],
[ OP_NUM_EQUALS, new NumberEqualsOperator ],
[ OP_NUM_NOT_EQUALS, new NumberNotEqualsOperator ],
[ OP_LT, new LessThanOperator ],
[ OP_GT, new GreaterThanOperator ],
[ OP_LTE, new LessThanOrEqualToOperator ],
[ OP_GTE, new GreaterThanOrEqualToOperator ],
]);
const defaultStringOperators = [
operatorMap.get(OP_STR_EQUALS),
operatorMap.get(OP_STR_NOT_EQUALS),
operatorMap.get(OP_CONTAINS),
operatorMap.get(OP_NOT_CONTAINS),
operatorMap.get(OP_STARTS_WITH),
operatorMap.get(OP_NOT_STARTS_WITH),
operatorMap.get(OP_ENDS_WITH),
operatorMap.get(OP_NOT_ENDS_WITH)
];
const defaultNumberOperators = [
operatorMap.get(OP_NUM_EQUALS),
operatorMap.get(OP_NUM_NOT_EQUALS),
operatorMap.get(OP_LT),
operatorMap.get(OP_GT),
operatorMap.get(OP_LTE),
operatorMap.get(OP_GTE)
];
module.exports = {
OP_STR_EQUALS,
OP_STR_NOT_EQUALS,
OP_CONTAINS,
OP_NOT_CONTAINS,
OP_STARTS_WITH,
OP_NOT_STARTS_WITH,
OP_ENDS_WITH,
OP_NOT_ENDS_WITH,
OP_NUM_EQUALS,
OP_NUM_NOT_EQUALS,
OP_LT,
OP_GT,
OP_LTE,
OP_GTE,
operatorMap,
defaultStringOperators,
defaultNumberOperators,
ConditionOperator,
};

View File

@ -0,0 +1,31 @@
/**
* Represents a variable used in a condition and the set of operators that can be applied to this variable.
*
* A `ConditionVariable` holds the ID of the variable and a list of operators that define how this variable can be evaluated
* in conditions. For example, if the variable is a request body or a specific field in a request, the operators can include
* operations such as equality checks, comparisons, or other custom evaluations.
*/
class ConditionVariable {
/**
* @type {string}
*/
id;
/**
* @type {import("./operators").ConditionOperator[]}
*/
operators = {};
/**
* @param {string} id ID of variable
* @param {import("./operators").ConditionOperator[]} operators Operators the condition supports
*/
constructor(id, operators = []) {
this.id = id;
this.operators = operators;
}
}
module.exports = {
ConditionVariable,
};

View File

@ -1,12 +1,22 @@
const { MonitorType } = require("./monitor-type");
const { UP } = require("../../src/util");
const { UP, DOWN } = require("../../src/util");
const dayjs = require("dayjs");
const { dnsResolve } = require("../util-server");
const { R } = require("redbean-node");
const { ConditionVariable } = require("../monitor-conditions/variables");
const { defaultStringOperators } = require("../monitor-conditions/operators");
const { ConditionExpressionGroup } = require("../monitor-conditions/expression");
const { evaluateExpressionGroup } = require("../monitor-conditions/evaluator");
class DnsMonitorType extends MonitorType {
name = "dns";
supportsConditions = true;
conditionVariables = [
new ConditionVariable("record", defaultStringOperators ),
];
/**
* @inheritdoc
*/
@ -17,28 +27,48 @@ class DnsMonitorType extends MonitorType {
let dnsRes = await dnsResolve(monitor.hostname, monitor.dns_resolve_server, monitor.port, monitor.dns_resolve_type);
heartbeat.ping = dayjs().valueOf() - startTime;
if (monitor.dns_resolve_type === "A" || monitor.dns_resolve_type === "AAAA" || monitor.dns_resolve_type === "TXT" || monitor.dns_resolve_type === "PTR") {
dnsMessage += "Records: ";
dnsMessage += dnsRes.join(" | ");
} else if (monitor.dns_resolve_type === "CNAME" || monitor.dns_resolve_type === "PTR") {
dnsMessage += dnsRes[0];
} else if (monitor.dns_resolve_type === "CAA") {
dnsMessage += dnsRes[0].issue;
} else if (monitor.dns_resolve_type === "MX") {
dnsRes.forEach(record => {
dnsMessage += `Hostname: ${record.exchange} - Priority: ${record.priority} | `;
});
dnsMessage = dnsMessage.slice(0, -2);
} else if (monitor.dns_resolve_type === "NS") {
dnsMessage += "Servers: ";
dnsMessage += dnsRes.join(" | ");
} else if (monitor.dns_resolve_type === "SOA") {
dnsMessage += `NS-Name: ${dnsRes.nsname} | Hostmaster: ${dnsRes.hostmaster} | Serial: ${dnsRes.serial} | Refresh: ${dnsRes.refresh} | Retry: ${dnsRes.retry} | Expire: ${dnsRes.expire} | MinTTL: ${dnsRes.minttl}`;
} else if (monitor.dns_resolve_type === "SRV") {
dnsRes.forEach(record => {
dnsMessage += `Name: ${record.name} | Port: ${record.port} | Priority: ${record.priority} | Weight: ${record.weight} | `;
});
dnsMessage = dnsMessage.slice(0, -2);
const conditions = ConditionExpressionGroup.fromMonitor(monitor);
let conditionsResult = true;
const handleConditions = (data) => conditions ? evaluateExpressionGroup(conditions, data) : true;
switch (monitor.dns_resolve_type) {
case "A":
case "AAAA":
case "TXT":
case "PTR":
dnsMessage = `Records: ${dnsRes.join(" | ")}`;
conditionsResult = dnsRes.some(record => handleConditions({ record }));
break;
case "CNAME":
dnsMessage = dnsRes[0];
conditionsResult = handleConditions({ record: dnsRes[0] });
break;
case "CAA":
dnsMessage = dnsRes[0].issue;
conditionsResult = handleConditions({ record: dnsRes[0].issue });
break;
case "MX":
dnsMessage = dnsRes.map(record => `Hostname: ${record.exchange} - Priority: ${record.priority}`).join(" | ");
conditionsResult = dnsRes.some(record => handleConditions({ record: record.exchange }));
break;
case "NS":
dnsMessage = `Servers: ${dnsRes.join(" | ")}`;
conditionsResult = dnsRes.some(record => handleConditions({ record }));
break;
case "SOA":
dnsMessage = `NS-Name: ${dnsRes.nsname} | Hostmaster: ${dnsRes.hostmaster} | Serial: ${dnsRes.serial} | Refresh: ${dnsRes.refresh} | Retry: ${dnsRes.retry} | Expire: ${dnsRes.expire} | MinTTL: ${dnsRes.minttl}`;
conditionsResult = handleConditions({ record: dnsRes.nsname });
break;
case "SRV":
dnsMessage = dnsRes.map(record => `Name: ${record.name} | Port: ${record.port} | Priority: ${record.priority} | Weight: ${record.weight}`).join(" | ");
conditionsResult = dnsRes.some(record => handleConditions({ record: record.name }));
break;
}
if (monitor.dns_last_result !== dnsMessage && dnsMessage !== undefined) {
@ -46,7 +76,7 @@ class DnsMonitorType extends MonitorType {
}
heartbeat.msg = dnsMessage;
heartbeat.status = UP;
heartbeat.status = conditionsResult ? UP : DOWN;
}
}

View File

@ -1,6 +1,19 @@
class MonitorType {
name = undefined;
/**
* Whether or not this type supports monitor conditions. Controls UI visibility in monitor form.
* @type {boolean}
*/
supportsConditions = false;
/**
* Variables supported by this type. e.g. an HTTP type could have a "response_code" variable to test against.
* This property controls the choices displayed in the monitor edit form.
* @type {import("../monitor-conditions/variables").ConditionVariable[]}
*/
conditionVariables = [];
/**
* Run the monitoring check on the given monitor
* @param {Monitor} monitor Monitor to check

View File

@ -63,7 +63,7 @@ if (process.platform === "win32") {
* @returns {Promise<boolean>} The executable is allowed?
*/
async function isAllowedChromeExecutable(executablePath) {
console.log(config.args);
log.info("Chromium", config.args);
if (config.args["allow-all-chrome-exec"] || process.env.UPTIME_KUMA_ALLOW_ALL_CHROME_EXEC === "1") {
return true;
}
@ -102,7 +102,8 @@ async function getBrowser() {
*/
async function getRemoteBrowser(remoteBrowserID, userId) {
let remoteBrowser = await RemoteBrowser.get(remoteBrowserID, userId);
log.debug("MONITOR", `Using remote browser: ${remoteBrowser.name} (${remoteBrowser.id})`);
log.debug("Chromium", `Using remote browser: ${remoteBrowser.name} (${remoteBrowser.id})`);
browser = chromium.connect(remoteBrowser.url);
browser = await chromium.connect(remoteBrowser.url);
return browser;
}

View File

@ -0,0 +1,63 @@
const { MonitorType } = require("./monitor-type");
const { UP, log, evaluateJsonQuery } = require("../../src/util");
const snmp = require("net-snmp");
class SNMPMonitorType extends MonitorType {
name = "snmp";
/**
* @inheritdoc
*/
async check(monitor, heartbeat, _server) {
let session;
try {
const sessionOptions = {
port: monitor.port || "161",
retries: monitor.maxretries,
timeout: monitor.timeout * 1000,
version: snmp.Version[monitor.snmpVersion],
};
session = snmp.createSession(monitor.hostname, monitor.radiusPassword, sessionOptions);
// Handle errors during session creation
session.on("error", (error) => {
throw new Error(`Error creating SNMP session: ${error.message}`);
});
const varbinds = await new Promise((resolve, reject) => {
session.get([ monitor.snmpOid ], (error, varbinds) => {
error ? reject(error) : resolve(varbinds);
});
});
log.debug("monitor", `SNMP: Received varbinds (Type: ${snmp.ObjectType[varbinds[0].type]} Value: ${varbinds[0].value})`);
if (varbinds.length === 0) {
throw new Error(`No varbinds returned from SNMP session (OID: ${monitor.snmpOid})`);
}
if (varbinds[0].type === snmp.ObjectType.NoSuchInstance) {
throw new Error(`The SNMP query returned that no instance exists for OID ${monitor.snmpOid}`);
}
// We restrict querying to one OID per monitor, therefore `varbinds[0]` will always contain the value we're interested in.
const value = varbinds[0].value;
const { status, response } = await evaluateJsonQuery(value, monitor.jsonPath, monitor.jsonPathOperator, monitor.expectedValue);
if (status) {
heartbeat.status = UP;
heartbeat.msg = `JSON query passes (comparing ${response} ${monitor.jsonPathOperator} ${monitor.expectedValue})`;
} else {
throw new Error(`JSON query does not pass (comparing ${response} ${monitor.jsonPathOperator} ${monitor.expectedValue})`);
}
} finally {
if (session) {
session.close();
}
}
}
}
module.exports = {
SNMPMonitorType,
};

View File

@ -1,7 +1,7 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { setting } = require("../util-server");
const { getMonitorRelativeURL, UP, DOWN } = require("../../src/util");
const { Settings } = require("../settings");
class AlertNow extends NotificationProvider {
name = "AlertNow";
@ -29,7 +29,7 @@ class AlertNow extends NotificationProvider {
textMsg += ` - ${msg}`;
const baseURL = await setting("primaryBaseURL");
const baseURL = await Settings.get("primaryBaseURL");
if (baseURL && monitorJSON) {
textMsg += ` >> ${baseURL + getMonitorRelativeURL(monitorJSON.id)}`;
}

View File

@ -1,7 +1,7 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util");
const { setting } = require("../util-server");
const { Settings } = require("../settings");
const successMessage = "Sent Successfully.";
class FlashDuty extends NotificationProvider {
@ -84,7 +84,7 @@ class FlashDuty extends NotificationProvider {
}
};
const baseURL = await setting("primaryBaseURL");
const baseURL = await Settings.get("primaryBaseURL");
if (baseURL && monitorInfo) {
options.client = "Uptime Kuma";
options.client_url = baseURL + getMonitorRelativeURL(monitorInfo.id);

View File

@ -1,7 +1,7 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { setting } = require("../util-server");
const { getMonitorRelativeURL, UP } = require("../../src/util");
const { Settings } = require("../settings");
class GoogleChat extends NotificationProvider {
name = "GoogleChat";
@ -45,7 +45,7 @@ class GoogleChat extends NotificationProvider {
}
// add button for monitor link if available
const baseURL = await setting("primaryBaseURL");
const baseURL = await Settings.get("primaryBaseURL");
if (baseURL) {
const urlPath = monitorJSON ? getMonitorRelativeURL(monitorJSON.id) : "/";
sectionWidgets.push({

View File

@ -1,4 +1,3 @@
const { log } = require("../../src/util");
const NotificationProvider = require("./notification-provider");
const {
relayInit,
@ -12,16 +11,7 @@ const {
// polyfills for node versions
const semver = require("semver");
const nodeVersion = process.version;
if (semver.lt(nodeVersion, "16.0.0")) {
log.warn("monitor", "Node <= 16 is unsupported for nostr, sorry :(");
} else if (semver.lt(nodeVersion, "18.0.0")) {
// polyfills for node 16
global.crypto = require("crypto");
global.WebSocket = require("isomorphic-ws");
if (typeof crypto !== "undefined" && !crypto.subtle && crypto.webcrypto) {
crypto.subtle = crypto.webcrypto.subtle;
}
} else if (semver.lt(nodeVersion, "20.0.0")) {
if (semver.lt(nodeVersion, "20.0.0")) {
// polyfills for node 18
global.crypto = require("crypto");
global.WebSocket = require("isomorphic-ws");

View File

@ -0,0 +1,47 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class Onesender extends NotificationProvider {
name = "Onesender";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const okMsg = "Sent Successfully.";
try {
let data = {
heartbeat: heartbeatJSON,
monitor: monitorJSON,
msg,
to: notification.onesenderReceiver,
type: "text",
recipient_type: "individual",
text: {
body: msg
}
};
if (notification.onesenderTypeReceiver === "private") {
data.to = notification.onesenderReceiver + "@s.whatsapp.net";
} else {
data.recipient_type = "group";
data.to = notification.onesenderReceiver + "@g.us";
}
let config = {
headers: {
"Authorization": "Bearer " + notification.onesenderToken,
}
};
await axios.post(notification.onesenderURL, data, config);
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = Onesender;

View File

@ -1,7 +1,7 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util");
const { setting } = require("../util-server");
const { Settings } = require("../settings");
let successMessage = "Sent Successfully.";
class PagerDuty extends NotificationProvider {
@ -95,7 +95,7 @@ class PagerDuty extends NotificationProvider {
}
};
const baseURL = await setting("primaryBaseURL");
const baseURL = await Settings.get("primaryBaseURL");
if (baseURL && monitorInfo) {
options.client = "Uptime Kuma";
options.client_url = baseURL + getMonitorRelativeURL(monitorInfo.id);

View File

@ -1,7 +1,7 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util");
const { setting } = require("../util-server");
const { Settings } = require("../settings");
let successMessage = "Sent Successfully.";
class PagerTree extends NotificationProvider {
@ -74,7 +74,7 @@ class PagerTree extends NotificationProvider {
}
};
const baseURL = await setting("primaryBaseURL");
const baseURL = await Settings.get("primaryBaseURL");
if (baseURL && monitorJSON) {
options.client = "Uptime Kuma";
options.client_url = baseURL + getMonitorRelativeURL(monitorJSON.id);

View File

@ -1,3 +1,6 @@
const { getMonitorRelativeURL } = require("../../src/util");
const { setting } = require("../util-server");
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
@ -23,6 +26,12 @@ class Pushover extends NotificationProvider {
"html": 1,
};
const baseURL = await setting("primaryBaseURL");
if (baseURL && monitorJSON) {
data["url"] = baseURL + getMonitorRelativeURL(monitorJSON.id);
data["url_title"] = "Link to Monitor";
}
if (notification.pushoverdevice) {
data.device = notification.pushoverdevice;
}

View File

@ -1,8 +1,8 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const Slack = require("./slack");
const { setting } = require("../util-server");
const { getMonitorRelativeURL, DOWN } = require("../../src/util");
const { Settings } = require("../settings");
class RocketChat extends NotificationProvider {
name = "rocket.chat";
@ -49,7 +49,7 @@ class RocketChat extends NotificationProvider {
await Slack.deprecateURL(notification.rocketbutton);
}
const baseURL = await setting("primaryBaseURL");
const baseURL = await Settings.get("primaryBaseURL");
if (baseURL) {
data.attachments[0].title_link = baseURL + getMonitorRelativeURL(monitorJSON.id);

View File

@ -0,0 +1,52 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { UP, DOWN } = require("../../src/util");
class SIGNL4 extends NotificationProvider {
name = "SIGNL4";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const okMsg = "Sent Successfully.";
try {
let data = {
heartbeat: heartbeatJSON,
monitor: monitorJSON,
msg,
// Source system
"X-S4-SourceSystem": "UptimeKuma",
monitorUrl: this.extractAdress(monitorJSON),
};
const config = {
headers: {
"Content-Type": "application/json"
}
};
if (heartbeatJSON == null) {
// Test alert
data.title = "Uptime Kuma Alert";
data.message = msg;
} else if (heartbeatJSON.status === UP) {
data.title = "Uptime Kuma Monitor ✅ Up";
data["X-S4-ExternalID"] = "UptimeKuma-" + monitorJSON.monitorID;
data["X-S4-Status"] = "resolved";
} else if (heartbeatJSON.status === DOWN) {
data.title = "Uptime Kuma Monitor 🔴 Down";
data["X-S4-ExternalID"] = "UptimeKuma-" + monitorJSON.monitorID;
data["X-S4-Status"] = "new";
}
await axios.post(notification.webhookURL, data, config);
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = SIGNL4;

View File

@ -1,7 +1,8 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { setSettings, setting } = require("../util-server");
const { getMonitorRelativeURL, UP } = require("../../src/util");
const { Settings } = require("../settings");
const { log } = require("../../src/util");
class Slack extends NotificationProvider {
name = "slack";
@ -14,15 +15,13 @@ class Slack extends NotificationProvider {
* @returns {Promise<void>}
*/
static async deprecateURL(url) {
let currentPrimaryBaseURL = await setting("primaryBaseURL");
let currentPrimaryBaseURL = await Settings.get("primaryBaseURL");
if (!currentPrimaryBaseURL) {
console.log("Move the url to be the primary base URL");
await setSettings("general", {
primaryBaseURL: url,
});
log.error("notification", "Move the url to be the primary base URL");
await Settings.set("primaryBaseURL", url, "general");
} else {
console.log("Already there, no need to move the primary base URL");
log.debug("notification", "Already there, no need to move the primary base URL");
}
}
@ -48,7 +47,8 @@ class Slack extends NotificationProvider {
}
if (monitorJSON.url) {
const address = this.extractAdress(monitorJSON);
if (address) {
actions.push({
"type": "button",
"text": {
@ -56,7 +56,7 @@ class Slack extends NotificationProvider {
"text": "Visit site",
},
"value": "Site",
"url": monitorJSON.url,
"url": address,
});
}
@ -135,7 +135,7 @@ class Slack extends NotificationProvider {
return okMsg;
}
const baseURL = await setting("primaryBaseURL");
const baseURL = await Settings.get("primaryBaseURL");
const title = "Uptime Kuma Alert";
let data = {

View File

@ -1,7 +1,7 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util");
const { setting } = require("../util-server");
const { Settings } = require("../settings");
let successMessage = "Sent Successfully.";
class Splunk extends NotificationProvider {
@ -95,7 +95,7 @@ class Splunk extends NotificationProvider {
}
};
const baseURL = await setting("primaryBaseURL");
const baseURL = await Settings.get("primaryBaseURL");
if (baseURL && monitorInfo) {
options.client = "Uptime Kuma";
options.client_url = baseURL + getMonitorRelativeURL(monitorInfo.id);

View File

@ -1,7 +1,7 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { setting } = require("../util-server");
const { getMonitorRelativeURL } = require("../../src/util");
const { Settings } = require("../settings");
class Stackfield extends NotificationProvider {
name = "stackfield";
@ -23,7 +23,7 @@ class Stackfield extends NotificationProvider {
textMsg += `\n${msg}`;
const baseURL = await setting("primaryBaseURL");
const baseURL = await Settings.get("primaryBaseURL");
if (baseURL) {
textMsg += `\n${baseURL + getMonitorRelativeURL(monitorJSON.id)}`;
}

View File

@ -0,0 +1,51 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { DOWN, UP } = require("../../src/util");
class WPush extends NotificationProvider {
name = "WPush";
/**
* @inheritdoc
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const okMsg = "Sent Successfully.";
try {
const context = {
"title": this.checkStatus(heartbeatJSON, monitorJSON),
"content": msg,
"apikey": notification.wpushAPIkey,
"channel": notification.wpushChannel
};
const result = await axios.post("https://api.wpush.cn/api/v1/send", context);
if (result.data.code !== 0) {
throw result.data.message;
}
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
/**
* Get the formatted title for message
* @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
* @param {?object} monitorJSON Monitor details (For Up/Down only)
* @returns {string} Formatted title
*/
checkStatus(heartbeatJSON, monitorJSON) {
let title = "UptimeKuma Message";
if (heartbeatJSON != null && heartbeatJSON["status"] === UP) {
title = "UptimeKuma Monitor Up " + monitorJSON["name"];
}
if (heartbeatJSON != null && heartbeatJSON["status"] === DOWN) {
title = "UptimeKuma Monitor Down " + monitorJSON["name"];
}
return title;
}
}
module.exports = WPush;

View File

@ -42,6 +42,7 @@ const Pushy = require("./notification-providers/pushy");
const RocketChat = require("./notification-providers/rocket-chat");
const SerwerSMS = require("./notification-providers/serwersms");
const Signal = require("./notification-providers/signal");
const SIGNL4 = require("./notification-providers/signl4");
const Slack = require("./notification-providers/slack");
const SMSPartner = require("./notification-providers/smspartner");
const SMSEagle = require("./notification-providers/smseagle");
@ -64,6 +65,8 @@ const SevenIO = require("./notification-providers/sevenio");
const Whapi = require("./notification-providers/whapi");
const GtxMessaging = require("./notification-providers/gtx-messaging");
const Cellsynt = require("./notification-providers/cellsynt");
const Onesender = require("./notification-providers/onesender");
const Wpush = require("./notification-providers/wpush");
class Notification {
@ -111,6 +114,7 @@ class Notification {
new Ntfy(),
new Octopush(),
new OneBot(),
new Onesender(),
new Opsgenie(),
new PagerDuty(),
new FlashDuty(),
@ -124,6 +128,7 @@ class Notification {
new ServerChan(),
new SerwerSMS(),
new Signal(),
new SIGNL4(),
new SMSManager(),
new SMSPartner(),
new Slack(),
@ -145,6 +150,7 @@ class Notification {
new Whapi(),
new GtxMessaging(),
new Cellsynt(),
new Wpush(),
];
for (let item of list) {
if (! item.name) {

View File

@ -1,3 +1,4 @@
const { R } = require("redbean-node");
const PrometheusClient = require("prom-client");
const { log } = require("../src/util");
@ -9,36 +10,102 @@ const commonLabels = [
"monitor_port",
];
const monitorCertDaysRemaining = new PrometheusClient.Gauge({
name: "monitor_cert_days_remaining",
help: "The number of days remaining until the certificate expires",
labelNames: commonLabels
});
const monitorCertIsValid = new PrometheusClient.Gauge({
name: "monitor_cert_is_valid",
help: "Is the certificate still valid? (1 = Yes, 0= No)",
labelNames: commonLabels
});
const monitorResponseTime = new PrometheusClient.Gauge({
name: "monitor_response_time",
help: "Monitor Response Time (ms)",
labelNames: commonLabels
});
const monitorStatus = new PrometheusClient.Gauge({
name: "monitor_status",
help: "Monitor Status (1 = UP, 0= DOWN, 2= PENDING, 3= MAINTENANCE)",
labelNames: commonLabels
});
class Prometheus {
monitorLabelValues = {};
/**
* @param {object} monitor Monitor object to monitor
* Metric: monitor_cert_days_remaining
* @type {PrometheusClient.Gauge<string> | null}
*/
constructor(monitor) {
static monitorCertDaysRemaining = null;
/**
* Metric: monitor_cert_is_valid
* @type {PrometheusClient.Gauge<string> | null}
*/
static monitorCertIsValid = null;
/**
* Metric: monitor_response_time
* @type {PrometheusClient.Gauge<string> | null}
*/
static monitorResponseTime = null;
/**
* Metric: monitor_status
* @type {PrometheusClient.Gauge<string> | null}
*/
static monitorStatus = null;
/**
* All registered metric labels.
* @type {string[] | null}
*/
static monitorLabelNames = null;
/**
* Monitor labels/values combination.
* @type {{}}
*/
monitorLabelValues;
/**
* Initialize metrics and get all label names the first time called.
* @returns {void}
*/
static async initMetrics() {
if (!this.monitorLabelNames) {
let labelNames = await R.getCol("SELECT name FROM tag");
this.monitorLabelNames = [ ...commonLabels, ...labelNames ];
}
if (!this.monitorCertDaysRemaining) {
this.monitorCertDaysRemaining = new PrometheusClient.Gauge({
name: "monitor_cert_days_remaining",
help: "The number of days remaining until the certificate expires",
labelNames: this.monitorLabelNames
});
}
if (!this.monitorCertIsValid) {
this.monitorCertIsValid = new PrometheusClient.Gauge({
name: "monitor_cert_is_valid",
help: "Is the certificate still valid? (1 = Yes, 0 = No)",
labelNames: this.monitorLabelNames
});
}
if (!this.monitorResponseTime) {
this.monitorResponseTime = new PrometheusClient.Gauge({
name: "monitor_response_time",
help: "Monitor Response Time (ms)",
labelNames: this.monitorLabelNames
});
}
if (!this.monitorStatus) {
this.monitorStatus = new PrometheusClient.Gauge({
name: "monitor_status",
help: "Monitor Status (1 = UP, 0 = DOWN, 2 = PENDING, 3 = MAINTENANCE)",
labelNames: this.monitorLabelNames
});
}
}
/**
* Wrapper to create a `Prometheus` instance and ensure metrics are initialized.
* @param {Monitor} monitor Monitor object to monitor
* @returns {Promise<Prometheus>} `Prometheus` instance
*/
static async createAndInitMetrics(monitor) {
await Prometheus.initMetrics();
let tags = await monitor.getTags();
return new Prometheus(monitor, tags);
}
/**
* Creates a prometheus metric instance.
*
* Note: Make sure to call `Prometheus.initMetrics()` once prior creating Prometheus instances.
* @param {Monitor} monitor Monitor object to monitor
* @param {Promise<LooseObject<any>[]>} tags Tags of the monitor
*/
constructor(monitor, tags) {
this.monitorLabelValues = {
monitor_name: monitor.name,
monitor_type: monitor.type,
@ -46,6 +113,12 @@ class Prometheus {
monitor_hostname: monitor.hostname,
monitor_port: monitor.port
};
Object.values(tags)
// only label names that were known at first metric creation.
.filter(tag => Prometheus.monitorLabelNames.includes(tag.name))
.forEach(tag => {
this.monitorLabelValues[tag.name] = tag.value;
});
}
/**
@ -55,7 +128,6 @@ class Prometheus {
* @returns {void}
*/
update(heartbeat, tlsInfo) {
if (typeof tlsInfo !== "undefined") {
try {
let isValid;
@ -64,7 +136,7 @@ class Prometheus {
} else {
isValid = 0;
}
monitorCertIsValid.set(this.monitorLabelValues, isValid);
Prometheus.monitorCertIsValid.set(this.monitorLabelValues, isValid);
} catch (e) {
log.error("prometheus", "Caught error");
log.error("prometheus", e);
@ -72,7 +144,7 @@ class Prometheus {
try {
if (tlsInfo.certInfo != null) {
monitorCertDaysRemaining.set(this.monitorLabelValues, tlsInfo.certInfo.daysRemaining);
Prometheus.monitorCertDaysRemaining.set(this.monitorLabelValues, tlsInfo.certInfo.daysRemaining);
}
} catch (e) {
log.error("prometheus", "Caught error");
@ -82,7 +154,7 @@ class Prometheus {
if (heartbeat) {
try {
monitorStatus.set(this.monitorLabelValues, heartbeat.status);
Prometheus.monitorStatus.set(this.monitorLabelValues, heartbeat.status);
} catch (e) {
log.error("prometheus", "Caught error");
log.error("prometheus", e);
@ -90,10 +162,10 @@ class Prometheus {
try {
if (typeof heartbeat.ping === "number") {
monitorResponseTime.set(this.monitorLabelValues, heartbeat.ping);
Prometheus.monitorResponseTime.set(this.monitorLabelValues, heartbeat.ping);
} else {
// Is it good?
monitorResponseTime.set(this.monitorLabelValues, -1);
Prometheus.monitorResponseTime.set(this.monitorLabelValues, -1);
}
} catch (e) {
log.error("prometheus", "Caught error");
@ -108,10 +180,10 @@ class Prometheus {
*/
remove() {
try {
monitorCertDaysRemaining.remove(this.monitorLabelValues);
monitorCertIsValid.remove(this.monitorLabelValues);
monitorResponseTime.remove(this.monitorLabelValues);
monitorStatus.remove(this.monitorLabelValues);
Prometheus.monitorCertDaysRemaining?.remove(this.monitorLabelValues);
Prometheus.monitorCertIsValid?.remove(this.monitorLabelValues);
Prometheus.monitorResponseTime?.remove(this.monitorLabelValues);
Prometheus.monitorStatus?.remove(this.monitorLabelValues);
} catch (e) {
console.error(e);
}

View File

@ -2,7 +2,7 @@ const { R } = require("redbean-node");
const HttpProxyAgent = require("http-proxy-agent");
const HttpsProxyAgent = require("https-proxy-agent");
const SocksProxyAgent = require("socks-proxy-agent");
const { debug } = require("../src/util");
const { log } = require("../src/util");
const { UptimeKumaServer } = require("./uptime-kuma-server");
const { CookieJar } = require("tough-cookie");
const { createCookieAgent } = require("http-cookie-agent/http");
@ -110,9 +110,9 @@ class Proxy {
proxyOptions.auth = `${proxy.username}:${proxy.password}`;
}
debug(`Proxy Options: ${JSON.stringify(proxyOptions)}`);
debug(`HTTP Agent Options: ${JSON.stringify(httpAgentOptions)}`);
debug(`HTTPS Agent Options: ${JSON.stringify(httpsAgentOptions)}`);
log.debug("update-proxy", `Proxy Options: ${JSON.stringify(proxyOptions)}`);
log.debug("update-proxy", `HTTP Agent Options: ${JSON.stringify(httpAgentOptions)}`);
log.debug("update-proxy", `HTTPS Agent Options: ${JSON.stringify(httpsAgentOptions)}`);
switch (proxy.protocol) {
case "http":

View File

@ -1,6 +1,5 @@
let express = require("express");
const {
setting,
allowDevAllOrigin,
allowAllOrigin,
percentageToColor,
@ -18,6 +17,7 @@ const { makeBadge } = require("badge-maker");
const { Prometheus } = require("../prometheus");
const Database = require("../database");
const { UptimeCalculator } = require("../uptime-calculator");
const { Settings } = require("../settings");
let router = express.Router();
@ -30,7 +30,7 @@ router.get("/api/entry-page", async (request, response) => {
let result = { };
let hostname = request.hostname;
if ((await setting("trustProxy")) && request.headers["x-forwarded-host"]) {
if ((await Settings.get("trustProxy")) && request.headers["x-forwarded-host"]) {
hostname = request.headers["x-forwarded-host"];
}
@ -232,8 +232,8 @@ router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (reques
let requestedDuration = request.params.duration !== undefined ? request.params.duration : "24h";
const overrideValue = value && parseFloat(value);
if (requestedDuration === "24") {
requestedDuration = "24h";
if (/^[0-9]+$/.test(requestedDuration)) {
requestedDuration = `${requestedDuration}h`;
}
let publicMonitor = await R.getRow(`
@ -265,7 +265,7 @@ router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (reques
// build a label string. If a custom label is given, override the default one (requestedDuration)
badgeValues.label = filterAndJoin([
labelPrefix,
label ?? `Uptime (${requestedDuration}${labelSuffix})`,
label ?? `Uptime (${requestedDuration.slice(0, -1)}${labelSuffix})`,
]);
badgeValues.message = filterAndJoin([ prefix, cleanUptime, suffix ]);
}
@ -302,8 +302,8 @@ router.get("/api/badge/:id/ping/:duration?", cache("5 minutes"), async (request,
let requestedDuration = request.params.duration !== undefined ? request.params.duration : "24h";
const overrideValue = value && parseFloat(value);
if (requestedDuration === "24") {
requestedDuration = "24h";
if (/^[0-9]+$/.test(requestedDuration)) {
requestedDuration = `${requestedDuration}h`;
}
// Check if monitor is public
@ -325,7 +325,7 @@ router.get("/api/badge/:id/ping/:duration?", cache("5 minutes"), async (request,
// use a given, custom labelColor or use the default badge label color (defined by badge-maker)
badgeValues.labelColor = labelColor ?? "";
// build a lable string. If a custom label is given, override the default one (requestedDuration)
badgeValues.label = filterAndJoin([ labelPrefix, label ?? `Avg. Ping (${requestedDuration}${labelSuffix})` ]);
badgeValues.label = filterAndJoin([ labelPrefix, label ?? `Avg. Ping (${requestedDuration.slice(0, -1)}${labelSuffix})` ]);
badgeValues.message = filterAndJoin([ prefix, avgPing, suffix ]);
}

View File

@ -18,6 +18,11 @@ router.get("/status/:slug", cache("5 minutes"), async (request, response) => {
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
});
router.get("/status/:slug/rss", cache("5 minutes"), async (request, response) => {
let slug = request.params.slug;
await StatusPage.handleStatusPageRSSResponse(response, slug);
});
router.get("/status", cache("5 minutes"), async (request, response) => {
let slug = "default";
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);

View File

@ -19,7 +19,7 @@ const nodeVersion = process.versions.node;
// Get the required Node.js version from package.json
const requiredNodeVersions = require("../package.json").engines.node;
const bannedNodeVersions = " < 14 || 20.0.* || 20.1.* || 20.2.* || 20.3.* ";
const bannedNodeVersions = " < 18 || 20.0.* || 20.1.* || 20.2.* || 20.3.* ";
console.log(`Your Node.js version: ${nodeVersion}`);
const semver = require("semver");
@ -90,8 +90,7 @@ const Monitor = require("./model/monitor");
const User = require("./model/user");
log.debug("server", "Importing Settings");
const { getSettings, setSettings, setting, initJWTSecret, checkLogin, doubleCheckPassword, shake256, SHAKE256_LENGTH, allowDevAllOrigin,
} = require("./util-server");
const { initJWTSecret, checkLogin, doubleCheckPassword, shake256, SHAKE256_LENGTH, allowDevAllOrigin } = require("./util-server");
log.debug("server", "Importing Notification");
const { Notification } = require("./notification");
@ -132,9 +131,9 @@ const twoFAVerifyOptions = {
const testMode = !!args["test"] || false;
// Must be after io instantiation
const { sendNotificationList, sendHeartbeatList, sendInfo, sendProxyList, sendDockerHostList, sendAPIKeyList, sendRemoteBrowserList } = require("./client");
const { sendNotificationList, sendHeartbeatList, sendInfo, sendProxyList, sendDockerHostList, sendAPIKeyList, sendRemoteBrowserList, sendMonitorTypeList } = require("./client");
const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler");
const databaseSocketHandler = require("./socket-handlers/database-socket-handler");
const { databaseSocketHandler } = require("./socket-handlers/database-socket-handler");
const { remoteBrowserSocketHandler } = require("./socket-handlers/remote-browser-socket-handler");
const TwoFA = require("./2fa");
const StatusPage = require("./model/status_page");
@ -201,7 +200,7 @@ let needSetup = false;
// Entry Page
app.get("/", async (request, response) => {
let hostname = request.hostname;
if (await setting("trustProxy")) {
if (await Settings.get("trustProxy")) {
const proxy = request.headers["x-forwarded-host"];
if (proxy) {
hostname = proxy;
@ -246,12 +245,42 @@ let needSetup = false;
log.debug("test", request.body);
response.send("OK");
});
const fs = require("fs");
app.get("/_e2e/take-sqlite-snapshot", async (request, response) => {
await Database.close();
try {
fs.cpSync(Database.sqlitePath, `${Database.sqlitePath}.e2e-snapshot`);
} catch (err) {
throw new Error("Unable to copy SQLite DB.");
}
await Database.connect();
response.send("Snapshot taken.");
});
app.get("/_e2e/restore-sqlite-snapshot", async (request, response) => {
if (!fs.existsSync(`${Database.sqlitePath}.e2e-snapshot`)) {
throw new Error("Snapshot doesn't exist.");
}
await Database.close();
try {
fs.cpSync(`${Database.sqlitePath}.e2e-snapshot`, Database.sqlitePath);
} catch (err) {
throw new Error("Unable to copy snapshot file.");
}
await Database.connect();
response.send("Snapshot restored.");
});
}
// Robots.txt
app.get("/robots.txt", async (_request, response) => {
let txt = "User-agent: *\nDisallow:";
if (!await setting("searchEngineIndex")) {
if (!await Settings.get("searchEngineIndex")) {
txt += " /";
}
response.setHeader("Content-Type", "text/plain");
@ -686,6 +715,8 @@ let needSetup = false;
monitor.kafkaProducerBrokers = JSON.stringify(monitor.kafkaProducerBrokers);
monitor.kafkaProducerSaslOptions = JSON.stringify(monitor.kafkaProducerSaslOptions);
monitor.conditions = JSON.stringify(monitor.conditions);
bean.import(monitor);
bean.user_id = socket.userID;
@ -701,7 +732,7 @@ let needSetup = false;
await startMonitor(socket.userID, bean.id);
}
log.info("monitor", `Added Monitor: ${monitor.id} User ID: ${socket.userID}`);
log.info("monitor", `Added Monitor: ${bean.id} User ID: ${socket.userID}`);
callback({
ok: true,
@ -826,11 +857,17 @@ let needSetup = false;
bean.kafkaProducerAllowAutoTopicCreation = monitor.kafkaProducerAllowAutoTopicCreation;
bean.kafkaProducerSaslOptions = JSON.stringify(monitor.kafkaProducerSaslOptions);
bean.kafkaProducerMessage = monitor.kafkaProducerMessage;
bean.cacheBust = monitor.cacheBust;
bean.kafkaProducerSsl = monitor.kafkaProducerSsl;
bean.kafkaProducerAllowAutoTopicCreation =
monitor.kafkaProducerAllowAutoTopicCreation;
bean.gamedigGivenPortOnly = monitor.gamedigGivenPortOnly;
bean.remote_browser = monitor.remote_browser;
bean.snmpVersion = monitor.snmpVersion;
bean.snmpOid = monitor.snmpOid;
bean.jsonPathOperator = monitor.jsonPathOperator;
bean.timeout = monitor.timeout;
bean.conditions = JSON.stringify(monitor.conditions);
bean.validate();
@ -1287,7 +1324,7 @@ let needSetup = false;
socket.on("getSettings", async (callback) => {
try {
checkLogin(socket);
const data = await getSettings("general");
const data = await Settings.getSettings("general");
if (!data.serverTimezone) {
data.serverTimezone = await server.getTimezone();
@ -1315,7 +1352,7 @@ let needSetup = false;
// Disabled Auth + Want to Enable Auth => No Check
// Enabled Auth + Want to Disable Auth => Check!!
// Enabled Auth + Want to Enable Auth => No Check
const currentDisabledAuth = await setting("disableAuth");
const currentDisabledAuth = await Settings.get("disableAuth");
if (!currentDisabledAuth && data.disableAuth) {
await doubleCheckPassword(socket, currentPassword);
}
@ -1329,7 +1366,7 @@ let needSetup = false;
const previousChromeExecutable = await Settings.get("chromeExecutable");
const previousNSCDStatus = await Settings.get("nscd");
await setSettings("general", data);
await Settings.setSettings("general", data);
server.entryPage = data.entryPage;
// Also need to apply timezone globally
@ -1425,7 +1462,7 @@ let needSetup = false;
});
} catch (e) {
console.error(e);
log.error("server", e);
callback({
ok: false,
@ -1538,7 +1575,7 @@ let needSetup = false;
// ***************************
log.debug("auth", "check auto login");
if (await setting("disableAuth")) {
if (await Settings.get("disableAuth")) {
log.info("auth", "Disabled Auth: auto login to admin");
await afterLogin(socket, await R.findOne("user"));
socket.emit("autoLogin");
@ -1636,6 +1673,7 @@ async function afterLogin(socket, user) {
sendDockerHostList(socket),
sendAPIKeyList(socket),
sendRemoteBrowserList(socket),
sendMonitorTypeList(socket),
]);
await StatusPage.sendStatusPageList(io, socket);

View File

@ -60,7 +60,7 @@ module.exports.apiKeySocketHandler = (socket) => {
ok: true,
});
} catch (e) {
console.error(e);
log.error("apikeys", e);
callback({
ok: false,
msg: e.message,

View File

@ -1,7 +1,8 @@
const { checkLogin, setSetting, setting, doubleCheckPassword } = require("../util-server");
const { checkLogin, doubleCheckPassword } = require("../util-server");
const { CloudflaredTunnel } = require("node-cloudflared-tunnel");
const { UptimeKumaServer } = require("../uptime-kuma-server");
const { log } = require("../../src/util");
const { Settings } = require("../settings");
const io = UptimeKumaServer.getInstance().io;
const prefix = "cloudflared_";
@ -40,7 +41,7 @@ module.exports.cloudflaredSocketHandler = (socket) => {
socket.join("cloudflared");
io.to(socket.userID).emit(prefix + "installed", cloudflared.checkInstalled());
io.to(socket.userID).emit(prefix + "running", cloudflared.running);
io.to(socket.userID).emit(prefix + "token", await setting("cloudflaredTunnelToken"));
io.to(socket.userID).emit(prefix + "token", await Settings.get("cloudflaredTunnelToken"));
} catch (error) { }
});
@ -55,7 +56,7 @@ module.exports.cloudflaredSocketHandler = (socket) => {
try {
checkLogin(socket);
if (token && typeof token === "string") {
await setSetting("cloudflaredTunnelToken", token);
await Settings.set("cloudflaredTunnelToken", token);
cloudflared.token = token;
} else {
cloudflared.token = null;
@ -67,7 +68,7 @@ module.exports.cloudflaredSocketHandler = (socket) => {
socket.on(prefix + "stop", async (currentPassword, callback) => {
try {
checkLogin(socket);
const disabledAuth = await setting("disableAuth");
const disabledAuth = await Settings.get("disableAuth");
if (!disabledAuth) {
await doubleCheckPassword(socket, currentPassword);
}
@ -83,7 +84,7 @@ module.exports.cloudflaredSocketHandler = (socket) => {
socket.on(prefix + "removeToken", async () => {
try {
checkLogin(socket);
await setSetting("cloudflaredTunnelToken", "");
await Settings.set("cloudflaredTunnelToken", "");
} catch (error) { }
});
@ -96,15 +97,15 @@ module.exports.cloudflaredSocketHandler = (socket) => {
*/
module.exports.autoStart = async (token) => {
if (!token) {
token = await setting("cloudflaredTunnelToken");
token = await Settings.get("cloudflaredTunnelToken");
} else {
// Override the current token via args or env var
await setSetting("cloudflaredTunnelToken", token);
console.log("Use cloudflared token from args or env var");
await Settings.set("cloudflaredTunnelToken", token);
log.info("cloudflare", "Use cloudflared token from args or env var");
}
if (token) {
console.log("Start cloudflared");
log.info("cloudflare", "Start cloudflared");
cloudflared.token = token;
cloudflared.start();
}

View File

@ -6,7 +6,7 @@ const Database = require("../database");
* @param {Socket} socket Socket.io instance
* @returns {void}
*/
module.exports = (socket) => {
module.exports.databaseSocketHandler = (socket) => {
// Post or edit incident
socket.on("getDatabaseSize", async (callback) => {

View File

@ -29,8 +29,13 @@ function getGameList() {
return gameList;
}
/**
* Handler for general events
* @param {Socket} socket Socket.io instance
* @param {UptimeKumaServer} server Uptime Kuma server
* @returns {void}
*/
module.exports.generalSocketHandler = (socket, server) => {
socket.on("initServerTimezone", async (timezone) => {
try {
checkLogin(socket);

View File

@ -67,7 +67,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
});
} catch (e) {
console.error(e);
log.error("maintenance", e);
callback({
ok: false,
msg: e.message,
@ -177,7 +177,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
ok: true,
});
} catch (e) {
console.error(e);
log.error("maintenance", e);
callback({
ok: false,
msg: e.message,
@ -201,7 +201,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
});
} catch (e) {
console.error(e);
log.error("maintenance", e);
callback({
ok: false,
msg: e.message,
@ -225,7 +225,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
});
} catch (e) {
console.error(e);
log.error("maintenance", e);
callback({
ok: false,
msg: e.message,

View File

@ -1,5 +1,5 @@
const { R } = require("redbean-node");
const { checkLogin, setSetting } = require("../util-server");
const { checkLogin } = require("../util-server");
const dayjs = require("dayjs");
const { log } = require("../../src/util");
const ImageDataURI = require("../image-data-uri");
@ -7,6 +7,7 @@ const Database = require("../database");
const apicache = require("../modules/apicache");
const StatusPage = require("../model/status_page");
const { UptimeKumaServer } = require("../uptime-kuma-server");
const { Settings } = require("../settings");
/**
* Socket handlers for status page
@ -233,7 +234,7 @@ module.exports.statusPageSocketHandler = (socket) => {
// Also change entry page to new slug if it is the default one, and slug is changed.
if (server.entryPage === "statusPage-" + slug && statusPage.slug !== slug) {
server.entryPage = "statusPage-" + statusPage.slug;
await setSetting("entryPage", server.entryPage, "general");
await Settings.set("entryPage", server.entryPage, "general");
}
apicache.clear();
@ -291,7 +292,7 @@ module.exports.statusPageSocketHandler = (socket) => {
});
} catch (error) {
console.error(error);
log.error("socket", error);
callback({
ok: false,
msg: error.message,
@ -313,7 +314,7 @@ module.exports.statusPageSocketHandler = (socket) => {
// Reset entry page if it is the default one.
if (server.entryPage === "statusPage-" + slug) {
server.entryPage = "dashboard";
await setSetting("entryPage", server.entryPage, "general");
await Settings.set("entryPage", server.entryPage, "general");
}
// No need to delete records from `status_page_cname`, because it has cascade foreign key.

View File

@ -543,7 +543,9 @@ class UptimeCalculator {
if (type === "minute" && num > 24 * 60) {
throw new Error("The maximum number of minutes is 1440");
}
if (type === "day" && num > 365) {
throw new Error("The maximum number of days is 365");
}
// Get the current time period key based on the type
let key = this.getKey(this.getCurrentDate(), type);
@ -741,20 +743,36 @@ class UptimeCalculator {
}
/**
* Get the uptime data by duration
* @param {'24h'|'30d'|'1y'} duration Only accept 24h, 30d, 1y
* Get the uptime data for given duration.
* @param {string} duration A string with a number and a unit (m,h,d,w,M,y), such as 24h, 30d, 1y.
* @returns {UptimeDataResult} UptimeDataResult
* @throws {Error} Invalid duration
* @throws {Error} Invalid duration / Unsupported unit
*/
getDataByDuration(duration) {
if (duration === "24h") {
return this.get24Hour();
} else if (duration === "30d") {
return this.get30Day();
} else if (duration === "1y") {
return this.get1Year();
} else {
throw new Error("Invalid duration");
const durationNumStr = duration.slice(0, -1);
if (!/^[0-9]+$/.test(durationNumStr)) {
throw new Error(`Invalid duration: ${duration}`);
}
const num = Number(durationNumStr);
const unit = duration.slice(-1);
switch (unit) {
case "m":
return this.getData(num, "minute");
case "h":
return this.getData(num, "hour");
case "d":
return this.getData(num, "day");
case "w":
return this.getData(7 * num, "day");
case "M":
return this.getData(30 * num, "day");
case "y":
return this.getData(365 * num, "day");
default:
throw new Error(`Unsupported unit (${unit}) for badge duration ${duration}`
);
}
}

View File

@ -113,6 +113,7 @@ class UptimeKumaServer {
UptimeKumaServer.monitorTypeList["tailscale-ping"] = new TailscalePing();
UptimeKumaServer.monitorTypeList["dns"] = new DnsMonitorType();
UptimeKumaServer.monitorTypeList["mqtt"] = new MqttMonitorType();
UptimeKumaServer.monitorTypeList["snmp"] = new SNMPMonitorType();
UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType();
// Allow all CORS origins (polling) in development
@ -517,4 +518,5 @@ const { RealBrowserMonitorType } = require("./monitor-types/real-browser-monitor
const { TailscalePing } = require("./monitor-types/tailscale-ping");
const { DnsMonitorType } = require("./monitor-types/dns");
const { MqttMonitorType } = require("./monitor-types/mqtt");
const { SNMPMonitorType } = require("./monitor-types/snmp");
const { MongodbMonitorType } = require("./monitor-types/mongodb");

View File

@ -12,7 +12,6 @@ const { Client } = require("pg");
const postgresConParse = require("pg-connection-string").parse;
const mysql = require("mysql2");
const { NtlmClient } = require("./modules/axios-ntlm/lib/ntlmClient.js");
const { Settings } = require("./settings");
const grpc = require("@grpc/grpc-js");
const protojs = require("protobufjs");
const radiusClient = require("node-radius-client");
@ -521,46 +520,6 @@ exports.redisPingAsync = function (dsn, rejectUnauthorized) {
});
};
/**
* Retrieve value of setting based on key
* @param {string} key Key of setting to retrieve
* @returns {Promise<any>} Value
* @deprecated Use await Settings.get(key)
*/
exports.setting = async function (key) {
return await Settings.get(key);
};
/**
* 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>}
*/
exports.setSetting = async function (key, value, type = null) {
await Settings.set(key, value, type);
};
/**
* Get settings based on type
* @param {string} type The type of setting
* @returns {Promise<Bean>} Settings of requested type
*/
exports.getSettings = async function (type) {
return await Settings.getSettings(type);
};
/**
* Set settings based on type
* @param {string} type Type of settings to set
* @param {object} data Values of settings
* @returns {Promise<void>}
*/
exports.setSettings = async function (type, data) {
await Settings.setSettings(type, data);
};
// ssl-checker by @dyaa
//https://github.com/dyaa/ssl-checker/blob/master/src/index.ts

View File

@ -576,6 +576,12 @@ optgroup {
outline: none !important;
}
.prism-editor__container {
.important {
font-weight: var(--bs-body-font-weight) !important;
}
}
h5.settings-subheading::after {
content: "";
display: block;

View File

@ -0,0 +1,152 @@
<template>
<div class="monitor-condition mb-3" data-testid="condition">
<button
v-if="!isInGroup || !isFirst || !isLast"
class="btn btn-outline-danger remove-button"
type="button"
:aria-label="$t('conditionDelete')"
data-testid="remove-condition"
@click="remove"
>
<font-awesome-icon icon="trash" />
</button>
<select v-if="!isFirst" v-model="model.andOr" class="form-select and-or-select" data-testid="condition-and-or">
<option value="and">{{ $t("and") }}</option>
<option value="or">{{ $t("or") }}</option>
</select>
<select v-model="model.variable" class="form-select" data-testid="condition-variable">
<option
v-for="variable in conditionVariables"
:key="variable.id"
:value="variable.id"
>
{{ $t(variable.id) }}
</option>
</select>
<select v-model="model.operator" class="form-select" data-testid="condition-operator">
<option
v-for="operator in getVariableOperators(model.variable)"
:key="operator.id"
:value="operator.id"
>
{{ $t(operator.caption) }}
</option>
</select>
<input
v-model="model.value"
type="text"
class="form-control"
:aria-label="$t('conditionValuePlaceholder')"
data-testid="condition-value"
required
/>
</div>
</template>
<script>
export default {
name: "EditMonitorCondition",
props: {
/**
* The monitor condition
*/
modelValue: {
type: Object,
required: true,
},
/**
* Whether this is the first condition
*/
isFirst: {
type: Boolean,
required: true,
},
/**
* Whether this is the last condition
*/
isLast: {
type: Boolean,
required: true,
},
/**
* Whether this condition is in a group
*/
isInGroup: {
type: Boolean,
required: false,
default: false,
},
/**
* Variable choices
*/
conditionVariables: {
type: Array,
required: true,
},
},
emits: [ "update:modelValue", "remove" ],
computed: {
model: {
get() {
return this.modelValue;
},
set(value) {
this.$emit("update:modelValue", value);
}
}
},
methods: {
remove() {
this.$emit("remove", this.model);
},
getVariableOperators(variableId) {
return this.conditionVariables.find(v => v.id === variableId)?.operators ?? [];
},
},
};
</script>
<style lang="scss" scoped>
@import "../assets/vars.scss";
.monitor-condition {
display: flex;
flex-wrap: wrap;
}
.remove-button {
justify-self: flex-end;
margin-bottom: 12px;
margin-left: auto;
}
@container (min-width: 500px) {
.monitor-condition {
display: flex;
flex-wrap: nowrap;
}
.remove-button {
margin-bottom: 0;
margin-left: 10px;
order: 100;
}
.and-or-select {
width: auto;
}
}
</style>

View File

@ -0,0 +1,189 @@
<template>
<div class="condition-group mb-3" data-testid="condition-group">
<div class="d-flex">
<select v-if="!isFirst" v-model="model.andOr" class="form-select" style="width: auto;" data-testid="condition-group-and-or">
<option value="and">{{ $t("and") }}</option>
<option value="or">{{ $t("or") }}</option>
</select>
</div>
<div class="condition-group-inner mt-2 pa-2">
<div class="condition-group-conditions">
<template v-for="(child, childIndex) in model.children" :key="childIndex">
<EditMonitorConditionGroup
v-if="child.type === 'group'"
v-model="model.children[childIndex]"
:is-first="childIndex === 0"
:get-new-group="getNewGroup"
:get-new-condition="getNewCondition"
:condition-variables="conditionVariables"
@remove="removeChild"
/>
<EditMonitorCondition
v-else
v-model="model.children[childIndex]"
:is-first="childIndex === 0"
:is-last="childIndex === model.children.length - 1"
:is-in-group="true"
:condition-variables="conditionVariables"
@remove="removeChild"
/>
</template>
</div>
<div class="condition-group-actions mt-3">
<button class="btn btn-outline-secondary me-2" type="button" data-testid="add-condition-button" @click="addCondition">
{{ $t("conditionAdd") }}
</button>
<button class="btn btn-outline-secondary me-2" type="button" data-testid="add-group-button" @click="addGroup">
{{ $t("conditionAddGroup") }}
</button>
<button
class="btn btn-outline-danger"
type="button"
:aria-label="$t('conditionDeleteGroup')"
data-testid="remove-condition-group"
@click="remove"
>
<font-awesome-icon icon="trash" />
</button>
</div>
</div>
</div>
</template>
<script>
import EditMonitorCondition from "./EditMonitorCondition.vue";
export default {
name: "EditMonitorConditionGroup",
components: {
EditMonitorCondition,
},
props: {
/**
* The condition group
*/
modelValue: {
type: Object,
required: true,
},
/**
* Whether this is the first condition
*/
isFirst: {
type: Boolean,
required: true,
},
/**
* Function to generate a new group model
*/
getNewGroup: {
type: Function,
required: true,
},
/**
* Function to generate a new condition model
*/
getNewCondition: {
type: Function,
required: true,
},
/**
* Variable choices
*/
conditionVariables: {
type: Array,
required: true,
},
},
emits: [ "update:modelValue", "remove" ],
computed: {
model: {
get() {
return this.modelValue;
},
set(value) {
this.$emit("update:modelValue", value);
}
}
},
methods: {
addGroup() {
const conditions = [ ...this.model.children ];
conditions.push(this.getNewGroup());
this.model.children = conditions;
},
addCondition() {
const conditions = [ ...this.model.children ];
conditions.push(this.getNewCondition());
this.model.children = conditions;
},
remove() {
this.$emit("remove", this.model);
},
removeChild(child) {
const idx = this.model.children.indexOf(child);
if (idx !== -1) {
this.model.children.splice(idx, 1);
}
},
},
};
</script>
<style lang="scss" scoped>
@import "../assets/vars.scss";
.condition-group-inner {
background: rgba(0, 0, 0, 0.05);
padding: 20px;
}
.dark .condition-group-inner {
background: rgba(255, 255, 255, 0.05);
}
.condition-group-conditions {
container-type: inline-size;
}
.condition-group-actions {
display: grid;
gap: 10px;
}
// Delete button
.condition-group-actions > :last-child {
margin-left: auto;
margin-top: 14px;
}
@container (min-width: 400px) {
.condition-group-actions {
display: flex;
}
// Delete button
.condition-group-actions > :last-child {
margin-left: auto;
margin-top: 0;
}
.btn-delete-group {
margin-left: auto;
}
}
</style>

View File

@ -0,0 +1,149 @@
<template>
<div class="monitor-conditions">
<label class="form-label">{{ $t("Conditions") }}</label>
<div class="monitor-conditions-conditions">
<template v-for="(condition, conditionIndex) in model" :key="conditionIndex">
<EditMonitorConditionGroup
v-if="condition.type === 'group'"
v-model="model[conditionIndex]"
:is-first="conditionIndex === 0"
:get-new-group="getNewGroup"
:get-new-condition="getNewCondition"
:condition-variables="conditionVariables"
@remove="removeCondition"
/>
<EditMonitorCondition
v-else
v-model="model[conditionIndex]"
:is-first="conditionIndex === 0"
:is-last="conditionIndex === model.length - 1"
:condition-variables="conditionVariables"
@remove="removeCondition"
/>
</template>
</div>
<div class="monitor-conditions-buttons">
<button class="btn btn-outline-secondary me-2" type="button" data-testid="add-condition-button" @click="addCondition">
{{ $t("conditionAdd") }}
</button>
<button class="btn btn-outline-secondary me-2" type="button" data-testid="add-group-button" @click="addGroup">
{{ $t("conditionAddGroup") }}
</button>
</div>
</div>
</template>
<script>
import EditMonitorConditionGroup from "./EditMonitorConditionGroup.vue";
import EditMonitorCondition from "./EditMonitorCondition.vue";
export default {
name: "EditMonitorConditions",
components: {
EditMonitorConditionGroup,
EditMonitorCondition,
},
props: {
/**
* The monitor conditions
*/
modelValue: {
type: Array,
required: true,
},
conditionVariables: {
type: Array,
required: true,
},
},
emits: [ "update:modelValue" ],
computed: {
model: {
get() {
return this.modelValue;
},
set(value) {
this.$emit("update:modelValue", value);
}
}
},
created() {
if (this.model.length === 0) {
this.addCondition();
}
},
methods: {
getNewGroup() {
return {
type: "group",
children: [ this.getNewCondition() ],
andOr: "and",
};
},
getNewCondition() {
const firstVariable = this.conditionVariables[0]?.id || null;
const firstOperator = this.getVariableOperators(firstVariable)[0] || null;
return {
type: "expression",
variable: firstVariable,
operator: firstOperator?.id || null,
value: "",
andOr: "and",
};
},
addGroup() {
const conditions = [ ...this.model ];
conditions.push(this.getNewGroup());
this.$emit("update:modelValue", conditions);
},
addCondition() {
const conditions = [ ...this.model ];
conditions.push(this.getNewCondition());
this.$emit("update:modelValue", conditions);
},
removeCondition(condition) {
const conditions = [ ...this.model ];
const idx = conditions.indexOf(condition);
if (idx !== -1) {
conditions.splice(idx, 1);
this.$emit("update:modelValue", conditions);
}
},
getVariableOperators(variableId) {
return this.conditionVariables.find(v => v.id === variableId)?.operators ?? [];
},
},
};
</script>
<style lang="scss" scoped>
@import "../assets/vars.scss";
.monitor-conditions,
.monitor-conditions-conditions {
container-type: inline-size;
}
.monitor-conditions-buttons {
display: grid;
gap: 10px;
}
@container (min-width: 400px) {
.monitor-conditions-buttons {
display: flex;
}
}
</style>

View File

@ -14,7 +14,7 @@
v-if="!$root.isMobile && size !== 'small' && beatList.length > 4 && $root.styleElapsedTime !== 'none'"
class="d-flex justify-content-between align-items-center word" :style="timeStyle"
>
<div>{{ timeSinceFirstBeat }} ago</div>
<div>{{ timeSinceFirstBeat }}</div>
<div v-if="$root.styleElapsedTime === 'with-line'" class="connecting-line"></div>
<div>{{ timeSinceLastBeat }}</div>
</div>
@ -184,11 +184,11 @@ export default {
}
if (seconds < tolerance) {
return "now";
return this.$t("now");
} else if (seconds < 60 * 60) {
return (seconds / 60).toFixed(0) + "m ago";
return this.$t("time ago", [ (seconds / 60).toFixed(0) + "m" ]);
} else {
return (seconds / 60 / 60).toFixed(0) + "h ago";
return this.$t("time ago", [ (seconds / 60 / 60).toFixed(0) + "h" ]);
}
}
},

View File

@ -45,7 +45,7 @@
</span>
</div>
</div>
<div ref="monitorList" class="monitor-list" :class="{ scrollbar: scrollbar }" :style="monitorListStyle">
<div ref="monitorList" class="monitor-list" :class="{ scrollbar: scrollbar }" :style="monitorListStyle" data-testid="monitor-list">
<div v-if="Object.keys($root.monitorList).length === 0" class="text-center mt-3">
{{ $t("No Monitors, please") }} <router-link to="/add">{{ $t("add one") }}</router-link>
</div>

View File

@ -43,12 +43,15 @@
<div v-if="!isCollapsed" class="childs">
<MonitorListItem
v-for="(item, index) in sortedChildMonitorList"
:key="index" :monitor="item"
:key="index"
:monitor="item"
:isSelectMode="isSelectMode"
:isSelected="isSelected"
:select="select"
:deselect="deselect"
:depth="depth + 1"
:filter-func="filterFunc"
:sort-func="sortFunc"
/>
</div>
</transition>

View File

@ -135,6 +135,7 @@ export default {
"ntfy": "Ntfy",
"octopush": "Octopush",
"OneBot": "OneBot",
"Onesender": "Onesender",
"Opsgenie": "Opsgenie",
"PagerDuty": "PagerDuty",
"PagerTree": "PagerTree",
@ -144,6 +145,7 @@ export default {
"pushy": "Pushy",
"rocket.chat": "Rocket.Chat",
"signal": "Signal",
"SIGNL4": "SIGNL4",
"slack": "Slack",
"squadcast": "SquadCast",
"SMSEagle": "SMSEagle",
@ -178,6 +180,7 @@ export default {
"WeCom": "WeCom (企业微信群机器人)",
"ServerChan": "ServerChan (Server酱)",
"smsc": "SMSC",
"WPush": "WPush(wpush.cn)",
};
// Sort by notification name

View File

@ -7,12 +7,12 @@
:animation="100"
>
<template #item="group">
<div class="mb-5 ">
<div class="mb-5" data-testid="group">
<!-- Group Title -->
<h2 class="group-title">
<font-awesome-icon v-if="editMode && showGroupDrag" icon="arrows-alt-v" class="action drag me-3" />
<font-awesome-icon v-if="editMode" icon="times" class="action remove me-3" @click="removeGroup(group.index)" />
<Editable v-model="group.element.name" :contenteditable="editMode" tag="span" />
<Editable v-model="group.element.name" :contenteditable="editMode" tag="span" data-testid="group-name" />
</h2>
<div class="shadow-box monitor-list mt-4 position-relative">
@ -31,9 +31,9 @@
item-key="id"
>
<template #item="monitor">
<div class="item">
<div class="item" data-testid="monitor">
<div class="row">
<div class="col-9 col-md-8 small-padding">
<div class="col-6 col-md-4 small-padding">
<div class="info">
<font-awesome-icon v-if="editMode" icon="arrows-alt-v" class="action drag me-3" />
<font-awesome-icon v-if="editMode" icon="times" class="action remove me-3" @click="removeMonitor(group.index, monitor.index)" />
@ -45,10 +45,11 @@
class="item-name"
target="_blank"
rel="noopener noreferrer"
data-testid="monitor-name"
>
{{ monitor.element.name }}
</a>
<p v-else class="item-name"> {{ monitor.element.name }} </p>
<p v-else class="item-name" data-testid="monitor-name"> {{ monitor.element.name }} </p>
<span
title="Setting"
@ -66,11 +67,11 @@
<Tag :item="{name: $t('Cert Exp.'), value: formattedCertExpiryMessage(monitor), color: certExpiryColor(monitor)}" :size="'sm'" />
</div>
<div v-if="showTags">
<Tag v-for="tag in monitor.element.tags" :key="tag" :item="tag" :size="'sm'" />
<Tag v-for="tag in monitor.element.tags" :key="tag" :item="tag" :size="'sm'" data-testid="monitor-tag" />
</div>
</div>
</div>
<div :key="$root.userHeartbeatBar" class="col-3 col-md-4">
<div :key="$root.userHeartbeatBar" class="col-6 col-md-8">
<HeartbeatBar size="mid" :monitor-id="monitor.element.id" />
</div>
</div>

View File

@ -14,6 +14,7 @@
type="button"
class="btn btn-outline-secondary btn-add"
:disabled="processing"
data-testid="add-tag-button"
@click.stop="showAddDialog"
>
<font-awesome-icon class="me-1" icon="plus" /> {{ $t("Add") }}
@ -59,6 +60,7 @@
v-model="newDraftTag.name" class="form-control"
:class="{'is-invalid': validateDraftTag.nameInvalid}"
:placeholder="$t('Name')"
data-testid="tag-name-input"
@keydown.enter.prevent="onEnter"
/>
<div class="invalid-feedback">
@ -76,6 +78,7 @@
label="name"
select-label=""
deselect-label=""
data-testid="tag-color-select"
>
<template #option="{ option }">
<div
@ -103,6 +106,7 @@
v-model="newDraftTag.value" class="form-control"
:class="{'is-invalid': validateDraftTag.valueInvalid}"
:placeholder="$t('value (optional)')"
data-testid="tag-value-input"
@keydown.enter.prevent="onEnter"
/>
<div class="invalid-feedback">
@ -114,6 +118,7 @@
type="button"
class="btn btn-secondary float-end"
:disabled="processing || validateDraftTag.invalid"
data-testid="tag-submit-button"
@click.stop="addDraftTag"
>
{{ $t("Add") }}

View File

@ -0,0 +1,81 @@
<template>
<div class="mb-3">
<label for="host-onesender" class="form-label">{{ $t("Host Onesender") }}</label>
<input
id="host-onesender"
v-model="$parent.notification.onesenderURL"
type="url"
placeholder="https://xxxxxxxxxxx.com/api/v1/messages"
pattern="https?://.+"
class="form-control"
required
/>
</div>
<div class="mb-3">
<label for="receiver-onesender" class="form-label">{{ $t("Token Onesender") }}</label>
<HiddenInput id="receiver-onesender" v-model="$parent.notification.onesenderToken" :required="true" autocomplete="false"></HiddenInput>
<i18n-t tag="div" keypath="wayToGetOnesenderUrlandToken" class="form-text">
<a href="https://onesender.net/" target="_blank">{{ $t("here") }}</a>
</i18n-t>
</div>
<div class="mb-3">
<label for="webhook-request-body" class="form-label">{{ $t("Recipient Type") }}</label>
<select
id="webhook-request-body"
v-model="$parent.notification.onesenderTypeReceiver"
class="form-select"
required
>
<option value="private">{{ $t("Private Number") }}</option>
<option value="group">{{ $t("Group ID") }}</option>
</select>
</div>
<div v-if="$parent.notification.onesenderTypeReceiver == 'private'" class="form-text">{{ $t("privateOnesenderDesc", ['"application/json"']) }}</div>
<div v-else class="form-text">{{ $t("groupOnesenderDesc") }}</div>
<div class="mb-3">
<input
id="type-receiver-onesender"
v-model="$parent.notification.onesenderReceiver"
type="text"
placeholder="628123456789 or 628123456789-34534"
class="form-control"
required
/>
</div>
<div class="mb-3">
<input
id="type-receiver-onesender"
v-model="computedReceiverResult"
type="text"
class="form-control"
disabled
/>
</div>
</template>
<script>
import HiddenInput from "../HiddenInput.vue";
export default {
components: {
HiddenInput,
},
data() {
return {};
},
computed: {
computedReceiverResult() {
let receiver = this.$parent.notification.onesenderReceiver;
return this.$parent.notification.onesenderTypeReceiver === "private" ? receiver + "@s.whatsapp.net" : receiver + "@g.us";
},
},
};
</script>
<style lang="scss" scoped>
textarea {
min-height: 200px;
}
</style>

View File

@ -0,0 +1,16 @@
<template>
<div class="mb-3">
<label for="signl4-webhook-url" class="form-label">{{ $t("SIGNL4 Webhook URL") }}</label>
<input
id="signl4-webhook-url"
v-model="$parent.notification.webhookURL"
type="url"
pattern="https?://.+"
class="form-control"
required
/>
<i18n-t tag="div" keypath="signl4Docs" class="form-text">
<a href="https://docs.signl4.com/integrations/uptime-kuma/uptime-kuma.html" target="_blank">SIGNL4 Docs</a>
</i18n-t>
</div>
</template>

View File

@ -0,0 +1,31 @@
<template>
<div class="mb-3">
<label for="wpush-apikey" class="form-label">WPush {{ $t("API Key") }}</label>
<HiddenInput id="wpush-apikey" v-model="$parent.notification.wpushAPIkey" :required="true" autocomplete="new-password" placeholder="WPushxxxxx"></HiddenInput>
</div>
<div class="mb-3">
<label for="wpush-channel" class="form-label">发送通道</label>
<select id="wpush-channel" v-model="$parent.notification.wpushChannel" class="form-select" required>
<option value="wechat">微信</option>
<option value="sms">短信</option>
<option value="mail">邮件</option>
<option value="feishu">飞书</option>
<option value="dingtalk">钉钉</option>
<option value="wechat_work">企业微信</option>
</select>
</div>
<i18n-t tag="p" keypath="More info on:">
<a href="https://wpush.cn/" rel="noopener noreferrer" target="_blank">https://wpush.cn/</a>
</i18n-t>
</template>
<script>
import HiddenInput from "../HiddenInput.vue";
export default {
components: {
HiddenInput,
},
};
</script>

View File

@ -29,6 +29,7 @@ import Nostr from "./Nostr.vue";
import Ntfy from "./Ntfy.vue";
import Octopush from "./Octopush.vue";
import OneBot from "./OneBot.vue";
import Onesender from "./Onesender.vue";
import Opsgenie from "./Opsgenie.vue";
import PagerDuty from "./PagerDuty.vue";
import FlashDuty from "./FlashDuty.vue";
@ -62,6 +63,8 @@ import Splunk from "./Splunk.vue";
import SevenIO from "./SevenIO.vue";
import Whapi from "./Whapi.vue";
import Cellsynt from "./Cellsynt.vue";
import WPush from "./WPush.vue";
import SIGNL4 from "./SIGNL4.vue";
/**
* Manage all notification form.
@ -98,6 +101,7 @@ const NotificationFormList = {
"ntfy": Ntfy,
"octopush": Octopush,
"OneBot": OneBot,
"Onesender": Onesender,
"Opsgenie": Opsgenie,
"PagerDuty": PagerDuty,
"FlashDuty": FlashDuty,
@ -111,6 +115,7 @@ const NotificationFormList = {
"rocket.chat": RocketChat,
"serwersms": SerwerSMS,
"signal": Signal,
"SIGNL4": SIGNL4,
"SMSManager": SMSManager,
"SMSPartner": SMSPartner,
"slack": Slack,
@ -132,6 +137,7 @@ const NotificationFormList = {
"whapi": Whapi,
"gtxmessaging": GtxMessaging,
"Cellsynt": Cellsynt,
"WPush": WPush
};
export default NotificationFormList;

View File

@ -6,6 +6,7 @@ const languageList = {
"cs-CZ": "Čeština",
"zh-HK": "繁體中文 (香港)",
"bg-BG": "Български",
"be": "Беларуская",
"de-DE": "Deutsch (Deutschland)",
"de-CH": "Deutsch (Schweiz)",
"nl-NL": "Nederlands",

935
src/lang/be.json Normal file
View File

@ -0,0 +1,935 @@
{
"Edit": "Змяніць",
"-hour": "-гадзін",
"ignoreTLSErrorGeneral": "Ігнараваць памылку TLS/SSL для злучэння",
"pushOthers": "Іншыя",
"Yes": "Так",
"Show URI": "Паказаць URI",
"Tags": "Тэгі",
"Tag with this value already exist.": "Тэг з такім значэннем ужо існуе.",
"color": "Колер",
"value (optional)": "значэнне (неабавязкова)",
"Gray": "Шэры",
"Red": "Чырвоны",
"Orange": "Аранжавы",
"Search monitored sites": "Пошук адсочваемых сайтаў",
"Avg. Ping": "Сярэдні пінг",
"Body": "Цела",
"Headers": "Загалоўкі",
"Create Incident": "Стварыць інцыдэнт",
"Style": "Стыль",
"Proxies": "Проксі",
"default": "Па змаўчанні",
"enabled": "Уключана",
"setAsDefault": "Усталяваць па змаўчанні",
"Remove the expiry notification": "Выдаліць дату сканчэньня тэрміну дзеяння абвесткі",
"Refresh Interval": "Інтэрвал абнаўлення",
"Refresh Interval Description": "Старонка статусу будзе цалкам абнаўляць сайт кожныя {0} секунд",
"maintenanceStatus-ended": "Скончыўся(ліся)",
"Select message type": "Выберыце тып паведамлення",
"Create new forum post": "Стварыць новы пост",
"postToExistingThread": "Стварыць пост у гэтай галіне",
"forumPostName": "Назва паста",
"e.g. {discordThreadID}": "Напр. {discordThreadID}",
"Number": "Нумар",
"lineDevConsoleTo": "Кансоль распрацошчыкаў Line - {0}",
"recurringIntervalMessage": "Запускаць 1 раз кожны дзень | Запускаць 1 раз кожныя {0} дзён",
"affectedMonitorsDescription": "Выберыце маніторы, якія будуць затронутыя падчас тэхабслугоўвання",
"pushoversounds gamelan": "Гамелан",
"pushoversounds incoming": "Уваходны",
"pushoversounds climb": "Падым (доўгі)",
"wayToGetKookBotToken": "Стварыце праграму і атрымайце токен бота па адрасу {0}",
"Device": "Прылада",
"Huawei": "Huawei",
"Expiry date": "Дата сканчэння",
"Don't expire": "Не сканчаецца",
"Badge URL": "URL значка",
"nostrRelays": "Рэле Nostr",
"gamedigGuessPort": "Gamedig: Угадай порт",
"GrafanaOncallUrl": "URL-адрас Grafana Oncall",
"API URL": "API URL-адрас",
"Originator type": "Тып крыніцы",
"Destination": "Прызначэнне",
"languageName": "Беларуская",
"setupDatabaseChooseDatabase": "Якую базу даных вы хацелі б выкарыстоўваць?",
"setupDatabaseEmbeddedMariaDB": "Вам не трэба нічога наладжваць. У гэты Docker-вобраз аўтаматычна ўбудавана і наладжана MariaDB. Uptime Kuma будзе падключацца да гэтай базы даных праз unix-socket.",
"setupDatabaseMariaDB": "Падключыцца да знешняй базы даных MariaDB. Вам трэба задаць інфармацыю аб падлучэнні да базы даных.",
"setupDatabaseSQLite": "Просты файл базы даных, рэкамендуецца для невялікіх разгортванняў. Да версіі 2.0.0 Uptime Kuma выкарыстоўваў SQLite як базу даных па змаўчанні.",
"settingUpDatabaseMSG": "Настраиваем базу даных. Гэта можа заняць некаторы час, калі ласка, пачакайце.",
"dbName": "Назва базы даных",
"Settings": "Налады",
"Dashboard": "Панэль кіравання",
"Help": "Дапамога",
"New Update": "Даступна абнаўленне",
"Language": "Мова",
"Appearance": "Знешні выгляд",
"Theme": "Тэма",
"General": "Агульныя",
"Game": "Гульня",
"Primary Base URL": "Асноўны URL",
"Version": "Версія",
"Check Update On GitHub": "Праверыць абнаўленні ў GitHub",
"List": "Спіс",
"Home": "Галоўная",
"Add": "Дадаць",
"Add New Monitor": "Дадаць новы манітор",
"Quick Stats": "Статыстыка",
"Up": "Працуе",
"Down": "Не працуе",
"Pending": "У чаканні",
"statusMaintenance": "Тэхабслугоўванне",
"Maintenance": "Тэхабслугоўванне",
"Unknown": "Невядома",
"Cannot connect to the socket server": "Немагчыма падключыцца да сервера",
"Reconnecting...": "Падключэнне...",
"General Monitor Type": "Агульны Тып Манітора",
"Passive Monitor Type": "Пасіўны Тып Манітора",
"Specific Monitor Type": "Спецыфічны Тып Манітора",
"markdownSupported": "Падтрымліваецца сінтаксіс Markdown",
"pauseDashboardHome": "Паўза",
"Pause": "Паўза",
"Name": "Назва",
"Status": "Статус",
"DateTime": "Дата і час",
"Message": "Паведамленне",
"No important events": "Няма важных падзей",
"Resume": "Узнавіць",
"Delete": "Выдаліць",
"Current": "Бягучы",
"Uptime": "Час працы",
"Cert Exp.": "Сертыфікат сконч.",
"Monitor": "Манітор | Маніторы",
"day": "дзень | дзён",
"-day": "-дзён",
"hour": "гадзіна",
"Response": "Адказ",
"Ping": "Пінг",
"Monitor Type": "Тып манітора",
"Keyword": "Ключавое слова",
"Invert Keyword": "Інвертаваць ключавое слова",
"Friendly Name": "Назва",
"URL": "URL-спасылка",
"Hostname": "Адрас хоста",
"Expected Value": "Чаканае значэнне",
"Json Query": "JSON Запыт",
"Host URL": "URL Хоста",
"locally configured mail transfer agent": "Наладжаны лакальна агент перадачы паштовых паведамленняў",
"Port": "Порт",
"Heartbeat Interval": "Частата апытання",
"Request Timeout": "Тайм-Аут запыту",
"timeoutAfter": "Тайм-Аут праз {0} секундаў",
"Retries": "Спробы",
"Heartbeat Retry Interval": "Інтэрвал паўтору апытання",
"Resend Notification if Down X times consecutively": "Паўторная адпраўка абвесткі пры адключэнні некалькі раз",
"Advanced": "Дадаткова",
"checkEverySecond": "Праверка кожныя {0} секунд",
"retryCheckEverySecond": "Паўтараць кожныя {0} секунд",
"resendEveryXTimes": "Перасылаць кожныя {0} раз",
"resendDisabled": "Перасылка адключана",
"retriesDescription": "Максімальная колькасць спробаў перад адзнакай службы, як недаступная, і адпраўкай абвесткі",
"ignoreTLSError": "Ігнараваць памылкі TLS/SSL для HTTPS сайтаў",
"upsideDownModeDescription": "Змяніць статус службы на ПРАЦУЕ, калі яна даступная, а пазначаецца як НЕ ПРАЦУЕ.",
"maxRedirectDescription": "Максімальная колькасць перанакіраванняў. Пастаўце 0, каб адключыць перанакіраванні.",
"Upside Down Mode": "Рэжым змены статусу",
"Max. Redirects": "Макс. колькасць перанакіраванняў",
"Accepted Status Codes": "Дапушчальныя коды статуса",
"Push URL": "URL-спасылка пуш абвестак",
"needPushEvery": "Да гэтага URL неабходна звяртацца кожныя {0} секунд.",
"pushOptionalParams": "Неабавязковыя параметры: {0}",
"pushViewCode": "Як выкарыстоўваць манітор Push? (Паглядзець код)",
"programmingLanguages": "Мовы праграмавання",
"Save": "Захаваць",
"Notifications": "Апавяшчэнні",
"Not available, please setup.": "Апавяшчэнні недаступныя, патрабуецца налада.",
"Setup Notification": "Наладзіць апавяшчэнні",
"Light": "Светлая",
"Dark": "Цёмная",
"Auto": "Як у сістэме",
"Theme - Heartbeat Bar": "Тэма - радка частаты апытання",
"styleElapsedTime": "Мінулы час пад радком частаты апытання",
"styleElapsedTimeShowNoLine": "Паказаць (Без лініі)",
"styleElapsedTimeShowWithLine": "Паказаць (З лініяй)",
"Normal": "Звычайны",
"Bottom": "Унізе",
"None": "Адсутнічае",
"Timezone": "Часавы пояс TZ",
"Search Engine Visibility": "Бачнасць у пошукавых сістэмах",
"Allow indexing": "Дазволіць індэксацыю",
"Discourage search engines from indexing site": "Забараніць індэксацыю",
"Change Password": "Змяніць пароль",
"Current Password": "Бягучы пароль",
"New Password": "Новы пароль",
"Repeat New Password": "Паўтарыць новы пароль",
"Update Password": "Абнавіць пароль",
"Disable Auth": "Адключыць аўтарызацыю",
"Enable Auth": "Уключыць аўтарызацыю",
"disableauth.message1": "Вы ўпэўнены, што хочаце {disableAuth}?",
"disable authentication": "адключыць аўтарызацыю",
"disableauth.message2": "Гэта падыходзіць для {intendThirdPartyAuth} перад адкрыццём Uptime Kuma, такіх як Cloudflare Access, Authelia або іншыя.",
"where you intend to implement third-party authentication": "тых, у каго настроена старонняя сістэма аўтарызацыі",
"Please use this option carefully!": "Выкарыстоўвайце гэтую наладу асцярожна!",
"Logout": "Выйсці",
"Leave": "Пакінуць",
"I understand, please disable": "Я разумею, усё роўна адключыць",
"Confirm": "Пацвердзіць",
"No": "Не",
"Username": "Лагін",
"Password": "Пароль",
"Remember me": "Запомніць мяне",
"Login": "Уваход у сістэму",
"No Monitors, please": "Няма манітораў, калі ласка",
"add one": "дадаць",
"Notification Type": "Тып абвесткі",
"Email": "Электронная пошта",
"Test": "Тэст",
"Certificate Info": "Інфармацыя пра сертыфікат",
"Resolver Server": "DNS сервер",
"Resource Record Type": "Тып рэсурснай запісі",
"Last Result": "Апошні вынік",
"Create your admin account": "Стварыце акаўнт адміністратара",
"Repeat Password": "Паўтарыць пароль",
"Import Backup": "Імпартаваць Backup",
"Export Backup": "Спампаваць Backup",
"Export": "Экспарт",
"Import": "Імпарт",
"respTime": "Час адказу (мс)",
"notAvailableShort": "N/A",
"Default enabled": "Па змаўчанні ўключана",
"Apply on all existing monitors": "Ужыць да ўсіх існуючых манітораў",
"Create": "Стварыць",
"Clear Data": "Выдаліць даныя",
"Events": "Падзеі",
"Heartbeats": "Апытанні",
"Auto Get": "Аўта-атрыманне",
"Schedule maintenance": "Запланаваць тэхабслугоўванне",
"Affected Monitors": "Задзейнічаныя Маніторы",
"Pick Affected Monitors...": "Выберыце Задзейнічаныя Маніторы…",
"Start of maintenance": "Пачатак тэхабслугоўвання",
"All Status Pages": "Усе старонкі статусаў",
"Select status pages...": "Выберыце старонку статуса…",
"alertNoFile": "Выберыце файл для імпарту.",
"alertWrongFileType": "Выберыце JSON-файл.",
"Clear all statistics": "Ачысціць усю статыстыку",
"Skip existing": "Прапусціць існуючыя",
"Overwrite": "Перазапісаць",
"Options": "Опцыі",
"Keep both": "Пакінуць абодва",
"Verify Token": "Праверыць токен",
"Setup 2FA": "Налады 2FA",
"Enable 2FA": "Уключыць 2FA",
"Disable 2FA": "Адключыць 2FA",
"2FA Settings": "Налады 2FA",
"Two Factor Authentication": "Двухфактарная аўтэнтыфікацыя",
"filterActive": "Актыўны",
"filterActivePaused": "На паўзе",
"Active": "Актыўна",
"Inactive": "Неактыўна",
"Token": "Токен",
"Add New Tag": "Дадаць тэг",
"Add New below or Select...": "Дадаць новы або выбраць…",
"Tag with this name already exist.": "Тэг з такім імем ужо існуе.",
"Green": "Зялёны",
"Blue": "Сіні",
"Indigo": "Індыга",
"Purple": "Пурпуровы",
"Pink": "Ружовы",
"Custom": "Сваёродны",
"Search...": "Пошук…",
"Avg. Response": "Сярэдні адказ",
"Entry Page": "Галоўная",
"statusPageNothing": "Нічога няма, дадайце групу або манітор.",
"statusPageRefreshIn": "Абнаўленне праз: {0}",
"No Services": "Няма сэрвісаў",
"All Systems Operational": "Усе сістэмы працуюць",
"Partially Degraded Service": "Часткова працуючы сэрвіс",
"Degraded Service": "Пашкоджаная служба",
"Add Group": "Дадаць групу",
"Add a monitor": "Дадаць манітор",
"Edit Status Page": "Рэдагаваць старонку статусаў",
"Go to Dashboard": "Перайсці да панэлі кіравання",
"Status Page": "Старонка статуса",
"Status Pages": "Старонкі статуса",
"defaultNotificationName": "Абвесткі {notification} ({number})",
"here": "тут",
"Required": "Абавязкова",
"Post URL": "Post URL",
"Content Type": "Тып кантэнту",
"webhookJsonDesc": "{0} падыходзіць для любых сучасных HTTP-сервераў, напрыклад Express.js",
"webhookFormDataDesc": "{multipart} падыходзіць для PHP. JSON-вывад неабходна будзе апрацаваць з дапамогай {decodeFunction}",
"liquidIntroduction": "Шаблоннасьць дасягаецца з дапамогай мовы шаблонаў Liquid. Інструкцыі па выкарыстаньні прадстаўлены ў раздзеле {0}. Вось даступныя зменныя:",
"templateMsg": "паведамленне апавешчання",
"templateHeartbeatJSON": "аб'ект, які апісвае сігнал",
"templateMonitorJSON": "аб'ект, які апісвае манітор",
"templateLimitedToUpDownNotifications": "даступна толькі для апавешчанняў UP/DOWN",
"templateLimitedToUpDownCertNotifications": "даступна толькі для апавешчанняў UP/DOWN і аб заканчэньні тэрміну дзеяньня сертыфіката",
"webhookAdditionalHeadersTitle": "Дадатковыя Загалоўкі",
"webhookAdditionalHeadersDesc": "Устанаўлівае дадатковыя загалоўкі, якія адпраўляюцца з дапамогай вэб-хука. Кожны загаловак павінен быць вызначаны як JSON ключ/значэнне.",
"webhookBodyPresetOption": "Прэсет - {0}",
"webhookBodyCustomOption": "Карыстацкі аб'ект",
"Webhook URL": "URL вэбхука",
"Application Token": "Токен праграмы",
"Server URL": "URL сервера",
"Priority": "Прыярытэт",
"emojiCheatSheet": "Шпаргалка па Emoji: {0}",
"Read more": "Падрабязней",
"appriseInstalled": "Апавяшчэнне ўсталявана.",
"appriseNotInstalled": "Апавяшчэнне не ўсталявана. {0}",
"Method": "Метад",
"PushUrl": "URL пуша",
"HeadersInvalidFormat": "Загалоўкі запыту не з'яўляюцца валідным JSON: ",
"BodyInvalidFormat": "Цела запыту не з'яўляецца валідным JSON: ",
"Monitor History": "Гісторыя маніторынгу",
"clearDataOlderThan": "Захоўваць статыстыку за {0} дзён.",
"PasswordsDoNotMatch": "Паролі не супадаюць.",
"records": "запісы",
"One record": "Адзін запіс",
"steamApiKeyDescription": "Для маніторынгу гульнявога сервера Steam вам патрэбны Web-API ключ Steam. Зарэгістраваць яго можна тут: ",
"Current User": "Бягучы карыстальнік",
"topic": "Тэма",
"topicExplanation": "MQTT топік для маніторынгу",
"successKeyword": "Ключавое слова паспяховасці",
"successKeywordExplanation": "Ключавое слова MQTT, якое будзе лічыцца паспяховым",
"recent": "Апошняе",
"Reset Token": "Скід токена",
"Done": "Гатова",
"Info": "Інфа",
"Security": "Бяспека",
"Steam API Key": "Steam API-Ключ",
"Shrink Database": "Сціснуць базу даных",
"Pick a RR-Type...": "Выберыце RR-Тып…",
"Pick Accepted Status Codes...": "Выберыце прынятыя коды статуса…",
"Default": "Па змаўчанні",
"HTTP Options": "HTTP Опцыі",
"Title": "Назва інцыдэнту",
"Content": "Змест інцыдэнту",
"info": "ІНФА",
"warning": "УВАГА",
"danger": "ПАМЫЛКА",
"error": "памылка",
"critical": "крытычна",
"primary": "АСНОЎНЫ",
"light": "СВЕТЛЫ",
"dark": "ЦЁМНЫ",
"Post": "Апублікаваць",
"Please input title and content": "Калі ласка, увядзіце назву і змест",
"Created": "Створана",
"Last Updated": "Апошняе абнаўленне",
"Switch to Light Theme": "Светлая тэма",
"Switch to Dark Theme": "Цёмная тэма",
"Show Tags": "Паказаць тэгі",
"Hide Tags": "Схаваць тэгі",
"Description": "Апісанне",
"No monitors available.": "Няма даступных манітораў.",
"Add one": "Дадаць новы",
"No Monitors": "Маніторы адсутнічаюць",
"Untitled Group": "Група без назвы",
"Services": "Службы",
"Powered by": "Працуе на",
"Discard": "Скасаваць",
"Cancel": "Скасаваць",
"Select": "Выбраць",
"selectedMonitorCount": "Выбрана: {0}",
"Check/Uncheck": "Адзначыць/Зняць",
"shrinkDatabaseDescription": "Уключае VACUUM для базы даных SQLite. Калі ваша база даных была створана на версіі 1.10.0 і больш, AUTO_VACUUM ужо ўключаны і гэтае дзеянне не патрабуецца.",
"Customize": "Персаналізаваць",
"Custom Footer": "Карыстацкі footer",
"Custom CSS": "Карыстацкі CSS",
"enableProxyDescription": "Гэты проксі не будзе ўплываць на запыты манітора, пакуль ён не будзе актываваны. Вы можаце кантраляваць часовае адключэнне проксі для ўсіх манітораў праз статус актывацыі.",
"deleteStatusPageMsg": "Вы сапраўды хочаце выдаліць гэтую старонку статуса?",
"deleteProxyMsg": "Вы сапраўды хочаце выдаліць гэты проксі для ўсіх манітораў?",
"proxyDescription": "Проксі павінны быць прывязаныя да манітора, каб працаваць.",
"setAsDefaultProxyDescription": "Гэты проксі будзе па змаўчанні ўключаны для новых манітораў. Вы ўсё яшчэ можаце асобна адключаць проксі ў кожным маніторы.",
"Certificate Chain": "Ланцуг сертыфікатаў",
"Valid": "Дзейны",
"Invalid": "Нядзейсны",
"User": "Карыстальнік",
"Page Not Found": "Старонка не знойдзена",
"Installed": "Усталявана",
"Not installed": "Не ўсталявана",
"Running": "Працуе",
"Not running": "Не працуе",
"Remove Token": "Выдаліць токен",
"Start": "Пачаць",
"Stop": "Спыніць",
"Add New Status Page": "Дадаць старонку статуса",
"Slug": "Slug",
"Accept characters:": "Прымаць сімвалы:",
"startOrEndWithOnly": "Пачынаецца або заканчваецца толькі на {0}",
"No consecutive dashes": "Без паслядоўных тырэ",
"statusPageSpecialSlugDesc": "Спецыяльны значок {0}: гэтая старонка будзе адлюстроўвацца, калі значок не пазначаны",
"Next": "Далей",
"The slug is already taken. Please choose another slug.": "Гэты slug ужо заняты. Калі ласка, выберыце іншы slug.",
"No Proxy": "Без проксі",
"Authentication": "Аўтэнтыфікацыя",
"HTTP Basic Auth": "HTTP Аўтарызацыя",
"New Status Page": "Новая старонка статуса",
"Reverse Proxy": "Зваротны проксі",
"Backup": "Рэзервовая копія",
"About": "Аб праграме",
"wayToGetCloudflaredURL": "(Спампаваць cloudflared з {0})",
"cloudflareWebsite": "Вэб-сайт Cloudflare",
"Message:": "Паведамленне:",
"Don't know how to get the token? Please read the guide:": "Не ведаеце, як атрымаць токен? Калі ласка, прачытайце кіраўніцтва:",
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Бягучае злучэнне можа быць страчана, калі вы ў цяперашні час падключаецеся праз тунэль Cloudflare. Вы ўпэўнены, што хочаце яго спыніць? Увядзіце свой бягучы пароль, каб пацвердзіць гэта.",
"HTTP Headers": "Загалоўкі HTTP",
"Trust Proxy": "Давераны проксі",
"Other Software": "Іншае праграмнае забеспячэнне",
"For example: nginx, Apache and Traefik.": "Напрыклад: nginx, Apache і Traefik.",
"Please read": "Калі ласка, прачытайце",
"Subject:": "Тэма:",
"Valid To:": "Дзейсны да:",
"Days Remaining:": "Засталося дзён:",
"Issuer:": "Выдавец:",
"Fingerprint:": "Адбітак:",
"No status pages": "Няма старонак статуса",
"Domain Name Expiry Notification": "Абвестка пра сканчэнне тэрміну дзеяння даменнай назвы",
"Add a new expiry notification day": "Дадаць новы дзень абвесткі пра сканчэньне тэрміну дзеяння",
"Proxy": "Проксі",
"Date Created": "Дата стварэння",
"Footer Text": "Тэкст у ніжнім калонтытуле",
"Show Powered By": "Паказаць на чым створана",
"Domain Names": "Даменныя імёны",
"signedInDisp": "Вы ўвайшлі як {0}",
"signedInDispDisabled": "Аўтэнтыфікацыя адключана.",
"RadiusSecret": "Сакрэт Radius",
"RadiusSecretDescription": "Агульны сакрэт паміж кліентам і серверам",
"RadiusCalledStationId": "Ідэнтыфікатар вызываемай станцыі",
"RadiusCalledStationIdDescription": "Ідэнтыфікатар вызываемага прылады",
"RadiusCallingStationId": "Ідэнтыфікатар вызывальніка станцыі",
"RadiusCallingStationIdDescription": "Ідэнтыфікатар вызывальніка прылады",
"Certificate Expiry Notification": "Абвестка пра сканчэнне тэрміну дзеяння сертыфіката",
"API Username": "Імя карыстальніка API",
"API Key": "API ключ",
"Show update if available": "Паказваць даступныя абнаўленні",
"Also check beta release": "Праверыць абнаўленні для бета версій",
"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": "Хутка",
"Connection String": "Радок падлучэння",
"Query": "Запыт",
"settingsCertificateExpiry": "Сканчэнне TLS сертыфіката",
"certificationExpiryDescription": "HTTPS Маніторы ініцыююць абвестку, калі срок дзеяння сертыфіката TLS скончыцца:",
"Setup Docker Host": "Налада Docker Host",
"Connection Type": "Тып злучэння",
"Docker Daemon": "Дэман Docker",
"noDockerHostMsg": "Не даступна. Спачатку наладзце хост Docker.",
"DockerHostRequired": "Усталюйце хост Docker для гэтага манітора.",
"deleteDockerHostMsg": "Вы сапраўды хочаце выдаліць гэты вузел docker для ўсіх манітораў?",
"socket": "Сокет",
"tcp": "TCP / HTTP",
"tailscalePingWarning": "Для таго, каб выкарыстоўваць манітор Tailscale Ping, неабходна ўсталяваць Uptime Kuma без Docker, а таксама ўсталяваць на сервер кліент Tailscale.",
"Docker Container": "Docker кантэйнер",
"Container Name / ID": "Назва кантэйнера / ID",
"Docker Host": "Хост Docker",
"Docker Hosts": "Хосты Docker",
"Domain": "Дамен",
"Workstation": "Рабочая станцыя",
"Packet Size": "Памер пакета",
"Bot Token": "Токен бота",
"wayToGetTelegramToken": "Вы можаце атрымаць токен тут - {0}.",
"Chat ID": "ID чата",
"telegramMessageThreadID": "(Неабавязкова) ID ланцуга паведамленняў",
"telegramMessageThreadIDDescription": "Неабавязковы ўнікальны ідэнтыфікатар для ланцуга паведамленняў (тэмы) форума; толькі для форумаў-супергруп",
"telegramSendSilently": "Адправіць без гуку",
"telegramSendSilentlyDescription": "Карыстальнікі атрымаюць абвестку без гуку.",
"telegramProtectContent": "Забараніць перасылку/захаванне",
"telegramProtectContentDescription": "Калі ўключана, паведамленні бота ў Telegram будуць забароненыя для перасылкі і захавання.",
"supportTelegramChatID": "Падтрымліваюцца ID чатаў, груп і каналаў",
"wayToGetTelegramChatID": "Вы можаце атрымаць ID вашага чата, адправіўшы паведамленне боту і перайсці па гэтаму URL для прагляду chat_id:",
"YOUR BOT TOKEN HERE": "ВАШ ТОКЕН БОТА ТУТ",
"chatIDNotFound": "ID чата не знойдзены; спачатку адпраўце паведамленне боту",
"disableCloudflaredNoAuthMsg": "Вы знаходзіцеся ў рэжыме без аўтарызацыі, пароль не патрабуецца.",
"trustProxyDescription": "Давяраць загалоўкам 'X-Forwarded-*'. Калі вы хочаце атрымаць правільны IP-адрас кліента, а ваш Uptime Kuma знаходзіцца пад Nginx або Apache, вам след включить гэты параметр.",
"wayToGetLineNotifyToken": "Вы можаце атрымаць токен доступу ў {0}",
"Examples": "Прыклады",
"Home Assistant URL": "URL-адрас Home Assistant",
"Long-Lived Access Token": "Токен доступу з доўгім тэрмінам службы",
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Токен доступу з доўгім тэрмінам дзеяння можна стварыць, націснуўшы на імя вашага профілю (ўнізе злева) і пракруціўшы яго ўніз, потым націсніце Стварыць токен. ",
"Notification Service": "Служба абвестак",
"default: notify all devices": "па змаўчанні: апавяшчаць усе прылады",
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Спіс службаў абвестак можна знайсці ў Home Assistant у раздзеле \"Інструменты распрацоўніка > Службы\", выканаўшы пошук па слове \"абвестка\", каб знайсці назву вашага прылады/тэлефона.",
"Automations can optionally be triggered in Home Assistant:": "Пры жаданні аўтаматызацыю можна актываваць у Home Assistant.:",
"Trigger type:": "Тып трыгера:",
"Event type:": "Тып падзеі:",
"Event data:": "даныя падзеі:",
"Then choose an action, for example switch the scene to where an RGB light is red.": "Затым выберыце дзеянне, напрыклад, пераключыце сцэну на чырвоны індыкатар RGB..",
"Frontend Version": "Версія інтэрфейса",
"Frontend Version do not match backend version!": "Версія інтэрфейса не адпавядае версіі сервернай часткі!",
"backupOutdatedWarning": "Састарэла: гэтая функцыя рэзервовага капіявання больш не падтрымліваецца. Праз даданыя шмат функцый, яна не можа стварыць або аднавіць поўную рэзервовую копію.",
"backupRecommend": "Зрабіце рэзервовую копію таму або папцы з данымі (./data/) напрамую.",
"Optional": "Неабавязкова",
"or": "або",
"sameAsServerTimezone": "Аналагічна часавому поясу сервера",
"startDateTime": "Пачатковая дата і час",
"endDateTime": "Канчатковая дата і час",
"cronExpression": "Выраз для Cron",
"cronSchedule": "Расклад: ",
"invalidCronExpression": "Няправільны выраз Cron: {0}",
"recurringInterval": "Інтэрвал",
"Recurring": "Паўторны",
"strategyManual": "Актыўны/Неактыўны Ручным спосабам",
"warningTimezone": "Выкарыстоўваецца часавы пояс сервера",
"weekdayShortMon": "Пн",
"weekdayShortTue": "Аўт",
"weekdayShortWed": "Ср",
"weekdayShortThu": "Чт",
"weekdayShortFri": "Пт",
"weekdayShortSat": "Сб",
"weekdayShortSun": "Нд",
"dayOfWeek": "Дзень тыдня",
"dayOfMonth": "Дзень месяца",
"lastDay": "Апошні дзень",
"lastDay1": "Апошні дзень месяца",
"lastDay2": "Другі апошні дзень месяца",
"lastDay3": "Трэці апошні дзень месяца",
"maintenanceStatus-scheduled": "Запланавана(ы)",
"maintenanceStatus-unknown": "Невядома",
"lastDay4": "Чацвёрты апошні дзень месяца",
"No Maintenance": "Няма тэхабслугоўванняў",
"pauseMaintenanceMsg": "Вы ўпэўненыя, што хочаце паставіць на паўзу?",
"maintenanceStatus-under-maintenance": "На тэхабслугоўванні",
"maintenanceStatus-inactive": "Неактыўны",
"Display Timezone": "Паказаць часавы пояс",
"Server Timezone": "Часавы пояс сервера",
"statusPageMaintenanceEndDate": "Канец",
"IconUrl": "URL значка",
"Enable DNS Cache": "(Састарэла) Уключыць DNS кэш для манітораў HTTP(S)",
"Enable": "Уключыць",
"Disable": "Адключыць",
"enableNSCD": "Уключыць NSCD (Name Service Cache Daemon) для кэшавання ўсіх DNS-запытаў",
"chromeExecutable": "Выканаўчы файл Chrome/Chromium",
"chromeExecutableAutoDetect": "Аўтавызначэнне",
"chromeExecutableDescription": "Для карыстальнікаў Docker, калі Chromium яшчэ не ўсталяваны, можа спатрэбіцца некалькі хвілін для ўсталявання і адлюстравання выніку тэставання. Ён займае 1 ГБ дыскавага прастору.",
"dnsCacheDescription": "Гэта можа не працаваць на некаторых IPv6 асяроддзях, адключыце гэта, калі ў вас узнікаюць праблемы.",
"Single Maintenance Window": "Адзінае акно тэхабслугоўвання",
"Maintenance Time Window of a Day": "Суточны інтэрвал для тэхабслугоўвання",
"Effective Date Range": "Даты дзеяння (Неабавязкова)",
"Schedule Maintenance": "Запланаваць тэхабслугоўванне",
"Edit Maintenance": "Рэдагаваць тэхабслугоўванне",
"Date and Time": "Дата і час",
"DateTime Range": "Дыяпазон даты і часу",
"loadingError": "Немагчыма атрымаць даныя, калі ласка паспрабуйце пазней.",
"plugin": "Плагін | Плагіны",
"install": "Усталяваць",
"installing": "Усталяваецца",
"uninstall": "Выдаліць",
"uninstalling": "Выдаляецца",
"confirmUninstallPlugin": "Вы ўпэўнены, што хочаце выдаліць гэты плагін?",
"notificationRegional": "Рэгіянальны",
"Clone Monitor": "Копія",
"Clone": "Кланаваць",
"cloneOf": "Копія {0}",
"smtp": "Email (SMTP)",
"secureOptionNone": "Няма / STARTTLS (25, 587)",
"secureOptionTLS": "TLS (465)",
"Ignore TLS Error": "Ігнараваць памылкі TLS",
"From Email": "Ад каго",
"emailCustomisableContent": "Наладжвальны змест",
"smtpLiquidIntroduction": "Наступныя два поля з'яўляюцца шабланізаванымі з дапамогай мовы шаблонаў Liquid. Інструкцыі па іх выкарыстаньні прадстаўлены ў раздзеле {0}. Вось даступныя зменныя:",
"emailCustomSubject": "Свая тэма",
"leave blank for default subject": "пакіньце пустым для тэмы па змаўчаньні",
"emailCustomBody": "Карыстацкі аб'ект",
"leave blank for default body": "пакіньце пустым для аб'екта па змаўчаньні",
"emailTemplateServiceName": "Назва сэрвіса",
"emailTemplateHostnameOrURL": "Назва хоста або URL",
"emailTemplateStatus": "Статус",
"emailTemplateMonitorJSON": "аб'ект, які апісвае манітор",
"emailTemplateHeartbeatJSON": "аб'ект, які апісвае сігнал",
"emailTemplateMsg": "паведамленне апавешчання",
"emailTemplateLimitedToUpDownNotification": "даступны толькі для сігналаў UP/DOWN, у адваротным выпадку null",
"To Email": "Каму",
"smtpCC": "Копія",
"smtpBCC": "Схаваная копія",
"Discord Webhook URL": "Discord вэбхук URL",
"wayToGetDiscordURL": "Вы можаце стварыць яго ў наладах канала \"Налады -> Інтэграцыі -> Стварыць Вэбхук\"",
"Bot Display Name": "Адлюстраваная назва бота",
"Prefix Custom Message": "Свой прэфікс паведамлення",
"Hello @everyone is...": "Прывітанне {'@'}everyone гэта…",
"wayToGetTeamsURL": "Як стварыць URL вэбхука вы можаце даведацца тут - {0}.",
"wayToGetZohoCliqURL": "Вы можаце даведацца, як стварыць webhook URL тут {0}.",
"needSignalAPI": "Вам патрэбны кліент Signal з падтрымкай REST API.",
"Channel access token": "Токен доступу да канала",
"wayToCheckSignalURL": "Перайдзіце па гэтаму URL, каб даведацца, як наладзіць такі кліент:",
"Recipients": "Атрымальнікі",
"Access Token": "Токен доступу",
"Channel access token (Long-lived)": "Токен доступу да канала (даўгавечны)",
"Line Developers Console": "Кансоль распрацошчыкаў Line",
"Basic Settings": "Базавыя налады",
"User ID": "ID карыстальніка",
"Your User ID": "Ваш ідэнтыфікатар карыстальніка",
"Messaging API": "API паведамленняў",
"wayToGetLineChannelToken": "Спачатку зайдзіце ў {0}, стварыце правайдэра і канал (API паведамленняў), потым вы зможаце атрымаць токен доступу да канала і ID карыстальніка з вышэйзгаданых пунктаў меню.",
"Icon URL": "URL значка",
"aboutIconURL": "Вы можаце ўставіць спасылку на значок ў поле \"URL значка\" каб змяніць малюнак профілю па змаўчанні. Не выкарыстоўваецца, калі зададзена значок Emoji.",
"aboutMattermostChannelName": "Вы можаце перавызначыць канал па змаўчанні, у які вэбхук піша, уведаўшы імя канала ў поле \"Імя канала\". Гэта неабходна ўключыць у наладах вэбхука Mattermost. Напрыклад: #other-channel",
"dataRetentionTimeError": "Перыяд захавання павінен быць 0 або больш",
"infiniteRetention": "Выберыце 0 для бясконцага захавання.",
"confirmDeleteTagMsg": "Вы сапраўды хочаце выдаліць гэты тэг? Маніторы, звязаныя з гэтым тэгам не будуць выдаленыя.",
"enableGRPCTls": "Дазволіць адпраўляць gRPC запыт праз TLS злучэнне",
"grpcMethodDescription": "Імя метада пераўтвараецца ў фармат camelCase, напрыклад, sayHello, check і г.д.",
"acceptedStatusCodesDescription": "Выберыце коды статусаў для вызначэння даступнасці службы.",
"deleteMonitorMsg": "Вы сапраўды хочаце выдаліць гэты манітор?",
"deleteMaintenanceMsg": "Вы сапраўды хочаце выдаліць гэтае тэхабслугоўванне?",
"deleteNotificationMsg": "Вы сапраўды хочаце выдаліць гэтую абвестку для ўсіх манітораў?",
"dnsPortDescription": "Па змаўчанні порт DNS сервера - 53. Мы можаце змяніць яго ў любы час.",
"resolverserverDescription": "Cloudflare з'яўляецца серверам па змаўчанні. Вы заўсёды можаце змяніць гэты сервер.",
"rrtypeDescription": "Выберыце тып рэсурснага запісу, які вы хочаце адсочваць",
"pauseMonitorMsg": "Вы сапраўды хочаце прыпыніць?",
"enableDefaultNotificationDescription": "Для кожнага новага манітора гэта апавяшчэнне будзе ўключана па змаўчанні. Вы ўсё яшчэ можаце адключыць апавяшчэнні ў кожным маніторы асобна.",
"clearEventsMsg": "Вы сапраўды хочаце выдаліць усю статыстыку падзей гэтага манітора?",
"clearHeartbeatsMsg": "Вы сапраўды хочаце выдаліць усю статыстыку апытанняў гэтага манітора?",
"confirmClearStatisticsMsg": "Вы сапраўды хочаце выдаліць УСЮ статыстыку?",
"importHandleDescription": "Выберыце \"Прапусціць існуючыя\", калі вы хочаце прапусціць кожны манітор або апавяшчэнне з такой жа назвай. \"Перазапісаць\" выдаліць кожны існуючы манітор або апавяшчэнне і дадаць зноў. Варыянт \"Не правяраць\" прымусова адновіць усе маніторы і апавяшчэнні, нават калі яны ўжо існуюць.",
"twoFAVerifyLabel": "Увядзіце свой токен, каб праверыць працу 2FA:",
"tokenValidSettingsMsg": "Токен сапраўдны! Цяпер вы можаце захаваць налады 2FA.",
"confirmImportMsg": "Вы сапраўды хочаце аднавіць рэзервовую копію? Пераканайцеся, што вы выбралі правільны варыянт імпарту.",
"confirmEnableTwoFAMsg": "Вы сапраўды хочаце ўключыць 2FA?",
"confirmDisableTwoFAMsg": "Вы сапраўды хочаце адключыць 2FA?",
"affectedStatusPages": "Паказваць абвестку аб тэхабслугоўванні на выбраных старонках статуса",
"atLeastOneMonitor": "Выберыце больш за адзін затрагаваны манітор",
"passwordNotMatchMsg": "Уведзеныя паролі не супадаюць.",
"notificationDescription": "Прымацаваць абвесткі да манітораў.",
"keywordDescription": "Пошук слова ў чыстым HTML або ў JSON-адказе (адчувальны да рэгістра).",
"invertKeywordDescription": "Шукаць, каб ключавое слова адсутнічала, а не прысутнічала.",
"jsonQueryDescription": "Выконайце json-запыт да адказу і праверце наяўнасць чаканага значэння (вяртанае значэнне будзе пераўтворана ў радок для параўнання). Глядзіце {0} для атрымання дакументацыі па мове запытаў. А трэніравацца вы можаце {1}.",
"backupDescription": "Вы можаце захаваць рэзервовую копію ўсіх манітораў і апавешчанняў у выглядзе JSON-файла.",
"backupDescription2": "Важна: гісторыя і падзеі захаваныя не будуць.",
"backupDescription3": "Важныя даныя, такія як токены апавешчанняў, дадаюцца пры экспарце, таму захоўвайце файлы ў бяспечным месцы.",
"endpoint": "канчатковая кропка",
"octopushAPIKey": "\"{API key}\" з даных уліковых запісаў HTTP API ў панэлі кіравання",
"octopushLogin": "\"Login\" з даных уліковых запісаў HTTP API ў панэлі кіравання",
"promosmsLogin": "Лагін API",
"promosmsPassword": "Пароль API",
"pushoversounds pushover": "Pushover (па змаўчанні)",
"pushoversounds bike": "Веласіпед",
"pushoversounds bugle": "Горн",
"pushoversounds cashregister": "Касавы апарат",
"pushoversounds classical": "Класічны",
"pushoversounds cosmic": "Касмічны",
"pushoversounds falling": "Падаючы",
"pushoversounds intermission": "Антракт",
"pushoversounds magic": "Магія",
"pushoversounds mechanical": "Механічны",
"pushoversounds pianobar": "Піяна-бар",
"pushoversounds siren": "Сірэна",
"pushoversounds spacealarm": "Касмічная сігналізацыя",
"pushoversounds tugboat": "Буксір",
"pushoversounds alien": "Іншаплянетная трывога (доўгая)",
"pushoversounds persistent": "Настойлівы (доўгі)",
"pushoversounds echo": "Pushover Эха (доўгае)",
"pushoversounds updown": "Уверх уніз (доўгае)",
"pushoversounds vibrate": "Толькі вібрацыя",
"pushoversounds none": "Няма (ціха)",
"pushyAPIKey": "Сакрэтны ключ API",
"pushyToken": "Токен прылады",
"apprise": "Apprise (Падтрымка 50+ сэрвісаў абвестак)",
"GoogleChat": "Google Chat (толькі Google Workspace)",
"wayToGetKookGuildID": "Уключыце \"Рэжым распрацошчыка\" у наладах Kook, а затым націсніце правай кнопкай на гільдыю, каб скапіраваць яе ID",
"Guild ID": "Ідэнтыфікатар гільдыі",
"User Key": "Ключ карыстальніка",
"Message Title": "Загаловак паведамлення",
"Notification Sound": "Гук абвесткі",
"More info on:": "Больш інфармацыі на: {0}",
"pushoverDesc1": "Экстрэмальны прыярытэт (2) мае таймаўт паўтору па змаўчанні 30 секунд і сканчаецца праз 1 гадзіну.",
"pushoverDesc2": "Калі вы хочаце адпраўляць абвесткі розным прыладам, неабходна запоўніць поле Прылада.",
"pushoverMessageTtl": "TTL паведамлення (у секундах)",
"SMS Type": "Тып SMS",
"octopushTypePremium": "Преміум (Хуткі - рэкамендуецца для аляртаў)",
"octopushTypeLowCost": "Танны (Павольны - часам блакуецца аператарамі)",
"apiCredentials": "API рэквізіты",
"checkPrice": "Тарыфы {0}:",
"octopushLegacyHint": "Вы выкарыстоўваеце старую версію Octopush (2011-2020) ці новую?",
"Check octopush prices": "Тарыфы Octopush {0}.",
"octopushPhoneNumber": "Нумар тэлефона (міжнародны фармат напр. +48123456789) ",
"octopushSMSSender": "Імя адпраўніка SMS: 3-11 сімвалаў алфавіта, лічбаў і прабелаў (a-zA-Z0-9)",
"LunaSea Device ID": "ID прылады LunaSea",
"Apprise URL": "URL апавяшчэння",
"Example:": "Прыклад: {0}",
"Read more:": "Падрабязней: {0}",
"Status:": "Статус: {0}",
"Strategy": "Стратэгія",
"Free Mobile User Identifier": "Бясплатны мабільны ідэнтыфікатар карыстальніка",
"Free Mobile API Key": "API ключ Free Mobile",
"Enable TLS": "Уключыць TLS",
"Proto Service Name": "Назва службы Proto",
"Proto Method": "Метад Proto",
"Proto Content": "Змест Proto",
"Economy": "Эканомія",
"Lowcost": "Бюджэтны",
"high": "высокі",
"SendKey": "SendKey",
"SMSManager API Docs": "Дакументацыя да API SMSManager ",
"Gateway Type": "Тып шлюза",
"You can divide numbers with": "Вы можаце дзяліць лічбы з",
"Base URL": "Базавы URL",
"goAlertInfo": "GoAlert — гэта праграма з адкрытым зыходным кодам для складання раскладу выклікаў, аўтаматычнай эскаляцыі і абвестак (напрыклад, SMS або галасавых выклікаў). Аўтаматычна прывабляйце патрэбнага чалавека, патрэбным спосабам і ў патрэбны час! {0}",
"goAlertIntegrationKeyInfo": "Атрымаць агульны ключ інтэграцыі API для службы ў гэтым фармаце \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\" звычайна значэнне параметра токена скапіяванага URL.",
"AccessKeyId": "ID ключа доступу",
"SecretAccessKey": "Сакрэтны ключ доступу",
"PhoneNumbers": "Нумары тэлефонаў",
"TemplateCode": "Код шаблону",
"SignName": "SignName",
"Sms template must contain parameters: ": "Шаблон SMS павінен змяшчаць параметры: ",
"Bark API Version": "Версія Bark API",
"Bark Endpoint": "Канчатковая кропка Bark",
"Bark Group": "Bark Group",
"Bark Sound": "Bark Sound",
"WebHookUrl": "WebHookUrl",
"SecretKey": "Сакрэтны Ключ",
"For safety, must use secret key": "Для бяспекі, неабходна выкарыстоўваць сакрэтны ключ",
"Mentioning": "Згадванне",
"Don't mention people": "Не згадваць людзей",
"Mention group": "Згадаць {group}",
"Device Token": "Токен прылады",
"Platform": "Платформа",
"High": "Высокі",
"Retry": "Паўторыць",
"Topic": "Тэма",
"WeCom Bot Key": "WeCom Bot Key",
"Setup Proxy": "Налада Проксі",
"Proxy Protocol": "Пратакол Проксі",
"Proxy Server": "Проксі",
"Proxy server has authentication": "Проксі мае аўтэнтыфікацыю",
"promosmsTypeEco": "SMS ECO - танкі і павольны, часта перагружаны. Толькі для атрымальнікаў з Польшчы.",
"promosmsTypeFlash": "SMS FLASH - паведамленні аўтаматычна з'яўляюцца на прыладзе атрымальніка. Толькі для атрымальнікаў з Польшчы.",
"promosmsTypeFull": "SMS FULL - прэміум-узровень SMS, можна выкарыстоўваць сваё імя адпраўніка (папярэдне зарэгістраваў яго). Надзейна для аляртаў.",
"promosmsTypeSpeed": "SMS SPEED - найвышэйшы прыярытэт у сістэме. Вельмі хутка і надзейна, але вельмі дорага (у два разы дорага, чым SMS FULL).",
"promosmsPhoneNumber": "Нумар тэлефона (для атрымальнікаў з Польшчы можна прапусціць код рэгіёна)",
"promosmsSMSSender": "Імя адпраўніка SMS: Зарэгістраванае або адно з імён па змаўчанні: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
"promosmsAllowLongSMS": "Дазволіць доўгія SMS",
"Feishu WebHookUrl": "Feishu WebHookURL",
"matrixHomeserverURL": "URL сервера (разам з http(s):// і па жаданні порт)",
"Internal Room Id": "Унутраны ID пакою",
"matrixDesc1": "Унутраны ID пакою можна знайсці ў Падрабязнасцях у параметрах канала вашага кліента Matrix. Ён павінен выглядаць прыблізна так !QMdRCpUIfLwsfjxye6:home.server.",
"matrixDesc2": "Рэкамендуецца стварыць новага карыстальніка і не выкарыстоўваць токен доступу асабістага карыстальніка Matrix, т.к. гэта ўяўляе за сабой поўны доступ да акаўнта і да пакояў, у якіх вы знаходзіцеся. Замест гэтага стварыце новага карыстальніка і запрасіце яго толькі ў той пакой, у якім вы хочаце атрымліваць абвесткі. Токен доступу можна атрымаць, выканаўшы каманду {0}",
"Channel Name": "Назва канала",
"Notify Channel": "Канал апавешчанняў",
"aboutNotifyChannel": "Апавяшчэнне аб канале выкліча настольнае або мабільнае апавяшчэнне для ўсіх удзельнікаў канала, незалежна ад таго, ці ўстаноўлена іх даступнасць як актыўная або адсутная.",
"Uptime Kuma URL": "Uptime Kuma URL",
"setup a new monitor group": "наладзіць новую групу манітораў",
"openModalTo": "адкрыць мадальнае акно {0}",
"Add a domain": "Дадаць дамен",
"Remove domain": "Выдаліць дамен '{0}'",
"Icon Emoji": "Emoji",
"signalImportant": "ВАЖНА: Нельга змешваць у Атрымальніках групы і нумары!",
"aboutWebhooks": "Больш інфармацыі аб вэбхуках: {0}",
"aboutChannelName": "Увядзіце назву канала ў поле {0} Назва канала, калі вы хочаце абысці канал вэбхука. Напрыклад: #other-channel",
"aboutKumaURL": "Калі поле Uptime Kuma URL у наладах застанецца пустым, па змаўчанні будзе выкарыстоўвацца спасылка на праект на GitHub.",
"smtpDkimSettings": "DKIM Налады",
"smtpDkimDesc": "Калі ласка, азнаёмцеся з {0} Nodemailer DKIM для выкарыстання.",
"documentation": "дакументацыяй",
"smtpDkimDomain": "Назва дамена",
"smtpDkimKeySelector": "Ключ",
"smtpDkimPrivateKey": "Прыватны ключ",
"smtpDkimHashAlgo": "Алгарытм хэша (неабавязкова)",
"smtpDkimheaderFieldNames": "Загаловак ключоў для подпісу (неабавязкова)",
"smtpDkimskipFields": "Загаловак ключоў не для подпісу (опцыянальна)",
"wayToGetPagerDutyKey": "Вы можаце гэта атрымаць, перайшоўшы ў Сервіс -> Каталог сервісаў -> (Выберыце сервіс) -> Інтэграцыі -> Дадаць інтэграцыю. Тут вы можаце шукаць «Events API V2». Падрабязней {0}",
"Integration Key": "Ключ інтэграцыі",
"Integration URL": "URL інтэграцыі",
"Auto resolve or acknowledged": "Аўтаматычнае развязванне або пацверджанне",
"do nothing": "нічога не рабіць",
"auto acknowledged": "аўтаматычна пацверджана",
"auto resolve": "аўтаматычна развязана",
"alertaApiEndpoint": "Канчатковая кропка API",
"alertaEnvironment": "Асяроддзе",
"alertaApiKey": "Ключ API",
"alertaAlertState": "Стан алярта",
"alertaRecoverState": "Стан аднаўлення",
"serwersmsAPIUser": "API Карыстальнік (уключаючы прэфікс webapi_)",
"serwersmsAPIPassword": "API Пароль",
"serwersmsPhoneNumber": "Нумар тэлефона",
"serwersmsSenderName": "SMS Імя адпраўніка (зарэгістравана праз карыстальніцкі партал)",
"smseagleTo": "Нумар(ы) тэлефона",
"smseagleGroup": "Назва(ы) групы тэлефоннай кнігі",
"smseagleContact": "Імёны кантактаў тэлефоннай кнігі",
"smseagleRecipientType": "Тып атрымальніка",
"smseagleRecipient": "Атрымальнік(і) (калі множнасць, павінны быць раздзеленыя коскай)",
"smseagleToken": "Токен доступу API",
"smseagleUrl": "URL вашага прылады SMSEagle",
"smseagleEncoding": "Адправіць у Unicode",
"smseaglePriority": "Прыярытэт паведамлення (0-9, па змаўчанні = 0)",
"Recipient Number": "Нумар атрымальніка",
"From Name/Number": "Імя/нумар адпраўніка",
"Leave blank to use a shared sender number.": "Пакіньце пустым, каб выкарыстоўваць агульны нумар адпраўніка.",
"Octopush API Version": "Версія API Octopush",
"Legacy Octopush-DM": "Састарэлы Octopush-DM",
"ntfy Topic": "Тэма ntfy",
"Server URL should not contain the nfty topic": "URL сервера не павінен утрымліваць тэму nfty",
"onebotHttpAddress": "HTTP-адрас OneBot",
"onebotMessageType": "Тып паведамлення OneBot",
"onebotGroupMessage": "Група",
"onebotPrivateMessage": "Асабістае",
"onebotUserOrGroupId": "ID групы/карыстальніка",
"onebotSafetyTips": "Для бяспекі неабходна ўсталяваць токен доступу",
"PushDeer Server": "Сервер PushDeer",
"pushDeerServerDescription": "Пакіньце пустым для выкарыстання афіцыйнага сервера",
"PushDeer Key": "Ключ PushDeer",
"wayToGetClickSendSMSToken": "Вы можаце атрымаць імя карыстальніка API і ключ API з {0} .",
"Custom Monitor Type": "Сваёродны тып манітора",
"Google Analytics ID": "ID Google Аналітыкі",
"Edit Tag": "Рэдагаваць тэг",
"Server Address": "Адрас сервера",
"Learn More": "Даведацца больш",
"Body Encoding": "Тып зместу запыту.(JSON або XML)",
"API Keys": "API Ключы",
"Expiry": "Сканчэнне",
"Continue": "Працягнуць",
"Add Another": "Дадаць яшчэ",
"Key Added": "Ключ дададзены",
"apiKeyAddedMsg": "Ваш ключ API дададзены. Звярніце ўвагу на гэтае паведамленне, так як яно адлюстроўваецца адзін раз.",
"Add API Key": "Дадаць API ключ",
"No API Keys": "Няма ключоў API",
"apiKey-active": "Актыўны",
"apiKey-expired": "Скончыўся",
"apiKey-inactive": "Неактыўны",
"Expires": "Сканчаецца",
"disableAPIKeyMsg": "Вы ўпэўнены, што хочаце адключыць гэты API ключ?",
"deleteAPIKeyMsg": "Вы ўпэўнены, што хочаце выдаліць гэты ключ API?",
"Generate": "Згенераваць",
"pagertreeIntegrationUrl": "URL-адрас інтэграцыі",
"pagertreeUrgency": "Тэрміновасць",
"pagertreeSilent": "Ціхі",
"pagertreeLow": "Нізкі",
"pagertreeMedium": "Сярэдні",
"pagertreeHigh": "Высокі",
"pagertreeCritical": "Крытычны",
"pagertreeResolve": "Аўтаматычнае развязванне",
"pagertreeDoNothing": "Нічога не рабіць",
"wayToGetPagerTreeIntegrationURL": "Пасля стварэння інтэграцыі Uptime Kuma ў PagerTree скапіруйце файл {Endpoint}. Гл. поўную інфармацыю {0}",
"lunaseaTarget": "Мэта",
"lunaseaDeviceID": "Ідэнтыфікатар прылады",
"lunaseaUserID": "Ідэнтыфікатар карыстальніка",
"ntfyAuthenticationMethod": "Метад уваходу",
"ntfyPriorityHelptextAllEvents": "Усе падзеі адпраўляюцца з максімальным прыярытэтам",
"ntfyPriorityHelptextAllExceptDown": "Усе падзеі адпраўляюцца з гэтым прыярытэтам, акрамя {0}-падзеяў, якія маюць прыярытэт {1}",
"ntfyUsernameAndPassword": "Лагін і пароль",
"twilioAccountSID": "SID уліковага запісу",
"twilioApiKey": "Ключ API (неабавязкова)",
"twilioAuthToken": "Токен аўтарызацыі / Сакрэтны API ключ",
"twilioFromNumber": "З нумара",
"twilioToNumber": "На нумар",
"Monitor Setting": "Налада манітора {0}",
"Show Clickable Link": "Паказаць націскальную спасылку",
"Show Clickable Link Description": "Калі пазначаны флажок, усе, хто мае доступ да гэтай старонкі стану, могуць мець доступ да URL-адрасу манітора.",
"Open Badge Generator": "Адкрыць генератар значкаў",
"Badge Generator": "Генератар значкоў для {0}",
"Badge Type": "Тып значка",
"Badge Duration (in hours)": "Тэрмін дзеяння значка (у гадзінах)",
"Badge Label": "Надпіс для значка",
"Badge Prefix": "Значэнне прэфікса значка",
"Badge Suffix": "Значэнне суфікса значка",
"Badge Label Color": "Колер надпісу значка",
"Badge Color": "Колер значка",
"Badge Label Prefix": "Прэфікс надпісу для значка",
"Badge Preview": "Папярэдні прагляд значка",
"Badge Label Suffix": "Суфікс надпісу для значка",
"Badge Up Color": "Колер значка для статусу \"Даступны\"",
"Badge Down Color": "Колер значка для статусу \"Недаступны\"",
"Badge Pending Color": "Колер значка для статусу \"Чаканне\"",
"Badge Maintenance Color": "Колер значка для статусу \"Тэхабслугоўванне\"",
"Badge Warn Color": "Колер значка для папярэджання",
"Badge Warn Days": "Значок для \"дзён папярэджання\"",
"Badge Down Days": "Значок для \"дзён недаступнасці\"",
"Badge Style": "Стыль значка",
"Badge value (For Testing only.)": "Значэнне значка (толькі для тэставання)",
"Group": "Група",
"Monitor Group": "Група манітораў",
"monitorToastMessagesLabel": "Апавяшчэнні",
"monitorToastMessagesDescription": "Паведамленні для манітораў знікаюць праз зададзены час у секундах. Значэнне -1 адключае тайм-аўт. Значэнне 0 адключае апавяшчэнні.",
"toastErrorTimeout": "Таймаут для апавешчанняў пра памылкі",
"toastSuccessTimeout": "Таймаут для апавешчанняў пра паспяховасьць",
"Enter the list of brokers": "Увядзіце спіс брокераў",
"Kafka Brokers": "Kafka Brokers",
"Press Enter to add broker": "Націсніце Enter, каб дадаць брокера",
"Kafka Topic Name": "Назва тэмы Kafka",
"Kafka Producer Message": "Паведамленне продюсера Kafka",
"Enable Kafka SSL": "Уключэнне пратаколу Kafka SSL",
"Enable Kafka Producer Auto Topic Creation": "Уключэнне аўтаматычнага стварэння тэм у Kafka Producer",
"Kafka SASL Options": "Параметры SASL у Kafka",
"Mechanism": "Механізм",
"Pick a SASL Mechanism...": "Выберыце механізм SASL…",
"Authorization Identity": "Аўтарызацыйная ідэнтычнасць",
"AccessKey Id": "AccessKey Id",
"Secret AccessKey": "Сакрэтны ключ доступу",
"Session Token": "Токен сеансу",
"noGroupMonitorMsg": "Не даступна. Спачатку стварыце групу манітораў.",
"Close": "Закрыць",
"Request Body": "Цела запыту",
"wayToGetFlashDutyKey": "Вы можаце перайсці на старонку \"Канал\" -> (Выберыце канал) -> \"Інтэграцыі\" -> \"Дадаць новую старонку інтэграцыі\", дадаць \"Карыстацкую падзею\", каб атрымаць push-адрас, скапіяваць ключ інтэграцыі ў адрас. Для атрымання дадатковай інфармацыі, калі ласка, наведайце",
"FlashDuty Severity": "Сур'ёзнасць",
"nostrRecipients": "Адкрытыя ключы атрымальнікаў (npub)",
"nostrRelaysHelp": "Адзін URL-адрас рэтрансляцыі ў кожным радку",
"nostrSender": "Закрыты ключ адпраўшчыка (nsec)",
"nostrRecipientsHelp": "фармат npub, па адным у радку",
"showCertificateExpiry": "Паказваць пратэрмінаваны сертыфікат",
"noOrBadCertificate": "Адсутнасць сертыфіката",
"gamedigGuessPortDescription": "Порт, які выкарыстоўваецца пратаколам Valve Server Query Protocol, можа адрознівацца ад порта кліента. Паспрабуйце гэта, калі манітор не можа падключыцца да сервера.",
"authUserInactiveOrDeleted": "Карыстальнік неактыўны або выдалены.",
"authInvalidToken": "Няправільны токен.",
"authIncorrectCreds": "Няправільнае імя карыстальніка або пароль.",
"2faAlreadyEnabled": "2FA ўжо ўключана.",
"2faEnabled": "2FA ўключана.",
"2faDisabled": "2FA адключана.",
"successAdded": "Паспяхова дададзена.",
"successResumed": "Паспяхова прадоўжана.",
"successPaused": "Паспяхова спынена.",
"successDeleted": "Паспяхова выдалена.",
"successEdited": "Паспяхова зменена.",
"successAuthChangePassword": "Пароль паспяхова абноўлены.",
"successBackupRestored": "Рэзервовая копія паспяхова адноўлена.",
"successDisabled": "Паспяхова адключана.",
"successEnabled": "Паспяхова ўключана.",
"tagNotFound": "Тэг не знойдзены.",
"foundChromiumVersion": "Выяўлены Chromium/Chrome. Версіі: {0}",
"Remote Browsers": "Аддаленыя браўзеры",
"Remote Browser": "Аддалены браўзер",
"Add a Remote Browser": "Дадаць аддалены браўзер",
"Remote Browser not found!": "Аддалены браўзер не знойдзены!",
"remoteBrowsersDescription": "Аддаленыя браўзеры — альтэрнатыва лакальнаму запуску Chromium. Усталюйце такі сервіс, як browserless.io, або падлучыцеся да свайго ўласнага",
"self-hosted container": "кантэйнер, які хостыцца самастойна",
"remoteBrowserToggle": "Па змаўчаньні Chromium працуе ўнутры кантэйнера Uptime Kuma. Вы можаце выкарыстоўваць аддалены браўзер, пераключыўшы гэты пераключальнік.",
"useRemoteBrowser": "Выкарыстоўваць удалены браўзер",
"deleteRemoteBrowserMessage": "Вы ўпэўнены, што хочаце выдаліць гэты удалены браўзер для ўсіх манітораў?",
"Browser Screenshot": "Скрыншот браўзера",
"wayToGetSevenIOApiKey": "Зайдзіце на панэль кіравання па адрасе app.seven.io > распрацоўшчык > {api key} > зялёная кнопка дадаць",
"senderSevenIO": "Адпраўляе нумар або імя",
"receiverSevenIO": "Нумар атрымання",
"apiKeySevenIO": "SevenIO {API Key}",
"receiverInfoSevenIO": "Калі нумар атрымальніка не знаходзіцца ў Германіі, то перад нумарам неабходна дадаць код краіны (напрыклад, для ЗША код краіны 1, тады выкарыстоўвайце 117612121212, замест 017612121212)",
"wayToGetWhapiUrlAndToken": "Вы можаце атрымаць {API URL} і токен, зайдзяўшы ў патрэбны вам канал з {0}",
"whapiRecipient": "Нумар тэлефона / ID кантакта / ID групы",
"documentationOf": "{0} Дакументацыя",
"What is a Remote Browser?": "Што такое аддалены браўзер?",
"wayToGetHeiiOnCallDetails": "Як атрымаць ID трыгера і {API Keys}, напісана ў {documentation}",
"callMeBotGet": "Тут вы можаце стварыць {endpoint} для {0}, {1} і {2}. Майце на ўвазе, што вы можаце атрымаць абмежаванне па хуткасці. Абмежаванні па хуткасці выглядаюць наступным чынам: {3}",
"gtxMessagingApiKeyHint": "Вы можаце знайсці свой {API key} на старонцы: Мае уліковыя запісы маршрутызацыі > Паказаць інфармацыю аб уліковым запісе > Уліковыя даныя API > REST API (v2.x)",
"From Phone Number / Transmission Path Originating Address (TPOA)": "Нумар тэлефона / Адрас крыніцы шляху перадачы (АІПП)",
"To Phone Number": "На нумар тэлефона",
"gtxMessagingToHint": "Міжнародны фармат, з «+» ({e164}, {e212} або {e214})",
"Alphanumeric (recommended)": "Літарна-лічбавая (рэкамендуецца)",
"Telephone number": "Нумар тэлефона",
"cellsyntOriginatortypeAlphanumeric": "Літарна-лічбавы радок (не больш за 11 літарна-лічбавых сімвалаў). Атрымальнікі не могуць адказаць на гэта паведамленне.",
"cellsyntOriginatortypeNumeric": "Лічбавае значэнне (не больш за 15 лічбаў) з нумарам тэлефона ў міжнародным фармаце без 00 ў пачатку (напрыклад, нумар Вялікабрытаніі 07920 110 000 павінен быць заданы, як 447920110000). Атрымальнікі могуць адказаць на паведамленне.",
"Originator": "Крыніца",
"cellsyntOriginator": "Бачны на мабільным тэлефоне атрымальніка як адпраўшчыка паведамлення. Дапушчальныя значэнні і функцыя залежаць ад параметра {originatortype}.",
"cellsyntDestination": "Нумар тэлефона атрымальніка ў міжнародным фармаце з 00 ў пачатку, за якім следуе код краіны, напрыклад, 00447920110000 для нумара Вялікабрытаніі 07920 110 000 (не больш за 17 лічбаў у суме). Не больш за 25000 атрымальнікаў, раздзеленых коскамі, на адзін HTTP-запыт.",
"Allow Long SMS": "Дазволіць доўгія SMS",
"cellsyntSplitLongMessages": "Раздзеляць доўгія паведамленні на 6 частак. 153 x 6 = 918 сімвалаў.",
"max 15 digits": "макс. 15 лічбаў",
"max 11 alphanumeric characters": "максімум 11 літарна-лічбавых сімвалаў",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Увядзіце {Hostname} сервера, да якога вы хочаце падключыцца, або {localhost}, калі вы хочаце выкарыстоўваць {local_mta}",
"Saved.": "Захавана.",
"wayToWriteWhapiRecipient": "Нумар тэлефона з міжнародным прэфіксам, але без знака плюс у пачатку ({0}), ідэнтыфікатара кантакта ({1}) або ідэнтыфікатара групы ({2}).",
"gtxMessagingFromHint": "На мабільных тэлефонах атрымальнікі бачаць АІПП як адпраўшчыка паведамлення. Дапускаецца выкарыстаньне да 11 літарна-лічбавых сімвалаў, шорткода, мясцовага доўгага кода або міжнародных нумароў ({e164}, {e212} або {e214})",
"Send to channel": "Адправіць у канал",
"threadForumPostID": "Трэд / ID паста",
"whatHappensAtForumPost": "Стварыць новы пост на форуме. Гэта НЕ размяшчае паведамленні ў існуючым пасце. Для публікацыі ў існуючай публікацыі выкарыстоўвайце \"{option}\""
}

View File

@ -77,7 +77,7 @@
"Save": "Запази",
"Notifications": "Известия",
"Not available, please setup.": "Не са налични. Моля, настройте.",
"Setup Notification": "Настрой известие",
"Setup Notification": "Настройка на известие",
"Light": "Светла",
"Dark": "Тъмна",
"Auto": "Автоматично",
@ -146,7 +146,7 @@
"Options": "Опции",
"Keep both": "Запази двете",
"Verify Token": "Провери токен код",
"Setup 2FA": "Настройка 2FA",
"Setup 2FA": "Настройка на 2FA",
"Enable 2FA": "Активирай 2FA",
"Disable 2FA": "Деактивирай 2FA",
"2FA Settings": "Настройка за 2FA",
@ -403,7 +403,7 @@
"Retry": "Повтори",
"Topic": "Тема",
"WeCom Bot Key": "WeCom бот ключ",
"Setup Proxy": "Настрой прокси",
"Setup Proxy": "Настройка на прокси",
"Proxy Protocol": "Прокси протокол",
"Proxy Server": "Прокси сървър",
"Proxy server has authentication": "Прокси сървърът е с удостоверяване",
@ -802,7 +802,6 @@
"twilioApiKey": "API ключ (по избор)",
"Expected Value": "Очаквана стойност",
"Json Query": "Заявка тип JSON",
"jsonQueryDescription": "Прави JSON заявка срещу отговора и проверява за очаквана стойност (Върнатата стойност ще бъде преобразувана в низ за сравнение). Разгледайте {0} за документация относно езика на заявката. Имате възможност да тествате {1}.",
"Badge Duration (in hours)": "Времетраене на баджа (в часове)",
"Badge Preview": "Преглед на баджа",
"Notify Channel": "Канал за известяване",
@ -897,10 +896,10 @@
"DockerHostRequired": "Моля, задайте \"Docker\" хоста за този монитор.",
"Browser Screenshot": "Екранна снимка на браузър",
"remoteBrowserToggle": "По подразбиране Chromium работи в контейнера Uptime Kuma. Можете да използвате отдалечен браузър, като превключите този ключ.",
"remoteBrowsersDescription": "Отдалечените браузъри са алтернатива на локалното стартиране на Chromium. Настройте с услуга като browserless.io или свържете с вашата собствена",
"remoteBrowsersDescription": "Отдалечените браузъри са алтернатива на локалното стартиране на Chromium. Настройте с услуга като \"browserless.io\" или свържете с Вашата собствена",
"Remove the expiry notification": "Премахни деня за известяване при изтичане",
"Add a new expiry notification day": "Добави нов ден за известяване при изтичане",
"setup a new monitor group": "настройване на нова група от монитори",
"setup a new monitor group": "настройка на нова група от монитори",
"openModalTo": "отвори модален прозорец към {0}",
"Add a domain": "Добави домейн",
"Remove domain": "Премахни домейн '{0}'",
@ -973,5 +972,23 @@
"Create new forum post": "Създай нова публикация във форум",
"postToExistingThread": "Публикувай в съществуваща тема/публикация във форум",
"forumPostName": "Име на публикацията във форума",
"threadForumPostID": "ID на публикация в темата/форум"
"threadForumPostID": "ID на публикация в темата/форум",
"smspartnerApiurl": "Можете да намерите вашия API ключ в таблото на {0}",
"smspartnerPhoneNumber": "Телефон номер(а)",
"smspartnerPhoneNumberHelptext": "Номерът задължително е в международен формат {0}, {1}. Отделните номера трябва да бъдат разделени посредством {2}",
"smspartnerSenderName": "Име на изпращащия на SMS",
"smspartnerSenderNameInfo": "Трябва да е между 3..=11 стандартни знака",
"wayToGetThreemaGateway": "Можете да се регистрирате за Threema Gateway {0}.",
"threemaRecipient": "Получател",
"threemaRecipientType": "Тип получател",
"threemaRecipientTypeIdentity": "Threema-ID",
"threemaRecipientTypePhone": "Телефонен номер",
"threemaRecipientTypeEmail": "Имейл адрес",
"threemaSenderIdentity": "Gateway-ID",
"threemaSenderIdentityFormat": "8 знака, обикновено започва с *",
"threemaApiAuthenticationSecret": "Gateway-ID Тайна фраза",
"threemaRecipientTypeIdentityFormat": "8 знака",
"threemaRecipientTypePhoneFormat": "E.164, без водещ +",
"threemaBasicModeInfo": "Забележка: Тази интеграция използва Threema Gateway в основен режим (сървърно базирано криптиране). Допълнителни подробности можете да намерите {0}.",
"apiKeysDisabledMsg": "API ключовете са деактивирани, защото удостоверяването е деактивирано."
}

View File

@ -1 +1,18 @@
{}
{
"setupDatabaseChooseDatabase": "আপনি কোন ডাটাবেজটি ব্যবহার করতে চান?",
"setupDatabaseEmbeddedMariaDB": "আপনাকে কিছু নিযুক্ত করতে হবে না। এই ডকার ইমেজটি (Docker image) স্বয়ংক্রিয়ভাবে আপনার জন্য মারিয়া ডিবি (MariaDB) বসিয়েছে এবং প্রস্তুত করেছে।Uptime Kuma ইউনিক্স সকেটের (Unix Socket) মাধ্যমে এই ডাটাবেসের সাথে সংযুক্ত হবে।",
"setupDatabaseMariaDB": "একটি বহিরাগত মারিয়া ডিবি (MariaDB) ডাটাবেসের সাথে সংযোগ করুন। আপনাকে ডাটাবেস সংযোগ তথ্য নিযুক্ত করতে হবে।",
"Add": "সংযোগ করুন",
"dbName": "ডাটাবেজের নাম",
"languageName": "ইংরেজি",
"Settings": "সেটিংস",
"Dashboard": "ড্যাশবোর্ড",
"Help": "সাহায্য",
"New Update": "নতুন আপডেট",
"Language": "ভাষা",
"Version": "সংস্করণ",
"Check Update On GitHub": "GitHub-এ আপডেট চেক করুন",
"List": "তালিকা",
"General": "সাধারণ",
"Game": "খেলা"
}

View File

@ -70,5 +70,148 @@
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Introduïu el nom del servidor al qual voleu connectar-vos o {localhost} si voleu utilitzar un {local_mta}",
"Host URL": "URL del servidor",
"Friendly Name": "Nom senzill",
"markdownSupported": "Sintaxi de Markdown suportada"
"markdownSupported": "Sintaxi de Markdown suportada",
"Retries": "Reintents",
"Advanced": "Avançat",
"ignoreTLSErrorGeneral": "Ignora errors TLS/SSL per connexió",
"maxRedirectDescription": "Nombre màxim de redireccions a seguir. Establiu a 0 per a desactivar les redireccions.",
"Upside Down Mode": "Mode al revés",
"Max. Redirects": "Redireccions Màx",
"Accepted Status Codes": "Codis d'Estat Acceptats",
"needPushEvery": "Hauries de cridar a aquesta URL cada {0} segons.",
"Heartbeat Retry Interval": "Reintent de l'interval de \"heartbeat\"",
"Resend Notification if Down X times consecutively": "Reenvia notificacions si Down X vegades consecutives",
"resendEveryXTimes": "Reenvia cada {0} vegades",
"retryCheckEverySecond": "Reintenta cada {0} segons",
"checkEverySecond": "Comprova cada {0} segons",
"resendDisabled": "Reenvia deshabilitat",
"retriesDescription": "Màxim d'intents abans de que el servei sigui marcat com a caigut i la notificació sigui enviada",
"ignoreTLSError": "Ignora errors de TLS/SSL per a pàgines web HTTPS",
"upsideDownModeDescription": "Canvia l'estat al revés. Si el servei és accessible, està CAIGUT.",
"Setup Notification": "Configurar Notificació",
"Allow indexing": "Permetre indexat",
"Discourage search engines from indexing site": "Desencoratjar als motors de cerca que indexin la pàgina",
"Current Password": "Contrasenya actual",
"Please use this option carefully!": "Per favor, empra aquesta opció amb cura !",
"disable authentication": "deshabilita autenticació",
"Partially Degraded Service": "Servei Parcialment Degradat",
"Degraded Service": "Servei Degradat",
"Add Group": "Afegir Grup",
"Add a monitor": "Afegir monitor",
"pushViewCode": "Com emprar el monitor de Push? (Veure Codi)",
"Notifications": "Notificacions",
"pushOthers": "Altres",
"programmingLanguages": "Llenguatges de programació",
"Dark": "Fosc",
"Remember me": "Recordar-me",
"Login": "Iniciar sessió",
"No Monitors, please": "Sense Monitors, per favor",
"notAvailableShort": "N/A",
"Two Factor Authentication": "Segon Factor d'Autenticació",
"Custom": "Personalitzat",
"Search...": "Cercar…",
"Search monitored sites": "Cercar llocs monitoritzats",
"Avg. Response": "Resp. Promig",
"Add New below or Select...": "Afegir nova o Seleccionar…",
"Tag with this name already exist.": "Aquesta etiqueta ja existeix.",
"color": "Color",
"Gray": "Gris",
"value (optional)": "valor (opcional)",
"Active": "Actiu",
"Push URL": "URL push",
"pushOptionalParams": "Paràmetres opcionals: {0}",
"Save": "Desa",
"Not available, please setup.": "No disponible, per favor configura-ho.",
"Light": "Clar",
"Auto": "Auto",
"Theme - Heartbeat Bar": "Tema - Heartbet Bar",
"styleElapsedTime": "Temps transcorregut a la barra",
"styleElapsedTimeShowNoLine": "Mostrar (Fora Línia)",
"styleElapsedTimeShowWithLine": "Mostrar (Amb línia)",
"Normal": "Normal",
"Bottom": "Inferior",
"None": "Cap",
"Timezone": "Zona Horària",
"Search Engine Visibility": "Visibilitat motor de cerca",
"Change Password": "Canviar contrasenya",
"New Password": "Nova Contrasenya",
"Repeat New Password": "Repeteix Nova Contrasenya",
"Update Password": "Actualitzar Contrasenya",
"Disable Auth": "Deshabilita autenticació",
"Enable Auth": "Habilita Autenticació",
"disableauth.message1": "Estau segur que voleu {disableAuth}?",
"disableauth.message2": "Està dissenyat per a escenaris {intendThirdPartyAuth} davant Uptime Kuma, com ara Cloudflare Access, Authelia o altres mecanismes d'autenticació.",
"where you intend to implement third-party authentication": "on es vol implementar l'autenticació de tercers",
"Logout": "Tancar sessió",
"Leave": "Marxar",
"I understand, please disable": "Ho entenc, per favor deshabilita-ho",
"Confirm": "Confirma",
"Yes": "Si",
"No": "No",
"Username": "Nom d'usuari",
"Password": "Contrasenya",
"add one": "afegir un",
"Notification Type": "Tipus de notificació",
"Test": "Test",
"Certificate Info": "Informació del certificat",
"Resolver Server": "Servidor DNS",
"Resource Record Type": "Tipus de registre",
"Create your admin account": "Crear compte d'administració",
"Repeat Password": "Repeteix Contrasenya",
"Export Backup": "Exportar Còpia",
"Import Backup": "Importar Còpia",
"Export": "Exporta",
"Import": "Importa",
"respTime": "Temps Resp. (ms)",
"Default enabled": "Habilitat per defecte",
"Apply on all existing monitors": "Aplicar a tots els monitors existents",
"Create": "Crear",
"Clear Data": "Esborra dades",
"Events": "Events",
"Heartbeats": "Heartbeat",
"Auto Get": "Obtenir automàticament",
"Schedule maintenance": "Programar manteniment",
"Affected Monitors": "Monitors Afectats",
"Pick Affected Monitors...": "Seleccionar Monitors Afectats…",
"Start of maintenance": "Inici del manteniment",
"All Status Pages": "Totes les pàgines d'estat",
"Select status pages...": "Selecciona pàgines d'estat…",
"alertNoFile": "Per favor, selecciona fitxer a importar.",
"alertWrongFileType": "Selecciona un fitxer JSON.",
"Clear all statistics": "Esborra totes les Estadístiques",
"Skip existing": "Ometre existent",
"Overwrite": "Sobreescriu",
"Options": "Opcions",
"Keep both": "Manté ambdos",
"Verify Token": "Verificar token",
"Setup 2FA": "Configurar 2FA",
"Enable 2FA": "Habilitar 2FA",
"Disable 2FA": "Deshabilitar 2FA",
"2FA Settings": "Ajustaments 2FA",
"filterActive": "Actiu",
"filterActivePaused": "Pausat",
"Inactive": "Inactiu",
"Token": "Token",
"Show URI": "Mostrar URI",
"Tags": "Etiquetes",
"Red": "Vermell",
"Orange": "Taronja",
"Green": "Verd",
"Blue": "Blau",
"Indigo": "Morat",
"Purple": "Porpra",
"Pink": "Rosa",
"Avg. Ping": "Ping promig",
"Entry Page": "Pàgina d'entrada",
"statusPageNothing": "Res per aquí, per favor afegeix un grup o un monitor.",
"statusPageRefreshIn": "Refrescat en: {0]",
"No Services": "Sense Servei",
"All Systems Operational": "Tots els sistemes operatius",
"Edit Status Page": "Editar pàgina Estat",
"Go to Dashboard": "Anar al Panell",
"Status Page": "Pàgina d'Estat",
"Email": "Correu",
"Last Result": "Darrer Resultat",
"Add New Tag": "Afegir nova etiqueta",
"Tag with this value already exist.": "Ja existeix una etiqueta amb aquest valor."
}

View File

@ -823,7 +823,6 @@
"Enable Kafka Producer Auto Topic Creation": "Povolit Kafka zprostředkovateli automatické vytváření vláken",
"Kafka Producer Message": "Zpráva Kafka zprostředkovatele",
"tailscalePingWarning": "Abyste mohli používat Tailscale Ping monitor, je nutné Uptime Kuma nainstalovat mimo Docker, a dále na váš server nainstalovat Tailscale klienta.",
"jsonQueryDescription": "Proveďte JSON dotaz vůči odpovědi a zkontrolujte očekávaný výstup (za účelem porovnání bude návratová hodnota převedena na řetězec). Dokumentaci k dotazovacímu jazyku naleznete na {0}, a využít můžete též {1}.",
"Select": "Vybrat",
"selectedMonitorCount": "Vybráno: {0}",
"Check/Uncheck": "Vybrat/Zrušit výběr",
@ -833,16 +832,16 @@
"nostrRelays": "Relé Nostr",
"FlashDuty Severity": "Závažnost",
"PushDeer Server": "Server PushDeer",
"wayToGetFlashDutyKey": "Můžete přejít na stránku Kanál -> (Vyberte kanál) -> Integrace -> Přidat novou integraci, přidat \"Vlastní událost\" a získat adresu pro odeslání, zkopírovat klíč integrace do adresy. Další informace naleznete na adrese",
"wayToGetFlashDutyKey": "Můžete přejít na stránku \"Kanál -> (Vyberte kanál) -> Integrace -> Přidat novou integraci\", přidat \"Uptime Kuma\" a získat push adresu, zkopírovat integrační klíč v adrese. Další informace naleznete na adrese",
"Request Timeout": "Časový limit požadavku",
"timeoutAfter": "Vypršení časového limitu po {0} sekundách",
"styleElapsedTime": "Čas uplynulý pod heartbeat ukazatelem",
"styleElapsedTimeShowWithLine": "Zobrazit (s linkou)",
"gamedigGuessPortDescription": "Port používaný protokolem Valve Server Query Protocol se může lišit od portu klienta. Pokud se monitor nemůže připojit k serveru, zkuste to.",
"styleElapsedTimeShowNoLine": "Zobrazit (bez linky)",
"gamedigGuessPort": "Gamedig: Guess Port",
"gamedigGuessPort": "Gamedig: Port",
"Saved.": "Uloženo.",
"setupDatabaseChooseDatabase": "Kterou databázi chcete použít?",
"setupDatabaseChooseDatabase": "Kterou databázi byste chtěli používat?",
"setupDatabaseEmbeddedMariaDB": "Nemusíte nic nastavovat. Tento Docker obraz pro vás automaticky vložil a nakonfiguroval databázi MariaDB. Uptime Kuma se k této databázi připojí prostřednictvím unixového socketu.",
"setupDatabaseMariaDB": "Připojení k externí databázi MariaDB. Je třeba nastavit informace o připojení k databázi.",
"setupDatabaseSQLite": "Jednoduchý databázový soubor, doporučený pro malé instalace. Před verzí 2.0.0 používal Uptime Kuma jako výchozí databázi SQLite.",
@ -895,9 +894,9 @@
"emailTemplateLimitedToUpDownNotification": "dostupné pouze pro heatbeaty BĚŽÍ/NEBĚŽÍ, jinak null",
"templateMonitorJSON": "objekt popisující dohled",
"templateLimitedToUpDownNotifications": "dostupné pouze pro oznámení BĚŽÍ/NEBĚŽÍ",
"successKeyword": "Nalezení klíčového slova",
"Search monitored sites": "Vyhledávání dohledů",
"settingUpDatabaseMSG": "Vytvářím strukturu databáze. Může to chvíli trvat, buďte trpěliví.",
"successKeyword": "Úspěch Klíčové slovo",
"Search monitored sites": "Hledat v monitorovaných umístěních",
"settingUpDatabaseMSG": "Nastavuje se databáze. Prosím buďte trpělivý, může to chvíli trvat.",
"successKeywordExplanation": "Klíčové slovo MQTT, které bude považováno za úspěch",
"Browser Screenshot": "Snímek obrazovky prohlížeče",
"setup a new monitor group": "nastavení nové skupiny dohledů",
@ -944,7 +943,7 @@
"remoteBrowserToggle": "Ve výchozím nastavení běží Chromium uvnitř kontejneru Uptime Kuma. Přepnutím tohoto přepínače můžete použít vzdálený prohlížeč.",
"wayToGetWhapiUrlAndToken": "URL rozhraní API a token získáte tak, že přejdete do požadovaného kanálu z {0}",
"wayToWriteWhapiRecipient": "Telefonní číslo s mezinárodní předvolbou, ale bez znaménka plus na začátku ({0}), ID kontaktu ({1}) nebo ID skupiny ({2}).",
"remoteBrowsersDescription": "Vzdálené prohlížeče jsou alternativou k lokálně spuštěnému Chromu. Nastavte tuto možnost pomocí služby jako je browserless.io, nebo se připojte k vlastnímu vzdálenému prohlížeči",
"remoteBrowsersDescription": "Vzdálené prohlížeče jsou alternativou k místnímu spuštění Chromu. Nastavte se pomocí služby, jako je browserless.io, nebo se připojte k vlastnímu",
"statusPageSpecialSlugDesc": "Speciální slug {0}: tato stránka se zobrazí, pokud není definován žádný slug",
"Mentioning": "Zmínky",
"wayToGetSevenIOApiKey": "Navštivte ovládací panel v části app.seven.io > developer > api key > zelené tlačítko přidat",
@ -953,5 +952,42 @@
"apiKeySevenIO": "API klíč SevenIO",
"locally configured mail transfer agent": "místně nakonfigurovaný agent pro přenos pošty",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Zadejte název hostitele serveru, ke kterému se chcete připojit, nebo {localhost}, pokud hodláte použít {local_mta}",
"receiverInfoSevenIO": "Pokud se přijímající číslo nenachází v Německu, musíte před číslo přidat kód země (např. pro kód země 420 z ČR použijte 420603603603 místo 603603603)"
"receiverInfoSevenIO": "Pokud se přijímající číslo nenachází v Německu, musíte před číslo přidat kód země (např. pro kód země 420 z ČR použijte 420603603603 místo 603603603)",
"Command": "Příkaz",
"mongodbCommandDescription": "Spusťte příkaz MongoDB proti databázi. Informace o dostupných příkazech najdete v {dokumentaci}",
"ignoreTLSErrorGeneral": "Ignorování chyby TLS/SSL u připojení",
"smspartnerApiurl": "Svůj klíč API najdete v ovládacím panelu na adrese {0}",
"smspartnerPhoneNumber": "Telefonní číslo (čísla)",
"smspartnerPhoneNumberHelptext": "Číslo musí být v mezinárodním formátu {0}, {1}. Více čísel musí být odděleno znakem {2}",
"smspartnerSenderName": "Název odesílatele SMS",
"smspartnerSenderNameInfo": "Musí obsahovat 3..=11 běžných znaků",
"Bitrix24 Webhook URL": "Adresa URL webhooku služby Bitrix24",
"wayToGetBitrix24Webhook": "Webhook můžete vytvořit podle pokynů na adrese {0}",
"bitrix24SupportUserID": "Zadejte své uživatelské ID v Bitrix24. ID zjistíte z odkazu, který najdete v profilu uživatele.",
"Refresh Interval": "Interval obnovení",
"Refresh Interval Description": "Stavová stránka provede úplnou obnovu webu každých {0} sekund",
"Select message type": "Zvolte typ zprávy",
"Send to channel": "Poslat na kanál",
"Create new forum post": "Vytvořit nový příspěvek na fóru",
"postToExistingThread": "Příspěvek do existujícího vlákna / příspěvek na fóru",
"forumPostName": "Název příspěvku ve fóru",
"threadForumPostID": "Vlákno / ID příspěvku ve fóru",
"e.g. {discordThreadID}": "např. {discordThreadID}",
"whatHappensAtForumPost": "Vytvořte nový příspěvek ve fóru. Tímto způsobem NENÍ možné odesílat zprávy v existujících příspěvcích. Pro vložení příspěvku do existujícího příspěvku použijte \"{option}\"",
"wayToGetDiscordThreadId": "Získání ID vlákna / příspěvku ve fóru je podobné získání ID kanálu. Přečtěte si více o tom, jak získat id {0}",
"Don't mention people": "Nezmiňujte se o osobách",
"Mention group": "Zmínka o {skupině}",
"Host URL": "URL hosta",
"threemaRecipientType": "Typ příjemce",
"threemaRecipient": "Příjemce",
"threemaSenderIdentityFormat": "8 znaků, obvykle začíná na *",
"threemaRecipientTypeEmail": "Emailová adresa",
"threemaSenderIdentity": "ID brány",
"threemaApiAuthenticationSecret": "Tajný klíč ID brány",
"apiKeysDisabledMsg": "Klíče API jsou zakázány, protože je zakázáno ověřování.",
"threemaBasicModeInfo": "Poznámka: Tato integrace využívá bránu Threema v základním režimu (šifrování pomocí serveru). Další podrobnosti naleznete {0}.",
"threemaRecipientTypeIdentityFormat": "8 znaků",
"threemaRecipientTypeIdentity": "Threema-ID",
"threemaRecipientTypePhone": "Telefonní číslo",
"wayToGetThreemaGateway": "Můžete se zaregistrovat do služby brány Threema {0}."
}

View File

@ -812,7 +812,6 @@
"Json Query": "Json-Abfrage",
"filterActive": "Aktiv",
"filterActivePaused": "Pausiert",
"jsonQueryDescription": "Führe eine JSON-Abfrage gegen die Antwort durch und prüfe den erwarteten Wert (der Rückgabewert wird zum Vergleich in eine Zeichenkette umgewandelt). Auf {0} findest du die Dokumentation zur Abfragesprache. {1} kannst du Abfragen üben.",
"Badge Duration (in hours)": "Abzeichen Dauer (in Stunden)",
"Badge Preview": "Abzeichen Vorschau",
"tailscalePingWarning": "Um den Tailscale Ping Monitor nutzen zu können, musst du Uptime Kuma ohne Docker installieren und den Tailscale Client auf dem Server installieren.",
@ -970,5 +969,23 @@
"ignoreTLSErrorGeneral": "TLS/SSL-Fehler für Verbindung ignorieren",
"threadForumPostID": "Themen-/Forumbeitrags-ID",
"e.g. {discordThreadID}": "z.B. {discordThreadID}",
"wayToGetDiscordThreadId": "Das Abrufen einer Thread-/Forumspost-ID ist ähnlich wie das Abrufen einer Channel-ID. Lese mehr darüber, wie man IDs abruft {0}"
"wayToGetDiscordThreadId": "Das Abrufen einer Thread-/Forumspost-ID ist ähnlich wie das Abrufen einer Channel-ID. Lese mehr darüber, wie man IDs abruft {0}",
"smspartnerApiurl": "Den API-Schlüssel findest du im Dashboard unter {0}",
"smspartnerPhoneNumber": "Telefonnummer(n)",
"smspartnerSenderName": "SMS Absender Name",
"smspartnerSenderNameInfo": "Muss zwischen 3..=11 regulären Zeichen sein",
"smspartnerPhoneNumberHelptext": "Die Nummer muss das internationale Format {0}, {1} haben. Mehrere Nummern müssen durch {2} getrennt werden",
"threemaRecipient": "Empfänger",
"threemaRecipientType": "Empfänger Typ",
"threemaRecipientTypeIdentity": "Threema-ID",
"threemaRecipientTypePhone": "Telefonnummer",
"threemaRecipientTypePhoneFormat": "E.164, ohne führendes +",
"threemaRecipientTypeEmail": "E-Mail Adresse",
"threemaSenderIdentity": "Gateway-ID",
"threemaApiAuthenticationSecret": "Gateway-ID Schlüssel",
"wayToGetThreemaGateway": "Du kannst dich für Threema Gateway {0} registrieren.",
"threemaRecipientTypeIdentityFormat": "8 Zeichen",
"threemaSenderIdentityFormat": "8 Zeichen, beginnt normalerweise mit *",
"threemaBasicModeInfo": "Hinweis: Diese Integration verwendet Threema Gateway im Basismodus (serverbasierte Verschlüsselung). Weitere Details siehe {0}.",
"apiKeysDisabledMsg": "API-Schlüssel sind deaktiviert, da die Authentifizierung deaktiviert ist."
}

View File

@ -817,7 +817,6 @@
"filterActivePaused": "Pausiert",
"Expected Value": "Erwarteter Wert",
"Json Query": "Json-Abfrage",
"jsonQueryDescription": "Führe eine JSON-Abfrage gegen die Antwort durch und prüfe den erwarteten Wert (der Rückgabewert wird zum Vergleich in eine Zeichenkette umgewandelt). Auf {0} findest du die Dokumentation zur Abfragesprache. {1} kannst du Abfragen üben.",
"tailscalePingWarning": "Um den Tailscale Ping Monitor nutzen zu können, musst du Uptime Kuma ohne Docker installieren und den Tailscale Client auf dem Server installieren.",
"Server URL should not contain the nfty topic": "Die Server-URL sollte das nfty-Thema nicht enthalten",
"pushDeerServerDescription": "Leer lassen um den offiziellen Server zu verwenden",
@ -973,5 +972,23 @@
"forumPostName": "Name des Forumsbeitrags",
"threadForumPostID": "Themen-/Forumbeitrags-ID",
"e.g. {discordThreadID}": "z.B. {discordThreadID}",
"wayToGetDiscordThreadId": "Das Abrufen einer Thread-/Forumspost-ID ist ähnlich wie das Abrufen einer Channel-ID. Lese mehr darüber, wie man IDs abruft {0}"
"wayToGetDiscordThreadId": "Das Abrufen einer Thread-/Forumspost-ID ist ähnlich wie das Abrufen einer Channel-ID. Lese mehr darüber, wie man IDs abruft {0}",
"smspartnerPhoneNumber": "Telefonnummer(n)",
"smspartnerSenderName": "SMS Absender Name",
"smspartnerSenderNameInfo": "Muss zwischen 3..=11 regulären Zeichen sein",
"smspartnerApiurl": "Den API-Schlüssel findest du im Dashboard unter {0}",
"smspartnerPhoneNumberHelptext": "Die Nummer muss das internationale Format {0}, {1} haben. Mehrere Nummern müssen durch {2} getrennt werden",
"threemaRecipient": "Empfänger",
"threemaRecipientType": "Empfänger Typ",
"threemaRecipientTypeIdentity": "Threema-ID",
"threemaRecipientTypePhone": "Telefonnummer",
"threemaRecipientTypePhoneFormat": "E.164, ohne führendes +",
"threemaRecipientTypeEmail": "E-Mail Adresse",
"threemaSenderIdentity": "Gateway-ID",
"threemaApiAuthenticationSecret": "Gateway-ID Schlüssel",
"wayToGetThreemaGateway": "Du kannst dich für Threema Gateway {0} registrieren.",
"threemaRecipientTypeIdentityFormat": "8 Zeichen",
"threemaSenderIdentityFormat": "8 Zeichen, beginnt normalerweise mit *",
"threemaBasicModeInfo": "Hinweis: Diese Integration verwendet Threema Gateway im Basismodus (serverbasierte Verschlüsselung). Weitere Details siehe {0}.",
"apiKeysDisabledMsg": "API-Schlüssel sind deaktiviert, da die Authentifizierung deaktiviert ist."
}

View File

@ -31,13 +31,13 @@
"confirmDisableTwoFAMsg": "Είστε βέβαιοι ότι θέλετε να απενεργοποιήσετε το 2FA;",
"Settings": "Ρυθμίσεις",
"Dashboard": "Πίνακας",
"New Update": "Νέα αναβάθμιση",
"New Update": "Νέα ενημέρωση",
"Language": "Γλώσσα",
"Appearance": "Εμφάνιση",
"Theme": "Θέμα",
"General": "Γενικά",
"Primary Base URL": "Κύρια βασική διεύθυνση URL",
"Version": "Εκδοχή",
"Version": "Έκδοση",
"Check Update On GitHub": "Ελέγξτε για Ενημέρωση στο GitHub",
"List": "Λίστα",
"Add": "Προσθήκη",
@ -56,7 +56,7 @@
"Resume": "Συνέχιση",
"Edit": "Επεξεργασία",
"Delete": "Διαγράφη",
"Current": ρέχον",
"Current": ωρινό",
"Uptime": "Χρόνος λειτουργίας",
"Cert Exp.": "Λήξη Πιστοπ.",
"day": "ημέρα | ημέρες",
@ -700,13 +700,13 @@
"Add New Tag": "Πρόσθεσε νέα ετικέτα",
"setupDatabaseMariaDB": "Συνδεθείτε με εξωτερική βάση δεδομένων MariaDB. Θα πρέπει να ορίσετε τα στοιχεία σύνδεσης της βάσης δεδομένων.",
"setupDatabaseChooseDatabase": "Ποια βάση δεδομένων θέλετε να χρησιμοποιήσετε;",
"setupDatabaseEmbeddedMariaDB": "Δεν χρειάζεται να ρυθμίσετε τίποτε. Η εικόνα Docker έχει ενσωματώσει και ρυθμίσει μια βάση δεδομένων MariaDB για εσάς αυτόματα. Το Uptime Kuma θα συνδεθεί με την βάση δεδομένων μέσω unix socket.",
"setupDatabaseEmbeddedMariaDB": "Δεν χρειάζεται να ορίσετε τίποτε. Το Docker Image έχει ενθέσειι και διαμορφώσει μια βάση δεδομένων MariaDB για εσάς αυτόματα. Το Uptime Kuma θα συνδεθεί με αυτήν την βάση δεδομένων μέσω unix socket.",
"setupDatabaseSQLite": "Ένα απλό αρχείο βάσης δεδομένων, προτεινόμενο για εγκαταστάσεις μικρής κλίμακας. Πρίν από την έκδοση 2.0.0, το Uptime Kuma χρησιμοποιούσε το SQLite ως την προεπιλεγμένη βάση δεδομένων.",
"Cannot connect to the socket server": "Δεν είναι δυνατή η σύνδεση με τον διακομιστή socket",
"Reconnecting...": "Επανασύνδεση",
"Reconnecting...": "Επανασύνδεση...",
"Home": "Αρχική",
"settingUpDatabaseMSG": "Ρύθμιση της βάσης δεδομένων. Μπορεί να διαρκέσει λίγο, παρακαλώ να είστε υπομονετικοί.",
"dbName": "Όνομα Βάσης Δεδομένων",
"settingUpDatabaseMSG": "Ρύθμιση της βάσης δεδομένων. Μπορεί να διαρκέσει λίγη ώρα, παρακαλώ κάνετε υπομονετικοί.",
"dbName": "Όνομα βάσης δεδομένων",
"Invert Keyword": "Αντιστροφή Λέξης-Κλειδιού",
"Expected Value": "Αναμενόμενη Τιμή",
"Json Query": "Ερώτημα Json"

View File

@ -49,17 +49,20 @@
"Uptime": "Uptime",
"Cert Exp.": "Cert Exp.",
"Monitor": "Monitor | Monitors",
"now": "now",
"time ago": "{0} ago",
"day": "day | days",
"-day": "-day",
"hour": "hour",
"-hour": "-hour",
"-year": "-year",
"Response": "Response",
"Ping": "Ping",
"Monitor Type": "Monitor Type",
"Keyword": "Keyword",
"Invert Keyword": "Invert Keyword",
"Expected Value": "Expected Value",
"Json Query": "Json Query",
"Json Query Expression": "Json Query Expression",
"Friendly Name": "Friendly Name",
"URL": "URL",
"Hostname": "Hostname",
@ -80,7 +83,7 @@
"resendDisabled": "Resend disabled",
"retriesDescription": "Maximum retries before the service is marked as down and a notification is sent",
"ignoreTLSError": "Ignore TLS/SSL errors for HTTPS websites",
"ignoreTLSErrorGeneral": "Ignore TLS/SSL error for connection",
"ignoreTLSErrorGeneral": "Ignore TLS/SSL error for connection",
"upsideDownModeDescription": "Flip the status upside down. If the service is reachable, it is DOWN.",
"maxRedirectDescription": "Maximum number of redirects to follow. Set to 0 to disable redirects.",
"Upside Down Mode": "Upside Down Mode",
@ -441,6 +444,7 @@
"backupOutdatedWarning": "Deprecated: Since a lot of features were added and this backup feature is a bit unmaintained, it cannot generate or restore a complete backup.",
"backupRecommend": "Please backup the volume or the data folder (./data/) directly instead.",
"Optional": "Optional",
"and": "and",
"or": "or",
"sameAsServerTimezone": "Same as Server Timezone",
"startDateTime": "Start Date/Time",
@ -588,7 +592,7 @@
"notificationDescription": "Notifications must be assigned to a monitor to function.",
"keywordDescription": "Search keyword in plain HTML or JSON response. The search is case-sensitive.",
"invertKeywordDescription": "Look for the keyword to be absent rather than present.",
"jsonQueryDescription": "Do a json Query against the response and check for expected value (Return value will get converted into string for comparison). Check out {0} for the documentation about the query language. A playground can be found {1}.",
"jsonQueryDescription": "Parse and extract specific data from the server's JSON response using JSON query or use \"$\" for the raw response, if not expecting JSON. The result is then compared to the expected value, as strings. See {0} for documentation and use {1} to experiment with queries.",
"backupDescription": "You can backup all monitors and notifications into a JSON file.",
"backupDescription2": "Note: history and event data is not included.",
"backupDescription3": "Sensitive data such as notification tokens are included in the export file; please store export securely.",
@ -876,6 +880,8 @@
"nostrRecipientsHelp": "npub format, one per line",
"showCertificateExpiry": "Show Certificate Expiry",
"noOrBadCertificate": "No/Bad Certificate",
"cacheBusterParam": "Add the {0} parameter",
"cacheBusterParamDescription": "Randomly generated parameter to skip caches.",
"gamedigGuessPort": "Gamedig: Guess Port",
"gamedigGuessPortDescription": "The port used by Valve Server Query Protocol may be different from the client port. Try this if the monitor cannot connect to your server.",
"Bitrix24 Webhook URL": "Bitrix24 Webhook URL",
@ -943,6 +949,13 @@
"cellsyntSplitLongMessages": "Split long messages into up to 6 parts. 153 x 6 = 918 characters.",
"max 15 digits": "max 15 digits",
"max 11 alphanumeric characters": "max 11 alphanumeric characters",
"Community String": "Community String",
"snmpCommunityStringHelptext": "This string functions as a password to authenticate and control access to SNMP-enabled devices. Match it with your SNMP device's configuration.",
"OID (Object Identifier)": "OID (Object Identifier)",
"snmpOIDHelptext": "Enter the OID for the sensor or status you want to monitor. Use network management tools like MIB browsers or SNMP software if you're unsure about the OID.",
"Condition": "Condition",
"SNMP Version": "SNMP Version",
"Please enter a valid OID.": "Please enter a valid OID.",
"wayToGetThreemaGateway": "You can register for Threema Gateway {0}.",
"threemaRecipient": "Recipient",
"threemaRecipientType": "Recipient Type",
@ -955,5 +968,51 @@
"threemaSenderIdentityFormat": "8 characters, usually starts with *",
"threemaApiAuthenticationSecret": "Gateway-ID Secret",
"threemaBasicModeInfo": "Note: This integration uses Threema Gateway in basic mode (server-based encryption). Further details can be found {0}.",
"apiKeysDisabledMsg": "API keys are disabled because authentication is disabled."
"apiKeysDisabledMsg": "API keys are disabled because authentication is disabled.",
"Host Onesender": "Host Onesender",
"Token Onesender": "Token Onesender",
"Recipient Type": "Recipient Type",
"Private Number": "Private Number",
"privateOnesenderDesc": "Make sure the number phone is valid. To send message into private number phone, ex: 628123456789",
"groupOnesenderDesc": "Make sure the GroupID is valid. To send message into Group, ex: 628123456789-342345",
"Group ID": "Group ID",
"wayToGetOnesenderUrlandToken":"You can get the URL and Token by going to the Onesender website. More info {0}",
"Add Remote Browser": "Add Remote Browser",
"New Group": "New Group",
"Group Name": "Group Name",
"OAuth2: Client Credentials": "OAuth2: Client Credentials",
"Authentication Method": "Authentication Method",
"Authorization Header": "Authorization Header",
"Form Data Body": "Form Data Body",
"OAuth Token URL": "OAuth Token URL",
"Client ID": "Client ID",
"Client Secret": "Client Secret",
"OAuth Scope": "OAuth Scope",
"Optional: Space separated list of scopes": "Optional: Space separated list of scopes",
"Go back to home page.": "Go back to home page.",
"No tags found.": "No tags found.",
"Lost connection to the socket server.": "Lost connection to the socket server.",
"Cannot connect to the socket server.": "Cannot connect to the socket server.",
"SIGNL4": "SIGNL4",
"SIGNL4 Webhook URL": "SIGNL4 Webhook URL",
"signl4Docs": "You can find more information about how to configure SIGNL4 and how to obtain the SIGNL4 webhook URL in the {0}.",
"Conditions": "Conditions",
"conditionAdd": "Add Condition",
"conditionDelete": "Delete Condition",
"conditionAddGroup": "Add Group",
"conditionDeleteGroup": "Delete Group",
"conditionValuePlaceholder": "Value",
"equals": "equals",
"not equals": "not equals",
"contains": "contains",
"not contains": "not contains",
"starts with": "starts with",
"not starts with": "not starts with",
"ends with": "ends with",
"not ends with": "not ends with",
"less than": "less than",
"greater than": "greater than",
"less than or equal to": "less than or equal to",
"greater than or equal to": "greater than or equal to",
"record": "record"
}

View File

@ -558,7 +558,7 @@
"affectedMonitorsDescription": "Selecciona los monitores que se ven afectados por el mantenimiento actual",
"affectedStatusPages": "Muestra este mensaje de mantenimiento en las páginas de estado seleccionadas",
"atLeastOneMonitor": "Selecciona al menos un monitor afectado",
"endpoint": "endpoint",
"endpoint": "punto final",
"promosmsPassword": "Contraseña API",
"pushoversounds pushover": "Pushover (predeterminado)",
"pushoversounds bike": "Bicicleta",
@ -655,7 +655,7 @@
"gorush": "Gorush",
"squadcast": "Squadcast",
"Maintenance Time Window of a Day": "Ventana de tiempo de mantenimiento de un día",
"Effective Date Range": "Rango de fecha efectivo (opcional)",
"Effective Date Range": "Rango de Fechas Efectivas (Opcional)",
"Free Mobile User Identifier": "Identificador de Usuario de Free Mobile",
"Gateway Type": "Tipo de puerta de enlace",
"SMSManager": "SMSManager",
@ -771,7 +771,6 @@
"Json Query": "Consulta Json",
"invertKeywordDescription": "Comprobar si la palabra clave está ausente en vez de presente.",
"enableNSCD": "Habilitar NSCD (Demonio de Caché de Servicio de Nombres) para almacenar en caché todas las solicitudes DNS",
"jsonQueryDescription": "Realiza una consulta JSON contra la respuesta y verifica el valor esperado (el valor de retorno se convertirá a una cadena para la comparación). Consulta {0} para obtener documentación sobre el lenguaje de consulta. Puede encontrar un espacio de prueba {1}.",
"Request Timeout": "Tiempo de espera máximo de petición",
"timeoutAfter": "Expirar después de {0} segundos",
"chromeExecutableDescription": "Para usuarios de Docker, si Chromium no está instalado, puede que tarde unos minutos en ser instalado y mostrar el resultado de la prueba. Usa 1GB de espacio.",
@ -831,7 +830,7 @@
"Badge value (For Testing only.)": "Valor de la insignia (Solo para pruebas.)",
"Enable Kafka Producer Auto Topic Creation": "Habilitar la Creación Automática de Temas del Productor de Kafka",
"noGroupMonitorMsg": "No disponible. Cree primero un monitor de grupo.",
"wayToGetFlashDutyKey": "Puede ir a Canal -> (Seleccionar un canal) -> Integraciones -> Agregar una nueva página de integración, agregar un 'Evento personalizado' para obtener una dirección push, copiar la clave de integración en la dirección. Para mayor información por favor visite",
"wayToGetFlashDutyKey": "Puedes ir a Canal -> (Seleccionar un Canal) -> Integraciones -> Agregar una nueva integración, agregar un 'Uptime Kuma' para obtener una dirección de envío, copiar la Clave de Integración en la dirección. Para más información, por favor visita",
"gamedigGuessPort": "Gamedig: Adivinar el puerto",
"gamedigGuessPortDescription": "El puerto utilizado por Valve Server Query Protocol puede ser diferente del puerto del cliente. Pruebe esto si el monitor no puede conectarse a su servidor.",
"twilioApiKey": "Clave de la API (opcional)",
@ -839,7 +838,7 @@
"styleElapsedTimeShowNoLine": "Mostrar (sin línea)",
"styleElapsedTimeShowWithLine": "Mostrar (Con línea)",
"webhookCustomBodyDesc": "Define un cuerpo HTTP personalizado para la petición. Las variables que puedes usar como plantillas son {msg}, {heartbeat}, y {monitor}.",
"webhookBodyPresetOption": "Preajuste- {0}",
"webhookBodyPresetOption": "Preajuste - {0}",
"tailscalePingWarning": "Para utilizar el monitor Tailscale Ping, debe instalar Uptime Kuma sin Docker y también instalar el cliente Tailscale en su servidor.",
"Bark API Version": "Versión de la API Bark",
"monitorToastMessagesDescription": "Las notificaciones Toast para monitores desaparecen después de un tiempo dado en segundos. Establecer a -1 desactiva el tiempo de espera. Si se establece en 0, se desactivan las notificaciones.",
@ -847,7 +846,7 @@
"monitorToastMessagesLabel": "Monitorizar las notificaciones Toast",
"toastSuccessTimeout": "Tiempo de espera para notificaciones de éxito",
"toastErrorTimeout": "Tiempo de espera para notificaciones de error",
"setupDatabaseChooseDatabase": "¿Qué base de datos desea utilizar?",
"setupDatabaseChooseDatabase": "¿Qué base de datos te gustaría usar?",
"setupDatabaseEmbeddedMariaDB": "No necesitas configurar nada. Esta imagen de Docker tiene incorporado y configurado MariaDB para ti automáticamente. Uptime Kuma se conectará a esta base de datos a través de un socket Unix.",
"setupDatabaseMariaDB": "Conectarse a una base de datos MariaDB externa. Debe configurar la información de conexión a la base de datos.",
"setupDatabaseSQLite": "Un archivo de base de datos simple, recomendado para despliegues a pequeña escala. Antes de la versión 2.0.0, Uptime Kuma utilizaba SQLite como base de datos predeterminada.",
@ -857,20 +856,20 @@
"2faEnabled": "2FA habilitado.",
"2faDisabled": "2FA deshabilitado.",
"liquidIntroduction": "La plantilla se logra a través del lenguaje de plantillas Liquid. Consulte {0} para obtener instrucciones de uso. Estas son las variables disponibles:",
"templateLimitedToUpDownCertNotifications": "sólo disponible para las notificaciones de LEVANTADO/CAÍDO/Caducidad de certificado",
"templateLimitedToUpDownCertNotifications": "disponible solo para notificaciones de arriba/abajo/caducidad del certificado",
"emailTemplateMsg": "mensaje de la notificación",
"emailTemplateLimitedToUpDownNotification": "sólo disponible para pulsos LEVANTADO/CAÍDO, en caso contrario null",
"emailTemplateLimitedToUpDownNotification": "disponible solo para latidos de arriba/abajo, de lo contrario, nulo",
"setup a new monitor group": "configurar un nuevo grupo de monitores",
"authUserInactiveOrDeleted": "El usuario está inactivo o eliminado.",
"2faAlreadyEnabled": "2FA ya está activado.",
"remoteBrowsersDescription": "Los navegadores remotos son una alternativa a la ejecución local de Chromium. Configúralos con un servicio como browserless.io o conéctate a uno propio",
"remoteBrowsersDescription": "Los navegadores remotos son una alternativa a ejecutar Chromium localmente. Configúralos con un servicio como browserless.io o conéctalos a tu propio servidor",
"successKeyword": "Palabra clave de éxito",
"successKeywordExplanation": "MQTT Palabra clave que se considerará como éxito",
"Remove the expiry notification": "Eliminar la notificación de vencimiento",
"Browser Screenshot": "Captura de pantalla del navegador",
"emailCustomisableContent": "Contenidos personalizables",
"smtpLiquidIntroduction": "Los dos campos siguientes son planificables mediante el lenguaje de plantillas Liquid. Consulte las instrucciones de uso en {0}. Estas son las variables disponibles:",
"leave blank for default subject": "dejar en blanco para el asunto por defecto",
"emailCustomisableContent": "Contenido personalizable",
"smtpLiquidIntroduction": "Los siguientes dos campos son personalizables a través del lenguaje de plantillas Liquid. Por favor, consulta {0} para las instrucciones de uso. Estas son las variables disponibles:",
"leave blank for default subject": "dejar en blanco para asunto predeterminado",
"emailCustomBody": "Cuerpo personalizado",
"successAuthChangePassword": "La contraseña se ha actualizado correctamente.",
"successDeleted": "Eliminado con éxito.",
@ -895,11 +894,11 @@
"programmingLanguages": "Lenguajes de Programación",
"templateMsg": "mensaje de la notificación",
"templateMonitorJSON": "objeto que describe el monitor",
"templateLimitedToUpDownNotifications": "sólo disponible para notificaciones LEVANTADO/CAÍDO",
"templateLimitedToUpDownNotifications": "disponible solo para notificaciones de arriba/abajo",
"Add a new expiry notification day": "Añadir una nueva notificación de vencimiento",
"leave blank for default body": "dejar en blanco para el cuerpo por defecto",
"emailTemplateServiceName": "Nombre del servicio",
"emailTemplateHostnameOrURL": "Nombre del host o URL",
"emailTemplateServiceName": "Nombre del Servicio",
"emailTemplateHostnameOrURL": "Nombre del Host o URL",
"emailTemplateStatus": "Estado",
"emailTemplateMonitorJSON": "objeto que describe el monitor",
"openModalTo": "abrir modal a {0}",
@ -913,10 +912,10 @@
"settingUpDatabaseMSG": "Configurando la base de datos. Puede tomar un tiempo, sea paciente, por favor.",
"Search monitored sites": "Buscar sitios monitoreados",
"statusPageSpecialSlugDesc": "Identificador único especial {0}: esta página será mostrada cuando no se proporcione ningún identificador único",
"emailTemplateHeartbeatJSON": "Objeto que describe la señal de vida",
"ntfyPriorityHelptextAllEvents": "Todos los eventos son enviados con la máxima prioridad",
"emailTemplateHeartbeatJSON": "objeto que describe el latido",
"ntfyPriorityHelptextAllEvents": "Todos los eventos se envían con la máxima prioridad",
"ntfyPriorityHelptextAllExceptDown": "Todos los eventos son enviados con esta prioridad, excepto los eventos {0}, que tienen una prioridad de {1}",
"templateHeartbeatJSON": "Objeto que describe el latido",
"templateHeartbeatJSON": "objeto que describe el latido",
"What is a Remote Browser?": "¿Qué es un Navegador Remoto?",
"Your User ID": "Tu ID de usuario",
"Alphanumeric (recommended)": "Alfanumérico (recomendado)",
@ -924,5 +923,71 @@
"wayToGetWhapiUrlAndToken": "Puedes obtener la URL de la API y el token accediendo al canal que desee desde {0}",
"API URL": "API URL",
"Allow Long SMS": "Permitir SMS largo",
"cellsyntDestination": "Número de teléfono del destinatario en formato internacional precedido de 00, seguido del código de país, ej. 00447920110000 para el número del Reino Unido 07920 110 000 (máximo 17 dígitos en total). Máximo 25.000 destinatarios, separados por comas, por solicitud HTTP."
"cellsyntDestination": "Número de teléfono del destinatario en formato internacional precedido de 00, seguido del código de país, ej. 00447920110000 para el número del Reino Unido 07920 110 000 (máximo 17 dígitos en total). Máximo 25.000 destinatarios, separados por comas, por solicitud HTTP.",
"Refresh Interval Description": "La página de estado se refrescará cada {0} segundos",
"Refresh Interval": "Intervalo de refresco",
"ignoreTLSErrorGeneral": "Ignorar errores SSL/TLS durante la conexión",
"documentationOf": "Documentación de {0}",
"wayToGetHeiiOnCallDetails": "Cómo obtener el ID del Disparador y las Claves API se explica en la {documentación}",
"Command": "Comando",
"wayToGetThreemaGateway": "Puedes registrarte para Threema Gateway {0}.",
"threemaRecipient": "Destinatario",
"threemaRecipientType": "Tipo de Destinatario",
"threemaRecipientTypeIdentity": "ID de Threema",
"threemaRecipientTypeIdentityFormat": "8 caracteres",
"threemaRecipientTypePhone": "Número de Teléfono",
"threemaRecipientTypeEmail": "Dirección de Correo Electrónico",
"threemaSenderIdentity": "ID de Gateway",
"threemaSenderIdentityFormat": "8 caracteres, generalmente comienza con *",
"Host URL": "URL del anfitrión",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Ingresa el nombre del host del servidor al que deseas conectarte o {localhost} si deseas usar un {local_mta}",
"smspartnerPhoneNumberHelptext": "El número debe estar en el formato internacional {0}, {1}. Múltiples números deben estar separados por {2}",
"smspartnerSenderName": "Nombre del remitente de SMS",
"smspartnerApiurl": "Puedes encontrar tu clave API en tu panel de control en {0}",
"smspartnerPhoneNumber": "Número(s) de teléfono",
"max 11 alphanumeric characters": "máximo 11 caracteres alfanuméricos",
"gtxMessagingFromHint": "En teléfonos móviles, tus destinatarios ven el TPOA mostrado como el remitente del mensaje. Se permiten hasta 11 caracteres alfanuméricos, un código corto, el código largo local o números internacionales ({e164}, {e212} o {e214})",
"cellsyntOriginatortypeAlphanumeric": "Cadena alfanumérica (máximo 11 caracteres alfanuméricos). Los destinatarios no pueden responder al mensaje.",
"cellsyntOriginatortypeNumeric": "Valor numérico (máximo 15 dígitos) con el número de teléfono en formato internacional sin el prefijo 00 (por ejemplo, el número del Reino Unido 07920 110 000 debe establecerse como 447920110000). Los destinatarios pueden responder al mensaje.",
"Originator type": "Tipo de originador",
"Telephone number": "Número de teléfono",
"Mentioning": "Mencionando",
"Don't mention people": "No mencionar a las personas",
"Mention group": "Mencionar a {group}",
"Bitrix24 Webhook URL": "URL del Webhook de Bitrix24",
"wayToGetBitrix24Webhook": "Puedes crear un webhook siguiendo los pasos en {0}",
"gtxMessagingApiKeyHint": "Puedes encontrar tu clave API en: My Routing Accounts > Show Account Information > API Credentials > REST API (v2.x)",
"Originator": "Originador",
"bitrix24SupportUserID": "Ingresa tu ID de usuario en Bitrix24. Puedes encontrar el ID en el enlace al ir al perfil del usuario.",
"wayToWriteWhapiRecipient": "El número de teléfono con el prefijo internacional, pero sin el signo más al inicio ({0}), el ID de Contacto ({1}) o el ID de Grupo ({2}).",
"From Phone Number / Transmission Path Originating Address (TPOA)": "Número de Teléfono del Remitente / Dirección de Origen de la Ruta de Transmisión (TPOA)",
"To Phone Number": "Al Número de Teléfono",
"Select message type": "Seleccionar tipo de mensaje",
"Send to channel": "Enviar al canal",
"max 15 digits": "máximo 15 dígitos",
"mongodbCommandDescription": "Ejecuta un comando de MongoDB contra la base de datos. Para obtener información sobre los comandos disponibles, consulta la {documentación}",
"whapiRecipient": "Número de Teléfono / ID de Contacto / ID de Grupo",
"cellsyntSplitLongMessages": "Divide mensajes largos en hasta 6 partes. 153 x 6 = 918 caracteres.",
"receiverSevenIO": "Número receptor",
"apiKeySevenIO": "Clave API de SevenIO",
"wayToGetSevenIOApiKey": "Visita el panel de control en app.seven.io > developer > api key > el botón verde de agregar",
"senderSevenIO": "Número o nombre del remitente",
"gtxMessagingToHint": "Formato internacional, con el signo \"+\" al inicio ({e164}, {e212} o {e214})",
"locally configured mail transfer agent": "agente de transferencia de correo configurado localmente",
"wayToGetDiscordThreadId": "Obtener un ID de hilo / publicación en el foro es similar a obtener un ID de canal. Lee más sobre cómo obtener IDs {0}",
"smspartnerSenderNameInfo": "Debe tener entre 3..=11 caracteres normales",
"receiverInfoSevenIO": "Si el número receptor no está ubicado en Alemania, debes agregar el código de país delante del número (por ejemplo, para el código de país 1 de EE. UU. usa 117612121212 en lugar de 017612121212)",
"callMeBotGet": "Aquí puedes generar un endpoint para {0}, {1} y {2}. Ten en cuenta que podrías recibir limitaciones de tasa. Las limitaciones de tasa parecen ser: {3}",
"cellsyntOriginator": "Visible en el teléfono móvil del destinatario como originador del mensaje. Los valores permitidos y la función dependen del parámetro originatortype.",
"threemaRecipientTypePhoneFormat": "E.164, sin el signo + al inicio",
"threemaApiAuthenticationSecret": "Clave Secreta del Gateway-ID",
"threemaBasicModeInfo": "Nota: Esta integración utiliza Threema Gateway en modo básico (encriptación basada en servidor). Puedes encontrar más detalles en {0}.",
"apiKeysDisabledMsg": "Las claves API están desactivadas porque la autenticación está desactivada.",
"Channel access token (Long-lived)": "Token de acceso al canal (de larga duración)",
"Create new forum post": "Crear nueva publicación en el foro",
"postToExistingThread": "Publicar en hilo / publicación existente",
"forumPostName": "Nombre de la publicación en el foro",
"threadForumPostID": "ID del hilo / publicación en el foro",
"e.g. {discordThreadID}": "por ejemplo, {discordThreadID}",
"whatHappensAtForumPost": "Crear una nueva publicación en el foro. Esto NO publica mensajes en una publicación existente. Para publicar en una publicación existente usa \"{option}\""
}

View File

@ -76,7 +76,7 @@
"Accepted Status Codes": "وضعیت‌های (Status Code) های قابل قبول",
"Save": "ذخیره",
"Notifications": "اطلاع‌رسانی‌ها",
"Not available, please setup.": "هیچ موردی موجود نیست، اولین مورد را راه اندازی کنید.",
"Not available, please setup.": "هیچ موردی موجود نیست، اولین مورد را راهاندازی کنید.",
"Setup Notification": "راه اندازی اطلاع‌رسانی‌",
"Light": "روشن",
"Dark": "تاریک",
@ -386,7 +386,7 @@
"Switch to Dark Theme": "تغییر به حالت تیره",
"Show Tags": "نمایش تگ ها",
"Hide Tags": "مخفی سازی تگ ها",
"Description": "توضحیات",
"Description": "توضیحات",
"Custom CSS": "CSS اختصاصی",
"deleteStatusPageMsg": "آیا بابت حذف این استاتوس پیچ مطمئن هستید؟",
"Proxies": "پروکسی ها",
@ -759,11 +759,10 @@
"filterActive": "فعال",
"webhookCustomBodyDesc": "یک بدنه HTTP سفارشی برای ریکوئست تعریف کنید. متغیر های قابل استفاده: {msg}, {heartbeat}, {monitor}.",
"tailscalePingWarning": "برای استفاده از Tailscale Ping monitor، شما باید آپتایم کوما را بدون استفاده از داکر و همچنین Tailscale client را نیز بر روی سرور خود نصب داشته باشید.",
"jsonQueryDescription": "یک کوئری json در برابر پاسخ انجام دهید و مقدار مورد انتظار را (مقدار برگشتی برای مقایسه به رشته تبدیل می شود). برای مستندات درباره زبان کوئری، {0} مشاهده کنید. همچنین محیط تست را میتوانید در {1} پیدا کنید.",
"Enter the list of brokers": "لیست بروکر هارا وارد کنید",
"Enable Kafka Producer Auto Topic Creation": "فعال سازی ایجاپ موضوع اتوماتیک تهیه کننده",
"Secret AccessKey": "کلید محرمانه AccessKey",
"wayToGetFlashDutyKey": "می توانید به کانال -> (انتخاب یک کانال) -> یکپارچه سازی -> صفحه یکپارچه سازی جدید بروید، یک \"رویداد سفارشی\" را برای دریافت یک آدرس فشار اضافه کنید، کلید یکپارچه سازی را در آدرس کپی کنید. برای اطلاعات بیشتر لطفا مراجعه کنید به",
"wayToGetFlashDutyKey": "می توانید به کانال -> (انتخاب یک کانال) -> یکپارچه سازی -> یکپارچه سازی جدید بروید، یک \"Uptime Kuma\" را برای دریافت یک آدرس پوش اضافه کنید، کلید یکپارچه سازی را در آدرس کپی کنید. برای اطلاعات بیشتر لطفا مراجعه کنید به",
"showCertificateExpiry": "نمایش زمان به پایان رسیدن اعتبار سرتیفیکیت",
"gamedigGuessPortDescription": "پورت مورد استفاده توسط پروتکل Query Valve Server ممکن است با پورت مشتری متفاوت باشد. اگر مانیتور نمی تواند به سرور شما متصل شود، این را امتحان کنید.",
"invertKeywordDescription": "دنبال کلمات کلیدی ناموجود باشید تا آنهایی که موجود است.",
@ -812,8 +811,8 @@
"Expected Value": "مقدار مورد انتظار",
"Json Query": "کوئری جیسون",
"Saved.": "ذخیره شده.",
"setupDatabaseChooseDatabase": "از چه دیتابیسی میخواهید استفاده کنید؟",
"setupDatabaseEmbeddedMariaDB": "شما نیازی نیست چیزی را تنظیم کنید . این Image داکر MariaDB را به طور خودکار برای شما جاسازی و پیکربندی کرده است. آپتایم کوما از طریق سوکت یونیکس به این دیتابیس متصل می شود.",
"setupDatabaseChooseDatabase": "از چه دیتابیسی میخواهید استفاده کنید؟",
"setupDatabaseEmbeddedMariaDB": "شما نیازی نیست چیزی را تنظیم کنید . این Image داکر، MariaDB را به طور خودکار برای شما جاسازی و پیکربندی کرده است. آپتایم کوما از طریق سوکت یونیکس به این دیتابیس متصل می شود.",
"setupDatabaseSQLite": "یک فایل دیتابیس ساده که برای استقرار در مقیاس کوچک توصیه می شود. قبل از نسخه 2.0.0، Uptime Kuma از SQLite به عنوان دیتابیس پیش فرض استفاده می کرد.",
"enableNSCD": "فعال سازی NSCD (Name Service Cache Daemon) برای کش کردن تمام ریکوئست های DNS",
"setupDatabaseMariaDB": "به یک دیتابیس خارجی MariaDB متصل شوید. شما باید اطلاعات اتصال دیتابیس را تنظیم کنید.",
@ -892,5 +891,74 @@
"documentationOf": "کلید مطلب ها",
"wayToGetHeiiOnCallDetails": "روش دریافت ایدی کلید و کلید ای پی آی درمطلب توضیح داده شده است",
"Channel access token (Long-lived)": "توکن دسترسی به کانال",
"Your User ID": "آیدی حساب کاربری شما"
"Your User ID": "آیدی حساب کاربری شما",
"ignoreTLSErrorGeneral": "نادیده گرفتن ارور TLS/SSL برای برقراری ارتباط",
"Originator": "ایجاد کننده",
"cellsyntOriginatortypeNumeric": "مقدار عددی (حداکثر 15 رقم) با شماره تلفن در قالب بین المللی بدون 00 اول (به عنوان مثال شماره 07920 110 000 بریتانیا باید به عنوان 447920110000 تنظیم شود). گیرندگان می توانند به پیام پاسخ دهند.",
"threemaRecipient": "گیرنده",
"threemaRecipientType": "نوع گیرنده",
"threemaRecipientTypeIdentity": "شناسه Threema",
"threemaRecipientTypeIdentityFormat": "8 کاراکتر",
"threemaRecipientTypePhone": "شماره موبایل",
"threemaRecipientTypePhoneFormat": "E.164، بدون پیشوند +",
"threemaRecipientTypeEmail": "آدرس ایمیل",
"threemaSenderIdentity": "شناسه ورودی",
"threemaApiAuthenticationSecret": "کلید شناسه ورودی",
"threemaBasicModeInfo": "توجه: این ادغام از ورودی Threema در حالت اولیه (رمزگذاری مبتنی بر سرور) استفاده می کند. جزئیات بیشتر را می توان در {0} یافت.",
"smspartnerApiurl": "شما می‌توانید کلید API را در داشبورد خود در {0} پیدا کنید",
"smspartnerPhoneNumber": "شماره موبایل(ها)",
"Host URL": "آدرس هاست",
"gtxMessagingApiKeyHint": "شما می‌توانید کلید API خود را در این آدرس پیدا کنید: My Routing Accounts > Show Account Information > API Credentials > REST API (v2.x)",
"Bitrix24 Webhook URL": "آدرس وب هوک Bitrix24",
"wayToGetBitrix24Webhook": "شما می توانید با دنبال کردن مراحل در {0} یک وب هوک ایجاد کنید",
"whapiRecipient": "شماره تلفن / شناسه ارتباط / شناسه گروه",
"gtxMessagingToHint": "قالب بین‌المللی، با پیشوند \"+\" ({e164}، {e212} یا {e214})",
"Mentioning": "منشن کردن",
"Send to channel": "ارسال به کانال",
"forumPostName": "نام پست انجمن",
"threadForumPostID": "شناسه پست رشته / انجمن",
"e.g. {discordThreadID}": "به عنوان مثال: {discordThreadID}",
"wayToGetDiscordThreadId": "دریافت شناسه پست / انجمن شبیه به دریافت شناسه کانال است. درباره نحوه دریافت شناسه بیشتر بخوانید {0}",
"senderSevenIO": "شماره یا نام ارسال کننده",
"receiverSevenIO": "شماره گیرنده",
"Don't mention people": "این آدم هارا منشن نکن",
"Mention group": "منشن {group}",
"smspartnerSenderName": "نام ارسال کننده اس ام اس",
"apiKeySevenIO": "کلید SevenIO API",
"API URL": "آدرس API",
"callMeBotGet": "اینجا شما می توانید یک نقطه پایانی برای {0}، {1} و {2} ایجاد کنید. به خاطر داشته باشید که ممکن است ریت لیمیت (Rate Limit) دریافت کنید. به نظر می رسد ریت لیمیت ها عبارتند از: {3}",
"To Phone Number": "به شماره موبایل",
"Originator type": "نوع Originator",
"Destination": "مقصد",
"Allow Long SMS": "اجازه ارسال پیام بلند",
"max 15 digits": "حداکثر 15 عدد",
"max 11 alphanumeric characters": "حداکثر 11 کاراکتر الفبا و اعداد",
"locally configured mail transfer agent": "نماینده انتقال نامه به صورت لوکال",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "یا آدرس هاست سروری که میخواهید به آن متصل شوید را وارد کنید یا {localhost} اگر میخواهید از یک {local_mta} استفاده کنید",
"Refresh Interval": "وقفه بین بارگزاری مجدد",
"Refresh Interval Description": "صفحه وضعیت هر {0} ثانیه یک بار سایت را به‌روزرسانی می‌کند",
"Select message type": "انتخاب نوع پیام",
"Create new forum post": "ایحاد یک پست جدید در انجمن",
"postToExistingThread": "پست در یک رشته / انجمن موجود",
"whatHappensAtForumPost": "ایحاد یک پست جدید در انجمن. این گزینه در یک پست موجود پیامی را ارسال نمی کند. برای پست در یک پیام موجود از گزینه\"{option}\" استفاده کنید",
"smspartnerPhoneNumberHelptext": "شماره باید در قالب بین المللی {0}، {1} باشد. شماره ها باید با {2} از هم جدا شوند",
"smspartnerSenderNameInfo": "باید بین 3..=11 کاراکتر معمولی باشد",
"bitrix24SupportUserID": "لطفا شناسه کاربری خود را در Bitrix24 وارد کنید. با رفتن به پروفایل کاربر می توانید شناسه را از لینک دریافت کنید.",
"Command": "دستور",
"mongodbCommandDescription": "یک دستور MongoDB را در پایگاه داده اجرا کنید. برای اطلاعات در مورد دستورات موجود، {documentation} را بررسی کنید",
"wayToGetSevenIOApiKey": "دز داشبورد به آدرس app.seven.io > developer > api key بر روی دکمه سبز اضافه کلیک کنید",
"receiverInfoSevenIO": "اگر شماره دریافت کننده در آلمان نیست، شما باید کد کشور را در مقابل شماره اضافه کنید (به عنوان مثال برای کد کشور 1 از ایالات متحده به جای 017612121212 از 117612121212 استفاده کنید)",
"wayToWriteWhapiRecipient": "شماره تلفن با پیشوند بین‌المللی، اما بدون علامت مثبت در شروع ({0})، شناسه تماس ({1}) یا شناسه گروه ({2}).",
"wayToGetWhapiUrlAndToken": "شما با رفتن به کانال مورد نظر خود از {0} می توانید URL API و توکن را دریافت کنید",
"gtxMessagingFromHint": "در موبایل ها، گیرندگان شما TPOA را که به عنوان فرستنده پیام نمایش داده می شود، می بینند. حداکثر 11 کاراکتر (فقط الفبا و اعداد)، یک کد کوتاه، کد طولانی محلی یا اعداد بین‌المللی مجاز هستند ({e164}، {e212} یا {e214})",
"cellsyntOriginator": "روی تلفن همراه گیرنده به عنوان Originator پیام قابل مشاهده است. مقادیر و تابع مجاز به پارامتر مبدا بستگی دارد.",
"cellsyntDestination": "شماره تلفن گیرنده با استفاده از فرمت بین‌المللی با 00 اصلی و به دنبال آن کد کشور، به عنوان مثال. 00447920110000 برای بریتانیا شماره 07920 110 000 (حداکثر 17 رقم در کل). حداکثر 25000 گیرنده جدا شده با کاما در هر درخواست HTTP.",
"cellsyntSplitLongMessages": "پیام های طولانی را به حداکثر 6 قسمت تقسیم کنید. 153 x 6 = 918 کاراکتر.",
"wayToGetThreemaGateway": "شما می توانید برای Threema Gateway {0} ثبت نام کنید.",
"threemaSenderIdentityFormat": "8 کاراکتر، معمولا با * (ستاره) شروع می شود",
"apiKeysDisabledMsg": "کلیدهای API غیرفعال هستند زیرا احراز هویت غیرفعال است.",
"From Phone Number / Transmission Path Originating Address (TPOA)": "از شماره تلفن / آدرس مبدأ مسیر انتقال (TPOA)",
"Alphanumeric (recommended)": "الفبا و اعداد (پیشنهاد شده)",
"Telephone number": "شماره تلفن",
"cellsyntOriginatortypeAlphanumeric": "الفبا و اعداد (حداکثر 11 کاراکتر). گیرندگان نمی توانند به پیام پاسخ دهند."
}

View File

@ -328,7 +328,7 @@
"Query": "Tiedustelu (Query)",
"settingsCertificateExpiry": "TLS-varmenteen vanheneminen",
"certificationExpiryDescription": "HTTPS-seuraimet käynnistävät ilmoituksen, kun TLS-varmenne vanhenee:",
"Setup Docker Host": "Asenna Docker-isäntä",
"Setup Docker Host": "Määritä Docker-isäntä",
"Connection Type": "Yhteystyyppi",
"tcp": "TCP / HTTP",
"Docker Container": "Docker-kontti",
@ -554,7 +554,7 @@
"High": "Korkea",
"Topic": "Aihe",
"WeCom Bot Key": "WeCom-bottiavain",
"Setup Proxy": "Asenna välityspalvelin",
"Setup Proxy": "Määritä välityspalvelin",
"Proxy Protocol": "Välityspalvelinprotokolla",
"Proxy Server": "Välityspalvelin",
"matrix": "Matriisi",
@ -792,7 +792,6 @@
"emailTemplateLimitedToUpDownNotification": "saatavilla vain YLÖS/ALAS sydämensykkeille, muulloin null",
"Your User ID": "Käyttäjätunnuksesi",
"invertKeywordDescription": "Etsi puuttuvaa avainsanaa.",
"jsonQueryDescription": "Suorita JSON-kysely vastaukselle ja tarkista odotettu arvo (Paluuarvo muutetaan merkkijonoksi vertailua varten). Katso kyselykielen ohjeita osoitteesta {0}. Leikkikenttä löytyy osoitteesta {1}.",
"Bark API Version": "Bark API-versio",
"Notify Channel": "Ilmoitus kanavalle",
"aboutNotifyChannel": "Ilmoitus kanavalle antaa työpöytä- tai mobiili-ilmoituksen kaikille kanavan jäsenille; riippumatta ovatko he paikalla vai poissa.",
@ -971,5 +970,23 @@
"threadForumPostID": "Langan / Keskustelualueketjun ID",
"e.g. {discordThreadID}": "esim. {discordThreadID}",
"whatHappensAtForumPost": "Luo uusi keskustelualueketju. Tämä EI jatka edellistä ketjua. Lähettääksesi olemassaolevaan ketjuun käytä toimintoa \"{option}\"",
"Command": "Komento"
"Command": "Komento",
"smspartnerApiurl": "Löydät API-avaimesi kojelaudalta osoitteesta {0}",
"smspartnerPhoneNumber": "Puhelinnumero(t)",
"smspartnerPhoneNumberHelptext": "Numeron täytyy olla kansainvälisessä muodossa {0},{1}. Jos numeroita on useita, ne täytyy erottaa merkillä {2}",
"smspartnerSenderName": "SMS-lähettäjän nimi",
"smspartnerSenderNameInfo": "Täytyy sisältää 3..=11 tavallista merkkiä",
"threemaRecipient": "Vastaanottaja",
"threemaRecipientType": "Vastaanottajan tyyppi",
"threemaRecipientTypeIdentityFormat": "8 merkkiä",
"threemaRecipientTypePhone": "Puhelinnumero",
"threemaRecipientTypePhoneFormat": "E.164, ilman etuliitettä +",
"threemaRecipientTypeEmail": "Sähköpostiosoite",
"threemaSenderIdentity": "Yhdyskäytävän tunnus (Gateway-ID)",
"threemaApiAuthenticationSecret": "Gateway-ID salaisuus",
"wayToGetThreemaGateway": "Voit rekisteröityä Threema Gateway:n käyttäjäksi {0}.",
"threemaRecipientTypeIdentity": "Threema-tunnus (Threema-ID)",
"threemaSenderIdentityFormat": "8 merkkiä, alkaa useimmiten merkillä *",
"threemaBasicModeInfo": "Huomio: Tämä integraatio käyttää Threema Gateway:tä perustilassa (palvelinpohjainen salaus). Lisätietoja löytyy {0}.",
"apiKeysDisabledMsg": "API-avaimet eivät ole käytössä koska tunnistautuminen ei ole käytössä."
}

View File

@ -797,7 +797,6 @@
"twilioApiKey": "Clé API (facultatif)",
"Expected Value": "Valeur attendue",
"Json Query": "Requête Json",
"jsonQueryDescription": "Faites une requête json contre la réponse et vérifiez la valeur attendue (la valeur de retour sera convertie en chaîne pour comparaison). Consultez {0} pour la documentation sur le langage de requête. Une aire de jeux peut être trouvée {1}.",
"Badge Duration (in hours)": "Durée du badge (en heures)",
"Badge Preview": "Aperçu du badge",
"aboutNotifyChannel": "Notifier le canal déclenchera une notification de bureau ou mobile pour tous les membres du canal, que leur disponibilité soit active ou absente.",
@ -973,5 +972,23 @@
"ignoreTLSErrorGeneral": "Ignorer l'erreur TLS/SSL pour la connexion",
"Bitrix24 Webhook URL": "URL du Webhook Bitrix24",
"wayToGetBitrix24Webhook": "Vous pouvez créer un webhook en suivant les étapes de {0}",
"bitrix24SupportUserID": "Entrez votre identifiant d'utilisateur dans Bitrix24. Vous pouvez trouver l'ID à partir du lien en allant sur le profil de l'utilisateur."
"bitrix24SupportUserID": "Entrez votre identifiant d'utilisateur dans Bitrix24. Vous pouvez trouver l'ID à partir du lien en allant sur le profil de l'utilisateur.",
"smspartnerPhoneNumber": "Numéro(s) de téléphone",
"smspartnerPhoneNumberHelptext": "Le numéro doit être au format international {0}, {1}. Plusieurs numéros doivent être séparés par {2}",
"smspartnerSenderName": "Nom de l'expéditeur SMS",
"smspartnerSenderNameInfo": "Doit être compris entre 3 et 11 caractères réguliers",
"smspartnerApiurl": "Vous pouvez trouver votre clé API dans votre tableau de bord à {0}",
"threemaRecipient": "Destinataire",
"threemaRecipientType": "Type de destinataire",
"threemaRecipientTypeIdentity": "Threema-ID",
"threemaRecipientTypeIdentityFormat": "8 caractères",
"threemaRecipientTypePhone": "Numéro de téléphone",
"threemaRecipientTypePhoneFormat": "E.164, sans le signe + initial",
"threemaRecipientTypeEmail": "Adresse email",
"threemaSenderIdentity": "Identifiant de passerelle",
"threemaSenderIdentityFormat": "8 caractères, commence généralement par *",
"threemaApiAuthenticationSecret": "Secret de l'identifiant de la passerelle",
"wayToGetThreemaGateway": "Vous pouvez vous inscrire à Threema Gateway {0}.",
"threemaBasicModeInfo": "Note : Cette intégration utilise Threema Gateway en mode basique (chiffrement basé sur le serveur). Vous pouvez trouver plus de détails {0}.",
"apiKeysDisabledMsg": "Les clés API sont désactivées car l'authentification est désactivée."
}

View File

@ -89,7 +89,7 @@
"programmingLanguages": "Teangacha Programála",
"Save": "Sábháil",
"Notifications": "Fógraí",
"Setup Notification": "Fógraí Socruithe",
"Setup Notification": "Socrú Fógra",
"Light": "Solas",
"Dark": "Dorcha",
"Auto": "Uathoibríoch",
@ -348,7 +348,7 @@
"Connection String": "Teaghrán Ceangail",
"Query": "Ceist",
"certificationExpiryDescription": "Spreagann Monatóirí HTTPS fógra nuair a théann teastas TLS in éag i:",
"Setup Docker Host": "Socrú Óstach Docker",
"Setup Docker Host": "Socraigh Suas Óstach Docker",
"Connection Type": "Cineál Ceangail",
"Docker Daemon": "Deamhan Docker",
"DockerHostRequired": "Socraigh an tÓstríomhaire Docker don mhonatóir seo.",
@ -639,7 +639,7 @@
"Channel Name": "Ainm Cainéal",
"Notify Channel": "Cainéal a chur ar an eolas",
"Uptime Kuma URL": "URL Uptime Kuma",
"setup a new monitor group": "grúpa monatóireachta nua a shocrú",
"setup a new monitor group": "grúpa monatóireachta nua a bhunú",
"openModalTo": "módúil a oscailt go {0}",
"Add a domain": "Cuir fearann leis",
"Remove domain": "Bain an fearann '{0}'",
@ -682,7 +682,6 @@
"confirmDisableTwoFAMsg": "An bhfuil tú cinnte gur mhaith leat 2FA a dhíchumasú?",
"affectedStatusPages": "Taispeáin an teachtaireacht cothabhála seo ar leathanaigh stádais roghnaithe",
"keywordDescription": "Cuardaigh eochairfhocal i ngnáthfhreagra HTML nó JSON. Tá an cuardach cás-íogair.",
"jsonQueryDescription": "Déan Iarratas json in aghaidh an fhreagra agus seiceáil an luach a bhfuiltear ag súil leis (Déanfar an luach fillte a thiontú ina theaghrán le haghaidh comparáide). Seiceáil {0} le haghaidh na gcáipéisí faoin teanga iarratais. Is féidir clós súgartha a aimsiú {1}.",
"backupDescription": "Is féidir leat gach monatóir agus fógra a chúltaca isteach i gcomhad JSON.",
"backupDescription2": "Nóta: níl sonraí staire agus imeachta san áireamh.",
"octopushAPIKey": "\"Eochair API\" ó dhintiúir API HTTP sa phainéal rialaithe",
@ -938,5 +937,23 @@
"Alphanumeric (recommended)": "Alfa-uimhriúil (molta)",
"Telephone number": "Uimhir theileafóin",
"cellsyntSplitLongMessages": "Roinn teachtaireachtaí fada suas le 6 chuid. 153 x 6 = 918 carachtar.",
"max 15 digits": "15 dhigit ar a mhéad"
"max 15 digits": "15 dhigit ar a mhéad",
"threemaRecipient": "Faighteoir",
"threemaRecipientType": "Cineál Faighteoir",
"threemaRecipientTypeIdentity": "Threema-ID",
"threemaRecipientTypeIdentityFormat": "8 gcarachtar",
"threemaRecipientTypePhone": "Uimhir teileafón",
"threemaRecipientTypePhoneFormat": "E.164, gan tosaigh +",
"threemaRecipientTypeEmail": "Seoladh ríomhphoist",
"threemaSenderIdentity": "Geata-ID",
"threemaApiAuthenticationSecret": "Rún Geata-ID",
"smspartnerPhoneNumber": "Uimhir(neacha) fóin",
"smspartnerSenderName": "Ainm Seoltóra SMS",
"smspartnerSenderNameInfo": "Caithfidh sé a bheith idir 3..=11 charachtar rialta",
"apiKeysDisabledMsg": "Tá eochracha API díchumasaithe toisc go bhfuil fíordheimhniú díchumasaithe.",
"smspartnerApiurl": "Is féidir leat d'eochair API a aimsiú ar do dheais ag {0}",
"smspartnerPhoneNumberHelptext": "Caithfidh an uimhir a bheith san fhormáid idirnáisiúnta {0}, {1}. Ní mór uimhreacha iolracha a dheighilt le {2}",
"wayToGetThreemaGateway": "Is féidir leat clárú le haghaidh Threema Gateway {0}.",
"threemaSenderIdentityFormat": "8 gcarachtar, a thosaíonn le * de ghnáth",
"threemaBasicModeInfo": "Nóta: Úsáideann an comhtháthú seo Threema Gateway i mód bunúsach (criptiúchán freastalaí-bhunaithe). Is féidir tuilleadh sonraí a fháil {0}."
}

View File

@ -799,7 +799,6 @@
"affectedStatusPages": "Prikazuje poruku o održavanju na odabranim statusnim stranicama",
"atLeastOneMonitor": "Odaberite barem jedan zahvaćeni Monitor",
"invertKeywordDescription": "Postavi da ključna riječ mora biti odsutna umjesto prisutna.",
"jsonQueryDescription": "Izvršite JSON upit nad primljenim odgovorom i provjerite očekivanu povrtanu vrijednost. Ona će se za usporedbu pretvoriti u niz znakova (string). Pogledajte stranicu {0} za dokumentaciju o jeziku upita. Testno okruženje možete pronaći {1}.",
"Strategy": "Strategija",
"Free Mobile User Identifier": "Besplatni mobilni korisnički identifikator",
"Free Mobile API Key": "Besplatni mobilni ključ za API",
@ -967,5 +966,23 @@
"Mention group": "Spomeni {group}",
"senderSevenIO": "Broj ili naziv pošiljatelja",
"receiverSevenIO": "Broj primatelja",
"receiverInfoSevenIO": "Ako broj primatelja nije registriran u Njemačkoj, potrebno je uključiti i pozivni broj države (primjerice, umjesto 023123123 potrebno je koristiti 36523123123 ako je riječ o hrvatskom broju)"
"receiverInfoSevenIO": "Ako broj primatelja nije registriran u Njemačkoj, potrebno je uključiti i pozivni broj države (primjerice, umjesto 023123123 potrebno je koristiti 36523123123 ako je riječ o hrvatskom broju)",
"threemaRecipient": "Primatelj",
"threemaRecipientType": "Tip pošiljatelja",
"threemaRecipientTypeIdentity": "Threema ID",
"threemaRecipientTypeIdentityFormat": "8 znakova",
"threemaRecipientTypeEmail": "Adresa e-pošte",
"threemaSenderIdentity": "ID pristupnika",
"threemaSenderIdentityFormat": "8 znakova, obično počinje znakom *",
"threemaApiAuthenticationSecret": "Tajna pristupnika",
"smspartnerApiurl": "Možete pronaći svoj API ključ na nadzornoj ploči: {0}",
"smspartnerPhoneNumber": "Broj(evi) telefona",
"smspartnerPhoneNumberHelptext": "Broj mora biti u međunarodnom formatu {0}, {1}. Višestruki unosi moraju biti odvojeni znakom {2}",
"smspartnerSenderName": "Naziv SMS pošiljatelja",
"apiKeysDisabledMsg": "API ključevi su onemogućeni jer je provjera autentičnosti onemogućena.",
"wayToGetThreemaGateway": "Možete se registrirati za uslugu Threema Gateway {0}.",
"threemaRecipientTypePhone": "Telefonski broj",
"threemaRecipientTypePhoneFormat": "E.164, bez vodećeg znaka +",
"threemaBasicModeInfo": "Napomena: Ova integracija koristi Threema Gateway u osnovnom načinu rada (enkripcija temeljena na poslužitelju). Dodatne pojedinosti možete pronaći na {0}.",
"smspartnerSenderNameInfo": "Mora biti između 3 i 11 znakova"
}

View File

@ -632,7 +632,7 @@
"Connection String": "Csatlakozási karakterlánc",
"statusPageSpecialSlugDesc": "Speciális slug {0}: ez az oldal akkor jelenik meg, ha nincs slug megadva",
"certificationExpiryDescription": "A HTTPS-monitorok értesítést váltanak ki, ha a TLS-tanúsítvány lejár:",
"Setup Docker Host": "Docker hoszt beállítása",
"Setup Docker Host": "Docker Gazda beállítása",
"Connection Type": "Csatlakozás Típusa",
"Docker Daemon": "Docker Daemon",
"deleteDockerHostMsg": "Biztos, hogy törölni akarod ezt a docker hostot az összes monitorról?",
@ -642,7 +642,7 @@
"Docker Hosts": "Docket Hosztok",
"Domain": "Domain",
"Docker Host": "Docket Hoszt",
"noDockerHostMsg": "Nem elérhető. Először állíts be egy Docker Hosztot.",
"noDockerHostMsg": "Nem elérhető. Először állítson be egy Docker Gazdát.",
"DockerHostRequired": "Kérlek állítsd be a Docker Hosztot ehhez a monitorhoz.",
"tailscalePingWarning": "A Tailscale Ping monitor használatához telepítenie kell az Uptime Kuma-t Docker nélkül, és telepíteni kell a Tailscale klienst is a szerverre.",
"Workstation": "Munkaállomás",
@ -776,7 +776,7 @@
"For safety, must use secret key": "Biztonsági okoból kötelező a titkos kulcs használata",
"emailCustomisableContent": "Testreszabható tartalom",
"leave blank for default subject": "hagyja üresen az alapértelmezett email tárgyát",
"smtpLiquidIntroduction": "A következő két mező a Liquid sablonozási nyelven keresztül szerkezthető. Kérjük, olvassa el a következőt: {0} a használati utasításokért. Ezek az elérhető változók:",
"smtpLiquidIntroduction": "A következő két mező a Liquid sablonozási nyelven keresztül szerkeszthető. Kérjük, olvassa el a következőt: {0} a használati utasításokért. Ezek az elérhető változók:",
"Learn More": "Tudjon meg többet",
"Notify Channel": "Csatorna értesítése",
"install": "Telepítés",
@ -797,7 +797,6 @@
"emailTemplateHeartbeatJSON": "a szívverést leíró objektum",
"emailTemplateMsg": "az értesítés üzenete",
"emailTemplateLimitedToUpDownNotification": "csak FEL/LE szívverés esetén érhető el, egyébként null érték",
"jsonQueryDescription": "Végezzen JSON-lekérdezést a válasz alapján, és ellenőrizze a várt értéket (a visszatérési értéket a rendszer karakterlánccá alakítja az összehasonlításhoz). Nézze meg a {0} webhelyet a lekérdezés paramétereivel kapcsolatos dokumentációért. A test környezet itt található: {1}.",
"pushoverMessageTtl": "TTL üzenet (másodperc)",
"Platform": "Platform",
"aboutNotifyChannel": "A Csatorna értesítése opció, értesítést fog küldeni a csatorna összes tagjának, függetlenül a tagok elérhetőségétől.",
@ -828,5 +827,28 @@
"Mechanism": "Mechanizmus",
"No API Keys": "Nincsenek API kulcsok",
"Monitor Group": "Monitor csoport",
"ntfyAuthenticationMethod": "Hitelesítési metódus"
"ntfyAuthenticationMethod": "Hitelesítési metódus",
"Host URL": "Gazda URL",
"Select message type": "Válasszon üzenet típust",
"Send to channel": "Küldés erre a csatornára",
"Create new forum post": "Új fórum üzenet készítése",
"Refresh Interval Description": "Az állapot megfigyelő {0} másodpercenként teljesen újra frissíti a weboldalt",
"Refresh Interval": "Frissítési intervallum",
"postToExistingThread": "Létező szál / fórum -ra küldés",
"forumPostName": "Fórum üzenet neve",
"threadForumPostID": "Szál / Fórum üzenet ID",
"e.g. {discordThreadID}": "például. {discordThreadID}",
"locally configured mail transfer agent": "Helyileg beállított email továbbító",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Adja meg a csatlakoztatni kívánt szerver gazdagép nevét vagy {localhost} ha a {local_mta}-t szeretné használni",
"ignoreTLSErrorGeneral": "Mellőzze a TLS/SSL hibákat a csatlakozáshoz",
"threemaRecipientTypeIdentityFormat": "8 karakter",
"threemaRecipientTypeEmail": "Email cím",
"threemaSenderIdentity": "Gateway-azonosító",
"threemaRecipientTypeIdentity": "Threema-azonosító",
"threemaSenderIdentityFormat": "8 karakter, általában *-al kezdődik",
"threemaRecipientTypePhone": "Telefonszám",
"max 15 digits": "max 15 karakter",
"cellsyntDestination": "A címzett telefonszáma nemzetközi formátumban megadva. A kezdő 00-t követően az országkód, pl. 003612127654 egy magyarországi 0612127654 szám esetében (max 17 karakter összesen). HTTP lekérdezésenként max 25000, vesszővel elválaszott címzett.",
"Telephone number": "Telefonszám",
"Allow Long SMS": "Hosszú SMS engedélyezve"
}

View File

@ -805,7 +805,7 @@
"emailTemplateLimitedToUpDownNotification": "hanya tersedia untuk detak jantung ATAS/BAWAH, jika tidak, null",
"aboutNotifyChannel": "Beritahu saluran akan memicu pemberitahuan desktop atau seluler untuk semua anggota saluran, baik ketersediaannya diatur ke aktif atau tidak.",
"monitorToastMessagesDescription": "Notifikasi Toast untuk monitor hilang setelah waktu tertentu dalam hitungan detik. Setel ke -1 akan menonaktifkan batas waktu. Setel ke 0 akan menonaktifkan notifikasi Toast.",
"wayToGetFlashDutyKey": "Anda dapat membuka Saluran -> (Pilih Saluran) -> Integrasi -> Tambahkan halaman integrasi baru, tambahkan 'Acara Khusus' untuk mendapatkan alamat push, salin Kunci Integrasi di alamat tersebut. Untuk informasi lebih lanjut, silahkan kunjungi",
"wayToGetFlashDutyKey": "Anda dapat membuka Saluran -> (Pilih Saluran) -> Integrasi -> Tambahkan halaman integrasi baru, tambahkan 'Uptime Kuma' untuk mendapatkan alamat push, salin Kunci Integrasi di alamat tersebut. Untuk informasi lebih lanjut, silakan kunjungi",
"Saved.": "Tersimpan.",
"authUserInactiveOrDeleted": "Pengguna tidak aktif atau dihapus.",
"authInvalidToken": "Token Tidak Valid.",
@ -838,7 +838,6 @@
"emailTemplateHeartbeatJSON": "objek yang menggambarkan heartbeat",
"emailTemplateMsg": "pesan pemberitahuan",
"emailCustomBody": "Kustomisasi Body",
"jsonQueryDescription": "Lakukan Query json terhadap respons dan periksa nilai yang diharapkan (Nilai yang dikembalikan akan diubah menjadi string untuk perbandingan). Lihat {0} untuk dokumentasi tentang bahasa kueri. Taman bermain dapat ditemukan {1}.",
"Notify Channel": "Beritahu Saluran",
"Server URL should not contain the nfty topic": "URL server tidak boleh berisi topik nfty",
"PushDeer Server": "Server PushDeer",
@ -897,7 +896,7 @@
"Remote Browser": "Peramban Jarak Jauh",
"Add a Remote Browser": "Tambahkan Remote Browser",
"Remote Browser not found!": "Remote Browser tidak ditemukan!",
"remoteBrowsersDescription": "Remote Browsers adalah alternatif untuk menjalankan Chromium secara lokal. Siapkan dengan layanan seperti browserless.io atau sambungkan ke layanan Anda sendiri",
"remoteBrowsersDescription": "Remote Browsers adalah cara alternatif untuk menjalankan Chromium secara lokal. Siapkan dengan layanan seperti browserless.io atau sambungkan ke layanan Anda sendiri",
"self-hosted container": "kontainer self-hosted",
"remoteBrowserToggle": "Secara default, Chromium berjalan di dalam kontainer Uptime Kuma. Anda dapat menggunakan remote browser dengan menekan tombol ini.",
"useRemoteBrowser": "Gunakan Remote Browser",
@ -920,7 +919,7 @@
"To Phone Number": "Untuk Nomor Telepon",
"gtxMessagingToHint": "Format internasional, dimulai dengan tanda plus \"+\" ({e164}, {e212} or {e214})",
"gtxMessagingApiKeyHint": "Anda dapat menemukan Kunci API Anda di: Perutean Akun Saya > Lihat Informasi Akun > Kredensial API > REST API (v2.x)",
"Originator type": "Tipe Pencetus",
"Originator type": "Tipe Originator",
"Alphanumeric (recommended)": "Alfanumerik (direkomendasikan)",
"Telephone number": "Nomor telepon",
"cellsyntOriginatortypeAlphanumeric": "String alfanumerik (maks 11 karakter). Penerima tidak dapat membalas pesan tersebut.",
@ -929,8 +928,8 @@
"Allow Long SMS": "Izinkan SMS Panjang",
"max 15 digits": "Maksimal 15 digit",
"callMeBotGet": "Anda dapat membuat endpoint untuk {0}, {1} dan {2}. Ingatlah bahwa Anda mungkin akan terkena batas tarif. Batas tarif saat ini adalah: {3}",
"Originator": "Pencetus",
"cellsyntOriginator": "Terlihat di ponsen penerima sebagai pencetus pesan. Nilai dan fungsi yang diizinkan bergantung pada parameter tipe pencetus.",
"Originator": "Originator",
"cellsyntOriginator": "Terlihat di ponsel penerima sebagai pencetus pesan. Nilai dan fungsi yang diizinkan bergantung pada parameter tipe pencetus.",
"Destination": "Tujuan",
"wayToGetWhapiUrlAndToken": "Anda dapat menggunakan URL API dan token dengan bergabung ke saluran yang Anda inginkan dari {0}",
"whapiRecipient": "Nomor Telepon / Kontak ID / Grup ID",
@ -940,5 +939,51 @@
"wayToWriteWhapiRecipient": "Nomor telepon dalam format internasional, tanpa tanda tambah ({0}), Kontak ID ({1}) atau Grup ID ({2}).",
"documentationOf": "{0} Dokumentasi",
"Channel access token (Long-lived)": "Token akses saluran (durasi panjang)",
"Your User ID": "User ID Anda"
"Your User ID": "User ID Anda",
"mongodbCommandDescription": "Jalankan perintah MongoDB terhadap database. Untuk informasi tentang perintah yang tersedia, lihat {documentation}",
"Command": "Perintah",
"threemaRecipient": "Penerima",
"threemaRecipientType": "Tipe Penerima",
"threemaRecipientTypeIdentity": "Threem-ID",
"threemaRecipientTypeIdentityFormat": "8 karakter",
"threemaRecipientTypePhone": "Nomor Telepon",
"threemaRecipientTypePhoneFormat": "E.164, tanpa awalan +",
"threemaRecipientTypeEmail": "Alamat Email",
"threemaSenderIdentity": "Gateway-ID",
"threemaApiAuthenticationSecret": "Gateway-ID Secret",
"smspartnerPhoneNumber": "Nomor telepon",
"smspartnerSenderName": "Nama Pengirim SMS",
"Mentioning": "Menyebut",
"Don't mention people": "Jangan menyebut orang",
"bitrix24SupportUserID": "Masukkan ID pengguna Anda di Bitrix24. Anda dapat mengetahui ID dari tautan dengan membuka profil pengguna.",
"Bitrix24 Webhook URL": "Bitrix24 Webhook URL",
"wayToGetBitrix24Webhook": "Anda dapat membuat webhook dengan mengikuti langkah-langkah di {0}",
"receiverSevenIO": "Menerima nomor",
"receiverInfoSevenIO": "Jika nomor penerima tidak berlokasi di Jerman, Anda harus menambahkan kode negara di depan nomor tersebut (misalnya untuk kode negara 1 dari AS gunakan 117612121212, bukan 017612121212)",
"Host URL": "Host URL",
"senderSevenIO": "Mengirim nomor atau nama",
"apiKeysDisabledMsg": "Kunci API dinonaktifkan karena autentikasi dinonaktifkan.",
"forumPostName": "Nama postingan forum",
"threadForumPostID": "Thread / ID postingan Forum",
"e.g. {discordThreadID}": "misalnya {discordThreadID}",
"Select message type": "Pilih jenis pesan",
"Send to channel": "Kirim ke saluran",
"Create new forum post": "Buat postingan forum baru",
"postToExistingThread": "Posting ke thread/postingan forum yang ada",
"whatHappensAtForumPost": "Buat postingan forum baru. Ini TIDAK mempublikasikan pesan di postingan yang sudah ada. Untuk mempublikasikan di postingan yang sudah ada gunakan '{option}'",
"smspartnerApiurl": "Anda dapat menemukan kunci API di dasbor Anda di {0}",
"smspartnerPhoneNumberHelptext": "Nomor harus dalam format internasional {0}, {1}. Beberapa angka harus dipisahkan dengan {2}",
"smspartnerSenderNameInfo": "Harus di antara 3..=11 karakter biasa",
"wayToGetSevenIOApiKey": "Kunjungi dasbor di bawah app.seven.io > pengembang > api key > tombol yang berwarna hijau",
"wayToGetThreemaGateway": "Anda dapat mendaftar ke Threema Gateway {0}.",
"threemaSenderIdentityFormat": "8 karakter, biasanya diawali dengan *",
"threemaBasicModeInfo": "Catatan: Integrasi ini menggunakan Threema Gateway dalam mode dasar (enkripsi berbasis server). Detail lebih lanjut dapat ditemukan {0}.",
"wayToGetDiscordThreadId": "Mendapatkan id postingan thread/forum mirip dengan mendapatkan id saluran. Baca selengkapnya tentang cara mendapatkan ID {0}",
"Mention group": "Sebutkan {grup}",
"Refresh Interval Description": "Laman status akan melakukan penyegaran situs secara penuh setiap {0} detik",
"Refresh Interval": "Interval muat ulang",
"apiKeySevenIO": "Kunci API SevenIO",
"locally configured mail transfer agent": "transfer email agent yang dikonfigurasi secara lokal",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Masukkan nama host server yang ingin Anda sambungkan atau {localhost} jika Anda ingin menggunakan {local_mta}",
"ignoreTLSErrorGeneral": "Abaikan kesalahan TLS/SSL untuk koneksi"
}

View File

@ -423,7 +423,7 @@
"styleElapsedTimeShowWithLine": "Mostra (con linea)",
"webhookBodyPresetOption": "Predefinito - {0}",
"webhookBodyCustomOption": "Corpo personalizzato",
"topic": "Topic",
"topic": "Argomento",
"selectedMonitorCount": "Selezionato: {0}",
"Check/Uncheck": "Seleziona/Deseleziona",
"Proxies": "Proxy",
@ -445,7 +445,7 @@
"Subject:": "Soggetto:",
"Valid To:": "Valido per:",
"Days Remaining:": "Giorni rimanenti:",
"Issuer:": "Emittente",
"Issuer:": "Emittente:",
"Fingerprint:": "Impronta digitale:",
"No status pages": "Nessuna pagina di stato",
"Domain Name Expiry Notification": "Notifica di scadenza del nome di dominio",
@ -535,10 +535,10 @@
"Server Timezone": "Fuso orario del server",
"statusPageMaintenanceEndDate": "Fine",
"IconUrl": "URL dell'icona",
"Enable DNS Cache": "(Obsoleto) Abilita la cache DNS per i monitor HTTP(s).",
"Enable DNS Cache": "(Obsoleto) Abilita la cache DNS per i monitor HTTP(s)",
"Enable": "Abilitare",
"Disable": "Disattivare",
"chromeExecutableAutoDetect": "Trovato automaticamente",
"chromeExecutableAutoDetect": "Trova automaticamente",
"dnsCacheDescription": "Potrebbe non funzionare in alcuni ambienti IPv6, disabilitalo in caso di problemi.",
"Single Maintenance Window": "Singola finestra di manutenzione",
"Maintenance Time Window of a Day": "Finestra temporale di manutenzione di un giorno",
@ -554,7 +554,7 @@
"uninstall": "Disinstalla",
"confirmUninstallPlugin": "Sei sicuro di voler disinstallare questo plugin?",
"notificationRegional": "Regionale",
"Clone": "Clone",
"Clone": "Duplica",
"cloneOf": "Clone di {0}",
"wayToGetZohoCliqURL": "Puoi scoprire come creare un URL webhook {0}.",
"dataRetentionTimeError": "Il periodo di conservazione deve essere pari o superiore a 0",
@ -586,7 +586,7 @@
"invalidCronExpression": "Espressione Cron non valida: {0}",
"lastDay2": "2° ultimo giorno del mese",
"maintenanceStatus-under-maintenance": "In manutenzione",
"chromeExecutable": "Cromo/cromo eseguibile",
"chromeExecutable": "Eseguibile Chrome/Chromium",
"chromeExecutableDescription": "Per gli utenti Docker, se Chromium non è ancora installato, potrebbero essere necessari alcuni minuti per l'installazione e la visualizzazione del risultato del test. Richiede 1 GB di spazio su disco.",
"uninstalling": "Disinstallazione",
"confirmDeleteTagMsg": "Sei sicuro di voler eliminare questo tag? I monitor associati a questo tag non verranno eliminati.",
@ -620,7 +620,6 @@
"enableNSCD": "Abilita NSCD (Name Service Cache Daemon) per abilitare la cache su tutte le richieste DNS",
"recurringIntervalMessage": "Esegui una volta al giorno | Esegui una volta ogni {0} giorni",
"affectedMonitorsDescription": "Seleziona i monitoraggi che sono influenzati da questa manutenzione",
"jsonQueryDescription": "Fai una query JSON verso la risposta e controlla se è presente il valore richiesto. (Il valore di ritorno verrà convertito in stringa ai fini della comparazione). Puoi controllare la documentazione su <a href='https://jsonata.org/'>jsonata.org</a> per conoscere come scrivere una query. Un area dimostrativa può essere trovata <a href='https://try.jsonata.org/'>qui</a>.",
"For safety, must use secret key": "Per sicurezza, devi usare una chiave segreta",
"Proxy server has authentication": "Il server Proxy ha una autenticazione",
"smseaglePriority": "Priorità messaggio (0-9, default = 0)",
@ -669,12 +668,35 @@
"templateMsg": "Messaggio della notifica",
"Search monitored sites": "Ricerca tra i siti monitorati",
"settingUpDatabaseMSG": "Configurazione del database in corso. Potrebbe richiedere un po' di tempo...",
"templateHeartbeatJSON": "oggetto che descrive il battito cardiaco",
"templateHeartbeatJSON": "oggetto che descrive il controllo",
"templateLimitedToUpDownNotifications": "disponibile solo per le notifiche UP/DOWN",
"Add a new expiry notification day": "Aggiungi un nuovo giorno di notifica di scadenza",
"DockerHostRequired": "Per favore, imposta l'host Docker per questo monitor.",
"smtpLiquidIntroduction": "I due campi seguenti sono adattabili tramite il linguaggio di templating Liquid. Consulta {0} per le istruzioni d'uso. Queste sono le variabili disponibili:",
"emailCustomisableContent": "Contenuto personalizzabile",
"noDockerHostMsg": "Non disponibile. Configura prima un host Docker.",
"Remove the expiry notification": "Rimuovi il giorno di notifica di scadenza"
"Remove the expiry notification": "Rimuovi il giorno di notifica di scadenza",
"emailTemplateHeartbeatJSON": "oggetto che descrive il controllo",
"leave blank for default subject": "Lasciare vuoto per oggetto predefinito",
"emailCustomBody": "Messaggio personalizzato",
"Select message type": "Seleziona il tipo di messaggio",
"Send to channel": "Invia al canale",
"Create new forum post": "Crea un nuovo post sul forum",
"postToExistingThread": "Scrivi in una conversazione / post esistente",
"forumPostName": "Nome forum del post",
"threadForumPostID": "ID della conversazione / Forum del post",
"e.g. {discordThreadID}": "es. {discordThreadID}",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Inserisci il nome host del server a cui vuoi connetterti oppure {localhost} se intendi utilizzare un {local_mta}",
"templateLimitedToUpDownCertNotifications": "disponibile solo per le notifiche UP/DOWN/Scadenza certificato",
"emailTemplateMsg": "Messaggio della notifica",
"emailTemplateLimitedToUpDownNotification": "disponibile solo per controlli UP/DOWN, altrimenti nullo",
"Refresh Interval": "Intervallo di aggiornamento",
"Refresh Interval Description": "La pagina di stato si aggiornerà completamente ogni {0} secondi",
"emailTemplateServiceName": "Nome servizio",
"leave blank for default body": "Lasciare vuoto per messaggio predefinito",
"emailTemplateHostnameOrURL": "Nome host o URL",
"emailTemplateStatus": "Stato",
"ignoreTLSErrorGeneral": "Ignora gli errori TLS/SSL per la connessione",
"statusPageSpecialSlugDesc": "Slug speciale {0}: questa pagina verrà mostrata quando non viene fornito alcuno slug",
"successKeywordExplanation": "Parola chiave MQTT che verrà considerata come corretta"
}

View File

@ -92,7 +92,7 @@
"No": "いいえ",
"Username": "ユーザー名",
"Password": "パスワード",
"Remember me": "パスワードを忘れた場合",
"Remember me": "ログインしたままにする",
"Login": "ログイン",
"No Monitors, please": "監視がありません",
"add one": "add one",
@ -131,7 +131,7 @@
"confirmDisableTwoFAMsg": "2段階認証を「無効」にします。よろしいですか?",
"Apply on all existing monitors": "既存のすべてのモニターに適用する",
"Verify Token": "認証する",
"Setup 2FA": "2段階認証の設定",
"Setup 2FA": "二要素認証 (2FA) の設定",
"Enable 2FA": "2段階認証を有効にする",
"Disable 2FA": "2段階認証を無効にする",
"2FA Settings": "2段階認証の設定",
@ -225,7 +225,7 @@
"Pink": "ピンク",
"Required": "必須",
"Select status pages...": "ステータスページを選択してください…",
"webhookAdditionalHeadersDesc": "Webhook で送信される追加ヘッダーを設定します。",
"webhookAdditionalHeadersDesc": "Webhook で送信される追加ヘッダーを設定します。各ヘッダーは JSON の key/value 型で定義されている必要があります。",
"Webhook URL": "Webhook URL",
"Application Token": "Application Token",
"steamApiKeyDescription": "Steam Game Server を監視するためには、Steam Web-API キーが必要です。APIキーの登録はこちらから行えます。 ",
@ -315,8 +315,8 @@
"signedInDisp": "{0}としてログイン中",
"RadiusSecret": "Radius シークレット",
"RadiusSecretDescription": "クライアントとサーバー間の共有シークレット",
"RadiusCalledStationId": "Called Station Id",
"RadiusCallingStationId": "Calling Station Id",
"RadiusCalledStationId": "Called-Station-Id",
"RadiusCallingStationId": "Calling-Station-Id",
"Subject:": "サブジェクト:",
"trustProxyDescription": "ヘッダー「X-Forwarded-*」を信頼します。Uptime Kumaがリバースプロキシの中にあり、正しいクライアントIPを取得する場合は、有効化してください。",
"Home Assistant URL": "ホームアシスタントURL",
@ -454,14 +454,14 @@
"maintenanceStatus-unknown": "不明",
"Server Timezone": "サーバータイムゾーン",
"IconUrl": "アイコンURL",
"Enable DNS Cache": "DNSキャッシュを有効にする",
"Enable DNS Cache": "(非推奨) HTTP(s)の監視に対しDNSキャッシュを有効にする",
"Enable": "有効",
"Disable": "無効",
"Schedule Maintenance": "スケジュールメンテナンス",
"loadingError": "データを取得できません。後でもう一度試してください。",
"uninstall": "アンインストール",
"installing": "インストール中",
"Ignore TLS Error": "TLSエラーを無視",
"Ignore TLS Error": "TLS エラーを無視",
"smtpCC": "CC",
"secureOptionTLS": "TLS (465)",
"smtpBCC": "BCC",
@ -555,7 +555,7 @@
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "通知サービスの一覧からデバイス名を見つけるには、Home Assistantの「開発者ツール > サービス」から通知で検索してください。",
"Notify Channel": "通知チャンネル",
"Icon Emoji": "絵文字アイコン",
"setupDatabaseChooseDatabase": "どのデータベースを利用しますか?",
"setupDatabaseChooseDatabase": "どのデータベースを使いたいですか?",
"setupDatabaseEmbeddedMariaDB": "何も設定する必要はありません。この Docker イメージは設定済みの MariaDB が組み込まれています。Uptime Kuma はこのデータベースに unix ソケットを通じて接続します。",
"setupDatabaseSQLite": "小規模な開発のために推奨される小さなデータベースファイルです。v2.0.0 以前は、Uptime Kuma は SQLite を標準のデータベースとして使用していました。",
"tailscalePingWarning": "Tailscale Ping モニターを使用するためには、Uptime Kuma を Docker を利用せずインストールし、そのうえで Tailscale Client をサーバーにインストールしてください。",
@ -567,5 +567,111 @@
"selectedMonitorCount": "選択済み: {0}",
"Long-Lived Access Token": "長期アクセストークン",
"Invert Keyword": "「含まない」キーワード",
"Expected Value": "期待値"
"Expected Value": "期待値",
"dataRetentionTimeError": "保持期間は 0 か、それ以上である必要があります",
"settingUpDatabaseMSG": "データベースをセットアップしています。しばらくお待ちください。",
"Check/Uncheck": "選択あり/なし",
"Alphanumeric (recommended)": "半角英数字(推奨)",
"GrafanaOncallUrl": "Grafana オンコール URL",
"Command": "コマンド",
"Browser Screenshot": "ブラウザ・スクリーンショット",
"mongodbCommandDescription": "データベースに対して MongoDB コマンドを実行します。使用できるコマンドについては {documentation} を参照ください",
"2faDisabled": "二要素認証 (2FA) を無効にしました。",
"Telephone number": "電話番号",
"remoteBrowsersDescription": "リモートブラウザは Chromium を実行するための代替手段です。ローカルで実行する代わりに、browserless.io のようなサービスや、独自のサービスに接続します",
"max 15 digits": "最大15桁",
"What is a Remote Browser?": "リモート・ブラウザとは何ですか?",
"Remote Browsers": "リモート・ブラウザ",
"Remote Browser": "リモート・ブラウザ",
"wayToGetSevenIOApiKey": "app.seven.io > developer > api key > 緑色の追加ボタンの下にあるダッシュボードをご覧ください",
"senderSevenIO": "番号もしくは名前を送信しています",
"receiverSevenIO": "番号を受信しています",
"Search monitored sites": "監視対象サイトの検索",
"liquidIntroduction": "Templatability は Liquid テンプレート言語を利用します。使い方は {0} をご覧ください。以下は利用可能な変数です:",
"templateMsg": "通知の内容",
"templateHeartbeatJSON": "死活監視 (heartbeat) を記述している JSON オブジェクト",
"templateMonitorJSON": "監視対象を記述している JSON オブジェクト",
"Remove the expiry notification": "有効期限の通知日を削除する",
"authInvalidToken": "無効なトークンです。",
"authIncorrectCreds": "無効なユーザー名かパスワードです。",
"self-hosted container": "セルフ・ホストのコンテナ",
"useRemoteBrowser": "リモート・ブラウザを使う",
"Add a Remote Browser": "リモート・ブラウザを追加する",
"remoteBrowserToggle": "デフォルトでは、Chromium は Uptime Kuma コンテナ内で実行されます。このスイッチを切り替えることで、リモート・ブラウザを使用できます。",
"Remote Browser not found!": "リモート・ブラウザがありません!",
"Select message type": "メッセージ・タイプを選択してください",
"Send to channel": "チャンネルに送信",
"Create new forum post": "新規フォーラムに投稿",
"needSignalAPI": "REST API に対応したシグナリング用のクライアントが必要です。",
"aboutIconURL": "「アイコン URL」に画像へのリンクを指定することで、デフォルトのプロフィール画像を上書きすることができます。「アイコン絵文字」が指定されている場合は使用されません。",
"octopushAPIKey": "コントロールパネルの HTTP API 認証情報にある「API キー」",
"2faEnabled": "二要素認証 (2FA) を有効にしました。",
"successAdded": "正常に追加されました。",
"successResumed": "正常に再開しました。",
"2faAlreadyEnabled": "二要素認証 (2FA) は、すでに有効になっています。",
"successDeleted": "正常に削除しました。",
"successPaused": "正常に一時停止しました。",
"successAuthChangePassword": "正常にパスワードを更新しました。",
"successEdited": "正常に編集できました。",
"successBackupRestored": "正常にバックアップから復元しました。",
"successEnabled": "正常に有効化しました。",
"tagNotFound": "タグが見つかりませんでした。",
"foundChromiumVersion": "Chromium/Chrome を見つけました。 Version: {0}",
"Select": "選択",
"Add a new expiry notification day": "有効期限の通知日を追加する",
"emailCustomSubject": "カスタム・トピック",
"emailTemplateMsg": "通知の内容",
"To Email": "Email へ",
"emailTemplateLimitedToUpDownNotification": "UP/DOWN 死活監視 (heartbeat) の場合のみ有効",
"deleteRemoteBrowserMessage": "本当にこのリモートブラウザをすべての監視から削除しますか?",
"Refresh Interval": "更新間隔",
"Refresh Interval Description": "ステータスページは{0}秒ごとに全面更新されます",
"wayToGetLineChannelToken": "まず {0} にアクセスし、プロバイダーとチャネル(Messaging API)を作成します。次に、上記のメニューからアクセストークンとチャネルのユーザー ID を取得します。",
"aboutMattermostChannelName": "「チャンネル名」フィールドにチャンネル名を入力することで、Webhook から送信されるデフォルトのチャンネル名を上書きできます。これは Mattermost の Webhook 設定で有効にしておく必要があります。例 #other-channel",
"Saved.": "保存しました。",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "接続するサーバーのホスト名を入力するか、{local_mta} を使用する場合は {localhost} を入力します",
"e.g. {discordThreadID}": "例 {discordThreadID}",
"postToExistingThread": "既存のスレッド/フォーラムに投稿",
"forumPostName": "投稿先のフォーラム名",
"threadForumPostID": "投稿先のスレッド/フォーラム ID",
"whatHappensAtForumPost": "新規フォーラム投稿。既存の投稿がある場合は投稿しません。既存の投稿の中に投稿を作成するには「{option}」を使用してください",
"emailTemplateHeartbeatJSON": "死活監視 (heartbeat) を記述している JSON オブジェクト",
"leave blank for default subject": "空の場合はデフォルトの件名を使用します",
"cellsyntSplitLongMessages": "長文メッセージは最大 6 つに分割してください。153 x 6 = 918文字です。",
"Allow Long SMS": "ロングコード SMS を許可する",
"cellsyntDestination": "受信者の電話番号。00 に続けて国番号を付ける国際形式である必要があります。たとえば、英国の番号 07920 110 000 の場合は 00447920110000(合計17桁まで)になります。HTTP リクエストごとに指定できる受信者数は、カンマ区切りで最大 25,000 件です。",
"emailTemplateMonitorJSON": "監視対象を記述している JSON オブジェクト",
"successDisabled": "正常に無効化しました。",
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "長期アクセストークンは、プロフィール名(左下)をクリックし、下にスクロールして「トークンを作成」をクリックすると作成できます。 ",
"Effective Date Range": "有効範囲(オプション)",
"DateTime Range": "日付範囲",
"Maintenance Time Window of a Day": "今日のメンテナンス時間のウィンドウ",
"octopushLogin": "コントロールパネルの HTTP API 認証情報にある「ログイン」",
"notificationRegional": "特殊地域",
"pushOthers": "その他",
"Host URL": "ホストURL",
"enableNSCD": "NSCD (Name Service Cache Daemon) を有効にして、すべての DNS クエリをキャッシュする",
"successKeywordExplanation": "成功としてカウントされる MQTT のキーワード",
"DockerHostRequired": "この監視の Docker ホストを設定してください。",
"noDockerHostMsg": "利用できません。Docker ホストを先にセットアップしてください。",
"styleElapsedTime": "経過時間を監視バーの下に表示",
"styleElapsedTimeShowNoLine": "表示(改行なし)",
"styleElapsedTimeShowWithLine": "表示(改行あり)",
"lastDay": "最終日",
"lastDay1": "月末",
"lastDay2": "月末の 2 日前",
"lastDay3": "月末の 3 日前",
"lastDay4": "月末の 4 日前",
"chromeExecutable": "Chrome/Chromium の実行ファイル",
"chromeExecutableDescription": "Docker を使用しており、Chromium がインストールされていない場合、インストールしてからテスト結果の表示するのに数分かかることがあります。1 GB の容量を必要とします。",
"jsonQueryDescription": "応答に対して json クエリを実行し、値が期待されたものであるか確認します(戻り値は比較の際文字列に変換されます)。 クエリ言語のドキュメントについては、{0}を参照してください。{1}にプレイグラウンドがあります。",
"leave blank for default body": "デフォルトの本文を使用するには空のままにしてください",
"apprise": "Apprise (50以上の通知サービスをサポートしています)",
"Apprise URL": "AppriseのURL",
"emailTemplateHostnameOrURL": "ホスト名またはURL",
"emailCustomisableContent": "カスタマイズ可能なコンテンツ",
"emailCustomBody": "カスタム本文",
"emailTemplateServiceName": "サービス名",
"smtpLiquidIntroduction": "次の 2 つのテンプレート・フィールドは Liquid テンプレート言語で記述できます。これらの使い方は {0} にあります。以下は利用可能な変数です:",
"emailTemplateStatus": "ステータス"
}

222
src/lang/lt.json Normal file
View File

@ -0,0 +1,222 @@
{
"languageName": "Lietuvių",
"settingUpDatabaseMSG": "Vyksta duomenų bazės sąranka. Tai gali užtrukti, būkite kantrūs.",
"Settings": "Parametrai",
"Dashboard": "Skydelis",
"Help": "Pagalba",
"New Update": "Naujas atnaujinimas",
"Language": "Kalba",
"Appearance": "Išvaizda",
"General": "Bendra",
"Version": "Versija",
"List": "Sąrašas",
"Home": "Pradžia",
"Add": "Pridėti",
"Add New Monitor": "Įtraukti naują monitorių",
"Quick Stats": "Greita statistika",
"Up": "Veikia",
"statusMaintenance": "Profilaktika",
"Unknown": "Nežinomas",
"Cannot connect to the socket server": "Nepavyksta prisijungti prie lizdo serverio",
"Reconnecting...": "Atkuriamas ryšys...",
"General Monitor Type": "Bendrasis monitoriaus tipas",
"Passive Monitor Type": "Pasyvusis monitoriaus tipas",
"markdownSupported": "Palaikoma Markdown sintaksė",
"Pause": "Pauzė",
"Name": "Pavadinimas",
"Status": "Būsena",
"DateTime": "DataLaikas",
"Message": "Žinutė",
"Resume": "Tęsti",
"Edit": "Redaguoti",
"Delete": "Ištrinti",
"Current": "Dabartinis",
"Uptime": "Veikimo trukmė",
"Cert Exp.": "Sertifikato baig.",
"day": "diena | dienų",
"-day": "-dienų",
"hour": "valanda",
"-hour": "-valandos",
"Ping": "Ping",
"Monitor Type": "Monitoriaus tipas",
"Keyword": "Raktažodis",
"Invert Keyword": "Invertuoti raktažodį",
"Json Query": "Json užklausa",
"Friendly Name": "Draugiškas pavadinimas",
"URL": "URL adresas",
"locally configured mail transfer agent": "lokaliai sukonfigūruotas pašto perdavimo agentas",
"Request Timeout": "Užklausos trukmės limitas",
"timeoutAfter": "Trukmės limitas po {0} sekundžių",
"Retries": "Pakartotiniai bandymai",
"Heartbeat Retry Interval": "Širdies ritmo kartojimo intervalas",
"Advanced": "Išplėstinis",
"checkEverySecond": "Tikrinti kas {0} sekundžių",
"retryCheckEverySecond": "Pakartotinai bandyti kas {0} sekundžių",
"resendEveryXTimes": "Pakartotinai siųsti kas {0} kartų",
"resendDisabled": "Pakartotinis siuntimas neįgalintas",
"ignoreTLSError": "TLS/SSL klaidų ignoravimas HTTPS svetainėse",
"ignoreTLSErrorGeneral": "Ignoruoti TLS/SSL ryšio klaidą",
"upsideDownModeDescription": "Apversti būseną aukštyn kojomis. Jei paslauga yra pasiekiama, ji NEVEIKIA.",
"Upside Down Mode": "Apverstas režimas",
"Max. Redirects": "Maksimalūs peradresavimai",
"pushOptionalParams": "Neprivalomi parametrai: {0}",
"pushViewCode": "Kaip naudoti Push monitorių? (Žiūrėti kodą)",
"pushOthers": "Kiti",
"programmingLanguages": "Programavimo kalbos",
"Save": "Išsaugoti",
"Notifications": "Pranešimai",
"Not available, please setup.": "Negalima, prašome nustatyti.",
"Setup Notification": "Nustatyti pranešimą",
"Light": "Šviesus",
"Theme - Heartbeat Bar": "Tema - Heartbeat Bar",
"styleElapsedTime": "Praėjęs laikas po širdies ritmo juosta",
"styleElapsedTimeShowNoLine": "Rodyti (be linijos)",
"styleElapsedTimeShowWithLine": "Rodyti (su linija)",
"Normal": "Normalus",
"Bottom": "Apačia",
"None": "Nėra",
"Search Engine Visibility": "Matomumas paieškos sistemose",
"Allow indexing": "Leisti indeksuoti",
"Change Password": "Keisti slaptažodį",
"Current Password": "Dabartinis slaptažodis",
"New Password": "Naujas slaptažodis",
"Repeat New Password": "Naujas slaptažodis",
"Disable Auth": "Išjungti autentifikavimą",
"Enable Auth": "Įgalinti autentifikavimą",
"disableauth.message1": "Ar tikrai norite {disableAuth}?",
"setupDatabaseChooseDatabase": "Kurią duomenų bazę norėtumėte naudoti?",
"setupDatabaseMariaDB": "Prisijunkite prie išorinės MariaDB duomenų bazės. Reikia nustatyti duomenų bazės prisijungimo informaciją.",
"setupDatabaseSQLite": "Paprastas duomenų bazės failas, rekomenduojamas nedidelės apimties diegimui. Iki versijos 2.0.0, Uptime Kuma, kaip numatytąją duomenų bazę, naudojo SQLite.",
"setupDatabaseEmbeddedMariaDB": "Nereikia nieko nustatyti. Šiame Docker atvaizde MariaDB įdiegta ir sukonfigūruota automatiškai. Uptime Kuma prie šios duomenų bazės prisijungs per Unix lizdą.",
"dbName": "Duomenų bazės pavadinimas",
"Theme": "Tema",
"Game": "Žaidimo",
"Primary Base URL": "Pradinis bazės URL adresas",
"Check Update On GitHub": "Patikrinkite atnaujinimą GitHub",
"Down": "Neveikia",
"Pending": "Laukiama",
"Maintenance": "Profilaktikos darbai",
"Specific Monitor Type": "Konkretus monitoriaus tipas",
"pauseDashboardHome": "Pauzė",
"No important events": "Jokių svarbių įvykių",
"Monitor": "Monitorius | Monitorių",
"Response": "Atsakymas",
"Expected Value": "Tikėtina vertė",
"Hostname": "Pagrindinio kompiuterio vardas",
"Host URL": "Priimančiojo URL adresas",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Įveskite serverio, prie kurio norite prisijungti, pagrindinį kompiuterio vardą arba {localhost}, jei ketinate naudoti {local_mta}",
"Port": "Prievadas",
"Heartbeat Interval": "Širdies ritmo intervalas",
"Resend Notification if Down X times consecutively": "Pakartotinis pranešimo siuntimas, jei neveikia X kartų iš eilės",
"retriesDescription": "Didžiausias pakartotinių bandymų skaičius, kol paslauga pažymėta, kaip neveikianti, ir išsiųstas pranešimas",
"maxRedirectDescription": "Didžiausias galimų nukreipimų skaičius. Nustatykite 0, jei norite išjungti nukreipimus.",
"Accepted Status Codes": "Priimtini būsenos kodai",
"Push URL": "Push URL adresas",
"needPushEvery": "Šį URL adresą turėtumėte iškviesti kas {0} sekundžių.",
"Dark": "Tamsus",
"Auto": "Automatinis",
"Timezone": "Laiko juosta",
"Discourage search engines from indexing site": "Neskatinti paieškos sistemų indeksuoti svetainę",
"Update Password": "Atnaujinti slaptažodį",
"disable authentication": "išjungti autentifikavimą",
"where you intend to implement third-party authentication": "kur ketinate įdiegti trečiosios šalies autentifikavimą",
"Please use this option carefully!": "Atsargiai naudokite šią parinktį!",
"Logout": "Atsijungti",
"Leave": "Palikti",
"Confirm": "Patvirtinti",
"Yes": "Taip",
"No": "Ne",
"Password": "Slaptažodis",
"Remember me": "Prisiminti mane",
"Login": "Prisijungti",
"add one": "pridėti vieną",
"Notification Type": "Pranešimo tipas",
"Email": "El. paštas",
"Test": "Testas",
"Resolver Server": "Resolverio serveris",
"Last Result": "Paskutinis rezultatas",
"Create your admin account": "Susikurkite administratoriaus paskyrą",
"Repeat Password": "Pakartoti slaptažodį",
"Export Backup": "Eksportuoti atsarginę kopiją",
"Export": "Eksportuoti",
"Import": "Importuoti",
"respTime": "Reakcijos laikas (ms)",
"notAvailableShort": "N/A",
"Create": "Sukurti",
"Clear Data": "Išvalyti duomenis",
"Events": "Įvykiai",
"Heartbeats": "Širdies ritmas",
"Affected Monitors": "Paveikti monitoriai",
"Pick Affected Monitors...": "Pasirinkite paveiktus monitorius…",
"All Status Pages": "Visi būsenų puslapiai",
"alertWrongFileType": "Pasirinkite JSON failą.",
"Clear all statistics": "Išvalyti visą statistiką",
"Overwrite": "Perrašyti",
"Options": "Parinktys",
"Keep both": "Palikti abu",
"Verify Token": "Paikrinti žetoną",
"Enable 2FA": "Įgalinti 2FA",
"Disable 2FA": "Išjungti 2FA",
"2FA Settings": "2FA nustatymai",
"filterActive": "Aktyvus",
"filterActivePaused": "Sustabdytas",
"Active": "Aktyvus",
"Inactive": "Neaktyvus",
"Token": "Žetonas",
"Show URI": "Rodyti URL",
"Tags": "Žymės",
"Add New Tag": "Pridėti naują žymą",
"Add New below or Select...": "Pridėti naują žemiau arba pasirinkti…",
"color": "Spalva",
"value (optional)": "reikšmė (neprivaloma)",
"Gray": "Pilka",
"Red": "Raudona",
"Green": "Žalia",
"Blue": "Mėlyna",
"Indigo": "Indigo",
"Purple": "Violetinė",
"Custom": "Pasirinktina",
"Search monitored sites": "Stebimų svetainių paieška",
"Avg. Ping": "Vidutinis Ping",
"Entry Page": "Puslapis įėjus",
"statusPageRefreshIn": "Perkrauti per: {0}",
"No Services": "Paslaugų nėra",
"All Systems Operational": "Visos sistemos veikia",
"Partially Degraded Service": "Dalinai pablogėjusi paslauga",
"Degraded Service": "Pablogėjusi paslauga",
"Add Group": "Pridėti grupę",
"Add a monitor": "Pridėti monitorių",
"Edit Status Page": "Redaguoti būsenos puslapį",
"Status Page": "Būsenos puslapis",
"here": "čia",
"Required": "Privaloma",
"Post URL": "Post URL",
"Content Type": "Turinio tipas",
"disableauth.message2": "Jis skirtas scenarijams {intendThirdPartyAuth} priešais Uptime Kuma, pavyzdžiui, Cloudflare Access, Authelia ar kitus autentifikavimo mechanizmus.",
"I understand, please disable": "Aš suprantu, prašau išjungti",
"Username": "Vartotojo vardas",
"No Monitors, please": "Jokių monitorių, prašau",
"Certificate Info": "Sertifikato informacija",
"Resource Record Type": "Išteklių įrašo tipas",
"Import Backup": "Importuoti atsarginę kopiją",
"Default enabled": "Pagal nutylėjimą įgalinta",
"Apply on all existing monitors": "Taikyti visiems esamiems monitoriams",
"Auto Get": "Automatinis gavimas",
"Schedule maintenance": "Profilaktikos tvarkaraštis",
"Start of maintenance": "Profilaktikos pradžia",
"Select status pages...": "Pasirinkite būsenos puslapius…",
"alertNoFile": "Pasirinkite importuojamą failą.",
"Skip existing": "Praleisti esamus",
"Setup 2FA": "Nustatyti 2FA",
"Two Factor Authentication": "Dviejų veiksnių autentifikavimas",
"Tag with this name already exist.": "Žyma tokiu pavadinimu jau egzistuoja.",
"Tag with this value already exist.": "Žyma tokia reikšme jau egzistuoja.",
"Orange": "Oranžinė",
"Pink": "Rožinė",
"Search...": "Ieškoti…",
"Avg. Response": "Vidutinė reakcija",
"statusPageNothing": "Čia nieko nėra, pridėkite grupę arba monitorių.",
"Go to Dashboard": "Eiti į skydelį",
"Status Pages": "Būsenos puslapiai",
"defaultNotificationName": "Mano {notification} įspėjimas nr. ({number})"
}

1
src/lang/lzh.json Normal file
View File

@ -0,0 +1 @@
{}

92
src/lang/mk.json Normal file
View File

@ -0,0 +1,92 @@
{
"setupDatabaseMariaDB": "Поврзи надворешна MariaDB датабаза. Мораш да ги внесеш податоците за најава од датабазата.",
"dbName": "Име од Датабаза",
"Settings": "Поставки",
"Dashboard": "Контролна табла",
"Help": "Помош",
"Language": "Јазик",
"Theme": "Тема",
"General": "Генерално",
"Game": "Игра",
"Version": "Верзија",
"Check Update On GitHub": "Проверете го ажурирањето на GitHub",
"List": "Листа",
"Home": "Дома",
"Add": "Додај",
"Add New Monitor": "Додај нов монитор",
"Quick Stats": "Брзи статистика",
"Up": "Горе",
"Down": "Доле",
"Pending": "Во очекување",
"Maintenance": "Одржување",
"Unknown": "Непознато",
"Reconnecting...": "Повторно поврзување...",
"Specific Monitor Type": "Специфичен тип на монитор",
"pauseDashboardHome": "Пауза",
"Name": "Име",
"Status": "Статус",
"Message": "Порака",
"No important events": "Нема важни настани",
"Resume": "Продолжи",
"Edit": "Измени",
"Current": "Сегашен",
"Cert Exp.": "Истек Серт.",
"Monitor": "Монитор | Монитори",
"day": "ден | денови",
"-day": "-ден",
"hour": "час",
"-hour": "-час",
"Ping": "Пинг",
"Monitor Type": "Мониторски тип",
"Invert Keyword": "Инвертирајте клучни зборови",
"Expected Value": "Очекувана Вредност",
"Json Query": "Json Query",
"URL": "УРЛ",
"Hostname": "Hostname",
"Port": "Порт",
"Heartbeat Interval": "Интервал на отчукување на срцето",
"Request Timeout": "Истекување на барањето",
"Retries": "Обиди",
"Advanced": "Напредно",
"checkEverySecond": "Провери секоја {0} секунда",
"retryCheckEverySecond": "Повтори секои {0} секунди",
"resendEveryXTimes": "Препрати на секои {0} пати",
"resendDisabled": "Повторно испраќање е оневозможено",
"ignoreTLSError": "Игнорирај TLS/SSL errors за HTTPS websites",
"ignoreTLSErrorGeneral": "Игнорирај TLS/SSL грешки при конекција",
"upsideDownModeDescription": "Превртете го статусот наопаку. Ако услугата е достапна, таа е ДОЛУ.",
"Upside Down Mode": "Режим наопаку",
"Max. Redirects": "Макс. Пренасочувања",
"Accepted Status Codes": "Прифатливи Статус Кодови",
"Push URL": "Push URL",
"pushOptionalParams": "Опционални параметри: {0}",
"languageName": "Македонски",
"setupDatabaseChooseDatabase": "Која датабаза би сакал да ја користиш?",
"setupDatabaseEmbeddedMariaDB": "Не треба ништо да поставувате. Оваа докер-слика автоматски ја вгради и конфигурираше MariaDB за вас. Uptime Kuma ќе се поврзе со оваа база на податоци преку уникс приклучок.",
"setupDatabaseSQLite": "Едноставна датотека со база на податоци, препорачана за распоредувања во мали размери. Пред верзијата 2.0.0, Uptime Kuma користеше SQLite како стандардна база на податоци.",
"settingUpDatabaseMSG": "Ја сетираме Датабазата за вас, ве молам почекајте.",
"New Update": "Ново ажурирање",
"Appearance": "Изглед",
"Primary Base URL": "Примарна основна URL",
"statusMaintenance": "Одржување",
"Cannot connect to the socket server": "Не може да се поврзе со сокет-серверот",
"General Monitor Type": "Општ тип на монитор",
"Passive Monitor Type": "Пасивен тип на монитор",
"markdownSupported": "Поддржана е синтакса Markdown",
"Pause": "Пауза",
"DateTime": "ДатаВреме",
"Delete": "Избриши",
"Uptime": "Време на работа",
"Response": "Одговор",
"Keyword": "Клучен збор",
"Friendly Name": "Пријателско Име",
"Host URL": "УРЛ адреса од сервер",
"locally configured mail transfer agent": "локално конфигуриран агент за пренос на пошта",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Или внесете го името на домаќинот на серверот на кој сакате да се поврзете или {localhost} ако имате намера да користите {local_mta}",
"timeoutAfter": "Истекување на времето по {0} секунди",
"Heartbeat Retry Interval": "Интервал на повторно обиди за отчукување на срцето",
"Resend Notification if Down X times consecutively": "Повторно испратете известување ако е долу X пати последователно",
"retriesDescription": "Максимално повторување пред услугата да биде означена како неискористена и да се испрати известување",
"maxRedirectDescription": "Максимален број пренасочувања што треба да се следат. Поставете на 0 за да ги оневозможите пренасочувањата.",
"needPushEvery": "Треба да ја повикувате оваа URL на секои {0} секунди."
}

View File

@ -135,7 +135,7 @@
"alertNoFile": "Selecteer een bestand om te importeren.",
"alertWrongFileType": "Selecteer een JSON-bestand.",
"Verify Token": "Controleer token",
"Setup 2FA": "2FA instellingen",
"Setup 2FA": "Stel 2FA in",
"Enable 2FA": "Schakel 2FA in",
"Disable 2FA": "Schakel 2FA uit",
"2FA Settings": "2FA-instellingen",
@ -411,7 +411,7 @@
"Retry": "Opnieuw",
"Topic": "Onderwerp",
"WeCom Bot Key": "WeCom Bot Key",
"Setup Proxy": "Proxy instellen",
"Setup Proxy": "Stel Proxy in",
"Proxy Protocol": "Proxy Protocol",
"Proxy Server": "Proxy Server",
"Proxy server has authentication": "Proxy server heeft authenticatie",
@ -535,7 +535,7 @@
"Connection Type": "Verbindingstype",
"Docker Daemon": "Docker Daemon",
"Trust Proxy": "Trust Proxy",
"Setup Docker Host": "Docker Host instellen",
"Setup Docker Host": "Stel Docker Host in",
"tcp": "TCP / HTTP",
"Optional": "Optioneel",
"socket": "Socket",
@ -804,7 +804,6 @@
"Reconnecting...": "Opnieuw verbinden...",
"Expected Value": "Verwachte waarde",
"Json Query": "Json zoekopdracht",
"jsonQueryDescription": "Voer een JSON-query uit op de respons en controleer de verwachte waarde (De retourwaarde wordt omgezet naar een string voor vergelijking). Bekijk {0} voor de documentatie over de querytaal. Een speelplaats is beschikbaar {1}.",
"pushViewCode": "Hoe gebruik je Push monitor?(View Code)",
"setupDatabaseChooseDatabase": "Welke database wil je gebruiken?",
"setupDatabaseEmbeddedMariaDB": "Je hoeft niks in te stellen. Dit docker image heeft een ingebouwde en geconfigureerde MariaDB instantie. Uptime Kuma verbindt met deze database via een unix socket.",
@ -855,7 +854,7 @@
"Check/Uncheck": "Vink/Ontvink",
"tailscalePingWarning": "Om de Tailscale Ping-monitor te kunnen gebruiken, moet u Uptime Kuma zonder Docker installeren en ook de Tailscale-client op uw server installeren.",
"selectedMonitorCount": "Geselecteerd: {0}",
"wayToGetFlashDutyKey": "Ga naar Kanaal -> (Kies een kanaal) -> Integraties -> Voeg een nieuwe integratie toe, voeg een 'Custom Event' toe om een push-adres te verkrijgen, kopieer de integratiesleutel in het adres-veld. Voor meer informatie, zie",
"wayToGetFlashDutyKey": "Ga naar Kanaal -> (Kies een kanaal) -> Integraties -> Voeg een nieuwe integratie toe, voeg een nieuwe 'Uptime Kuma' toe om een push-adres te verkrijgen, kopieer de integratiesleutel in het adres-veld. Voor meer informatie, zie",
"gamedigGuessPortDescription": "De poort die wordt gebruikt door het Valve Server Query Protocol kan verschillen van de clientpoort. Probeer dit als de monitor geen verbinding kan maken met je server.",
"authUserInactiveOrDeleted": "De gebruiker is inactief of verwijderd.",
"authInvalidToken": "Ongeldig token.",
@ -957,5 +956,40 @@
"Mentioning": "Vermelden",
"receiverSevenIO": "Nummer ontvangen",
"receiverInfoSevenIO": "Als het ontvangende nummer zich niet in Duitsland bevindt, moet u de landcode vóór het nummer zetten (bijvoorbeeld voor de landcode 1 uit de VS gebruikt u 117612121212 in plaats van 017612121212)",
"apiKeySevenIO": "SevenIO API Sleutel"
"apiKeySevenIO": "SevenIO API Sleutel",
"wayToGetThreemaGateway": "Je kunt je registreren voor Threema Gateway {0}.",
"threemaRecipient": "Ontvanger",
"threemaRecipientType": "Type ontvanger",
"threemaRecipientTypeIdentity": "Threema-ID",
"threemaRecipientTypeIdentityFormat": "8 Karakters",
"threemaRecipientTypePhone": "Telefoonnummer",
"threemaRecipientTypePhoneFormat": "E.164, zonder voorgaande +",
"threemaSenderIdentityFormat": "8 karakters, begint normaliter met een *",
"smspartnerPhoneNumber": "Telefoonnummer(s)",
"smspartnerSenderNameInfo": "Moet tussen 3..=11 reguliere karakters zijn",
"Bitrix24 Webhook URL": "Bitrix24 Webhook URL",
"wayToGetBitrix24Webhook": "Je kunt een webhook maken door de stappen bij {0} te volgen",
"bitrix24SupportUserID": "Voer je gebruikers ID van Bitrix25 in. Je kunt dit achterhalen uit de link naar je gebruikersprofiel.",
"apiKeysDisabledMsg": "API-Sleutels zijn uitgeschakeld omdat authenticatie niet is ingeschakeld.",
"smspartnerApiurl": "Je kunt je API-sleutel vinden in je dashboard bij {0}",
"smspartnerPhoneNumberHelptext": "Het nummer moet in het internationale format {0}, {1} zijn. Meerdere nummers moeten gescheiden zijn door {2}",
"Command": "Commando",
"mongodbCommandDescription": "Draai een MongoDB commando tegen de database. Voor meer informatie over beschikbare commando's, raadpleeg de {documentation}",
"threemaBasicModeInfo": "Notitie: Deze integratie gebruikt Threema Gateway in de basis modus (server gebaseerde versleuteling). Meer details vind je hier {0}.",
"Select message type": "Selecteer bericht type",
"Send to channel": "Stuur naar kanaal",
"Create new forum post": "Maak nieuw forum bericht",
"Refresh Interval": "Ververs interval",
"Refresh Interval Description": "De status pagina zal elke {0} seconden een volledige website verversing doen",
"ignoreTLSErrorGeneral": "Negeer TLS/SSL-fout voor verbinding",
"forumPostName": "Forum bericht naam",
"threadForumPostID": "Thread / Forum bericht ID",
"e.g. {discordThreadID}": "bijv. {discordThreadID}",
"whatHappensAtForumPost": "Maak een nieuw forum bericht. Dit stuurt GEEN berichten in bestaande forum berichten. Om naar een bestaand forum een nieuw bericht te sturen, gebruik \"{option}\"",
"postToExistingThread": "Plaats op bestaande thread / forum bericht",
"wayToGetDiscordThreadId": "Verkrijgen van een thread / forum bericht id is vergelijkbaar met het verkrijgen van een kanaal id. Lees meer over het verkrijgen van ids {0}",
"threemaRecipientTypeEmail": "E-mailadres",
"threemaSenderIdentity": "Gateway ID",
"threemaApiAuthenticationSecret": "Gateway ID Secret",
"smspartnerSenderName": "SMS afzender naam"
}

View File

@ -54,7 +54,7 @@
"Delete": "Usuń",
"Current": "Aktualny",
"Uptime": "Czas pracy",
"Cert Exp.": "Certyfikat wygasa",
"Cert Exp.": "Data ważności certyfikatu.",
"day": "dzień | dni",
"-day": "dni",
"hour": "godzina",
@ -793,7 +793,6 @@
"styleElapsedTime": "Czas, który upłynął pod paskiem bicia serca",
"tailscalePingWarning": "Aby korzystać z monitora Tailscale Ping, należy zainstalować Uptime Kuma bez Dockera, a także zainstalować klienta Tailscale na serwerze.",
"invertKeywordDescription": "Słowo kluczowe powinno być raczej nieobecne niż obecne.",
"jsonQueryDescription": "Wykonaj zapytanie json względem odpowiedzi i sprawdź oczekiwaną wartość (wartość zwracana zostanie przekonwertowana na ciąg znaków do porównania). Sprawdź {0}, aby uzyskać dokumentację dotyczącą języka zapytań. Plac zabaw można znaleźć {1}.",
"Server URL should not contain the nfty topic": "Adres URL serwera nie powinien zawierać tematu nfty",
"Badge Duration (in hours)": "Czas trwania odznaki (w godzinach)",
"Enter the list of brokers": "Wprowadź listę brokerów",
@ -801,7 +800,7 @@
"showCertificateExpiry": "Pokaż wygaśnięcie certyfikatu",
"gamedigGuessPortDescription": "Port używany przez Valve Server Query Protocol może różnić się od portu klienta. Spróbuj tego, jeśli monitor nie może połączyć się z serwerem.",
"Secret AccessKey": "Tajny klucz AccessKey",
"wayToGetFlashDutyKey": "Możesz przejść do Channel -> (Select a Channel) -> Integrations -> Add a new integration' page, dodać \"Custom Event\", aby uzyskać adres push, skopiować klucz integracji w adresie. Więcej informacji można znaleźć na stronie",
"wayToGetFlashDutyKey": "Możesz przejść do Channel -> (Select a Channel) -> Integrations -> Add a new integration' page, dodać \"Uptime Kuma\", aby uzyskać adres push, skopiować klucz integracji w adresie. Więcej informacji można znaleźć na stronie",
"Badge Down Color": "Kolor odznaki Offline",
"Notify Channel": "Powiadom kanał",
"Request Timeout": "Limit czasu żądania",
@ -843,7 +842,7 @@
"Json Query": "Zapytanie Json",
"enableNSCD": "Włącz NSCD (Name Service Cache Daemon) do buforowania wszystkich żądań DNS",
"Saved.": "Zapisano.",
"setupDatabaseChooseDatabase": "Której bazy danych chcesz użyć?",
"setupDatabaseChooseDatabase": "Której bazy danych chcesz używać?",
"setupDatabaseEmbeddedMariaDB": "Nie musisz niczego ustawiać. Ten obraz docker automatycznie osadził i skonfigurował MariaDB. Uptime Kuma połączy się z tą bazą danych za pośrednictwem gniazda Unix.",
"setupDatabaseMariaDB": "Połącz z zewnętrzną bazą danych MariaDB. Należy ustawić informacje o połączeniu z bazą danych.",
"setupDatabaseSQLite": "Prosty plik bazy danych, zalecany do wdrożeń na małą skalę. Przed wersją 2.0.0 Uptime Kuma używała SQLite jako domyślnej bazy danych.",
@ -922,7 +921,74 @@
"Mentioning": "Oznaczenia",
"Don't mention people": "Nie oznaczaj nikogo",
"Mention group": "Oznacz {group}",
"Channel access token (Long-lived)": "Token dostępu kanału (długotrwały)",
"Channel access token (Long-lived)": "Token dostępu do kanału (długotrwały)",
"Your User ID": "Twój identyfikator użytkownika",
"locally configured mail transfer agent": "lokalnie skonfigurowany serwer poczty"
"locally configured mail transfer agent": "lokalnie skonfigurowany serwer poczty",
"documentationOf": "{0} Dokumentacja",
"wayToGetHeiiOnCallDetails": "Jak uzyskać identyfikator wyzwalacza i klucze API wyjaśniono w {dokumentacji}",
"Select message type": "Wybierz typ wiadomości",
"Create new forum post": "Utwórz nowy post na forum",
"whatHappensAtForumPost": "Utwórz nowy post na forum. NIE powoduje to opublikowania wiadomości w istniejącym poście. Aby opublikować wiadomość w istniejącym poście, użyj \"{option}\"",
"callMeBotGet": "Tutaj możesz wygenerować punkt końcowy dla {0}, {1} i {2}. Należy pamiętać, że mogą wystąpić ograniczenia szybkości. Limity szybkości wydają się być następujące: {3}",
"Command": "Polecenie",
"mongodbCommandDescription": "Uruchom polecenie MongoDB względem bazy danych. Aby uzyskać informacje na temat dostępnych poleceń, sprawdź {documentation}",
"max 11 alphanumeric characters": "maksymalnie 11 znaków alfanumerycznych",
"Originator type": "Typ nadawcy",
"Alphanumeric (recommended)": "Alfanumeryczne (zalecane)",
"smspartnerApiurl": "Klucz API można znaleźć na pulpicie nawigacyjnym pod adresem {0}",
"smspartnerPhoneNumber": "Numer(y) telefonu(ów)",
"smspartnerPhoneNumberHelptext": "Numer musi być w międzynarodowym formacie {0}, {1}. Kilka numerów musi być oddzielonych znakiem {2}",
"smspartnerSenderName": "Nazwa nadawcy wiadomości SMS",
"smspartnerSenderNameInfo": "Musi zawierać między 3..=11 zwykłych znaków",
"Telephone number": "Nr telefonu",
"To Phone Number": "Na numer telefonu",
"Destination": "Miejsce docelowe",
"Bitrix24 Webhook URL": "Adres URL usługi Bitrix24 Webhook",
"wayToGetBitrix24Webhook": "Webhook można utworzyć, wykonując czynności opisane na stronie {0}",
"gtxMessagingToHint": "Format międzynarodowy, z początkowym \"+\" ({e164}, {e212} lub {e214})",
"wayToGetSevenIOApiKey": "Odwiedź pulpit nawigacyjny pod adresem app.seven.io > deweloper > klucz api > zielony przycisk dodawania",
"cellsyntOriginator": "Widoczny na telefonie komórkowym odbiorcy jako inicjator wiadomości. Dozwolone wartości i funkcja zależą od parametru originatortype.",
"cellsyntSplitLongMessages": "Dzielenie długich wiadomości na maksymalnie 6 części. 153 x 6 = 918 znaków.",
"max 15 digits": "maksymalnie 15 cyfr",
"bitrix24SupportUserID": "Wprowadź swój identyfikator użytkownika w Bitrix24. Identyfikator można znaleźć w linku, przechodząc do profilu użytkownika.",
"gtxMessagingApiKeyHint": "Klucz API można znaleźć na stronie: My Routing Accounts > Show Account Information > API Credentials > REST API (v2.x)",
"cellsyntOriginatortypeAlphanumeric": "Ciąg alfanumeryczny (maksymalnie 11 znaków alfanumerycznych). Odbiorcy nie mogą odpowiedzieć na wiadomość.",
"Send to channel": "Wyślij do kanału",
"postToExistingThread": "Opublikuj w istniejącym wątku / poście na forum",
"forumPostName": "Nazwa posta na forum",
"threadForumPostID": "Identyfikator wątku/postu na forum",
"e.g. {discordThreadID}": "np. {discordThreadID}",
"wayToGetDiscordThreadId": "Uzyskiwanie identyfikatora wątku / postu na forum jest podobne do uzyskiwania identyfikatora kanału. Przeczytaj więcej o tym, jak uzyskać identyfikatory {0}",
"cellsyntDestination": "Numer telefonu odbiorcy w formacie międzynarodowym z początkowym 00, po którym następuje numer kierunkowy kraju, np. 00447920110000 dla numeru w Wielkiej Brytanii 07920 110 000 (łącznie maksymalnie 17 cyfr). Maksymalnie 25000 odbiorców oddzielonych przecinkami na żądanie HTTP.",
"Allow Long SMS": "Zezwalaj na długie wiadomości SMS",
"Host URL": "Adres URL hosta",
"Refresh Interval": "Częstotliwość odświeżania",
"Refresh Interval Description": "Strona stanu będzie odświeżać całą witrynę co {0} sekund",
"ignoreTLSErrorGeneral": "Ignorowanie błędu TLS/SSL dla połączenia",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Wprowadź nazwę hosta serwera, z którym chcesz się połączyć lub {localhost}, jeśli zamierzasz użyć {local_mta}",
"senderSevenIO": "Wysyłany numer lub nazwa",
"receiverSevenIO": "Numer odbiorcy",
"receiverInfoSevenIO": "Jeśli numer odbiorczy nie znajduje się w Niemczech, należy dodać kod kraju przed numerem (np. dla kodu kraju 1 z USA należy użyć 117612121212 zamiast 017612121212)",
"apiKeySevenIO": "Klucz API SevenIO",
"wayToWriteWhapiRecipient": "Numer telefonu z prefiksem międzynarodowym, ale bez znaku plus na początku ({0}), identyfikator kontaktu ({1}) lub identyfikator grupy ({2}).",
"wayToGetWhapiUrlAndToken": "Adres URL API i token można uzyskać, przechodząc do żądanego kanału z {0}",
"Originator": "Nadawca",
"whapiRecipient": "Nr telefonu / ID kontaktu / ID grupy",
"API URL": "URL dla API",
"From Phone Number / Transmission Path Originating Address (TPOA)": "Od numeru telefonu / adresu początkowego ścieżki transmisji (TPOA)",
"gtxMessagingFromHint": "W telefonach komórkowych odbiorcy widzą TPOA jako nadawcę wiadomości. Dozwolone jest do 11 znaków alfanumerycznych, krótki kod, lokalny długi kod lub numery międzynarodowe ({e164}, {e212} lub {e214})",
"cellsyntOriginatortypeNumeric": "Wartość numeryczna (maks. 15 cyfr) z numerem telefonu w formacie międzynarodowym bez początkowego 00 (np. brytyjski numer 07920 110 000 powinien być ustawiony jako 447920110000). Odbiorcy mogą odpowiedzieć na wiadomość.",
"threemaRecipient": "Odbiorca",
"threemaRecipientType": "Typ odbiorcy",
"threemaRecipientTypeIdentity": "Threema ID",
"threemaRecipientTypeIdentityFormat": "8 znaków",
"threemaRecipientTypePhone": "Numer telefonu",
"threemaRecipientTypePhoneFormat": "E.164, bez znaku + na początku",
"threemaRecipientTypeEmail": "Adres e-mail",
"threemaSenderIdentity": "Gateway ID",
"threemaApiAuthenticationSecret": "Hasło Gateway ID",
"wayToGetThreemaGateway": "Możesz zarejestrować się w Threema Gateway {0}.",
"threemaSenderIdentityFormat": "8 znaków, zwykle zaczyna się od *",
"threemaBasicModeInfo": "Uwaga: Ta integracja korzysta z Threema Gateway w trybie podstawowym (szyfrowanie po stronie serwera). Więcej szczegółów można znaleźć {0}.",
"apiKeysDisabledMsg": "Klucze API są wyłączone, ponieważ wyłączone jest uwierzytelnianie."
}

View File

@ -308,7 +308,7 @@
"Notification Service": "Serviço De Notificação",
"default: notify all devices": "padrão: notificar todos os dispositivos",
"Trigger type:": "Tipo Do Acionamento:",
"Then choose an action, for example switch the scene to where an RGB light is red.": "Escolha uma ação, por exemplo, mudar o cenário onde uma luz RGB está vermelha.",
"Then choose an action, for example switch the scene to where an RGB light is red.": "Em seguida, escolha uma ação, por exemplo, mudar a cena para onde uma luz RGB fica vermelha.",
"Enable": "Habilitado",
"Disable": "Desabilitado",
"IconUrl": "URL Do Ícone",
@ -405,7 +405,7 @@
"Device Token": "Token Do Dispositivo",
"Retry": "Tentar Novamente",
"Topic": "Tópico",
"Setup Proxy": "Configuração Do Proxy",
"Setup Proxy": "Configuração do Proxy",
"Proxy Protocol": "Protocolo Do Proxy",
"Proxy Server": "Servidor Proxy",
"Proxy server has authentication": "O servidor proxy tem autenticação",
@ -580,7 +580,7 @@
"Post": "Post",
"Slug": "Apelido",
"The slug is already taken. Please choose another slug.": "Este apelido já está em uso. Por favor escolha outro apelido.",
"Setup Docker Host": "Configurar um Host Docker",
"Setup Docker Host": "Configurar um host Docker",
"trustProxyDescription": "Confiar nos cabeçalhos 'X-Forwarded-*'. Se você quer obter o endereço IP correto do cliente mas seu Uptime Kuma está atrás de um proxy como Nginx ou Apache, você deve habilitar isso.",
"Automations can optionally be triggered in Home Assistant:": "Automações podem ser acionadas opcionalmente no Home Assistant:",
"secureOptionNone": "Nenhum / STARTTLS (25, 587)",
@ -605,7 +605,6 @@
"wayToGetLineChannelToken": "Primeiro acesse o {0}, crie um provedor e um canal (API de Mensagens), então você pode obter o token de acesso do canal e o ID do usuário nos itens de menu mencionados acima.",
"aboutMattermostChannelName": "Você pode substituir o canal padrão para o qual o Webhook envia postagens, inserindo o nome do canal no campo \"Nome do Canal\". Isso precisa ser habilitado nas configurações do Webhook do Mattermost. Por exemplo: #outro-canal",
"invertKeywordDescription": "Procure pela palavra-chave estar ausente em vez de presente.",
"jsonQueryDescription": "Faça uma consulta JSON na resposta e verifique o valor esperado (o valor de retorno será convertido em uma string para comparação). Confira {0} para a documentação sobre a linguagem de consulta. Você pode encontrar um playground {1}.",
"octopushTypePremium": "Premium (Rápido - recomendado para alertas)",
"octopushTypeLowCost": "Baixo Custo (Lento - às vezes bloqueado pelo operador)",
"octopushSMSSender": "Nome do Remetente de SMS: 3-11 caracteres alfanuméricos e espaço (a-zA-Z0-9)",
@ -822,7 +821,7 @@
"emailTemplateHeartbeatJSON": "objeto que descreve o batimento cardíaco",
"emailTemplateMsg": "mensagem da notificação",
"emailTemplateLimitedToUpDownNotification": "disponível apenas para pulsações UP/DOWN, caso contrário, nulo",
"wayToGetFlashDutyKey": "Você pode ir para Canal -> (Selecionar um Canal) -> Integrações -> Adicionar uma nova integração', adicionar um 'Evento Personalizado' para obter um endereço de push, copiar a Chave de Integração no endereço. Para mais informações por favor visite",
"wayToGetFlashDutyKey": "Você pode ir em Canal -> (Selecionar um Canal) -> Integrações -> Adicionar uma nova integração, adicione um 'Uptime Kuma' para obter um endereço de push, copie a Chave de Integração no endereço. Para mais informações, visite",
"FlashDuty Severity": "Gravidade",
"templateMsg": "mensagem da notificação",
"templateHeartbeatJSON": "objeto que descreve o batimento cardíaco",
@ -846,7 +845,7 @@
"nostrSender": "Chave privada do remetente (nsec)",
"nostrRecipients": "Chaves Públicas dos Destinatários (npub)",
"GrafanaOncallUrl": "URL do Grafana Oncall",
"noDockerHostMsg": "Não disponível. Configure primeiro um Docker Host.",
"noDockerHostMsg": "Não disponível. Configure primeiro um Host Docker.",
"DockerHostRequired": "Defina o Docker Host para este monitor.",
"nostrRelaysHelp": "Um URL de retransmissão por linha",
"showCertificateExpiry": "Mostrar expiração do certificado",
@ -866,7 +865,7 @@
"successKeywordExplanation": "Palavra-chave MQTT que será considerada bem-sucedida",
"Add a new expiry notification day": "Adicione um novo dia de notificação de expiração",
"Remove the expiry notification": "Remova o dia de notificação de expiração",
"setup a new monitor group": "Configure um novo grupo de monitores",
"setup a new monitor group": "Configure um novo grupo de monitoramento",
"successKeyword": "Palavra-chave de Sucesso",
"Browser Screenshot": "Captura de tela do navegador",
"Remote Browsers": "Navegadores Remotos",
@ -913,5 +912,51 @@
"cellsyntDestination": "Número de telefone do destinatário em formato internacional com 00 inicial seguido do código do país, por ex. 00447920110000 para o número do Reino Unido 07920 110 000 (máximo de 17 dígitos no total). Máximo de 25.000 destinatários separados por vírgula por solicitação HTTP.",
"Your User ID": "Sua ID de usuário",
"gtxMessagingFromHint": "Em telefones celulares, seus destinatários veem o TPOA exibido como remetente da mensagem. São permitidos até 11 caracteres alfanuméricos, um DDD, o DDI local ou números internacionais ({e164}, {e212} ou {e214})",
"Channel access token (Long-lived)": "Token de acesso ao canal (de longa duração)"
"Channel access token (Long-lived)": "Token de acesso ao canal (de longa duração)",
"apiKeySevenIO": "SevenIO chave de API",
"wayToGetThreemaGateway": "Você pode se registrar no Threema Gateway {0}.",
"threemaRecipient": "Destinatário",
"threemaRecipientType": "Tipo de destinatário",
"threemaRecipientTypeIdentity": "Threema-ID",
"threemaRecipientTypeIdentityFormat": "8 caracteres",
"threemaRecipientTypePhone": "Número de telefone",
"threemaRecipientTypeEmail": "Endereço de email",
"threemaSenderIdentity": "ID do Gateway",
"threemaSenderIdentityFormat": "8 caracteres, geralmente começa com *",
"Command": "Comando",
"mongodbCommandDescription": "Execute um comando MongoDB no banco de dados. Para informações sobre os comandos disponíveis confira a {documentação}",
"smspartnerApiurl": "Você pode encontrar sua chave de API em seu painel em {0}",
"smspartnerPhoneNumber": "Números de telefone)",
"smspartnerPhoneNumberHelptext": "O número deve estar no formato internacional {0}, {1}. Vários números devem ser separados por {2}",
"smspartnerSenderName": "Nome do remetente de SMS",
"smspartnerSenderNameInfo": "Deve ter entre 3..=11 caracteres regulares",
"wayToGetBitrix24Webhook": "Você pode criar um webhook seguindo as etapas em {0}",
"Mentioning": "Mencionando",
"Don't mention people": "Não mencione pessoas",
"Mention group": "Mencionar {grupo}",
"senderSevenIO": "Enviando número ou nome",
"receiverSevenIO": "Número de recebimento",
"wayToGetSevenIOApiKey": "Visite o painel em app.seven.io > desenvolvedor > chave de API > botão verde adicionar",
"Select message type": "Selecione o tipo de mensagem",
"Send to channel": "Enviar para o canal",
"Create new forum post": "Criar nova postagem no fórum",
"threadForumPostID": "ID da postagem do tópico/fórum",
"postToExistingThread": "Postar em tópico/postagem existente",
"forumPostName": "Nome da postagem no fórum",
"Host URL": "Host URL",
"Refresh Interval": "Intervalo de atualização",
"Refresh Interval Description": "A página de status fará uma atualização completa do site a cada {0} segundos",
"locally configured mail transfer agent": "configurado de agente de transferência de e-mail localmente",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Insira o nome do host do servidor ao qual deseja se conectar ou {localhost} se pretende usar um {local_mta}",
"ignoreTLSErrorGeneral": "Ignorar erro TLS/SSL para conexão",
"threemaRecipientTypePhoneFormat": "E.164, sem o sinal de \"+\" no início",
"threemaApiAuthenticationSecret": "ID secreto do Gateway",
"threemaBasicModeInfo": "Observação: Esta integração usa o Threema Gateway no modo básico (criptografia baseada em servidor). Mais detalhes podem ser encontrados em {0}.",
"bitrix24SupportUserID": "Insira seu ID de usuário no Bitrix24. Você pode encontrar o ID no link ao acessar o perfil do usuário.",
"Bitrix24 Webhook URL": "URL do Webhook do Bitrix24",
"wayToGetDiscordThreadId": "Obter o ID de uma thread/postagem em um fórum é similar a obter o ID de um canal. Saiba mais sobre como obter IDs {0}",
"whatHappensAtForumPost": "Criar um novo tópico no fórum. Isto NÃO publica mensagens em tópicos existentes. Para publicar em um tópico existente, use \"{option}\"",
"e.g. {discordThreadID}": "Por exemplo {discordThreadID}",
"receiverInfoSevenIO": "Se o número de destino não estiver localizado na Alemanha, você deve adicionar o código do país antes do número (por exemplo, para o código de país 1 dos EUA, use 117612121212 em vez de 017612121212)",
"apiKeysDisabledMsg": "As chaves de API estão desativadas porque a autenticação está desativada."
}

View File

@ -76,7 +76,7 @@
"Accepted Status Codes": "Status Code Aceitáveis",
"Save": "Guardar",
"Notifications": "Notificações",
"Not available, please setup.": "Não disponível, por favor configura.",
"Not available, please setup.": "Não disponível, por favor configure.",
"Setup Notification": "Configurar Notificação",
"Light": "Claro",
"Dark": "Escuro",
@ -101,7 +101,7 @@
"disableauth.message2": "Isso é para {intendThirdPartyAuth} em frente ao 'UpTime Kuma' como o Cloudflare Access.",
"where you intend to implement third-party authentication": "alguém que tem autenticação de terceiros",
"Please use this option carefully!": "Por favor, utiliza esta opção com cuidado.",
"Logout": "Logout",
"Logout": "Terminar sessão",
"Leave": "Sair",
"I understand, please disable": "Eu entendo, por favor desativa.",
"Confirm": "Confirmar",
@ -110,7 +110,7 @@
"Username": "Utilizador",
"Password": "Senha",
"Remember me": "Lembra-me",
"Login": "Autenticar",
"Login": "Iniciar Sessão",
"No Monitors, please": "Nenhum monitor, por favor",
"add one": "adicionar um",
"Notification Type": "Tipo de Notificação",
@ -458,5 +458,20 @@
"Expected Value": "Valor Esperado",
"Json Query": "Consulta JSON",
"Cannot connect to the socket server": "Não é possível conectar ao servidor de sockets",
"Reconnecting...": "Reconectando..."
"Reconnecting...": "Reconectando...",
"liquidIntroduction": "A personalização das templates é conseguida através da linguagem de templates Liquid. Por favor consulte [0] para instruções de utilização. As variáveis disponíveis são :",
"pushViewCode": "Como usar o monitor Push? (Ver Código)",
"Host URL": "URL do Host",
"programmingLanguages": "Linguagens de Programação",
"locally configured mail transfer agent": "Agente de entrega de email local",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Entre o hostname do servidor ao qual se quer ligar ou a {localhost} se pretende usar {local_mta}",
"ignoreTLSErrorGeneral": "Ignorar erros TLS/SSL ao ligar",
"filterActive": "Ativo",
"filterActivePaused": "Em Pausa",
"Add New Tag": "Adicionar Nova Etiqueta",
"Search monitored sites": "Pesquisar sites monitorizados",
"templateMsg": "Mensagem da notificação",
"styleElapsedTimeShowNoLine": "Mostrar (Sem Linha)",
"styleElapsedTimeShowWithLine": "Mostrar (Com Linha)",
"statusPageRefreshIn": "Atualizar em: [0]"
}

View File

@ -36,17 +36,56 @@
"Add New Monitor": "Adicionar Novo Monitor",
"Home": "Home",
"Check Update On GitHub": "Verificar por Atualizações no GitHub",
"setupDatabaseChooseDatabase": "Qual banco de dados você deseja usar?",
"setupDatabaseChooseDatabase": "Qual banco de dados você gostaria de usar?",
"setupDatabaseEmbeddedMariaDB": "Não é necessario definir. Esta imagem do docker incorporou e configurou automaticamente o MariaDB para você. O Uptime Kuma se conectará a este banco de dados via soquete unix.",
"setupDatabaseMariaDB": "Conecte-se a um banco de dados MariaDB externo. Você precisa definir as informações de conexão do banco de dados.",
"setupDatabaseSQLite": "Um arquivo de banco de dados simples, recomendado para implantações em pequena escala. Antes da v2.0.0, o Uptime Kuma usava SQLite como banco de dados padrão.",
"dbName": "Nome do banco de dados",
"Monitor": "Monitorar",
"Monitor": "Monitoramento | Monitoramentos",
"hour": "hora",
"-hour": "-hora",
"Response": "Resposta",
"Ping": "Ping",
"-day": "-dia",
"Port": "Porta",
"Cannot connect to the socket server": "Não é possível conectar-se ao socket server"
"Cannot connect to the socket server": "Não é possível conectar-se ao socket server",
"URL": "URL",
"upsideDownModeDescription": "Inverter o status. Se o serviço estiver acessível, ele será considerado INATIVO.",
"settingUpDatabaseMSG": "Configurando o banco de dados. Isso pode levar algum tempo, por favor, seja paciente.",
"Passive Monitor Type": "Tipo de Monitoramento Passivo",
"Specific Monitor Type": "Tipo Específico de Monitoramento",
"markdownSupported": "Sintaxe Markdown suportada",
"DateTime": "Data e Hora",
"Cert Exp.": "Expiração do Certificado",
"Monitor Type": "Tipo de Monitoramento",
"Keyword": "Palavra-chave",
"Invert Keyword": "Inverter Palavra-chave",
"Expected Value": "Valor Esperado",
"Json Query": "Json Query",
"Friendly Name": "Nome Amigável",
"Hostname": "Hostname",
"Heartbeat Interval": "Intervalo de verificação",
"checkEverySecond": "Verificar a cada {0} segundos",
"Host URL": "URL do Host",
"retryCheckEverySecond": "Tentar novamente a cada {0} segundos",
"Accepted Status Codes": "Códigos de Status Aceitos",
"retriesDescription": "Número máximo de tentativas antes de o serviço ser marcado como inativo e uma notificação ser enviada",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Insira o nome do host do servidor ao qual você deseja se conectar ou {localhost} se você pretende usar um {local_mta}",
"Request Timeout": "Tempo limite de requisição",
"timeoutAfter": "Tempo limite após {0} segundos",
"Retries": "Tentativas",
"Heartbeat Retry Interval": "Intervalo entre novas verificações",
"Resend Notification if Down X times consecutively": "Reenviar notificação se houver X falhas consecutivas",
"Advanced": "Avançado",
"resendEveryXTimes": "Reenviar a cada {0} vezes",
"resendDisabled": "Reenvio desativado",
"ignoreTLSError": "Ignorar erros de TLS/SSL para sites HTTPS",
"maxRedirectDescription": "Número máximo de redirecionamentos a seguir. Defina como 0 para desabilitar redirecionamentos.",
"Upside Down Mode": "Modo Invertido",
"locally configured mail transfer agent": "agente de transferência de correio configurado localmente",
"ignoreTLSErrorGeneral": "Ignorar erro de TLS/SSL para conexão",
"Max. Redirects": "Máx. Redirecionamentos",
"General Monitor Type": "Tipo Geral de Monitoramento",
"needPushEvery": "Você deve chamar essa URL a cada {0} segundos.",
"pushOptionalParams": "Parâmetros opcionais: {0}"
}

View File

@ -55,7 +55,7 @@
"Save": "Salvează",
"Notifications": "Notificări",
"Not available, please setup.": "Indisponibil, trebuie configurat.",
"Setup Notification": "Configurare Notificări",
"Setup Notification": "Configurați notificarea",
"Light": "Luminos",
"Dark": "Întunecat",
"Auto": "Automat",
@ -265,7 +265,7 @@
"Connection String": "Șirul de conexiune",
"Query": "Interogare",
"settingsCertificateExpiry": "Expirarea certificatului TLS",
"Setup Docker Host": "Configurează Docker Host",
"Setup Docker Host": "Configurați Docker Host",
"Connection Type": "Tipul Conexiunii",
"Docker Daemon": "Docker Daemon",
"deleteDockerHostMsg": "Sigur doriți să ștergeți acest docker host pentru toate monitoarele?",
@ -481,7 +481,7 @@
"alertNoFile": "Vă rugăm să selectați un fișier de importat.",
"alertWrongFileType": "Vă rugăm să selectați un fișier JSON.",
"Clear all statistics": "Șterge toate Statisticile",
"Setup 2FA": "Configurează Autentificarea în Doi Pași",
"Setup 2FA": "Configurați Autentificarea în Doi Pași",
"Two Factor Authentication": "Autentificare în Doi Pași",
"Inactive": "Inactiv",
"Add New below or Select...": "Adăugați Nou mai jos sau selectați…",
@ -562,7 +562,7 @@
"wayToGetKookBotToken": "Creați o aplicație și obțineți tokenul dvs. robot la {0}",
"wayToGetKookGuildID": "Activați „Modul dezvoltator” în setarea Kook și faceți clic dreapta pe breaslă pentru a obține ID-ul acesteia",
"pushoverDesc1": "Prioritate de urgență (2) are o pauză implicită de 30 de secunde între reîncercări și expiră după o oră.",
"Setup Proxy": "Configurare Proxy",
"Setup Proxy": "Configurați proxy",
"Proxy Protocol": "Protocol Proxy",
"For safety, must use secret key": "Pentru siguranță, trebuie să utilizați cheia secretă",
"promosmsTypeFlash": "SMS FLASH - Mesajul va fi afișat automat pe dispozitivul destinatarului. Valabil doar către destinatarii din Polonia.",
@ -621,7 +621,7 @@
"successKeywordExplanation": "Cuvântul cheie MQTT care va fi considerat succes",
"successKeyword": "Cuvânt Cheie Succes",
"pushViewCode": "Cum se utilizează monitorul Push? (Vizualizare cod)",
"setupDatabaseChooseDatabase": "Ce bază de date dori să utilizați?",
"setupDatabaseChooseDatabase": "Ce bază de date ați dori să utilizați?",
"setupDatabaseMariaDB": "Conectați-vă la o bază de date externă MariaDB. Trebuie să setați informațiile de conectare la baza de date.",
"setupDatabaseSQLite": "Un fișier de bază de date simplu, recomandat pentru implementări la scară mică. Înainte de v2.0.0, Uptime Kuma folosea SQLite ca bază de date implicită.",
"dbName": "Numele bazei de date",
@ -689,7 +689,6 @@
"emailTemplateLimitedToUpDownNotification": "disponibil numai pentru heartbeat-uri UP/DOWN, altfel nul",
"emailTemplateStatus": "Stare",
"invertKeywordDescription": "Căutați după cuvântul cheie să fie absent și nu prezent.",
"jsonQueryDescription": "Efectuați o interogare json după răspuns și verificați valoarea așteptată (valoarea returnată va fi convertită în șir pentru comparație). Consultați {0} pentru documentația despre limbajul de interogare. Un playground poate fi găsit {1}.",
"goAlertInfo": "GoAlert este o aplicație open source pentru programarea apelurilor, escalări automate și notificări (cum ar fi SMS-uri sau apeluri vocale). Angajați automat persoana potrivită, în modul potrivit și la momentul potrivit! {0}",
"goAlertIntegrationKeyInfo": "Obțineți cheia generică de integrare API pentru serviciu în formatul \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\" de obicei valoarea parametrului token al URL-ului copiat.",
"SecretAccessKey": "Secret AccessKey",
@ -807,7 +806,7 @@
"Badge Warn Days": "Badge zile de avertizare",
"monitorToastMessagesDescription": "Notificările toast pentru monitoare dispar după un anumit timp în secunde. Setat la -1, dezactivează timpul de expirare. Setat la 0, dezactivează notificările toast.",
"noGroupMonitorMsg": "Nu este disponibil. Creați mai întâi un grup de monitoare.",
"wayToGetFlashDutyKey": "Puteți merge la Canal -> (Selectați un canal) -> Integrari -> Adăugați o nouă pagină de integrare, adăugați un \"Eveniment personalizat\" pentru a obține o adresă push, copiați cheia de integrare în adresă. Pentru mai multe informatii va rugam vizitati",
"wayToGetFlashDutyKey": "Puteți merge la Canal -> (Selectați un canal) -> Integrari -> Adăugați o nouă pagină de integrare, adăugați \"Uptime Kuma\" pentru a obține o adresă push, copiați cheia de integrare în adresă. Pentru mai multe informatii va rugam vizitati",
"remoteBrowsersDescription": "Browserele Remote sunt o alternativă la rularea locală a Chromium. Configurați cu un serviciu precum browserless.io sau conectați-vă la cel personal",
"Remote Browsers": "Browsere Remote",
"Remote Browser": "Browser Remote",
@ -945,5 +944,40 @@
"senderSevenIO": "Numărul sau numele expeditorului",
"receiverSevenIO": "Număr de primire",
"receiverInfoSevenIO": "Dacă numărul de destinație nu se află în Germania, trebuie să adăugați codul de țară în fața numărului (de exemplu, pentru codul de țară 1 din SUA utilizați 117612121212 în loc de 017612121212)",
"apiKeySevenIO": "Cheia API SevenIO"
"apiKeySevenIO": "Cheia API SevenIO",
"Command": "Comanda",
"smspartnerSenderName": "Numele expeditorului SMS",
"smspartnerSenderNameInfo": "Trebuie să aibă între 3..=11 caractere obișnuite",
"mongodbCommandDescription": "Rulați o comandă MongoDB în baza de date. Pentru informații despre comenzile disponibile, consultați {documentația}",
"Bitrix24 Webhook URL": "URL Bitrix24 Webhook",
"bitrix24SupportUserID": "Introduceți ID-ul dvs. de utilizator în Bitrix24. Puteți afla ID-ul din link accesând profilul utilizatorului.",
"smspartnerApiurl": "Puteți găsi cheia dvs. API în tabloul de bord la {0}",
"smspartnerPhoneNumber": "Număr(numere) de telefon",
"smspartnerPhoneNumberHelptext": "Numărul trebuie să fie în format internațional {0}, {1}. Numerele multiple trebuie separate prin {2}",
"wayToGetBitrix24Webhook": "Puteți crea un webhook urmând pașii de la {0}",
"Select message type": "Selectați tipul mesajului",
"Send to channel": "Trimite pe canal",
"Create new forum post": "Creați o nouă postare pe forum",
"postToExistingThread": "Postați în firul de discuție/postul de forum existent",
"forumPostName": "Numele postării pe forum",
"wayToGetDiscordThreadId": "Obținerea unui subiect / ID postare forum este similară cu obținerea unui ID de canal. Citiți mai multe despre cum să obțineți ID-uri {0}",
"threadForumPostID": "Subiect / ID postare forum",
"e.g. {discordThreadID}": "ex. {discordThreadID}",
"whatHappensAtForumPost": "Creați o nouă postare pe forum. Acest lucru NU postează mesaje în postarea existentă. Pentru a posta în postarea existentă, utilizați „{option}”",
"Refresh Interval": "Interval de reîmprospătare",
"Refresh Interval Description": "Pagina de status va efectua o reîmprospătare completă a site-ului la fiecare {0} secunde",
"ignoreTLSErrorGeneral": "Ignorați eroarea TLS/SSL pentru conexiune",
"threemaRecipient": "Destinatar",
"threemaRecipientType": "Tip de destinatar",
"threemaRecipientTypeIdentity": "ID Threema",
"threemaRecipientTypeIdentityFormat": "8 caractere",
"threemaRecipientTypePhone": "Număr de telefon",
"threemaRecipientTypePhoneFormat": "E.164, fără prefixul +",
"threemaRecipientTypeEmail": "Adresa de e-mail",
"threemaSenderIdentity": "ID Gateway",
"threemaApiAuthenticationSecret": "Secret ID Gateway",
"wayToGetThreemaGateway": "Vă puteți înregistra pentru Threema Gateway {0}.",
"threemaSenderIdentityFormat": "8 caractere, de obicei începe cu *",
"threemaBasicModeInfo": "Notă: Această integrare utilizează Threema Gateway în modul de bază (criptare bazată pe server). Mai multe detalii pot fi găsite {0}.",
"apiKeysDisabledMsg": "Cheile API sunt dezactivate deoarece autentificarea este dezactivată."
}

View File

@ -3,7 +3,7 @@
"checkEverySecond": "Проверка каждые {0} секунд",
"retriesDescription": "Максимальное количество попыток перед пометкой сервиса, как недоступного, и отправкой уведомления",
"ignoreTLSError": "Игнорировать ошибки TLS/SSL для HTTPS сайтов",
"upsideDownModeDescription": зменить статус сервиса на РАБОТАЕТ если он доступен, а помечается как НЕ РАБОТАЕТ.",
"upsideDownModeDescription": нверсия статуса. Если сервис доступен, он будет отмечен как недоступный.",
"maxRedirectDescription": "Максимальное количество перенаправлений. Поставьте 0, чтобы отключить перенаправления.",
"acceptedStatusCodesDescription": "Выберите коды статусов для определения доступности сервиса.",
"passwordNotMatchMsg": "Введённые пароли не совпадают.",
@ -17,19 +17,19 @@
"pauseMonitorMsg": "Вы действительно хотите приостановить?",
"Settings": "Настройки",
"Dashboard": "Панель управления",
"New Update": "Есть обновление",
"New Update": "Новое обновление",
"Language": "Язык",
"Appearance": "Внешний вид",
"Theme": "Тема",
"General": "Общее",
"Version": "Версия",
"Check Update On GitHub": "Проверить обновления в GitHub",
"Check Update On GitHub": "Проверить наличие обновления в GitHub",
"List": "Список",
"Add": "Добавить",
"Add New Monitor": "Добавить Новый Монитор",
"Add New Monitor": "Добавить Новый Сенсор",
"Quick Stats": "Статистика",
"Up": "Работает",
"Down": "Не работает",
"Up": "Доступен",
"Down": "Не доступен",
"Pending": "В ожидании",
"Unknown": "Неизвестно",
"Pause": "Пауза",
@ -59,22 +59,22 @@
"Heartbeat Interval": "Частота опроса",
"Retries": "Попыток",
"Advanced": "Дополнительно",
"Upside Down Mode": "Режим смены статуса",
"Upside Down Mode": "Режим инверсии статуса",
"Max. Redirects": "Макс. количество перенаправлений",
"Accepted Status Codes": "Допустимые коды статуса",
"Save": "Сохранить",
"Notifications": "Уведомления",
"Not available, please setup.": "Уведомления не доступны, требуется настройка.",
"Setup Notification": "Настроить уведомление",
"Setup Notification": "Настройка уведомления",
"Light": "Светлая",
"Dark": "Тёмная",
"Auto": "Как в системе",
"Theme - Heartbeat Bar": "Тема - Полосы частоты опроса",
"Theme - Heartbeat Bar": "Полоса частоты опроса",
"Normal": "Обычный",
"Bottom": "Внизу",
"None": "Отсутствует",
"Timezone": "Часовой пояс TZ",
"Search Engine Visibility": "Видимость в поисковых системах",
"Search Engine Visibility": "Индексация поисковыми системами",
"Allow indexing": "Разрешить индексирование",
"Discourage search engines from indexing site": "Запретить индексирование",
"Change Password": "Изменить пароль",
@ -88,7 +88,7 @@
"disable authentication": "отключить авторизацию",
"disableauth.message2": "Это подходит для {intendThirdPartyAuth} перед открытием Uptime Kuma, такие как Cloudflare Access, Authelia или другие.",
"where you intend to implement third-party authentication": "тех, у кого настроена сторонняя система авторизации",
"Please use this option carefully!": "Пожалуйста, используйте эту настройку с осторожностью!",
"Please use this option carefully!": "Пожалуйста, используйте с осторожностью!",
"Logout": "Выйти",
"Leave": "Оставить",
"I understand, please disable": "Я понимаю, всё равно отключить",
@ -150,9 +150,9 @@
"retryCheckEverySecond": "Повторять каждые {0} секунд",
"importHandleDescription": "Выберите \"Пропустить существующие\", если вы хотите пропустить каждый монитор или уведомление с таким же именем. \"Перезаписать\" удалит каждый существующий монитор или уведомление и добавит заново. Вариант \"Не проверять\" принудительно восстанавливает все мониторы и уведомления, даже если они уже существуют.",
"confirmImportMsg": "Вы действительно хотите восстановить резервную копию? Убедитесь, что вы выбрали подходящий вариант импорта.",
"Heartbeat Retry Interval": "Интервал повтора опроса",
"Import Backup": "Загрузить Backup",
"Export Backup": "Скачать Backup",
"Heartbeat Retry Interval": "Интервал повтора запроса",
"Import Backup": "Импорт резервной копии",
"Export Backup": "Скачать резервную копию",
"Skip existing": "Пропустить существующие",
"Overwrite": "Перезаписать",
"Options": "Опции",
@ -175,14 +175,14 @@
"Avg. Ping": "Средний пинг",
"Avg. Response": "Средний отклик",
"Entry Page": "Главная",
"statusPageNothing": "Ничего нет, добавьте группу или монитор.",
"statusPageNothing": "Тут ничего нет, добавьте группу или монитор.",
"No Services": "Нет Сервисов",
"All Systems Operational": "Все системы работают",
"Partially Degraded Service": "Частичная работа сервисов",
"Degraded Service": "Отказ всех сервисов",
"Add Group": "Добавить Группу",
"Add a monitor": "Добавить монитор",
"Edit Status Page": "Редактировать страницу статусов",
"Edit Status Page": "Редактировать Страницу Статусов",
"Go to Dashboard": "В Панель Управления",
"Status Page": "Страница статуса",
"Status Pages": "Страницы статуса",
@ -209,9 +209,9 @@
"line": "Line Messenger",
"mattermost": "Mattermost",
"Primary Base URL": "Основной URL",
"Push URL": "URL-ссылка пуш уведомлений",
"Push URL": "URL-ссылка push уведомлений",
"needPushEvery": "К этому URL необходимо обращаться каждые {0} секунд.",
"pushOptionalParams": "Необязательные параметры: {0}",
"pushOptionalParams": "Опциональные параметры: {0}",
"defaultNotificationName": "Уведомления {notification} ({number})",
"here": "здесь",
"Required": "Обязательно",
@ -490,7 +490,7 @@
"Octopush API Version": "Версия API Octopush",
"Legacy Octopush-DM": "устаревший Octopush-DM",
"endpoint": "конечная точка",
"octopushAPIKey": "\"{API key}\" из учетных данных HTTP API в панели управления",
"octopushAPIKey": "\"API key\" из учетных данных HTTP API в панели управления",
"octopushLogin": "\"Login\" из учетных данных HTTP API в панели управления",
"promosmsLogin": "Логин API",
"promosmsPassword": "Пароль API",
@ -534,7 +534,7 @@
"Query": "Запрос",
"settingsCertificateExpiry": "Истекание TLS сертификата",
"certificationExpiryDescription": "HTTPS Мониторы инициируют уведомление, когда срок действия сертификата TLS истечет:",
"Setup Docker Host": "Настроить Docker Host",
"Setup Docker Host": "Настройка хоста Docker",
"Connection Type": "Тип соединения",
"Docker Daemon": "Демон Docker",
"deleteDockerHostMsg": "Вы уверены, что хотите удалить этот узел docker для всех мониторов?",
@ -589,18 +589,18 @@
"recurringIntervalMessage": "Запускать 1 раз каждый день | Запускать 1 раз каждые {0} дней",
"error": "ошибка",
"statusMaintenance": "Техобслуживание",
"Affected Monitors": "Задействованные Мониторы",
"Affected Monitors": "Затронутые мониторы",
"Start of maintenance": "Начало техобслуживания",
"All Status Pages": "Все страницы статусов",
"Select status pages...": "Выберите страницу статуса…",
"resendEveryXTimes": ереотправлять каждые {0} раз",
"resendDisabled": ереотправка отключена",
"resendEveryXTimes": овтор каждые {0} раз",
"resendDisabled": овторная отправка отключена",
"deleteMaintenanceMsg": "Вы действительно хотите удалить это техобслуживание?",
"critical": "критично",
"Custom Monitor Type": "Собственный тип монитора",
"markdownSupported": "Поддерживает синтаксис Markdown",
"Passive Monitor Type": "Пассивный Тип Монитора",
"Specific Monitor Type": "Специфичный Тип Монитора",
"Specific Monitor Type": "Специфический Тип Монитора",
"Help": "Помощь",
"Game": "Игра",
"Resend Notification if Down X times consequently": "Повторно отправить уведомление, если не работает X раз подряд",
@ -611,7 +611,7 @@
"weekdayShortSat": "Сб",
"weekdayShortSun": "Вс",
"dayOfMonth": "День месяца",
"Pick Affected Monitors...": "Выберите Задействованные Мониторы…",
"Pick Affected Monitors...": "Выберите затронутые мониторы…",
"Custom": "Свой цвет",
"successMessage": "Сообщение об успехе",
"successMessageExplanation": "Сообщение MQTT, которое может рассматриваться как успешное",
@ -690,7 +690,7 @@
"Guild ID": "Идентификатор гильдии",
"Kook": "Kook",
"wayToGetKookBotToken": "Создайте приложение и получите токен бота по адресу {0}",
"Resend Notification if Down X times consecutively": "Повторная отправка уведомления при отключении несколько раз",
"Resend Notification if Down X times consecutively": "Повторная отправка уведомления при неудачном запросе X раз",
"telegramProtectContent": "Запретить пересылку/сохранение",
"telegramProtectContentDescription": "Если включено, сообщения бота в Telegram будут запрещены для пересылки и сохранения.",
"telegramSendSilently": "Отправить без звука",
@ -741,7 +741,7 @@
"wayToGetPagerDutyKey": "Вы можете это получить, перейдя в Сервис -> Каталог сервисов -> (Выберите сервис) -> Интеграции -> Добавить интеграцию. Здесь вы можете искать «Events API V2». Подробнее {0}",
"apiKeyAddedMsg": "Ваш ключ API добавлен. Пожалуйста, обратите внимание на это сообщение, так как оно отображается один раз.",
"deleteAPIKeyMsg": "Вы уверены, что хотите удалить этот ключ API?",
"wayToGetPagerTreeIntegrationURL": "После создания интеграции Uptime Kuma в PagerTree скопируйте файл {Endpoint}. См. полную информацию {0}",
"wayToGetPagerTreeIntegrationURL": "После создания интеграции Uptime Kuma в PagerTree скопируйте файл Endpoint. См. полную информацию {0}",
"telegramMessageThreadIDDescription": "Необязательный уникальный идентификатор для цепочки сообщений (темы) форума; только для форумов-супергрупп",
"grpcMethodDescription": "Имя метода преобразуется в формат camelCase, например, sayHello, check и т. д.",
"Proto Service Name": "Название службы Proto",
@ -812,7 +812,6 @@
"AccessKey Id": "AccessKey Id",
"Secret AccessKey": "Секретный ключ доступа",
"Session Token": "Токен сессии",
"jsonQueryDescription": "Выполните json-запрос к ответу и проверьте наличие ожидаемого значения (возвращаемое значение будет преобразовано в строку для сравнения). Посмотрите {0} для получения документации по языку запросов. A Потренироваться вы можете {1}.",
"Notify Channel": "Канал оповещений",
"aboutNotifyChannel": "Уведомление о канале вызовет настольное или мобильное уведомление для всех участников канала, независимо от того, установлена ли их доступность как активная или отсутствующая.",
"Enter the list of brokers": "Введите список брокеров",
@ -852,10 +851,10 @@
"nostrRelaysHelp": "Один URL-адрес ретрансляции в каждой строке",
"enableNSCD": "Включить NSCD (Name Service Cache Daemon) для кэширования всех DNS-запросов",
"Saved.": "Сохранено",
"setupDatabaseChooseDatabase": "Какую базу данных Вы хотели бы использовать?",
"setupDatabaseEmbeddedMariaDB": "Вам не нужно ничего настраивать. В этот Docker образ автоматически встроена и настроена MariaDB. Uptime Kuma будет подключаться к этой базе данных через unix-socket.",
"setupDatabaseChooseDatabase": "Какую базу данных Вы бы хотели использовать?",
"setupDatabaseEmbeddedMariaDB": "Вам не нужно ничего настраивать. В этот докер-образ автоматически встроена и настроена MariaDB. Uptime Kuma будет подключаться к этой базе данных через unix-сокет.",
"setupDatabaseSQLite": "Простой файл базы данных, рекомендуемый для небольших развертываний. До версии 2.0.0 Uptime Kuma использовал SQLite в качестве базы данных по умолчанию.",
"setupDatabaseMariaDB": "Подключитесь к внешней базе данных MariaDB. Вам необходимо задать информацию о подключении к базе данных.",
"setupDatabaseMariaDB": "Подключитесь к внешней базе данных MariaDB. Необходимо задать информацию о подключении к базе данных.",
"dbName": "Имя базы данных",
"pushViewCode": "Как использовать монитор Push? (Посмотреть код)",
"programmingLanguages": "Языки программирования",
@ -932,7 +931,7 @@
"Your User ID": "Ваш идентификатор пользователя",
"Host URL": "URL Хоста",
"locally configured mail transfer agent": "Настроенный локально агент передачи почты",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Введите {Hostname} сервера, к которому вы хотите подключиться, либо {localhost}, если вы собираетесь использовать {local_mta}.",
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Введите {Hostname} сервера, к которому вы хотите подключиться, либо {localhost}, если вы собираетесь использовать {local_mta}",
"wayToGetHeiiOnCallDetails": "Как получить ID триггера и {API Keys}, рассказывается в {documentation}",
"gtxMessagingApiKeyHint": "Вы можете найти свой {API key} на странице: Мои учетные записи маршрутизации > Показать информацию об учетной записи > Учетные данные API > REST API (v2.x)",
"From Phone Number / Transmission Path Originating Address (TPOA)": "Номер телефона / Адрес источника пути передачи (АИПП)",
@ -965,5 +964,13 @@
"Destination": "Назначение",
"Allow Long SMS": "Разрешить длинные SMS",
"max 15 digits": "макс. 15 цифр",
"max 11 alphanumeric characters": "максимум 11 буквенно-цифровых символов"
"max 11 alphanumeric characters": "максимум 11 буквенно-цифровых символов",
"Command": "Команда",
"Create new forum post": "Создать новый пост",
"forumPostName": "Название поста",
"postToExistingThread": "Создать пост в этой ветке",
"Select message type": "Выберите тип сообщения",
"Send to channel": "Отправить в канал",
"Refresh Interval": "Интервал обновления",
"ignoreTLSErrorGeneral": "Игнорировать ошибки TLS/SSL для подключения"
}

Some files were not shown because too many files have changed in this diff Show More