Merge branch 'master' into feature/umami-analytics-status-page
This commit is contained in:
commit
c4c747407e
167
.github/copilot-instructions.md
vendored
Normal file
167
.github/copilot-instructions.md
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
# Copilot Instructions for Uptime Kuma
|
||||
|
||||
## Copilot's Goals/Tasks
|
||||
|
||||
- Check spelling
|
||||
- Do not show "Pull Request Overview"
|
||||
- You do not have to reply if there are no issues
|
||||
|
||||
## Repository Overview
|
||||
|
||||
**Uptime Kuma** is a self-hosted monitoring tool for HTTP(s), TCP, DNS, Docker, etc. Built with Vue 3 (frontend) and Node.js/Express (backend), using Socket.IO for real-time communication.
|
||||
|
||||
- **Languages**: JavaScript, Vue 3, TypeScript (limited), HTML, CSS/SCSS
|
||||
- **Backend**: Node.js >= 20.4, Express.js, Socket.IO, SQLite
|
||||
- **Frontend**: Vue 3, Vite, Bootstrap 5, Chart.js
|
||||
- **Package Manager**: npm with `legacy-peer-deps=true` (.npmrc)
|
||||
|
||||
## Build & Validation Commands
|
||||
|
||||
### Prerequisites
|
||||
- Node.js >= 20.4.0, npm >= 9.3, Git
|
||||
|
||||
### Essential Command Sequence
|
||||
|
||||
1. **Install Dependencies**:
|
||||
```bash
|
||||
npm ci # Use npm ci NOT npm install (~60-90 seconds)
|
||||
```
|
||||
|
||||
2. **Linting** (required before committing):
|
||||
```bash
|
||||
npm run lint # Both linters (~15-30 seconds)
|
||||
npm run lint:prod # For production (zero warnings)
|
||||
```
|
||||
|
||||
3. **Build Frontend**:
|
||||
```bash
|
||||
npm run build # Takes ~90-120 seconds, builds to dist/
|
||||
```
|
||||
|
||||
4. **Run Tests**:
|
||||
```bash
|
||||
npm run test-backend # Backend tests (~50-60 seconds)
|
||||
npm test # All tests
|
||||
```
|
||||
|
||||
### Development Workflow
|
||||
|
||||
```bash
|
||||
npm run dev # Starts frontend (port 3000) and backend (port 3001)
|
||||
```
|
||||
|
||||
## Project Architecture
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
/
|
||||
├── server/ Backend source code
|
||||
│ ├── model/ Database models (auto-mapped to tables)
|
||||
│ ├── monitor-types/ Monitor type implementations
|
||||
│ ├── notification-providers/ Notification integrations
|
||||
│ ├── routers/ Express routers
|
||||
│ ├── socket-handlers/ Socket.IO event handlers
|
||||
│ ├── server.js Server entry point
|
||||
│ └── uptime-kuma-server.js Main server logic
|
||||
├── src/ Frontend source code (Vue 3 SPA)
|
||||
│ ├── components/ Vue components
|
||||
│ ├── pages/ Page components
|
||||
│ ├── lang/ i18n translations
|
||||
│ ├── router.js Vue Router configuration
|
||||
│ └── main.js Frontend entry point
|
||||
├── db/ Database related
|
||||
│ ├── knex_migrations/ Knex migration files
|
||||
│ └── kuma.db SQLite database (gitignored)
|
||||
├── test/ Test files
|
||||
│ ├── backend-test/ Backend unit tests
|
||||
│ └── e2e/ Playwright E2E tests
|
||||
├── config/ Build configuration
|
||||
│ ├── vite.config.js Vite build config
|
||||
│ └── playwright.config.js Playwright test config
|
||||
├── dist/ Frontend build output (gitignored)
|
||||
├── data/ App data directory (gitignored)
|
||||
├── public/ Static frontend assets (dev only)
|
||||
├── docker/ Docker build files
|
||||
└── extra/ Utility scripts
|
||||
```
|
||||
|
||||
### Key Configuration Files
|
||||
|
||||
- **package.json**: Scripts, dependencies, Node.js version requirement
|
||||
- **.eslintrc.js**: ESLint rules (4 spaces, double quotes, unix line endings, JSDoc required)
|
||||
- **.stylelintrc**: Stylelint rules (4 spaces indentation)
|
||||
- **.editorconfig**: Editor settings (4 spaces, LF, UTF-8)
|
||||
- **tsconfig-backend.json**: TypeScript config for backend (only src/util.ts)
|
||||
- **.npmrc**: `legacy-peer-deps=true` (required for dependency resolution)
|
||||
- **.gitignore**: Excludes node_modules, dist, data, tmp, private
|
||||
|
||||
### Code Style (strictly enforced by linters)
|
||||
|
||||
- 4 spaces indentation, double quotes, Unix line endings (LF), semicolons required
|
||||
- **Naming**: JavaScript/TypeScript (camelCase), SQLite (snake_case), CSS/SCSS (kebab-case)
|
||||
- JSDoc required for all functions/methods
|
||||
|
||||
## CI/CD Workflows
|
||||
|
||||
**auto-test.yml** (runs on PR/push to master/1.23.X):
|
||||
- Linting, building, backend tests on multiple OS/Node versions (15 min timeout)
|
||||
- E2E Playwright tests
|
||||
|
||||
**validate.yml**: Validates JSON/YAML files, language files, knex migrations
|
||||
|
||||
**PR Requirements**: All linters pass, tests pass, code follows style guidelines
|
||||
|
||||
## Common Issues
|
||||
|
||||
1. **npm install vs npm ci**: Always use `npm ci` for reproducible builds
|
||||
2. **TypeScript errors**: `npm run tsc` shows 1400+ errors - ignore them, they don't affect builds
|
||||
3. **Stylelint warnings**: Deprecation warnings are expected, ignore them
|
||||
4. **Test failures**: Always run `npm run build` before running tests
|
||||
5. **Port conflicts**: Dev server uses ports 3000 and 3001
|
||||
6. **First run**: Server shows "db-config.json not found" - this is expected, starts setup wizard
|
||||
|
||||
## Translations
|
||||
|
||||
- Managed via Weblate. Add keys to `src/lang/en.json` only
|
||||
- Don't include other languages in PRs
|
||||
- Use `$t("key")` in Vue templates
|
||||
|
||||
## Database
|
||||
|
||||
- Primary: SQLite (also supports MariaDB/MySQL/PostgreSQL)
|
||||
- Migrations in `db/knex_migrations/` using Knex.js
|
||||
- Filename format validated by CI: `node ./extra/check-knex-filenames.mjs`
|
||||
|
||||
## Testing
|
||||
|
||||
- **Backend**: Node.js test runner, fast unit tests
|
||||
- **E2E**: Playwright (requires `npx playwright install` first time)
|
||||
- Test data in `data/playwright-test`
|
||||
|
||||
## Adding New Features
|
||||
|
||||
### New Notification Provider
|
||||
Files to modify:
|
||||
1. `server/notification-providers/PROVIDER_NAME.js` (backend logic)
|
||||
2. `server/notification.js` (register provider)
|
||||
3. `src/components/notifications/PROVIDER_NAME.vue` (frontend UI)
|
||||
4. `src/components/notifications/index.js` (register frontend)
|
||||
5. `src/components/NotificationDialog.vue` (add to list)
|
||||
6. `src/lang/en.json` (add translation keys)
|
||||
|
||||
### New Monitor Type
|
||||
Files to modify:
|
||||
1. `server/monitor-types/MONITORING_TYPE.js` (backend logic)
|
||||
2. `server/uptime-kuma-server.js` (register monitor type)
|
||||
3. `src/pages/EditMonitor.vue` (frontend UI)
|
||||
4. `src/lang/en.json` (add translation keys)
|
||||
|
||||
## Important Notes
|
||||
|
||||
1. **Trust these instructions** - based on testing. Search only if incomplete/incorrect
|
||||
2. **Dependencies**: 5 known vulnerabilities (3 moderate, 2 high) - acknowledged, don't fix without discussion
|
||||
3. **Git Branches**: `master` (v2 development), `1.23.X` (v1 maintenance)
|
||||
4. **Node Version**: >= 20.4.0 required
|
||||
5. **Socket.IO**: Most backend logic in `server/socket-handlers/`, not REST
|
||||
6. **Never commit**: `data/`, `dist/`, `tmp/`, `private/`, `node_modules/`
|
||||
6
.github/workflows/auto-test.yml
vendored
6
.github/workflows/auto-test.yml
vendored
@ -22,8 +22,12 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-22.04, windows-latest, ARM64]
|
||||
node: [ 20, 24 ]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
node: [ 20, 24 ]
|
||||
# Also test non-LTS, but only on Ubuntu.
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
node: 25
|
||||
|
||||
steps:
|
||||
- run: git config --global core.autocrlf false # Mainly for Windows
|
||||
|
||||
22
README.md
22
README.md
@ -45,8 +45,7 @@ cd uptime-kuma
|
||||
curl -o compose.yaml https://raw.githubusercontent.com/louislam/uptime-kuma/master/compose.yaml
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Uptime Kuma is now running on <http://0.0.0.0:3001>.
|
||||
Uptime Kuma is now running on all network interfaces (e.g. http://localhost:3001 or http://your-ip:3001).
|
||||
|
||||
> [!WARNING]
|
||||
> File Systems like **NFS** (Network File System) are **NOT** supported. Please map to a local directory or volume.
|
||||
@ -56,22 +55,22 @@ Uptime Kuma is now running on <http://0.0.0.0:3001>.
|
||||
```bash
|
||||
docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:2
|
||||
```
|
||||
Uptime Kuma is now running on all network interfaces (e.g. http://localhost:3001 or http://your-ip:3001).
|
||||
|
||||
If you want to limit exposure to localhost only:
|
||||
|
||||
```bash
|
||||
docker run ... -p 127.0.0.1:3001:3001 ...
|
||||
```
|
||||
|
||||
Uptime Kuma is now running on <http://0.0.0.0:3001>.
|
||||
|
||||
> [!NOTE]
|
||||
> If you want to limit exposure to localhost (without exposing port for other users or to use a [reverse proxy](https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy)), you can expose the port like this:
|
||||
>
|
||||
> ```bash
|
||||
> docker run -d --restart=always -p 127.0.0.1:3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:2
|
||||
> ```
|
||||
|
||||
### 💪🏻 Non-Docker
|
||||
|
||||
Requirements:
|
||||
|
||||
- Platform
|
||||
- ✅ Major Linux distros such as Debian, Ubuntu, CentOS, Fedora and ArchLinux etc.
|
||||
- ✅ Major Linux distros such as Debian, Ubuntu, Fedora and ArchLinux etc.
|
||||
- ✅ Windows 10 (x64), Windows Server 2012 R2 (x64) or higher
|
||||
- ❌ FreeBSD / OpenBSD / NetBSD
|
||||
- ❌ Replit / Heroku
|
||||
@ -94,8 +93,7 @@ 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>
|
||||
Uptime Kuma is now running on all network interfaces (e.g. http://localhost:3001 or http://your-ip:3001).
|
||||
|
||||
More useful PM2 Commands
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ import vue from "@vitejs/plugin-vue";
|
||||
import { defineConfig } from "vite";
|
||||
import visualizer from "rollup-plugin-visualizer";
|
||||
import viteCompression from "vite-plugin-compression";
|
||||
import VueDevTools from "vite-plugin-vue-devtools";
|
||||
|
||||
const postCssScss = require("postcss-scss");
|
||||
const postcssRTLCSS = require("postcss-rtlcss");
|
||||
@ -31,7 +30,6 @@ export default defineConfig({
|
||||
algorithm: "brotliCompress",
|
||||
filter: viteCompressionFilter,
|
||||
}),
|
||||
VueDevTools(),
|
||||
],
|
||||
css: {
|
||||
postcss: {
|
||||
|
||||
1356
package-lock.json
generated
1356
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,7 @@
|
||||
"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": "node extra/release/upload-artifacts.mjs",
|
||||
"upload-artifacts-beta": "node extra/release/upload-artifacts-beta.mjs",
|
||||
"setup": "git checkout 2.0.2 && npm ci --omit dev && npm run download-dist",
|
||||
"setup": "git checkout 2.0.2 && npm ci --omit dev --no-audit && 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",
|
||||
@ -199,7 +199,6 @@
|
||||
"v-pagination-3": "~0.1.7",
|
||||
"vite": "~5.4.15",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-vue-devtools": "^7.0.15",
|
||||
"vue": "~3.4.2",
|
||||
"vue-chartjs": "~5.2.0",
|
||||
"vue-confirm-dialog": "~1.0.2",
|
||||
|
||||
@ -1727,6 +1727,55 @@ class Monitor extends BeanModel {
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a monitor from the system
|
||||
* @param {number} monitorID ID of the monitor to delete
|
||||
* @param {number} userID ID of the user who owns the monitor
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async deleteMonitor(monitorID, userID) {
|
||||
const server = UptimeKumaServer.getInstance();
|
||||
|
||||
// Stop the monitor if it's running
|
||||
if (monitorID in server.monitorList) {
|
||||
await server.monitorList[monitorID].stop();
|
||||
delete server.monitorList[monitorID];
|
||||
}
|
||||
|
||||
// Delete from database
|
||||
await R.exec("DELETE FROM monitor WHERE id = ? AND user_id = ? ", [
|
||||
monitorID,
|
||||
userID,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively delete a monitor and all its descendants
|
||||
* @param {number} monitorID ID of the monitor to delete
|
||||
* @param {number} userID ID of the user who owns the monitor
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async deleteMonitorRecursively(monitorID, userID) {
|
||||
// Check if this monitor is a group
|
||||
const monitor = await R.findOne("monitor", " id = ? AND user_id = ? ", [
|
||||
monitorID,
|
||||
userID,
|
||||
]);
|
||||
|
||||
if (monitor && monitor.type === "group") {
|
||||
// Get all children and delete them recursively
|
||||
const children = await Monitor.getChildren(monitorID);
|
||||
if (children && children.length > 0) {
|
||||
for (const child of children) {
|
||||
await Monitor.deleteMonitorRecursively(child.id, userID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the monitor itself
|
||||
await Monitor.deleteMonitor(monitorID, userID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks recursive if parent (ancestors) are active
|
||||
* @param {number} monitorID ID of the monitor to get
|
||||
|
||||
@ -11,35 +11,67 @@ class GroupMonitorType extends MonitorType {
|
||||
async check(monitor, heartbeat, _server) {
|
||||
const children = await Monitor.getChildren(monitor.id);
|
||||
|
||||
if (children.length > 0) {
|
||||
heartbeat.status = UP;
|
||||
heartbeat.msg = "All children up and running";
|
||||
for (const child of children) {
|
||||
if (!child.active) {
|
||||
// Ignore inactive childs
|
||||
continue;
|
||||
}
|
||||
const lastBeat = await Monitor.getPreviousHeartbeat(child.id);
|
||||
|
||||
// Only change state if the monitor is in worse conditions then the ones before
|
||||
// lastBeat.status could be null
|
||||
if (!lastBeat) {
|
||||
heartbeat.status = PENDING;
|
||||
} else if (heartbeat.status === UP && (lastBeat.status === PENDING || lastBeat.status === DOWN)) {
|
||||
heartbeat.status = lastBeat.status;
|
||||
} else if (heartbeat.status === PENDING && lastBeat.status === DOWN) {
|
||||
heartbeat.status = lastBeat.status;
|
||||
}
|
||||
}
|
||||
|
||||
if (heartbeat.status !== UP) {
|
||||
heartbeat.msg = "Child inaccessible";
|
||||
}
|
||||
} else {
|
||||
if (children.length === 0) {
|
||||
// Set status pending if group is empty
|
||||
heartbeat.status = PENDING;
|
||||
heartbeat.msg = "Group empty";
|
||||
return;
|
||||
}
|
||||
|
||||
let worstStatus = UP;
|
||||
const downChildren = [];
|
||||
const pendingChildren = [];
|
||||
|
||||
for (const child of children) {
|
||||
if (!child.active) {
|
||||
// Ignore inactive (=paused) children
|
||||
continue;
|
||||
}
|
||||
|
||||
const label = child.name || `#${child.id}`;
|
||||
const lastBeat = await Monitor.getPreviousHeartbeat(child.id);
|
||||
|
||||
if (!lastBeat) {
|
||||
if (worstStatus === UP) {
|
||||
worstStatus = PENDING;
|
||||
}
|
||||
pendingChildren.push(label);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastBeat.status === DOWN) {
|
||||
worstStatus = DOWN;
|
||||
downChildren.push(label);
|
||||
} else if (lastBeat.status === PENDING) {
|
||||
if (worstStatus !== DOWN) {
|
||||
worstStatus = PENDING;
|
||||
}
|
||||
pendingChildren.push(label);
|
||||
}
|
||||
}
|
||||
|
||||
if (worstStatus === UP) {
|
||||
heartbeat.status = UP;
|
||||
heartbeat.msg = "All children up and running";
|
||||
return;
|
||||
}
|
||||
|
||||
if (worstStatus === PENDING) {
|
||||
heartbeat.status = PENDING;
|
||||
heartbeat.msg = `Pending child monitors: ${pendingChildren.join(", ")}`;
|
||||
return;
|
||||
}
|
||||
|
||||
heartbeat.status = DOWN;
|
||||
|
||||
let message = `Child monitors down: ${downChildren.join(", ")}`;
|
||||
|
||||
if (pendingChildren.length > 0) {
|
||||
message += `; pending: ${pendingChildren.join(", ")}`;
|
||||
}
|
||||
|
||||
// Throw to leverage the generic retry handling and notification flow
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ class TailscalePing extends MonitorType {
|
||||
timeout: timeout,
|
||||
encoding: "utf8",
|
||||
});
|
||||
if (res.stderr && res.stderr.toString()) {
|
||||
if (res.stderr && res.stderr.toString() && res.code !== 0) {
|
||||
throw new Error(`Error in output: ${res.stderr.toString()}`);
|
||||
}
|
||||
if (res.stdout && res.stdout.toString()) {
|
||||
|
||||
52
server/notification-providers/smsir.js
Normal file
52
server/notification-providers/smsir.js
Normal file
@ -0,0 +1,52 @@
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
|
||||
class SMSIR extends NotificationProvider {
|
||||
name = "smsir";
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
const okMsg = "Sent Successfully.";
|
||||
const url = "https://api.sms.ir/v1/send/verify";
|
||||
|
||||
try {
|
||||
let config = {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
"X-API-Key": notification.smsirApiKey
|
||||
}
|
||||
};
|
||||
config = this.getAxiosConfigWithProxy(config);
|
||||
|
||||
let formattedMobile = notification.smsirNumber;
|
||||
if (formattedMobile.length === 11 && formattedMobile.startsWith("09") && String(parseInt(formattedMobile)) === formattedMobile.substring(1)) {
|
||||
// 09xxxxxxxxx Format
|
||||
formattedMobile = formattedMobile.substring(1);
|
||||
}
|
||||
|
||||
await axios.post(
|
||||
url,
|
||||
{
|
||||
mobile: formattedMobile,
|
||||
templateId: parseInt(notification.smsirTemplate),
|
||||
parameters: [
|
||||
{
|
||||
name: "uptkumaalert",
|
||||
value: msg
|
||||
}
|
||||
]
|
||||
},
|
||||
config
|
||||
);
|
||||
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SMSIR;
|
||||
@ -17,6 +17,7 @@ class Telegram extends NotificationProvider {
|
||||
text: msg,
|
||||
disable_notification: notification.telegramSendSilently ?? false,
|
||||
protect_content: notification.telegramProtectContent ?? false,
|
||||
link_preview_options: { is_disabled: true },
|
||||
};
|
||||
if (notification.telegramMessageThreadID) {
|
||||
params.message_thread_id = notification.telegramMessageThreadID;
|
||||
@ -30,9 +31,9 @@ class Telegram extends NotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
let config = this.getAxiosConfigWithProxy({ params });
|
||||
let config = this.getAxiosConfigWithProxy();
|
||||
|
||||
await axios.get(`${url}/bot${notification.telegramBotToken}/sendMessage`, config);
|
||||
await axios.post(`${url}/bot${notification.telegramBotToken}/sendMessage`, params, config);
|
||||
return okMsg;
|
||||
|
||||
} catch (error) {
|
||||
|
||||
@ -81,6 +81,7 @@ const Brevo = require("./notification-providers/brevo");
|
||||
const YZJ = require("./notification-providers/yzj");
|
||||
const SMSPlanet = require("./notification-providers/sms-planet");
|
||||
const SpugPush = require("./notification-providers/spugpush");
|
||||
const SMSIR = require("./notification-providers/smsir");
|
||||
const { commandExists } = require("./util-server");
|
||||
|
||||
class Notification {
|
||||
@ -179,6 +180,7 @@ class Notification {
|
||||
new SMSPlanet(),
|
||||
new SpugPush(),
|
||||
new Notifery(),
|
||||
new SMSIR(),
|
||||
];
|
||||
for (let item of list) {
|
||||
if (!item.name) {
|
||||
|
||||
@ -59,7 +59,7 @@ if (process.env.UPTIME_KUMA_WS_ORIGIN_CHECK === "bypass") {
|
||||
}
|
||||
|
||||
const checkVersion = require("./check-version");
|
||||
log.info("server", "Uptime Kuma Version: " + checkVersion.version);
|
||||
log.info("server", "Uptime Kuma Version:", checkVersion.version);
|
||||
|
||||
log.info("server", "Loading modules");
|
||||
|
||||
@ -1047,30 +1047,78 @@ let needSetup = false;
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("deleteMonitor", async (monitorID, callback) => {
|
||||
socket.on("deleteMonitor", async (monitorID, deleteChildren, callback) => {
|
||||
try {
|
||||
checkLogin(socket);
|
||||
|
||||
log.info("manage", `Delete Monitor: ${monitorID} User ID: ${socket.userID}`);
|
||||
|
||||
if (monitorID in server.monitorList) {
|
||||
await server.monitorList[monitorID].stop();
|
||||
delete server.monitorList[monitorID];
|
||||
// Backward compatibility: if deleteChildren is omitted, the second parameter is the callback
|
||||
if (typeof deleteChildren === "function") {
|
||||
callback = deleteChildren;
|
||||
deleteChildren = false;
|
||||
}
|
||||
|
||||
checkLogin(socket);
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
await R.exec("DELETE FROM monitor WHERE id = ? AND user_id = ? ", [
|
||||
// Check if this is a group monitor
|
||||
const monitor = await R.findOne("monitor", " id = ? AND user_id = ? ", [
|
||||
monitorID,
|
||||
socket.userID,
|
||||
]);
|
||||
|
||||
// Log with context about deletion type
|
||||
if (monitor && monitor.type === "group") {
|
||||
if (deleteChildren) {
|
||||
log.info("manage", `Delete Group and Children: ${monitorID} User ID: ${socket.userID}`);
|
||||
} else {
|
||||
log.info("manage", `Delete Group (unlink children): ${monitorID} User ID: ${socket.userID}`);
|
||||
}
|
||||
} else {
|
||||
log.info("manage", `Delete Monitor: ${monitorID} User ID: ${socket.userID}`);
|
||||
}
|
||||
|
||||
if (monitor && monitor.type === "group") {
|
||||
// Get all children before processing
|
||||
const children = await Monitor.getChildren(monitorID);
|
||||
|
||||
if (deleteChildren) {
|
||||
// Delete all child monitors recursively
|
||||
if (children && children.length > 0) {
|
||||
for (const child of children) {
|
||||
await Monitor.deleteMonitorRecursively(child.id, socket.userID);
|
||||
await server.sendDeleteMonitorFromList(socket, child.id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Unlink all children from the group (set parent to null)
|
||||
await Monitor.unlinkAllChildren(monitorID);
|
||||
|
||||
// Notify frontend to update each child monitor's parent to null
|
||||
if (children && children.length > 0) {
|
||||
for (const child of children) {
|
||||
await server.sendUpdateMonitorIntoList(socket, child.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the monitor itself
|
||||
await Monitor.deleteMonitor(monitorID, socket.userID);
|
||||
|
||||
// Fix #2880
|
||||
apicache.clear();
|
||||
|
||||
const endTime = Date.now();
|
||||
|
||||
log.info("DB", `Delete Monitor completed in : ${endTime - startTime} ms`);
|
||||
// Log completion with context about children handling
|
||||
if (monitor && monitor.type === "group") {
|
||||
if (deleteChildren) {
|
||||
log.info("DB", `Delete Monitor completed (group and children deleted) in: ${endTime - startTime} ms`);
|
||||
} else {
|
||||
log.info("DB", `Delete Monitor completed (group deleted, children unlinked) in: ${endTime - startTime} ms`);
|
||||
}
|
||||
} else {
|
||||
log.info("DB", `Delete Monitor completed in: ${endTime - startTime} ms`);
|
||||
}
|
||||
|
||||
callback({
|
||||
ok: true,
|
||||
|
||||
@ -1,6 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<div :style="depthMargin">
|
||||
<div
|
||||
class="draggable-item"
|
||||
:style="depthMargin"
|
||||
:class="{ 'drag-over': dragOverCount > 0 }"
|
||||
@dragstart="onDragStart"
|
||||
@dragenter.prevent="onDragEnter"
|
||||
@dragleave.prevent="onDragLeave"
|
||||
@dragover.prevent
|
||||
@drop.prevent="onDrop"
|
||||
>
|
||||
<!-- Checkbox -->
|
||||
<div v-if="isSelectMode" class="select-input-wrapper">
|
||||
<input
|
||||
@ -116,6 +125,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
isCollapsed: true,
|
||||
dragOverCount: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -187,6 +197,91 @@ export default {
|
||||
|
||||
window.localStorage.setItem("monitorCollapsed", JSON.stringify(storageObject));
|
||||
},
|
||||
/**
|
||||
* Initializes the drag operation if the monitor is draggable.
|
||||
* @param {DragEvent} event - The dragstart event triggered by the browser.
|
||||
* @returns {void} This method does not return anything.
|
||||
*/
|
||||
onDragStart(event) {
|
||||
try {
|
||||
event.dataTransfer.setData("text/monitor-id", String(this.monitor.id));
|
||||
event.dataTransfer.effectAllowed = "move";
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
},
|
||||
|
||||
onDragEnter(event) {
|
||||
if (this.monitor.type !== "group") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dragOverCount++;
|
||||
},
|
||||
|
||||
onDragLeave(event) {
|
||||
if (this.monitor.type !== "group") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dragOverCount = Math.max(0, this.dragOverCount - 1);
|
||||
},
|
||||
|
||||
async onDrop(event) {
|
||||
this.dragOverCount = 0;
|
||||
|
||||
// Only groups accept drops
|
||||
if (this.monitor.type !== "group") {
|
||||
return;
|
||||
}
|
||||
|
||||
const draggedId = event.dataTransfer.getData("text/monitor-id");
|
||||
if (!draggedId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const draggedMonitorId = parseInt(draggedId);
|
||||
if (isNaN(draggedMonitorId) || draggedMonitorId === this.monitor.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const draggedMonitor = this.$root.monitorList[draggedMonitorId];
|
||||
if (!draggedMonitor) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save original parent so we can revert locally if server returns error
|
||||
const originalParent = draggedMonitor.parent;
|
||||
|
||||
// Prepare a full monitor object (clone) and set new parent
|
||||
const monitorToSave = JSON.parse(JSON.stringify(draggedMonitor));
|
||||
monitorToSave.parent = this.monitor.id;
|
||||
|
||||
// Optimistically update local state so UI updates immediately
|
||||
this.$root.monitorList[draggedMonitorId].parent = this.monitor.id;
|
||||
|
||||
// Send updated monitor state via socket
|
||||
try {
|
||||
this.$root.getSocket().emit("editMonitor", monitorToSave, (res) => {
|
||||
if (!res || !res.ok) {
|
||||
// Revert local change on error
|
||||
if (this.$root.monitorList[draggedMonitorId]) {
|
||||
this.$root.monitorList[draggedMonitorId].parent = originalParent;
|
||||
}
|
||||
if (res && res.msg) {
|
||||
this.$root.toastError(res.msg);
|
||||
}
|
||||
} else {
|
||||
this.$root.toastRes(res);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
// revert on exception
|
||||
if (this.$root.monitorList[draggedMonitorId]) {
|
||||
this.$root.monitorList[draggedMonitorId].parent = originalParent;
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Get URL of monitor
|
||||
* @param {number} id ID of monitor
|
||||
@ -253,4 +348,35 @@ export default {
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
.drag-over {
|
||||
border: 4px dashed $primary;
|
||||
border-radius: 0.5rem;
|
||||
background-color: $highlight-white;
|
||||
}
|
||||
|
||||
.dark {
|
||||
.drag-over {
|
||||
background-color: $dark-bg2;
|
||||
}
|
||||
}
|
||||
|
||||
/* -4px on all due to border-width */
|
||||
.monitor-list .drag-over .item {
|
||||
padding: 9px 11px 6px 11px;
|
||||
}
|
||||
|
||||
.draggable-item {
|
||||
cursor: grab;
|
||||
position: relative;
|
||||
|
||||
/* We don't want the padding change due to the border animated */
|
||||
.item {
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
&.dragging {
|
||||
cursor: grabbing;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@ -192,6 +192,7 @@ export default {
|
||||
"PushPlus": "PushPlus (推送加)",
|
||||
"SpugPush": "SpugPush(Spug推送助手)",
|
||||
"smsc": "SMSC",
|
||||
"smsir": "SMS.IR",
|
||||
"WPush": "WPush(wpush.cn)",
|
||||
"YZJ": "YZJ (云之家自定义机器人)",
|
||||
"SMSPlanet": "SMSPlanet.pl"
|
||||
|
||||
31
src/components/notifications/SMSIR.vue
Normal file
31
src/components/notifications/SMSIR.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="smsir-key" class="form-label">{{ $t("API Key") }}</label>
|
||||
<HiddenInput id="smsir-key" v-model="$parent.notification.smsirApiKey" :required="true" autocomplete="new-password"></HiddenInput>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="smsir-number" class="form-label">{{ $t("Recipient Number") }}</label>
|
||||
<input id="smsir-number" v-model="$parent.notification.smsirNumber" placeholder="9123456789" type="text" maxlength="11" minlength="10" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="smsir-template" class="form-label">{{ $t("Template ID") }}</label>
|
||||
<input id="smsir-template" v-model="$parent.notification.smsirTemplate" placeholder="12345" type="text" class="form-control" required>
|
||||
<i18n-t tag="div" class="form-text" keypath="wayToGetClickSMSIRTemplateID">
|
||||
<template #uptkumaalert>
|
||||
<code>#uptkumaalert#</code>
|
||||
</template>
|
||||
<template #here>
|
||||
<a href="https://app.sms.ir/fast-send/template" target="_blank">{{ $t("here") }}</a>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -79,6 +79,7 @@ import SendGrid from "./SendGrid.vue";
|
||||
import Brevo from "./Brevo.vue";
|
||||
import YZJ from "./YZJ.vue";
|
||||
import SMSPlanet from "./SMSPlanet.vue";
|
||||
import SMSIR from "./SMSIR.vue";
|
||||
|
||||
/**
|
||||
* Manage all notification form.
|
||||
@ -95,6 +96,7 @@ const NotificationFormList = {
|
||||
"clicksendsms": ClickSendSMS,
|
||||
"CallMeBot": CallMeBot,
|
||||
"smsc": SMSC,
|
||||
"smsir": SMSIR,
|
||||
"DingDing": DingDing,
|
||||
"discord": Discord,
|
||||
"Elks": Elks,
|
||||
|
||||
@ -1209,5 +1209,18 @@
|
||||
"Send UP silently": "Безшумно известяване за Достъпен",
|
||||
"Send DOWN silently": "Безшумно известяване за Недостъпен",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Инсталирането на Nextcloud Talk бот изисква администраторски достъп до сървъра.",
|
||||
"auto-select": "Автоматичен избор"
|
||||
"auto-select": "Автоматичен избор",
|
||||
"supportBaleChatID": "Поддръжка на директен чат / група / чат ID на канала",
|
||||
"wayToGetBaleChatID": "Можете да получите вашия чат ID, като изпратите съобщение до бота и отидете на този URL адрес, за да видите chat_id:",
|
||||
"wayToGetBaleToken": "Можете да получите токен код от {0}.",
|
||||
"Mention Mobile List": "Списък със споменаващи мобилни устройства",
|
||||
"Mention User List": "Списък със споменаващи потребителски ID-та",
|
||||
"Dingtalk Mobile List": "Списък с мобилни устройства",
|
||||
"Dingtalk User List": "Списък с потребителски ID-та",
|
||||
"Enter a list of userId": "Въведете списък с потребителски ID-та",
|
||||
"Enter a list of mobile": "Въведете списък с мобилни устройства",
|
||||
"Invalid mobile": "Невалиден мобилен телефон [{mobile}]",
|
||||
"Invalid userId": "Невалидно потребителско ID [{userId}]",
|
||||
"Maximum Retries": "Максимален брой повторни опити",
|
||||
"Number of retry attempts if webhook fails": "Брой повторни опити (на всеки 60-180 секунди), ако уеб куката се првали."
|
||||
}
|
||||
|
||||
@ -225,5 +225,48 @@
|
||||
"ignoreTLSError": "HTTPS ওয়েবসাইটগুলির জন্য TLS/SSL ত্রুটিগুলি উপেক্ষা করুন",
|
||||
"pushViewCode": "পুশ মনিটর কীভাবে ব্যবহার করবেন? (কোড দেখুন)",
|
||||
"Appearance": "দেখানোর ধরন",
|
||||
"Quick Stats": "তাৎক্ষণিক পরিসংখ্যান"
|
||||
"Quick Stats": "তাৎক্ষণিক পরিসংখ্যান",
|
||||
"affectedMonitorsDescription": "বর্তমান রক্ষণাবেক্ষণে প্রভাবিত মনিটরগুলো নির্বাচন করুন",
|
||||
"atLeastOneMonitor": "অন্তত একটি প্রভাবিত মনিটর নির্বাচন করুন",
|
||||
"pushoversounds cashregister": "নগদ রেজিস্টার",
|
||||
"pushoversounds incoming": "আগত",
|
||||
"importHandleDescription": "আপনি যদি একই নামের প্রতিটি মনিটর অথবা নোটিফিকেশান এড়িয়ে যেতে চান তাহলে 'যেটা এখন আছে' সেটা এড়িয়ে যান । 'ওভাররাইট' প্রতিটি বিদ্যমান মনিটর এবং নোটিফিকেশান মুছে ফেলবে।",
|
||||
"confirmImportMsg": "তুমি কি নিশ্চিত যে তুমি ব্যাকআপটি ইমপোর্ট করতে চাও? অনুগ্রহ করে যাচাই করো তুমি সঠিক ইমপোর্ট অপশনটি নির্বাচন করেছ কিনা।",
|
||||
"twoFAVerifyLabel": "দয়া করে আপনার টোকেনটি প্রবেশ করুন ২-ধাপ যাচাইকরণের (2FA) জন্যঃ",
|
||||
"tokenValidSettingsMsg": "টোকেনটি বৈধ! এখন আপনি ২-ধাপ যাচাইকরণের (2FA) সেটিংস সংরক্ষণ করতে পারেন।",
|
||||
"confirmEnableTwoFAMsg": "তুমি কি নিশ্চিত যে তুমি ২-ধাপ যাচাইকরণ (2FA) চালু করতে চাও?",
|
||||
"confirmDisableTwoFAMsg": "তুমি কি নিশ্চিত যে তুমি ২-ধাপ যাচাইকরণ (2FA) বন্ধ করতে চাও?",
|
||||
"recurringIntervalMessage": "প্রতিদিন একবার চালান । প্রতি {0} দিনে একবার চালান",
|
||||
"affectedStatusPages": "নির্বাচিত স্ট্যাটাস পেজগুলোতে এই রক্ষণাবেক্ষণ বার্তাটি দেখান",
|
||||
"passwordNotMatchMsg": "পুনরায় দেওয়া পাসওয়ার্ডটি মিলছে না।",
|
||||
"invertKeywordDescription": "কীওয়ার্ডটি উপস্থিত আছে কি না নয়, বরং অনুপস্থিত আছে কি না দেখুন।",
|
||||
"jsonQueryDescription": "সার্ভারের JSON প্রতিক্রিয়া থেকে JSON কুয়েরি ব্যবহার করে নির্দিষ্ট ডেটা পার্স ও এক্সট্র্যাক্ট করুন; যদি JSON প্রত্যাশিত না হয়, তাহলে প্রতিক্রিয়ার জন্য “$” ব্যবহার করুন। প্রাপ্ত ফল এরপর প্রত্যাশিত মানের সাথে **স্ট্রিং** হিসেবে তুলনা করা হবে। ডকুমেন্টেশনের জন্য {0} দেখুন এবং কুয়েরি নিয়ে পরীক্ষা করতে {1} ব্যবহার করুন।",
|
||||
"backupDescription": "আপনি সব মনিটর ও নোটিফিকেশনকে একটি JSON ফাইলে ব্যাকআপ নিতে পারেন।",
|
||||
"backupDescription2": "নোট: ইতিহাস ও ইভেন্ট সম্পর্কিত তথ্য এতে অন্তর্ভুক্ত নয়।",
|
||||
"backupDescription3": "নোটিফিকেশন টোকেনের মতো সংবেদনশীল ডেটা এক্সপোর্ট ফাইলে অন্তর্ভুক্ত থাকে; অনুগ্রহ করে এক্সপোর্টটি নিরাপদভাবে সংরক্ষণ করুন।",
|
||||
"endpoint": "সংযোগ বিন্দু",
|
||||
"octopushAPIKey": "কন্ট্রোল প্যানেলে থাকা HTTP API ক্রেডেনশিয়াল থেকে “API key” সংগ্রহ করুন",
|
||||
"octopushLogin": "কন্ট্রোল প্যানেলে থাকা HTTP API ক্রেডেনশিয়াল থেকে “লগইন” তথ্য সংগ্রহ করুন",
|
||||
"promosmsLogin": "API লগইন নাম",
|
||||
"promosmsPassword": "API পাসওয়ার্ড",
|
||||
"pushoversounds pushover": "Pushover (ডিফল্ট)",
|
||||
"pushoversounds bike": "সাইকেল",
|
||||
"pushoversounds bugle": "বিউগল",
|
||||
"pushoversounds classical": "ক্লাসিক",
|
||||
"pushoversounds cosmic": "মহাজাগতিক",
|
||||
"pushoversounds falling": "পড়ে যাওয়া / পতনশীল",
|
||||
"pushoversounds gamelan": "গামেলান",
|
||||
"pushoversounds intermission": "বিরতি",
|
||||
"pushoversounds magic": "ম্যাজিক",
|
||||
"pushoversounds mechanical": "যান্ত্রিক",
|
||||
"pushoversounds pianobar": "পিয়ানো বার",
|
||||
"pushoversounds siren": "সাইরেন",
|
||||
"pushoversounds spacealarm": "স্পেস অ্যালার্ম",
|
||||
"pushoversounds tugboat": "টাগবোট",
|
||||
"pushoversounds alien": "এলিয়েন সতর্কতা (দীর্ঘ)",
|
||||
"pushoversounds climb": "আরোহণ (দীর্ঘ)",
|
||||
"pushoversounds persistent": "স্থায়ী (দীর্ঘ)",
|
||||
"pushoversounds echo": "Pushover ইকো (দীর্ঘ)",
|
||||
"notificationDescription": "নোটিফিকেশনগুলো কার্যকর হতে হলে সেগুলোকে কোনো মনিটরের সাথে যুক্ত করতে হবে।",
|
||||
"keywordDescription": "সাধারণ HTML বা JSON প্রতিক্রিয়ায় কীওয়ার্ড অনুসন্ধান করুন। এই অনুসন্ধানটি কেস-সেনসিটিভ।"
|
||||
}
|
||||
|
||||
@ -1201,5 +1201,19 @@
|
||||
"Bot secret": "Bot secret",
|
||||
"Send UP silently": "UP odeslat tiše",
|
||||
"Send DOWN silently": "DOWN odeslat tiše",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Instalace Nextcloud Talk bota vyžaduje administrátorský přístup k serveru."
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Instalace Nextcloud Talk bota vyžaduje administrátorský přístup k serveru.",
|
||||
"Maximum Retries": "Max. počet pokusů",
|
||||
"Number of retry attempts if webhook fails": "Počet pokusů o opakování (každých 60–180 sekund), pokud se webhook nepodaří odeslat.",
|
||||
"wayToGetBaleToken": "Token můžete získat na adrese {0}.",
|
||||
"wayToGetBaleChatID": "ID chatu získáte zasláním zprávy robotovi a přejdete na tuto URL adresu, na které se zobrazí chat_id:",
|
||||
"supportBaleChatID": "Podpora přímého chatu / skupiny / ID chatu kanálu",
|
||||
"Dingtalk Mobile List": "Seznam telefonních čísel",
|
||||
"Dingtalk User List": "Seznam ID uživatelů",
|
||||
"Mention Mobile List": "Seznam Mention telefonních čísel",
|
||||
"Mention User List": "Seznam ID uživatelů Mention",
|
||||
"Enter a list of userId": "Zadejte seznam userID",
|
||||
"Enter a list of mobile": "Zadejte seznam telefonních čísel",
|
||||
"Invalid mobile": "Neplatné telefonní číslo [{mobile}]",
|
||||
"Invalid userId": "Neplatné userID [{userId}]",
|
||||
"auto-select": "Automatický výběr"
|
||||
}
|
||||
|
||||
@ -1206,5 +1206,22 @@
|
||||
"Send UP silently": "UP still senden",
|
||||
"Send DOWN silently": "DOWN still senden",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Die Installation eines Nextcloud Talk-Bots erfordert Administratorrechte für den Server.",
|
||||
"auto-select": "Automatische Auswahl"
|
||||
"auto-select": "Automatische Auswahl",
|
||||
"Dingtalk User List": "Benutzer-ID-Liste",
|
||||
"Invalid userId": "Ungültige Benutzer-ID [{userId}]",
|
||||
"supportBaleChatID": "Support-Direkt-Chat / Gruppe / Chat-ID des Kanals",
|
||||
"wayToGetBaleChatID": "Du kannst deine Chat-ID erhalten, indem du dem Bot eine Nachricht sendest und dann diese URL aufrufst, um die chat_id anzusehen:",
|
||||
"wayToGetBaleToken": "Du kannst ein Token von {0} erhalten.",
|
||||
"Mention Mobile List": "Mobile Liste erwähnen",
|
||||
"Mention User List": "Benutzer-ID-Liste erwähnen",
|
||||
"Dingtalk Mobile List": "Liste der Mobilgeräte",
|
||||
"Enter a list of userId": "Gib eine Liste von Benutzer-IDs ein",
|
||||
"Enter a list of mobile": "Gib eine Liste von Mobilnummern ein",
|
||||
"Invalid mobile": "Ungültige Mobilnummer [{mobile}]",
|
||||
"Number of retry attempts if webhook fails": "Anzahl der Wiederholungsversuche (alle 60–180 Sekunden), wenn der Webhook fehlschlägt.",
|
||||
"Maximum Retries": "Maximale Wiederholungsversuche",
|
||||
"descriptionHelpText": "Wird auf dem internen Dashboard angezeigt. Markdown ist zulässig und wird vor der Anzeige bereinigt (Leerzeichen und Einrückungen bleiben erhalten).",
|
||||
"HTTP Method": "HTTP-Methode",
|
||||
"webhookPostMethodDesc": "POST eignet sich für die meisten modernen HTTP-Server.",
|
||||
"webhookGetMethodDesc": "GET sendet Daten als Abfrageparameter und erlaubt keine Konfiguration eines Bodys. Nützlich zum Auslösen von Uptime Kuma Push-Überwachungen."
|
||||
}
|
||||
|
||||
@ -1209,5 +1209,22 @@
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Die Installation eines Nextcloud Talk-Bots erfordert Administratorrechte für den Server.",
|
||||
"Nextcloud host": "Nextcloud Host",
|
||||
"Send UP silently": "UP still senden",
|
||||
"auto-select": "Automatische Auswahl"
|
||||
"auto-select": "Automatische Auswahl",
|
||||
"supportBaleChatID": "Support-Direkt-Chat / Gruppe / Chat-ID des Kanals",
|
||||
"wayToGetBaleChatID": "Du kannst deine Chat-ID erhalten, indem du dem Bot eine Nachricht sendest und dann diese URL aufrufst, um die chat_id anzusehen:",
|
||||
"wayToGetBaleToken": "Du kannst ein Token von {0} erhalten.",
|
||||
"Mention Mobile List": "Mobile Liste erwähnen",
|
||||
"Mention User List": "Benutzer-ID-Liste erwähnen",
|
||||
"Dingtalk Mobile List": "Liste der Mobilgeräte",
|
||||
"Dingtalk User List": "Benutzer-ID-Liste",
|
||||
"Enter a list of userId": "Gib eine Liste von Benutzer-IDs ein",
|
||||
"Enter a list of mobile": "Gib eine Liste von Mobilnummern ein",
|
||||
"Invalid mobile": "Ungültige Mobilnummer [{mobile}]",
|
||||
"Invalid userId": "Ungültige Benutzer-ID [{userId}]",
|
||||
"Number of retry attempts if webhook fails": "Anzahl der Wiederholungsversuche (alle 60–180 Sekunden), wenn der Webhook fehlschlägt.",
|
||||
"Maximum Retries": "Maximale Wiederholungsversuche",
|
||||
"webhookPostMethodDesc": "POST eignet sich für die meisten modernen HTTP-Server.",
|
||||
"descriptionHelpText": "Wird auf dem internen Dashboard angezeigt. Markdown ist zulässig und wird vor der Anzeige bereinigt (Leerzeichen und Einrückungen bleiben erhalten).",
|
||||
"HTTP Method": "HTTP-Methode",
|
||||
"webhookGetMethodDesc": "GET sendet Daten als Abfrageparameter und erlaubt keine Konfiguration eines Bodys. Nützlich zum Auslösen von Uptime Kuma Push-Überwachungen."
|
||||
}
|
||||
|
||||
@ -518,6 +518,12 @@
|
||||
"Effective Date Range": "Effective Date Range (Optional)",
|
||||
"Schedule Maintenance": "Schedule Maintenance",
|
||||
"Edit Maintenance": "Edit Maintenance",
|
||||
"Clone Maintenance": "Clone Maintenance",
|
||||
"ariaPauseMaintenance": "Pause this maintenance schedule",
|
||||
"ariaResumeMaintenance": "Resume this maintenance schedule",
|
||||
"ariaCloneMaintenance": "Create a copy of this maintenance schedule",
|
||||
"ariaEditMaintenance": "Edit this maintenance schedule",
|
||||
"ariaDeleteMaintenance": "Delete this maintenance schedule",
|
||||
"Date and Time": "Date and Time",
|
||||
"DateTime Range": "DateTime Range",
|
||||
"loadingError": "Cannot fetch the data, please try again later.",
|
||||
@ -590,6 +596,8 @@
|
||||
"grpcMethodDescription": "Method name is convert to camelCase format such as sayHello, check, etc.",
|
||||
"acceptedStatusCodesDescription": "Select status codes which are considered as a successful response.",
|
||||
"deleteMonitorMsg": "Are you sure want to delete this monitor?",
|
||||
"deleteGroupMsg": "Are you sure you want to delete this group?",
|
||||
"deleteChildrenMonitors": "Also delete the direct child monitors and its children if it has any | Also delete all {count} direct child monitors and their children if they have any",
|
||||
"deleteMaintenanceMsg": "Are you sure want to delete this maintenance?",
|
||||
"deleteNotificationMsg": "Are you sure want to delete this notification for all monitors?",
|
||||
"dnsPortDescription": "DNS server port. Defaults to 53. You can change the port at any time.",
|
||||
@ -1183,5 +1191,7 @@
|
||||
"Send DOWN silently": "Send DOWN silently",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Installing a Nextcloud Talk bot requires administrative access to the server.",
|
||||
"Number of retry attempts if webhook fails": "Number of retry attempts (every 60-180 seconds) if the webhook fails.",
|
||||
"Maximum Retries": "Maximum Retries"
|
||||
"Maximum Retries": "Maximum Retries",
|
||||
"Template ID": "Template ID",
|
||||
"wayToGetClickSMSIRTemplateID": "Your template must contain an {uptkumaalert} field. You can create a new template {here}."
|
||||
}
|
||||
|
||||
@ -1165,8 +1165,51 @@
|
||||
"No monitors found": "No se encontraron monitores.",
|
||||
"Could not clear events": "No se pudieron limpiar {failed}/{total} eventos",
|
||||
"smseagleGroupV2": "ID(s) de grupo(s) de Guía Telefónica",
|
||||
"mqttWebsocketPathExplanation": "Ruta del WebSocker para MQTT sobre conexion WebSocker (ejemplo, /mqtt)",
|
||||
"mqttWebsocketPathExplanation": "Ruta del WebSocker para MQTT sobre conexión WebSocker (ejemplo, /mqtt)",
|
||||
"OAuth Audience": "Audiencia OAuth",
|
||||
"Template plain text instead of using cards": "Plantilla de texto plano en vez de utilizar tarjetas",
|
||||
"issueWithGoogleChatOnAndroidHelptext": "Esto también permite evitar errores anteriores como {issuetackerURL}"
|
||||
"issueWithGoogleChatOnAndroidHelptext": "Esto también permite evitar errores anteriores como {issuetackerURL}",
|
||||
"wayToGetBaleChatID": "Puedes obtener tu ID de chat enviando un mensaje al bot y yendo a esta URL para ver el chat_id:",
|
||||
"smseagleContactV2": "ID(s) de contacto(s) de Guía Telefónica",
|
||||
"smseagleMsgTtsAdvanced": "Llamada avanzada de texto a voz",
|
||||
"wayToWriteEvolutionRecipient": "El número de teléfono con el prefijo internacional, pero sin el signo más al principio ({0}), el ID de contacto ({1}) o el ID de grupo ({2}).",
|
||||
"brevoApiHelp": "Crea una clave API aquí: {0}",
|
||||
"brevoLeaveBlankForDefaultName": "deja en blanco para el nombre por defecto",
|
||||
"brevoLeaveBlankForDefaultSubject": "Deja en blanco para sujeto por defecto",
|
||||
"Send DOWN silently": "Envía DOWN silenciosamente",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "La instalación de un bot de Nextcloud Talk requiere acceso administrativo al servidor.",
|
||||
"Font Twemoji by Twitter licensed under": "Fuente Twemoji de Twitter con licencia",
|
||||
"Optional: The audience to request the JWT for": "Opcional: La audiencia para la que se solicitará el JWT",
|
||||
"brevoApiKey": "Clave API de Brevo",
|
||||
"supportBaleChatID": "Soporte de chat directo/grupo/ID de chat del canal",
|
||||
"wayToGetBaleToken": "Puedes obtener un token de {0}.",
|
||||
"Mention Mobile List": "Mencionar lista de móviles",
|
||||
"Mention User List": "Mencionar la lista de id de usuario",
|
||||
"Dingtalk Mobile List": "Lista de móviles",
|
||||
"Dingtalk User List": "Lista de ID de usuario",
|
||||
"Enter a list of userId": "Ingresa una lista de userId",
|
||||
"Enter a list of mobile": "Ingresa una lista de móviles",
|
||||
"Invalid mobile": "Móvil inválido [{mobile}]",
|
||||
"Invalid userId": "UserId inválido [{userId}]",
|
||||
"smseagleTtsModel": "ID del modelo de texto a voz",
|
||||
"ntfyPriorityHelptextPriorityHigherThanDown": "La prioridad regular debe ser mayor que la prioridad {0}. La prioridad {1} es mayor que la prioridad {0} {2}",
|
||||
"FlashDuty Push URL": "URL push",
|
||||
"brevoFromEmail": "Desde el correo electrónico",
|
||||
"brevoFromName": "De Nombre",
|
||||
"brevoToEmail": "Para el correo electrónico",
|
||||
"brevoCcEmail": "Correo electrónico CC",
|
||||
"brevoBccEmail": "Correo electrónico BCC",
|
||||
"brevoSeparateMultipleEmails": "Separa múltiples direcciones de correo con comas",
|
||||
"brevoSubject": "Sujeto",
|
||||
"Staged Tags for Batch Add": "Etiquetas preparadas para agregar por lotes",
|
||||
"Nextcloud host": "Servidor Nextcloud",
|
||||
"Conversation token": "Token de conversación",
|
||||
"Bot secret": "Secreto del Bot",
|
||||
"Send UP silently": "Envía UP silenciosamente",
|
||||
"wayToGetEvolutionUrlAndToken": "Puede obtener la URL de la API y el token ingresando al canal deseado desde {0}",
|
||||
"evolutionRecipient": "Número de teléfono / ID de contacto / ID de grupo",
|
||||
"evolutionInstanceName": "Nombre de instancia",
|
||||
"auto-select": "Selección automática",
|
||||
"Number of retry attempts if webhook fails": "Número de intentos de reintento (cada 60–180 segundos) si el webhook falla.",
|
||||
"Maximum Retries": "Máximo de reintentos"
|
||||
}
|
||||
|
||||
@ -1209,5 +1209,22 @@
|
||||
"Conversation token": "Jeton de conversation",
|
||||
"Send UP silently": "Envoyer un UP silencieusement",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "L’installation d’un bot Nextcloud Talk nécessite un accès administratif au serveur.",
|
||||
"auto-select": "Sélection automatique"
|
||||
"auto-select": "Sélection automatique",
|
||||
"Enter a list of userId": "Entrez une liste d’IDs utilisateur",
|
||||
"supportBaleChatID": "Prend en charge l’ID de chat direct / de groupe / de canal",
|
||||
"wayToGetBaleChatID": "Vous pouvez obtenir votre ID de chat en envoyant un message au bot, puis en accédant à cette URL pour voir le chat_id :",
|
||||
"wayToGetBaleToken": "Vous pouvez obtenir un jeton depuis {0}.",
|
||||
"Mention Mobile List": "Liste des mentions mobiles",
|
||||
"Mention User List": "Liste des IDs des utilisateurs à mentionner",
|
||||
"Dingtalk Mobile List": "Liste des mobiles",
|
||||
"Dingtalk User List": "Liste des IDs utilisateurs",
|
||||
"Enter a list of mobile": "Entrez une liste de numéros de téléphone",
|
||||
"Invalid mobile": "Numéro de téléphone invalide [{mobile}]",
|
||||
"Invalid userId": "ID utilisateur invalide [{userId}]",
|
||||
"Maximum Retries": "Nombre maximal de tentatives",
|
||||
"Number of retry attempts if webhook fails": "Nombre de tentatives de réessai (toutes les 60 à 180 secondes) en cas d’échec du webhook.",
|
||||
"HTTP Method": "Méthode HTTP",
|
||||
"webhookPostMethodDesc": "POST convient à la plupart des serveurs HTTP modernes.",
|
||||
"webhookGetMethodDesc": "GET envoie les données sous forme de paramètres de requête et ne permet pas de configurer un corps. Utile pour déclencher les sondes Push d’Uptime Kuma.",
|
||||
"descriptionHelpText": "Affiché sur le tableau de bord interne. Le Markdown est autorisé et assaini (les espaces et l’indentation sont conservés) avant l’affichage."
|
||||
}
|
||||
|
||||
@ -1142,5 +1142,38 @@
|
||||
"Clear All Events": "Glan Gach Imeacht",
|
||||
"clearAllEventsMsg": "An bhfuil tú cinnte gur mian leat gach imeacht a scriosadh?",
|
||||
"Template plain text instead of using cards": "Téacs simplí teimpléid in ionad cártaí a úsáid",
|
||||
"issueWithGoogleChatOnAndroidHelptext": "Ligeann sé seo freisin dul timpeall ar fhabhtanna suas an sruth cosúil le {issuetackerURL}"
|
||||
"issueWithGoogleChatOnAndroidHelptext": "Ligeann sé seo freisin dul timpeall ar fhabhtanna suas an sruth cosúil le {issuetackerURL}",
|
||||
"supportBaleChatID": "Tacaíocht Comhrá Díreach / Grúpa / ID Comhrá an Chainéil",
|
||||
"wayToGetBaleChatID": "Is féidir leat d’ID comhrá a fháil trí theachtaireacht a sheoladh chuig an bot agus dul chuig an URL seo chun an chat_id a fheiceáil:",
|
||||
"Mention Mobile List": "Luaigh liosta soghluaiste",
|
||||
"Mention User List": "Luaigh liosta aitheantais úsáideora",
|
||||
"Invalid mobile": "Fón póca neamhbhailí [{mobile}]",
|
||||
"brevoApiKey": "Eochair API Brevo",
|
||||
"brevoLeaveBlankForDefaultName": "fág bán don ainm réamhshocraithe",
|
||||
"brevoToEmail": "Chuig Ríomhphost",
|
||||
"brevoSeparateMultipleEmails": "Deighil seoltaí ríomhphoist iolracha le camóga",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Éilíonn suiteáil bot Nextcloud Talk rochtain riaracháin ar an bhfreastalaí.",
|
||||
"brevoApiHelp": "Cruthaigh eochair API anseo: {0}",
|
||||
"brevoFromEmail": "Ó Ríomhphost",
|
||||
"brevoFromName": "Ó Ainm",
|
||||
"Nextcloud host": "Óstach Nextcloud",
|
||||
"Conversation token": "Comhartha comhrá",
|
||||
"Bot secret": "Rún an bhota",
|
||||
"wayToGetBaleToken": "Is féidir leat comhartha a fháil ó {0}.",
|
||||
"Dingtalk Mobile List": "Liosta soghluaiste",
|
||||
"Dingtalk User List": "Liosta aitheantais úsáideora",
|
||||
"Enter a list of userId": "Cuir isteach liosta d'AitheantasÚsáideora",
|
||||
"Enter a list of mobile": "Cuir isteach liosta de shoghluaisteáin",
|
||||
"Invalid userId": "Aitheantas úsáideora neamhbhailí [{userId}]",
|
||||
"wayToWriteEvolutionRecipient": "An uimhir theileafóin leis an réimír idirnáisiúnta, ach gan an comhartha móide ag an tús ({0}), an ID Teagmhála ({1}) ná an ID Grúpa ({2}).",
|
||||
"wayToGetEvolutionUrlAndToken": "Is féidir leat URL an API agus an comhartha a fháil trí dhul isteach sa chainéal atá uait ó {0}",
|
||||
"evolutionRecipient": "Uimhir Theileafóin / Aitheantas Teagmhála / Aitheantas Grúpa",
|
||||
"evolutionInstanceName": "Ainm an Cháis",
|
||||
"brevoCcEmail": "Ríomhphost CC",
|
||||
"brevoBccEmail": "Ríomhphost BCC",
|
||||
"brevoSubject": "Ábhar",
|
||||
"brevoLeaveBlankForDefaultSubject": "fág bán don ábhar réamhshocraithe",
|
||||
"Send UP silently": "Seol SUAS go ciúin",
|
||||
"Send DOWN silently": "Seol SÍOS go ciúin",
|
||||
"auto-select": "Roghnaigh Uathoibríoch"
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@
|
||||
"Keyword": "Ključna riječ",
|
||||
"Friendly Name": "Prilagođen naziv",
|
||||
"URL": "URL",
|
||||
"Hostname": "Domaćin",
|
||||
"Hostname": "Naziv hosta",
|
||||
"Port": "Port",
|
||||
"Heartbeat Interval": "Interval provjere",
|
||||
"Retries": "Broj ponovnih pokušaja",
|
||||
@ -547,16 +547,16 @@
|
||||
"Query": "Upit",
|
||||
"settingsCertificateExpiry": "TLS istek certifikata",
|
||||
"certificationExpiryDescription": "HTTPS monitori će obavijesiti kada je istek TLS certifikata za:",
|
||||
"Setup Docker Host": "Dodaj Docker domaćina",
|
||||
"Setup Docker Host": "Dodaj Docker hosta",
|
||||
"Connection Type": "Tip veze",
|
||||
"Docker Daemon": "Docker daemon",
|
||||
"deleteDockerHostMsg": "Sigurno želite izbrisati ovog Docker domaćina za sve monitore?",
|
||||
"deleteDockerHostMsg": "Sigurno želite izbrisati ovog Docker hosta za sve monitore?",
|
||||
"socket": "Docker socket",
|
||||
"tcp": "TCP / HTTP",
|
||||
"Docker Container": "Docker kontejner",
|
||||
"Container Name / ID": "Naziv / identifikator kontejnera",
|
||||
"Docker Host": "Docker domaćin",
|
||||
"Docker Hosts": "Docker domaćini",
|
||||
"Docker Host": "Docker host",
|
||||
"Docker Hosts": "Docker hostovi",
|
||||
"ntfy Topic": "ntfy tema",
|
||||
"Domain": "Domena",
|
||||
"Workstation": "Radna stanica",
|
||||
@ -885,15 +885,15 @@
|
||||
"templateHeartbeatJSON": "predmet koji opisuje provjeru",
|
||||
"templateMonitorJSON": "objekt koji opisuje Monitor",
|
||||
"templateLimitedToUpDownNotifications": "dostupno samo za obavijesti dostupnosti",
|
||||
"noDockerHostMsg": "Nije dostupno. Morate postaviti Docker domaćina.",
|
||||
"DockerHostRequired": "Postavite Docker domaćina za ovaj Monitor.",
|
||||
"noDockerHostMsg": "Nije dostupno. Morate postaviti Docker hosta.",
|
||||
"DockerHostRequired": "Postavite Docker hosta za ovaj Monitor.",
|
||||
"Browser Screenshot": "Snimka zaslona preglednika",
|
||||
"successKeyword": "Ključna riječ za uspjeh",
|
||||
"successKeywordExplanation": "MQTT ključna riječ koja označava uspješan odgovor",
|
||||
"remoteBrowserToggle": "Chromium se pokreće unutar Uptime Kuma kontejnera. Možete koristiti udaljeni preglednik uključivanjem ove opcije.",
|
||||
"deleteRemoteBrowserMessage": "Jeste li sigurni da želite ukloniti ovaj udaljeni preglednik za sve Monitore?",
|
||||
"Remote Browsers": "Udaljeni preglednici",
|
||||
"settingUpDatabaseMSG": "Postavljanje baze podatak u tijeku. Ovaj postupak može potrajati, budite strpljivi.",
|
||||
"settingUpDatabaseMSG": "Postavljanje baze podataka u tijeku. Ovaj postupak može potrajati, hvala na strpljenju.",
|
||||
"ntfyPriorityHelptextAllEvents": "Svi događaji šalju se s maksimalnim prioritetom",
|
||||
"ntfyPriorityHelptextAllExceptDown": "Svi događaji šalju se ovim prioritetom, osim {0} događaja, koji imaju prioritet {1}",
|
||||
"Search monitored sites": "Pretraži monitorirane stranice",
|
||||
@ -947,7 +947,7 @@
|
||||
"wayToGetBitrix24Webhook": "Možete napraviti webhook prateći upute na {0}",
|
||||
"bitrix24SupportUserID": "Unesite svoj korisnički identifikator u Bitrix24. Možete ga dobiti iz URL-a odlaskom na vlastiti profil.",
|
||||
"apiKeySevenIO": "SevenIO API ključ",
|
||||
"Host URL": "URL domaćina",
|
||||
"Host URL": "URL hosta",
|
||||
"Either enter the hostname of the server you want to connect to or localhost if you intend to use a locally configured mail transfer agent": "Unesite adresu poslužitelja na koju se želite spojiti ili {localhost} ako planirate koristiti {local_mta}",
|
||||
"Select message type": "Odaberite tip poruke",
|
||||
"postToExistingThread": "Pošalji u postojeću temu / forumsku raspravu",
|
||||
@ -1026,7 +1026,7 @@
|
||||
"Private Number": "Privatni broj",
|
||||
"wayToGetOnesenderUrlandToken": "URL i token možete dobiti odlaskom na OneSender web stranicu. Više informacija na {0}",
|
||||
"Token Onesender": "OneSender Token",
|
||||
"Host Onesender": "Adresa OneSender domaćina",
|
||||
"Host Onesender": "Adresa OneSender hosta",
|
||||
"Group ID": "Identifikator Grupe",
|
||||
"groupOnesenderDesc": "Provjerite je li Identifikator Grupe valjan. Za slanje poruke na Grupu, npr. 628123456789-342345",
|
||||
"Add Remote Browser": "Dodaj udaljeni preglednik",
|
||||
@ -1098,7 +1098,7 @@
|
||||
"telegramTemplateFormatDescription": "Telegram dozvoljava korištenje različitih markup jezika za formatiranje poruka, pogledajte {0} za više detalja.",
|
||||
"YZJ Robot Token": "YZJ token robota",
|
||||
"YZJ Webhook URL": "YZJ URL webhooka",
|
||||
"templateHostnameOrURL": "domaćin ili URL",
|
||||
"templateHostnameOrURL": "naziv hosta ili URL",
|
||||
"templateStatus": "status",
|
||||
"telegramUseTemplateDescription": "Ako je omogućeno, poruka će biti poslana koristeći prilagođeni predložak.",
|
||||
"Plain Text": "Obični tekst",
|
||||
@ -1157,7 +1157,7 @@
|
||||
"pingCountLabel": "Maks. paketa",
|
||||
"pingCountDescription": "Ukupan broj paketa koji će se poslati",
|
||||
"pingNumericLabel": "Brojčani ispis",
|
||||
"pingNumericDescription": "Ako je odabrano, bit će ispisane IP adrese umjesto naziva domaćina",
|
||||
"pingNumericDescription": "Ako je odabrano, bit će ispisane IP adrese umjesto naziva hostova",
|
||||
"pingGlobalTimeoutLabel": "Globalno vrijeme čekanja",
|
||||
"pingPerRequestTimeoutLabel": "Vrijeme čekanja za jedan ping",
|
||||
"pingIntervalAdjustedInfo": "Interval koji se prilagođava broju paketa, globalnom vremenu čekanja i vremenu čekanja jednog pinga",
|
||||
@ -1196,5 +1196,29 @@
|
||||
"brevoSubject": "Predmet e-pošte",
|
||||
"brevoApiKey": "Brevo API ključ",
|
||||
"brevoLeaveBlankForDefaultName": "ostaviti prazno za zadani naziv",
|
||||
"brevoLeaveBlankForDefaultSubject": "ostaviti prazno za korištenje zadang teksta predmeta"
|
||||
"brevoLeaveBlankForDefaultSubject": "ostaviti prazno za korištenje zadang teksta predmeta",
|
||||
"Nextcloud host": "Nextcloud ime hosta",
|
||||
"Conversation token": "Token razgovora",
|
||||
"Bot secret": "Tajna bota",
|
||||
"Send UP silently": "Pošalji UP utišano",
|
||||
"auto-select": "Automatski odabir",
|
||||
"Send DOWN silently": "Pošalji DOWN utišano",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Instaliranje Nextcloud Talk bota zahtijeva administratorski pristup poslužitelju.",
|
||||
"Number of retry attempts if webhook fails": "Broj ponovnih pokušaja (svakih 60-180 sekundi) ako webhook ne uspije.",
|
||||
"Maximum Retries": "Maksimalan broj ponovnih pokušaja",
|
||||
"HTTP Method": "HTTP metoda",
|
||||
"webhookPostMethodDesc": "POST je dobar za većinu modernih HTTP poslužitelja.",
|
||||
"Invalid userId": "Nevažeći korisnički ID [{userId}]",
|
||||
"supportBaleChatID": "Podržan ID izravnoga razgovora / grupe / kanala",
|
||||
"wayToGetBaleChatID": "Svoj ID razgovora (chat_id) možete dobiti slanjem poruke botu i odlaskom na ovaj URL:",
|
||||
"webhookGetMethodDesc": "GET šalje podatke kao parametre upita i ne dopušta konfiguriranje tijela zahtjeva. Korisno za okidanje Uptime Kuma Push monitora.",
|
||||
"descriptionHelpText": "Prikazuje se na internoj nadzornoj ploči. Markdown je dopušten i sanitiziran (čuva razmake i uvlačenja) prije prikazivanja.",
|
||||
"wayToGetBaleToken": "Token možete dobiti na {0}.",
|
||||
"Mention Mobile List": "Popis mobilnih uređaja za Mention",
|
||||
"Mention User List": "Popis korisničkih ID-jeva za Mention",
|
||||
"Dingtalk Mobile List": "Popis mobilnih uređaja",
|
||||
"Dingtalk User List": "Popis korisničkih ID-jeva",
|
||||
"Enter a list of userId": "Unesite popis korisničkih ID-jeva",
|
||||
"Enter a list of mobile": "Unesite popis mobilnih uređaja",
|
||||
"Invalid mobile": "Nevažeći mobitel [{mobile}]"
|
||||
}
|
||||
|
||||
@ -1188,5 +1188,18 @@
|
||||
"Nextcloud host": "Sistema Nextcloud",
|
||||
"Conversation token": "Token di conversazione",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Per installare un bot Nextcloud Talk è necessario disporre dell'accesso amministrativo al server.",
|
||||
"auto-select": "Selezione automatica"
|
||||
"auto-select": "Selezione automatica",
|
||||
"supportBaleChatID": "Supporto Chat Diretta / Gruppo / ID Chat del Canale",
|
||||
"wayToGetBaleChatID": "Puoi ottenere il tuo ID chat inviando un messaggio al bot e andando a questo URL per visualizzare la chat_id:",
|
||||
"wayToGetBaleToken": "Puoi ottenere un token da {0}.",
|
||||
"Mention Mobile List": "Menziona l'elenco dei cellulari",
|
||||
"Mention User List": "Menziona l'elenco degli ID utente",
|
||||
"Dingtalk Mobile List": "Elenco dei cellulari",
|
||||
"Dingtalk User List": "Elenco ID utente",
|
||||
"Enter a list of userId": "Inserisci un elenco di userId",
|
||||
"Invalid mobile": "Cellulare non valido [{mobile}]",
|
||||
"Enter a list of mobile": "Inserisci un elenco di cellulari",
|
||||
"Invalid userId": "ID utente non valido [{userId}]",
|
||||
"Maximum Retries": "Tentativi massimi",
|
||||
"Number of retry attempts if webhook fails": "Numero di tentativi di ripetizione (ogni 60-180 secondi) se il webhook fallisce."
|
||||
}
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
{
|
||||
"Dashboard": "დაფა",
|
||||
"Dashboard": "საინფორმაციო დაფა",
|
||||
"Help": "დახმარება",
|
||||
"New Update": "განახლება",
|
||||
"New Update": "ახალი განახლება",
|
||||
"Language": "ენა",
|
||||
"Appearance": "ვიზუალი",
|
||||
"Theme": "სტილი",
|
||||
"Game": "თამაში",
|
||||
"Version": "ვერსია",
|
||||
"Quick Stats": "თვალის გადავლება",
|
||||
"Quick Stats": "მოკლე სტატისტიკა",
|
||||
"Up": "მაღლა",
|
||||
"Pending": "მოლოდინი",
|
||||
"languageName": "Georgian",
|
||||
"Settings": "კონფიგურაცია",
|
||||
"languageName": "ქართული",
|
||||
"Settings": "პარამეტრები",
|
||||
"General": "ძირითადი",
|
||||
"Check Update On GitHub": "GitHub_ზე განახლების შემოწმება",
|
||||
"Check Update On GitHub": "GitHub ზე განახლების შემოწმება",
|
||||
"List": "სია",
|
||||
"Add": "დამატება",
|
||||
"Add New Monitor": "ახალი მონიტორის დამატება",
|
||||
@ -39,5 +39,41 @@
|
||||
"Keyword": "საკვანძო სიტყვა",
|
||||
"Unknown": "უცნობი",
|
||||
"dbName": "მონაცემთა ბაზის სახელი",
|
||||
"Home": "მთავარი"
|
||||
"Home": "მთავარი",
|
||||
"Setup Notification": "შეტყობინების გამართვა",
|
||||
"Notification Type": "შეტყობინების ტიპი",
|
||||
"Schedule maintenance": "ტექნიკური მომსახურების დაგეგმვა",
|
||||
"Notifications": "შეტყობინებები",
|
||||
"Search Engine Visibility": "საძიებო სისტემებში ხილვადობა",
|
||||
"Discourage search engines from indexing site": "საძიებო სისტემებისთვის საიტის ინდექსირების აკრძალვა",
|
||||
"Entry Page": "საწყისი გვერდი",
|
||||
"Monitor History": "მონიტორის ისტორია",
|
||||
"telegramSendSilentlyDescription": "შეტყობინებას ჩუმად აგზავნის. მომხმარებლი შეტყობინებას ხმის გარეშე მიიღებს.",
|
||||
"telegramProtectContentDescription": "ჩართვის შემთხვევაში, Telegram-ში ბოტის შეტყობინებები დაცული იქნება გადამისამართებისა და შენახვისგან.",
|
||||
"Body Encoding": "ტანის ენკოდირება",
|
||||
"Expires": "ვადა იწურება",
|
||||
"Auto Get": "ავტომატური შევსება",
|
||||
"Display Timezone": "საჩვენებელი დროის სარტყელი",
|
||||
"notificationRegional": "რეგიონალური",
|
||||
"Clone Monitor": "მონიტორის კლონირება",
|
||||
"Clone": "კლონირება",
|
||||
"cloneOf": "დაკლონე {0}",
|
||||
"API Keys": "API გასაღებები",
|
||||
"Add API Key": "API გასაღების დამატება",
|
||||
"supportTelegramChatID": "პირდაპირი ჩატის / ჯგუფის / არხის ჩატის ID-ის მხარდაჭერა",
|
||||
"Powered by": "მხარდაჭერილია",
|
||||
"Proxies": "პროქსიები",
|
||||
"Reverse Proxy": "საპირისპირო პროქსი",
|
||||
"Bot Token": "ბოტის ტოკენი",
|
||||
"Chat ID": "ჩათის ID",
|
||||
"telegramMessageThreadID": "(ნებაყოფლობითი) შეტყობინების ნაკადის ID",
|
||||
"telegramProtectContent": "გადამისამართებისგან/შენახვისგან დაცვა",
|
||||
"Save": "შენახვა",
|
||||
"setupDatabaseMariaDB": "გარე MariaDB მონაცემთა ბაზასთან დაკავშირება. საჭიროა შეავსო მონაცემთა ბაზასთან დასაკავშირებელი ინფორმაცია.",
|
||||
"settingUpDatabaseMSG": "მიმდინარეობს მონაცემთა ბაზის დაყენება. შესაძლოა გარკვეული დრო დასჭირდეს, გთხოვთ, მოთმინება გამოიჩინოთ.",
|
||||
"Cannot connect to the socket server": "socket სერვერთან დაკავშირება შეუძლებელია",
|
||||
"Reconnecting...": "მიმდინარეობს დაკავშირება...",
|
||||
"Primary Base URL": "ძირითადი ძირი URL",
|
||||
"Maintenance": "მოვლა",
|
||||
"statusMaintenance": "მუშავდება"
|
||||
}
|
||||
|
||||
@ -863,7 +863,7 @@
|
||||
"emailTemplateHeartbeatJSON": "하트 비트를 설명하는 객체",
|
||||
"pushoverMessageTtl": "메시지 TTL(초)",
|
||||
"Bark API Version": "Bark API 버전",
|
||||
"Mentioning": "멘토링",
|
||||
"Mentioning": "멘션하기",
|
||||
"Mention group": "{group}을(를) 멘션",
|
||||
"setup a new monitor group": "새 모니터 그룹 설정",
|
||||
"openModalTo": "{0}을(를) 위한 모달 열기",
|
||||
@ -924,5 +924,41 @@
|
||||
"Badge URL": "배지 URL",
|
||||
"Group": "그룹",
|
||||
"monitorToastMessagesLabel": "모니터 토스트 알림",
|
||||
"monitorToastMessagesDescription": "모니터용 토스트 알림은 지정된 초 단위 시간이 지나면 사라집니다. -1로 설정하면 시간 초과를 비활성화합니다. 0으로 설정하면 토스트 알림을 비활성화합니다."
|
||||
"monitorToastMessagesDescription": "모니터용 토스트 알림은 지정된 초 단위 시간이 지나면 사라집니다. -1로 설정하면 시간 초과를 비활성화합니다. 0으로 설정하면 토스트 알림을 비활성화합니다.",
|
||||
"supportBaleChatID": "개인 채팅 / 그룹 / 채널의 ID를 지원해요",
|
||||
"wayToGetBaleChatID": "봇에 메시지를 보내 채팅 ID를 얻고 밑에 URL로 이동해 chat_id를 볼 수 있어요:",
|
||||
"wayToGetBaleToken": "토큰은 여기서 얻을 수 있어요: {0}.",
|
||||
"auto-select": "자동 선택",
|
||||
"issueWithGoogleChatOnAndroidHelptext": "이를 통해 {issuetackerURL}과 같은 상류 버그를 우회할 수도 있습니다",
|
||||
"wayToGetHeiiOnCallDetails": "트리거 ID와 API 키를 얻는 방법은 {documentation}에 설명되어 있습니다",
|
||||
"authIncorrectCreds": "사용자명 혹은 비밀번호가 올바르지 않습니다.",
|
||||
"successDeleted": "삭제되었습니다.",
|
||||
"foundChromiumVersion": "Chromium/Chrome 확인됨. 버전 {0}",
|
||||
"2faAlreadyEnabled": "2FA가 이미 활성화되어 있습니다.",
|
||||
"authInvalidToken": "유효하지 않은 토큰입니다.",
|
||||
"Close": "닫기",
|
||||
"Dingtalk User List": "사용자 ID 목록",
|
||||
"Enter a list of userId": "userId 목록을 입력하세요",
|
||||
"Enter a list of mobile": "전화번호 목록을 입력하세요",
|
||||
"Invalid userId": "유효하지 않은 userId: [{userId}]",
|
||||
"Mention User List": "사용자 ID 목록을 멘션",
|
||||
"Invalid mobile": "유효하지 않은 전화번호: [{mobile}]",
|
||||
"Dingtalk Mobile List": "전화번호 목록",
|
||||
"Mention Mobile List": "전화번호 목록을 멘션",
|
||||
"FlashDuty Push URL": "푸시 URL",
|
||||
"Bitrix24 Webhook URL": "Bitrix24 Webhook URL",
|
||||
"wayToGetSevenIOApiKey": "app.seven.io > 개발자 > API 키 > 녹색 추가 버튼 아래 대시보드를 방문하세요",
|
||||
"2faEnabled": "2FA가 활성화되었습니다.",
|
||||
"2faDisabled": "2FA가 비활성화되었습니다.",
|
||||
"wayToGetBitrix24Webhook": "{0}의 단계를 따라 webhook을 생성할 수 있습니다",
|
||||
"successResumed": "성공적으로 재개되었습니다.",
|
||||
"successPaused": "성공적으로 일시 중지되었습니다.",
|
||||
"successEdited": "수정되었습니다.",
|
||||
"successAdded": "추가되었습니다.",
|
||||
"successAuthChangePassword": "비밀번호가 성공적으로 업데이트되었습니다.",
|
||||
"Telephone number": "전화번호",
|
||||
"SNMP Version": "SNMP 버전",
|
||||
"Originator": "발신자",
|
||||
"cellsyntOriginator": "수신자의 휴대폰에 메시지 발신자로 표시됩니다. 허용되는 값과 기능은 originatortype 매개변수에 따라 다릅니다.",
|
||||
"Message Template": "메세지 템플릿"
|
||||
}
|
||||
|
||||
106
src/lang/pl.json
106
src/lang/pl.json
@ -369,8 +369,8 @@
|
||||
"smseagleRecipient": "Odbiorca/y (wiele musi być oddzielone przecinkami)",
|
||||
"smseagleToken": "Klucz dostępu API",
|
||||
"smseagleUrl": "URL Twojego urządzenia SMSEagle",
|
||||
"smseagleEncoding": "Wyślij jako Unicode",
|
||||
"smseaglePriority": "Priorytet wiadomości (0-9, domyślnie = 0)",
|
||||
"smseagleEncoding": "Wyślij jako Unicode (domyślnie=GSM-7)",
|
||||
"smseaglePriority": "Priorytet wiadomości (0-9, najwyższy priorytet = 9)",
|
||||
"stackfield": "Stackfield",
|
||||
"Customize": "Dostosuj",
|
||||
"Custom Footer": "Niestandardowa stopka",
|
||||
@ -799,7 +799,7 @@
|
||||
"showCertificateExpiry": "Pokaż wygaśnięcie certyfikatu",
|
||||
"gamedigGuessPortDescription": "Port używany przez Valve Server Query Protocol może różnić się od portu klienta. Spróbuj tego, jeśli monitor nie może połączyć się z serwerem.",
|
||||
"Secret AccessKey": "Tajny klucz AccessKey",
|
||||
"wayToGetFlashDutyKey": "Możesz przejść do Channel -> (Select a Channel) -> Integrations -> Add a new integration' page, dodać \"Uptime Kuma\", aby uzyskać adres push, skopiować klucz integracji w adresie. Więcej informacji można znaleźć na stronie",
|
||||
"wayToGetFlashDutyKey": "Aby zintegrować Uptime Kuma z Flashduty: Przejdź do Kanały > Wybierz kanał > Integracje > Dodaj nową integrację, wybierz Uptime Kuma i skopiuj adres URL Push.",
|
||||
"Badge Down Color": "Kolor odznaki Offline",
|
||||
"Notify Channel": "Powiadom kanał",
|
||||
"Request Timeout": "Limit czasu żądania",
|
||||
@ -1087,7 +1087,7 @@
|
||||
"Scifi": "Scifi",
|
||||
"Clear": "Clear",
|
||||
"Elevator": "Elevator",
|
||||
"Guitar": "Guitar",
|
||||
"Guitar": "Gitara",
|
||||
"Pop": "Pop",
|
||||
"RabbitMQ Nodes": "Węzły zarządzania RabbitMQ",
|
||||
"rabbitmqNodesDescription": "Wprowadź adres URL węzłów zarządzania RabbitMQ, w tym protokół i port. Przykład: {0}",
|
||||
@ -1124,5 +1124,101 @@
|
||||
"the smsplanet documentation": "dokumentacja smsplanet",
|
||||
"Phone numbers": "Numery telefonów",
|
||||
"Sender name": "Nazwa nadawcy",
|
||||
"smsplanetNeedToApproveName": "Wymaga zatwierdzenia w panelu klienta"
|
||||
"smsplanetNeedToApproveName": "Wymaga zatwierdzenia w panelu klienta",
|
||||
"Staged Tags for Batch Add": "Tagi etapowe dla dodawania zbiorczego",
|
||||
"Happy Eyeballs algorithm": "Algorytm Happy Eyeballs",
|
||||
"smseagleApiv1": "APIv1 (dla istniejących projektów i kompatybilności wstecznej)",
|
||||
"ntfyPriorityDown": "Priorytet dla zdarzeń DOWN",
|
||||
"mqttWebsocketPathExplanation": "Ścieżka WebSocket dla połączeń MQTT przez WebSocket (np. /mqtt)",
|
||||
"supportBaleChatID": "Pomoc techniczna Czat bezpośredni / Grupa / Identyfikator czatu kanału",
|
||||
"wayToGetBaleChatID": "Możesz uzyskać swój identyfikator czatu, wysyłając wiadomość do bota i przechodząc do tego adresu URL, aby wyświetlić identyfikator czatu:",
|
||||
"OAuth Audience": "Odbiorcy OAuth",
|
||||
"Ip Family": "Rodzina IP",
|
||||
"Conversation token": "Token konwersacji",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Instalacja bota Nextcloud Talk wymaga uprawnień administratora serwera.",
|
||||
"Manual": "Instrukcja obsługi",
|
||||
"clearAllEventsMsg": "Czy na pewno chcesz usunąć wszystkie wydarzenia?",
|
||||
"Clear All Events": "Wyczyść wszystkie wydarzenia",
|
||||
"smseagleMsgType": "Typ wiadomości",
|
||||
"smseagleMsgSms": "Wiadomość SMS (domyślnie)",
|
||||
"smseagleMsgRing": "Dzwonek",
|
||||
"smseagleMsgTts": "Połączenie z funkcją zamiany tekstu na mowę",
|
||||
"smseagleMsgTtsAdvanced": "Zaawansowana funkcja zamiany tekstu na mowę",
|
||||
"smseagleTtsModel": "Identyfikator modelu zamiany tekstu na mowę",
|
||||
"smseagleApiType": "Wersja API",
|
||||
"smseagleApiv2": "APIv2 (zalecane dla nowych integracji)",
|
||||
"smseagleDocs": "Sprawdź dokumentację lub dostępność APIv2: {0}",
|
||||
"smseagleComma": "Wiele wartości należy oddzielić przecinkami",
|
||||
"pingCountLabel": "Maksymalna liczba pakietów",
|
||||
"pingGlobalTimeoutDescription": "Całkowity czas w sekundach przed zatrzymaniem pingowania, niezależnie od wysłanych pakietów",
|
||||
"pingPerRequestTimeoutLabel": "Limit czasu na ping",
|
||||
"pingPerRequestTimeoutDescription": "Jest to maksymalny czas oczekiwania (w sekundach) przed uznaniem pojedynczego pakietu ping za utracony",
|
||||
"Path": "Ścieżka",
|
||||
"mqttWebSocketPath": "Ścieżka MQTT WebSocket",
|
||||
"mqttWebsocketPathInvalid": "Użyj prawidłowego formatu ścieżki WebSocket",
|
||||
"mqttHostnameTip": "Użyj tego formatu {hostnameFormat}",
|
||||
"brevoApiKey": "Klucz API Brevo",
|
||||
"brevoApiHelp": "Utwórz klucz API tutaj: {0}",
|
||||
"brevoToEmail": "Na adres e-mail",
|
||||
"Clear Form": "Wyczyść formularz",
|
||||
"wayToGetBaleToken": "Możesz otrzymać token z {0}.",
|
||||
"Use HTML for custom E-mail body": "Użyj HTML do tworzenia niestandardowej treści wiadomości e-mail",
|
||||
"Events cleared successfully": "Wydarzenia zostały pomyślnie usunięte.",
|
||||
"No monitors found": "Nie znaleziono monitorów.",
|
||||
"Could not clear events": "Nie można usunąć {failed}/{total} zdarzeń",
|
||||
"Mention Mobile List": "Lista urządzeń mobilnych Mention",
|
||||
"Mention User List": "Lista identyfikatorów użytkowników Mention",
|
||||
"Dingtalk Mobile List": "Lista urządzeń mobilnych",
|
||||
"Dingtalk User List": "Lista identyfikatorów użytkowników",
|
||||
"Enter a list of userId": "Wprowadź listę identyfikatorów użytkowników",
|
||||
"Enter a list of mobile": "Wprowadź listę numerów telefonów komórkowych",
|
||||
"Invalid mobile": "Nieprawidłowy numer telefonu komórkowego [{mobile}]",
|
||||
"Invalid userId": "Nieprawidłowy identyfikator użytkownika [{userId}]",
|
||||
"smseagleContactV2": "Identyfikatory kontaktów w książce telefonicznej",
|
||||
"smseagleDuration": "Czas trwania (w sekundach)",
|
||||
"SpugPush Template Code": "Kod szablonu",
|
||||
"ntfyPriorityHelptextPriorityHigherThanDown": "Priorytet regularny powinien być wyższy niż priorytet {0}. Priorytet {1} jest wyższy niż priorytet {0} i priorytet {2}",
|
||||
"FlashDuty Push URL": "Adres URL Push",
|
||||
"FlashDuty Push URL Placeholder": "Kopiuj ze strony integracji alertów",
|
||||
"Optional: The audience to request the JWT for": "Opcjonalnie: odbiorca żądający JWT dla",
|
||||
"brevoFromEmail": "Z e-maila",
|
||||
"brevoFromName": "Od nazwy",
|
||||
"brevoLeaveBlankForDefaultName": "pozostaw puste pole, aby użyć nazwy domyślnej",
|
||||
"brevoCcEmail": "E-mail CC",
|
||||
"brevoBccEmail": "E-mail BCC",
|
||||
"brevoSeparateMultipleEmails": "Oddziel wiele adresów e-mail przecinkami",
|
||||
"brevoSubject": "Temat",
|
||||
"brevoLeaveBlankForDefaultSubject": "pozostaw puste pole dla domyślnego tematu",
|
||||
"pingCountDescription": "Liczba pakietów do wysłania przed zatrzymaniem",
|
||||
"pingNumericLabel": "Wyjście numeryczne",
|
||||
"pingNumericDescription": "Jeśli opcja jest zaznaczona, zamiast symbolicznych nazw hostów będą wyświetlane adresy IP",
|
||||
"pingGlobalTimeoutLabel": "Globalny limit czasu",
|
||||
"pingIntervalAdjustedInfo": "Interwał dostosowany na podstawie liczby pakietów, globalnego limitu czasu i limitu czasu na ping",
|
||||
"smtpHelpText": "„SMTPS” sprawdza, czy SMTP/TLS działa; „Ignore TLS” łączy się za pomocą zwykłego tekstu; „STARTTLS” łączy się, wysyła polecenie STARTTLS i weryfikuje certyfikat serwera. Żadna z tych opcji nie wysyła wiadomości e-mail.",
|
||||
"Custom URL": "Niestandardowy adres URL",
|
||||
"customUrlDescription": "Będzie używany jako klikalny adres URL zamiast adresu monitora.",
|
||||
"OneChatAccessToken": "Token dostępu OneChat",
|
||||
"OneChatUserIdOrGroupId": "Identyfikator użytkownika OneChat lub identyfikator grupy",
|
||||
"OneChatBotId": "Identyfikator bota OneChat",
|
||||
"Disable URL in Notification": "Wyłącz adres URL w powiadomieniu",
|
||||
"Add Another Tag": "Dodaj kolejny tag",
|
||||
"pause": "Pauza",
|
||||
"Nextcloud host": "Host Nextcloud",
|
||||
"Bot secret": "Sekret bota",
|
||||
"Send UP silently": "Wyślij UP po cichu",
|
||||
"Send DOWN silently": "Wyślij DOWN po cichu",
|
||||
"wayToWriteEvolutionRecipient": "Numer telefonu z prefiksem międzynarodowym, ale bez znaku plusa na początku ({0}), identyfikator kontaktu ({1}) lub identyfikator grupy ({2}).",
|
||||
"wayToGetEvolutionUrlAndToken": "Adres URL interfejsu API i token można uzyskać, przechodząc do wybranego kanału z {0}",
|
||||
"evolutionRecipient": "Numer telefonu / Identyfikator kontaktu / Identyfikator grupy",
|
||||
"evolutionInstanceName": "Nazwa instancji",
|
||||
"Template plain text instead of using cards": "Szablon zwykłego tekstu zamiast używania kart",
|
||||
"defaultFriendlyName": "Nowy monitor",
|
||||
"smseagleGroupV2": "Identyfikatory grup w książce telefonicznej",
|
||||
"Add Tags": "Dodaj tagi",
|
||||
"tagAlreadyOnMonitor": "Ten tag (nazwa i wartość) jest już na monitorze lub oczekuje na dodanie.",
|
||||
"tagAlreadyStaged": "Ten tag (nazwa i wartość) jest już przygotowany dla tej partii.",
|
||||
"tagNameExists": "Tag systemowy o tej nazwie już istnieje. Wybierz go z listy lub użyj innej nazwy.",
|
||||
"auto-select": "Wybór automatyczny",
|
||||
"issueWithGoogleChatOnAndroidHelptext": "Pozwala to również ominąć błędy upstream, takie jak {issuetackerURL}",
|
||||
"ipFamilyDescriptionAutoSelect": "Używa {happyEyeballs} do określania rodziny adresów IP."
|
||||
}
|
||||
|
||||
@ -1173,5 +1173,16 @@
|
||||
"Send UP silently": "Enviar UP silenciosamente",
|
||||
"Send DOWN silently": "Envie DOWN silenciosamente",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "A instalação de um bot Nextcloud Talk requer acesso administrativo ao servidor.",
|
||||
"auto-select": "Seleção automática"
|
||||
"auto-select": "Seleção automática",
|
||||
"Mention Mobile List": "Mencionar lista de celulares",
|
||||
"Enter a list of userId": "Insira uma lista de userId",
|
||||
"supportBaleChatID": "Suporte a ID de Chat Direto / Grupo / Canal",
|
||||
"wayToGetBaleChatID": "Você pode obter seu ID de bate-papo enviando uma mensagem ao bot e acessando esta URL para visualizar o chat_id:",
|
||||
"wayToGetBaleToken": "Você pode obter um token de {0}.",
|
||||
"Mention User List": "Mencionar lista de IDs de usuários",
|
||||
"Dingtalk Mobile List": "Lista de celulares",
|
||||
"Dingtalk User List": "Lista de IDs de usuário",
|
||||
"Enter a list of mobile": "Insira uma lista de dispositivos móveis",
|
||||
"Invalid mobile": "Celular inválido [{mobile}]",
|
||||
"Invalid userId": "ID de usuário inválido [{userId}]"
|
||||
}
|
||||
|
||||
@ -1216,5 +1216,6 @@
|
||||
"brevoLeaveBlankForDefaultSubject": "оставьте пустым для темы по умолчанию",
|
||||
"Nextcloud host": "Хост Nextcloud",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Для установки бота Nextcloud Talk требуется административный доступ к серверу.",
|
||||
"Conversation token": "Токен разговора"
|
||||
"Conversation token": "Токен разговора",
|
||||
"auto-select": "Автоматический выбор"
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"Settings": "Nastavenia",
|
||||
"Help": "Nápoveda",
|
||||
"Help": "Pomoc",
|
||||
"New Update": "Nová aktualizácia",
|
||||
"Language": "Jazyk",
|
||||
"Appearance": "Vzhľad",
|
||||
@ -18,8 +18,8 @@
|
||||
"General Monitor Type": "Všeobecný typ sledovania",
|
||||
"Passive Monitor Type": "Pasívny typ sledovania",
|
||||
"Specific Monitor Type": "Špecifický typ sledovania",
|
||||
"pauseDashboardHome": "Pauza",
|
||||
"Pause": "Pauza",
|
||||
"pauseDashboardHome": "Pozastavené",
|
||||
"Pause": "Pozastaviť",
|
||||
"Status": "Stav",
|
||||
"Message": "Správa",
|
||||
"No important events": "Žiadne dôležité udalosti",
|
||||
@ -27,7 +27,7 @@
|
||||
"Delete": "Odstrániť",
|
||||
"Current": "Aktuálne",
|
||||
"Cert Exp.": "Platnosť cert.",
|
||||
"day": "deň | dni",
|
||||
"day": "deň | dní",
|
||||
"hour": "hodina",
|
||||
"Response": "Odpoveď",
|
||||
"Ping": "Ping",
|
||||
@ -35,11 +35,11 @@
|
||||
"Friendly Name": "Názov",
|
||||
"Port": "Port",
|
||||
"Retries": "Opakovania",
|
||||
"Resend Notification if Down X times consecutively": "Poslať oznámenie znovu, ak je nedostupné X-krát za sebou",
|
||||
"Resend Notification if Down X times consecutively": "Znovu odoslať upozornenie, ak je X-krát po sebe nedostupné",
|
||||
"Advanced": "Pokročilé",
|
||||
"checkEverySecond": "Skontrolovať každých {0} sekúnd",
|
||||
"retryCheckEverySecond": "Zopakovať každých {0} sekúnd",
|
||||
"resendEveryXTimes": "Znovu poslať každých {0} krát",
|
||||
"resendEveryXTimes": "Odoslať znova po {0} pokusoch",
|
||||
"resendDisabled": "Opakované odoslanie vypnuté",
|
||||
"ignoreTLSError": "Ignorovať TLS/SSL chyby pre HTTPS stránky",
|
||||
"upsideDownModeDescription": "Obrátiť stav. Pokiaľ je služba dostupná, zobrazuje sa ako NEDOSTUPNÁ.",
|
||||
@ -51,8 +51,8 @@
|
||||
"Notifications": "Notifikácie",
|
||||
"Not available, please setup.": "Nedostupné, prosím nastavte.",
|
||||
"Setup Notification": "Nastavenie notifikácií",
|
||||
"Dark": "Tmavý",
|
||||
"Light": "Svetlý",
|
||||
"Dark": "Tmavá",
|
||||
"Light": "Svetlá",
|
||||
"Auto": "Automaticky",
|
||||
"Normal": "Normálna",
|
||||
"Bottom": "Dole",
|
||||
@ -81,7 +81,7 @@
|
||||
"maxRedirectDescription": "Maximálny počet presmerovaní, ktoré sa majú sledovať. Nastavte na 0, aby ste presmerovania deaktivovali.",
|
||||
"needPushEvery": "Tuto adresu by ste mali volať každých {0} sekúnd.",
|
||||
"pushOptionalParams": "Voliteľné parametre: {0}",
|
||||
"Theme - Heartbeat Bar": "Téma - Heartbeat Bar",
|
||||
"Theme - Heartbeat Bar": "Téma - lišta pulzu",
|
||||
"Game": "Hra",
|
||||
"Search Engine Visibility": "Viditeľnosť vyhľadávačmi",
|
||||
"Allow indexing": "Povoliť indexovanie",
|
||||
@ -118,7 +118,7 @@
|
||||
"notAvailableShort": "N/A",
|
||||
"Default enabled": "Predvolene povolené",
|
||||
"Create": "Vytvoriť",
|
||||
"Clear Data": "Vyčistiť dáta",
|
||||
"Clear Data": "Vyčistiť údaje",
|
||||
"Events": "Udalosti",
|
||||
"Heartbeats": "Pulzy",
|
||||
"Auto Get": "Získať automaticky",
|
||||
@ -142,12 +142,12 @@
|
||||
"Inactive": "Neaktívne",
|
||||
"Token": "Token",
|
||||
"Show URI": "Zobraziť URI",
|
||||
"Tags": "Značky",
|
||||
"Tags": "Štítky",
|
||||
"Add New below or Select...": "Pridať novú nižšie alebo vybrať…",
|
||||
"Tag with this value already exist.": "Značka s touto hodnotou už existuje.",
|
||||
"Tag with this value already exist.": "Štítok s touto hodnotou už existuje.",
|
||||
"color": "Farba",
|
||||
"value (optional)": "hodnota (voliteľné)",
|
||||
"Gray": "Šedá",
|
||||
"Gray": "Sivá",
|
||||
"Red": "Červená",
|
||||
"Orange": "Oranžová",
|
||||
"Green": "Zelená",
|
||||
@ -176,7 +176,7 @@
|
||||
"webhookJsonDesc": "{0} je vhodný pre všetky moderné servery HTTP, ako napríklad Express.js",
|
||||
"webhookFormDataDesc": "{multipart} je dobré pre PHP. JSON bude potrebné analyzovať pomocou {decodeFunction}",
|
||||
"Generate": "Generovať",
|
||||
"Discourage search engines from indexing site": "Odradiť vyhľadávacie nástroje od indexovania stránky",
|
||||
"Discourage search engines from indexing site": "Zabrániť vyhľadávačom v indexovaní stránky",
|
||||
"disableauth.message1": "Ste si istý, že chcete {disableAuth}?",
|
||||
"disable authentication": "vypnúť autentifikáciu",
|
||||
"disableauth.message2": "Je navrhnutý pre scenáre, {intendThirdPartyAuth} pred Uptime Kuma, ako je Cloudflare Access, Authelia alebo iné autentifikačné mechanizmy.",
|
||||
@ -189,8 +189,8 @@
|
||||
"Verify Token": "Overiť token",
|
||||
"Enable 2FA": "Povoliť 2FA",
|
||||
"Active": "Aktívne",
|
||||
"Add New Tag": "Pridať novú značku",
|
||||
"Tag with this name already exist.": "Značka s týmto názvom už existuje.",
|
||||
"Add New Tag": "Pridať nový štítok",
|
||||
"Tag with this name already exist.": "Štítok s týmto názvom už existuje.",
|
||||
"Blue": "Modrá",
|
||||
"Search...": "Hľadať…",
|
||||
"statusPageNothing": "Nič tu nie je, pridajte skupinu alebo sledovanie.",
|
||||
@ -205,10 +205,10 @@
|
||||
"Read more": "Prečítajte si viac",
|
||||
"appriseInstalled": "Apprise je nainštalovaný.",
|
||||
"Reconnecting...": "Prepájanie...",
|
||||
"Request Timeout": "Platnosť požiadavky vypršala",
|
||||
"styleElapsedTimeShowWithLine": "Zobraziť (S Riadkom)",
|
||||
"Request Timeout": "Časový limit požiadavky",
|
||||
"styleElapsedTimeShowWithLine": "Zobraziť (s riadkom)",
|
||||
"webhookCustomBodyDesc": "Zadajte vlastné HTTP Body pre request. Šablónové premenné {msg}, {heartbeat}, {monitor} sú akceptované.",
|
||||
"timeoutAfter": "Platnosť požiadavky vypršala po {0} sekundách",
|
||||
"timeoutAfter": "Časový limit vyprší po {0} sekundách",
|
||||
"styleElapsedTime": "Uplynutý čas pod lištou pulzu",
|
||||
"styleElapsedTimeShowNoLine": "Zobraziť (Žiadny riadok)",
|
||||
"filterActive": "Aktívne",
|
||||
@ -252,7 +252,7 @@
|
||||
"HTTP Headers": "HTTP hlavičky",
|
||||
"Other Software": "Iný softvér",
|
||||
"For example: nginx, Apache and Traefik.": "Napríklad: nginx, Apache a Traefik.",
|
||||
"Please read": "Prečítajte si, prosím",
|
||||
"Please read": "Prečítajte si prosím",
|
||||
"pushOthers": "Ostatné",
|
||||
"Created": "Vytvorené",
|
||||
"ignoreTLSErrorGeneral": "Ignorovať chybu TLS/SSL pre pripojenie",
|
||||
@ -289,7 +289,7 @@
|
||||
"Security": "Zabezpečenie",
|
||||
"Steam API Key": "Kľúč API služby Steam",
|
||||
"Pick a RR-Type...": "Vyberte typ RR…",
|
||||
"Discard": "Vyhodiť",
|
||||
"Discard": "Zrušiť zmeny",
|
||||
"Select": "Vybrať",
|
||||
"selectedMonitorCount": "Vybrané: {0}",
|
||||
"Check/Uncheck": "Označiť/Odznačiť",
|
||||
@ -352,14 +352,14 @@
|
||||
"deleteDockerHostMsg": "Ste si istí, že chcete odstrániť tohto docker hostiteľa pre všetky sledovania?",
|
||||
"Container Name / ID": "Názov kontajnera / ID",
|
||||
"telegramSendSilentlyDescription": "Odošle správu v tichosti. Používatelia dostanú oznámenie bez zvuku.",
|
||||
"trustProxyDescription": "Dôverujte hlavičkám 'X-Forwarded-*'. Ak chcete získať správnu IP adresu klienta a vaša služba Uptime Kuma sa nachádza za proxy serverom, napríklad Nginx alebo Apache, mali by ste túto funkciu povoliť.",
|
||||
"trustProxyDescription": "Dôverovať hlavičkám 'X-Forwarded-*'. Ak chcete získať správnu IP adresu klienta a vaša služba Uptime Kuma sa nachádza za proxy serverom, napríklad Nginx alebo Apache, mali by ste túto funkciu povoliť.",
|
||||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Dlhodobý prístupový token môžete vytvoriť kliknutím na názov svojho profilu (vľavo dole) a rolovaním na spodok, potom kliknite na Vytvoriť token. ",
|
||||
"Event data:": "Dáta udalosti:",
|
||||
"Event data:": "Údaje udalosti:",
|
||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "Potom vyberte akciu, napríklad prepnite scénu na miesto, kde je svetlo RGB červené.",
|
||||
"warningTimezone": "Používa časové pásmo servera",
|
||||
"lastDay1": "Posledný deň mesiaca",
|
||||
"smtpLiquidIntroduction": "Nasledujúce dve polia je možné šablónovať pomocou šablónovacieho jazyka Liquid. Pokyny na použitie nájdete v časti {0}. Toto sú dostupné premenné:",
|
||||
"wayToGetDiscordURL": "Získate to, ak prejdete do Nastavenia servera -> Integrácie -> Zobraziť webhooky -> Nový webhook",
|
||||
"wayToGetDiscordURL": "Toto nastavenie nájdete v časti Nastavenia servera -> Integrácie -> Zobraziť webhooky -> Nový webhook",
|
||||
"wayToGetLineChannelToken": "Najprv pristupte k {0}, vytvorte poskytovateľa a kanál ( Rozhranie API správ), potom môžete získať prístupový token kanála a ID používateľa z vyššie uvedených položiek ponuky.",
|
||||
"enableDefaultNotificationDescription": "Toto upozornenie bude predvolene povolené pre nové sledovania. Toto oznámenie môžete stále vypnúť pre každé sledovanie samostatne.",
|
||||
"or": "alebo",
|
||||
@ -378,13 +378,13 @@
|
||||
"Issuer:": "Vydavateľ:",
|
||||
"Fingerprint:": "Odtlačok:",
|
||||
"No status pages": "Žiadne stavové stránky",
|
||||
"Domain Name Expiry Notification": "Oznámenie o vypršaní platnosti domény",
|
||||
"Domain Name Expiry Notification": "Oznámiť o vypršaní platnosti domény",
|
||||
"Remove the expiry notification": "Odstrániť deň oznámenia o vypršaní platnosti",
|
||||
"Proxy": "Proxy",
|
||||
"Date Created": "Dátum vytvorenia",
|
||||
"Footer Text": "Text päty",
|
||||
"Footer Text": "Text v pätičke",
|
||||
"RadiusCallingStationIdDescription": "Identifikátor volajúceho zariadenia",
|
||||
"Certificate Expiry Notification": "Oznámenie o skončení platnosti certifikátu",
|
||||
"Certificate Expiry Notification": "Oznámiť o skončení platnosti certifikátu",
|
||||
"API Username": "Používateľské meno API",
|
||||
"API Key": "Kľúč API",
|
||||
"Show update if available": "Zobraziť aktualizáciu, ak je k dispozícii",
|
||||
@ -444,9 +444,9 @@
|
||||
"maintenanceStatus-unknown": "Neznáme",
|
||||
"IconUrl": "URL adresa ikony",
|
||||
"chromeExecutableAutoDetect": "Automatická detekcia",
|
||||
"chromeExecutableDescription": "Ak používatelia nástroja Docker ešte nemajú nainštalovanú aplikáciu Chromium, inštalácia a zobrazenie výsledkov testu môže trvať niekoľko minút. Zaberie 1 GB miesta na disku.",
|
||||
"chromeExecutableDescription": "Pre používateľov nástroja Docker, ak Chromium ešte nie je nainštalované, môže inštalácia a zobrazenie výsledku testu trvať niekoľko minút. Vyžaduje 1 GB miesta na disku.",
|
||||
"dnsCacheDescription": "V niektorých prostrediach IPv6 nemusí fungovať, ak narazíte na problémy, vypnite to.",
|
||||
"Single Maintenance Window": "Jediné okno údržby",
|
||||
"Single Maintenance Window": "Jedno okno údržby",
|
||||
"install": "Nainštalovať",
|
||||
"installing": "Inštaluje sa",
|
||||
"uninstall": "Odinštalovať",
|
||||
@ -566,7 +566,7 @@
|
||||
"Maintenance Time Window of a Day": "Časový interval údržby cez deň",
|
||||
"Hello @everyone is...": "Dobrý deň, {'@'}všetci sú…",
|
||||
"clearHeartbeatsMsg": "Naozaj chcete odstrániť všetky pulzy pre toto sledovanie?",
|
||||
"Trust Proxy": "Dôveryhodná proxy",
|
||||
"Trust Proxy": "Dôverovať proxy",
|
||||
"RadiusCalledStationId": "ID volaného zariadenia",
|
||||
"Connection String": "Reťazec pripojenia",
|
||||
"socket": "Socket",
|
||||
@ -574,7 +574,7 @@
|
||||
"confirmClearStatisticsMsg": "Naozaj chcete odstrániť VŠETKY štatistiky?",
|
||||
"-year": "-rok",
|
||||
"and": "a",
|
||||
"shrinkDatabaseDescriptionSqlite": "Podmienka spustenia príkazu pre SQLite databázu. Príkaz {auto_vacuum} je už zapnutý, ale nedochádza k defragmentácii databázy ani k prebaleniu jednotlivých stránok databázy ako to robí príkaz {vacuum}.",
|
||||
"shrinkDatabaseDescriptionSqlite": "Spusti prečistenie databázy {vacuum} pre SQLite. {auto_vacuum} je už povolené, ale to nedefragmentuje databázu ani neprebalí jednotlivé stránky databázy tak, ako to robí príkaz {vacuum}.",
|
||||
"lineDevConsoleTo": "Konzola Line Developers - {0}",
|
||||
"clearEventsMsg": "Naozaj chcete odstrániť všetky udalosti pre toto sledovanie?",
|
||||
"now": "teraz",
|
||||
@ -638,10 +638,10 @@
|
||||
"defaultFriendlyName": "Nové sledovanie",
|
||||
"promosmsPassword": "Heslo API",
|
||||
"WebHookUrl": "URL webhooku",
|
||||
"Add Tags": "Pridať značky",
|
||||
"tagAlreadyStaged": "Táto značka (názov a hodnota) je už pripravená pre tento batch.",
|
||||
"Add Tags": "Pridať štítky",
|
||||
"tagAlreadyStaged": "Tento štítok (názov a hodnota) je už pripravený pre túto dávku.",
|
||||
"tagAlreadyOnMonitor": "Tento štítok (názov a hodnota) je už sledovaný alebo čaká na pridanie.",
|
||||
"tagNameExists": "Systémová značka s týmto názvom už existuje. Vyberte ju zo zoznamu alebo použite iný názov.",
|
||||
"tagNameExists": "Systémový štítok s týmto názvom už existuje. Vyberte ho zo zoznamu alebo použite iný názov.",
|
||||
"octopushAPIKey": "„Kľúč API“ z prihlasovacích údajov HTTP API v ovládacom paneli",
|
||||
"octopushLogin": "„Prihlásenie“ z prihlasovacích údajov HTTP API v ovládacom paneli",
|
||||
"pushoversounds pushover": "Pushover (predvolené)",
|
||||
@ -1105,8 +1105,8 @@
|
||||
"pingNumericDescription": "Ak je táto možnosť označená, namiesto symbolických názvov hostiteľov sa budú zobrazovať IP adresy",
|
||||
"smtpHelpText": "„SMTPS“ testuje, či SMTP/TLS funguje; „“Ignorovať TLS“ sa pripája cez nezabezpečený text; „STARTTLS“ sa prippojí, vydá príkaz STARTTLS a overí certifikát servera. Žiadna z týchto možností neodosiela e-mail.",
|
||||
"rabbitmqNodesDescription": "Zadajte URL adresu pre uzly na správu RabbitMQ vrátane protokolu a portu. Príklad: {0}",
|
||||
"ipFamilyDescriptionAutoSelect": "Používa {happyEyeballs} na určenie IP rodiny.",
|
||||
"Ip Family": "IP rodina",
|
||||
"ipFamilyDescriptionAutoSelect": "Používa {happyEyeballs} na určenie IP verzie.",
|
||||
"Ip Family": "Verzia IP",
|
||||
"Manual": "Manuálne",
|
||||
"OAuth Audience": "OAuth publikum",
|
||||
"alertaRecoverState": "Obnoviť stav",
|
||||
@ -1127,7 +1127,7 @@
|
||||
"pingGlobalTimeoutLabel": "Globálny časový limit",
|
||||
"pingGlobalTimeoutDescription": "Celkový čas v sekundách, po ktorom ping prestane bez ohľadu na odoslané pakety",
|
||||
"pingPerRequestTimeoutLabel": "Časový limit pre jednotlivý ping",
|
||||
"Staged Tags for Batch Add": "Fázované značky pre hromadné pridávanie",
|
||||
"Staged Tags for Batch Add": "Fázované štítky pre hromadné pridávanie",
|
||||
"senderSevenIO": "Odosielanie čísla alebo mena",
|
||||
"pingIntervalAdjustedInfo": "Interval upravený na základe počtu paketov, globálneho časového limitu a časového limitu pre jednotlivý ping",
|
||||
"FlashDuty Severity": "Závažnosť",
|
||||
@ -1165,5 +1165,22 @@
|
||||
"Conversation token": "Token konverzácie",
|
||||
"Installing a Nextcloud Talk bot requires administrative access to the server.": "Inštalácia bota Nextcloud Talk vyžaduje prístup správcu k serveru.",
|
||||
"Send UP silently": "Odoslať DOSTUPNÉ potichu",
|
||||
"auto-select": "Automaticky vybrať"
|
||||
"auto-select": "Automaticky vybrať",
|
||||
"Enter a list of userId": "Zadajte zoznam používateľských identifikátorov",
|
||||
"wayToGetBaleChatID": "Svoje chat ID získate tak, že pošlete správu botovi a prejdete na túto URL adresu, kde sa zobrazí chat_id:",
|
||||
"wayToGetBaleToken": "Token môžete získať z {0}.",
|
||||
"supportBaleChatID": "Podpora pre Priamy chat / Skupinu / ID chatu kanála",
|
||||
"Invalid userId": "Neplatné userId [{userId}]",
|
||||
"Mention User List": "Zoznam používateľských ID Mention",
|
||||
"Dingtalk Mobile List": "Zoznam mobilov",
|
||||
"Dingtalk User List": "Zoznam používateľských ID",
|
||||
"Enter a list of mobile": "Zadajte zoznam mobilov",
|
||||
"Invalid mobile": "Neplatný mobil [{mobile}]",
|
||||
"Mention Mobile List": "Zoznam mobilov Mention",
|
||||
"Maximum Retries": "Maximálny počet opakovaní",
|
||||
"Number of retry attempts if webhook fails": "Počet pokusov o opakovanie (každých 60–180 sekúnd), ak webhook zlyhá.",
|
||||
"webhookGetMethodDesc": "GET odosiela údaje ako parametre dopytu a neumožňuje konfiguráciu tela. Je užitočné na spúšťanie Push monitorov Uptime Kuma.",
|
||||
"descriptionHelpText": "Zobrazené na internom paneli. Markdown je povolený a pred zobrazením je očistený (zachováva medzery a odsadenie).",
|
||||
"HTTP Method": "Metóda HTTP",
|
||||
"webhookPostMethodDesc": "POST je vhodný pre väčšinu moderných HTTP serverov."
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"languageName": "İngilizce",
|
||||
"languageName": "Türkçe",
|
||||
"checkEverySecond": "{0} saniyede bir kontrol et",
|
||||
"retryCheckEverySecond": "{0} saniyede bir dene",
|
||||
"resendEveryXTimes": "Her {0} bir yeniden gönder",
|
||||
@ -526,18 +526,18 @@
|
||||
"Most likely causes:": "En olası nedenler:",
|
||||
"The resource is no longer available.": "Kaynak artık mevcut değil.",
|
||||
"There might be a typing error in the address.": "Adreste bir yazım hatası olabilir.",
|
||||
"What you can try:": "Ne deneyebilirsin:",
|
||||
"What you can try:": "Deneyebileceğin şeyler:",
|
||||
"Retype the address.": "Adresi tekrar yazın.",
|
||||
"Go back to the previous page.": "Bir önceki sayfaya geri git.",
|
||||
"Coming Soon": "Yakında gelecek",
|
||||
"Coming Soon": "Yakında Gelecek",
|
||||
"wayToGetClickSendSMSToken": "API Kullanıcı Adı ve API Anahtarını {0} adresinden alabilirsiniz.",
|
||||
"Connection String": "Bağlantı dizisi",
|
||||
"Connection String": "Bağlantı Dizisi",
|
||||
"Query": "Sorgu",
|
||||
"settingsCertificateExpiry": "TLS Sertifikasının Geçerlilik Süresi",
|
||||
"certificationExpiryDescription": "HTTPS Monitörleri, TLS sertifikasının süresi dolduğunda bildirimi tetikler:",
|
||||
"Setup Docker Host": "Docker Ana Bilgisayarını Ayarla",
|
||||
"Connection Type": "Bağlantı türü",
|
||||
"Docker Daemon": "Docker Daemon",
|
||||
"Docker Daemon": "Docker Servisi",
|
||||
"deleteDockerHostMsg": "Bu docker ana bilgisayarını tüm monitörler için silmek istediğinizden emin misiniz?",
|
||||
"socket": "Soket",
|
||||
"tcp": "TCP / HTTP",
|
||||
@ -840,11 +840,11 @@
|
||||
"styleElapsedTime": "Kalp atışı çubuğunun altında geçen süre",
|
||||
"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ı, MariaDB'yi sizin için otomatik olarak yerleştirdi ve yapılandırdı. Çalışma Süresi Kuma bu veri tabanı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 veri tabanını kullanmak istersiniz?",
|
||||
"setupDatabaseEmbeddedMariaDB": "Hiçbir şey ayarlamanıza gerek yok. Bu Docker görseli, MariaDB’yi otomatik olarak gömülü ve yapılandırılmış şekilde içerir. Uptime Kuma bu veri tabanına unix soketi aracılığıyla bağlanacaktır.",
|
||||
"setupDatabaseSQLite": "Küçük ölçekli dağıtımlar için önerilen basit bir veri tabanı dosyası. v2.0.0'dan önce Uptime Kuma, varsayılan veri tabanı olarak SQLite'ı kullanıyordu.",
|
||||
"setupDatabaseChooseDatabase": "Hangi veritabanını kullanmak istersiniz?",
|
||||
"setupDatabaseMariaDB": "Harici bir MariaDB veri tabanına bağlanın. Veri tabanı bağlantı bilgilerini ayarlamanız gerekir.",
|
||||
"dbName": "Veri tabanı ismi",
|
||||
"dbName": "Veri Tabanı Adı",
|
||||
"Saved.": "Kaydedildi.",
|
||||
"toastErrorTimeout": "Hata Bildirimleri için Zaman Aşımı",
|
||||
"toastSuccessTimeout": "Başarı Bildirimleri için Zaman Aşımı",
|
||||
@ -913,7 +913,7 @@
|
||||
"Add a domain": "Alan adı ekle",
|
||||
"Search monitored sites": "İzlenen siteleri arayın",
|
||||
"ntfyPriorityHelptextAllEvents": "Tüm olaylar maksimum öncelik ile gönderilir",
|
||||
"settingUpDatabaseMSG": "Veritabanı kuruluyor. Biraz zaman alabilir, lütfen sabırlı olun.",
|
||||
"settingUpDatabaseMSG": "Veri tabanı kuruluyor. Biraz zaman alabilir, lütfen sabırlı olun.",
|
||||
"statusPageSpecialSlugDesc": "Özel slug {0}: slug belirtilmediğinde bu sayfa gösterilecektir",
|
||||
"ntfyPriorityHelptextAllExceptDown": "Önceliği {1} olan {0}-olayları hariç tüm olaylar bu öncelik ile gönderilir",
|
||||
"What is a Remote Browser?": "Uzak Tarayıcı Nedir?",
|
||||
@ -1175,5 +1175,21 @@
|
||||
"tagNameExists": "Bu isimde bir sistem etiketi zaten var. Listeden seçin veya farklı bir isim kullanın.",
|
||||
"Clear Form": "Formu Temizle",
|
||||
"Optional: The audience to request the JWT for": "İsteğe bağlı: JWT'nin talep edileceği kitle",
|
||||
"OAuth Audience": "OAuth Kitlesi"
|
||||
"OAuth Audience": "OAuth Kitlesi",
|
||||
"mqttWebSocketPath": "MQTT WebSocket Yolu",
|
||||
"Path": "Yol",
|
||||
"mqttWebsocketPathExplanation": "WebSocket bağlantıları üzerinden MQTT için WebSocket yolu (örn. /mqtt)",
|
||||
"clearAllEventsMsg": "Tüm etkinlikleri silmek istediğinizden emin misiniz?",
|
||||
"Template plain text instead of using cards": "Kartlar yerine düz metin şablonu",
|
||||
"auto-select": "Otomatik Seç",
|
||||
"Could not clear events": "{failed}/{total} etkinlik temizlenemedi",
|
||||
"Clear All Events": "Tüm Etkinlikleri Temizle",
|
||||
"mqttWebsocketPathInvalid": "Lütfen geçerli bir WebSocket yolu formatı kullanın",
|
||||
"mqttHostnameTip": "Lütfen bu formatı kullanın {hostnameFormat}",
|
||||
"wayToGetBaleChatID": "Bot’a bir mesaj göndererek ve şu URL’ye giderek chat_id’nizi görüntüleyebilirsiniz:",
|
||||
"wayToGetBaleToken": "{0} üzerinden bir token alabilirsiniz.",
|
||||
"supportBaleChatID": "Destek Direkt Mesaj / Grup / Kanalın Mesaj ID'si",
|
||||
"Events cleared successfully": "Etkinlikler başarıyla temizlendi.",
|
||||
"No monitors found": "Monitör bulunamadı.",
|
||||
"issueWithGoogleChatOnAndroidHelptext": "Bu ayrıca {issuetackerURL} gibi üst akıştaki hataları aşmayı sağlar"
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { currentLocale } from "../i18n";
|
||||
import { setPageLocale, relativeTimeFormatter } from "../util-frontend";
|
||||
import { setPageLocale, timeDurationFormatter } from "../util-frontend";
|
||||
const langModules = import.meta.glob("../lang/*.json");
|
||||
|
||||
export default {
|
||||
@ -34,7 +34,7 @@ export default {
|
||||
this.$i18n.locale = lang;
|
||||
localStorage.locale = lang;
|
||||
setPageLocale();
|
||||
relativeTimeFormatter.updateLocale(lang);
|
||||
timeDurationFormatter.updateLocale(lang);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -602,11 +602,12 @@ export default {
|
||||
/**
|
||||
* Delete monitor by ID
|
||||
* @param {number} monitorID ID of monitor to delete
|
||||
* @param {boolean} deleteChildren Whether to delete child monitors (for groups)
|
||||
* @param {socketCB} callback Callback for socket response
|
||||
* @returns {void}
|
||||
*/
|
||||
deleteMonitor(monitorID, callback) {
|
||||
socket.emit("deleteMonitor", monitorID, callback);
|
||||
deleteMonitor(monitorID, deleteChildren, callback) {
|
||||
socket.emit("deleteMonitor", monitorID, deleteChildren, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@ -441,7 +441,23 @@
|
||||
:no-text="$t('No')"
|
||||
@yes="deleteMonitor"
|
||||
>
|
||||
{{ $t("deleteMonitorMsg") }}
|
||||
<div v-if="monitor && monitor.type === 'group'">
|
||||
<div>{{ $t("deleteGroupMsg") }}</div>
|
||||
<div v-if="hasChildren" class="form-check">
|
||||
<input
|
||||
id="delete-children-checkbox"
|
||||
v-model="deleteChildrenMonitors"
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
>
|
||||
<label class="form-check-label" for="delete-children-checkbox">
|
||||
{{ $t("deleteChildrenMonitors", childrenCount, { count: childrenCount }) }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ $t("deleteMonitorMsg") }}
|
||||
</div>
|
||||
</Confirm>
|
||||
|
||||
<Confirm
|
||||
@ -487,7 +503,7 @@ import { getMonitorRelativeURL } from "../util.ts";
|
||||
import { URL } from "whatwg-url";
|
||||
import DOMPurify from "dompurify";
|
||||
import { marked } from "marked";
|
||||
import { getResBaseURL, relativeTimeFormatter } from "../util-frontend";
|
||||
import { getResBaseURL, timeDurationFormatter } from "../util-frontend";
|
||||
import { highlight, languages } from "prismjs/components/prism-core";
|
||||
import "prismjs/components/prism-clike";
|
||||
import "prismjs/components/prism-javascript";
|
||||
@ -530,6 +546,7 @@ export default {
|
||||
currentExample: "javascript-fetch",
|
||||
code: "",
|
||||
},
|
||||
deleteChildrenMonitors: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -538,6 +555,26 @@ export default {
|
||||
return this.$root.monitorList[id];
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the count of children monitors for this group
|
||||
* @returns {number} Number of children monitors
|
||||
*/
|
||||
childrenCount() {
|
||||
if (!this.monitor || this.monitor.type !== "group") {
|
||||
return 0;
|
||||
}
|
||||
const children = Object.values(this.$root.monitorList).filter(m => m.parent === this.monitor.id);
|
||||
return children.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if the monitor is a group and has children
|
||||
* @returns {boolean} True if monitor is a group with children
|
||||
*/
|
||||
hasChildren() {
|
||||
return this.childrenCount > 0;
|
||||
},
|
||||
|
||||
lastHeartBeat() {
|
||||
// Also trigger screenshot refresh here
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
@ -752,7 +789,7 @@ export default {
|
||||
* @returns {void}
|
||||
*/
|
||||
deleteMonitor() {
|
||||
this.$root.deleteMonitor(this.monitor.id, (res) => {
|
||||
this.$root.deleteMonitor(this.monitor.id, this.deleteChildrenMonitors, (res) => {
|
||||
this.$root.toastRes(res);
|
||||
if (res.ok) {
|
||||
this.$router.push("/dashboard");
|
||||
@ -928,7 +965,7 @@ export default {
|
||||
},
|
||||
|
||||
secondsToHumanReadableFormat(seconds) {
|
||||
return relativeTimeFormatter.secondsToHumanReadableFormat(seconds);
|
||||
return timeDurationFormatter.secondsToHumanReadableFormat(seconds);
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -937,6 +974,10 @@ export default {
|
||||
<style lang="scss" scoped>
|
||||
@import "../assets/vars.scss";
|
||||
|
||||
.form-check {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.badge {
|
||||
margin-top: 14px;
|
||||
|
||||
@ -354,7 +354,14 @@ export default {
|
||||
},
|
||||
|
||||
pageName() {
|
||||
return this.$t((this.isAdd) ? "Schedule Maintenance" : "Edit Maintenance");
|
||||
let name = "Schedule Maintenance";
|
||||
|
||||
if (this.isEdit) {
|
||||
name = "Edit Maintenance";
|
||||
} else if (this.isClone) {
|
||||
name = "Clone Maintenance";
|
||||
}
|
||||
return this.$t(name);
|
||||
},
|
||||
|
||||
isAdd() {
|
||||
@ -365,6 +372,9 @@ export default {
|
||||
return this.$route.path.startsWith("/maintenance/edit");
|
||||
},
|
||||
|
||||
isClone() {
|
||||
return this.$route.path.startsWith("/maintenance/clone");
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"$route.fullPath"() {
|
||||
@ -443,11 +453,16 @@ export default {
|
||||
daysOfMonth: [],
|
||||
timezoneOption: null,
|
||||
};
|
||||
} else if (this.isEdit) {
|
||||
} else if (this.isEdit || this.isClone) {
|
||||
this.$root.getSocket().emit("getMaintenance", this.$route.params.id, (res) => {
|
||||
if (res.ok) {
|
||||
this.maintenance = res.maintenance;
|
||||
|
||||
if (this.isClone) {
|
||||
this.maintenance.id = undefined; // Remove id when cloning as we want a new id
|
||||
this.maintenance.title = this.$t("cloneOf", [ this.maintenance.title ]);
|
||||
}
|
||||
|
||||
this.$root.getSocket().emit("getMonitorMaintenance", this.$route.params.id, (res) => {
|
||||
if (res.ok) {
|
||||
Object.values(res.monitors).map(monitor => {
|
||||
@ -491,7 +506,7 @@ export default {
|
||||
return this.processing = false;
|
||||
}
|
||||
|
||||
if (this.isAdd) {
|
||||
if (this.isAdd || this.isClone) {
|
||||
this.$root.addMaintenance(this.maintenance, async (res) => {
|
||||
if (res.ok) {
|
||||
await this.addMonitorMaintenance(res.maintenanceID, async () => {
|
||||
|
||||
@ -1174,7 +1174,7 @@ import {
|
||||
MIN_INTERVAL_SECOND,
|
||||
sleep,
|
||||
} from "../util.ts";
|
||||
import { hostNameRegexPattern, relativeTimeFormatter } from "../util-frontend";
|
||||
import { hostNameRegexPattern, timeDurationFormatter } from "../util-frontend";
|
||||
import HiddenInput from "../components/HiddenInput.vue";
|
||||
import EditMonitorConditions from "../components/EditMonitorConditions.vue";
|
||||
|
||||
@ -1190,7 +1190,7 @@ const monitorDefaults = {
|
||||
method: "GET",
|
||||
ipFamily: null,
|
||||
interval: 60,
|
||||
humanReadableInterval: relativeTimeFormatter.secondsToHumanReadableFormat(60),
|
||||
humanReadableInterval: timeDurationFormatter.secondsToHumanReadableFormat(60),
|
||||
retryInterval: 60,
|
||||
resendInterval: 0,
|
||||
maxretries: 0,
|
||||
@ -1574,7 +1574,7 @@ message HealthCheckResponse {
|
||||
this.monitor.retryInterval = value;
|
||||
}
|
||||
// Converting monitor.interval to human readable format.
|
||||
this.monitor.humanReadableInterval = relativeTimeFormatter.secondsToHumanReadableFormat(value);
|
||||
this.monitor.humanReadableInterval = timeDurationFormatter.secondsToHumanReadableFormat(value);
|
||||
},
|
||||
|
||||
"monitor.timeout"(value, oldValue) {
|
||||
|
||||
@ -41,19 +41,23 @@
|
||||
<router-link v-if="false" :to="maintenanceURL(item.id)" class="btn btn-light">{{ $t("Details") }}</router-link>
|
||||
|
||||
<div class="btn-group" role="group">
|
||||
<button v-if="item.active" class="btn btn-normal" @click="pauseDialog(item.id)">
|
||||
<button v-if="item.active" class="btn btn-normal" :aria-label="$t('ariaPauseMaintenance')" @click="pauseDialog(item.id)">
|
||||
<font-awesome-icon icon="pause" /> {{ $t("Pause") }}
|
||||
</button>
|
||||
|
||||
<button v-if="!item.active" class="btn btn-primary" @click="resumeMaintenance(item.id)">
|
||||
<button v-if="!item.active" class="btn btn-primary" :aria-label="$t('ariaResumeMaintenance')" @click="resumeMaintenance(item.id)">
|
||||
<font-awesome-icon icon="play" /> {{ $t("Resume") }}
|
||||
</button>
|
||||
|
||||
<router-link :to="'/maintenance/edit/' + item.id" class="btn btn-normal">
|
||||
<router-link :to="'/maintenance/clone/' + item.id" class="btn btn-normal" :aria-label="$t('ariaCloneMaintenance')">
|
||||
<font-awesome-icon icon="clone" /> {{ $t("Clone") }}
|
||||
</router-link>
|
||||
|
||||
<router-link :to="'/maintenance/edit/' + item.id" class="btn btn-normal" :aria-label="$t('ariaEditMaintenance')">
|
||||
<font-awesome-icon icon="edit" /> {{ $t("Edit") }}
|
||||
</router-link>
|
||||
|
||||
<button class="btn btn-normal text-danger" @click="deleteDialog(item.id)">
|
||||
<button class="btn btn-normal text-danger" :aria-label="$t('ariaDeleteMaintenance')" @click="deleteDialog(item.id)">
|
||||
<font-awesome-icon icon="trash" /> {{ $t("Delete") }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -162,6 +162,10 @@ const routes = [
|
||||
path: "/maintenance/edit/:id",
|
||||
component: EditMaintenance,
|
||||
},
|
||||
{
|
||||
path: "/maintenance/clone/:id",
|
||||
component: EditMaintenance,
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@ -214,13 +214,18 @@ export function getToastErrorTimeout() {
|
||||
return errorTimeout;
|
||||
}
|
||||
|
||||
class RelativeTimeFormatter {
|
||||
class TimeDurationFormatter {
|
||||
/**
|
||||
* Default locale and options for Relative Time Formatter
|
||||
* Default locale and options for Time Duration Formatter (supports both DurationFormat and RelativeTimeFormat)
|
||||
*/
|
||||
constructor() {
|
||||
this.options = { numeric: "always" };
|
||||
this.instance = new Intl.RelativeTimeFormat(currentLocale(), this.options);
|
||||
this.durationFormatOptions = { style: "long" };
|
||||
this.relativeTimeFormatOptions = { numeric: "always" };
|
||||
if (Intl.DurationFormat !== undefined) {
|
||||
this.durationFormatInstance = new Intl.DurationFormat(currentLocale(), this.durationFormatOptions);
|
||||
} else {
|
||||
this.relativeTimeFormatInstance = new Intl.RelativeTimeFormat(currentLocale(), this.relativeTimeFormatOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,7 +234,11 @@ class RelativeTimeFormatter {
|
||||
* @returns {void} No return value.
|
||||
*/
|
||||
updateLocale(locale) {
|
||||
this.instance = new Intl.RelativeTimeFormat(locale, this.options);
|
||||
if (Intl.DurationFormat !== undefined) {
|
||||
this.durationFormatInstance = new Intl.DurationFormat(locale, this.durationFormatOptions);
|
||||
} else {
|
||||
this.relativeTimeFormatInstance = new Intl.RelativeTimeFormat(locale, this.relativeTimeFormatOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,6 +251,17 @@ class RelativeTimeFormatter {
|
||||
const hours = Math.floor((seconds % 86400) / 3600);
|
||||
const minutes = Math.floor(((seconds % 86400) % 3600) / 60);
|
||||
const secs = ((seconds % 86400) % 3600) % 60;
|
||||
|
||||
if (this.durationFormatInstance !== undefined) {
|
||||
// use Intl.DurationFormat if available
|
||||
return this.durationFormatInstance.format({
|
||||
days,
|
||||
hours,
|
||||
minutes,
|
||||
seconds: secs
|
||||
});
|
||||
}
|
||||
|
||||
const parts = [];
|
||||
/**
|
||||
* Build the formatted string from parts
|
||||
@ -253,12 +273,11 @@ class RelativeTimeFormatter {
|
||||
* @returns {void}
|
||||
*/
|
||||
const toFormattedPart = (value, unitOfTime) => {
|
||||
const partsArray = this.instance.formatToParts(value, unitOfTime);
|
||||
const partsArray = this.relativeTimeFormatInstance.formatToParts(value, unitOfTime);
|
||||
const filteredParts = partsArray
|
||||
.filter(
|
||||
(part, index) =>
|
||||
(part.type === "literal" || part.type === "integer") &&
|
||||
index > 0
|
||||
part.type === "integer" || (part.type === "literal" && index > 0)
|
||||
)
|
||||
.map((part) => part.value);
|
||||
|
||||
@ -282,9 +301,9 @@ class RelativeTimeFormatter {
|
||||
if (parts.length > 0) {
|
||||
return `${parts.join(" ")}`;
|
||||
}
|
||||
return this.instance.format(0, "second"); // Handle case for 0 seconds
|
||||
return this.relativeTimeFormatInstance.format(0, "second"); // Handle case for 0 seconds
|
||||
}
|
||||
}
|
||||
|
||||
export const relativeTimeFormatter = new RelativeTimeFormatter();
|
||||
export const timeDurationFormatter = new TimeDurationFormatter();
|
||||
|
||||
|
||||
57
src/util.js
57
src/util.js
@ -133,7 +133,7 @@ function ucfirst(str) {
|
||||
}
|
||||
exports.ucfirst = ucfirst;
|
||||
function debug(msg) {
|
||||
exports.log.log("", msg, "debug");
|
||||
exports.log.log("", "debug", msg);
|
||||
}
|
||||
exports.debug = debug;
|
||||
class Logger {
|
||||
@ -156,7 +156,7 @@ class Logger {
|
||||
this.debug("server", this.hideLog);
|
||||
}
|
||||
}
|
||||
log(module, msg, level) {
|
||||
log(module, level, ...msg) {
|
||||
if (level === "DEBUG" && !exports.isDev) {
|
||||
return;
|
||||
}
|
||||
@ -177,7 +177,6 @@ class Logger {
|
||||
let timePart;
|
||||
let modulePart;
|
||||
let levelPart;
|
||||
let msgPart;
|
||||
if (exports.isNode) {
|
||||
switch (level) {
|
||||
case "DEBUG":
|
||||
@ -189,72 +188,50 @@ class Logger {
|
||||
}
|
||||
modulePart = "[" + moduleColor + module + exports.CONSOLE_STYLE_Reset + "]";
|
||||
levelPart = levelColor + `${level}:` + exports.CONSOLE_STYLE_Reset;
|
||||
switch (level) {
|
||||
case "ERROR":
|
||||
if (typeof msg === "string") {
|
||||
msgPart = exports.CONSOLE_STYLE_FgRed + msg + exports.CONSOLE_STYLE_Reset;
|
||||
}
|
||||
else {
|
||||
msgPart = msg;
|
||||
}
|
||||
break;
|
||||
case "DEBUG":
|
||||
if (typeof msg === "string") {
|
||||
msgPart = exports.CONSOLE_STYLE_FgGray + msg + exports.CONSOLE_STYLE_Reset;
|
||||
}
|
||||
else {
|
||||
msgPart = msg;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
msgPart = msg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
timePart = now;
|
||||
modulePart = `[${module}]`;
|
||||
levelPart = `${level}:`;
|
||||
msgPart = msg;
|
||||
}
|
||||
switch (level) {
|
||||
case "ERROR":
|
||||
console.error(timePart, modulePart, levelPart, msgPart);
|
||||
console.error(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
case "WARN":
|
||||
console.warn(timePart, modulePart, levelPart, msgPart);
|
||||
console.warn(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
case "INFO":
|
||||
console.info(timePart, modulePart, levelPart, msgPart);
|
||||
console.info(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
case "DEBUG":
|
||||
if (exports.isDev) {
|
||||
console.debug(timePart, modulePart, levelPart, msgPart);
|
||||
console.debug(timePart, modulePart, levelPart, ...msg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log(timePart, modulePart, levelPart, msgPart);
|
||||
console.log(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
info(module, msg) {
|
||||
this.log(module, msg, "info");
|
||||
info(module, ...msg) {
|
||||
this.log(module, "info", ...msg);
|
||||
}
|
||||
warn(module, msg) {
|
||||
this.log(module, msg, "warn");
|
||||
warn(module, ...msg) {
|
||||
this.log(module, "warn", ...msg);
|
||||
}
|
||||
error(module, msg) {
|
||||
this.log(module, msg, "error");
|
||||
error(module, ...msg) {
|
||||
this.log(module, "error", ...msg);
|
||||
}
|
||||
debug(module, msg) {
|
||||
this.log(module, msg, "debug");
|
||||
debug(module, ...msg) {
|
||||
this.log(module, "debug", ...msg);
|
||||
}
|
||||
exception(module, exception, msg) {
|
||||
exception(module, exception, ...msg) {
|
||||
let finalMessage = exception;
|
||||
if (msg) {
|
||||
finalMessage = `${msg}: ${exception}`;
|
||||
}
|
||||
this.log(module, finalMessage, "error");
|
||||
this.log(module, "error", finalMessage);
|
||||
}
|
||||
}
|
||||
exports.log = new Logger();
|
||||
|
||||
64
src/util.ts
64
src/util.ts
@ -193,7 +193,7 @@ export function ucfirst(str: string) {
|
||||
* @returns {void}
|
||||
*/
|
||||
export function debug(msg: unknown) {
|
||||
log.log("", msg, "debug");
|
||||
log.log("", "debug", msg);
|
||||
}
|
||||
|
||||
class Logger {
|
||||
@ -238,11 +238,11 @@ class Logger {
|
||||
/**
|
||||
* 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.
|
||||
* @param msg Message to write
|
||||
* @returns {void}
|
||||
*/
|
||||
log(module: string, msg: any, level: string) {
|
||||
log(module: string, level: string, ...msg: unknown[]) {
|
||||
if (level === "DEBUG" && !isDev) {
|
||||
return;
|
||||
}
|
||||
@ -267,7 +267,6 @@ class Logger {
|
||||
let timePart: string;
|
||||
let modulePart: string;
|
||||
let levelPart: string;
|
||||
let msgPart: string;
|
||||
|
||||
if (isNode) {
|
||||
// Add console colors
|
||||
@ -281,54 +280,33 @@ class Logger {
|
||||
}
|
||||
|
||||
modulePart = "[" + moduleColor + module + CONSOLE_STYLE_Reset + "]";
|
||||
|
||||
levelPart = levelColor + `${level}:` + CONSOLE_STYLE_Reset;
|
||||
|
||||
switch (level) {
|
||||
case "ERROR":
|
||||
if (typeof msg === "string") {
|
||||
msgPart = CONSOLE_STYLE_FgRed + msg + CONSOLE_STYLE_Reset;
|
||||
} else {
|
||||
msgPart = msg;
|
||||
}
|
||||
break;
|
||||
case "DEBUG":
|
||||
if (typeof msg === "string") {
|
||||
msgPart = CONSOLE_STYLE_FgGray + msg + CONSOLE_STYLE_Reset;
|
||||
} else {
|
||||
msgPart = msg;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
msgPart = msg;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// No console colors
|
||||
timePart = now;
|
||||
modulePart = `[${module}]`;
|
||||
levelPart = `${level}:`;
|
||||
msgPart = msg;
|
||||
}
|
||||
|
||||
// Write to console
|
||||
switch (level) {
|
||||
case "ERROR":
|
||||
console.error(timePart, modulePart, levelPart, msgPart);
|
||||
console.error(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
case "WARN":
|
||||
console.warn(timePart, modulePart, levelPart, msgPart);
|
||||
console.warn(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
case "INFO":
|
||||
console.info(timePart, modulePart, levelPart, msgPart);
|
||||
console.info(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
case "DEBUG":
|
||||
if (isDev) {
|
||||
console.debug(timePart, modulePart, levelPart, msgPart);
|
||||
console.debug(timePart, modulePart, levelPart, ...msg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log(timePart, modulePart, levelPart, msgPart);
|
||||
console.log(timePart, modulePart, levelPart, ...msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -339,8 +317,8 @@ class Logger {
|
||||
* @param msg Message to write
|
||||
* @returns {void}
|
||||
*/
|
||||
info(module: string, msg: unknown) {
|
||||
this.log(module, msg, "info");
|
||||
info(module: string, ...msg: unknown[]) {
|
||||
this.log(module, "info", ...msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -349,8 +327,8 @@ class Logger {
|
||||
* @param msg Message to write
|
||||
* @returns {void}
|
||||
*/
|
||||
warn(module: string, msg: unknown) {
|
||||
this.log(module, msg, "warn");
|
||||
warn(module: string, ...msg: unknown[]) {
|
||||
this.log(module, "warn", ...msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -359,8 +337,8 @@ class Logger {
|
||||
* @param msg Message to write
|
||||
* @returns {void}
|
||||
*/
|
||||
error(module: string, msg: unknown) {
|
||||
this.log(module, msg, "error");
|
||||
error(module: string, ...msg: unknown[]) {
|
||||
this.log(module, "error", ...msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -369,8 +347,8 @@ class Logger {
|
||||
* @param msg Message to write
|
||||
* @returns {void}
|
||||
*/
|
||||
debug(module: string, msg: unknown) {
|
||||
this.log(module, msg, "debug");
|
||||
debug(module: string, ...msg: unknown[]) {
|
||||
this.log(module, "debug", ...msg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -380,14 +358,8 @@ class Logger {
|
||||
* @param msg The message to write
|
||||
* @returns {void}
|
||||
*/
|
||||
exception(module: string, exception: unknown, msg: unknown) {
|
||||
let finalMessage = exception;
|
||||
|
||||
if (msg) {
|
||||
finalMessage = `${msg}: ${exception}`;
|
||||
}
|
||||
|
||||
this.log(module, finalMessage, "error");
|
||||
exception(module: string, exception: unknown, ...msg: unknown[]) {
|
||||
this.log(module, "error", ...msg, exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user