Merge branch 'master' into feature/locale_on_status_page

pull/3523/head
Wampie Driessen 7 months ago
commit aff6a5bf7f

@ -6,7 +6,7 @@ You can modifiy Uptime Kuma in your browser without setting up a local developme
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
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)

@ -30,7 +30,6 @@ SECURITY.md
tsconfig.json
.env
/tmp
/babel.config.js
/ecosystem.config.js
/extra/healthcheck.exe
/extra/healthcheck
@ -38,6 +37,10 @@ tsconfig.json
/extra/push-examples
/extra/uptime-kuma-push
# Comment the following line if you want to rebuild the healthcheck binary
/extra/healthcheck-armv7
### .gitignore content (commented rules are duplicated)
#node_modules

@ -19,12 +19,13 @@ module.exports = {
],
parser: "vue-eslint-parser",
parserOptions: {
parser: "@babel/eslint-parser",
parser: "@typescript-eslint/parser",
sourceType: "module",
requireConfigFile: false,
},
plugins: [
"jsdoc"
"jsdoc",
"@typescript-eslint",
],
rules: {
"yoda": "error",
@ -163,6 +164,22 @@ module.exports = {
context: true,
jestPuppeteer: true,
},
},
// Override for TypeScript
{
"files": [
"**/*.ts",
],
extends: [
"plugin:@typescript-eslint/recommended",
],
"rules": {
"jsdoc/require-returns-type": "off",
"jsdoc/require-param-type": "off",
"@typescript-eslint/no-explicit-any": "off",
"prefer-const": "off",
}
}
]
};

@ -12,8 +12,6 @@ labels:
DO NOT PROVIDE ANY DETAILS HERE. Please privately report to https://github.com/louislam/uptime-kuma/security/advisories/new.
Why need this issue? It is because GitHub Advisory do not send a notification to @louislam, it is a workaround to do so.
Your GitHub Advisory URL:

@ -1,7 +1,7 @@
⚠️⚠️⚠️ Since we do not accept all types of pull requests and do not want to waste your time. Please be sure that you have read pull request rules:
https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md#can-i-create-a-pull-request-for-uptime-kuma
Tick the checkbox if you understand [x]:
Tick the checkbox if you understand [x]:
- [ ] I have read and understand the pull request rules.
# Description

@ -5,11 +5,11 @@ name: Auto Test
on:
push:
branches: [ master ]
branches: [ master, 1.23.X ]
paths-ignore:
- '*.md'
pull_request:
branches: [ master, 2.0.X ]
branches: [ master, 1.23.X ]
paths-ignore:
- '*.md'

@ -34,24 +34,27 @@ Yes or no, it depends on what you will try to do. Since I don't want to waste yo
Here are some references:
### ✅ Usually accepted:
### ✅ Usually accepted
- Bug fix
- Security fix
- Adding notification providers
- Adding new language files (see [these instructions](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md))
- Adding new language keys: `$t("...")`
### ⚠️ Discussion required:
### ⚠️ Discussion required
- Large pull requests
- New features
### ❌ Won't be merged:
### ❌ Won't be merged
- A dedicated PR for translating existing languages (see [these instructions](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md))
- Do not pass the auto-test
- Any breaking changes
- Duplicated pull requests
- Buggy
- UI/UX is not close to Uptime Kuma
- UI/UX is not close to Uptime Kuma
- Modifications or deletions of existing logic without a valid reason.
- Adding functions that is completely out of scope
- Converting existing code into other programming languages
@ -65,7 +68,6 @@ I will assign your pull request to a [milestone](https://github.com/louislam/upt
Also, please don't rush or ask for an ETA, because I have to understand the pull request, make sure it is no breaking changes and stick to my vision of this project, especially for large pull requests.
### Recommended Pull Request Guideline
Before deep into coding, discussion first is preferred. Creating an empty pull request for discussion would be recommended.
@ -114,7 +116,7 @@ I personally do not like something that requires so many configurations before y
### GitHub Codespace
If you don't want to setup an local environment, you can now develop on GitHub Codespace, read more:
If you don't want to setup an local environment, you can now develop on GitHub Codespace, read more:
https://github.com/louislam/uptime-kuma/tree/master/.devcontainer
@ -143,7 +145,8 @@ npm run dev
```
But sometimes, you would like to restart the server, but not the frontend, you can run these commands in two terminals:
```
```bash
npm run start-frontend-dev
npm run start-server-dev
```
@ -152,15 +155,14 @@ npm run start-server-dev
It binds to `0.0.0.0:3001` by default.
It is mainly a socket.io app + express.js.
express.js is used for:
express.js is used for:
- entry point such as redirecting to a status page or the dashboard
- serving the frontend built files (index.html, .js and .css etc.)
- serving internal APIs of the status page
### Structure in /server/
- jobs/ (Jobs that are running in another process)
@ -175,9 +177,9 @@ express.js is used for:
## Frontend Dev Server
It binds to `0.0.0.0:3000` by default. The frontend dev server is used for development only.
It binds to `0.0.0.0:3000` by default. The frontend dev server is used for development only.
For production, it is not used. It will be compiled to `dist` directory instead.
For production, it is not used. It will be compiled to `dist` directory instead.
You can use Vue.js devtools Chrome extension for debugging.
@ -231,7 +233,7 @@ If for security / bug / other reasons, a library must be updated, breaking chang
Please add **all** the strings which are translatable to `src/lang/en.json` (If translation keys are omitted, they can not be translated).
**Don't include any other languages in your initial Pull-Request** (even if this is your mother tongue), to avoid merge-conflicts between weblate and `master`.
**Don't include any other languages in your initial Pull-Request** (even if this is your mother tongue), to avoid merge-conflicts between weblate and `master`.
The translations can then (after merging a PR into `master`) be translated by awesome people donating their language skills.
If you want to help by translating Uptime Kuma into your language, please visit the [instructions on how to translate using weblate](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md).
@ -249,7 +251,7 @@ https://github.com/louislam/uptime-kuma-wiki
## Docker
#### Arch
### Arch
- amd64
- arm64
@ -293,12 +295,12 @@ https://github.com/louislam/uptime-kuma/issues?q=sort%3Aupdated-desc
1. Draft a release note
2. Make sure the repo is cleared
3. If the healthcheck is updated, remember to re-compile it: `npm run build-docker-builder-go`
3. `npm run release-final` with env vars: `VERSION` and `GITHUB_TOKEN`
4. Wait until the `Press any key to continue`
5. `git push`
6. Publish the release note as 1.X.X
7. Press any key to continue
8. Deploy to the demo server: `npm run deploy-demo-server`
4. `npm run release-final` with env vars: `VERSION` and `GITHUB_TOKEN`
5. Wait until the `Press any key to continue`
6. `git push`
7. Publish the release note as 1.X.X
8. Press any key to continue
9. Deploy to the demo server: `npm run deploy-demo-server`
Checking:
@ -336,6 +338,6 @@ git push production master
Change the base of a pull request such as `master` to `1.23.X`
```
```bash
git rebase --onto <new parent> <old parent>
```

@ -23,17 +23,17 @@ It is a temporary live demo, all data will be deleted after 10 minutes. Use the
## ⭐ Features
* Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers
* Fancy, Reactive, Fast UI/UX
* Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications)
* 20-second intervals
* [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/lang)
* Multiple status pages
* Map status pages to specific domains
* Ping chart
* Certificate info
* Proxy support
* 2FA support
- Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers
- Fancy, Reactive, Fast UI/UX
- Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications)
- 20-second intervals
- [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/lang)
- Multiple status pages
- Map status pages to specific domains
- Ping chart
- Certificate info
- Proxy support
- 2FA support
## 🔧 How to Install
@ -43,19 +43,21 @@ It is a temporary live demo, all data will be deleted after 10 minutes. Use the
docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:1
```
⚠️ Please use a **local volume** only. Other types such as NFS are not supported.
Uptime Kuma is now running on http://localhost:3001
> [!WARNING]
> **NFS** (Network File System) are **NOT** supported. Please map to a local directory or volume.
### 💪🏻 Non-Docker
Requirements:
- Platform
- ✅ Major Linux distros such as Debian, Ubuntu, CentOS, Fedora and ArchLinux etc.
- ✅ Windows 10 (x64), Windows Server 2012 R2 (x64) or higher
- ❌ Replit / Heroku
- [Node.js](https://nodejs.org/en/download/) 14 / 16 / 18 / 20.4
- [npm](https://docs.npmjs.com/cli/) >= 7
- [npm](https://docs.npmjs.com/cli/) 9
- [Git](https://git-scm.com/downloads)
- [pm2](https://pm2.keymetrics.io/) - For running Uptime Kuma in the background
@ -76,9 +78,8 @@ npm install pm2 -g && pm2 install pm2-logrotate
# Start Server
pm2 start server/server.js --name uptime-kuma
```
Uptime Kuma is now running on http://localhost:3001
More useful PM2 Commands
@ -91,10 +92,6 @@ pm2 monit
pm2 save && pm2 startup
```
### Windows Portable (x64)
https://github.com/louislam/uptime-kuma/releases/download/1.23.1/uptime-kuma-windows-x64-portable-1.23.1-2.zip
### Advanced Installation
If you need more options or need to browse via a reverse proxy, please read:
@ -113,10 +110,6 @@ I will assign requests/issues to the next milestone.
https://github.com/louislam/uptime-kuma/milestones
Project Plan:
https://github.com/users/louislam/projects/4/views/1
## ❤️ Sponsors
Thank you so much! (GitHub Sponsors will be updated manually. OpenCollective sponsors will be updated automatically, the list will be cached by GitHub though. It may need some time to be updated)
@ -143,28 +136,27 @@ Telegram Notification Sample:
## Motivation
* I was looking for a self-hosted monitoring tool like "Uptime Robot", but it is hard to find a suitable one. One of the close ones is statping. Unfortunately, it is not stable and no longer maintained.
* Want to build a fancy UI.
* Learn Vue 3 and vite.js.
* Show the power of Bootstrap 5.
* Try to use WebSocket with SPA instead of REST API.
* Deploy my first Docker image to Docker Hub.
- I was looking for a self-hosted monitoring tool like "Uptime Robot", but it is hard to find a suitable one. One of the close ones is statping. Unfortunately, it is not stable and no longer maintained.
- Want to build a fancy UI.
- Learn Vue 3 and vite.js.
- Show the power of Bootstrap 5.
- Try to use WebSocket with SPA instead of REST API.
- Deploy my first Docker image to Docker Hub.
If you love this project, please consider giving me a ⭐.
## 🗣️ Discussion / Ask for Help
⚠️ For any general or technical questions, please don't send me an email, as I am unable to provide support in that manner. I will not response if you asked such questions.
⚠️ For any general or technical questions, please don't send me an email, as I am unable to provide support in that manner. I will not respond if you asked such questions.
I recommend using Google, GitHub Issues, or Uptime Kuma's Subreddit for finding answers to your question. If you cannot find the information you need, feel free to ask:
- [GitHub Issues](https://github.com/louislam/uptime-kuma/issues)
- [Subreddit r/Uptime kuma](https://www.reddit.com/r/UptimeKuma/)
My Reddit account: [u/louislamlam](https://reddit.com/u/louislamlam).
My Reddit account: [u/louislamlam](https://reddit.com/u/louislamlam).
You can mention me if you ask a question on Reddit.
## Contribute
### Test Pull Requests
@ -179,9 +171,11 @@ https://github.com/louislam/uptime-kuma/wiki/Test-Pull-Requests
Check out the latest beta release here: https://github.com/louislam/uptime-kuma/releases
### Bug Reports / Feature Requests
If you want to report a bug or request a new feature, feel free to open a [new issue](https://github.com/louislam/uptime-kuma/issues).
### Translations
If you want to translate Uptime Kuma into your language, please visit [Weblate Readme](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md).
### Spelling & Grammar
@ -190,4 +184,5 @@ Feel free to correct the grammar in the documentation or code.
My mother language is not english and my grammar is not that great.
### Create Pull Requests
If you want to modify Uptime Kuma, please read this guide and follow the rules here: https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md

@ -1,7 +0,0 @@
const config = {};
if (process.env.TEST_FRONTEND) {
config.presets = [ "@babel/preset-env" ];
}
module.exports = config;

@ -1,4 +1,3 @@
import legacy from "@vitejs/plugin-legacy";
import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";
import visualizer from "rollup-plugin-visualizer";
@ -24,9 +23,6 @@ export default defineConfig({
plugins: [
commonjs(),
vue(),
legacy({
targets: [ "since 2015" ],
}),
visualizer({
filename: "tmp/dist-stats.html"
}),

@ -275,7 +275,7 @@ async function createTables() {
table.boolean("active").notNullable().defaultTo(true);
table.integer("user_id").unsigned();
table.boolean("is_default").notNullable().defaultTo(false);
table.text("config");
table.text("config", "longtext");
});
// monitor_notification

@ -0,0 +1,14 @@
exports.up = function (knex) {
// update monitor.push_token to 32 length
return knex.schema
.alterTable("monitor", function (table) {
table.string("push_token", 32).alter();
});
};
exports.down = function (knex) {
return knex.schema
.alterTable("monitor", function (table) {
table.string("push_token", 20).alter();
});
};

@ -1,10 +1,11 @@
## Info
# Info
https://knexjs.org/guide/migrations.html#knexfile-in-other-languages
## Basic rules
- All tables must have a primary key named `id`
- Filename format: `YYYY-MM-DD-HHMM-patch-name.js`
- Filename format: `YYYY-MM-DD-HHMM-patch-name.js`
- Avoid native SQL syntax, use knex methods, because Uptime Kuma supports SQLite and MariaDB.
## Template

@ -0,0 +1,10 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
-- SQLite: Change the data type of the column "config" from VARCHAR to TEXT
ALTER TABLE notification RENAME COLUMN config TO config_old;
ALTER TABLE notification ADD COLUMN config TEXT;
UPDATE notification SET config = config_old;
ALTER TABLE notification DROP COLUMN config_old;
COMMIT;

@ -30,6 +30,8 @@ FROM $BASE_IMAGE AS release
USER node
WORKDIR /app
LABEL org.opencontainers.image.source="https://github.com/louislam/uptime-kuma"
ENV UPTIME_KUMA_IS_CONTAINER=1
# Copy app files from build layer

@ -1,3 +1,4 @@
# How to run
Node.js (ts-node)
@ -16,4 +17,3 @@ Bun.js
```bash
bun index.ts
```

8888
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{
"name": "uptime-kuma",
"version": "1.23.2",
"version": "1.23.3",
"license": "MIT",
"repository": {
"type": "git",
@ -10,8 +10,6 @@
"node": "14 || 16 || 18 || >= 20.4.0"
},
"scripts": {
"install-legacy": "npm install",
"update-legacy": "npm update",
"lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
"lint-fix:js": "eslint --ext \".js,.vue\" --fix --ignore-path .gitignore .",
"lint:style": "stylelint \"**/*.{vue,css,scss}\" --ignore-path .gitignore",
@ -23,6 +21,7 @@
"start": "npm run start-server",
"start-server": "node server/server.js",
"start-server-dev": "cross-env NODE_ENV=development node server/server.js",
"start-server-dev:watch": "cross-env NODE_ENV=development node --watch server/server.js",
"build": "vite build --config ./config/vite.config.js",
"test": "node test/prepare-test-server.js && npm run test-backend",
"test-with-build": "npm run build && npm test",
@ -42,7 +41,7 @@
"build-docker-nightly-local": "npm run build && docker build -f docker/dockerfile -t louislam/uptime-kuma:nightly2 --target nightly .",
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test2 --target pr-test2 . --push",
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
"setup": "git checkout 1.23.2 && npm ci --production && npm run download-dist",
"setup": "git checkout 1.23.3 && npm ci --production && npm run download-dist",
"download-dist": "node extra/download-dist.js",
"mark-as-nightly": "node extra/mark-as-nightly.js",
"reset-password": "node extra/reset-password.js",
@ -99,7 +98,7 @@
"express-basic-auth": "~1.2.1",
"express-static-gzip": "~2.1.7",
"form-data": "~4.0.0",
"gamedig": "~4.0.5",
"gamedig": "~4.1.0",
"http-graceful-shutdown": "~3.1.7",
"http-proxy-agent": "~5.0.0",
"https-proxy-agent": "~5.0.1",
@ -146,15 +145,14 @@
},
"devDependencies": {
"@actions/github": "~5.0.1",
"@babel/eslint-parser": "^7.22.7",
"@babel/preset-env": "^7.15.8",
"@fortawesome/fontawesome-svg-core": "~1.2.36",
"@fortawesome/free-regular-svg-icons": "~5.15.4",
"@fortawesome/free-solid-svg-icons": "~5.15.4",
"@fortawesome/vue-fontawesome": "~3.0.0-5",
"@popperjs/core": "~2.10.2",
"@types/bootstrap": "~5.1.9",
"@vitejs/plugin-legacy": "~4.1.0",
"@typescript-eslint/eslint-plugin": "^6.7.5",
"@typescript-eslint/parser": "^6.7.5",
"@vitejs/plugin-vue": "~4.2.3",
"@vue/compiler-sfc": "~3.3.4",
"@vuepic/vue-datepicker": "~3.4.8",

@ -85,6 +85,7 @@ class Database {
"patch-monitor-oauth-cc.sql": true,
"patch-add-timeout-monitor.sql": true,
"patch-add-gamedig-given-port.sql": true, // The last file so far converted to a knex migration file
"patch-notification-config.sql": true,
};
/**
@ -130,7 +131,7 @@ class Database {
fs.mkdirSync(Database.dockerTLSDir, { recursive: true });
}
log.info("db", `Data Dir: ${Database.dataDir}`);
log.info("server", `Data Dir: ${Database.dataDir}`);
}
/**
@ -317,10 +318,10 @@ class Database {
await R.exec("PRAGMA synchronous = NORMAL");
if (!noLog) {
log.info("db", "SQLite config:");
log.info("db", await R.getAll("PRAGMA journal_mode"));
log.info("db", await R.getAll("PRAGMA cache_size"));
log.info("db", "SQLite Version: " + await R.getCell("SELECT sqlite_version()"));
log.debug("db", "SQLite config:");
log.debug("db", await R.getAll("PRAGMA journal_mode"));
log.debug("db", await R.getAll("PRAGMA cache_size"));
log.debug("db", "SQLite Version: " + await R.getCell("SELECT sqlite_version()"));
}
}
@ -389,13 +390,15 @@ class Database {
version = 0;
}
log.info("db", "Your database version: " + version);
log.info("db", "Latest database version: " + this.latestVersion);
if (version !== this.latestVersion) {
log.info("db", "Your database version: " + version);
log.info("db", "Latest database version: " + this.latestVersion);
}
if (version === this.latestVersion) {
log.info("db", "Database patch not needed");
log.debug("db", "Database patch not needed");
} else if (version > this.latestVersion) {
log.info("db", "Warning: Database version is newer than expected");
log.warn("db", "Warning: Database version is newer than expected");
} else {
log.info("db", "Database patch is needed");
@ -431,7 +434,7 @@ class Database {
* @returns {Promise<void>}
*/
static async patchSqlite2() {
log.info("db", "Database Patch 2.0 Process");
log.debug("db", "Database Patch 2.0 Process");
let databasePatchedFiles = await setting("databasePatchedFiles");
if (! databasePatchedFiles) {

@ -2,7 +2,7 @@ const https = require("https");
const dayjs = require("dayjs");
const axios = require("axios");
const { Prometheus } = require("../prometheus");
const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, TimeLogger, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND,
const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND,
SQL_DATETIME_FORMAT
} = require("../../src/util");
const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, mqttAsync, setSetting, httpNtlm, radius, grpcQuery,
@ -56,7 +56,7 @@ class Monitor extends BeanModel {
obj.tags = await this.getTags();
}
if (certExpiry && this.type === "http" && this.getURLProtocol() === "https:") {
if (certExpiry && (this.type === "http" || this.type === "keyword" || this.type === "json-query") && this.getURLProtocol() === "https:") {
const { certExpiryDaysRemaining, validCert } = await this.getCertExpiry(this.id);
obj.certExpiryDaysRemaining = certExpiryDaysRemaining;
obj.validCert = validCert;
@ -1067,7 +1067,7 @@ class Monitor extends BeanModel {
/**
* Example: http: or https:
* @returns {(null|string)}
* @returns {(null|string)} URL's protocol
*/
getURLProtocol() {
const url = this.getUrl();
@ -1137,7 +1137,7 @@ class Monitor extends BeanModel {
if (hasClients) {
// Send 24 hour average ping
let data24h = await uptimeCalculator.get24Hour();
io.to(userID).emit("avgPing", monitorID, (data24h.avgPing) ? data24h.avgPing.toFixed(2) : null);
io.to(userID).emit("avgPing", monitorID, (data24h.avgPing) ? Number(data24h.avgPing.toFixed(2)) : null);
// Send 24 hour uptime
io.to(userID).emit("uptime", monitorID, 24, data24h.uptime);

@ -1,6 +1,8 @@
const { BeanModel } = require("redbean-node/dist/bean-model");
const passwordHash = require("../password-hash");
const { R } = require("redbean-node");
const jwt = require("jsonwebtoken");
const { shake256, SHAKE256_LENGTH } = require("../util-server");
class User extends BeanModel {
/**
@ -27,6 +29,19 @@ class User extends BeanModel {
this.password = newPassword;
}
/**
* Create a new JWT for a user
* @param {User} user The User to create a JsonWebToken for
* @param {string} jwtSecret The key used to sign the JsonWebToken
* @returns {string} the JsonWebToken as a string
*/
static createJWT(user, jwtSecret) {
return jwt.sign({
username: user.username,
h: shake256(user.password, SHAKE256_LENGTH),
}, jwtSecret);
}
}
module.exports = User;

@ -49,8 +49,6 @@ if (process.platform === "win32") {
];
}
log.debug("chrome", allowedList);
/**
* Is the executable path allowed?
* @param {string} executablePath Path to executable

@ -65,7 +65,7 @@ class Notification {
* @throws Duplicate notification providers in list
*/
static init() {
log.info("notification", "Prepare Notification Providers");
log.debug("notification", "Prepare Notification Providers");
this.providerList = {};

@ -1,5 +1,12 @@
let express = require("express");
const { allowDevAllOrigin, allowAllOrigin, percentageToColor, filterAndJoin, sendHttpError } = require("../util-server");
const {
setting,
allowDevAllOrigin,
allowAllOrigin,
percentageToColor,
filterAndJoin,
sendHttpError,
} = require("../util-server");
const { R } = require("redbean-node");
const apicache = require("../modules/apicache");
const Monitor = require("../model/monitor");
@ -23,10 +30,14 @@ router.get("/api/entry-page", async (request, response) => {
allowDevAllOrigin(response);
let result = { };
let hostname = request.hostname;
if ((await setting("trustProxy")) && request.headers["x-forwarded-host"]) {
hostname = request.headers["x-forwarded-host"];
}
if (request.hostname in StatusPage.domainMappingList) {
if (hostname in StatusPage.domainMappingList) {
result.type = "statusPageMatchedDomain";
result.statusPageSlug = StatusPage.domainMappingList[request.hostname];
result.statusPageSlug = StatusPage.domainMappingList[hostname];
} else {
result.type = "entryPage";
result.entryPage = server.entryPage;
@ -283,8 +294,6 @@ router.get("/api/badge/:id/ping/:duration?", cache("5 minutes"), async (request,
requestedDuration = "24h";
}
const sqlHourOffset = Database.sqlHourOffset();
// Check if monitor is public
const uptimeCalculator = await UptimeCalculator.getUptimeCalculator(requestedMonitorId);

@ -4,7 +4,6 @@ const { UptimeKumaServer } = require("../uptime-kuma-server");
const StatusPage = require("../model/status_page");
const { allowDevAllOrigin, sendHttpError } = require("../util-server");
const { R } = require("redbean-node");
const Monitor = require("../model/monitor");
const { badgeConstants } = require("../config");
const { makeBadge } = require("badge-maker");
const { UptimeCalculator } = require("../uptime-calculator");

@ -38,9 +38,7 @@ if (!semver.satisfies(nodeVersion, requiredNodeVersions)) {
const args = require("args-parser")(process.argv);
const { sleep, log, getRandomInt, genSecret, isDev } = require("../src/util");
const config = require("./config");
log.info("server", "Welcome to Uptime Kuma");
log.debug("server", "Arguments");
log.debug("server", args);
@ -48,8 +46,13 @@ if (! process.env.NODE_ENV) {
process.env.NODE_ENV = "production";
}
log.info("server", "Node Env: " + process.env.NODE_ENV);
log.info("server", "Inside Container: " + (process.env.UPTIME_KUMA_IS_CONTAINER === "1"));
log.info("server", "Env: " + process.env.NODE_ENV);
log.debug("server", "Inside Container: " + (process.env.UPTIME_KUMA_IS_CONTAINER === "1"));
const checkVersion = require("./check-version");
log.info("server", "Uptime Kuma Version: " + checkVersion.version);
log.info("server", "Loading modules");
log.debug("server", "Importing express");
const express = require("express");
@ -62,8 +65,6 @@ log.debug("server", "Importing http-graceful-shutdown");
const gracefulShutdown = require("http-graceful-shutdown");
log.debug("server", "Importing prometheus-api-metrics");
const prometheusAPIMetrics = require("prometheus-api-metrics");
log.debug("server", "Importing compare-versions");
const compareVersions = require("compare-versions");
const { passwordStrength } = require("check-password-strength");
log.debug("server", "Importing 2FA Modules");
@ -71,25 +72,23 @@ const notp = require("notp");
const base32 = require("thirty-two");
const { UptimeKumaServer } = require("./uptime-kuma-server");
const server = UptimeKumaServer.getInstance(args);
const io = module.exports.io = server.io;
const app = server.app;
log.info("server", "Importing this project modules");
log.debug("server", "Importing Monitor");
const Monitor = require("./model/monitor");
const User = require("./model/user");
log.debug("server", "Importing Settings");
const { getSettings, setSettings, setting, initJWTSecret, checkLogin, FBSD, doubleCheckPassword, startE2eTests,
allowDevAllOrigin
const { getSettings, setSettings, setting, initJWTSecret, checkLogin, FBSD, doubleCheckPassword, startE2eTests, shake256, SHAKE256_LENGTH, allowDevAllOrigin,
} = require("./util-server");
log.debug("server", "Importing Notification");
const { Notification } = require("./notification");
Notification.init();
log.debug("server", "Importing Proxy");
const { Proxy } = require("./proxy");
log.debug("server", "Importing Database");
const Database = require("./database");
@ -101,9 +100,6 @@ const { apiAuth } = require("./auth");
const { login } = require("./auth");
const passwordHash = require("./password-hash");
const checkVersion = require("./check-version");
log.info("server", "Version: " + checkVersion.version);
// If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available and the unspecified IPv4 address (0.0.0.0) otherwise.
// Dual-stack support for (::)
// Also read HOST if not FreeBSD, as HOST is a system environment variable in FreeBSD
@ -134,10 +130,6 @@ const twoFAVerifyOptions = {
const testMode = !!args["test"] || false;
const e2eTestMode = !!args["e2e"] || false;
if (config.demoMode) {
log.info("server", "==== Demo Mode ====");
}
// Must be after io instantiation
const { sendNotificationList, sendHeartbeatList, sendInfo, sendProxyList, sendDockerHostList, sendAPIKeyList } = require("./client");
const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler");
@ -198,7 +190,7 @@ let needSetup = false;
server.entryPage = await Settings.get("entryPage");
await StatusPage.loadDomainMappingList();
log.info("server", "Adding route");
log.debug("server", "Adding route");
// ***************************
// Normal Router here
@ -298,7 +290,7 @@ let needSetup = false;
}
});
log.info("server", "Adding socket handler");
log.debug("server", "Adding socket handler");
io.on("connection", async (socket) => {
sendInfo(socket, true);
@ -326,6 +318,11 @@ let needSetup = false;
decoded.username,
]);
// Check if the password changed
if (decoded.h !== shake256(user.password, SHAKE256_LENGTH)) {
throw new Error("The token is invalid due to password change or old token");
}
if (user) {
log.debug("auth", "afterLogin");
afterLogin(socket, user);
@ -347,9 +344,10 @@ let needSetup = false;
});
}
} catch (error) {
log.error("auth", `Invalid token. IP=${clientIP}`);
if (error.message) {
log.error("auth", error.message, `IP=${clientIP}`);
}
callback({
ok: false,
msg: "authInvalidToken",
@ -389,9 +387,7 @@ let needSetup = false;
callback({
ok: true,
token: jwt.sign({
username: data.username,
}, server.jwtSecret),
token: User.createJWT(user, server.jwtSecret),
});
}
@ -419,9 +415,7 @@ let needSetup = false;
callback({
ok: true,
token: jwt.sign({
username: data.username,
}, server.jwtSecret),
token: User.createJWT(user, server.jwtSecret),
});
} else {
@ -1435,212 +1429,6 @@ let needSetup = false;
}
});
socket.on("uploadBackup", async (uploadedJSON, importHandle, callback) => {
try {
checkLogin(socket);
let backupData = JSON.parse(uploadedJSON);
log.info("manage", `Importing Backup, User ID: ${socket.userID}, Version: ${backupData.version}`);
let notificationListData = backupData.notificationList;
let proxyListData = backupData.proxyList;
let monitorListData = backupData.monitorList;
let version17x = compareVersions.compare(backupData.version, "1.7.0", ">=");
// If the import option is "overwrite" it'll clear most of the tables, except "settings" and "user"
if (importHandle === "overwrite") {
// Stops every monitor first, so it doesn't execute any heartbeat while importing
for (let id in server.monitorList) {
let monitor = server.monitorList[id];
await monitor.stop();
}
await R.exec("DELETE FROM heartbeat");
await R.exec("DELETE FROM monitor_notification");
await R.exec("DELETE FROM monitor_tls_info");
await R.exec("DELETE FROM notification");
await R.exec("DELETE FROM monitor_tag");
await R.exec("DELETE FROM tag");
await R.exec("DELETE FROM monitor");
await R.exec("DELETE FROM proxy");
}
// Only starts importing if the backup file contains at least one notification
if (notificationListData.length >= 1) {
// Get every existing notification name and puts them in one simple string
let notificationNameList = await R.getAll("SELECT name FROM notification");
let notificationNameListString = JSON.stringify(notificationNameList);
for (let i = 0; i < notificationListData.length; i++) {
// Only starts importing the notification if the import option is "overwrite", "keep" or "skip" but the notification doesn't exists
if ((importHandle === "skip" && notificationNameListString.includes(notificationListData[i].name) === false) || importHandle === "keep" || importHandle === "overwrite") {
let notification = JSON.parse(notificationListData[i].config);
await Notification.save(notification, null, socket.userID);
}
}
}
// Only starts importing if the backup file contains at least one proxy
if (proxyListData && proxyListData.length >= 1) {
const proxies = await R.findAll("proxy");
// Loop over proxy list and save proxies
for (const proxy of proxyListData) {
const exists = proxies.find(item => item.id === proxy.id);
// Do not process when proxy already exists in import handle is skip and keep
if ([ "skip", "keep" ].includes(importHandle) && !exists) {
return;
}
// Save proxy as new entry if exists update exists one
await Proxy.save(proxy, exists ? proxy.id : undefined, proxy.userId);
}
}
// Only starts importing if the backup file contains at least one monitor
if (monitorListData.length >= 1) {
// Get every existing monitor name and puts them in one simple string
let monitorNameList = await R.getAll("SELECT name FROM monitor");
let monitorNameListString = JSON.stringify(monitorNameList);
for (let i = 0; i < monitorListData.length; i++) {
// Only starts importing the monitor if the import option is "overwrite", "keep" or "skip" but the notification doesn't exists
if ((importHandle === "skip" && monitorNameListString.includes(monitorListData[i].name) === false) || importHandle === "keep" || importHandle === "overwrite") {
// Define in here every new variable for monitors which where implemented after the first version of the Import/Export function (1.6.0)
// --- Start ---
// Define default values
let retryInterval = 0;
let timeout = monitorListData[i].timeout || (monitorListData[i].interval * 0.8); // fallback to old value
/*
Only replace the default value with the backup file data for the specific version, where it appears the first time
More information about that where "let version" will be defined
*/
if (version17x) {
retryInterval = monitorListData[i].retryInterval;
}
// --- End ---
let monitor = {
// Define the new variable from earlier here
name: monitorListData[i].name,
description: monitorListData[i].description,
type: monitorListData[i].type,
url: monitorListData[i].url,
method: monitorListData[i].method || "GET",
body: monitorListData[i].body,
headers: monitorListData[i].headers,
authMethod: monitorListData[i].authMethod,
basic_auth_user: monitorListData[i].basic_auth_user,
basic_auth_pass: monitorListData[i].basic_auth_pass,
authWorkstation: monitorListData[i].authWorkstation,
authDomain: monitorListData[i].authDomain,
timeout,
interval: monitorListData[i].interval,
retryInterval: retryInterval,
resendInterval: monitorListData[i].resendInterval || 0,
hostname: monitorListData[i].hostname,
maxretries: monitorListData[i].maxretries,
port: monitorListData[i].port,
keyword: monitorListData[i].keyword,
invertKeyword: monitorListData[i].invertKeyword,
ignoreTls: monitorListData[i].ignoreTls,
upsideDown: monitorListData[i].upsideDown,
maxredirects: monitorListData[i].maxredirects,
accepted_statuscodes: monitorListData[i].accepted_statuscodes,
dns_resolve_type: monitorListData[i].dns_resolve_type,
dns_resolve_server: monitorListData[i].dns_resolve_server,
notificationIDList: monitorListData[i].notificationIDList,
proxy_id: monitorListData[i].proxy_id || null,
};
if (monitorListData[i].pushToken) {
monitor.pushToken = monitorListData[i].pushToken;
}
let bean = R.dispense("monitor");
let notificationIDList = monitor.notificationIDList;
delete monitor.notificationIDList;
monitor.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes);
delete monitor.accepted_statuscodes;
bean.import(monitor);
bean.user_id = socket.userID;
await R.store(bean);
// Only for backup files with the version 1.7.0 or higher, since there was the tag feature implemented
if (version17x) {
// Only import if the specific monitor has tags assigned
for (const oldTag of monitorListData[i].tags) {
// Check if tag already exists and get data ->
let tag = await R.findOne("tag", " name = ?", [
oldTag.name,
]);
let tagId;
if (!tag) {
// -> If it doesn't exist, create new tag from backup file
let beanTag = R.dispense("tag");
beanTag.name = oldTag.name;
beanTag.color = oldTag.color;
await R.store(beanTag);
tagId = beanTag.id;
} else {
// -> If it already exist, set tagId to value from database
tagId = tag.id;
}
// Assign the new created tag to the monitor
await R.exec("INSERT INTO monitor_tag (tag_id, monitor_id, value) VALUES (?, ?, ?)", [
tagId,
bean.id,
oldTag.value,
]);
}
}
await updateMonitorNotification(bean.id, notificationIDList);
// If monitor was active start it immediately, otherwise pause it
if (monitorListData[i].active === 1) {
await startMonitor(socket.userID, bean.id);
} else {
await pauseMonitor(socket.userID, bean.id);
}
}
}
await sendNotificationList(socket);
await server.sendMonitorList(socket);
}
callback({
ok: true,
msg: "successBackupRestored",
msgi18n: true,
});
} catch (e) {
callback({
ok: false,
msg: e.message,
});
}
});
socket.on("clearEvents", async (monitorID, callback) => {
try {
checkLogin(socket);
@ -1736,11 +1524,12 @@ let needSetup = false;
});
log.info("server", "Init the server");
log.debug("server", "Init the server");
server.httpServer.once("error", async (err) => {
console.error("Cannot listen: " + err.message);
log.error("server", "Cannot listen: " + err.message);
await shutdownFunction();
process.exit(1);
});
server.start();
@ -1852,9 +1641,9 @@ async function afterLogin(socket, user) {
* @returns {Promise<void>}
*/
async function initDatabase(testMode = false) {
log.info("server", "Connecting to the Database");
log.debug("server", "Connecting to the database");
await Database.connect(testMode);
log.info("server", "Connected");
log.info("server", "Connected to the database");
// Patch the database
await Database.patch();
@ -1868,7 +1657,7 @@ async function initDatabase(testMode = false) {
jwtSecretBean = await initJWTSecret();
log.info("server", "Stored JWT secret into database");
} else {
log.info("server", "Load JWT secret from database.");
log.debug("server", "Load JWT secret from database.");
}
// If there is no record in user table, it is a new Uptime Kuma instance, need to setup

@ -48,7 +48,7 @@ class SetupDatabase {
try {
dbConfig = Database.readDBConfig();
log.info("setup-database", "db-config.json is found and is valid");
log.debug("setup-database", "db-config.json is found and is valid");
this.needSetup = false;
} catch (e) {

@ -83,7 +83,7 @@ class UptimeKumaServer {
const sslCert = args["ssl-cert"] || process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || undefined;
const sslKeyPassphrase = args["ssl-key-passphrase"] || process.env.UPTIME_KUMA_SSL_KEY_PASSPHRASE || process.env.SSL_KEY_PASSPHRASE || undefined;
log.info("server", "Creating express and socket.io instance");
log.debug("server", "Creating express and socket.io instance");
this.app = express();
if (sslKey && sslCert) {
log.info("server", "Server Type: HTTPS");

@ -29,13 +29,11 @@ const {
},
} = require("node-radius-utils");
const dayjs = require("dayjs");
const readline = require("readline");
const rl = readline.createInterface({ input: process.stdin,
output: process.stdout });
// SASLOptions used in JSDoc
// eslint-disable-next-line no-unused-vars
const { Kafka, SASLOptions } = require("kafkajs");
const crypto = require("crypto");
const isWindows = process.platform === /^win/.test(process.platform);
/**
@ -290,22 +288,22 @@ exports.kafkaProducerAsync = function (brokers, topic, message, options = {}, sa
producer.connect().then(
() => {
try {
producer.send({
topic: topic,
messages: [{
value: message,
}],
});
connectedToKafka = true;
clearTimeout(timeoutID);
producer.send({
topic: topic,
messages: [{
value: message,
}],
}).then((_) => {
resolve("Message sent successfully");
} catch (e) {
}).catch((e) => {
connectedToKafka = true;
producer.disconnect();
clearTimeout(timeoutID);
reject(new Error("Error sending message: " + e.message));
}
}).finally(() => {
connectedToKafka = true;
clearTimeout(timeoutID);
});
}
).catch(
(e) => {
@ -317,8 +315,10 @@ exports.kafkaProducerAsync = function (brokers, topic, message, options = {}, sa
);
producer.on("producer.network.request_timeout", (_) => {
clearTimeout(timeoutID);
reject(new Error("producer.network.request_timeout"));
if (!connectedToKafka) {
clearTimeout(timeoutID);
reject(new Error("producer.network.request_timeout"));
}
});
producer.on("producer.disconnect", (_) => {
@ -1060,7 +1060,31 @@ module.exports.grpcQuery = async (options) => {
});
};
module.exports.prompt = (query) => new Promise((resolve) => rl.question(query, resolve));
module.exports.SHAKE256_LENGTH = 16;
/**
* @param {string} data The data to be hashed
* @param {number} len Output length of the hash
* @returns {string} The hashed data in hex format
*/
module.exports.shake256 = (data, len) => {
if (!data) {
return "";
}
return crypto.createHash("shake256", { outputLength: len })
.update(data)
.digest("hex");
};
/**
* Non await sleep
* Source: https://stackoverflow.com/questions/59099454/is-there-a-way-to-call-sleep-without-await-keyword
* @param {number} n Milliseconds to wait
* @returns {void}
*/
module.exports.wait = (n) => {
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, n);
};
// For unit test, export functions
if (process.env.TEST_BACKEND) {

@ -92,11 +92,9 @@
<script lang="ts">
import { Modal } from "bootstrap";
import { useToast } from "vue-toastification";
import dayjs from "dayjs";
import Datepicker from "@vuepic/vue-datepicker";
import CopyableInput from "./CopyableInput.vue";
const toast = useToast();
export default {
components: {
@ -158,7 +156,7 @@ export default {
this.keymodal.show();
this.clearForm();
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
},

@ -62,8 +62,6 @@
<script lang="ts">
import { Modal } from "bootstrap";
import Confirm from "./Confirm.vue";
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
components: {
@ -120,7 +118,7 @@ export default {
}
if (!found) {
toast.error("Docker Host not found!");
this.$root.toastError("Docker Host not found!");
}
} else {

@ -35,7 +35,7 @@
</button>
<div v-if="res && !res.ok" class="alert alert-danger mt-3" role="alert">
{{ res.msg }}
{{ $t(res.msg) }}
</div>
</form>
</div>

@ -346,7 +346,7 @@ export default {
pauseSelected() {
Object.keys(this.selectedMonitors)
.filter(id => this.$root.monitorList[id].active)
.forEach(id => this.$root.getSocket().emit("pauseMonitor", id));
.forEach(id => this.$root.getSocket().emit("pauseMonitor", id, () => {}));
this.cancelSelectMode();
},
@ -357,7 +357,7 @@ export default {
resumeSelected() {
Object.keys(this.selectedMonitors)
.filter(id => !this.$root.monitorList[id].active)
.forEach(id => this.$root.getSocket().emit("resumeMonitor", id));
.forEach(id => this.$root.getSocket().emit("resumeMonitor", id, () => {}));
this.cancelSelectMode();
},

@ -21,11 +21,8 @@ import { BarController, BarElement, Chart, Filler, LinearScale, LineController,
import "chartjs-adapter-dayjs-4";
import dayjs from "dayjs";
import { Line } from "vue-chartjs";
import { useToast } from "vue-toastification";
import { DOWN, PENDING, MAINTENANCE, log } from "../util.ts";
const toast = useToast();
Chart.register(LineController, BarController, LineElement, PointElement, TimeScale, BarElement, LinearScale, Tooltip, Filler);
export default {
@ -231,7 +228,7 @@ export default {
this.$root.getMonitorBeats(this.monitorId, newPeriod, (res) => {
if (!res.ok) {
toast.error(res.msg);
this.$root.toastError(res.msg);
} else {
this.heartbeatList = res.data;
this.$root.storage()[`chart-period-${this.monitorId}`] = newPeriod;

@ -123,9 +123,7 @@ import Confirm from "./Confirm.vue";
import Tag from "./Tag.vue";
import VueMultiselect from "vue-multiselect";
import { colorOptions } from "../util-frontend";
import { useToast } from "vue-toastification";
import { getMonitorRelativeURL } from "../util.ts";
const toast = useToast();
export default {
components: {
@ -320,7 +318,7 @@ export default {
for (let addId of this.addingMonitor) {
await this.addMonitorTagAsync(this.tag.id, addId, "").then((res) => {
if (!res.ok) {
toast.error(res.msg);
this.$root.toastError(res.msg);
editResult = false;
}
});
@ -330,7 +328,7 @@ export default {
this.monitors.find(monitor => monitor.id === removeId)?.tags.forEach(async (monitorTag) => {
await this.deleteMonitorTagAsync(this.tag.id, removeId, monitorTag.value).then((res) => {
if (!res.ok) {
toast.error(res.msg);
this.$root.toastError(res.msg);
editResult = false;
}
});

@ -129,10 +129,8 @@
<script>
import { Modal } from "bootstrap";
import VueMultiselect from "vue-multiselect";
import { useToast } from "vue-toastification";
import { colorOptions } from "../util-frontend";
import Tag from "../components/Tag.vue";
const toast = useToast();
/**
* @typedef Tag
@ -262,7 +260,7 @@ export default {
if (res.ok) {
this.existingTags = res.tags;
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
},
@ -399,7 +397,7 @@ export default {
let newTagResult;
await this.addTagAsync(newTag).then((res) => {
if (!res.ok) {
toast.error(res.msg);
this.$root.toastError(res.msg);
newTagResult = false;
}
newTagResult = res.tag;
@ -424,7 +422,7 @@ export default {
// Assign tag to monitor
await this.addMonitorTagAsync(tagId, monitorId, newTag.value).then((res) => {
if (!res.ok) {
toast.error(res.msg);
this.$root.toastError(res.msg);
newMonitorTagResult = false;
}
newMonitorTagResult = true;
@ -440,7 +438,7 @@ export default {
let deleteMonitorTagResult;
await this.deleteMonitorTagAsync(deleteTag.tag_id, deleteTag.monitor_id, deleteTag.value).then((res) => {
if (!res.ok) {
toast.error(res.msg);
this.$root.toastError(res.msg);
deleteMonitorTagResult = false;
}
deleteMonitorTagResult = true;

@ -76,8 +76,6 @@
import { Modal } from "bootstrap";
import Confirm from "./Confirm.vue";
import VueQrcode from "vue-qrcode";
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
components: {
@ -138,7 +136,7 @@ export default {
if (res.ok) {
this.uri = res.uri;
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
},
@ -159,7 +157,7 @@ export default {
this.currentPassword = "";
this.modal.hide();
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
},
@ -180,7 +178,7 @@ export default {
this.currentPassword = "";
this.modal.hide();
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
},
@ -194,7 +192,7 @@ export default {
if (res.ok) {
this.tokenValid = res.valid;
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
},
@ -208,7 +206,7 @@ export default {
if (res.ok) {
this.twoFAStatus = res.status;
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
},

@ -58,8 +58,6 @@
<script>
import HiddenInput from "../HiddenInput.vue";
import axios from "axios";
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
components: {
@ -110,7 +108,7 @@ export default {
}
} catch (error) {
toast.error(error.message);
this.$root.toastError(error.message);
}
},

@ -72,8 +72,6 @@
<script>
import APIKeyDialog from "../../components/APIKeyDialog.vue";
import Confirm from "../Confirm.vue";
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
components: {
@ -109,11 +107,7 @@ export default {
*/
deleteKey() {
this.$root.deleteAPIKey(this.selectedKeyID, (res) => {
if (res.ok) {
toast.success(res.msg);
} else {
toast.error(res.msg);
}
this.$root.toastRes(res);
});
},

@ -1,232 +0,0 @@
<template>
<div>
<div class="my-4">
<div class="alert alert-warning" role="alert" style="border-radius: 15px;">
{{ $t("backupOutdatedWarning") }}<br />
<br />
{{ $t("backupRecommend") }}
</div>
<h4 class="mt-4 mb-2">{{ $t("Export Backup") }}</h4>
<p>
{{ $t("backupDescription") }} <br />
({{ $t("backupDescription2") }}) <br />
</p>
<div class="mb-2">
<button class="btn btn-primary" @click="downloadBackup">
{{ $t("Export") }}
</button>
</div>
<p>
<strong>{{ $t("backupDescription3") }}</strong>
</p>
</div>
<div class="my-4">
<h4 class="mt-4 mb-2">{{ $t("Import Backup") }}</h4>
<label class="form-label">{{ $t("Options") }}:</label>
<br />
<div class="form-check form-check-inline">
<input
id="radioKeep"
v-model="importHandle"
class="form-check-input"
type="radio"
name="radioImportHandle"
value="keep"
/>
<label class="form-check-label" for="radioKeep">
{{ $t("Keep both") }}
</label>
</div>
<div class="form-check form-check-inline">
<input
id="radioSkip"
v-model="importHandle"
class="form-check-input"
type="radio"
name="radioImportHandle"
value="skip"
/>
<label class="form-check-label" for="radioSkip">
{{ $t("Skip existing") }}
</label>
</div>
<div class="form-check form-check-inline">
<input
id="radioOverwrite"
v-model="importHandle"
class="form-check-input"
type="radio"
name="radioImportHandle"
value="overwrite"
/>
<label class="form-check-label" for="radioOverwrite">
{{ $t("Overwrite") }}
</label>
</div>
<div class="form-text mb-2">
{{ $t("importHandleDescription") }}
</div>
<div class="mb-2">
<input
id="import-backend"
type="file"
class="form-control"
accept="application/json"
/>
</div>
<div class="input-group mb-2 justify-content-end">
<button
type="button"
class="btn btn-outline-primary"
:disabled="processing"
@click="confirmImport"
>
<div
v-if="processing"
class="spinner-border spinner-border-sm me-1"
></div>
{{ $t("Import") }}
</button>
</div>
<div
v-if="importAlert"
class="alert alert-danger mt-3"
style="padding: 6px 16px;"
>
{{ importAlert }}
</div>
</div>
<Confirm
ref="confirmImport"
btn-style="btn-danger"
:yes-text="$t('Yes')"
:no-text="$t('No')"
@yes="importBackup"
>
{{ $t("confirmImportMsg") }}
</Confirm>
</div>
</template>
<script>
import Confirm from "../../components/Confirm.vue";
import dayjs from "dayjs";
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
components: {
Confirm,
},
data() {
return {
processing: false,
importHandle: "skip",
importAlert: null,
};
},
methods: {
/**
* Show the confimation dialog confirming the configuration
* be imported
* @returns {void}
*/
confirmImport() {
this.$refs.confirmImport.show();
},
/**
* Download a backup of the configuration
* @returns {void}
*/
downloadBackup() {
let time = dayjs().format("YYYY_MM_DD-hh_mm_ss");
let fileName = `Uptime_Kuma_Backup_${time}.json`;
let monitorList = Object.values(this.$root.monitorList);
let exportData = {
version: this.$root.info.version,
notificationList: this.$root.notificationList,
monitorList: monitorList,
};
exportData = JSON.stringify(exportData, null, 4);
let downloadItem = document.createElement("a");
downloadItem.setAttribute(
"href",
"data:application/json;charset=utf-8," +
encodeURIComponent(exportData)
);
downloadItem.setAttribute("download", fileName);
downloadItem.click();
},
/**
* Import the specified backup file
* @returns {string|void} Error message
*/
importBackup() {
this.processing = true;
let uploadItem = document.getElementById("import-backend").files;
if (uploadItem.length <= 0) {
this.processing = false;
return (this.importAlert = this.$t("alertNoFile"));
}
if (uploadItem.item(0).type !== "application/json") {
this.processing = false;
return (this.importAlert = this.$t("alertWrongFileType"));
}
let fileReader = new FileReader();
fileReader.readAsText(uploadItem.item(0));
fileReader.onload = (item) => {
this.$root.uploadBackup(
item.target.result,
this.importHandle,
(res) => {
this.processing = false;
if (res.ok) {
toast.success(res.msg);
} else {
toast.error(res.msg);
}
}
);
};
},
},
};
</script>
<style lang="scss" scoped>
@import "../../assets/vars.scss";
.dark {
#import-backend {
&::file-selector-button {
color: $primary;
background-color: $dark-bg;
}
&:hover:not(:disabled):not([readonly])::file-selector-button {
color: $dark-font-color2;
background-color: $primary;
}
}
}
</style>

@ -57,9 +57,6 @@
<script>
import Confirm from "../../components/Confirm.vue";
import { log } from "../../util.ts";
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
components: {
@ -118,7 +115,7 @@ export default {
this.$root.getSocket().emit("shrinkDatabase", (res) => {
if (res.ok) {
this.loadDatabaseSize();
toast.success("Done");
this.$root.toastSuccess("Done");
} else {
log.debug("monitorhistory", res);
}
@ -142,7 +139,7 @@ export default {
if (res.ok) {
this.$router.go();
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
},

@ -28,11 +28,9 @@
</template>
<script>
import { useToast } from "vue-toastification";
import TagEditDialog from "../../components/TagEditDialog.vue";
import Tag from "../Tag.vue";
import Confirm from "../Confirm.vue";
const toast = useToast();
export default {
components: {
@ -86,7 +84,7 @@ export default {
if (res.ok) {
this.tagsList = res.tags;
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
},

@ -1,4 +1,6 @@
# How to translate
# Translations
## How to translate
(2023-01-24 Updated)
@ -7,7 +9,7 @@
3. Make sure your GitHub email is matched with Weblate's account, so that it could show you as a contributor on GitHub
4. Choose your language on Weblate and start translating.
# How to add a new language in the dropdown
## How to add a new language in the dropdown
1. Add your language at https://weblate.kuma.pet/projects/uptime-kuma/uptime-kuma/
2. Find the language code (You can find it at the end of the URL)

@ -63,7 +63,7 @@
"Add one": "أضف واحدا",
"wayToGetCloudflaredURL": "(قم بتنزيل CloudFlared من {0})",
"cloudflareWebsite": "موقع CloudFlare",
"Message:": ":رسالة",
"Message:": "رسالة:",
"Don't know how to get the token? Please read the guide:": "لا أعرف كيفية الحصول على الرمز المميز؟ يرجى قراءة الدليل:",
"telegramSendSilently": "أرسل بصمت",
"telegramSendSilentlyDescription": "ترسل الرسالة بصمت ويتلقى المستخدمون إشعارا بدون صوت.",
@ -134,7 +134,7 @@
"ignoreTLSError": "تجاهل خطأ TLS/SSL لمواقع HTTPS",
"upsideDownModeDescription": "اقلب الحالة رأسًا على عقب. إذا كانت الخدمة قابلة للوصول إلى أسفل.",
"maxRedirectDescription": "الحد الأقصى لعدد إعادة التوجيه لمتابعة. ضبط على 0 لتعطيل إعادة التوجيه.",
"Upside Down Mode": "وضع أسفل أسفل",
"Upside Down Mode": "وضع رأسا على عقب",
"Max. Redirects": "الأعلى. إعادة التوجيه",
"Accepted Status Codes": "رموز الحالة المقبولة",
"Push URL": "دفع عنوان URL",
@ -209,7 +209,7 @@
"Indigo": "النيلي",
"Purple": "نفسجي",
"webhookAdditionalHeadersDesc": "يحدد رؤوس إضافية مرسلة مع webhook.",
"Webhook URL": "Webhook URL",
"Webhook URL": "عنوان URL للخطاف الإلكتروني",
"Pink": "لون القرنفل",
"Custom": "العادة",
"Status Pages": "صفحات الحالة",
@ -359,10 +359,10 @@
"Connection String": "سلسلة الاتصال",
"Query": "استفسار",
"settingsCertificateExpiry": "شهادة TLS انتهاء الصلاحية",
"certificationExpiryDescription": "شاشات HTTPS تضيء عندما تنتهي شهادة TLS في",
"certificationExpiryDescription": "تقوم مراقبات HTTPS بتشغيل إشعار عند انتهاء صلاحية شهادة TLS في:",
"Setup Docker Host": "إعداد مضيف Docker",
"Connection Type": "نوع الاتصال",
"Docker Daemon": "Docker Daemon",
"Docker Daemon": "دُوكر Daemon",
"deleteDockerHostMsg": "هل أنت متأكد من حذف مضيف Docker لجميع الشاشات؟",
"socket": "قابس كهرباء",
"tcp": "TCP / HTTP",
@ -378,20 +378,20 @@
"Chat ID": "معرف الدردشة",
"telegramMessageThreadID": "معرف المواضيع",
"supportTelegramChatID": "دعم الدردشة المباشرة / معرف الدردشة للقناة",
"wayToGetTelegramChatID": "يمكنك الحصول على معرف الدردشة الخاص بك عن طريق إرسال رسالة إلى الروبوت والانتقال إلى عنوان URL هذا لعرض Chat_id",
"wayToGetTelegramChatID": "يمكنك الحصول على معرف الدردشة الخاص بك عن طريق إرسال رسالة إلى البوت والانتقال إلى عنوان URL هذا لعرض chat_id:",
"YOUR BOT TOKEN HERE": "رمز الروبوت الخاص بك هنا",
"chatIDNotFound": "لم يتم العثور على معرف الدردشة ؛ الرجاء إرسال رسالة إلى هذا الروبوت أولاً",
"disableCloudflaredNoAuthMsg": "أنت في وضع مصادقة لا توجد كلمة مرور غير مطلوبة.",
"trustProxyDescription": "ثق في رؤوس \"X-Forwarded- *\". إذا كنت ترغب في الحصول على عنوان IP الصحيح للعميل وكان Uptime Kuma خلف وكيل مثل Nginx أو Apache ، فيجب عليك تمكين هذا.",
"wayToGetLineNotifyToken": "يمكنك الحصول على رمز الوصول من {0}",
"Examples": "أمثلة",
"Home Assistant URL": "Home Assistant URL",
"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.": "يمكن العثور على قائمة بخدمات الإخطار في المساعد المنزلي ضمن \"Developer Tools > Services\" ابحث عن \"notification\" للعثور على اسم جهازك/هاتفك.",
"Automations can optionally be triggered in Home Assistant:": "يمكن تشغيل الأتمتة اختياريًا في Home Assistant:",
"Automations can optionally be triggered in Home Assistant:": "الاتمته يمكن اختياريا تحفيزها عبر Home Assistant:",
"Trigger type:": "نوع الزناد:",
"Event type:": "نوع الحدث:",
"Event data:": "بيانات الحدث:",
@ -430,7 +430,7 @@
"Display Timezone": "عرض المنطقة الزمنية",
"Server Timezone": "المنطقة الزمنية الخادم",
"statusPageMaintenanceEndDate": "نهاية",
"IconUrl": "url url icon",
"IconUrl": "عنوان URL للرمز",
"Enable DNS Cache": "تمكين ذاكرة التخزين المؤقت DNS",
"Disable": "إبطال",
"dnsCacheDescription": "قد لا يعمل في بعض بيئات IPv6 تعطيله إذا واجهت أي مشكلات.",
@ -456,7 +456,7 @@
"To Email": "للبريد الإلكتروني",
"smtpCC": "نسخة",
"smtpBCC": "BCC",
"Discord Webhook URL": "Discord Webhook URL",
"Discord Webhook URL": "عنوان URL للخّطاف على الويب للديسكورد",
"wayToGetDiscordURL": "يمكنك الحصول على هذا بالانتقال إلى إعدادات الخادم -> عمليات التكامل -> عرض الخطافات على الويب -> خطاف ويب جديد",
"Bot Display Name": "اسم عرض الروبوت",
"Prefix Custom Message": "بادئة رسالة مخصصة",
@ -464,7 +464,7 @@
"wayToGetTeamsURL": "يمكنك معرفة كيفية إنشاء عنوان URL webhook {0}.",
"wayToGetZohoCliqURL": "يمكنك معرفة كيفية إنشاء عنوان URL webhook {0}.",
"needSignalAPI": "تحتاج إلى وجود عميل إشارة مع REST API.",
"wayToCheckSignalURL": "يمكنك التحقق من عنوان URL هذا لعرض كيفية إعداد واحد",
"wayToCheckSignalURL": "يمكنك التحقق من عنوان URL هذا لعرض كيفية إعداد واحد:",
"Number": "رقم",
"Recipients": "المستلمين",
"Access Token": "رمز وصول",
@ -477,8 +477,8 @@
"User ID": "معرف المستخدم",
"Messaging API": "واجهة برمجة تطبيقات المراسلة",
"wayToGetLineChannelToken": "قم أولاً بالوصول إلى {0} إنشاء مزود وقناة (واجهة برمجة تطبيقات المراسلة) ، ثم يمكنك الحصول على رمز الوصول إلى القناة ومعرف المستخدم من عناصر القائمة المذكورة أعلاه.",
"Icon URL": "url url icon",
"aboutIconURL": "يمكنك توفير رابط لصورة في \"Icon URL\" لتجاوز صورة الملف الشخصي الافتراضي. لن يتم استخدامه إذا تم تعيين رمز رمز رمز.",
"Icon URL": "عنوان URL للرمز",
"aboutIconURL": "يمكنك توفير رابط لصورة في \"رمز URL\" لتجاوز صورة الملف الشخصي الافتراضية. لن يتم استخدامه إذا تم تعيين ايقونة اموجي.",
"aboutMattermostChannelName": "يمكنك تجاوز القناة الافتراضية التي تنشرها WebHook من خلال إدخال اسم القناة في \"Channel Name\" الحقل. يجب تمكين هذا في إعدادات Webhook Mattern. السابق",
"dataRetentionTimeError": "يجب أن تكون فترة الاستبقاء 0 أو أكبر",
"infiniteRetention": "ضبط على 0 للاحتفاظ لا نهائي.",
@ -492,7 +492,7 @@
"clearEventsMsg": "هل أنت متأكد من حذف جميع الأحداث لهذا الشاشة؟",
"clearHeartbeatsMsg": "هل أنت متأكد من حذف جميع دقات القلب لهذا الشاشة؟",
"confirmImportMsg": "هل أنت متأكد من أنك تريد استيراد النسخ الاحتياطي؟ يرجى التحقق من أنك حددت خيار الاستيراد الصحيح.",
"twoFAVerifyLabel": "الرجاء إدخال الرمز المميز الخاص بك للتحقق من 2FA",
"twoFAVerifyLabel": "يرجى إدخال الرمز المميز الخاص بك للتحقق من المصادقة الثنائية (2FA):",
"pushoversounds pushover": "سداد (افتراضي)",
"pushoversounds bike": "دراجة هوائية",
"pushoversounds bugle": "بوق",
@ -550,7 +550,7 @@
"SMS Type": "نوع الرسائل القصيرة",
"octopushTypePremium": "قسط (سريع - موصى به للتنبيه)",
"octopushTypeLowCost": "التكلفة المنخفضة (بطيئة - تم حظرها أحيانًا بواسطة المشغل)",
"checkPrice": "تحقق من الأسعار {0}",
"checkPrice": "تحقق من أسعار {0}:",
"apiCredentials": "بيانات اعتماد API",
"octopushLegacyHint": "هل تستخدم الإصدار القديم من Octopush (2011-2020) أو الإصدار الجديد؟",
"Check octopush prices": "تحقق من أسعار Octopush {0}.",
@ -581,7 +581,7 @@
"Base URL": "عنوان URL الأساسي",
"goAlertInfo": "الهدف هو تطبيق مفتوح المصدر لجدولة الجدولة التلقائية والإشعارات (مثل الرسائل القصيرة أو المكالمات الصوتية). إشراك الشخص المناسب تلقائيًا بالطريقة الصحيحة وفي الوقت المناسب! {0}",
"goAlertIntegrationKeyInfo": "احصل على مفتاح تكامل API العام للخدمة في هذا التنسيق \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\" عادةً قيمة المعلمة الرمزية لعنوان url المنسق.",
"TemplateCode": "TemplateCode",
"TemplateCode": "رمز القالب",
"SignName": "اسم تسجيل الدخول",
"Sms template must contain parameters: ": "يجب أن يحتوي قالب الرسائل القصيرة على معلمات: ",
"Bark Endpoint": "نقطة نهاية اللحاء",
@ -613,10 +613,10 @@
"Feishu WebHookUrl": "Feishu Webhookurl",
"matrixHomeserverURL": "عنوان URL HomeServer (مع HTTP (S)",
"Internal Room Id": "معرف الغرفة الداخلية",
"matrixDesc1": "يمكنك العثور على معرف الغرفة الداخلي من خلال البحث في القسم المتقدم من إعدادات الغرفة في عميل Matrix الخاص بك. يجب أن تبدو مثل! QMDRCPUIFLWSFJXYE6",
"matrixDesc1": "يمكنك العثور على معرف الغرفة الداخلي من خلال البحث في القسم المتقدم لإعدادات الغرفة في عميل Matrix الخاص بك. ينبغي أن يبدو مثل QMdRCpUIfLwsfjxye6:home.server!.",
"Uptime Kuma URL": "UPTIME KUMA URL",
"Icon Emoji": "أيقونة الرموز التعبيرية",
"signalImportant": "مهم",
"signalImportant": "هام: لا يمكنك المزج بين المجموعات والأرقام في المستلمين!",
"aboutWebhooks": "مزيد من المعلومات حول Webhooks ON",
"aboutChannelName": "أدخل اسم القناة في حقل اسم القناة {0} إذا كنت تريد تجاوز قناة WebHook. السابق",
"aboutKumaURL": "إذا تركت حقل URL في وقت التشغيل KUMA فارغًا ، فسيتم افتراضيًا إلى صفحة GitHub Project.",
@ -679,10 +679,13 @@
"deleteAPIKeyMsg": "هل أنت متأكد أنك تريد حذف مفتاح API هذا؟",
"Auto Get": "الحصول التلقائي",
"Auto resolve or acknowledged": "",
"backupDescription2": "ملحوظة",
"backupDescription2": "ملحوظة: لم يتم تضمين بيانات السجل والأحداث.",
"languageName": "العربية",
"Game": "الألعاب",
"List": "القائمة",
"statusMaintenance": "الصيانة",
"Home": "الرئيسة"
"Home": "الرئيسة",
"setupDatabaseChooseDatabase": "ما هي قاعدة البيانات التي تريد استخدامها؟",
"setupDatabaseEmbeddedMariaDB": "لا تحتاج إلى تعيين أي شيء. قامت نسخة دُوكر بتضمين MariaDB لك تلقائيًا. سيتصل (آب تايم كارما) بقاعدة البيانات هذه عبر مقبس Unix.",
"setupDatabaseMariaDB": "للاتصال بقاعدة بيانات MariaDB خارجية. تحتاج إلى تعيين معلومات اتصال قاعدة البيانات."
}

@ -644,7 +644,7 @@
"IconUrl": "Икона URL адрес",
"webhookAdditionalHeadersTitle": "Допълнителни хедъри",
"webhookAdditionalHeadersDesc": "Задава допълнителни хедъри, изпратени с уеб куката. Всеки хедър трябва да бъде дефиниран като JSON ключ/стойност.",
"Enable DNS Cache": "Активирай DNS кеширане за HTTP(S) монитори",
"Enable DNS Cache": "(Отпаднала) Активирай DNS кеширане за HTTP(S) монитори",
"Enable": "Активирай",
"Disable": "Деактивирай",
"dnsCacheDescription": "Възможно е да не работи в IPv6 среда - деактивирайте, ако срещнете проблеми.",
@ -838,5 +838,37 @@
"styleElapsedTimeShowNoLine": "Покажи (без ред)",
"gamedigGuessPort": "Gamedig: Познай порт",
"gamedigGuessPortDescription": "Портът, използван от Valve Server Query Protocol, може да е различен от клиентския порт. Опитайте това, ако мониторът не може да се свърже с вашия сървър.",
"styleElapsedTimeShowWithLine": "Покажи (с ред)"
"styleElapsedTimeShowWithLine": "Покажи (с ред)",
"enableNSCD": "Активирай NSCD (Name Service Cache Daemon) за кеширане на всички DNS заявки",
"dbName": "Име на базата данни",
"setupDatabaseChooseDatabase": "Коя база данни желаете да използвате?",
"Saved.": "Запазено.",
"toastErrorTimeout": "Време за изчакване на известията при грешка",
"toastSuccessTimeout": "Време за изчакване на известията при успех",
"monitorToastMessagesDescription": "Известието за състояние на монитора изчезва след определено време в секунди. Задаване на -1, деактивира времето за изчакване. Задаване на 0 деактивира тост известията.",
"monitorToastMessagesLabel": "Мониторинг на известията при промяна на състоянието",
"setupDatabaseEmbeddedMariaDB": "Не е нужно да настройвате нищо. Този Docker имидж автоматично е вградил и конфигурирал MariaDB за Вас. Uptime Kuma ще се свърже с тази база данни чрез Unix сокет.",
"setupDatabaseMariaDB": "Свързване към външна MariaDB база данни. Трябва да зададете информацията за връзка с базата данни.",
"setupDatabaseSQLite": "Обикновен файл с база данни, препоръчително при маломащабен тип внедрявания. Преди v2.0.0 Uptime Kuma използва SQLite като база данни по подразбиране.",
"Bark API Version": "Версия на Bark API",
"pushViewCode": "Как да използвате Push монитор? (Вижте кода)",
"pushOthers": "Други",
"programmingLanguages": "Програмни езици",
"authInvalidToken": "Невалиден токен.",
"authUserInactiveOrDeleted": "Потребителят е неактивен или изтрит.",
"authIncorrectCreds": "Неправилно потребителско име или парола.",
"2faAlreadyEnabled": "2FA вече е активирано.",
"2faEnabled": "2FA е активирано.",
"2faDisabled": "2FA е деактивирано.",
"successAdded": "Добавен успешно.",
"successPaused": "Успешно поставен на пауза.",
"successDeleted": "Успешно изтрит.",
"successEdited": "Успешно редактиран.",
"successBackupRestored": "Резервното копие е възстановено успешно.",
"successDisabled": "Успешно деактивиран.",
"successEnabled": "Успешно активиран.",
"tagNotFound": "Етикетът не е намерен.",
"successResumed": "Успешно възобновен.",
"successAuthChangePassword": "Паролата е актуализирана успешно.",
"foundChromiumVersion": "Намерен Chromium/Chrome. Версия: {0}"
}

@ -653,7 +653,7 @@
"Server Timezone": "Časové pásmo serveru",
"statusPageMaintenanceEndDate": "Konec",
"IconUrl": "Adresa URL ikony",
"Enable DNS Cache": "Povolit DNS Cache pro HTTP(s) dohledy",
"Enable DNS Cache": "(Zastaralé) Povolit DNS Cache pro HTTP(s) dohledy",
"Enable": "Povolit",
"Disable": "Zakázat",
"dnsCacheDescription": "V některých IPv6 prostředích nemusí fungovat. Pokud narazíte na nějaké problémy, tuto možnost vypněte.",
@ -838,5 +838,37 @@
"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: Guess Port",
"Saved.": "Uloženo.",
"setupDatabaseChooseDatabase": "Kterou databázi chcete použít?",
"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.",
"dbName": "Název databáze",
"enableNSCD": "Povolit NSCD (Name Service Cache Daemon) pro cachování všech DNS požadavků",
"toastErrorTimeout": "Časový limit pro oznámení o chybách",
"toastSuccessTimeout": "Časový limit pro oznámení o úspěchu",
"Bark API Version": "Verze API Bark",
"authInvalidToken": "Neplatný token.",
"2faAlreadyEnabled": "2FA je již aktivní.",
"2faEnabled": "2FA aktivní.",
"2faDisabled": "2FA neaktivní.",
"successResumed": "Úspěšně obnoveno.",
"successPaused": "Úspěšně pozastaveno.",
"successDeleted": "Úspěšně smazáno.",
"successEdited": "Úspěšně upraveno.",
"successBackupRestored": "Záloha byla úspěšně obnovena.",
"successDisabled": "Úspěšně zakázáno.",
"successEnabled": "Úspěšně povoleno.",
"tagNotFound": "Štítek nebyl nalezen.",
"foundChromiumVersion": "Nalezeno Chromium/Chrom. Verze: {0}",
"authUserInactiveOrDeleted": "Uživatel je neaktivní nebo smazaný.",
"authIncorrectCreds": "Nesprávné uživatelské jméno nebo heslo.",
"successAdded": "Úspěšně přidáno.",
"successAuthChangePassword": "Heslo bylo úspěšně aktualizováno.",
"pushOthers": "Ostatní",
"programmingLanguages": "Programovací jazyky",
"monitorToastMessagesLabel": "Upozornění Monitor Toast",
"monitorToastMessagesDescription": "Upozornění Toast zmizí po uplynutí nastaveného času. Časový limit vypnete nastavením -1. Upozornění vypnete nastavením 0.",
"pushViewCode": "Jak používat Push monitor? (Zobrazit kód)"
}

@ -1,5 +1,5 @@
{
"languageName": "Danish (Danmark)",
"languageName": "Dansk",
"Settings": "Indstillinger",
"Dashboard": "Betjeningspanel",
"New Update": "Opdatering tilgængelig",
@ -8,10 +8,10 @@
"Theme": "Tema",
"General": "Generelt",
"Version": "Version",
"Check Update On GitHub": "Tjek efter opdateringer på Github",
"Check Update On GitHub": "Tjek efter opdateringer på GitHub",
"List": "Liste",
"Add": "Tilføj",
"Add New Monitor": "Tilføj ny Overvåger",
"Add New Monitor": "Tilføj ny overvågning",
"Quick Stats": "Oversigt",
"Up": "Aktiv",
"Down": "Inaktiv",
@ -25,7 +25,7 @@
"Message": "Beskeder",
"No important events": "Ingen vigtige begivenheder",
"Resume": "Fortsæt",
"Edit": "Rediger",
"Edit": "Redigér",
"Delete": "Slet",
"Current": "Aktuelt",
"Uptime": "Oppetid",
@ -37,7 +37,7 @@
"checkEverySecond": "Tjek hvert {0} sekund",
"Response": "Respons",
"Ping": "Ping",
"Monitor Type": "Overvåger type",
"Monitor Type": "Overvågningstype",
"Keyword": "Nøgleord",
"Friendly Name": "Visningsnavn",
"URL": "URL",
@ -47,7 +47,7 @@
"Retries": "Gentagelser",
"retriesDescription": "Maksimalt antal gentagelser, før tjenesten markeres som inaktiv og sender en meddelelse.",
"Advanced": "Avanceret",
"ignoreTLSError": "Ignorere TLS/SSL web fejl",
"ignoreTLSError": "Ignorér TLS/SSL fejl for HTTPS websteder",
"Upside Down Mode": "Omvendt tilstand",
"upsideDownModeDescription": "Håndter tilstanden omvendt. Hvis tjenesten er tilgængelig, vises den som inaktiv.",
"Max. Redirects": "Maks. Omdirigeringer",
@ -69,17 +69,17 @@
"Search Engine Visibility": "Søgemaskine synlighed",
"Allow indexing": "Tillad indeksering",
"Discourage search engines from indexing site": "Frabed søgemaskiner at indeksere webstedet",
"Change Password": "Ændre adgangskode",
"Change Password": "Skift adgangskode",
"Current Password": "Nuværende adgangskode",
"New Password": "Ny adgangskode",
"Repeat New Password": "Gentag den nye adgangskode",
"passwordNotMatchMsg": "Adgangskoderne er ikke ens.",
"Update Password": "Opdater adgangskode",
"Disable Auth": "Deaktiver autentificering",
"Enable Auth": "Aktiver autentificering",
"Update Password": "Opdatér adgangskode",
"Disable Auth": "Deaktivér autentifikation",
"Enable Auth": "Aktivér autentifikation",
"Logout": "Log ud",
"notificationDescription": "Tildel underretninger til Overvåger(e), så denne funktion træder i kraft.",
"Leave": "Verlassen",
"Leave": "Forlad",
"I understand, please disable": "Jeg er indforstået, deaktiver venligst",
"Confirm": "Bekræft",
"Yes": "Ja",
@ -88,7 +88,7 @@
"Password": "Adgangskode",
"Remember me": "Husk mig",
"Login": "Log ind",
"No Monitors, please": "Ingen Overvågere",
"No Monitors, please": "Ingen overvågninger",
"add one": "tilføj en",
"Notification Type": "Underretningstype",
"Email": "E-Mail",
@ -101,7 +101,7 @@
"Resolver Server": "Navne-server",
"rrtypeDescription": "Vælg den type RR, du vil overvåge.",
"Last Result": "Seneste resultat",
"pauseMonitorMsg": "Er du sikker på, at du vil standse Overvågeren?",
"pauseMonitorMsg": "Er du sikker på at du vil standse overvågningen?",
"Create your admin account": "Opret din administratorkonto",
"Repeat Password": "Gentag adgangskoden",
"Resource Record Type": "Resource Record Type",
@ -130,14 +130,14 @@
"confirmEnableTwoFAMsg": "Er du sikker på at du vil aktivere 2FA?",
"confirmDisableTwoFAMsg": "Er du sikker på at du vil deaktivere 2FA?",
"Apply on all existing monitors": "Anvend på alle eksisterende overvågere",
"Verify Token": "Verificere Token",
"Verify Token": "Bekræft nøgle",
"Setup 2FA": "Opsæt 2FA",
"Enable 2FA": "Aktiver 2FA",
"Disable 2FA": "Deaktiver 2FA",
"2FA Settings": "2FA Indstillinger",
"Two Factor Authentication": "To-Faktor Autentificering",
"Active": "Aktive",
"Inactive": "Inaktive",
"Active": "Aktiv",
"Inactive": "Inaktiv",
"Token": "Token",
"Show URI": "Vis URI",
"Clear all statistics": "Ryd alle Statistikker",
@ -145,16 +145,16 @@
"importHandleDescription": "Vælg 'Spring over eksisterende', hvis du vil springe over hver overvåger eller underretning med samme navn. 'Overskriv' sletter alle eksisterende overvågere og underretninger.",
"confirmImportMsg": "Er du sikker på at importere sikkerhedskopien? Sørg for, at du har valgt den rigtige importindstilling.",
"Heartbeat Retry Interval": "Hjerteslag gentagelsesinterval",
"Import Backup": "Importer Backup",
"Export Backup": "Eksporter Backup",
"Import Backup": "Importér Backup",
"Export Backup": "Eksportér Backup",
"Skip existing": "Spring over eksisterende",
"Overwrite": "Overskriv",
"Options": "Valgmuligheder",
"Keep both": "Behold begge",
"Tags": "Etiketter",
"Add New below or Select...": "Tilføj Ny nedenfor eller Vælg…",
"Tag with this name already exist.": "Et Tag med dette navn findes allerede.",
"Tag with this value already exist.": "Et Tag med denne værdi findes allerede.",
"Tag with this name already exist.": "En etiket med dette navn findes allerede.",
"Tag with this value already exist.": "En etiket med denne værdi findes allerede.",
"color": "farve",
"value (optional)": "værdi (valgfri)",
"Gray": "Grå",
@ -175,8 +175,8 @@
"Partially Degraded Service": "Delvist forringet service",
"Degraded Service": "Forringet service",
"Add Group": "Tilføj Gruppe",
"Add a monitor": "Tilføj en Overvåger",
"Edit Status Page": "Rediger Statusside",
"Add a monitor": "Tilføj en overvågning",
"Edit Status Page": "Redigér Statusside",
"Go to Dashboard": "Gå til Betjeningspanel",
"Status Page": "Statusside",
"Status Pages": "Statusside",
@ -228,7 +228,7 @@
"wayToGetDiscordURL": "Du kan få dette ved at gå til Serverindstillinger -> Integrationer -> Opret webhook",
"Bot Display Name": "Bot Visningsnavn",
"Prefix Custom Message": "Præfiks Brugerdefineret Besked",
"Hello @everyone is...": "Hello {'@'}everyone is...",
"Hello @everyone is...": "Hej {'@'}alle er…",
"Webhook URL": "Webhook URL",
"wayToGetTeamsURL": "Du kan lære, hvordan du laver en webhook URL {0}.",
"Number": "Nummer",
@ -239,7 +239,7 @@
"Application Token": "Program Token",
"Server URL": "Server URL",
"Priority": "Prioritet",
"Icon Emoji": "Icon Emoji",
"Icon Emoji": "Ikon Emoji",
"Channel Name": "Kanalnavn",
"Uptime Kuma URL": "Uptime Kuma URL",
"aboutWebhooks": "Mere info om Webhooks på: {0}",
@ -271,8 +271,8 @@
"Read more": "Læs mere",
"appriseInstalled": "Apprise er installeret.",
"appriseNotInstalled": "Apprise er ikke installeret. {0}",
"Access Token": "Access Token",
"Channel access token": "kanaladgangstoken",
"Access Token": "Adgangsnøgle",
"Channel access token": "Kanal adgangsnøgle",
"Line Developers Console": "Line Udviklerkonsol",
"lineDevConsoleTo": "Line Udviklerkonsol - {0}",
"Basic Settings": "Basisindstillinger",
@ -300,7 +300,7 @@
"PushUrl": "Push URL",
"HeadersInvalidFormat": "\"request headers\"-erne er ikke gyldige JSON: ",
"BodyInvalidFormat": "\"request body\"-en er ikke gyldige JSON: ",
"Monitor History": "Overvåger Historik",
"Monitor History": "Overvågningshistorik",
"clearDataOlderThan": "Gem overvågningshistorikdata i {0} dage.",
"PasswordsDoNotMatch": "Adgangskoderne stemmer ikke overens.",
"records": "forekomster",
@ -337,7 +337,7 @@
"Show Tags": "Vis Etiketter",
"Hide Tags": "Skjul Etiketter",
"Description": "Beskrivelse",
"No monitors available.": "No monitors available.",
"No monitors available.": "Ingen tilgængelige overvågninger.",
"Add one": "Tilføj en",
"No Monitors": "Ingen Overvågere",
"Untitled Group": "Unavngivet Gruppe",
@ -360,7 +360,7 @@
"From Name/Number": "Fra Navn/Nummer",
"Help": "Hjælp",
"Please use this option carefully!": "Brug venligst denne funktion med forsigtighed!",
"disableauth.message1": "Er du sikker på, at du vil <strong>deaktivere authentication</strong>?",
"disableauth.message1": "Er du sikker på, at du vil <strong>deaktivere autentifikation</strong>?",
"successMessage": "Succesmeddelelse",
"error": "fejl",
"critical": "kritisk",
@ -386,15 +386,15 @@
"Notification Service": "Notifikationstjeneste",
"Domain": "Domæne",
"Google Analytics ID": "Google Analytics ID",
"Edit Tag": "Ændre Tag",
"Edit Tag": "Redigér etiket",
"Learn More": "Lær mere",
"Schedule maintenance": "Planlæg vedligeholdelse",
"Invalid": "Ugyldig",
"User": "Bruger",
"Installed": "Installeret",
"Not installed": "Ikke installeret",
"Running": "Køre",
"Not running": "Køre ikke",
"Running": "Kører",
"Not running": "Kører ikke",
"Remove Token": "Fjern Token",
"Start": "Start",
"Stop": "Stop",
@ -412,7 +412,7 @@
"Trust Proxy": "Trust Proxy",
"For example: nginx, Apache and Traefik.": "For eksempel: nginx, Apache og Traefik.",
"Please read": "Læs venligst",
"Show Powered By": "Vis Powered By",
"Show Powered By": "Vis Drevet af",
"Domain Names": "Domænenavne",
"signedInDisp": "Logget ind som {0}",
"Certificate Expiry Notification": "Meddelelse om udløbsdato for certifikatet",
@ -448,7 +448,7 @@
"loadingError": "Kan ikke hente dataene, prøv igen senere.",
"Custom": "Brugerdefineret",
"Monitor": "Overvåger | Overvågere",
"Specific Monitor Type": "Specifik monitor-type",
"Specific Monitor Type": "Specifik overvågningstype",
"topic": "Emne",
"Fingerprint:": "Fingerprint:",
"Issuer:": "Udsteder:",
@ -472,23 +472,23 @@
"Display Timezone": "Vis tidszone",
"Server Timezone": "Serverens tidszone",
"IconUrl": "Ikon URL",
"Enable DNS Cache": "Aktiver DNS Cache",
"Enable": "Aktiver",
"Disable": "Deaktiver",
"Enable DNS Cache": "Aktivér DNS Cache",
"Enable": "Aktivér",
"Disable": "Deaktivér",
"dnsCacheDescription": "Det fungerer muligvis ikke i alle IPv6-miljøer, så deaktiver det, hvis du støder på problemer.",
"Maintenance Time Window of a Day": "Tidsvindue for vedligeholdelse af en dag",
"Schedule Maintenance": "Planlæg vedligeholdelse",
"Date and Time": "Dato og klokkeslæt",
"plugin": "Plugin | Plugins",
"install": "Installer",
"uninstall": "Afinstaller",
"install": "Installér",
"uninstall": "Afinstallér",
"uninstalling": "Afinstallerer",
"confirmUninstallPlugin": "Er du sikker på, at du vil afinstallere dette plugin?",
"installing": "Installerer",
"markdownSupported": "Markdown syntax understøttet",
"Affected Monitors": "Berørte monitors",
"Affected Monitors": "Berørte overvågninger",
"All Status Pages": "Alle statussider",
"Pick Affected Monitors...": "Vælg berørte monitors…",
"Pick Affected Monitors...": "Vælg berørte overvågninger…",
"Select status pages...": "Vælg statusside…",
"proxyDescription": "Proxyer skal være tilknyttet en monitor for at fungere.",
"Accept characters:": "Accepter tegn:",
@ -581,5 +581,44 @@
"deleteAPIKeyMsg": "Er du sikker på du vil slette denne API nøgle?",
"pagertreeDoNothing": "Gør intet",
"Start of maintenance": "Start på vedligeholdelse",
"Add New Tag": "Tilføj nyt tag"
"Add New Tag": "Tilføj ny etiket",
"setupDatabaseChooseDatabase": "Hvilken database vil du gerne bruge?",
"Saved.": "Gemt.",
"authUserInactiveOrDeleted": "Denne bruger er inaktiv eller er blevet slettet.",
"webhookBodyPresetOption": "Forudindstilling - {0}",
"filterActive": "Aktiv",
"filterActivePaused": "På pause",
"Select": "Vælg",
"selectedMonitorCount": "Valgte: {0}",
"chromeExecutableAutoDetect": "Autodetektér",
"pushyToken": "Enhedsnøgle",
"You can divide numbers with": "Du kan dividere numre med",
"alertaEnvironment": "Miljø",
"promosmsAllowLongSMS": "Tillad lang SMS",
"smseagleToken": "API Adgangsnøgle",
"twilioFromNumber": "Fra nummer",
"twilioToNumber": "Til nummer",
"twilioApiKey": "API nøgle (valgfrit)",
"ntfyUsernameAndPassword": "Brugernavn og adgangskode",
"lunaseaUserID": "Bruger ID",
"lunaseaDeviceID": "Enheds ID",
"lunaseaTarget": "Mål",
"Expiry": "Udløber",
"pushDeerServerDescription": "Efterlad blank for at bruge den officielle server",
"Close": "Luk",
"Group": "Gruppe",
"Device Token": "Enhedsnøgle",
"dbName": "Database navn",
"Monitor Group": "Overvågningsgruppe",
"telegramSendSilently": "Send lydløst",
"smseagleRecipientType": "Modtager type",
"smseagleRecipient": "Modtager(e) (Adskil med komma)",
"statusPageRefreshIn": "Genopfrisk om: {0}",
"Home": "Hjem",
"tagNotFound": "Etiket blev ikke fundet.",
"pushOthers": "Andre",
"confirmDeleteTagMsg": "Er du sikker på at du vil slette denne etiket? Overvågninger med denne etiket vil ikke blive slettet.",
"resendEveryXTimes": "Gensend hver {0} gang",
"resendDisabled": "Gensendelse deaktiveret",
"Reconnecting...": "Genforbinder..."
}

@ -658,7 +658,7 @@
"webhookAdditionalHeadersDesc": "Legt zusätzliche Kopfzeilen fest, die mit dem Webhook gesendet werden. Jede Kopfzeile sollte als JSON Schlüssel/Wert definiert werden.",
"Packet Size": "Paketgrösse",
"IconUrl": "Symbol URL",
"Enable DNS Cache": "DNS-Cache für HTTP(s)-Monitore aktivieren",
"Enable DNS Cache": "(Veraltet) DNS-Cache für HTTP(s)-Monitore aktivieren",
"Help": "Hilfe",
"Game": "Spiel",
"General Monitor Type": "Allgemeiner Monitortyp",
@ -824,7 +824,7 @@
"nostrRelays": "Nostr relays",
"nostrRelaysHelp": "Eine Relay-URL pro Zeile",
"nostrRecipients": "Öffentliche Schlüssel des Empfängers (npub)",
"gamedigGuessPort": "Gamedig: Guess Port",
"gamedigGuessPort": "Gamedig: Vermuteter Port",
"Request Timeout": "Zeitüberschreitung der Anfrage",
"styleElapsedTimeShowNoLine": "Anzeigen (keine Zeile)",
"styleElapsedTimeShowWithLine": "Anzeigen (mit Zeile)",
@ -835,5 +835,37 @@
"gamedigGuessPortDescription": "Der vom Valve Server Query Protocol verwendete Port kann sich vom Port des Clients unterscheiden. Versuche dies, wenn der Monitor keine Verbindung zum Server herstellen kann.",
"timeoutAfter": "Zeitüberschreitung nach {0} Sekunden",
"styleElapsedTime": "Verstrichene Zeit unter der Prüfintervallleiste",
"Check/Uncheck": "Aktivieren/Deaktivieren"
"Check/Uncheck": "Aktivieren/Deaktivieren",
"enableNSCD": "Aktiviere NSCD (Name Service Cache Daemon) zur Zwischenspeicherung aller DNS-Anfragen",
"setupDatabaseChooseDatabase": "Welche Datenbank möchtest du verwenden?",
"setupDatabaseEmbeddedMariaDB": "Du brauchst nichts einzustellen. Dieses Docker-Image hat automatisch eine MariaDB für dich eingerichtet und konfiguriert. Uptime Kuma wird sich mit dieser Datenbank über einen Unix-Socket verbinden.",
"dbName": "Datenbank Name",
"setupDatabaseMariaDB": "Mit externer MariaDB-Datenbank verbinden. Du musst die Verbindungsinformationen für die Datenbank festlegen.",
"setupDatabaseSQLite": "Eine einfache Datenbankdatei, empfohlen für kleinere Bereitstellungen. Vor v2.0.0 verwendete Uptime Kuma SQLite als Standarddatenbank.",
"Saved.": "Gespeichert.",
"monitorToastMessagesLabel": "Toast-Benachrichtigungen überwachen",
"toastSuccessTimeout": "Zeitüberschreitung für Erfolgsbenachrichtigungen",
"toastErrorTimeout": "Zeitüberschreitung für Fehlerbenachrichtigungen",
"monitorToastMessagesDescription": "Toast-Benachrichtigungen für Monitore verschwinden nach einer bestimmten Zeit in Sekunden. Auf -1 setzen, um die Zeitüberschreitung zu deaktivieren. Der Wert 0 deaktiviert die Toast-Benachrichtigungen.",
"Bark API Version": "Bark API Version",
"pushViewCode": "Wie verwendet man den Push-Monitor? (Code anzeigen)",
"pushOthers": "Sonstige",
"programmingLanguages": "Programmiersprachen",
"authInvalidToken": "Ungültiges Token.",
"authIncorrectCreds": "Falscher Benutzername oder falsches Passwort.",
"2faAlreadyEnabled": "2FA ist bereits aktiviert.",
"2faEnabled": "2FA ist aktiviert.",
"2faDisabled": "2FA ist deaktiviert.",
"successResumed": "Erfolgreich wiederaufgenommen.",
"successPaused": "Erfolgreich pausiert.",
"successDeleted": "Erfolgreich gelöscht.",
"successEdited": "Erfolgreich bearbeitet.",
"successBackupRestored": "Sicherung erfolgreich wiederhergestellt.",
"successEnabled": "Erfolgreich aktiviert.",
"tagNotFound": "Tag nicht gefunden.",
"foundChromiumVersion": "Gefunden Chromium/Chrome. Version: {0}",
"authUserInactiveOrDeleted": "Der Benutzer ist inaktiv oder gelöscht.",
"successAdded": "Erfolgreich hinzugefügt.",
"successAuthChangePassword": "Das Passwort wurde erfolgreich aktualisiert.",
"successDisabled": "Erfolgreich deaktiviert."
}

@ -1,5 +1,5 @@
{
"languageName": "Deutsch (Deutschland)",
"languageName": "Englisch",
"Settings": "Einstellungen",
"Dashboard": "Dashboard",
"New Update": "Aktualisierung verfügbar",
@ -253,7 +253,7 @@
"Uptime Kuma URL": "Uptime Kuma URL",
"aboutWebhooks": "Weitere Informationen zu Webhooks auf: {0}",
"aboutChannelName": "Gebe den Kanalnamen ein in {0} Feld Kanalname, falls du den Webhook-Kanal umgehen möchtest. Ex: #other-channel",
"aboutKumaURL": "Wenn das Feld für die Uptime Kuma URL leer gelassen wird, wird standardmäßig die GitHub Projekt Seite verwendet.",
"aboutKumaURL": "Wenn Sie das Feld für die Uptime Kuma URL leer lassen, wird es standardmäßig auf die Projekt-GitHub-Seite gesetzt.",
"emojiCheatSheet": "Emoji Cheat Sheet: {0}",
"User Key": "Benutzerschlüssel",
"Device": "Gerät",
@ -600,7 +600,7 @@
"Optional": "Optional",
"squadcast": "Squadcast",
"SendKey": "SendKey",
"SMSManager API Docs": "SMSManager API Dokumente",
"SMSManager API Docs": "SMSManager API Dokumente ",
"Gateway Type": "Gateway Typ",
"SMSManager": "SMSManager",
"You can divide numbers with": "Du kannst Zahlen teilen mit",
@ -644,7 +644,7 @@
"Help": "Hilfe",
"Game": "Spiel",
"Custom": "Benutzerdefiniert",
"Enable DNS Cache": "DNS-Cache für HTTP(s)-Monitore aktivieren",
"Enable DNS Cache": "(Veraltet) Aktivieren Sie den DNS-Cache für HTTP(s)-Überwachungen",
"Enable": "Aktivieren",
"Disable": "Deaktivieren",
"Custom Monitor Type": "Benutzerdefinierter Monitortyp",
@ -821,7 +821,7 @@
"pushDeerServerDescription": "Leer lassen um den offiziellen Server zu verwenden",
"FlashDuty Severity": "Schweregrad",
"nostrRelays": "Nostr relays",
"gamedigGuessPort": "Gamedig: Guess Port",
"gamedigGuessPort": "Gamedig: Vermuteter Port",
"Request Timeout": "Zeitüberschreitung der Anfrage",
"styleElapsedTimeShowNoLine": "Anzeigen (keine Zeile)",
"Select": "Auswählen",
@ -838,5 +838,37 @@
"nostrRecipients": "Öffentliche Schlüssel des Empfängers (npub)",
"nostrRecipientsHelp": "npub-Format, eine pro Zeile",
"showCertificateExpiry": "Ablauf des Zertifikats anzeigen",
"noOrBadCertificate": "Kein/schlechtes Zertifikat"
"noOrBadCertificate": "Kein/schlechtes Zertifikat",
"enableNSCD": "Aktivieren Sie NSCD (Name Service Cache Daemon) zur Zwischenspeicherung aller DNS-Anfragen",
"setupDatabaseChooseDatabase": "Welche Datenbank möchtest du verwenden?",
"setupDatabaseEmbeddedMariaDB": "Du brauchst nichts einzustellen. Dieses Docker-Image hat automatisch eine MariaDB für dich eingerichtet und konfiguriert. Uptime Kuma wird sich mit dieser Datenbank über einen Unix-Socket verbinden.",
"dbName": "Datenbank Name",
"setupDatabaseMariaDB": "Mit externer MariaDB-Datenbank verbinden. Du musst die Verbindungsinformationen für die Datenbank festlegen.",
"setupDatabaseSQLite": "Eine einfache Datenbankdatei, empfohlen für kleinere Bereitstellungen. Vor v2.0.0 verwendete Uptime Kuma SQLite als Standarddatenbank.",
"Saved.": "Gespeichert.",
"toastSuccessTimeout": "Zeitüberschreitung für Erfolgsbenachrichtigungen",
"toastErrorTimeout": "Zeitüberschreitung für Fehlerbenachrichtigungen",
"monitorToastMessagesLabel": "Toast-Benachrichtigungen überwachen",
"monitorToastMessagesDescription": "Toast-Benachrichtigungen für Monitore verschwinden nach einer bestimmten Zeit in Sekunden. Auf -1 setzen, um die Zeitüberschreitung zu deaktivieren. Der Wert 0 deaktiviert die Toast-Benachrichtigungen.",
"Bark API Version": "Bark API Version",
"pushViewCode": "Wie verwendet man den Push-Monitor? (Code anzeigen)",
"pushOthers": "Sonstige",
"programmingLanguages": "Programmiersprachen",
"authInvalidToken": "Ungültiges Token.",
"authIncorrectCreds": "Falscher Benutzername oder falsches Passwort.",
"2faAlreadyEnabled": "2FA ist bereits aktiviert.",
"2faEnabled": "2FA ist aktiviert.",
"2faDisabled": "2FA ist deaktiviert.",
"successResumed": "Erfolgreich wiederaufgenommen.",
"successPaused": "Erfolgreich pausiert.",
"successDeleted": "Erfolgreich gelöscht.",
"successEdited": "Erfolgreich bearbeitet.",
"successBackupRestored": "Sicherung erfolgreich wiederhergestellt.",
"successDisabled": "Erfolgreich deaktiviert.",
"successEnabled": "Erfolgreich aktiviert.",
"tagNotFound": "Tag nicht gefunden.",
"authUserInactiveOrDeleted": "Der Benutzer ist inaktiv oder gelöscht.",
"successAdded": "Erfolgreich hinzugefügt.",
"successAuthChangePassword": "Das Passwort wurde erfolgreich aktualisiert.",
"foundChromiumVersion": "Gefunden Chromium/Chrome. Version: {0}"
}

@ -84,7 +84,7 @@
"Push URL": "Push URL",
"needPushEvery": "You should call this URL every {0} seconds.",
"pushOptionalParams": "Optional parameters: {0}",
"pushViewCode": "View Code",
"pushViewCode": "How to use Push monitor? (View Code)",
"pushOthers": "Others",
"programmingLanguages": "Programming Languages",
"Save": "Save",
@ -244,6 +244,7 @@
"successMessage": "Success Message",
"successMessageExplanation": "MQTT message that will be considered as success",
"recent": "Recent",
"Reset Token": "Reset Token",
"Done": "Done",
"Info": "Info",
"Security": "Security",
@ -812,8 +813,8 @@
"noGroupMonitorMsg": "Not Available. Create a Group Monitor First.",
"Close": "Close",
"Request Body": "Request Body",
"wayToGetFlashDutyKey":"You can go to Channel -> (Select a Channel) -> Integrations -> Add a new integration' page, add a 'Custom Event' to get a push address, copy the Integration Key in the address. For more information, please visit",
"FlashDuty Severity":"Severity",
"wayToGetFlashDutyKey": "You can go to Channel -> (Select a Channel) -> Integrations -> Add a new integration' page, add a 'Custom Event' to get a push address, copy the Integration Key in the address. For more information, please visit",
"FlashDuty Severity": "Severity",
"nostrRelays": "Nostr relays",
"nostrRelaysHelp": "One relay URL per line",
"nostrSender": "Sender Private Key (nsec)",

@ -270,7 +270,7 @@
"Display Timezone": "Mostrar Zona Horaria",
"Server Timezone": "Servidor de Zona Horaria",
"statusPageMaintenanceEndDate": "Finaliza",
"Enable DNS Cache": "Habilitar Cache DNS de monitores HTTP(s)",
"Enable DNS Cache": "(Obsoleto) Habilitar caché DNS para monitores HTTP(s)",
"No Maintenance": "Sin Mantenimiento",
"weekdayShortSun": "Dom",
"dayOfWeek": "Día de la Semana",
@ -556,11 +556,11 @@
"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": "punto final",
"endpoint": "endpoint",
"promosmsPassword": "Contraseña API",
"pushoversounds pushover": "Pushover (predeterminado)",
"pushoversounds bike": "Bicicleta",
"pushoversounds bugle": "Bugle",
"pushoversounds bugle": "Trompeta",
"pushoversounds cashregister": "Caja Registradora",
"pushoversounds classical": "Clásica",
"pushoversounds cosmic": "Cósmico",
@ -653,18 +653,18 @@
"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 Fecha Vigente (Opcional)",
"Free Mobile User Identifier": "Identificador de Usuario de Free Mobile",
"Gateway Type": "Tipo de Puerta de Enlace",
"Gateway Type": "Tipo de puerta de enlace",
"SMSManager": "SMSManager",
"goAlertInfo": "GoAlert es una aplicación de código abierto para la programación de guardias, escaladas automatizadas y notificaciones (como SMS o llamadas de voz). ¡Involucre automáticamente a la persona adecuada, de la manera correcta y en el momento adecuado! {0}",
"Free Mobile API Key": "Clave API de Free Mobile",
"high": "alto",
"SMSManager API Docs": "Documentación API de SMSManager ",
"smseagleContact": "Nombre(s) de contacto de Guía Telefónica",
"smseagleContact": "Nombre(s) de contacto en la guía telefónica",
"smseagleToken": "Token de Acceso a la API",
"smseagleUrl": "URL del dispositivo SMSEagle",
"Legacy Octopush-DM": "Octopush-DM heredado",
"Legacy Octopush-DM": "Octopush-DM (legacy)",
"HomeAssistant": "Home Assistant",
"goAlertIntegrationKeyInfo": "Obtenga la clave de integración API genérica para el servicio en este formato \"aaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\", generalmente el valor del parámetro token de la URL copiada.",
"Topic": "Tema",
@ -676,23 +676,23 @@
"alertaRecoverState": "Estado de Recuperación",
"serwersms": "SerwerSMS.pl",
"serwersmsAPIUser": "Nombre de usuario de API (inc. webapi_ prefix)",
"smseagleGroup": "Nombre(s) de grupo de Guía Telefónica",
"smseagleGroup": "Nombre/s del grupo de la guía telefónica",
"Unpin": "Dejar de Fijar",
"Prefix Custom Message": "Prefijo personalizado",
"markdownSupported": "Sintaxis de Markdown soportada",
"Server Address": "Dirección del Servidor",
"Learn More": "Aprende Más",
"Pick a RR-Type...": "Seleccione un Tipo RR",
"Pick a RR-Type...": "Seleccione un Tipo RR",
"onebotHttpAddress": "Dirección HTTP OneBot",
"SendKey": "Clave de Envío",
"octopushAPIKey": "\"Clave API\" desde credenciales API HTTP en panel de control",
"octopushLogin": "\"Inicio de Sesión\" a partir de las credenciales API HTTP en el panel de control",
"octopushLogin": "\"Inicio de sesión\" desde credenciales API HTTP en panel de control",
"ntfy Topic": "Tema ntfy",
"Google Analytics ID": "ID Analíticas de Google",
"Edit Tag": "Editar Etiqueta",
"SignName": "Firma",
"Bark Endpoint": "Endpoint Bark",
"WebHookUrl": "WebHookUrl",
"WebHookUrl": "URL del WebHook",
"High": "Alto",
"alertaApiEndpoint": "Endpoint API",
"Body Encoding": "Codificación del cuerpo",
@ -700,7 +700,7 @@
"Expiry": "Expiración",
"API Keys": "Claves API",
"Key Added": "Clave añadida",
"Add Another": "Añadir otro",
"Add Another": "Agregar otro/a",
"Continue": "Continuar",
"Don't expire": "No caduca",
"apiKey-inactive": "Inactivo",
@ -713,7 +713,7 @@
"cloneOf": "Clon de {0}",
"pagertreeDoNothing": "No hacer nada",
"pagertreeResolve": "Resolución automática",
"pagertreeCritical": "Crítico",
"pagertreeCritical": "Crítico/a",
"pagertreeHigh": "Alto",
"pagertreeMedium": "Medio",
"pagertreeLow": "Bajo",
@ -728,7 +728,7 @@
"telegramMessageThreadIDDescription": "Opcional Identificador único para el hilo de mensajes de destino (asunto) del foro; solo para supergrupos de foros",
"telegramProtectContent": "Proteger Forwarding/Saving",
"telegramProtectContentDescription": "Si se activa, los mensajes del bot en Telegram estarán protegidos contra el reenvío y el guardado.",
"notificationRegional": "Regional",
"notificationRegional": "Regionales",
"Clone Monitor": "Clonar Monitor",
"telegramSendSilently": "Enviar en silencio",
"telegramSendSilentlyDescription": "Envía el mensaje en silencio. Los usuarios recibirán una notificación sin sonido.",
@ -747,7 +747,7 @@
"cronSchedule": "Cronograma: ",
"invalidCronExpression": "Expresión Cron invalida:{0}",
"statusPageRefreshIn": "Reinicio en: {0}",
"twilioAuthToken": "Token de Autentificación",
"twilioAuthToken": "Token de autenticación / Secreto de clave API",
"ntfyUsernameAndPassword": "Nombre de Usuario y Contraseña",
"ntfyAuthenticationMethod": "Método de Autenticación",
"Cannot connect to the socket server": "No se puede conectar al servidor socket",
@ -766,5 +766,88 @@
"filterActivePaused": "Pausado",
"Home": "Inicio",
"Expected Value": "Valor esperado",
"Json Query": "Consulta Json"
"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 <a href='https://jsonata.org/'>jsonata.org</a> para obtener documentación sobre el lenguaje de consulta. Puede encontrar un espacio de prueba <a href='https://try.jsonata.org/'>aquí</a>.",
"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.",
"chromeExecutable": "Ejecutable de Chrome/Chromium",
"Monitor Setting": "Ajustes del monitor de {0}",
"Show Clickable Link": "Mostrar enlace clickeable",
"Open Badge Generator": "Abrir generador de insignias",
"Badge Generator": "Generador de insignias de {0}",
"Badge Type": "Tipo de insignia",
"Badge Label": "Etiqueta de la insignia",
"Badge Label Color": "Color de la etiqueta de la insignia",
"Badge Color": "Color de la insignia",
"Badge Label Prefix": "Prefijo de la etiqueta de insignia",
"Badge Preview": "Vista previa de la insignia",
"Badge Up Color": "Color de la insignia superior",
"Badge Down Color": "Color de la insignia inferior",
"Badge Pending Color": "Color de la insignia pendiente",
"Badge Maintenance Color": "Color de mantenimiento de la insignia",
"Badge Warn Days": "Días de advertencia de insignia",
"Badge Down Days": "Días sin insignia",
"Badge Style": "Estilo de insignia",
"Badge URL": "URL de la insignia",
"Group": "Grupo",
"Monitor Group": "Grupo de Monitoreo",
"Kafka Brokers": "Brokers de Kafka",
"Enter the list of brokers": "Ingrese a la lista de brokers",
"Press Enter to add broker": "Presione Enter para agregar un broker",
"Kafka Topic Name": "Nombre del tema Kafka",
"Kafka Producer Message": "Mensaje del Productor de Kafka",
"Enable Kafka SSL": "Habilitar Kafka SSL",
"Kafka SASL Options": "Opciones de Kafka SASL",
"Mechanism": "Mecanismo",
"Pick a SASL Mechanism...": "Elija un mecanismo SASL...",
"Authorization Identity": "Identidad de autorización",
"AccessKey Id": "ID de clave de acceso",
"Secret AccessKey": "Secreto de la clave de acceso",
"Session Token": "Token de sesión",
"Close": "Cerrar",
"Request Body": "Cuerpo de solicitud",
"FlashDuty Severity": "Gravedad",
"nostrRelays": "Relays de Nostr",
"nostrRelaysHelp": "Una URL de retransmisión por línea",
"nostrSender": "Clave Privada del remitente (nsec)",
"nostrRecipients": "Claves públicas de destinatarios (npub)",
"nostrRecipientsHelp": "formato npub, uno por línea",
"showCertificateExpiry": "Mostrar caducidad del certificado",
"noOrBadCertificate": "Certificado Nulo/Incorrecto",
"aboutNotifyChannel": "Notificar canal activará una notificación de escritorio o móvil para todos los miembros del canal, ya sea que su disponibilidad esté activa o ausente.",
"Server URL should not contain the nfty topic": "La URL del servidor no debe contener el tema nfty",
"PushDeer Server": "Servidor PushDeer",
"pushDeerServerDescription": "Dejar en blanco para usar el servidor oficial",
"Badge Duration (in hours)": "Duración de la insignia (en horas)",
"Badge Prefix": "Prefijo del valor de la insignia",
"Badge Suffix": "Sufijo del valor de la insignia",
"Badge Label Suffix": "Sufijo de la etiqueta de insignia",
"Badge Warn Color": "Color de advertencia de insignia",
"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",
"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)",
"styleElapsedTime": "Tiempo transcurrido en la barra de latidos",
"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}",
"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.",
"Saved.": "Guardado.",
"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?",
"setupDatabaseEmbeddedMariaDB": "No necesitas configurar nada. Esta imagen docker ha incrustado y configurado un 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.",
"dbName": "Nombre de la base de datos"
}

@ -672,7 +672,7 @@
"Server Timezone": "منطقه زمانی در سرور",
"statusPageMaintenanceEndDate": "پایان",
"IconUrl": "URL آیکون",
"Enable DNS Cache": "فعال سازی کش DNS برای مانیتور های HTTP",
"Enable DNS Cache": "(منسوخ شده) فعال سازی کش DNS برای مانیتور های HTTP",
"Access Token": "توکن دسترسی",
"smtp": "ایمیل (SMTP)",
"Device": "دستگاه",
@ -808,5 +808,37 @@
"noOrBadCertificate": "بدون سرتیفیکت یا بد",
"Invert Keyword": "کلمه کلیدی معکوس",
"Expected Value": "مقدار مورد انتظار",
"Json Query": "کوئری جیسون"
"Json Query": "کوئری جیسون",
"Saved.": "ذخیره شده.",
"setupDatabaseChooseDatabase": "از چه دیتابیسی میخواهید استفاده کنید؟",
"setupDatabaseEmbeddedMariaDB": "شما نیازی نیست چیزی را تنظیم کنید . این Image داکر یک MariaDB را به طور خودکار برای شما جاسازی و پیکربندی کرده است. آپتایم کوما از طریق سوکت یونیکس به این دیتابیس متصل می شود.",
"setupDatabaseSQLite": "یک فایل دیتابیس ساده که برای استقرار در مقیاس کوچک توصیه می شود. قبل از نسخه 2.0.0، Uptime Kuma از SQLite به عنوان دیتابیس پیش فرض استفاده می کرد.",
"enableNSCD": "فعال سازی NSCD (Name Service Cache Daemon) برای کش کردن تمام ریکوئست های DNS",
"setupDatabaseMariaDB": "به یک دیتابیس خارجی MariaDB متصل شوید. شما باید اطلاعات اتصال دیتابیس را تنظیم کنید.",
"dbName": "نام دیتابیس",
"Bark API Version": "نسخه API Bark",
"monitorToastMessagesDescription": "پیام های Toasy برای مانیتورها پس از زمان معین در چند ثانیه ناپدید می‌شوند. با تنظیم آن بر روی -1 باعث غیرفعال شدن مهلت زمانی می شود. تنظیم بر روی 0 پیام های Toastرا غیرفعال می‌کند.",
"monitorToastMessagesLabel": "پیام های Monitor Toast",
"toastErrorTimeout": "تایم اوت برای پیام های خطا",
"toastSuccessTimeout": "تایم اوت برای پیام های موفقیت آمیز",
"authInvalidToken": "توکن نامعتبر است.",
"authIncorrectCreds": "نام کاربری یا رمز عبور اشتباه است.",
"2faEnabled": "تایید دو مرحله ای فعال است.",
"2faDisabled": "تایید دو مرحله ای غیرفعال است.",
"successPaused": "با موفقیت متوقف شد.",
"successDeleted": "با موفقیت حذف شد.",
"successEdited": "با موفقیت ویرایش شد.",
"successBackupRestored": "بکاپ با موفقیت بازیابی شد.",
"successDisabled": "با موفقیت غیرفعال شد.",
"successEnabled": "با موفقیت فعال شد.",
"tagNotFound": "برچسب پیدا نشد.",
"foundChromiumVersion": "کرومیوم/کروم پیدا شد. نسخه: {0}",
"pushViewCode": "چگونه از پوش مانیتور استفاده شود؟ (نگاه به کد)",
"programmingLanguages": "زبان های برنامه نویسی",
"authUserInactiveOrDeleted": "کاربر غیرفعال یا حذف شده است.",
"2faAlreadyEnabled": "تایید دومرحله ای قبلاً فعال شده است.",
"successAdded": "با موفقیت اضافه شد.",
"successResumed": "با موفقیت از سر گرفته شد.",
"successAuthChangePassword": "رمز عبور با موفقیت به روز رسانی شد.",
"pushOthers": "غیره"
}

@ -650,7 +650,7 @@
"Server Timezone": "Fuseau horaire du serveur",
"statusPageMaintenanceEndDate": "Fin",
"IconUrl": "URL vers l'icône",
"Enable DNS Cache": "Activer le cache DNS pour les sondes HTTP(s)",
"Enable DNS Cache": "(Obsolète) Activer le cache DNS pour les sondes HTTP(s)",
"Enable": "Activer",
"Disable": "Désactiver",
"dnsCacheDescription": "Il peut ne pas fonctionner dans certains environnements IPv6, désactivez-le si vous rencontrez des problèmes.",
@ -677,7 +677,7 @@
"infiniteRetention": "Définissez la valeur à 0 pour une durée de conservation infinie.",
"Monitor": "Sonde | Sondes",
"Custom": "Personnalisé",
"confirmDeleteTagMsg": "Voulez-vous vraiment supprimer cette étiquettes ? Les moniteurs associés ne seront pas supprimés.",
"confirmDeleteTagMsg": "Voulez-vous vraiment supprimer cette étiquette ? Les sondes associées ne seront pas supprimées.",
"promosmsAllowLongSMS": "Autoriser les longs SMS",
"Help": "Aide",
"Game": "Jeux",
@ -752,7 +752,7 @@
"ntfyAuthenticationMethod": "Méthode d'authentification",
"pushoverMessageTtl": "TTL Message (Secondes)",
"Show Clickable Link": "Afficher le lien cliquable",
"Show Clickable Link Description": "Si cette case est cochée, tous ceux qui ont accès à cette page d'état peuvent accéder à l'URL du moniteur.",
"Show Clickable Link Description": "Si cette case est cochée, tous ceux qui ont accès à cette page d'état peuvent accéder à l'URL de la sonde.",
"Open Badge Generator": "Ouvrir le générateur de badges",
"Badge Type": "Type de badge",
"Badge Duration": "Durée du badge",
@ -834,9 +834,41 @@
"wayToGetFlashDutyKey": "Vous pouvez aller dans Canal -> (Sélectionner un canal) -> Intégrations -> Ajouter une nouvelle page d'intégration, ajouter un \"événement personnalisé\" pour obtenir une adresse push, copier la clé d'intégration dans l'adresse. Pour plus d'informations, veuillez visiter",
"Request Timeout": "Délai d'expiration de la demande",
"timeoutAfter": "Délai dépassé après {0} secondes",
"gamedigGuessPort": "Gamedig: Devinez le port",
"gamedigGuessPort": "Gamedig : Devinez le port",
"gamedigGuessPortDescription": "Le port utilisé par Valve Server Query Protocol peut être différent du port client. Essayez ceci si la sonde ne peut pas se connecter à votre serveur.",
"styleElapsedTimeShowNoLine": "Afficher (pas de ligne)",
"styleElapsedTimeShowWithLine": "Afficher (avec ligne)",
"styleElapsedTime": "Temps écoulé sous la barre d'état"
"styleElapsedTime": "Temps écoulé sous la barre d'état",
"enableNSCD": "Activer NSCD (Name Service Cache Daemon) pour mettre en cache toutes les demandes DNS",
"setupDatabaseChooseDatabase": "Quelle base de données souhaitez-vous utiliser ?",
"setupDatabaseEmbeddedMariaDB": "Vous n'avez pas besoin de régler quoi que ce soit. Cette image docker a intégré et configuré automatiquement une MariaDB pour vous. Uptime Kuma se connectera à cette base de données via la socket unix.",
"setupDatabaseSQLite": "Un fichier de base de données simple, recommandé pour les déploiements à petite échelle. Avant la v2.0.0, Uptime Kuma utilisait SQLite comme base de données par défaut.",
"setupDatabaseMariaDB": "Connectez-vous à une base de données MariaDB externe. Vous devez définir les informations de connexion à la base de données.",
"dbName": "Nom de la base de données",
"Saved.": "Enregistré.",
"toastErrorTimeout": "Délai d'attente pour les notifications d'erreur",
"toastSuccessTimeout": "Délai d'attente pour les notifications de réussite",
"monitorToastMessagesLabel": "Surveiller les notifications Toast",
"monitorToastMessagesDescription": "Les notifications Toast pour les sondes disparaissent après un délai donné en secondes. La valeur -1 désactive le délai d'attente. La valeur 0 désactive les notifications toast.",
"Bark API Version": "Version de l'API Bark",
"pushViewCode": "Comment utiliser une sonde type « Push » (voir le code)",
"pushOthers": "Autres",
"programmingLanguages": "Langages de programmation",
"authInvalidToken": "Jeton invalide.",
"authIncorrectCreds": "Nom d'utilisateur ou mot de passe incorrects.",
"2faAlreadyEnabled": "L'authentification à deux facteurs (2FA) est déjà activée.",
"2faDisabled": "Authentification à deux facteurs (2FA) désactivée.",
"successAdded": "Ajouté avec succès.",
"successEdited": "Modifié avec succès.",
"successBackupRestored": "Sauvegarde restaurée avec succès.",
"successDisabled": "Désactivé avec succès.",
"successEnabled": "Activé avec succès.",
"tagNotFound": "Étiquette non trouvée.",
"foundChromiumVersion": "Version de Chromium/Chrome trouvée : {0}",
"successResumed": "Reprise avec succès.",
"successPaused": "Mis en pause avec succès.",
"authUserInactiveOrDeleted": "L'utilisateur est inactif ou a été supprimé.",
"2faEnabled": "Authentification à deux facteurs (2FA) activée.",
"successDeleted": "Supprimé avec succès.",
"successAuthChangePassword": "Le mot de passe a bien été mis à jour."
}

@ -102,7 +102,7 @@
"Enable Auth": "Omogući autentikaciju",
"disableauth.message1": "Jeste li sigurni da želite <strong>isključiti autentikaciju</strong>?",
"disableauth.message2": "To je za <strong>korisnike koji imaju vanjsku autentikaciju stranice</strong> ispred Uptime Kume, poput usluge Cloudflare Access.",
"Please use this option carefully!": "Pažljivo koristite ovu opciju.",
"Please use this option carefully!": "Pažljivo koristite ovu opciju!",
"Logout": "Odjava",
"Leave": "Poništi",
"I understand, please disable": "Razumijem, svejedno onemogući",
@ -158,8 +158,8 @@
"Token": "Token",
"Show URI": "Pokaži URI",
"Tags": "Oznake",
"Add New below or Select...": "Dodajte novu oznaku ispod ili odaberite...",
"Tag with this name already exist.": "Oznaka s tim nazivom već postoji",
"Add New below or Select...": "Dodajte novu oznaku ispod ili odaberite",
"Tag with this name already exist.": "Oznaka s tim nazivom već postoji.",
"Tag with this value already exist.": "Oznaka s tom vrijednošću već postoji.",
"color": "Boja",
"value (optional)": "Vrijednost (neobavezno)",
@ -171,7 +171,7 @@
"Indigo": "Indigo",
"Purple": "Ljubičasta",
"Pink": "Ružičasta",
"Search...": "Pretraga...",
"Search...": "Pretraga",
"Avg. Ping": "Prosječni odziv",
"Avg. Response": "Prosječni odgovor",
"Entry Page": "Početna stranica",
@ -213,10 +213,10 @@
"smtpBCC": "Bcc",
"discord": "Discord",
"Discord Webhook URL": "URL Discord webhooka",
"wayToGetDiscordURL": "Ovo možete dobiti tako da odete na Postavke servera -> Integracije -> Napravi webhook",
"wayToGetDiscordURL": "Ovo možete dobiti tako da odete na Postavke servera -> Integracije -> Pogledaj webhookove -> Novi webhook",
"Bot Display Name": "Nadimak Bota unutar servera",
"Prefix Custom Message": "Prefiks prilagođene poruke",
"Hello @everyone is...": "Pozdrav {'@'}everyone...",
"Hello @everyone is...": "Pozdrav {'@'}everyone",
"teams": "Microsoft Teams",
"Webhook URL": "URL webhooka",
"wayToGetTeamsURL": "Više informacija o Teams webhookovima možete pročitati {0}.",
@ -315,8 +315,8 @@
"Info": "Informacije",
"Security": "Sigurnost",
"Shrink Database": "Smanji bazu podataka",
"Pick a RR-Type...": "Odaberite vrstu DNS zapisa od navedenih...",
"Pick Accepted Status Codes...": "Odaberite HTTP statusne kodove koji će biti prihvaćeni...",
"Pick a RR-Type...": "Odaberite vrstu DNS zapisa od navedenih",
"Pick Accepted Status Codes...": "Odaberite HTTP statusne kodove koji će biti prihvaćeni",
"Steam API Key": "Steam API ključ",
"Default": "Zadano",
"HTTP Options": "HTTP Postavke",
@ -385,7 +385,7 @@
"successMessageExplanation": "MQTT poruka koja se smatra uspješnom",
"error": "greška",
"critical": "kritično",
"Customize": "Customize",
"Customize": "Prilagodi",
"Custom Footer": "Prilagođeno podnožje",
"Custom CSS": "Prilagođeni CSS",
"wayToGetPagerDutyKey": "Ključ možete dobiti odlaskom na \"Service -> Service Directory -> (Odabrani servis) -> Integrations -> Add integration\". Ovdje pretražite za \"Events API V2\". Više informacija {0}",
@ -406,7 +406,7 @@
"Certificate Chain": "Lanac certifikata",
"Valid": "Važeći",
"Invalid": "Nevažeći",
"AccessKeyId": "AccessKey ID",
"AccessKeyId": "AccessKey identifikator",
"SecretAccessKey": "AccessKey tajni ključ",
"PhoneNumbers": "Telefonski brojevi",
"TemplateCode": "Predložak koda",
@ -415,7 +415,7 @@
"Bark Endpoint": "Bark krajnja točka (endpoint)",
"Bark Group": "Bark grupa",
"Bark Sound": "Bark zvuk",
"WebHookUrl": "WebHookUrl",
"WebHookUrl": "URL webhooka",
"SecretKey": "Tajni ključ",
"For safety, must use secret key": "Korištenje tajnog ključa je obavezno",
"Device Token": "Token uređaja",
@ -447,7 +447,7 @@
"The slug is already taken. Please choose another slug.": "Slug je zauzet. Odaberite novi slug.",
"No Proxy": "Bez proxy poslužitelja",
"Authentication": "Autentikacija",
"HTTP Basic Auth": "HTTP Basic Auth",
"HTTP Basic Auth": "HTTP \"Basic\" autentifikacija",
"New Status Page": "Dodaj statusnu stranicu",
"Page Not Found": "Stranica nije pronađena",
"Reverse Proxy": "Reverzni proxy",
@ -497,36 +497,36 @@
"Recipient Number": "Broj primatelja",
"From Name/Number": "Naziv/broj pošiljatelja",
"Leave blank to use a shared sender number.": "Ostaviti prazno za korištenje dijeljenog broja pošiljatelja.",
"Octopush API Version": "Octopush verzija API-ja",
"Legacy Octopush-DM": "Legacy Octopush-DM",
"Octopush API Version": "Verzija Octopush API-ja",
"Legacy Octopush-DM": "Zastarijela Octopush-DM",
"endpoint": "krajnja točka (endpoint)",
"octopushAPIKey": "\"API ključ\" iz HTTP API postavki",
"octopushAPIKey": "\"API ključ\" iz HTTP API postavki na upravljačkoj ploči",
"octopushLogin": "\"Korisničko ime\" iz HTTP API postavki",
"promosmsLogin": "API korisničko ime",
"promosmsPassword": "API lozinka",
"pushoversounds pushover": "Pushover (default)",
"pushoversounds bike": "Bike",
"pushoversounds bugle": "Bugle",
"pushoversounds cashregister": "Cash Register",
"pushoversounds pushover": "Pushover (zadano)",
"pushoversounds bike": "Bicikl",
"pushoversounds bugle": "Truba",
"pushoversounds cashregister": "Blagajna",
"pushoversounds classical": "Classical",
"pushoversounds cosmic": "Cosmic",
"pushoversounds falling": "Falling",
"pushoversounds cosmic": "Kozmički",
"pushoversounds falling": "Padanje",
"pushoversounds gamelan": "Gamelan",
"pushoversounds incoming": "Incoming",
"pushoversounds intermission": "Intermission",
"pushoversounds magic": "Magic",
"pushoversounds mechanical": "Mechanical",
"pushoversounds pianobar": "Piano Bar",
"pushoversounds siren": "Siren",
"pushoversounds spacealarm": "Space Alarm",
"pushoversounds tugboat": "Tug Boat",
"pushoversounds alien": "Alien Alarm (long)",
"pushoversounds climb": "Climb (long)",
"pushoversounds persistent": "Persistent (long)",
"pushoversounds echo": "Pushover Echo (long)",
"pushoversounds updown": "Up Down (long)",
"pushoversounds vibrate": "Vibrate Only",
"pushoversounds none": "None (silent)",
"pushoversounds incoming": "Dolazno",
"pushoversounds intermission": "Intermisija",
"pushoversounds magic": "Čarolija",
"pushoversounds mechanical": "Mehanički",
"pushoversounds pianobar": "Bar s klavirom",
"pushoversounds siren": "Sirena",
"pushoversounds spacealarm": "Svemirski alarm",
"pushoversounds tugboat": "Remorker",
"pushoversounds alien": "Vanzemaljski alarm (dugačko)",
"pushoversounds climb": "Penjanje (dugačko)",
"pushoversounds persistent": "Uporno (dugačko)",
"pushoversounds echo": "Pushover jeka (dugačko)",
"pushoversounds updown": "Gore-dolje (dugačko)",
"pushoversounds vibrate": "Samo vibracija",
"pushoversounds none": "Utišano (bez zvuka)",
"pushyAPIKey": "Tajni API ključ",
"pushyToken": "Token uređaja",
"Show update if available": "Pokaži moguću nadogradnju",
@ -575,5 +575,294 @@
"Event data:": "Podaci eventa:",
"Then choose an action, for example switch the scene to where an RGB light is red.": "Potrebno je i odabrati akciju za izvođenje na Home Assistantu.",
"Frontend Version": "Inačica sučelja",
"Frontend Version do not match backend version!": "Inačica sučelja ne odgovara poslužitelju!"
"Frontend Version do not match backend version!": "Inačica sučelja ne odgovara poslužitelju!",
"monitorToastMessagesLabel": "Skočne obavijesti Monitora",
"toastSuccessTimeout": "Vrijeme isteka skočnih obavijesti o uspjehu",
"toastErrorTimeout": "Vrijeme isteka skočnih obavijesti o pogrešci",
"Enter the list of brokers": "Upišite popis brokera",
"Press Enter to add broker": "Pritisnite Enter za dodavanje brokera",
"Kafka Topic Name": "Naziv Kafka teme",
"Kafka Producer Message": "Poruka Kafka producera",
"Enable Kafka SSL": "Omogući SSL",
"Enable Kafka Producer Auto Topic Creation": "Omogući automatsku izradu teme za Kafka producera",
"Kafka SASL Options": "Kafka SASL opcije",
"Mechanism": "Mehanizam",
"Pick a SASL Mechanism...": "Odaberite SASL mehanizam...",
"AccessKey Id": "ID pristupnog ključa",
"Secret AccessKey": "Tajni pristupni ključ",
"Session Token": "Token sesije",
"Schedule maintenance": "Zakaži održavanje",
"Select status pages...": "Odaberi statusne stranice…",
"webhookAdditionalHeadersTitle": "Dodatna zaglavlja",
"webhookAdditionalHeadersDesc": "Postavlja dodatna polja zaglavlja koja se šalju s webhookom. Svako zaglavlje treba se definirati kao JSON par ključ-vrijednost.",
"Packet Size": "Veličina paketa",
"backupRecommend": "Umjesto toga napravite ručnu sigurnosnu kopiju cijelog volumena ili izravno direktorija s podacima (./data/).",
"No Maintenance": "Ne postoje zakazana održavanja",
"Server Timezone": "Vremenska zona poslužitelja",
"dnsCacheDescription": "Možda ne radi kako spada u nekim IPv6 okruženjima. Onemogućite ako naiđete na probleme.",
"Select": "Odaberi",
"tailscalePingWarning": "Kako biste koristili Tailscale Ping monitor, trebate instalirati Uptime Kuma bez Dockera te također instalirati Tailscale klijent na svoj poslužitelj.",
"telegramProtectContentDescription": "Ako je omogućeno, poruke bota će biti zaštićene od prosljeđivanja i spremanja.",
"enableNSCD": "Omogući NSCD (Name Service Cache Daemon) za sve DNS zahtjeve",
"chromeExecutableDescription": "Za korisnike Dockera, ako Chromium još nije instaliran, instalacija i prikaz rezultata testa može potrajati nekoliko minuta. Zauzima 1 GB prostora na disku.",
"grpcMethodDescription": "Naziv metode automatski se pretvara u camelCase format. Primjerice, \"say hello\" će se pretvoriti u \"sayHello\".",
"wayToGetKookBotToken": "Kreirajte aplikaciju i preuzmite token svog bota na {0}",
"wayToGetKookGuildID": "Uključite 'Developer Mode' za Kook u postavkama i desnom tipkom miša kliknite na guild kako biste dobili njegov ID",
"Lowcost": "Niskotarifni",
"SendKey": "Ključ za slanje (SendKey)",
"You can divide numbers with": "Možete odvojiti brojeve pomoću",
"goAlertInfo": "GoAlert je aplikacija otvorenog koda za zakazivanje poziva, automatiziranu eskalaciju i slanje obavijesti (poput SMS-a ili glasovnih poziva). Automatski obavijestite pravu osobu, na pravi način i u pravo vrijeme! {0}",
"smseagleTo": "Broj(evi) telefona",
"smseagleGroup": "Nazivi grupa telefonskog imenika",
"smseagleRecipient": "Primatelj(i) (višestruke vrijednosti moraju se odvojiti zarezom)",
"pushDeerServerDescription": "Ostavite prazno za korištenje službenog poslužitelja",
"Edit Tag": "Uredi oznaku",
"Expiry date": "Datum isteka",
"Schedule Maintenance": "Zakazivanje održavanja",
"Edit Maintenance": "Uređivanje održavanja",
"uninstall": "Deinstaliraj",
"uninstalling": "Deinstalacija",
"Badge Type": "Tip značke",
"apiKeyAddedMsg": "Vaš API ključ je dodan. Spremite ga sada jer se više neće prikazivati.",
"pagertreeDoNothing": "Ne čini ništa",
"wayToGetPagerTreeIntegrationURL": "Nakon što stvorite Uptime Kuma integraciju u aplikaciji PagerTree, kopirajte krajnju točku (endpoint). Pogledajte sve pojedinosti {0}",
"Show Clickable Link Description": "Ako je označeno, svi koji imaju pristup ovoj statusnoj stranici mogu imati pristup URL-u Monitora.",
"monitorToastMessagesDescription": "Skočne obavijesti za monitore nestaju nakon zadanog vremena u sekundama. Vrijednost od -1 onemogućuje vremensko ograničenje, 0 onemogućuje skočne obavijesti.",
"Authorization Identity": "Identitet autorizacije",
"weekdayShortThu": "Čet",
"setupDatabaseChooseDatabase": "Koju bazu podataka želite koristiti?",
"setupDatabaseEmbeddedMariaDB": "Ne morate ništa dodatno postavljati. Ovaj docker image ima ugrađenu i konfiguriranu MariaDB bazu podataka za Vas. Uptime Kuma će se spojiti na ovu bazu preko UNIX socketa.",
"setupDatabaseMariaDB": "Spojite vanjsku MariaDB bazu podataka. Morate unijeti informacije o konekciji prema bazi.",
"setupDatabaseSQLite": "Jednostavna datoteka s bazom podataka, preporuča se samo za manje implementacije. Prije inačice v2.0.0, Uptime Kuma je koristila SQLite kao zadanu bazu podataka.",
"dbName": "Naziv baze podataka",
"Start of maintenance": "Početak održavanja",
"All Status Pages": "Sve statusne stranice",
"Affected Monitors": "Zahvaćeni Monitori",
"Pick Affected Monitors...": "Odaberi zahvaćene Monitore…",
"filterActivePaused": "Pauzirano",
"Add New Tag": "Dodaj novu oznaku",
"statusPageRefreshIn": "Osvježavanje za: {0}",
"webhookCustomBodyDesc": "Prilagodite tijelo HTTP zahtjeva. Dozvoljene varijable predloška: {msg}, {heartbeat}, {monitor}.",
"webhookBodyPresetOption": "Unaprijed postavljeno - {0}",
"webhookBodyCustomOption": "Prilagođeno tijelo zahtjeva",
"selectedMonitorCount": "Odabrano: {0}",
"Check/Uncheck": "Označi/odznači",
"telegramMessageThreadID": "(Neobavezno) ID dretve poruka",
"telegramMessageThreadIDDescription": "Neobavezni jedinstveni identifikator za dretvu poruka (temu) foruma; samo za forumske supergrupe",
"telegramSendSilently": "Pošalji nečujno",
"telegramSendSilentlyDescription": "Šalje poruku nečujno. Primatelji će dobiti obavijest bez zvuka.",
"telegramProtectContent": "Zaštiti od prosljeđivanja i spremanja",
"Optional": "Neobavezno",
"or": "ili",
"weekdayShortTue": "Uto",
"weekdayShortWed": "Sri",
"weekdayShortFri": "Pet",
"weekdayShortSat": "Sub",
"dayOfWeek": "Dan u tjednu",
"dayOfMonth": "Dan u mjesecu",
"lastDay": "Posljednji dan",
"lastDay1": "Posljednji dan mjeseca",
"lastDay2": "Pretposljednji dan mjeseca",
"lastDay3": "Treći do posljednjeg dana u mjesecu",
"lastDay4": "Četvrti do posljednjeg dana u mjesecu",
"pauseMaintenanceMsg": "Jeste li sigurni da želite pauzirati?",
"maintenanceStatus-under-maintenance": "Održavanje u tijeku",
"maintenanceStatus-inactive": "Neaktivno",
"maintenanceStatus-scheduled": "Zakazano",
"maintenanceStatus-ended": "Završeno",
"maintenanceStatus-unknown": "Nepoznato",
"Display Timezone": "Prikaži vremensku zonu",
"statusPageMaintenanceEndDate": "Kraj",
"IconUrl": "URL ikone",
"Enable": "Omogući",
"Disable": "Onemogući",
"sameAsServerTimezone": "Ista kao i vremenska zona poslužitelja",
"chromeExecutable": "Izvršna datoteka za Chrome/Chromium",
"chromeExecutableAutoDetect": "Automatska detekcija",
"Single Maintenance Window": "Jednokratno održavanje",
"Maintenance Time Window of a Day": "Vrijeme održavanja u danu",
"Effective Date Range": "Efektivan raspon datuma (neobavezno)",
"Clone": "Kloniraj",
"dataRetentionTimeError": "Razdoblje zadržavanja mora biti 0 ili veće",
"infiniteRetention": "Postavite na 0 za beskonačno zadržavanje.",
"confirmDeleteTagMsg": "Jeste li sigurni da želite izbrisati ovu oznaku? Monitori povezani s ovom oznakom neće biti izbrisani.",
"enableGRPCTls": "Omogući sigurno slanje gRPC zahtjeva koristeći TLS",
"deleteMaintenanceMsg": "Jeste li sigurni da želite izbrisati ovo održavanje?",
"Guild ID": "ID za guild",
"pushoverMessageTtl": "Vrijeme isteka poruke (u sekundama)",
"Proto Method": "Metoda poziva",
"Proto Content": "Proto sadržaj",
"Economy": "Ekonomski",
"high": "visoko",
"SMSManager API Docs": "Dokumentacija SMSManager API-ja ",
"Gateway Type": "Tip poveznika (gateway)",
"Base URL": "Osnovni URL",
"goAlertIntegrationKeyInfo": "Nabavite generički integracijski API ključ za ovu uslugu u formatu \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\", koji je obično vrijednost token parametra kopiranog URL-a.",
"aboutNotifyChannel": "Ova opcija će poslati mobilnu ili desktop obavijest za sve članove kanala, bez obzira na to jesu li trenutno dostupni ili ne.",
"smseagleContact": "Nazivi kontakata telefonskog imenika",
"smseagleRecipientType": "Tip primatelja",
"smseagleToken": "Token za pristup API-ju",
"smseagleUrl": "URL Vašeg SMSEagle uređaja",
"smseagleEncoding": "Pošalji kao Unicode",
"smseaglePriority": "Prioritet poruke (0-9, zadana vrijednost je 0)",
"Server URL should not contain the nfty topic": "URL poslužitelja ne smije sadržavati temu nfty",
"PushDeer Server": "PushDeer poslužitelj",
"Custom Monitor Type": "Prilagođeni tip Monitora",
"Google Analytics ID": "Google Analytics identifikator",
"Server Address": "Adresa poslužitelja",
"Learn More": "Saznaj više",
"Body Encoding": "Vrsta sadržaja u tijelu zahtjeva",
"API Keys": "API ključevi",
"Expiry": "Istek",
"Don't expire": "Bez isteka",
"Continue": "Nastavi",
"Add Another": "Dodaj još jedan",
"Key Added": "Ključ dodan",
"Add API Key": "Dodaj API ključ",
"No API Keys": "Nema dodanih API ključeva",
"apiKey-active": "Aktivan",
"apiKey-expired": "Istekao",
"apiKey-inactive": "Neaktivan",
"Expires": "Ističe",
"disableAPIKeyMsg": "Jeste li sigurni da želite onemogućiti ovaj API ključ?",
"Generate": "Generiraj",
"pagertreeIntegrationUrl": "URL integracije",
"pagertreeUrgency": "Hitnost",
"pagertreeSilent": "Utišano",
"pagertreeLow": "Niska",
"pagertreeMedium": "Srednja",
"pagertreeHigh": "Visoka",
"pagertreeCritical": "Kritična",
"pagertreeResolve": "Automatsko rješavanje",
"lunaseaTarget": "Cilj",
"lunaseaDeviceID": "ID uređaja",
"lunaseaUserID": "Korisnički ID",
"ntfyAuthenticationMethod": "Metoda provjere autentičnosti",
"ntfyUsernameAndPassword": "Korisničko ime i lozinka",
"twilioAccountSID": "SID korisničkog računa",
"twilioAuthToken": "Token za autentifikaciju / tajni API ključ",
"twilioFromNumber": "Broj pošiljatelja",
"twilioToNumber": "Broj primatelja",
"Show Clickable Link": "Pokaži poveznicu",
"Open Badge Generator": "Otvori generator znački",
"Badge Duration (in hours)": "Trajanje značke (u satima)",
"Badge Prefix": "Prefiks vrijednosti značke",
"Badge Suffix": "Sufiks vrijednosti značke",
"Badge Label": "Natpis značke",
"Badge Label Color": "Boja natpisa značke",
"Badge Color": "Boja značke",
"Badge Label Prefix": "Prefiks natpisa značke",
"Badge Preview": "Pretpregled značke",
"Badge Label Suffix": "Sufiks natpisa značke",
"Badge Up Color": "Boja značke za dostupnost",
"Badge Down Color": "Boja značke za nedostupnost",
"Badge Pending Color": "Boja značke za monitore u tijeku",
"Badge Maintenance Color": "Boja značke za monitore u održavanju",
"Badge Warn Color": "Boja značke za upozorenje",
"Badge Warn Days": "Dani značke za upozorenje",
"Badge Down Days": "Dani značke za nedostupnost",
"Badge value (For Testing only.)": "Vrijednost značke (samo za testiranje)",
"Badge URL": "URL značke",
"Group": "Grupa",
"Monitor Group": "Grupa Monitora",
"Badge Style": "Stil značke",
"Custom": "Prilagođeno",
"styleElapsedTime": "Vremenske oznake ispod trake dostupnosti",
"styleElapsedTimeShowNoLine": "Pokaži (bez linije)",
"styleElapsedTimeShowWithLine": "Pokaži (s linijom)",
"recurringInterval": "Periodično",
"Recurring": "Ponavljajući",
"strategyManual": "Ručno aktivan/neaktivan",
"warningTimezone": "Koristi vremensku zonu poslužitelja",
"weekdayShortMon": "Pon",
"weekdayShortSun": "Ned",
"startDateTime": "Vrijeme početka",
"endDateTime": "Vrijeme završetka",
"cronExpression": "Cron izraz",
"cronSchedule": "Raspored: ",
"invalidCronExpression": "Nevaljali Cron izraz: {0}",
"Date and Time": "Datum i vrijeme",
"DateTime Range": "Vremenski raspon",
"loadingError": "Nije moguće dohvatiti podatke, pokušajte ponovno kasnije.",
"plugin": "Dodatak | Dodaci",
"install": "Instaliraj",
"installing": "Instaliranje",
"confirmUninstallPlugin": "Jeste li sigurni da želite deinstalirati ovaj dodatak?",
"notificationRegional": "Specifično za regiju",
"Clone Monitor": "Kloniraj Monitor",
"cloneOf": "Klon monitora {0}",
"wayToGetZohoCliqURL": "Možete naučiti kako kreirati URL za webhook {0}.",
"affectedMonitorsDescription": "Odaberite monitore koji će biti zahvaćeni održavanjem",
"recurringIntervalMessage": "Pokreni jednom svaki dan | Pokreni jednom svakih {0} dana",
"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 <a href='https://jsonata.org/'>jsonata.org</a> za dokumentaciju o jeziku upita. Testno okruženje možete pronaći <a href='https://try.jsonata.org/'>ovdje</a>.",
"Strategy": "Strategija",
"Free Mobile User Identifier": "Besplatni mobilni korisnički identifikator",
"Free Mobile API Key": "Besplatni mobilni ključ za API",
"Enable TLS": "Omogući TLS",
"Proto Service Name": "Naziv servisa",
"promosmsAllowLongSMS": "Dozvoli dugačke SMS-ove",
"Notify Channel": "Obavijesti cijeli kanal",
"Request Timeout": "Vrijeme isteka zahtjeva",
"timeoutAfter": "Istek nakon {0} sekundi",
"backupOutdatedWarning": "Zastarjelo: Budući da je dodano puno značajki, a ova je pomalo neodržavana, ne može generirati niti vratiti potpunu sigurnosnu kopiju.",
"Enable DNS Cache": "(Zastarijelo) Omogući DNS privremenu memoriju (cache) za HTTP(s) monitore",
"Home": "Početna",
"deleteAPIKeyMsg": "Jeste li sigurni da želite obrisati ovaj API ključ?",
"twilioApiKey": "API ključ (neobavezno)",
"Kafka Brokers": "Kafka brokeri",
"Game": "Igra",
"Passive Monitor Type": "Pasivni tip Monitora",
"markdownSupported": "Podržana je Markdown sintaksa",
"statusMaintenance": "Održavanje",
"General Monitor Type": "Općeniti tip Monitora",
"Maintenance": "Održavanje",
"Specific Monitor Type": "Određeni tip Monitora",
"Monitor": "Monitor | Monitori",
"Invert Keyword": "Obrni ključnu riječ",
"filterActive": "Aktivnost",
"Cannot connect to the socket server": "Nije moguće spojiti se na socket poslužitelj",
"Reconnecting...": "Ponovno povezivanje...",
"Expected Value": "Očekivana vrijednost",
"Json Query": "JSON upit",
"Help": "Pomoć",
"noGroupMonitorMsg": "Nije dostupno. Prvo kreirajte grupu Monitora.",
"Close": "Zatvori",
"Request Body": "Tijelo zahtjeva",
"wayToGetFlashDutyKey": "Možete otići na 'Channel' -> (Odaberite kanal) -> 'Integrations' -> 'Add a new integration' i odaberite 'Custom Event' da biste dobili push adresu. Zatim kopirajte integracijski ključ u adresu. Za više informacija posjetite",
"FlashDuty Severity": "Stupanj ozbiljnosti",
"nostrRelays": "Nostr releji",
"nostrRelaysHelp": "Jedan URL releja po liniji",
"nostrSender": "Privatni ključ pošiljatelja (nsec)",
"nostrRecipients": "Javni ključevi primatelja (npub)",
"nostrRecipientsHelp": "U formatu npub, jedan ključ po liniji",
"showCertificateExpiry": "Pokaži istek certifikata",
"noOrBadCertificate": "Nepostojeći ili nevaljali certifikat",
"gamedigGuessPort": "Gamedig: Pogodi vrijednost porta",
"gamedigGuessPortDescription": "Port koji koristi Valve Server Query Protocol može se razlikovati od klijentskog porta. Pokušajte uključiti ovu opciju ako Monitor ne može uspostaviti vezu s vašim poslužiteljem.",
"Monitor Setting": "Postavka monitora korisnika {0}",
"Badge Generator": "Generator znački korisnika {0}",
"Bark API Version": "Verzija Bark API-ja",
"authInvalidToken": "Nevažeći token.",
"authIncorrectCreds": "Pogrešno korisničko ime ili lozinka.",
"2faAlreadyEnabled": "Dvofaktorska autentifikacija je već omogućena.",
"2faDisabled": "Dvofaktorska autentifikacija je onemogućena.",
"successAdded": "Uspješno dodano.",
"successPaused": "Uspješno pauzirano.",
"successEdited": "Uspješno uređeno.",
"successAuthChangePassword": "Lozinka je uspješno ažurirana.",
"successBackupRestored": "Sigurnosna kopija je uspješno vraćena.",
"successDisabled": "Uspješno onemogućeno.",
"successEnabled": "Uspješno omogućeno.",
"foundChromiumVersion": "Pronađen program Chromium ili Chrome. Inačica: {0}",
"pushViewCode": "Kako koristiti Monitor Push? (Prikaži kôd)",
"programmingLanguages": "Programski jezici",
"authUserInactiveOrDeleted": "Korisnik je neaktivan ili obrisan.",
"2faEnabled": "Dvofaktorska autentifikacija je omogućena.",
"successResumed": "Uspješno nastavljeno.",
"successDeleted": "Uspješno obrisano.",
"tagNotFound": "Oznaka nije pronađena.",
"pushOthers": "Ostali"
}

@ -31,7 +31,7 @@
"confirmDisableTwoFAMsg": "Apakah Anda yakin ingin menonaktifkan 2FA?",
"Settings": "Pengaturan",
"Dashboard": "Dasbor",
"New Update": "Update terbaru",
"New Update": "Pembaruan Baru",
"Language": "Bahasa",
"Appearance": "Tampilan",
"Theme": "Tema",
@ -584,7 +584,7 @@
"Game": "Permainan",
"markdownSupported": "Dukungan sintaks markdown",
"statusMaintenance": "Pemeliharaan",
"Maintenance": "Pemeliharaan",
"Maintenance": "Tidak Ada Pemeliharaan",
"General Monitor Type": "Tipe Monitor Umum",
"Passive Monitor Type": "Tipe Monitor Pasif",
"Specific Monitor Type": "Tipe Monitor Spesifik",
@ -788,5 +788,10 @@
"Badge Pending Color": "Warna Lencana Tertunda",
"Monitor Group": "Monitor Grup",
"Expected Value": "Value yang diharapkan",
"Json Query": "Json Query"
"Json Query": "Json Query",
"setupDatabaseSQLite": "File database sederhana, direkomendasikan untuk penerapan skala kecil. Sebelum v2.0.0, Uptime Kuma menggunakan SQLite sebagai database default.",
"setupDatabaseMariaDB": "Hubungkan ke database MariaDB eksternal. Anda perlu mengatur informasi koneksi database.",
"setupDatabaseEmbeddedMariaDB": "Anda tidak perlu mengatur apa pun. Docker Image ini telah menyematkan dan mengonfigurasi MariaDB untuk Anda secara otomatis. Uptime Kuma akan terhubung ke database ini melalui soket unix.",
"setupDatabaseChooseDatabase": "Database mana yang ingin Anda gunakan?",
"dbName": "Nama Database"
}

@ -610,5 +610,6 @@
"Expected Value": "Valore atteso",
"Json Query": "Query Json",
"deleteMaintenanceMsg": "Sei sicuro di voler cancellare questa attività di manutenzione?",
"dnsPortDescription": "Porta server DNS. Default 53. Puoi cambiare questa porta in ogni momento."
"dnsPortDescription": "Porta server DNS. Default 53. Puoi cambiare questa porta in ogni momento.",
"setupDatabaseChooseDatabase": "Quale database vuoi usare?"
}

@ -552,5 +552,18 @@
"Lowcost": "低コスト",
"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": "絵文字アイコン"
"Icon Emoji": "絵文字アイコン",
"setupDatabaseChooseDatabase": "どのデータベースを利用しますか?",
"setupDatabaseEmbeddedMariaDB": "何も設定する必要はありません。この Docker イメージは設定済みの MariaDB が組み込まれています。Uptime Kuma はこのデータベースに unix ソケットを通じて接続します。",
"setupDatabaseSQLite": "小規模な開発のために推奨される小さなデータベースファイルです。v2.0.0 以前は、Uptime Kuma は SQLite を標準のデータベースとして使用していました。",
"tailscalePingWarning": "Tailscale Ping モニターを使用するためには、Uptime Kuma を Docker を利用せずインストールし、そのうえで Tailscale Client をサーバーにインストールしてください。",
"invertKeywordDescription": "キーワードが含まれているものではなく、含まれないものを探します。",
"setupDatabaseMariaDB": "外部の MariaDB データベースに接続するためには、データベースの接続情報を設定する必要があります。",
"dbName": "データベース名",
"Request Timeout": "リクエストタイムアウト",
"timeoutAfter": "{0} 秒後にタイムアウト",
"selectedMonitorCount": "選択済み: {0}",
"Long-Lived Access Token": "Long-Lived Access Token",
"Invert Keyword": "「含まない」キーワード",
"Expected Value": "期待値"
}

@ -54,7 +54,7 @@
"Delete": "삭제",
"Current": "현재",
"Uptime": "업타임",
"Cert Exp.": "인증서 만료",
"Cert Exp.": "인증서 만료.",
"day": "일",
"-day": "-일",
"hour": "시간",
@ -84,7 +84,7 @@
"Theme - Heartbeat Bar": "테마 - 하트비트 바",
"Normal": "기본값",
"Bottom": "가운데",
"None": "없애기",
"None": "없",
"Timezone": "시간대",
"Search Engine Visibility": "검색 엔진 활성화",
"Allow indexing": "인덱싱 허용",
@ -749,5 +749,15 @@
"lunaseaDeviceID": "기기 ID",
"statusPageRefreshIn": "{0} 후 새로고침",
"telegramMessageThreadIDDescription": "포럼의 대상 메시지 쓰레드(주제)에 대한 선택적 고유 식별인, 포럼 관리자 그룹에만 해당",
"pagertreeSilent": "없음"
"pagertreeSilent": "없음",
"setupDatabaseChooseDatabase": "어떤 데이터베이스를 사용하시겠습니까?",
"setupDatabaseEmbeddedMariaDB": "추가 설정은 필요 없습니다. 이 도커 이미지는 MariaDB가 내장되어 구성되어 있습니다. Uptime Kuma는 Unix Socket을 통해 데이터베이스에 연결합니다.",
"setupDatabaseMariaDB": "외부 MariaDB 데이터베이스에 연결합니다. 데이터베이스 연결 정보를 설정해야 합니다.",
"setupDatabaseSQLite": "소규모 배포에 권장되는 간단한 데이터베이스 파일입니다. v2.0.0 이전에는 Uptime Kuma가 SQLite를 기본 데이터베이스로 사용했습니다.",
"dbName": "데이터베이스 이름",
"filterActive": "활성화",
"filterActivePaused": "일시중지",
"Home": "홈",
"Cannot connect to the socket server": "소켓 서버에 연결 할 수 없습니다",
"Reconnecting...": "재 연결중..."
}

@ -24,5 +24,30 @@
"Dashboard": "Papan pemuka",
"Language": "Bahasa",
"Add New Monitor": "Tambah monitor baharu",
"Passive Monitor Type": "Jenis monitor pasif"
"Passive Monitor Type": "Jenis monitor pasif",
"No Services": "Tiada Servis",
"Add a monitor": "Tambah Monitor",
"High": "Tinggi",
"Normal": "Biasa",
"Bottom": "Bawah",
"None": "None",
"All Systems Operational": "Semua Sistem Baik",
"Partially Degraded Service": "Perkhidmatan Separa Tergendala",
"Degraded Service": "Perkhidmatan Tergendala",
"Add Group": "Tambah Kumpulan",
"Edit Status Page": "Ubah Laman Status",
"Go to Dashboard": "Ke Dashboard",
"Status Page": "Laman Status",
"Status Pages": "Laman Status",
"Avg. Ping": "Ping Purata",
"Avg. Response": "Respons Purata",
"color": "Warna",
"Active": "Aktif",
"Inactive": "Nyahaktif",
"Blue": "Biru",
"Red": "MErah",
"Content Type": "Jenis Content",
"Home": "Laman Utama",
"Settings": "Tetapan",
"Save": "Simpan"
}

@ -659,7 +659,7 @@
"Disable": "Wyłącz",
"Date and Time": "Data i czas",
"IconUrl": "URL ikony",
"Enable DNS Cache": "Włącz pamięć podręczną DNS dla monitorów HTTP",
"Enable DNS Cache": "(Przestarzałe) Włącz pamięć podręczną DNS dla monitorów HTTP",
"Single Maintenance Window": "Pojedyncze okno konserwacji",
"Effective Date Range": "Zakres dat obowiązywania (opcjonalnie)",
"Schedule Maintenance": "Planowanie konserwacji",
@ -838,5 +838,37 @@
"noOrBadCertificate": "Brak/zły certyfikat",
"Invert Keyword": "Odwróć słowo kluczowe",
"Expected Value": "Oczekiwana wartość",
"Json Query": "Zapytanie Json"
"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ć?",
"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.",
"dbName": "Nazwa bazy danych",
"toastErrorTimeout": "Limit czasu dla powiadomień o błędach",
"monitorToastMessagesLabel": "Powiadomienie Toast Monitora",
"monitorToastMessagesDescription": "Powiadomienia toast dla monitorów znikają po określonym czasie w sekundach. Ustawienie -1 wyłącza limit czasu. Ustawienie 0 wyłącza powiadomienia toast.",
"authInvalidToken": "Nieprawidłowy token.",
"authIncorrectCreds": "Nieprawidłowa nazwa użytkownika lub hasło.",
"2faAlreadyEnabled": "2FA jest już włączone.",
"2faEnabled": "2FA włączone.",
"2faDisabled": "2FA wyłączone.",
"successAdded": "Pomyślnie dodano.",
"successPaused": "Wstrzymano pomyślnie.",
"successDeleted": "Usunięto pomyślnie.",
"successEdited": "Edytowano pomyślnie.",
"successAuthChangePassword": "Hasło zostało pomyślnie zaktualizowane.",
"successDisabled": "Wyłączono pomyślnie.",
"successEnabled": "Włączono pomyślnie.",
"tagNotFound": "Nie znaleziono tagu.",
"foundChromiumVersion": "Znaleziono Chromium/Chrome. Wersja: {0}",
"authUserInactiveOrDeleted": "Użytkownik jest nieaktywny lub usunięty.",
"successResumed": "Wznowiono pomyślnie.",
"successBackupRestored": "Kopia zapasowa została pomyślnie przywrócona.",
"pushViewCode": "Jak korzystać z monitora Push? (wyświetl kod)",
"Bark API Version": "Wersja API Bark",
"pushOthers": "Inne",
"programmingLanguages": "Języki programowania",
"toastSuccessTimeout": "Limit czasu dla powiadomień o powodzeniu"
}

@ -10,7 +10,7 @@
"passwordNotMatchMsg": "A senha repetida não corresponde.",
"notificationDescription": "Atribua uma notificação ao (s) monitor (es) para que funcione.",
"keywordDescription": "Pesquise a palavra-chave em html simples ou resposta JSON e diferencia maiúsculas de minúsculas.",
"pauseDashboardHome": "Pausar",
"pauseDashboardHome": "Pausado",
"deleteMonitorMsg": "Tem certeza de que deseja excluir este monitor?",
"deleteNotificationMsg": "Tem certeza de que deseja excluir esta notificação para todos os monitores?",
"resolverserverDescription": "Cloudflare é o servidor padrão, você pode alterar o servidor resolvedor a qualquer momento.",
@ -63,7 +63,7 @@
"Ping": "Ping",
"Monitor Type": "Tipo de Monitor",
"Keyword": "Palavra-Chave",
"Friendly Name": "Nome Amigável",
"Friendly Name": "Apelido",
"URL": "URL",
"Hostname": "Hostname",
"Port": "Porta",
@ -196,7 +196,7 @@
"Required": "Requerido",
"webhookJsonDesc": "{0} é bom para qualquer servidor HTTP moderno, como Express.js",
"webhookAdditionalHeadersTitle": "Cabeçalhos Adicionais",
"webhookAdditionalHeadersDesc": "Define cabeçalhos adicionais enviados com o webhook.",
"webhookAdditionalHeadersDesc": "Define cabeçalhos adicionais enviados com o webhook. Cada cabeçalho deve ser definido como uma chave/valor JSON.",
"Webhook URL": "URL Do Webhook",
"Priority": "Prioridade",
"Read more": "Ver mais",
@ -306,11 +306,11 @@
"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.": "",
"Then choose an action, for example switch the scene to where an RGB light is red.": "Em seguida, escolha uma ação, por exemplo, alterar a cena onde uma luz RGB está vermelha.",
"Enable": "Habilitado",
"Disable": "Desabilitado",
"IconUrl": "URL Do Ícone",
"Enable DNS Cache": "Habilitar Cache Do DNS",
"Enable DNS Cache": "(Descontinuado) Habilitar o Cache DNS para monitores HTTP(s)",
"Single Maintenance Window": "Janela Única De Manutenção",
"dnsCacheDescription": "Pode não funcionar em alguns ambientes com IPv6, desabita caso encontre qualquer problema.",
"Messaging API": "API Da Mensageira",
@ -588,5 +588,206 @@
"wayToGetDiscordURL": "Voce pode configurar isso indo à Configurações do Servidor -> Integrações -> Ver Webhooks -> Novo Webhook",
"Home": "Início",
"Reconnecting...": "Reconectando...",
"Cannot connect to the socket server": "Não foi possível conectar ao servidor socket"
"Cannot connect to the socket server": "Não foi possível conectar ao servidor socket",
"Uptime Kuma URL": "URL do Uptime Kuma",
"Saved.": "Salvo.",
"Feishu WebHookUrl": "URL de Webhook do Feishu",
"serwersmsAPIUser": "Nome de usuário da API (incluindo o prefixo webapi_)",
"setupDatabaseEmbeddedMariaDB": "Você não precisa configurar nada. Esta imagem Docker possui o MariaDB incorporado e configurado automaticamente para você. O Uptime Kuma se conectará a este banco de dados através do soquete Unix.",
"Select": "Selecione",
"supportTelegramChatID": "Suporte para o ID de bate-papo direto / grupo / canal do chat",
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Uma lista de Serviços de Notificação pode ser encontrada no Home Assistant em \"Ferramentas de Desenvolvimento > Serviços\". Pesquise por \"notificação\" para encontrar o nome do seu dispositivo/telefone.",
"chromeExecutableAutoDetect": "Auto Detectar",
"chromeExecutableDescription": "Para os usuários do Docker, se o Chromium ainda não estiver instalado, pode demorar alguns minutos para instalar e exibir o resultado do teste. Ele ocupa 1GB de espaço em disco.",
"wayToCheckSignalURL": "Você pode checar esse link para ver como configurar um:",
"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 <a href='https://jsonata.org/'>jsonata.org</a> para a documentação sobre a linguagem de consulta. Você pode encontrar um playground <a href='https://try.jsonata.org/'>aqui</a>.",
"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)",
"pushoversounds pianobar": "Piano Bar",
"SendKey": "\"SendKey\" é uma palavra usada para notificação do ServerChan",
"goAlertInfo": "GoAlert é uma aplicação de código aberto para escalas de plantão, escalonamentos automatizados e notificações (como SMS ou chamadas de voz). Engage automaticamente a pessoa certa, da maneira certa e no momento certo! {0}",
"promosmsTypeFlash": "SMS FLASH - A mensagem será exibida automaticamente no dispositivo do destinatário. Limitado apenas aos destinatários poloneses.",
"promosmsTypeSpeed": "SMS SPEED - Maior prioridade no sistema. Muito rápido e confiável, mas custoso (cerca de duas vezes o preço do SMS FULL).",
"matrixDesc1": "Você pode encontrar o ID da sala interna olhando na seção avançada das configurações da sala em seu cliente Matrix. Deve parecer algo como !QMdRCpUIfLwsfjxye6:home.server.",
"matrixDesc2": "É altamente recomendado que você crie um novo usuário e não use o token de acesso do seu próprio usuário Matrix, pois isso permitirá acesso total à sua conta e todas as salas às quais você se juntou. Em vez disso, crie um novo usuário e convide-o apenas para a sala na qual você deseja receber a notificação. Você pode obter o token de acesso executando {0}.",
"aboutChannelName": "Digite o nome do canal no campo Nome do Canal em {0} se você deseja ignorar o canal do Webhook. Exemplo: #outro-canal",
"wayToGetPagerDutyKey": "Você pode obter isso indo para Serviço -> Diretório de Serviço -> (Selecionar um serviço) -> Integrações -> Adicionar integração. Aqui você pode procurar por \"Events API V2\". Mais informações {0}.",
"From Name/Number": "Nome/Número de Origem",
"Server URL should not contain the nfty topic": "A URL do servidor não deve conter o tópico do nfty",
"pushDeerServerDescription": "Deixe em branco para usar o servidor oficial",
"wayToGetPagerTreeIntegrationURL": "Após criar a integração do Uptime Kuma no PagerTree, copie o Endpoint. Veja detalhes completos {0}",
"setupDatabaseChooseDatabase": "Qual banco de dados você deseja usar?",
"setupDatabaseMariaDB": "Conectar a um banco de dados MariaDB externo. Você precisa definir as informações de conexão com o banco de dados.",
"setupDatabaseSQLite": "Um arquivo de banco de dados simples, recomendado para implantações de pequena escala. Antes da versão 2.0.0, o Uptime Kuma usava o SQLite como banco de dados padrão.",
"dbName": "Nome do Banco de Dados",
"styleElapsedTimeShowNoLine": "Mostrar (Sem Linha)",
"styleElapsedTimeShowWithLine": "Mostrar (Com Linha)",
"filterActive": "Ativo",
"filterActivePaused": "Pausado",
"selectedMonitorCount": "Selecione: {0}",
"enableNSCD": "Habilitar o NSCD (Name Service Cache Daemon) para o cache de todas as solicitações DNS",
"chromeExecutable": "Executável do Chrome/Chromium",
"Edit Maintenance": "Editar Manutenção",
"aboutIconURL": "Você pode fornecer um link para uma imagem em \"URL do Ícone\" para substituir a imagem de perfil padrão. Não será usado se o \"Ícone Emoji\" estiver configurado.",
"octopushAPIKey": "\"Chave API\" das credenciais da API HTTP no painel de controle.",
"octopushLogin": "\"Login\" das credenciais da API HTTP no painel de controle.",
"pushoversounds pushover": "Pushover (padrão)",
"pushoversounds bike": "Bicicleta",
"pushoversounds bugle": "Corneta",
"pushoversounds cashregister": "Caixa registradora",
"pushoversounds classical": "Clássico",
"pushoversounds cosmic": "Cósmico",
"pushoversounds falling": "Cair",
"pushoversounds gamelan": "Gamelão",
"pushoversounds incoming": "Entrada",
"checkPrice": "Verifique os preços de {0}:",
"Check octopush prices": "Verifique os preços da octopush {0}.",
"octopushPhoneNumber": "Número de telefone (formato internacional, por exemplo: +33612345678) ",
"LunaSea Device ID": "ID do Dispositivo LunaSea",
"Apprise URL": "URL do Apprise",
"Strategy": "Estratégia",
"Free Mobile User Identifier": "Identificador de Usuário Free Mobile",
"Free Mobile API Key": "Chave da API Free Mobile",
"Enable TLS": "Habilitar TLS",
"Proto Service Name": "Nome do Serviço Proto",
"Proto Method": "Método Proto",
"Proto Content": "Conteúdo Proto",
"Economy": "Economia",
"Lowcost": "Baixo Custo",
"high": "alto",
"pushoversounds intermission": "Intervalo",
"pushoversounds magic": "Mágico",
"pushoversounds mechanical": "Mecânico",
"pushoversounds siren": "Sirene",
"pushoversounds spacealarm": "Alarme Espacial",
"pushoversounds tugboat": "Rebocador",
"pushoversounds alien": "Alarme Alienígena (longo)",
"pushoversounds climb": "Subir (longo)",
"pushoversounds persistent": "Persistente (longo)",
"pushoversounds echo": "Eco pushover (longo)",
"pushoversounds updown": "Up Down (longo)",
"SMSManager API Docs": "Docs da API SMSManager ",
"Gateway Type": "Tipo de gateway",
"You can divide numbers with": "Você pode dividir números com",
"Base URL": "URL base",
"goAlertIntegrationKeyInfo": "Obtenha a chave de integração genérica da API para o serviço neste formato \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\", geralmente o valor do parâmetro token da URL copiada.",
"AccessKeyId": "ID da Chave de Acesso",
"promosmsTypeFull": "SMS FULL - Nível premium de SMS, você pode usar o seu Nome do Remetente (é necessário registrar o nome primeiro). Confiável para alertas.",
"promosmsPhoneNumber": "Número de telefone (para destinatários poloneses, você pode pular os códigos de área)",
"promosmsSMSSender": "Nome do Remetente de SMS: Nome pré-registrado ou um dos padrões: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
"matrixHomeserverURL": "URL do Servidor (com http(s):// e opcionalmente a porta)",
"Notify Channel": "Canal de Notificação",
"aboutNotifyChannel": "O canal de notificação acionará uma notificação na área de trabalho ou no dispositivo móvel para todos os membros do canal, independentemente de sua disponibilidade estar definida como ativa ou ausente.",
"signalImportant": "IMPORTANTE: Você não pode misturar grupos e números nos destinatários!",
"aboutKumaURL": "Se você deixar o campo URL do Uptime Kuma em branco, ele será definido como padrão para a página do GitHub do projeto.",
"smtpDkimDesc": "Por favor, consulte o DKIM do Nodemailer em {0} para obter instruções de uso.",
"Auto resolve or acknowledged": "Auto resolva ou reconhecido",
"auto acknowledged": "reconhecimento automático",
"auto resolve": "resolução automática",
"alertaApiEndpoint": "Endpoint da API",
"serwersmsSenderName": "Nome do Remetente de SMS (registrado via portal do cliente)",
"smseagleGroup": "Nome(s) do grupo(s) da agenda telefônica",
"smseagleContact": "Nome(s) do(s) contato(s) da agenda telefônica",
"smseagleRecipientType": "Tipo de destinatário",
"smseagleRecipient": "Destinatário(s) (múltiplos devem ser separados por vírgula)",
"smseagleUrl": "URL do seu dispositivo SMSEagle",
"Recipient Number": "Número do Destinatário",
"Leave blank to use a shared sender number.": "Deixe em branco para usar um número de remetente compartilhado.",
"Octopush API Version": "Versão da API Octopush",
"Legacy Octopush-DM": "Octopush-DM Legado",
"ntfy Topic": "Tópico do ntfy",
"onebotHttpAddress": "Endereço HTTP do OneBot",
"onebotMessageType": "Tipo de Mensagem do OneBot",
"PushDeer Server": "Servidor PushDeer",
"PushDeer Key": "Chave PushDeer",
"wayToGetClickSendSMSToken": "Você pode obter o Nome de Usuário da API e a Chave da API em {0}.",
"Custom Monitor Type": "Tipo de Monitor Personalizado",
"Body Encoding": "Codificação do Corpo",
"API Keys": "Chaves da API",
"pagertreeSilent": "Silencioso",
"pagertreeLow": "Baixo",
"pagertreeMedium": "Médio",
"pagertreeHigh": "Alto",
"pagertreeCritical": "Crítico",
"pagertreeResolve": "Resolução Automática",
"pagertreeDoNothing": "Não fazer nada",
"lunaseaTarget": "Alvo",
"lunaseaDeviceID": "ID do Dispositivo",
"lunaseaUserID": "ID do Usuário",
"ntfyAuthenticationMethod": "Método de Autenticação",
"ntfyUsernameAndPassword": "Usuário e Senha",
"twilioAccountSID": "SID da Conta",
"twilioApiKey": "Chave da API (opcional)",
"twilioAuthToken": "Token de Autenticação / Segredo da Chave da API",
"twilioFromNumber": "Número de origem",
"twilioToNumber": "Número de destino",
"Monitor Setting": "Configuração do monitor de {0}",
"Show Clickable Link Description": "Se marcada, todos que têm acesso a esta página de status podem ter acesso ao URL do monitor.",
"Group": "Grupo",
"Monitor Group": "Grupo do Monitor",
"Request Timeout": "Tempo Limite da Solicitação",
"timeoutAfter": "Tempo limite após {0} segundos",
"webhookBodyPresetOption": "Predefinição - {0}",
"webhookBodyCustomOption": "Corpo Customizado",
"Check/Uncheck": "Marcar/Desmarcar",
"tailscalePingWarning": "Para usar o monitor Tailscale Ping, você precisa instalar o Uptime Kuma sem o Docker e também instalar o cliente Tailscale em seu servidor.",
"telegramMessageThreadIDDescription": "Identificador único opcional para o tópico da mensagem alvo do fórum; apenas para supergrupos de fóruns.",
"pushoversounds none": "Nenhum (silencioso)",
"pushyAPIKey": "Chave de API Secreta",
"pushyToken": "Token do Dispositivo",
"GoogleChat": "Google Chat (Apenas para Google Workspace)",
"wayToGetKookGuildID": "Ative o 'Modo Desenvolvedor' nas configurações do Kook e clique com o botão direito do mouse no servidor para obter seu ID.",
"Guild ID": "ID do Servidor (Guild)",
"pushoverDesc1": "A prioridade de emergência (2) possui um intervalo de 30 segundos entre as tentativas padrão e expirará após 1 hora.",
"pushoverDesc2": "Se você deseja enviar notificações para diferentes dispositivos, preencha o campo \"Dispositivo\".",
"pushoverMessageTtl": "Tempo de Vida da Mensagem (Segundos)",
"pushoversounds vibrate": "Somente vibrar",
"SecretAccessKey": "Segredo da Chave de Acesso",
"PhoneNumbers": "Números de Telefone",
"TemplateCode": "Código de Modelo",
"SignName": "Nome de Assinatura",
"Sms template must contain parameters: ": "O modelo de SMS deve conter parâmetros: ",
"Bark Endpoint": "Endpoint do Bark",
"Bark Group": "Grupo do Bark",
"Bark Sound": "Som do Bark",
"WebHookUrl": "URL de Webhook",
"SecretKey": "Chave Secreta",
"High": "Alto",
"WeCom Bot Key": "Chave do Bot do WeCom",
"promosmsTypeEco": "SMS ECO - barato, mas lento e frequentemente sobrecarregado. Limitado apenas aos destinatários poloneses.",
"styleElapsedTime": "Tempo decorrido abaixo da barra de pulsação",
"Expected Value": "Valor Esperado",
"webhookCustomBodyDesc": "Defina um corpo HTTP personalizado para a solicitação. Variáveis de modelo {msg}, {heartbeat}, {monitor} são aceitas.",
"Invert Keyword": "Palavra-chave de Inversão",
"Json Query": "Consulta JSON",
"toastErrorTimeout": "Tempo limite para Notificações de Erro",
"toastSuccessTimeout": "Tempo limite para Notificações de Sucesso",
"monitorToastMessagesLabel": "Monitorar notificações Toast",
"monitorToastMessagesDescription": "As notificações Toast para monitores desaparecem após um determinado tempo em segundos. Definir como -1 desativa o tempo limite. Definir como 0 desativa as notificações Toast.",
"Open Badge Generator": "Gerador de Distintivo",
"Badge Label Color": "Cor do Nome do Distintivo",
"Badge Color": "Cor do Distintivo",
"Badge Label Prefix": "Prefixo do Nome do Distintivo",
"Badge Preview": "Prévia do Distintivo",
"Badge Label Suffix": "Sufixo do Nome do Distintivo",
"Badge Up Color": "Cor de Cima do Distintivo",
"Badge Down Color": "Cor de Baixo do Distintivo",
"Badge Pending Color": "Cor do Distintivo Pendente",
"Badge Maintenance Color": "Cor do Distintivo Em Manutenção",
"Badge Warn Color": "Cor do Distintivo de Aviso",
"Badge Warn Days": "Dias de Aviso do Distintivo",
"Badge Down Days": "Dias Desligado do Distintivo",
"Badge Style": "Estilo do Distintivo",
"Badge value (For Testing only.)": "Valor do Distintivo (Apenas para Testes).",
"Badge URL": "URL do Distintivo",
"Badge Generator": "Gerador de Distintivo de {0}",
"Badge Type": "Tipo de Distintivo",
"Badge Duration (in hours)": "Duração do Distintivo (em horas)",
"Badge Label": "Nome do Distintivo",
"Badge Prefix": "Prefixo do Valor do Distintivo",
"Badge Suffix": "Sufixo do Valor do Distintivo"
}

@ -639,7 +639,7 @@
"Server Timezone": "Часовой пояс сервера",
"statusPageMaintenanceEndDate": "Конец",
"IconUrl": "URL иконки",
"Enable DNS Cache": "Включить DNS кэш для мониторов HTTP(S)",
"Enable DNS Cache": "(Устарело) Включить DNS кэш для мониторов HTTP(S)",
"Enable": "Включить",
"Disable": "Отключить",
"Single Maintenance Window": "Единое окно техбслуживания",
@ -847,5 +847,20 @@
"nostrRecipientsHelp": "формат npub, по одному в строке",
"FlashDuty Severity": "Серьёзность",
"nostrRelays": "Реле Nostr",
"nostrRelaysHelp": "Один URL-адрес ретрансляции в каждой строке"
"nostrRelaysHelp": "Один URL-адрес ретрансляции в каждой строке",
"enableNSCD": "Включить NSCD (Name Service Cache Daemon) для кэширования всех DNS-запросов",
"Saved.": "Сохранено",
"setupDatabaseChooseDatabase": "Какую базу данных Вы хотите использовать?",
"setupDatabaseEmbeddedMariaDB": "Вам не нужно ничего настраивать. В этот докер-образ автоматически встроена и настроена MariaDB. Uptime Kuma будет подключаться к этой базе данных через unix-сокет.",
"setupDatabaseSQLite": "Простой файл базы данных, рекомендуемый для небольших развертываний. До версии 2.0.0 Uptime Kuma использовал SQLite в качестве базы данных по умолчанию.",
"setupDatabaseMariaDB": "Подключитесь к внешней базе данных MariaDB. Необходимо задать информацию о подключении к базе данных.",
"dbName": "Имя базы данных",
"pushViewCode": "Как использовать монитор Push? (Посмотреть код)",
"programmingLanguages": "Языки программирования",
"Bark API Version": "Версия Bark API",
"monitorToastMessagesDescription": "Уведомления для мониторов исчезают через заданное время в секундах. Значение -1 отключает тайм-аут. Значение 0 отключает уведомления.",
"monitorToastMessagesLabel": "Уведомления",
"toastErrorTimeout": "Таймаут для уведомлений об ошибках",
"toastSuccessTimeout": "Таймаут для уведомлений об успехе",
"pushOthers": "Другие"
}

@ -137,5 +137,239 @@
"resendDisabled": "Omsändning inaktiverat",
"Pick Affected Monitors...": "Välj påverkade övervakare…",
"Select status pages...": "Välj statussidor…",
"General Monitor Type": "Allmänna övervakare"
"General Monitor Type": "Allmänna övervakare",
"webhookFormDataDesc": "{multipart} är bra för PHP. Den JSON kommer att bli analyserat med {decodeFunction}",
"appriseInstalled": "Apprise är installerad.",
"clearDataOlderThan": "Behåll övervakare historik data i {0} dagar.",
"steamApiKeyDescription": "För att övervaka en Steam Game Server behöver man en Steam Web-API nyckel. Du kan registrera din API nyckel här: ",
"No Monitors": "Inga Övervaktare",
"shrinkDatabaseDescription": "Utlösa databas VACUUM för SQLite. Om din databas skappades efter 1.10.0, AUTO_VACUUM är redan aktiverat och denna aktion behövs inte.",
"proxyDescription": "Proxyservrar måste tilldelas en övervakare för att fungera.",
"setAsDefaultProxyDescription": "Denna proxyserver kommer att aktiveras som standard för nya övervakare. Du kan fortfarande inaktivera proxyserven var för sig övervakare.",
"Content Type": "Innehållstyp",
"webhookAdditionalHeadersDesc": "Ställer in ytterligare headers skickat med webhooken. Varenda header skulle definieras som ett JSON nyckel/värde par.",
"RadiusCallingStationIdDescription": "Kallande Enhetsidentifierare",
"Slug": "Slugg",
"Invert Keyword": "Invertera Nyckelord",
"Degraded Service": "Försämrad Tjänst",
"Request Timeout": "Request Timeout",
"timeoutAfter": "Timeout efter {0} sekunder",
"styleElapsedTime": "Förfluten tid under den heartbeat indikatorn",
"styleElapsedTimeShowNoLine": "Visa (Utan Linje)",
"styleElapsedTimeShowWithLine": "Visa (Med Linje)",
"Create": "Skapa",
"Clear Data": "Radera Data",
"Auto Get": "Hämta Automatiskt",
"Overwrite": "Skriva över",
"Options": "Alternativ",
"Verify Token": "Verifiera Token",
"Enable 2FA": "Aktivera 2FA",
"Disable 2FA": "Inaktivera 2FA",
"2FA Settings": "2FA Inställningar",
"Two Factor Authentication": "Tvåfaktorsautentisering",
"filterActive": "Aktiv",
"filterActivePaused": "Pausad",
"Inactive": "Inaktiv",
"Setup 2FA": "Uppstart 2FA",
"Clear all statistics": "Rensa alla Statistiker",
"Skip existing": "Hoppa över existerande",
"Keep both": "Behåll båda",
"Token": "Token",
"notAvailableShort": "N/A",
"Apply on all existing monitors": "Applicera på alla existerande övervakare",
"Heartbeats": "Heartbeats",
"Show URI": "Visa URI",
"color": "Färg",
"value (optional)": "Värde (valfritt)",
"Gray": "Grå",
"Tags": "Taggar",
"Tag with this name already exist.": "Tag med detta namn finns redan.",
"Red": "Röd",
"Orange": "Orange",
"Green": "Grön",
"Blue": "Blå",
"Indigo": "Indigoblå",
"Purple": "Lila",
"Pink": "Rosa",
"Custom": "Anpassad",
"Search...": "Sök…",
"Avg. Ping": "Medelvärde Ping",
"Tag with this value already exist.": "Tagg med detta värde finns redan.",
"Avg. Response": "Medelvärde Respons",
"Entry Page": "Entry Sida",
"statusPageRefreshIn": "Uppdaterar om: {0}",
"No Services": "Inga Tjänster",
"All Systems Operational": "Alla System i Drift",
"Partially Degraded Service": "Delvis Försämrada Tjänster",
"Add Group": "Lägg till Grupp",
"Add New Tag": "Lägg till Ny Tagg",
"Add New below or Select...": "Lägg till Ny under eller Välj…",
"Add a monitor": "Lägg till en Övervakare",
"Edit Status Page": "Hantera Status Sida",
"Status Page": "Status Sida",
"Status Pages": "Status Sidor",
"Go to Dashboard": "Till Dashboard",
"here": "här",
"Required": "Krävs",
"webhookJsonDesc": "{0} är bra för någon moderna HTTP servrar till exempel Express.js",
"webhookCustomBodyDesc": "Definiera en anpassad HTTP Body till den request. Mall variabler {msg}, {heartbeat}, {monitor} accepteras.",
"webhookAdditionalHeadersTitle": "Ytterligare Headers",
"webhookBodyPresetOption": "Förinställning - {0}",
"defaultNotificationName": "Min {notification} Varna ({number})",
"webhookBodyCustomOption": "Anpassad Body",
"Webhook URL": "Webhook URL",
"Application Token": "Applikation Token",
"Server URL": "Server URL",
"Priority": "Prioritet",
"emojiCheatSheet": "Emoji fusklapp: {0}",
"Read more": "Läs mer",
"appriseNotInstalled": "Apprise är inte installerad. {0}",
"Method": "Metod",
"Body": "Body",
"Headers": "Headers",
"HeadersInvalidFormat": "Requestens headers är inte giltig JSON: ",
"BodyInvalidFormat": "Requestens body är inte giltig JSON: ",
"Monitor History": "Övervakare Historik",
"PasswordsDoNotMatch": "Lösenorden matchar inte.",
"records": "rekorder",
"One record": "En rekord",
"Current User": "Nuvarande Användare",
"topic": "Ämne",
"topicExplanation": "MQTT ämne att övervaka",
"successMessageExplanation": "MQTT meddelande som ska anses vara framgång",
"successMessage": "Framgång Meddelande",
"recent": "Nyligen",
"Done": "Klar",
"Info": "Info",
"Security": "Säkerhet",
"Steam API Key": "Steam API Nyckel",
"Shrink Database": "Minska Databas",
"Pick a RR-Type...": "Välj en RR-Typ…",
"Pick Accepted Status Codes...": "Välj Accepterade Statuskod…",
"Default": "Standard",
"HTTP Options": "HTTP Alternativ",
"Create Incident": "Skapa Incident",
"Title": "Titel",
"Content": "Innehåll",
"Style": "Stil",
"info": "info",
"Post URL": "Post URL",
"PushUrl": "Push URL",
"danger": "risk",
"error": "fel",
"critical": "kritisk",
"primary": "primär",
"light": "ljus",
"dark": "mörk",
"Post": "Post",
"Please input title and content": "Snälla lägg till titel och innehåll",
"Created": "Skapat",
"Last Updated": "Senaste Uppdaterade",
"Switch to Light Theme": "Byt till Ljustema",
"Switch to Dark Theme": "Byt till Mörktema",
"Show Tags": "Visa Taggar",
"Hide Tags": "Göma Taggar",
"Description": "Beskrivning",
"No monitors available.": "Inga övervaktare tillgänglig.",
"Add one": "Lägg till en",
"Untitled Group": "Namnlös Grupp",
"Services": "Tjänster",
"Discard": "Radera",
"Cancel": "Kancellera",
"Select": "Välj",
"selectedMonitorCount": "Valt: {0}",
"Check/Uncheck": "Markera/Omarkera",
"Powered by": "Drivs av",
"Customize": "Anpassa",
"Custom Footer": "Anpassad Footer",
"Custom CSS": "Anpassad CSS",
"deleteStatusPageMsg": "Är du säkert att du vill radera denna status sida?",
"Proxies": "Proxyservrar",
"default": "Standard",
"enabled": "Aktiverad",
"setAsDefault": "Ange Som Standard",
"deleteProxyMsg": "Är du säkert att du vill radera denna proxyserver för alla övervakare?",
"Certificate Chain": "Certifikatkedja",
"Valid": "Giltig",
"Invalid": "Ogiltig",
"User": "Användare",
"Installed": "Installerat",
"Not installed": "Installerat ej",
"Running": "Körs",
"Not running": "Körs inte",
"Remove Token": "Ta bort Token",
"Start": "Starta",
"Stop": "Stoppa",
"Add New Status Page": "Lägg till Ny Status Sida",
"Accept characters:": "Acceptera tecken:",
"Unpin": "Unpin",
"startOrEndWithOnly": "Börja eller sluta med {0} bara",
"No consecutive dashes": "Ingen följande streck",
"Next": "Nästa",
"The slug is already taken. Please choose another slug.": "Sluggen är redan tagit. Snälla välja en annan slugg.",
"No Proxy": "Ingen Proxyservern",
"Authentication": "Autentisering",
"HTTP Basic Auth": "HTTP Basic Auth",
"New Status Page": "Ny Status Sida",
"Page Not Found": "Sida hittas inte",
"Reverse Proxy": "Omvänd Proxyserver",
"Backup": "Backup",
"About": "Om",
"wayToGetCloudflaredURL": "(Ladda ned cloudflared från {0})",
"cloudflareWebsite": "Cloudflare Webbsida",
"Message:": "Meddelande:",
"Don't know how to get the token? Please read the guide:": "Vet inte hur att få en token? Snälla läs guiden:",
"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.": "Den nuvarande anslutningen kan kopplas bort om du närvarande ansluter via Cloudflare Tunnel. Är du säkert du vill avsluta den? Skriv ditt nuvarande lösenord för att konfirmera.",
"HTTP Headers": "HTTP Headers",
"Trust Proxy": "Lita på Proxyserver",
"Other Software": "Annan programvara",
"For example: nginx, Apache and Traefik.": "Till exempel: nginx, Apache och Traefik.",
"Please read": "Läs är du snäll",
"Subject:": "Subjekt:",
"Valid To:": "Giltig Till:",
"Days Remaining:": "Dagar kvar:",
"Fingerprint:": "Fingertryck:",
"No status pages": "Ingen status sidor",
"Proxy": "Proxyservern",
"Date Created": "Datum Skapade",
"Footer Text": "Footer Text",
"Show Powered By": "Visa Drivs Av",
"Domain Names": "Domain Namn",
"signedInDisp": "Inloggad som {0}",
"signedInDispDisabled": "Auth Inaktiverad.",
"RadiusSecret": "Radius Hemlighet",
"RadiusSecretDescription": "Delad Hemlighet mellan client och server",
"RadiusCalledStationId": "Kancellerad Station Id",
"RadiusCalledStationIdDescription": "Enhetsidentifierare",
"RadiusCallingStationId": "Calling Station Id",
"Certificate Expiry Notification": "Notif om certifikatets utgång",
"Domain Name Expiry Notification": "Notif om Domain Namns utgång",
"API Key": "API Nyckel",
"API Username": "API Användarnamn",
"Show update if available": "Visa uppdatering om tillgänglig",
"Also check beta release": "Kolla upp också beta version",
"Events": "Händelser",
"Active": "Aktiv",
"statusPageNothing": "Ingenting här, snälla lägg till en grupp eller en monitor.",
"warning": "varning",
"Issuer:": "Utfärdare:",
"Expected Value": "Förväntat Värde",
"Primary Base URL": "Huvud Bas URL",
"Home": "Hem",
"Cannot connect to the socket server": "Kan inte koppla till socketservern",
"Reconnecting...": "Återanslutar...",
"Json Query": "Json Query",
"Default enabled": "Standard aktiverad",
"pushViewCode": "Visa kod",
"Steam Game Server": "Steam Spel Server",
"Docker Container": "Docker Container",
"setupDatabaseChooseDatabase": "Vilken databas skulle du vilja använda?",
"dbName": "Databas Namn",
"What you can try:": "Vad du kan försöka:",
"Container Name / ID": "Containernamn / ID",
"Docker Host": "Docker värd",
"Docker Hosts": "Docker värdar",
"Domain": "Domän",
"Most likely causes:": "Störst troliga anledningar:",
"Coming Soon": "Kommer snart"
}

@ -187,5 +187,127 @@
"Tag with this value already exist.": "ఈ విలువతో ట్యాగ్ ఇప్పటికే ఉంది.",
"Custom": "కస్టమ్",
"Entry Page": "ఎంట్రీ పేజీ",
"statusPageNothing": "ఇక్కడ ఏమీ లేదు, దయచేసి సమూహాన్ని లేదా మానిటర్‌ని జోడించండి."
"statusPageNothing": "ఇక్కడ ఏమీ లేదు, దయచేసి సమూహాన్ని లేదా మానిటర్‌ని జోడించండి.",
"No Services": "సేవలు లేవు",
"Partially Degraded Service": "పాక్షికంగా క్షీణించిన సేవ",
"Degraded Service": "దిగజారిన సేవ",
"Add Group": "సమూహాన్ని జోడించండి",
"Add a monitor": "మానిటర్‌ను జోడించండి",
"Go to Dashboard": "డాష్బోర్డ్ కు వెళ్ళండి",
"Status Page": "స్థితి పేజీ",
"Status Pages": "స్థితి పేజీలు",
"here": "ఇక్కడ",
"Required": "అవసరం",
"Post URL": "పోస్ట్ URL",
"Content Type": "కంటెంట్ రకం",
"webhookFormDataDesc": "PHPకి {multipart} మంచిది. JSON {decodeFunction}తో అన్వయించబడాలి",
"webhookAdditionalHeadersTitle": "అదనపు శీర్షికలు",
"webhookBodyPresetOption": "ప్రీసెట్ - {0}",
"webhookBodyCustomOption": "కస్టమ్ బాడీ",
"Webhook URL": "వెబ్‌హుక్ URL",
"Application Token": "అప్లికేషన్ టోకెన్",
"Server URL": "సర్వర్ URL",
"Priority": "ప్రాధాన్యత",
"Read more": "ఇంకా చదవండి",
"appriseInstalled": "అప్రైజ్ ఇన్‌స్టాల్ చేయబడింది.",
"Method": "పద్ధతి",
"Body": "శరీరం",
"Headers": "హెడర్సు",
"PushUrl": "పుష్ URL",
"BodyInvalidFormat": "అభ్యర్థన విషయం JSON చెల్లదు: ",
"Monitor History": "మానిటర్ చరిత్ర",
"clearDataOlderThan": "మానిటర్ చరిత్ర డేటాను {0} రోజుల పాటు ఉంచండి.",
"records": "రికార్డులు",
"One record": "ఒక రికార్డు",
"Current User": "ప్రస్తుత వినియోగదారుడు",
"topic": "అంశం",
"topicExplanation": "పర్యవేక్షించడానికి MQTT అంశం",
"successMessage": "విజయ సందేశం",
"successMessageExplanation": "MQTT సందేశం విజయంగా పరిగణించబడుతుంది",
"recent": "ఇటీవలి",
"Done": "పూర్తి",
"Info": "సమాచారం",
"Steam API Key": "స్టీమ్ API కీ",
"Shrink Database": "డేటాబేస్ కుదించు",
"Pick Accepted Status Codes...": "ఆమోదించబడిన స్థితి కోడ్‌లను ఎంచుకోండి…",
"Default": "డిఫాల్ట్",
"HTTP Options": "HTTP ఎంపికలు",
"Title": "శీర్షిక",
"Content": "విషయము",
"Style": "శైలి",
"info": "సమాచారం",
"warning": "హెచ్చరిక",
"danger": "ప్రమాదం",
"error": "లోపం",
"primary": "ప్రాథమిక",
"light": "వెలుతురు",
"dark": "చీకటి",
"Post": "పోస్ట్",
"Created": "సృష్టించబడింది",
"Last Updated": "చివరిగా నవీకరించబడింది",
"Unpin": "అన్‌పిన్",
"Show Tags": "ట్యాగ్‌లను చూపించు",
"Hide Tags": "ట్యాగ్‌లను దాచండి",
"Description": "వివరణ",
"Add one": "ఒకటి జోడించండి",
"No Monitors": "మానిటర్లు లేవు",
"Services": "సేవలు",
"Select": "ఎంచుకోండి",
"selectedMonitorCount": "ఎంచుకున్నది: {0}",
"Powered by": "ద్వారా ఆధారితం",
"Customize": "అనుకూలీకరించండి",
"Custom Footer": "అనుకూల ఫుటర్",
"Custom CSS": "అనుకూల CSS",
"deleteStatusPageMsg": "మీరు ఖచ్చితంగా ఈ స్థితి పేజీని తొలగించాలనుకుంటున్నారా?",
"Proxies": "ప్రాక్సీలు",
"default": "డిఫాల్ట్",
"enabled": "ప్రారంభించబడింది",
"Certificate Chain": "సర్టిఫికేట్ చైన్",
"Valid": "చెల్లుబాటు అవుతుంది",
"Invalid": "చెల్లదు",
"User": "వినియోగదారు",
"Installed": "ఇన్‌స్టాల్ చేయబడింది",
"Not installed": "ఇన్‌స్టాల్ చేయలేదు",
"Running": "నడుస్తోంది",
"Not running": "నడవడం లేదు",
"Remove Token": "టోకెన్‌ని తీసివేయండి",
"Start": "ప్రారంభించండి",
"Stop": "ఆపు",
"Add New Status Page": "కొత్త స్థితి పేజీని జోడించండి",
"Slug": "స్లగ్",
"startOrEndWithOnly": "{0}తో మాత్రమే ప్రారంభించండి లేదా ముగించండి",
"Next": "తరువాత",
"No Proxy": "ప్రాక్సీ లేదు",
"All Systems Operational": "అన్ని సిస్టమ్స్ ఆపరేషనల్",
"Edit Status Page": "స్థితి పేజీని సవరించండి",
"defaultNotificationName": "నా {నోటిఫికేషన్} హెచ్చరిక ({సంఖ్య})",
"webhookJsonDesc": "Express.js వంటి ఏదైనా ఆధునిక HTTP సర్వర్‌లకు {0} మంచిది",
"webhookCustomBodyDesc": "అభ్యర్థన కోసం అనుకూల HTTP బాడీని నిర్వచించండి. టెంప్లేట్ వేరియబుల్స్ {msg}, {heartbeat}, {monitor} ఆమోదయోగ్యమైనవి.",
"webhookAdditionalHeadersDesc": "webhookతో పంపబడిన అదనపు హెడర్లను సెట్ చేస్తుంది. ప్రతి హెడర్ JSON కీ/విలువగా నిర్వచించబడాలి.",
"emojiCheatSheet": "ఎమోజి చీట్ షీట్: {0}",
"appriseNotInstalled": "అప్రైజ్ ఇన్‌స్టాల్ చేయబడలేదు. {0}",
"HeadersInvalidFormat": "అభ్యర్థన హెడర్సు చెల్లుబాటు కావు JSON: ",
"PasswordsDoNotMatch": "గుత్త పదములు సరి పోవట్లేదు.",
"steamApiKeyDescription": "స్టీమ్ గేమ్ సర్వర్‌ని పర్యవేక్షించడానికి మీకు స్టీమ్ వెబ్-API కీ అవసరం. మీరు మీ API కీని ఇక్కడ నమోదు చేసుకోవచ్చు: ",
"Security": "భద్రత",
"Pick a RR-Type...": "RR-రకాన్ని ఎంచుకోండి…",
"Create Incident": "సంఘటనను సృష్టించండి",
"critical": "ప్రమాదకరమైన",
"Please input title and content": "దయచేసి శీర్షిక మరియు కంటెంట్‌ని ఇన్‌పుట్ చేయండి",
"Switch to Light Theme": "లైట్ థీమ్‌కి మారండి",
"Switch to Dark Theme": "డార్క్ థీమ్‌కి మారండి",
"No monitors available.": "మానిటర్లు అందుబాటులో లేవు.",
"Untitled Group": "పేరులేని సమూహం",
"Discard": "విస్మరించండి",
"Cancel": "రద్దు చేయండి",
"Check/Uncheck": "చెక్/చెక్చేయవద్దు",
"shrinkDatabaseDescription": "SQLite కోసం డేటాబేస్ VACUUMని ట్రిగ్గర్ చేయండి. మీ డేటాబేస్ 1.10.0 తర్వాత సృష్టించబడితే, AUTO_VACUUM ఇప్పటికే ప్రారంభించబడింది మరియు ఈ చర్య అవసరం లేదు.",
"setAsDefault": "డిఫాల్ట్ సెట్ చేయబడింది",
"deleteProxyMsg": "మీరు ఖచ్చితంగా అన్ని మానిటర్‌ల కోసం ఈ ప్రాక్సీని తొలగించాలనుకుంటున్నారా?",
"proxyDescription": "పనిచేయడానికి ప్రాక్సీలు తప్పనిసరిగా మానిటర్‌కు కేటాయించబడాలి.",
"enableProxyDescription": "ఈ ప్రాక్సీ సక్రియం చేయబడే వరకు మానిటర్ అభ్యర్థనలపై ప్రభావం చూపదు. మీరు యాక్టివేషన్ స్థితి ద్వారా అన్ని మానిటర్‌ల నుండి ప్రాక్సీని తాత్కాలికంగా నిలిపివేయడాన్ని నియంత్రించవచ్చు.",
"setAsDefaultProxyDescription": "కొత్త మానిటర్‌ల కోసం ఈ ప్రాక్సీ డిఫాల్ట్‌గా ప్రారంభించబడుతుంది. మీరు ఇప్పటికీ ప్రతి మానిటర్‌కు విడిగా ప్రాక్సీని నిలిపివేయవచ్చు.",
"Accept characters:": "అక్షరాలను అంగీకరించండి:",
"No consecutive dashes": "వరుస డాష్‌లను ఉపయోగించవద్దు",
"The slug is already taken. Please choose another slug.": "స్లగ్ ఇప్పటికే తీసుకోబడింది. దయచేసి మరొక స్లగ్‌ని ఎంచుకోండి."
}

@ -623,7 +623,7 @@
"maintenanceStatus-scheduled": "กำหนดการ",
"maintenanceStatus-ended": "สิ้นสุด",
"maintenanceStatus-unknown": "ไม่ทราบ",
"Specific Monitor Type": "ประเภทมอนิเตอร์เฉพาะ",
"Specific Monitor Type": "ชนิดมอนิเตอร์เฉพาะ",
"telegramMessageThreadID": "(ตัวเลือก) ไอดีเทรดข้อความ",
"telegramMessageThreadIDDescription": "ตัวระบุที่ไม่ซ้ำซึ่งเป็นทางเลือกสำหรับเธรดข้อความเป้าหมาย (หัวข้อ) ของฟอรัม สำหรับฟอรัมซูเปอร์กรุ๊ปเท่านั้น",
"sameAsServerTimezone": "เช่นเดียวกับเขตเวลาของเซิร์ฟเวอร์",
@ -675,5 +675,11 @@
"notificationRegional": "ภูมิภาค",
"timeoutAfter": "หมดเวลาหลังจาก {0} วินาที",
"Select": "เลือก",
"Expected Value": "ค่าที่คาดหวัง"
"Expected Value": "ค่าที่คาดหวัง",
"setupDatabaseChooseDatabase": "ฐานข้อมูลไหนที่ต้องการใช้งาน?",
"setupDatabaseEmbeddedMariaDB": "คุณไม่จำเป็นต้องทำอะไร Docker image จะสร้างและตั่งค่า MariaDB ให้โดยอัตโนมัติ Uptime Kuma จะเชื่อมต่อกับฐานข้อมูลนี้ด้วย unix socket",
"setupDatabaseMariaDB": "เชื่อมต่อไปยัง MariaDB ภายนอก คุณจำเป็นจะต้องตั่งค่าการเชื่อมต่อฐานข้อมูล",
"setupDatabaseSQLite": "ไฟล์ฐานข้อมูลอย่างง่าย แนะนำสำหรับการปรับใช้ขนาดเล็ก ก่อนเวอร์ชัน 2.0.0 Uptime Kuma ใช้ SQLite เป็นฐานข้อมูลเริ่มต้น",
"dbName": "ชื่อฐานข้อมูล",
"Passive Monitor Type": "ชนิดมอนิเตอร์แบบพาสซีฟ"
}

@ -640,7 +640,7 @@
"Server Timezone": "Sunucu Saat Dilimi",
"statusPageMaintenanceEndDate": "Bitiş Zamanı",
"IconUrl": "Icon URL",
"Enable DNS Cache": "HTTP monitörleri için DNS Önbelleğini etkinleştir",
"Enable DNS Cache": "(Kullanımdan kaldırıldı) HTTP(ler) monitörleri için DNS Önbelleğini etkinleştirin",
"Enable": "Etkin",
"Disable": "Devre Dışı",
"dnsCacheDescription": "Bazı IPv6 ortamlarında çalışmıyor olabilir, herhangi bir sorunla karşılaşırsanız devre dışı bırakın.",
@ -838,5 +838,37 @@
"gamedigGuessPortDescription": "Valve Server Sorgu Protokolü tarafından kullanılan bağlantı noktası, istemci bağlantı noktasından farklı olabilir. Monitör sunucunuza bağlanamıyorsa bunu deneyin.",
"styleElapsedTimeShowNoLine": "Göster (Satır Yok)",
"styleElapsedTime": "Kalp atışı çubuğunun altında geçen süre",
"styleElapsedTimeShowWithLine": "Göster (Satır ile birlikte)"
"styleElapsedTimeShowWithLine": "Göster (Satır ile birlikte)",
"enableNSCD": "Tüm DNS isteklerini önbelleğe almak için NSCD'yi (Ad Hizmeti Önbellek Programı) etkinleştirin",
"setupDatabaseEmbeddedMariaDB": "Hiçbir şey ayarlamanıza gerek yok. Bu docker imajı sizin için otomatik olarak bir MariaDB yerleştirdi ve yapılandırdı. Çalışma Süresi Kuma bu veritabanına unix soketi aracılığıyla bağlanacaktır.",
"setupDatabaseSQLite": "Küçük ölçekli dağıtımlar için önerilen basit bir veritabanı dosyası. v2.0.0'dan önce Uptime Kuma, varsayılan veritabanı olarak SQLite'ı kullanıyordu.",
"setupDatabaseChooseDatabase": "Hangi veritabanını kullanmak istiyorsunuz?",
"setupDatabaseMariaDB": "Harici bir MariaDB veritabanına bağlanın. Veritabanı bağlantı bilgilerini ayarlamanız gerekir.",
"dbName": "Veritabanı ismi",
"Saved.": "Kaydedildi.",
"toastErrorTimeout": "Hata Bildirimleri için Zaman Aşımı",
"toastSuccessTimeout": "Başarı Bildirimleri için Zaman Aşımı",
"monitorToastMessagesLabel": "Toast bildirimlerini izleyin",
"monitorToastMessagesDescription": "Monitörler için bildirimler, saniye cinsinden belirli bir süre sonunda kaybolur. -1'e ayarlamak zaman aşımını devre dışı bırakır. 0'a ayarlamak, tost bildirimlerini devre dışı bırakır.",
"Bark API Version": "Bark API Sürümü",
"pushViewCode": "Push monitör nasıl kullanılır? (Kodu Görüntüle)",
"programmingLanguages": "Programlama dilleri",
"pushOthers": "Diğerleri",
"authInvalidToken": "Geçersiz Token.",
"authIncorrectCreds": "Kullanıcı adı ya da parola yanlış.",
"2faAlreadyEnabled": "2FA zaten etkin.",
"2faEnabled": "2FA Etkin.",
"2faDisabled": "2FA Devre Dışı.",
"successResumed": "Başarıyla Devam Edildi.",
"successPaused": "Başarıyla Duraklatıldı.",
"successDeleted": "Başarıyla silindi.",
"successEdited": "Başarıyla Düzenlendi.",
"successBackupRestored": "Yedekleme başarıyla geri yüklendi.",
"successDisabled": "Başarıyla Devre Dışı Bırakıldı.",
"successEnabled": "Başarıyla Etkinleştirildi.",
"tagNotFound": "Etiket bulunamadı.",
"authUserInactiveOrDeleted": "Kullanıcı etkin değil veya silinmiş.",
"successAdded": "Başarıyla eklendi.",
"successAuthChangePassword": "Şifre başarıyla güncellendi.",
"foundChromiumVersion": "Chromium/Chrome bulundu. Versiyon: {0}"
}

@ -678,7 +678,7 @@
"Server Timezone": "Часовий пояс сервера",
"statusPageMaintenanceEndDate": "Закінчення",
"IconUrl": "URL-адреса іконки",
"Enable DNS Cache": "Увімкнути DNS-кеш для HTTP(s) моніторів",
"Enable DNS Cache": "(Застаріле) Увімкнути DNS-кеш для HTTP(s) моніторів",
"Enable": "Увімкнути",
"confirmDeleteTagMsg": "Ви впевнені, що хочете видалити цей тег? Монітори, пов'язані з цим тегом, не будуть видалені.",
"Guild ID": "ID гільдії",
@ -844,5 +844,37 @@
"gamedigGuessPort": "Gamedig: Вгадати порт",
"gamedigGuessPortDescription": "Порт, що використовується протоколом запитів до сервера Valve, може відрізнятися від порту клієнта. Спробуйте це, якщо монітор не може підключитися до вашого сервера.",
"styleElapsedTimeShowWithLine": "Показати (з лінією)",
"styleElapsedTimeShowNoLine": "Показати (без лінії)"
"styleElapsedTimeShowNoLine": "Показати (без лінії)",
"enableNSCD": "Увімкнути NSCD (Name Service Cache Daemon) для кешування всіх DNS-запитів",
"setupDatabaseChooseDatabase": "Яку базу даних ви хочете використовувати?",
"setupDatabaseEmbeddedMariaDB": "Вам не потрібно нічого налаштовувати. Цей докер-образ містить вбудовану та автоматично налаштовану базу даних MariaDB. Uptime Kuma підключиться до цієї бази даних через unix-сокет.",
"setupDatabaseSQLite": "Простий файл бази даних, рекомендований для невеликих проєктів. До версії 2.0.0 Uptime Kuma використовувала SQLite як базу даних за замовчуванням.",
"setupDatabaseMariaDB": "Підключитися до зовнішньої бази даних MariaDB. Вам потрібно задати інформацію для підключення до бази даних.",
"dbName": "Назва бази даних",
"Saved.": "Збережено.",
"monitorToastMessagesLabel": "Тост-сповіщення монітора",
"toastErrorTimeout": "Таймаут для сповіщень про помилки",
"toastSuccessTimeout": "Таймаут для сповіщень про успіх",
"monitorToastMessagesDescription": "Тост-сповіщення для моніторів зникають через заданий час у секундах. Значення -1 вимикає таймаут. Значення 0 вимикає тост-сповіщення.",
"Bark API Version": "Версія Bark API",
"pushViewCode": "Як користуватися Push-монітором? (Переглянути код)",
"pushOthers": "Інші",
"programmingLanguages": "Мови програмування",
"authInvalidToken": "Недійсний токен.",
"2faAlreadyEnabled": "2FA вже увімкнено.",
"2faEnabled": "2FA увімкнено.",
"2faDisabled": "2FA вимкнено.",
"successAdded": "Успішно додано.",
"successResumed": "Успішно відновлено.",
"successPaused": "Успішно зупинено.",
"successDeleted": "Успішно видалено.",
"successAuthChangePassword": "Пароль успішно оновлено.",
"successBackupRestored": "Резервну копію успішно відновлено.",
"successDisabled": "Успішно вимкнено.",
"tagNotFound": "Тег не знайдено.",
"foundChromiumVersion": "Знайдено Chromium/Chrome. Версія: {0}",
"authUserInactiveOrDeleted": "Користувач неактивний або видалений.",
"authIncorrectCreds": "Неправильне ім'я користувача або пароль.",
"successEdited": "Успішно відредаговано.",
"successEnabled": "Успішно увімкнено."
}

@ -654,7 +654,7 @@
"Server Timezone": "服务器时区",
"statusPageMaintenanceEndDate": "结束时间",
"IconUrl": "图标 URL",
"Enable DNS Cache": "为 HTTP(s) 监控项启用 DNS 缓存",
"Enable DNS Cache": "(已弃用)为 HTTP(s) 监控项启用 DNS 缓存",
"Enable": "启用",
"Disable": "禁用",
"dnsCacheDescription": "可能无法在某些 IPv6 环境工作,如果遇到问题请禁用。",
@ -840,5 +840,37 @@
"gamedigGuessPort": "Gamedig: 自动检测端口号",
"styleElapsedTimeShowWithLine": "显示(带连接线)",
"styleElapsedTimeShowNoLine": "显示(不带连接线)",
"styleElapsedTime": "在监控项详情的心跳栏下显示起止时间"
"styleElapsedTime": "在监控项详情的心跳栏下显示起止时间",
"enableNSCD": "启用 NSCD名称服务缓存以缓存所有 DNS 请求",
"setupDatabaseChooseDatabase": "您想用哪种数据库?",
"setupDatabaseEmbeddedMariaDB": "您无需设置此项。通过 Docker 方式安装时已自动配置了一个 MariaDB 数据库。Uptime Kuma 会通过 Unix 套接字方式连接该数据库。",
"setupDatabaseMariaDB": "连接到外部 MariaDB 数据库。您需要设置该数据库的连接方式。",
"setupDatabaseSQLite": "一个简单的数据库文件,推荐小规模部署使用。在 v2.0.0 版本之前Uptime Kuma 使用 SQLite 作为默认数据库。",
"dbName": "数据库名称",
"Saved.": "已保存。",
"monitorToastMessagesLabel": "监控项的弹窗通知",
"toastSuccessTimeout": "成功类弹窗通知的自动关闭用时",
"toastErrorTimeout": "失败类弹窗通知的自动关闭用时",
"monitorToastMessagesDescription": "监控项的弹窗通知的自动关闭用时,以秒为单位。设置为 -1 将禁用弹窗通知的自动关闭功能,设置为 0 将完全禁用弹窗通知功能。",
"Bark API Version": "Bark API 版本",
"programmingLanguages": "编程语言",
"pushOthers": "其他",
"pushViewCode": "如何使用 Push 监控项?(查看示例代码)",
"authInvalidToken": "无效的令牌。",
"authUserInactiveOrDeleted": "该用户被禁用或删除。",
"tagNotFound": "标签未找到。",
"successEnabled": "已成功启用。",
"successDisabled": "已成功禁用。",
"successBackupRestored": "已成功恢复备份。",
"successEdited": "已成功编辑。",
"successDeleted": "已成功删除。",
"successPaused": "已成功暂停。",
"successResumed": "已成功恢复。",
"successAdded": "已成功添加。",
"2faDisabled": "已成功禁用 2FA。",
"2faEnabled": "已成功启用 2FA。",
"2faAlreadyEnabled": "2FA 已经启用。",
"foundChromiumVersion": "已找到 Chromium/Chrome。版本{0}",
"successAuthChangePassword": "已成功更新密码。",
"authIncorrectCreds": "错误的用户名或密码。"
}

@ -731,5 +731,27 @@
"Home": "首頁",
"Expected Value": "預期值",
"Json Query": "JSON 查询",
"Saved.": "已儲存。"
"Saved.": "已儲存。",
"Select": "選擇",
"selectedMonitorCount": "已選:{0}",
"Check/Uncheck": "選取中/取消選取",
"telegramMessageThreadIDDescription": "(可選) Telegram 在超級群組使用的話題標識字串",
"pushViewCode": "查看代碼",
"pushOthers": "其他",
"webhookBodyCustomOption": "自定義內容",
"tailscalePingWarning": "如要使用 Tailscale Ping ,您需要以非 docker 方式安裝 Uptime Kuma並在系統安裝 Tailscale 客戶端。",
"invertKeywordDescription": "出現關鍵詞將令檢測結果設為失敗,而非成功。",
"enableNSCD": "啟用 NSCD名稱服務緩存以緩存所有 DNS 請求",
"setupDatabaseChooseDatabase": "你想使用以下哪種資料庫?",
"setupDatabaseEmbeddedMariaDB": "你無需作任何設定。Docker image 中已包含設定好的 MariaDB。Uptime Kuma 會自動通過 Unix socket 連接到此資料庫。",
"setupDatabaseMariaDB": "連接到額外 MariaDB 資料庫。 你需要設置資料庫連接資訊。",
"setupDatabaseSQLite": "以一個檔案作為資料庫,建議用於小型的部署。在 v2.0.0 版本之前Uptime Kuma 使用 SQLite 作為預設資料庫。",
"dbName": "資料庫名稱",
"webhookBodyPresetOption": "預設 - {0}",
"programmingLanguages": "編程語言",
"styleElapsedTime": "狀態條下顯示已過的時間",
"styleElapsedTimeShowNoLine": "顯示(不帶連接線)",
"styleElapsedTimeShowWithLine": "顯示(帶連接線)",
"Request Timeout": "請求超時",
"timeoutAfter": "{0} 秒後為超時"
}

@ -121,7 +121,7 @@
"Enable Auth": "啟用驗證",
"disableauth.message1": ">你是否要<strong>取消登入驗證</strong>",
"disableauth.message2": "此功能是設計給已有<strong>第三方認證</strong>的使用者,例如 Cloudflare Access。",
"Please use this option carefully!": "請謹慎使用",
"Please use this option carefully!": "請謹慎使用",
"Logout": "登出",
"Leave": "離開",
"I understand, please disable": "我了解了,請停用",
@ -220,9 +220,9 @@
"Post URL": "Post 網址",
"Content Type": "內容類型",
"webhookJsonDesc": "{0} 適合任何現代的 HTTP 伺服器,如 Express.js",
"webhookFormDataDesc": "{multipart} 適合 PHP。 JSON 必須先經由 {decodeFunction} 剖析",
"webhookFormDataDesc": "{multipart} 適合 PHP。 JSON 必須先經由 {decodeFunction} 剖析",
"webhookAdditionalHeadersTitle": "額外標頭",
"webhookAdditionalHeadersDesc": "設定與 webhook 一同傳送的額外標頭。",
"webhookAdditionalHeadersDesc": "設置 webhook 請求的額外 Header。每一個 Header 應被定義為一對 JSON 鍵值對。",
"smtp": "Email (SMTP)",
"secureOptionNone": "無 / STARTTLS (25, 587)",
"secureOptionTLS": "TLS (465)",
@ -323,14 +323,14 @@
"Body": "主體",
"Headers": "標頭",
"PushUrl": "Push 網址",
"HeadersInvalidFormat": "要求標頭不是有效的 JSON",
"BodyInvalidFormat": "要求主體不是有效的 JSON",
"HeadersInvalidFormat": "要求標頭不是有效的 JSON: ",
"BodyInvalidFormat": "要求主體不是有效的 JSON: ",
"Monitor History": "監測器歷史紀錄",
"clearDataOlderThan": "保留 {0} 天內的監測器歷史紀錄。",
"PasswordsDoNotMatch": "密碼不相符。",
"records": "記錄",
"One record": "一項記錄",
"steamApiKeyDescription": "若要監測 Steam 遊戲伺服器,您將需要 Steam Web-API 金鑰。您可以在此註冊您的 API 金鑰",
"steamApiKeyDescription": "若要監測 Steam 遊戲伺服器,您將需要 Steam Web-API 金鑰。您可以在此註冊您的 API 金鑰: ",
"Current User": "目前使用者",
"topic": "Topic",
"topicExplanation": "要監測的 MQTT Topic",
@ -436,7 +436,7 @@
"PhoneNumbers": "PhoneNumbers",
"TemplateCode": "TemplateCode",
"SignName": "SignName",
"Sms template must contain parameters: ": "Sms 範本必須包含參數",
"Sms template must contain parameters: ": "Sms 範本必須包含參數: ",
"Bark Endpoint": "Bark 端點",
"Bark Group": "Bark 群組",
"Bark Sound": "Bark 鈴聲",
@ -590,7 +590,7 @@
"Examples": "範例",
"Home Assistant 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. ": "若要建立長期有效存取權杖,請點擊您的個人檔案名稱 (左下角),捲動至最下方,然後點擊建立權杖。",
"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 中查看通知服務的列表,在\"開發者工具 > 服務\"下搜尋\"通知\"來找到您的裝置/手機的名稱。",
@ -644,7 +644,7 @@
"Server Timezone": "伺服器時區",
"statusPageMaintenanceEndDate": "結束",
"IconUrl": "圖示網址",
"Enable DNS Cache": "啟用 DNS 快取",
"Enable DNS Cache": "(已棄用)為 HTTP(s) 監控項啟用 DNS 緩存",
"Enable": "啟用",
"Disable": "停用",
"dnsCacheDescription": "在某些 IPv6 環境可能會無法運作,如果您遇到任何問題,請停用。",
@ -689,7 +689,7 @@
"telegramProtectContentDescription": "如果啟用Telegram 中的機器人訊息將受到保護,不會被轉發和保存。",
"installing": "安裝中",
"uninstall": "卸載",
"loadingError": "無法獲取數據, 請重試",
"loadingError": "無法獲取數據, 請重試",
"markdownSupported": "支援 Markdown 語法",
"Packet Size": "數據包大小",
"statusPageRefreshIn": "將於 {0} 後刷新",
@ -705,7 +705,7 @@
"dataRetentionTimeError": "保留期限必須為 0 或正數",
"infiniteRetention": "設定為 0 以作無限期保留。",
"confirmDeleteTagMsg": "你確定你要刪除此標籤?相關的監測器不會被刪除。",
"twilioAuthToken": "認證 Token",
"twilioAuthToken": "認證 Token / API 金鑰",
"twilioAccountSID": "帳號 SID",
"ntfyUsernameAndPassword": "使用者名稱和密碼",
"ntfyAuthenticationMethod": "認證類型",
@ -748,5 +748,41 @@
"Home": "首頁",
"chromeExecutable": "Chrome/Chromium 執行檔",
"chromeExecutableAutoDetect": "自動偵測",
"pagertreeCritical": "緊急"
"pagertreeCritical": "緊急",
"PushDeer Server": "PushDeer 伺服器",
"pushDeerServerDescription": "留空則使用官方伺服器",
"Body Encoding": "請求體編碼",
"filterActive": "啟用",
"filterActivePaused": "暫停",
"Select": "選擇",
"enableNSCD": "啟用 NSCD名稱服務緩存以緩存所有 DNS 請求",
"Server URL should not contain the nfty topic": "服務器地址不應包含 ntfy主題",
"Invert Keyword": "反轉模式",
"Request Timeout": "請求超時",
"timeoutAfter": "{0} 秒後超時",
"styleElapsedTime": "在監控項詳情的心跳欄下顯示起止時間",
"styleElapsedTimeShowNoLine": "顯示(不帶連接線)",
"styleElapsedTimeShowWithLine": "顯示(帶連接線)",
"webhookCustomBodyDesc": "為 webhook 設定一個自定義 HTTP 請求體。可在模板內使用{msg},、{heartbeat}和{monitor} 變量。",
"webhookBodyPresetOption": "預設 - {0}",
"webhookBodyCustomOption": "自定義內容",
"selectedMonitorCount": "已選:{0}",
"Check/Uncheck": "選中/取消選中",
"tailscalePingWarning": "如需使用 Tailscale Ping 客戶端,您需要以非 docker 方式安裝 Uptime Kuma並同時安裝 Tailscale 客戶端。",
"invertKeywordDescription": "出現關鍵詞將令檢測結果設為失敗,而非成功。",
"jsonQueryDescription": "對響應結果執行一次 JSON 查詢,其返回值將會被轉換為字符串,再與期望值進行比較。可訪問<a href='https://jsonata.org/'>jsonata.org</a> 閱讀JSON 查詢語言的文檔,或在<a href='https://try.jsonata.org/'>此處</a>測試查詢語句。",
"wayToGetKookGuildID": "在 Kook 設置中打開“開發者模式”,然後右鍵點擊頻道可獲取其 ID",
"Notify Channel": "通知該頻道",
"aboutNotifyChannel": "勾選“通知該頻道”,會令該頻道內所有成員都收到一條桌面端或移動端通知,無論其狀態是在線或離開。",
"pagertreeIntegrationUrl": "集成 URL 地址",
"pagertreeUrgency": "緊急程度",
"Expected Value": "預期值",
"Json Query": "JSON 查詢",
"setupDatabaseChooseDatabase": "您想使用什麼資料庫?",
"setupDatabaseEmbeddedMariaDB": "您不需要設置任何東西。 此 docker 映像檔已自動為您嵌入並配置了 MariaDB。 Uptime Kuma 將通過 unix 套接字連接到該資料庫。",
"setupDatabaseMariaDB": "連接到外部 MariaDB 資料庫。 需要設置資料庫連接資訊。",
"dbName": "資料庫名稱",
"Show Clickable Link": "顯示可點擊連結",
"pagertreeSilent": "靜音",
"twilioApiKey": "API 金鑰 (選用)"
}

@ -370,12 +370,16 @@ main {
padding: 9px 15px;
width: 48px;
box-shadow: 2px 2px 30px rgba(0, 0, 0, 0.2);
z-index: 100;
.dark & {
box-shadow: 2px 2px 30px rgba(0, 0, 0, 0.5);
}
}
@media (max-width: 770px) {
.clear-all-toast-btn {
bottom: 72px;
z-index: 100;
}
}

@ -342,7 +342,7 @@ export default {
* @returns {void}
*/
toastSuccess(msg) {
toast.success(msg);
toast.success(this.$t(msg));
},
/**
@ -351,7 +351,7 @@ export default {
* @returns {void}
*/
toastError(msg) {
toast.error(msg);
toast.error(this.$t(msg));
},
/**

@ -66,7 +66,7 @@ export default {
} else {
if (res.msg.includes("UNIQUE constraint")) {
this.$root.toastError(this.$t("The slug is already taken. Please choose another slug."));
this.$root.toastError("The slug is already taken. Please choose another slug.");
} else {
this.$root.toastRes(res);
}

@ -437,7 +437,7 @@ export default {
*/
testNotification() {
this.$root.getSocket().emit("testNotification", this.monitor.id);
toast.success("Test notification is requested.");
this.$root.toastSuccess("Test notification is requested.");
},
/**
@ -498,11 +498,9 @@ export default {
*/
deleteMonitor() {
this.$root.deleteMonitor(this.monitor.id, (res) => {
this.$root.toastRes(res);
if (res.ok) {
toast.success(res.msg);
this.$router.push("/dashboard");
} else {
toast.error(res.msg);
}
});
},

@ -246,14 +246,11 @@
</template>
<script>
import { useToast } from "vue-toastification";
import VueMultiselect from "vue-multiselect";
import Datepicker from "@vuepic/vue-datepicker";
import { timezoneList } from "../util-frontend";
import cronstrue from "cronstrue/i18n";
const toast = useToast();
export default {
components: {
VueMultiselect,
@ -457,7 +454,7 @@ export default {
this.affectedMonitors.push(this.affectedMonitorsOptions.find(item => item.id === monitor.id));
});
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
@ -472,11 +469,11 @@ export default {
this.showOnAllPages = Object.values(res.statusPages).length === this.selectedStatusPagesOptions.length;
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
}
@ -490,7 +487,7 @@ export default {
this.processing = true;
if (this.affectedMonitors.length === 0) {
toast.error(this.$t("atLeastOneMonitor"));
this.$root.toastError(this.$t("atLeastOneMonitor"));
return this.processing = false;
}
@ -499,14 +496,14 @@ export default {
if (res.ok) {
await this.addMonitorMaintenance(res.maintenanceID, async () => {
await this.addMaintenanceStatusPage(res.maintenanceID, () => {
toast.success(res.msg);
this.$root.toastRes(res);
this.processing = false;
this.$root.getMaintenanceList();
this.$router.push("/maintenance");
});
});
} else {
toast.error(res.msg);
this.$root.toastRes(res);
this.processing = false;
}
@ -524,7 +521,7 @@ export default {
});
} else {
this.processing = false;
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
}
@ -539,7 +536,7 @@ export default {
async addMonitorMaintenance(maintenanceID, callback) {
await this.$root.addMonitorMaintenance(maintenanceID, this.affectedMonitors, async (res) => {
if (!res.ok) {
toast.error(res.msg);
this.$root.toastError(res.msg);
} else {
this.$root.getMonitorList();
}
@ -557,7 +554,7 @@ export default {
async addMaintenanceStatusPage(maintenanceID, callback) {
await this.$root.addMaintenanceStatusPage(maintenanceID, (this.showOnAllPages) ? this.selectedStatusPagesOptions : this.selectedStatusPages, async (res) => {
if (!res.ok) {
toast.error(res.msg);
this.$root.toastError(res.msg);
} else {
this.$root.getMaintenanceList();
}

@ -119,6 +119,9 @@
{{ $t("needPushEvery", [monitor.interval]) }}<br />
{{ $t("pushOptionalParams", ["status, msg, ping"]) }}
</div>
<button class="btn btn-primary" type="button" @click="resetToken">
{{ $t("Reset Token") }}
</button>
</div>
<!-- Keyword -->
@ -845,7 +848,9 @@ import { genSecret, isDev, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND } from "../u
import { hostNameRegexPattern } from "../util-frontend";
import { sleep } from "../util";
const toast = useToast();
const toast = useToast;
const pushTokenLength = 32;
const monitorDefaults = {
type: "http",
@ -881,6 +886,7 @@ const monitorDefaults = {
kafkaProducerSaslOptions: {
mechanism: "None",
},
kafkaProducerSsl: false,
gamedigGivenPortOnly: true,
};
@ -1144,7 +1150,9 @@ message HealthCheckResponse {
"monitor.type"() {
if (this.monitor.type === "push") {
if (! this.monitor.pushToken) {
this.monitor.pushToken = genSecret(10);
// ideally this would require checking if the generated token is already used
// it's very unlikely to get a collision though (62^32 ~ 2.27265788 * 10^57 unique tokens)
this.monitor.pushToken = genSecret(pushTokenLength);
}
}
@ -1165,7 +1173,7 @@ message HealthCheckResponse {
if (res.ok) {
this.gameList = res.gameList;
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
}
@ -1310,7 +1318,7 @@ message HealthCheckResponse {
this.monitor.timeout = ~~(this.monitor.interval * 8) / 10;
}
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
}
@ -1347,6 +1355,10 @@ message HealthCheckResponse {
return true;
},
resetToken() {
this.monitor.pushToken = genSecret(pushTokenLength);
},
/**
* Submit the form data for processing
* @returns {void}
@ -1400,7 +1412,7 @@ message HealthCheckResponse {
createdNewParent = true;
this.monitor.parent = res.monitorID;
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
this.processing = false;
return;
}
@ -1416,17 +1428,14 @@ message HealthCheckResponse {
if (createdNewParent) {
this.startParentGroupMonitor();
}
toast.success(res.msg);
this.processing = false;
this.$root.getMonitorList();
this.$router.push("/dashboard/" + res.monitorID);
} else {
toast.error(res.msg);
this.processing = false;
}
this.$root.toastRes(res);
});
} else {
await this.$refs.tagsManager.submit(this.monitor.id);

@ -101,12 +101,8 @@ export default {
*/
deleteMaintenance() {
this.$root.deleteMaintenance(this.maintenance.id, (res) => {
if (res.ok) {
toast.success(res.msg);
this.$router.push("/maintenance");
} else {
toast.error(res.msg);
}
this.$root.toastRes(res);
this.$router.push("/maintenance");
});
},
},

@ -81,8 +81,6 @@ import { getResBaseURL } from "../util-frontend";
import { getMaintenanceRelativeURL } from "../util.ts";
import Confirm from "../components/Confirm.vue";
import MaintenanceTime from "../components/MaintenanceTime.vue";
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
components: {
@ -159,11 +157,9 @@ export default {
*/
deleteMaintenance() {
this.$root.deleteMaintenance(this.selectedMaintenanceID, (res) => {
this.$root.toastRes(res);
if (res.ok) {
toast.success(res.msg);
this.$router.push("/maintenance");
} else {
toast.error(res.msg);
}
});
},

@ -113,9 +113,6 @@ export default {
proxies: {
title: this.$t("Proxies"),
},
backup: {
title: this.$t("Backup"),
},
about: {
title: this.$t("About"),
},

@ -46,9 +46,6 @@
</template>
<script>
import { useToast } from "vue-toastification";
const toast = useToast();
export default {
data() {
return {
@ -79,7 +76,7 @@ export default {
this.processing = true;
if (this.password !== this.repeatPassword) {
toast.error(this.$t("PasswordsDoNotMatch"));
this.$root.toastError("PasswordsDoNotMatch");
this.processing = false;
return;
}

@ -179,7 +179,7 @@ export default {
},
test() {
toast.error("not implemented");
this.$root.toastError("not implemented");
}
},
};

@ -457,7 +457,7 @@ export default {
lastUpdateTime: dayjs(),
updateCountdown: null,
updateCountdownText: null,
loading: false,
loading: true,
};
},
computed: {
@ -633,7 +633,7 @@ export default {
}
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
}
@ -725,6 +725,8 @@ export default {
if (!localStorage.locale && this.config.defaultLocale) {
this.$root.changeCurrentPageLang(this.config.defaultLocale);
}
this.loading = false;
}).catch( function (error) {
if (error.response.status === 404) {
location.href = "/page-not-found";
@ -890,7 +892,7 @@ export default {
this.enableEditMode = false;
location.href = "/manage-status-page";
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});
},
@ -980,7 +982,7 @@ export default {
*/
postIncident() {
if (this.incident.title === "" || this.incident.content === "") {
toast.error(this.$t("Please input title and content"));
this.$root.toastError("Please input title and content");
return;
}
@ -990,7 +992,7 @@ export default {
this.enableEditIncidentMode = false;
this.incident = res.incident;
} else {
toast.error(res.msg);
this.$root.toastError(res.msg);
}
});

@ -30,7 +30,6 @@ import Tags from "./components/settings/Tags.vue";
import MonitorHistory from "./components/settings/MonitorHistory.vue";
const Security = () => import("./components/settings/Security.vue");
import Proxies from "./components/settings/Proxies.vue";
import Backup from "./components/settings/Backup.vue";
import About from "./components/settings/About.vue";
const routes = [
@ -126,10 +125,6 @@ const routes = [
path: "proxies",
component: Proxies,
},
{
path: "backup",
component: Backup,
},
{
path: "about",
component: About,

@ -1,13 +1,16 @@
"use strict";
/*!
// Common Util for frontend and backend
//
// DOT NOT MODIFY util.js!
// Need to run "tsc" to compile if there are any changes.
// Need to run "npm run tsc" to compile if there are any changes.
//
// Backend uses the compiled file util.js
// Frontend uses util.ts
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.MIN_INTERVAL_SECOND = exports.MAX_INTERVAL_SECOND = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.CONSOLE_STYLE_BgGray = exports.CONSOLE_STYLE_BgWhite = exports.CONSOLE_STYLE_BgCyan = exports.CONSOLE_STYLE_BgMagenta = exports.CONSOLE_STYLE_BgBlue = exports.CONSOLE_STYLE_BgYellow = exports.CONSOLE_STYLE_BgGreen = exports.CONSOLE_STYLE_BgRed = exports.CONSOLE_STYLE_BgBlack = exports.CONSOLE_STYLE_FgPink = exports.CONSOLE_STYLE_FgBrown = exports.CONSOLE_STYLE_FgViolet = exports.CONSOLE_STYLE_FgLightBlue = exports.CONSOLE_STYLE_FgLightGreen = exports.CONSOLE_STYLE_FgOrange = exports.CONSOLE_STYLE_FgGray = exports.CONSOLE_STYLE_FgWhite = exports.CONSOLE_STYLE_FgCyan = exports.CONSOLE_STYLE_FgMagenta = exports.CONSOLE_STYLE_FgBlue = exports.CONSOLE_STYLE_FgYellow = exports.CONSOLE_STYLE_FgGreen = exports.CONSOLE_STYLE_FgRed = exports.CONSOLE_STYLE_FgBlack = exports.CONSOLE_STYLE_Hidden = exports.CONSOLE_STYLE_Reverse = exports.CONSOLE_STYLE_Blink = exports.CONSOLE_STYLE_Underscore = exports.CONSOLE_STYLE_Dim = exports.CONSOLE_STYLE_Bright = exports.CONSOLE_STYLE_Reset = exports.MIN_INTERVAL_SECOND = exports.MAX_INTERVAL_SECOND = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
exports.intHash = exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = void 0;
const dayjs = require("dayjs");
exports.isDev = process.env.NODE_ENV === "development";
exports.appName = "Uptime Kuma";
@ -22,9 +25,57 @@ exports.STATUS_PAGE_MAINTENANCE = 3;
exports.SQL_DATE_FORMAT = "YYYY-MM-DD";
exports.SQL_DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = "YYYY-MM-DD HH:mm";
exports.MAX_INTERVAL_SECOND = 2073600; // 24 days
exports.MIN_INTERVAL_SECOND = 20; // 20 seconds
/** Flip the status of s */
exports.MAX_INTERVAL_SECOND = 2073600;
exports.MIN_INTERVAL_SECOND = 20;
exports.CONSOLE_STYLE_Reset = "\x1b[0m";
exports.CONSOLE_STYLE_Bright = "\x1b[1m";
exports.CONSOLE_STYLE_Dim = "\x1b[2m";
exports.CONSOLE_STYLE_Underscore = "\x1b[4m";
exports.CONSOLE_STYLE_Blink = "\x1b[5m";
exports.CONSOLE_STYLE_Reverse = "\x1b[7m";
exports.CONSOLE_STYLE_Hidden = "\x1b[8m";
exports.CONSOLE_STYLE_FgBlack = "\x1b[30m";
exports.CONSOLE_STYLE_FgRed = "\x1b[31m";
exports.CONSOLE_STYLE_FgGreen = "\x1b[32m";
exports.CONSOLE_STYLE_FgYellow = "\x1b[33m";
exports.CONSOLE_STYLE_FgBlue = "\x1b[34m";
exports.CONSOLE_STYLE_FgMagenta = "\x1b[35m";
exports.CONSOLE_STYLE_FgCyan = "\x1b[36m";
exports.CONSOLE_STYLE_FgWhite = "\x1b[37m";
exports.CONSOLE_STYLE_FgGray = "\x1b[90m";
exports.CONSOLE_STYLE_FgOrange = "\x1b[38;5;208m";
exports.CONSOLE_STYLE_FgLightGreen = "\x1b[38;5;119m";
exports.CONSOLE_STYLE_FgLightBlue = "\x1b[38;5;117m";
exports.CONSOLE_STYLE_FgViolet = "\x1b[38;5;141m";
exports.CONSOLE_STYLE_FgBrown = "\x1b[38;5;130m";
exports.CONSOLE_STYLE_FgPink = "\x1b[38;5;219m";
exports.CONSOLE_STYLE_BgBlack = "\x1b[40m";
exports.CONSOLE_STYLE_BgRed = "\x1b[41m";
exports.CONSOLE_STYLE_BgGreen = "\x1b[42m";
exports.CONSOLE_STYLE_BgYellow = "\x1b[43m";
exports.CONSOLE_STYLE_BgBlue = "\x1b[44m";
exports.CONSOLE_STYLE_BgMagenta = "\x1b[45m";
exports.CONSOLE_STYLE_BgCyan = "\x1b[46m";
exports.CONSOLE_STYLE_BgWhite = "\x1b[47m";
exports.CONSOLE_STYLE_BgGray = "\x1b[100m";
const consoleModuleColors = [
exports.CONSOLE_STYLE_FgCyan,
exports.CONSOLE_STYLE_FgGreen,
exports.CONSOLE_STYLE_FgLightGreen,
exports.CONSOLE_STYLE_FgBlue,
exports.CONSOLE_STYLE_FgLightBlue,
exports.CONSOLE_STYLE_FgMagenta,
exports.CONSOLE_STYLE_FgOrange,
exports.CONSOLE_STYLE_FgViolet,
exports.CONSOLE_STYLE_FgBrown,
exports.CONSOLE_STYLE_FgPink,
];
const consoleLevelColors = {
"INFO": exports.CONSOLE_STYLE_FgCyan,
"WARN": exports.CONSOLE_STYLE_FgYellow,
"ERROR": exports.CONSOLE_STYLE_FgRed,
"DEBUG": exports.CONSOLE_STYLE_FgGray,
};
function flipStatus(s) {
if (s === exports.UP) {
return exports.DOWN;
@ -35,18 +86,10 @@ function flipStatus(s) {
return s;
}
exports.flipStatus = flipStatus;
/**
* Delays for specified number of seconds
* @param ms Number of milliseconds to sleep for
*/
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
exports.sleep = sleep;
/**
* PHP's ucfirst
* @param str
*/
function ucfirst(str) {
if (!str) {
return str;
@ -55,26 +98,12 @@ function ucfirst(str) {
return firstLetter.toUpperCase() + str.substr(1);
}
exports.ucfirst = ucfirst;
/**
* @deprecated Use log.debug
* @since https://github.com/louislam/uptime-kuma/pull/910
* @param msg
*/
function debug(msg) {
exports.log.log("", msg, "debug");
}
exports.debug = debug;
class Logger {
constructor() {
/**
* UPTIME_KUMA_HIDE_LOG=debug_monitor,info_monitor
*
* Example:
* [
* "debug_monitor", // Hide all logs that level is debug and the module is monitor
* "info_monitor",
* ]
*/
this.hideLog = {
info: [],
warn: [],
@ -82,10 +111,9 @@ class Logger {
debug: [],
};
if (typeof process !== "undefined" && process.env.UPTIME_KUMA_HIDE_LOG) {
let list = process.env.UPTIME_KUMA_HIDE_LOG.split(",").map(v => v.toLowerCase());
for (let pair of list) {
// split first "_" only
let values = pair.split(/_(.*)/s);
const list = process.env.UPTIME_KUMA_HIDE_LOG.split(",").map(v => v.toLowerCase());
for (const pair of list) {
const values = pair.split(/_(.*)/s);
if (values.length >= 2) {
this.hideLog[values[0]].push(values[1]);
}
@ -94,12 +122,6 @@ class Logger {
this.debug("server", this.hideLog);
}
}
/**
* Write a message to the log
* @param module The module the log comes from
* @param msg Message to write
* @param level Log level. One of INFO, WARN, ERROR, DEBUG or can be customized.
*/
log(module, msg, level) {
if (this.hideLog[level] && this.hideLog[level].includes(module.toLowerCase())) {
return;
@ -113,63 +135,56 @@ class Logger {
else {
now = dayjs().format();
}
const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg;
const levelColor = consoleLevelColors[level];
const moduleColor = consoleModuleColors[intHash(module, consoleModuleColors.length)];
let timePart = exports.CONSOLE_STYLE_FgCyan + now + exports.CONSOLE_STYLE_Reset;
let modulePart = "[" + moduleColor + module + exports.CONSOLE_STYLE_Reset + "]";
let levelPart = levelColor + `${level}:` + exports.CONSOLE_STYLE_Reset;
if (level === "INFO") {
console.info(formattedMessage);
console.info(timePart, modulePart, levelPart, msg);
}
else if (level === "WARN") {
console.warn(formattedMessage);
console.warn(timePart, modulePart, levelPart, msg);
}
else if (level === "ERROR") {
console.error(formattedMessage);
let msgPart;
if (typeof msg === "string") {
msgPart = exports.CONSOLE_STYLE_FgRed + msg + exports.CONSOLE_STYLE_Reset;
}
else {
msgPart = msg;
}
console.error(timePart, modulePart, levelPart, msgPart);
}
else if (level === "DEBUG") {
if (exports.isDev) {
console.log(formattedMessage);
timePart = exports.CONSOLE_STYLE_FgGray + now + exports.CONSOLE_STYLE_Reset;
let msgPart;
if (typeof msg === "string") {
msgPart = exports.CONSOLE_STYLE_FgGray + msg + exports.CONSOLE_STYLE_Reset;
}
else {
msgPart = msg;
}
console.debug(timePart, modulePart, levelPart, msgPart);
}
}
else {
console.log(formattedMessage);
console.log(timePart, modulePart, msg);
}
}
/**
* Log an INFO message
* @param module Module log comes from
* @param msg Message to write
*/
info(module, msg) {
this.log(module, msg, "info");
}
/**
* Log a WARN message
* @param module Module log comes from
* @param msg Message to write
*/
warn(module, msg) {
this.log(module, msg, "warn");
}
/**
* Log an ERROR message
* @param module Module log comes from
* @param msg Message to write
*/
error(module, msg) {
this.log(module, msg, "error");
}
/**
* Log a DEBUG message
* @param module Module log comes from
* @param msg Message to write
*/
debug(module, msg) {
this.log(module, msg, "debug");
}
/**
* Log an exeption as an ERROR
* @param module Module log comes from
* @param exception The exeption to include
* @param msg The message to write
*/
exception(module, exception, msg) {
let finalMessage = exception;
if (msg) {
@ -179,20 +194,12 @@ class Logger {
}
}
exports.log = new Logger();
/**
* String.prototype.replaceAll() polyfill
* https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/
* @author Chris Ferdinandi
* @license MIT
*/
function polyfill() {
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function (str, newStr) {
// If a regex pattern
if (Object.prototype.toString.call(str).toLowerCase() === "[object regexp]") {
return this.replace(str, newStr);
}
// If a string
return this.replace(new RegExp(str, "g"), newStr);
};
}
@ -202,10 +209,6 @@ class TimeLogger {
constructor() {
this.startTime = dayjs().valueOf();
}
/**
* Output time since start of monitor
* @param name Name of monitor
*/
print(name) {
if (exports.isDev && process.env.TIMELOGGER === "1") {
console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms");
@ -213,66 +216,42 @@ class TimeLogger {
}
}
exports.TimeLogger = TimeLogger;
/**
* Returns a random number between min (inclusive) and max (exclusive)
*/
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
exports.getRandomArbitrary = getRandomArbitrary;
/**
* From: https://stackoverflow.com/questions/1527803/generating-random-whole-numbers-in-javascript-in-a-specific-range
*
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
exports.getRandomInt = getRandomInt;
/**
* Returns either the NodeJS crypto.randomBytes() function or its
* browser equivalent implemented via window.crypto.getRandomValues()
*/
let getRandomBytes = ((typeof window !== 'undefined' && window.crypto)
// Browsers
const getRandomBytes = ((typeof window !== "undefined" && window.crypto)
? function () {
return (numBytes) => {
let randomBytes = new Uint8Array(numBytes);
const randomBytes = new Uint8Array(numBytes);
for (let i = 0; i < numBytes; i += 65536) {
window.crypto.getRandomValues(randomBytes.subarray(i, i + Math.min(numBytes - i, 65536)));
}
return randomBytes;
};
}
// Node
: function () {
return require("crypto").randomBytes;
})();
/**
* Get a random integer suitable for use in cryptography between upper
* and lower bounds.
* @param min Minimum value of integer
* @param max Maximum value of integer
* @returns Cryptographically suitable random integer
*/
function getCryptoRandomInt(min, max) {
// synchronous version of: https://github.com/joepie91/node-random-number-csprng
const range = max - min;
if (range >= Math.pow(2, 32))
if (range >= Math.pow(2, 32)) {
console.log("Warning! Range is too large.");
}
let tmpRange = range;
let bitsNeeded = 0;
let bytesNeeded = 0;
let mask = 1;
while (tmpRange > 0) {
if (bitsNeeded % 8 === 0)
if (bitsNeeded % 8 === 0) {
bytesNeeded += 1;
}
bitsNeeded += 1;
mask = mask << 1 | 1;
tmpRange = tmpRange >>> 1;
@ -291,11 +270,6 @@ function getCryptoRandomInt(min, max) {
}
}
exports.getCryptoRandomInt = getCryptoRandomInt;
/**
* Generate a random alphanumeric string of fixed length
* @param length Length of string to generate
* @returns string
*/
function genSecret(length = 64) {
let secret = "";
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@ -306,29 +280,14 @@ function genSecret(length = 64) {
return secret;
}
exports.genSecret = genSecret;
/**
* Get the path of a monitor
* @param id ID of monitor
* @returns Formatted relative path
*/
function getMonitorRelativeURL(id) {
return "/dashboard/" + id;
}
exports.getMonitorRelativeURL = getMonitorRelativeURL;
/**
* Get relative path for maintenance
* @param id ID of maintenance
* @returns Formatted relative path
*/
function getMaintenanceRelativeURL(id) {
return "/maintenance/" + id;
}
exports.getMaintenanceRelativeURL = getMaintenanceRelativeURL;
/**
* Parse to Time Object that used in VueDatePicker
* @param {string} time E.g. 12:00
* @returns object
*/
function parseTimeObject(time) {
if (!time) {
return {
@ -336,11 +295,11 @@ function parseTimeObject(time) {
minutes: 0,
};
}
let array = time.split(":");
const array = time.split(":");
if (array.length < 2) {
throw new Error("parseVueDatePickerTimeFormat: Invalid Time");
}
let obj = {
const obj = {
hours: parseInt(array[0]),
minutes: parseInt(array[1]),
seconds: 0,
@ -351,9 +310,6 @@ function parseTimeObject(time) {
return obj;
}
exports.parseTimeObject = parseTimeObject;
/**
* @returns string e.g. 12:00
*/
function parseTimeFromTimeObject(obj) {
if (!obj) {
return obj;
@ -366,36 +322,27 @@ function parseTimeFromTimeObject(obj) {
return result;
}
exports.parseTimeFromTimeObject = parseTimeFromTimeObject;
/**
* Convert ISO date to UTC
* @param input Date
* @returns ISO Date time
*/
function isoToUTCDateTime(input) {
return dayjs(input).utc().format(exports.SQL_DATETIME_FORMAT);
}
exports.isoToUTCDateTime = isoToUTCDateTime;
/**
* @param input
*/
function utcToISODateTime(input) {
return dayjs.utc(input).toISOString();
}
exports.utcToISODateTime = utcToISODateTime;
/**
* For SQL_DATETIME_FORMAT
*/
function utcToLocal(input, format = exports.SQL_DATETIME_FORMAT) {
return dayjs.utc(input).local().format(format);
}
exports.utcToLocal = utcToLocal;
/**
* Convert local datetime to UTC
* @param input Local date
* @param format Format to return
* @returns Date in requested format
*/
function localToUTC(input, format = exports.SQL_DATETIME_FORMAT) {
return dayjs(input).utc().format(format);
}
exports.localToUTC = localToUTC;
function intHash(str, length = 10) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash += str.charCodeAt(i);
}
return (hash % length + length) % length;
}
exports.intHash = intHash;

@ -1,13 +1,19 @@
/*!
// Common Util for frontend and backend
//
// DOT NOT MODIFY util.js!
// Need to run "tsc" to compile if there are any changes.
// Need to run "npm run tsc" to compile if there are any changes.
//
// Backend uses the compiled file util.js
// Frontend uses util.ts
*/
import * as dayjs from "dayjs";
import * as dayjs from "dayjs";
// For loading dayjs plugins, don't remove event though it is not used in this file
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import * as timezone from "dayjs/plugin/timezone";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import * as utc from "dayjs/plugin/utc";
export const isDev = process.env.NODE_ENV === "development";
@ -29,7 +35,66 @@ export const SQL_DATETIME_FORMAT_WITHOUT_SECOND = "YYYY-MM-DD HH:mm";
export const MAX_INTERVAL_SECOND = 2073600; // 24 days
export const MIN_INTERVAL_SECOND = 20; // 20 seconds
/** Flip the status of s */
// Console colors
// https://stackoverflow.com/questions/9781218/how-to-change-node-jss-console-font-color
export const CONSOLE_STYLE_Reset = "\x1b[0m";
export const CONSOLE_STYLE_Bright = "\x1b[1m";
export const CONSOLE_STYLE_Dim = "\x1b[2m";
export const CONSOLE_STYLE_Underscore = "\x1b[4m";
export const CONSOLE_STYLE_Blink = "\x1b[5m";
export const CONSOLE_STYLE_Reverse = "\x1b[7m";
export const CONSOLE_STYLE_Hidden = "\x1b[8m";
export const CONSOLE_STYLE_FgBlack = "\x1b[30m";
export const CONSOLE_STYLE_FgRed = "\x1b[31m";
export const CONSOLE_STYLE_FgGreen = "\x1b[32m";
export const CONSOLE_STYLE_FgYellow = "\x1b[33m";
export const CONSOLE_STYLE_FgBlue = "\x1b[34m";
export const CONSOLE_STYLE_FgMagenta = "\x1b[35m";
export const CONSOLE_STYLE_FgCyan = "\x1b[36m";
export const CONSOLE_STYLE_FgWhite = "\x1b[37m";
export const CONSOLE_STYLE_FgGray = "\x1b[90m";
export const CONSOLE_STYLE_FgOrange = "\x1b[38;5;208m";
export const CONSOLE_STYLE_FgLightGreen = "\x1b[38;5;119m";
export const CONSOLE_STYLE_FgLightBlue = "\x1b[38;5;117m";
export const CONSOLE_STYLE_FgViolet = "\x1b[38;5;141m";
export const CONSOLE_STYLE_FgBrown = "\x1b[38;5;130m";
export const CONSOLE_STYLE_FgPink = "\x1b[38;5;219m";
export const CONSOLE_STYLE_BgBlack = "\x1b[40m";
export const CONSOLE_STYLE_BgRed = "\x1b[41m";
export const CONSOLE_STYLE_BgGreen = "\x1b[42m";
export const CONSOLE_STYLE_BgYellow = "\x1b[43m";
export const CONSOLE_STYLE_BgBlue = "\x1b[44m";
export const CONSOLE_STYLE_BgMagenta = "\x1b[45m";
export const CONSOLE_STYLE_BgCyan = "\x1b[46m";
export const CONSOLE_STYLE_BgWhite = "\x1b[47m";
export const CONSOLE_STYLE_BgGray = "\x1b[100m";
const consoleModuleColors = [
CONSOLE_STYLE_FgCyan,
CONSOLE_STYLE_FgGreen,
CONSOLE_STYLE_FgLightGreen,
CONSOLE_STYLE_FgBlue,
CONSOLE_STYLE_FgLightBlue,
CONSOLE_STYLE_FgMagenta,
CONSOLE_STYLE_FgOrange,
CONSOLE_STYLE_FgViolet,
CONSOLE_STYLE_FgBrown,
CONSOLE_STYLE_FgPink,
];
const consoleLevelColors : Record<string, string> = {
"INFO": CONSOLE_STYLE_FgCyan,
"WARN": CONSOLE_STYLE_FgYellow,
"ERROR": CONSOLE_STYLE_FgRed,
"DEBUG": CONSOLE_STYLE_FgGray,
};
/**
* Flip the status of s
* @param s
*/
export function flipStatus(s: number) {
if (s === UP) {
return DOWN;
@ -64,11 +129,10 @@ export function ucfirst(str: string) {
}
/**
* @deprecated Use log.debug
* @since https://github.com/louislam/uptime-kuma/pull/910
* @deprecated Use log.debug (https://github.com/louislam/uptime-kuma/pull/910)
* @param msg
*/
export function debug(msg: any) {
export function debug(msg: unknown) {
log.log("", msg, "debug");
}
@ -83,20 +147,23 @@ class Logger {
* "info_monitor",
* ]
*/
hideLog : any = {
hideLog : Record<string, string[]> = {
info: [],
warn: [],
error: [],
debug: [],
};
/**
*
*/
constructor() {
if (typeof process !== "undefined" && process.env.UPTIME_KUMA_HIDE_LOG) {
let list = process.env.UPTIME_KUMA_HIDE_LOG.split(",").map(v => v.toLowerCase());
const list = process.env.UPTIME_KUMA_HIDE_LOG.split(",").map(v => v.toLowerCase());
for (let pair of list) {
for (const pair of list) {
// split first "_" only
let values = pair.split(/_(.*)/s);
const values = pair.split(/_(.*)/s);
if (values.length >= 2) {
this.hideLog[values[0]].push(values[1]);
@ -128,20 +195,39 @@ class Logger {
} else {
now = dayjs().format();
}
const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg;
const levelColor = consoleLevelColors[level];
const moduleColor = consoleModuleColors[intHash(module, consoleModuleColors.length)];
let timePart = CONSOLE_STYLE_FgCyan + now + CONSOLE_STYLE_Reset;
let modulePart = "[" + moduleColor + module + CONSOLE_STYLE_Reset + "]";
let levelPart = levelColor + `${level}:` + CONSOLE_STYLE_Reset;
if (level === "INFO") {
console.info(formattedMessage);
console.info(timePart, modulePart, levelPart, msg);
} else if (level === "WARN") {
console.warn(formattedMessage);
console.warn(timePart, modulePart, levelPart, msg);
} else if (level === "ERROR") {
console.error(formattedMessage);
let msgPart :string;
if (typeof msg === "string") {
msgPart = CONSOLE_STYLE_FgRed + msg + CONSOLE_STYLE_Reset;
} else {
msgPart = msg;
}
console.error(timePart, modulePart, levelPart, msgPart);
} else if (level === "DEBUG") {
if (isDev) {
console.log(formattedMessage);
timePart = CONSOLE_STYLE_FgGray + now + CONSOLE_STYLE_Reset;
let msgPart :string;
if (typeof msg === "string") {
msgPart = CONSOLE_STYLE_FgGray + msg + CONSOLE_STYLE_Reset;
} else {
msgPart = msg;
}
console.debug(timePart, modulePart, levelPart, msgPart);
}
} else {
console.log(formattedMessage);
console.log(timePart, modulePart, msg);
}
}
@ -150,7 +236,7 @@ class Logger {
* @param module Module log comes from
* @param msg Message to write
*/
info(module: string, msg: any) {
info(module: string, msg: unknown) {
this.log(module, msg, "info");
}
@ -159,7 +245,7 @@ class Logger {
* @param module Module log comes from
* @param msg Message to write
*/
warn(module: string, msg: any) {
warn(module: string, msg: unknown) {
this.log(module, msg, "warn");
}
@ -168,8 +254,8 @@ class Logger {
* @param module Module log comes from
* @param msg Message to write
*/
error(module: string, msg: any) {
this.log(module, msg, "error");
error(module: string, msg: unknown) {
this.log(module, msg, "error");
}
/**
@ -177,24 +263,24 @@ class Logger {
* @param module Module log comes from
* @param msg Message to write
*/
debug(module: string, msg: any) {
this.log(module, msg, "debug");
debug(module: string, msg: unknown) {
this.log(module, msg, "debug");
}
/**
* Log an exeption as an ERROR
* Log an exception as an ERROR
* @param module Module log comes from
* @param exception The exeption to include
* @param exception The exception to include
* @param msg The message to write
*/
exception(module: string, exception: any, msg: any) {
let finalMessage = exception
exception(module: string, exception: unknown, msg: unknown) {
let finalMessage = exception;
if (msg) {
finalMessage = `${msg}: ${exception}`
finalMessage = `${msg}: ${exception}`;
}
this.log(module, finalMessage , "error");
this.log(module, finalMessage, "error");
}
}
@ -225,22 +311,28 @@ export function polyfill() {
export class TimeLogger {
startTime: number;
/**
*
*/
constructor() {
this.startTime = dayjs().valueOf();
}
/**
* Output time since start of monitor
* @param name Name of monitor
*/
print(name: string) {
if (isDev && process.env.TIMELOGGER === "1") {
console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms")
console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms");
}
}
}
/**
* Returns a random number between min (inclusive) and max (exclusive)
* @param min
* @param max
*/
export function getRandomArbitrary(min: number, max: number) {
return Math.random() * (max - min) + min;
@ -254,6 +346,8 @@ export function getRandomArbitrary(min: number, max: number) {
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
* @param min
* @param max
*/
export function getRandomInt(min: number, max: number) {
min = Math.ceil(min);
@ -265,13 +359,13 @@ export function getRandomInt(min: number, max: number) {
* Returns either the NodeJS crypto.randomBytes() function or its
* browser equivalent implemented via window.crypto.getRandomValues()
*/
let getRandomBytes = (
(typeof window !== 'undefined' && window.crypto)
const getRandomBytes = (
(typeof window !== "undefined" && window.crypto)
// Browsers
? function () {
return (numBytes: number) => {
let randomBytes = new Uint8Array(numBytes);
const randomBytes = new Uint8Array(numBytes);
for (let i = 0; i < numBytes; i += 65536) {
window.crypto.getRandomValues(randomBytes.subarray(i, i + Math.min(numBytes - i, 65536)));
}
@ -279,8 +373,9 @@ let getRandomBytes = (
};
}
// Node
: function() {
// Node
: function () {
// eslint-disable-next-line @typescript-eslint/no-var-requires
return require("crypto").randomBytes;
}
)();
@ -296,35 +391,38 @@ export function getCryptoRandomInt(min: number, max: number):number {
// synchronous version of: https://github.com/joepie91/node-random-number-csprng
const range = max - min
if (range >= Math.pow(2, 32))
console.log("Warning! Range is too large.")
const range = max - min;
if (range >= Math.pow(2, 32)) {
console.log("Warning! Range is too large.");
}
let tmpRange = range
let bitsNeeded = 0
let bytesNeeded = 0
let mask = 1
let tmpRange = range;
let bitsNeeded = 0;
let bytesNeeded = 0;
let mask = 1;
while (tmpRange > 0) {
if (bitsNeeded % 8 === 0) bytesNeeded += 1
bitsNeeded += 1
mask = mask << 1 | 1
tmpRange = tmpRange >>> 1
if (bitsNeeded % 8 === 0) {
bytesNeeded += 1;
}
bitsNeeded += 1;
mask = mask << 1 | 1;
tmpRange = tmpRange >>> 1;
}
const randomBytes = getRandomBytes(bytesNeeded)
let randomValue = 0
const randomBytes = getRandomBytes(bytesNeeded);
let randomValue = 0;
for (let i = 0; i < bytesNeeded; i++) {
randomValue |= randomBytes[i] << 8 * i
randomValue |= randomBytes[i] << 8 * i;
}
randomValue = randomValue & mask;
if (randomValue <= range) {
return min + randomValue
return min + randomValue;
} else {
return getCryptoRandomInt(min, max)
return getCryptoRandomInt(min, max);
}
}
@ -374,17 +472,17 @@ export function parseTimeObject(time: string) {
};
}
let array = time.split(":");
const array = time.split(":");
if (array.length < 2) {
throw new Error("parseVueDatePickerTimeFormat: Invalid Time");
}
let obj = {
const obj = {
hours: parseInt(array[0]),
minutes: parseInt(array[1]),
seconds: 0,
}
};
if (array.length >= 3) {
obj.seconds = parseInt(array[2]);
}
@ -392,6 +490,7 @@ export function parseTimeObject(time: string) {
}
/**
* @param obj
* @returns string e.g. 12:00
*/
export function parseTimeFromTimeObject(obj : any) {
@ -401,10 +500,10 @@ export function parseTimeFromTimeObject(obj : any) {
let result = "";
result += obj.hours.toString().padStart(2, "0") + ":" + obj.minutes.toString().padStart(2, "0")
result += obj.hours.toString().padStart(2, "0") + ":" + obj.minutes.toString().padStart(2, "0");
if (obj.seconds) {
result += ":" + obj.seconds.toString().padStart(2, "0")
result += ":" + obj.seconds.toString().padStart(2, "0");
}
return result;
@ -428,8 +527,11 @@ export function utcToISODateTime(input : string) {
/**
* For SQL_DATETIME_FORMAT
* @param input
* @param format
* @returns A string date of SQL_DATETIME_FORMAT
*/
export function utcToLocal(input : string, format = SQL_DATETIME_FORMAT) {
export function utcToLocal(input : string, format = SQL_DATETIME_FORMAT) : string {
return dayjs.utc(input).local().format(format);
}
@ -442,3 +544,19 @@ export function utcToLocal(input : string, format = SQL_DATETIME_FORMAT) {
export function localToUTC(input : string, format = SQL_DATETIME_FORMAT) {
return dayjs(input).utc().format(format);
}
/**
* Generate a decimal integer number from a string
* @param str Input
* @param length Default is 10 which means 0 - 9
*/
export function intHash(str : string, length = 10) : number {
// A simple hashing function (you can use more complex hash functions if needed)
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash += str.charCodeAt(i);
}
// Normalize the hash to the range [0, 10]
return (hash % length + length) % length; // Ensure the result is non-negative
}

@ -1,12 +1,9 @@
# Node.js Test Runner
Documentation: https://nodejs.org/api/test.html
Create a test file in this directory with the name `*.js`.
## Template
```js
@ -26,7 +23,7 @@ test("Test name", async (t) => {
});
```
## Run
## Run
Node.js >=18

@ -8,7 +8,8 @@
"es2020",
"DOM"
],
"removeComments": false,
"declaration": false,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": false,
"strict": true

Loading…
Cancel
Save