mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-10-29 18:50:39 +00:00
Merge remote-tracking branch 'origin/master' into mongodb-ping
# Conflicts: # server/model/monitor.js # server/util-server.js # src/pages/EditMonitor.vue
This commit is contained in:
commit
e48a987b9c
92 changed files with 6445 additions and 2124 deletions
|
@ -31,6 +31,9 @@ tsconfig.json
|
|||
/tmp
|
||||
/babel.config.js
|
||||
/ecosystem.config.js
|
||||
/extra/healthcheck.exe
|
||||
/extra/healthcheck
|
||||
|
||||
|
||||
### .gitignore content (commented rules are duplicated)
|
||||
|
||||
|
|
|
@ -19,3 +19,6 @@ indent_size = 2
|
|||
|
||||
[*.vue]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
|
|
18
.github/workflows/auto-test.yml
vendored
18
.github/workflows/auto-test.yml
vendored
|
@ -18,7 +18,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
node: [ 14, 16, 17, 18 ]
|
||||
node: [ 14, 16, 18, 19 ]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
|
@ -66,3 +66,19 @@ jobs:
|
|||
- run: npm install
|
||||
- run: npm run build
|
||||
- run: npm run cy:test
|
||||
|
||||
frontend-unit-tests:
|
||||
needs: [ check-linters ]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: git config --global core.autocrlf false # Mainly for Windows
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js 14
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14
|
||||
cache: 'npm'
|
||||
- run: npm install
|
||||
- run: npm run build
|
||||
- run: npm run cy:run:unit
|
||||
|
|
6
.github/workflows/stale-bot.yml
vendored
6
.github/workflows/stale-bot.yml
vendored
|
@ -12,13 +12,11 @@ jobs:
|
|||
- uses: actions/stale@v5
|
||||
with:
|
||||
stale-issue-message: 'We are clearing up our old issues and your ticket has been open for 3 months with no activity. Remove stale label or comment or this will be closed in 2 days.'
|
||||
stale-pr-message: 'We are clearing up our old Pull Requests and yours has been open for 3 months with no activity. Remove stale label or comment or this will be closed in 2 days.'
|
||||
close-issue-message: 'This issue was closed because it has been stalled for 2 days with no activity.'
|
||||
close-pr-message: 'This PR was closed because it has been stalled for 2 days with no activity.'
|
||||
days-before-stale: 90
|
||||
days-before-close: 2
|
||||
days-before-pr-stale: 999999999
|
||||
days-before-pr-close: 1
|
||||
exempt-issue-labels: 'News,Medium,High,discussion,bug,doc,feature-request'
|
||||
exempt-pr-labels: 'awaiting-approval,work-in-progress,enhancement,feature-request'
|
||||
exempt-issue-assignees: 'louislam'
|
||||
exempt-pr-assignees: 'louislam'
|
||||
operations-per-run: 200
|
||||
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -16,3 +16,7 @@ dist-ssr
|
|||
|
||||
cypress/videos
|
||||
cypress/screenshots
|
||||
|
||||
/extra/healthcheck.exe
|
||||
/extra/healthcheck
|
||||
/extra/healthcheck-armv7
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Project Info
|
||||
|
||||
First of all, thank you everyone who made pull requests for Uptime Kuma, I never thought GitHub Community can be that nice! And also because of this, I also never thought other people actually read my code and edit my code. It is not structured and commented so well, lol. Sorry about that.
|
||||
First of all, I want to thank everyone who made pull requests for Uptime Kuma. I never thought the GitHub Community would be so nice! Because of this, I also never thought that other people would actually read and edit my code. It is not very well structured or commented, sorry about that.
|
||||
|
||||
The project was created with vite.js (vue3). Then I created a subdirectory called "server" for server part. Both frontend and backend share the same package.json.
|
||||
|
||||
|
@ -27,7 +27,7 @@ The frontend code build into "dist" directory. The server (express.js) exposes t
|
|||
|
||||
## Can I create a pull request for Uptime Kuma?
|
||||
|
||||
Yes or no, it depends on what you will try to do. Since I don't want to waste your time, be sure to **create an empty draft pull request or open an issue, so we can discuss first**. Especially for a large pull request or you don't know it will be merged or not.
|
||||
Yes or no, it depends on what you will try to do. Since I don't want to waste your time, be sure to **create an empty draft pull request or open an issue, so we can have a discussion first**. Especially for a large pull request or you don't know it will be merged or not.
|
||||
|
||||
Here are some references:
|
||||
|
||||
|
@ -48,8 +48,13 @@ Here are some references:
|
|||
- UI/UX is not close to Uptime Kuma
|
||||
- Existing logic is completely modified or deleted for no reason
|
||||
- A function that is completely out of scope
|
||||
- Convert existing code into other programming languages
|
||||
- Unnecessary large code changes (Hard to review, causes code conflicts to other pull requests)
|
||||
|
||||
The above cases cannot cover all situations.
|
||||
|
||||
I (@louislam) have the final say. If your pull request does not meet my expectations, I will reject it, no matter how much time you spend on it. Therefore, it is essential to have a discussion beforehand.
|
||||
|
||||
I will mark your pull request in the [milestones](https://github.com/louislam/uptime-kuma/milestones), if I am plan to review and merge it.
|
||||
|
||||
Also, please don't rush or ask for ETA, because I have to understand the pull request, make sure it is no breaking changes and stick to my vision of this project, especially for large pull requests.
|
||||
|
@ -72,9 +77,9 @@ Before deep into coding, discussion first is preferred. Creating an empty pull r
|
|||
|
||||
## Project Styles
|
||||
|
||||
I personally do not like something need to learn so much and need to config so much before you can finally start the app.
|
||||
I personally do not like it when something requires so much learning and configuration before you can finally start the app.
|
||||
|
||||
- Easy to install for non-Docker users, no native build dependency is needed (at least for x86_64), no extra config, no extra effort to get it run
|
||||
- Easy to install for non-Docker users, no native build dependency is needed (at least for x86_64), no extra config, no extra effort required to get it running
|
||||
- Single container for Docker users, no very complex docker-compose file. Just map the volume and expose the port, then good to go
|
||||
- Settings should be configurable in the frontend. Environment variable is not encouraged, unless it is related to startup such as `DATA_DIR`.
|
||||
- Easy to use
|
||||
|
@ -172,15 +177,11 @@ The data and socket logic are in `src/mixins/socket.js`.
|
|||
|
||||
## Unit Test
|
||||
|
||||
It is an end-to-end testing. It is using Jest and Puppeteer.
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm test
|
||||
```
|
||||
|
||||
By default, the Chromium window will be shown up during the test. Specifying `HEADLESS_TEST=1` for terminal environments.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Both frontend and backend share the same package.json. However, the frontend dependencies are eventually not used in the production environment, because it is usually also baked into dist files. So:
|
||||
|
|
30
README.md
30
README.md
|
@ -7,9 +7,9 @@
|
|||
<img src="./public/icon.svg" width="128" alt="" />
|
||||
</div>
|
||||
|
||||
It is a self-hosted monitoring tool like "Uptime Robot".
|
||||
Uptime Kuma is an easy-to-use self-hosted monitoring tool.
|
||||
|
||||
<img src="https://uptime.kuma.pet/img/dark.jpg" width="700" alt="" />
|
||||
<img src="https://user-images.githubusercontent.com/1336778/212262296-e6205815-ad62-488c-83ec-a5b0d0689f7c.jpg" width="700" alt="" />
|
||||
|
||||
## 🥔 Live Demo
|
||||
|
||||
|
@ -22,17 +22,17 @@ It is a temporary live demo, all data will be deleted after 10 minutes. Use the
|
|||
|
||||
## ⭐ Features
|
||||
|
||||
* Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / Ping / DNS Record / Push / Steam Game Server / Docker Containers.
|
||||
* Fancy, Reactive, Fast UI/UX.
|
||||
* Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications).
|
||||
* 20 second intervals.
|
||||
* Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / Ping / DNS Record / Push / Steam Game Server / Docker Containers
|
||||
* Fancy, Reactive, Fast UI/UX
|
||||
* Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications)
|
||||
* 20 second intervals
|
||||
* [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/languages)
|
||||
* Multiple Status Pages
|
||||
* Map Status Page to Domain
|
||||
* Ping Chart
|
||||
* Certificate Info
|
||||
* Proxy Support
|
||||
* 2FA available
|
||||
* Multiple status pages
|
||||
* Map status pages to specific domains
|
||||
* Ping chart
|
||||
* Certificate info
|
||||
* Proxy support
|
||||
* 2FA support
|
||||
|
||||
## 🔧 How to Install
|
||||
|
||||
|
@ -44,14 +44,14 @@ docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name upti
|
|||
|
||||
⚠️ Please use a **local volume** only. Other types such as NFS are not supported.
|
||||
|
||||
Browse to http://localhost:3001 after starting.
|
||||
Uptime Kuma is now running on http://localhost:3001
|
||||
|
||||
### 💪🏻 Non-Docker
|
||||
|
||||
Required Tools:
|
||||
- [Node.js](https://nodejs.org/en/download/) >= 14
|
||||
- [Git](https://git-scm.com/downloads)
|
||||
- [pm2](https://pm2.keymetrics.io/) - For run in background
|
||||
- [pm2](https://pm2.keymetrics.io/) - For running Uptime Kuma in the background
|
||||
|
||||
```bash
|
||||
# Update your npm to the latest version
|
||||
|
@ -73,7 +73,7 @@ pm2 start server/server.js --name uptime-kuma
|
|||
|
||||
|
||||
```
|
||||
Browse to http://localhost:3001 after starting.
|
||||
Uptime Kuma is now running on http://localhost:3001
|
||||
|
||||
More useful PM2 Commands
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report security issues to uptime@kuma.pet.
|
||||
Please report security issues to https://github.com/louislam/uptime-kuma/security/advisories/new.
|
||||
|
||||
Do not use the issue tracker or discuss it in the public as it will cause more damage.
|
||||
Do not use the public issue tracker or discuss it in the public as it will cause more damage.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
|
|
10
config/cypress.frontend.config.js
Normal file
10
config/cypress.frontend.config.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
const { defineConfig } = require("cypress");
|
||||
|
||||
module.exports = defineConfig({
|
||||
e2e: {
|
||||
supportFile: false,
|
||||
specPattern: [
|
||||
"test/cypress/unit/**/*.js"
|
||||
],
|
||||
}
|
||||
});
|
|
@ -4,5 +4,5 @@ WORKDIR /app
|
|||
|
||||
# Install apprise, iputils for non-root ping, setpriv
|
||||
RUN apk add --no-cache iputils setpriv dumb-init python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib && \
|
||||
pip3 --no-cache-dir install apprise==1.0.0 && \
|
||||
pip3 --no-cache-dir install apprise==1.2.1 && \
|
||||
rm -rf /root/.cache
|
||||
|
|
16
docker/builder-go.dockerfile
Normal file
16
docker/builder-go.dockerfile
Normal file
|
@ -0,0 +1,16 @@
|
|||
############################################
|
||||
# Build in Golang
|
||||
# Run npm run build-healthcheck-armv7 in the host first, another it will be super slow where it is building the armv7 healthcheck
|
||||
############################################
|
||||
FROM golang:1.19.4-buster
|
||||
WORKDIR /app
|
||||
ARG TARGETPLATFORM
|
||||
COPY ./extra/ ./extra/
|
||||
|
||||
# Compile healthcheck.go
|
||||
RUN apt update && \
|
||||
apt --yes --no-install-recommends install curl && \
|
||||
curl -sL https://deb.nodesource.com/setup_18.x | bash && \
|
||||
apt --yes --no-install-recommends install nodejs && \
|
||||
node ./extra/build-healthcheck.js $TARGETPLATFORM && \
|
||||
apt --yes remove nodejs
|
|
@ -11,7 +11,7 @@ WORKDIR /app
|
|||
RUN apt update && \
|
||||
apt --yes --no-install-recommends install python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \
|
||||
sqlite3 iputils-ping util-linux dumb-init && \
|
||||
pip3 --no-cache-dir install apprise==1.0.0 && \
|
||||
pip3 --no-cache-dir install apprise==1.2.1 && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
apt --yes autoremove
|
||||
|
||||
|
|
|
@ -1,30 +1,50 @@
|
|||
############################################
|
||||
# Build in Golang
|
||||
# Run npm run build-healthcheck-armv7 in the host first, another it will be super slow where it is building the armv7 healthcheck
|
||||
# Check file: builder-go.dockerfile
|
||||
############################################
|
||||
FROM louislam/uptime-kuma:builder-go AS build_healthcheck
|
||||
|
||||
############################################
|
||||
# Build in Node.js
|
||||
############################################
|
||||
FROM louislam/uptime-kuma:base-debian AS build
|
||||
WORKDIR /app
|
||||
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
|
||||
|
||||
COPY .npmrc .npmrc
|
||||
COPY package.json package.json
|
||||
COPY package-lock.json package-lock.json
|
||||
RUN npm ci --omit=dev
|
||||
COPY . .
|
||||
RUN npm ci --production && \
|
||||
chmod +x /app/extra/entrypoint.sh
|
||||
|
||||
COPY --from=build_healthcheck /app/extra/healthcheck /app/extra/healthcheck
|
||||
RUN chmod +x /app/extra/entrypoint.sh
|
||||
|
||||
############################################
|
||||
# ⭐ Main Image
|
||||
############################################
|
||||
FROM louislam/uptime-kuma:base-debian AS release
|
||||
WORKDIR /app
|
||||
|
||||
# Copy app files from build layer
|
||||
COPY --from=build /app /app
|
||||
|
||||
|
||||
EXPOSE 3001
|
||||
VOLUME ["/app/data"]
|
||||
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD node extra/healthcheck.js
|
||||
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD extra/healthcheck
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "extra/entrypoint.sh"]
|
||||
CMD ["node", "server/server.js"]
|
||||
|
||||
|
||||
############################################
|
||||
# Mark as Nightly
|
||||
############################################
|
||||
FROM release AS nightly
|
||||
RUN npm run mark-as-nightly
|
||||
|
||||
############################################
|
||||
# Build an image for testing pr
|
||||
############################################
|
||||
FROM louislam/uptime-kuma:base-debian AS pr-test
|
||||
|
||||
WORKDIR /app
|
||||
|
@ -54,8 +74,9 @@ VOLUME ["/app/data"]
|
|||
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD node extra/healthcheck.js
|
||||
CMD ["npm", "run", "start-pr-test"]
|
||||
|
||||
|
||||
############################################
|
||||
# Upload the artifact to Github
|
||||
############################################
|
||||
FROM louislam/uptime-kuma:base-debian AS upload-artifact
|
||||
WORKDIR /
|
||||
RUN apt update && \
|
||||
|
|
|
@ -3,10 +3,12 @@ WORKDIR /app
|
|||
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
|
||||
|
||||
COPY .npmrc .npmrc
|
||||
COPY package.json package.json
|
||||
COPY package-lock.json package-lock.json
|
||||
RUN npm ci --omit=dev
|
||||
COPY . .
|
||||
RUN npm ci --production && \
|
||||
chmod +x /app/extra/entrypoint.sh
|
||||
|
||||
RUN chmod +x /app/extra/entrypoint.sh
|
||||
|
||||
FROM louislam/uptime-kuma:base-alpine AS release
|
||||
WORKDIR /app
|
||||
|
|
27
extra/build-healthcheck.js
Normal file
27
extra/build-healthcheck.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
const childProcess = require("child_process");
|
||||
const fs = require("fs");
|
||||
const platform = process.argv[2];
|
||||
|
||||
if (!platform) {
|
||||
console.error("No platform??");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (platform === "linux/arm/v7") {
|
||||
console.log("Arch: armv7");
|
||||
if (fs.existsSync("./extra/healthcheck-armv7")) {
|
||||
fs.renameSync("./extra/healthcheck-armv7", "./extra/healthcheck");
|
||||
console.log("Already built in the host, skip.");
|
||||
process.exit(0);
|
||||
} else {
|
||||
console.log("prebuilt not found, it will be slow! You should execute `npm run build-healthcheck-armv7` before build.");
|
||||
}
|
||||
} else {
|
||||
if (fs.existsSync("./extra/healthcheck-armv7")) {
|
||||
fs.rmSync("./extra/healthcheck-armv7");
|
||||
}
|
||||
}
|
||||
|
||||
const output = childProcess.execSync("go build -x -o ./extra/healthcheck ./extra/healthcheck.go").toString("utf8");
|
||||
console.log(output);
|
||||
|
81
extra/healthcheck.go
Normal file
81
extra/healthcheck.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* If changed, have to run `npm run build-docker-builder-go`.
|
||||
* This script should be run after a period of time (180s), because the server may need some time to prepare.
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
isFreeBSD := runtime.GOOS == "freebsd"
|
||||
|
||||
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
client := http.Client{
|
||||
Timeout: 28 * time.Second,
|
||||
}
|
||||
|
||||
sslKey := os.Getenv("UPTIME_KUMA_SSL_KEY")
|
||||
if len(sslKey) == 0 {
|
||||
sslKey = os.Getenv("SSL_KEY")
|
||||
}
|
||||
|
||||
sslCert := os.Getenv("UPTIME_KUMA_SSL_CERT")
|
||||
if len(sslCert) == 0 {
|
||||
sslCert = os.Getenv("SSL_CERT")
|
||||
}
|
||||
|
||||
hostname := os.Getenv("UPTIME_KUMA_HOST")
|
||||
if len(hostname) == 0 && !isFreeBSD {
|
||||
hostname = os.Getenv("HOST")
|
||||
}
|
||||
if len(hostname) == 0 {
|
||||
hostname = "127.0.0.1"
|
||||
}
|
||||
|
||||
port := os.Getenv("UPTIME_KUMA_PORT")
|
||||
if len(port) == 0 {
|
||||
port = os.Getenv("PORT")
|
||||
}
|
||||
if len(port) == 0 {
|
||||
port = "3001"
|
||||
}
|
||||
|
||||
protocol := ""
|
||||
if len(sslKey) != 0 && len(sslCert) != 0 {
|
||||
protocol = "https"
|
||||
} else {
|
||||
protocol = "http"
|
||||
}
|
||||
|
||||
url := protocol + "://" + hostname + ":" + port
|
||||
|
||||
log.Println("Checking " + url)
|
||||
resp, err := client.Get(url)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
_, err = ioutil.ReadAll(resp.Body)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
log.Printf("Health Check OK [Res Code: %d]\n", resp.StatusCode)
|
||||
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
* ⚠️ Deprecated: Changed to healthcheck.go, it will be deleted in the future.
|
||||
* This script should be run after a period of time (180s), because the server may need some time to prepare.
|
||||
*/
|
||||
const { FBSD } = require("../server/util-server");
|
||||
|
|
|
@ -5,7 +5,7 @@ const util = require("../src/util");
|
|||
util.polyfill();
|
||||
|
||||
const oldVersion = pkg.version;
|
||||
const newVersion = oldVersion + "-nightly";
|
||||
const newVersion = oldVersion + "-nightly-" + util.genSecret(8);
|
||||
|
||||
console.log("Old Version: " + oldVersion);
|
||||
console.log("New Version: " + newVersion);
|
||||
|
|
3350
package-lock.json
generated
3350
package-lock.json
generated
File diff suppressed because it is too large
Load diff
21
package.json
21
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.19.0-beta.0",
|
||||
"version": "1.19.4",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -22,7 +22,6 @@
|
|||
"start": "npm run start-server",
|
||||
"start-server": "node server/server.js",
|
||||
"start-server-dev": "cross-env NODE_ENV=development node server/server.js",
|
||||
"start-server-watch-dev": "cross-env NODE_ENV=development node --watch server/server.js",
|
||||
"build": "vite build --config ./config/vite.config.js",
|
||||
"test": "node test/prepare-test-server.js && npm run jest-backend",
|
||||
"test-with-build": "npm run build && npm test",
|
||||
|
@ -32,6 +31,7 @@
|
|||
"build-docker": "npm run build && npm run build-docker-debian && npm run build-docker-alpine",
|
||||
"build-docker-alpine-base": "docker buildx build -f docker/alpine-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-alpine . --push",
|
||||
"build-docker-debian-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-debian . --push",
|
||||
"build-docker-builder-go": "docker buildx build -f docker/builder-go.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:builder-go . --push",
|
||||
"build-docker-alpine": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:alpine -t louislam/uptime-kuma:1-alpine -t louislam/uptime-kuma:$VERSION-alpine --target release . --push",
|
||||
"build-docker-debian": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:$VERSION -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:$VERSION-debian --target release . --push",
|
||||
"build-docker-nightly": "npm run build && docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push",
|
||||
|
@ -39,7 +39,7 @@
|
|||
"build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain",
|
||||
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test --target pr-test . --push",
|
||||
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
||||
"setup": "git checkout 1.18.5 && npm ci --production && npm run download-dist",
|
||||
"setup": "git checkout 1.19.4 && npm ci --production && npm run download-dist",
|
||||
"download-dist": "node extra/download-dist.js",
|
||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||
"reset-password": "node extra/reset-password.js",
|
||||
|
@ -61,14 +61,17 @@
|
|||
"start-pr-test": "node extra/checkout-pr.js && npm install && npm run dev",
|
||||
"cy:test": "node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/ --e2e",
|
||||
"cy:run": "npx cypress run --browser chrome --headless --config-file ./config/cypress.config.js",
|
||||
"cypress-open": "concurrently -k -r \"node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/\" \"cypress open --config-file ./config/cypress.config.js\""
|
||||
"cy:run:unit": "npx cypress run --browser chrome --headless --config-file ./config/cypress.frontend.config.js",
|
||||
"cypress-open": "concurrently -k -r \"node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/\" \"cypress open --config-file ./config/cypress.config.js\"",
|
||||
"build-healthcheck-armv7": "cross-env GOOS=linux GOARCH=arm GOARM=7 go build -x -o ./extra/healthcheck-armv7 ./extra/healthcheck.go"
|
||||
},
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.7.0",
|
||||
"@grpc/grpc-js": "~1.7.3",
|
||||
"@louislam/ping": "~0.4.2-mod.0",
|
||||
"@louislam/sqlite3": "15.1.2",
|
||||
"args-parser": "~1.3.0",
|
||||
"axios": "~0.27.0",
|
||||
"axios-ntlm": "~1.3.0",
|
||||
"axios-ntlm": "1.3.0",
|
||||
"badge-maker": "~3.3.1",
|
||||
"bcryptjs": "~2.4.3",
|
||||
"bree": "~7.1.5",
|
||||
|
@ -90,12 +93,13 @@
|
|||
"https-proxy-agent": "~5.0.1",
|
||||
"iconv-lite": "~0.6.3",
|
||||
"jsesc": "~3.0.2",
|
||||
"jsonwebtoken": "~8.5.1",
|
||||
"jsonwebtoken": "~9.0.0",
|
||||
"jwt-decode": "~3.1.2",
|
||||
"limiter": "~2.1.0",
|
||||
"mongodb": "^4.12.0",
|
||||
"mqtt": "~4.3.7",
|
||||
"mssql": "~8.1.4",
|
||||
"mysql2": "~2.3.3",
|
||||
"node-cloudflared-tunnel": "~1.0.9",
|
||||
"node-radius-client": "~1.0.0",
|
||||
"nodemailer": "~6.6.5",
|
||||
|
@ -107,6 +111,7 @@
|
|||
"prometheus-api-metrics": "~3.2.1",
|
||||
"protobufjs": "~7.1.1",
|
||||
"redbean-node": "0.1.4",
|
||||
"redis": "~4.5.1",
|
||||
"socket.io": "~4.5.3",
|
||||
"socket.io-client": "~4.5.3",
|
||||
"socks-proxy-agent": "6.1.1",
|
||||
|
@ -134,7 +139,7 @@
|
|||
"chart.js": "~3.6.2",
|
||||
"chartjs-adapter-dayjs": "~1.0.0",
|
||||
"concurrently": "^7.1.0",
|
||||
"core-js": "~3.18.3",
|
||||
"core-js": "~3.26.1",
|
||||
"cross-env": "~7.0.3",
|
||||
"cypress": "^10.1.0",
|
||||
"delay": "^5.0.0",
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
const https = require("https");
|
||||
const http = require("http");
|
||||
const CacheableLookup = require("cacheable-lookup");
|
||||
const { Settings } = require("./settings");
|
||||
const { log } = require("../src/util");
|
||||
|
||||
class CacheableDnsHttpAgent {
|
||||
|
||||
|
@ -9,12 +11,30 @@ class CacheableDnsHttpAgent {
|
|||
static httpAgentList = {};
|
||||
static httpsAgentList = {};
|
||||
|
||||
static enable = false;
|
||||
|
||||
/**
|
||||
* Register cacheable to global agents
|
||||
* Register/Disable cacheable to global agents
|
||||
*/
|
||||
static registerGlobalAgent() {
|
||||
this.cacheable.install(http.globalAgent);
|
||||
this.cacheable.install(https.globalAgent);
|
||||
static async update() {
|
||||
log.debug("CacheableDnsHttpAgent", "update");
|
||||
let isEnable = await Settings.get("dnsCache");
|
||||
|
||||
if (isEnable !== this.enable) {
|
||||
log.debug("CacheableDnsHttpAgent", "value changed");
|
||||
|
||||
if (isEnable) {
|
||||
log.debug("CacheableDnsHttpAgent", "enable");
|
||||
this.cacheable.install(http.globalAgent);
|
||||
this.cacheable.install(https.globalAgent);
|
||||
} else {
|
||||
log.debug("CacheableDnsHttpAgent", "disable");
|
||||
this.cacheable.uninstall(http.globalAgent);
|
||||
this.cacheable.uninstall(https.globalAgent);
|
||||
}
|
||||
}
|
||||
|
||||
this.enable = isEnable;
|
||||
}
|
||||
|
||||
static install(agent) {
|
||||
|
@ -26,6 +46,10 @@ class CacheableDnsHttpAgent {
|
|||
* @return {https.Agent}
|
||||
*/
|
||||
static getHttpsAgent(agentOptions) {
|
||||
if (!this.enable) {
|
||||
return new https.Agent(agentOptions);
|
||||
}
|
||||
|
||||
let key = JSON.stringify(agentOptions);
|
||||
if (!(key in this.httpsAgentList)) {
|
||||
this.httpsAgentList[key] = new https.Agent(agentOptions);
|
||||
|
@ -39,6 +63,10 @@ class CacheableDnsHttpAgent {
|
|||
* @return {https.Agents}
|
||||
*/
|
||||
static getHttpAgent(agentOptions) {
|
||||
if (!this.enable) {
|
||||
return new http.Agent(agentOptions);
|
||||
}
|
||||
|
||||
let key = JSON.stringify(agentOptions);
|
||||
if (!(key in this.httpAgentList)) {
|
||||
this.httpAgentList[key] = new http.Agent(agentOptions);
|
||||
|
|
|
@ -25,7 +25,7 @@ exports.startInterval = () => {
|
|||
let checkBeta = await setting("checkBeta");
|
||||
|
||||
if (checkBeta && res.data.beta) {
|
||||
if (compareVersions.compare(res.data.beta, res.data.beta, ">")) {
|
||||
if (compareVersions.compare(res.data.beta, res.data.slow, ">")) {
|
||||
exports.latestVersion = res.data.beta;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -152,9 +152,6 @@ class Database {
|
|||
await R.exec("PRAGMA cache_size = -12000");
|
||||
await R.exec("PRAGMA auto_vacuum = FULL");
|
||||
|
||||
// Avoid error "SQLITE_BUSY: database is locked" by allowing SQLITE to wait up to 5 seconds to do a write
|
||||
await R.exec("PRAGMA busy_timeout = 5000");
|
||||
|
||||
// This ensures that an operating system crash or power failure will not corrupt the database.
|
||||
// FULL synchronous is very safe, but it is also slower.
|
||||
// Read more: https://sqlite.org/pragma.html#pragma_synchronous
|
||||
|
|
|
@ -25,15 +25,20 @@ const DEFAULT_KEEP_PERIOD = 180;
|
|||
parsedPeriod = DEFAULT_KEEP_PERIOD;
|
||||
}
|
||||
|
||||
log(`Clearing Data older than ${parsedPeriod} days...`);
|
||||
if (parsedPeriod < 1) {
|
||||
log(`Data deletion has been disabled as period is less than 1. Period is ${parsedPeriod} days.`);
|
||||
} else {
|
||||
|
||||
try {
|
||||
await R.exec(
|
||||
"DELETE FROM heartbeat WHERE time < DATETIME('now', '-' || ? || ' days') ",
|
||||
[ parsedPeriod ]
|
||||
);
|
||||
} catch (e) {
|
||||
log(`Failed to clear old data: ${e.message}`);
|
||||
log(`Clearing Data older than ${parsedPeriod} days...`);
|
||||
|
||||
try {
|
||||
await R.exec(
|
||||
"DELETE FROM heartbeat WHERE time < DATETIME('now', '-' || ? || ' days') ",
|
||||
[ parsedPeriod ]
|
||||
);
|
||||
} catch (e) {
|
||||
log(`Failed to clear old data: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
exit();
|
||||
|
|
|
@ -188,13 +188,13 @@ class Maintenance extends BeanModel {
|
|||
*/
|
||||
static getActiveMaintenanceSQLCondition() {
|
||||
return `
|
||||
|
||||
(maintenance_timeslot.start_date <= DATETIME('now')
|
||||
AND maintenance_timeslot.end_date >= DATETIME('now')
|
||||
AND maintenance.active = 1)
|
||||
OR
|
||||
(maintenance.strategy = 'manual' AND active = 1)
|
||||
|
||||
(
|
||||
(maintenance_timeslot.start_date <= DATETIME('now')
|
||||
AND maintenance_timeslot.end_date >= DATETIME('now')
|
||||
AND maintenance.active = 1)
|
||||
OR
|
||||
(maintenance.strategy = 'manual' AND active = 1)
|
||||
)
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -204,10 +204,12 @@ class Maintenance extends BeanModel {
|
|||
*/
|
||||
static getActiveAndFutureMaintenanceSQLCondition() {
|
||||
return `
|
||||
((maintenance_timeslot.end_date >= DATETIME('now')
|
||||
AND maintenance.active = 1)
|
||||
OR
|
||||
(maintenance.strategy = 'manual' AND active = 1))
|
||||
(
|
||||
((maintenance_timeslot.end_date >= DATETIME('now')
|
||||
AND maintenance.active = 1)
|
||||
OR
|
||||
(maintenance.strategy = 'manual' AND active = 1))
|
||||
)
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@ const https = require("https");
|
|||
const dayjs = require("dayjs");
|
||||
const axios = require("axios");
|
||||
const { Prometheus } = require("../prometheus");
|
||||
const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, TimeLogger } = require("../../src/util");
|
||||
const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mongodbPing, mqttAsync, setSetting, httpNtlm, radius, grpcQuery } = require("../util-server");
|
||||
const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, TimeLogger, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND } = require("../../src/util");
|
||||
const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, mqttAsync, setSetting, httpNtlm, radius, grpcQuery,
|
||||
redisPingAsync, mongodbPing,
|
||||
} = require("../util-server");
|
||||
const { R } = require("redbean-node");
|
||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||
const { Notification } = require("../notification");
|
||||
|
@ -15,6 +17,7 @@ const { UptimeKumaServer } = require("../uptime-kuma-server");
|
|||
const { CacheableDnsHttpAgent } = require("../cacheable-dns-http-agent");
|
||||
const { DockerHost } = require("../docker");
|
||||
const Maintenance = require("./maintenance");
|
||||
const { UptimeCacheList } = require("../uptime-cache-list");
|
||||
|
||||
/**
|
||||
* status:
|
||||
|
@ -89,32 +92,23 @@ class Monitor extends BeanModel {
|
|||
dns_resolve_type: this.dns_resolve_type,
|
||||
dns_resolve_server: this.dns_resolve_server,
|
||||
dns_last_result: this.dns_last_result,
|
||||
pushToken: this.pushToken,
|
||||
docker_container: this.docker_container,
|
||||
docker_host: this.docker_host,
|
||||
proxyId: this.proxy_id,
|
||||
notificationIDList,
|
||||
tags: tags,
|
||||
maintenance: await Monitor.isUnderMaintenance(this.id),
|
||||
mqttUsername: this.mqttUsername,
|
||||
mqttPassword: this.mqttPassword,
|
||||
mqttTopic: this.mqttTopic,
|
||||
mqttSuccessMessage: this.mqttSuccessMessage,
|
||||
databaseConnectionString: this.databaseConnectionString,
|
||||
databaseQuery: this.databaseQuery,
|
||||
authMethod: this.authMethod,
|
||||
authWorkstation: this.authWorkstation,
|
||||
authDomain: this.authDomain,
|
||||
grpcUrl: this.grpcUrl,
|
||||
grpcProtobuf: this.grpcProtobuf,
|
||||
grpcMethod: this.grpcMethod,
|
||||
grpcServiceName: this.grpcServiceName,
|
||||
grpcEnableTls: this.getGrpcEnableTls(),
|
||||
radiusUsername: this.radiusUsername,
|
||||
radiusPassword: this.radiusPassword,
|
||||
radiusCalledStationId: this.radiusCalledStationId,
|
||||
radiusCallingStationId: this.radiusCallingStationId,
|
||||
radiusSecret: this.radiusSecret,
|
||||
};
|
||||
|
||||
if (includeSensitiveData) {
|
||||
|
@ -127,9 +121,18 @@ class Monitor extends BeanModel {
|
|||
basic_auth_user: this.basic_auth_user,
|
||||
basic_auth_pass: this.basic_auth_pass,
|
||||
pushToken: this.pushToken,
|
||||
databaseConnectionString: this.databaseConnectionString,
|
||||
radiusUsername: this.radiusUsername,
|
||||
radiusPassword: this.radiusPassword,
|
||||
radiusSecret: this.radiusSecret,
|
||||
mqttUsername: this.mqttUsername,
|
||||
mqttPassword: this.mqttPassword,
|
||||
authWorkstation: this.authWorkstation,
|
||||
authDomain: this.authDomain,
|
||||
};
|
||||
}
|
||||
|
||||
data.includeSensitiveData = includeSensitiveData;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -267,6 +270,7 @@ class Monitor extends BeanModel {
|
|||
|
||||
log.debug("monitor", `[${this.name}] Prepare Options for axios`);
|
||||
|
||||
// Axios Options
|
||||
const options = {
|
||||
url: this.url,
|
||||
method: (this.method || "get").toLowerCase(),
|
||||
|
@ -305,20 +309,8 @@ class Monitor extends BeanModel {
|
|||
log.debug("monitor", `[${this.name}] Axios Options: ${JSON.stringify(options)}`);
|
||||
log.debug("monitor", `[${this.name}] Axios Request`);
|
||||
|
||||
let res;
|
||||
if (this.auth_method === "ntlm") {
|
||||
options.httpsAgent.keepAlive = true;
|
||||
|
||||
res = await httpNtlm(options, {
|
||||
username: this.basic_auth_user,
|
||||
password: this.basic_auth_pass,
|
||||
domain: this.authDomain,
|
||||
workstation: this.authWorkstation ? this.authWorkstation : undefined
|
||||
});
|
||||
|
||||
} else {
|
||||
res = await axios.request(options);
|
||||
}
|
||||
// Make Request
|
||||
let res = await this.makeAxiosRequest(options);
|
||||
|
||||
bean.msg = `${res.status} - ${res.statusText}`;
|
||||
bean.ping = dayjs().valueOf() - startTime;
|
||||
|
@ -524,7 +516,9 @@ class Monitor extends BeanModel {
|
|||
let res = await axios.request(options);
|
||||
if (res.data.State.Running) {
|
||||
bean.status = UP;
|
||||
bean.msg = "";
|
||||
bean.msg = res.data.State.Status;
|
||||
} else {
|
||||
throw Error("Container State is " + res.data.State.Status);
|
||||
}
|
||||
} else if (this.type === "mqtt") {
|
||||
bean.msg = await mqttAsync(this.hostname, this.mqttTopic, this.mqttSuccessMessage, {
|
||||
|
@ -558,7 +552,7 @@ class Monitor extends BeanModel {
|
|||
log.debug("monitor:", `gRPC response: ${JSON.stringify(response)}`);
|
||||
let responseData = response.data;
|
||||
if (responseData.length > 50) {
|
||||
responseData = response.substring(0, 47) + "...";
|
||||
responseData = responseData.toString().substring(0, 47) + "...";
|
||||
}
|
||||
if (response.code !== 1) {
|
||||
bean.status = DOWN;
|
||||
|
@ -578,6 +572,14 @@ class Monitor extends BeanModel {
|
|||
|
||||
await postgresQuery(this.databaseConnectionString, this.databaseQuery);
|
||||
|
||||
bean.msg = "";
|
||||
bean.status = UP;
|
||||
bean.ping = dayjs().valueOf() - startTime;
|
||||
} else if (this.type === "mysql") {
|
||||
let startTime = dayjs().valueOf();
|
||||
|
||||
await mysqlQuery(this.databaseConnectionString, this.databaseQuery);
|
||||
|
||||
bean.msg = "";
|
||||
bean.status = UP;
|
||||
bean.ping = dayjs().valueOf() - startTime;
|
||||
|
@ -589,6 +591,7 @@ class Monitor extends BeanModel {
|
|||
bean.msg = "";
|
||||
bean.status = UP;
|
||||
bean.ping = dayjs().valueOf() - startTime;
|
||||
|
||||
} else if (this.type === "radius") {
|
||||
let startTime = dayjs().valueOf();
|
||||
|
||||
|
@ -625,6 +628,12 @@ class Monitor extends BeanModel {
|
|||
}
|
||||
}
|
||||
bean.ping = dayjs().valueOf() - startTime;
|
||||
} else if (this.type === "redis") {
|
||||
let startTime = dayjs().valueOf();
|
||||
|
||||
bean.msg = await redisPingAsync(this.databaseConnectionString);
|
||||
bean.status = UP;
|
||||
bean.ping = dayjs().valueOf() - startTime;
|
||||
} else {
|
||||
bean.msg = "Unknown Monitor Type";
|
||||
bean.status = PENDING;
|
||||
|
@ -709,6 +718,7 @@ class Monitor extends BeanModel {
|
|||
}
|
||||
|
||||
log.debug("monitor", `[${this.name}] Send to socket`);
|
||||
UptimeCacheList.clearCache(this.id);
|
||||
io.to(this.user_id).emit("heartbeat", bean.toJSON());
|
||||
Monitor.sendStats(io, this.id, this.user_id);
|
||||
|
||||
|
@ -755,6 +765,40 @@ class Monitor extends BeanModel {
|
|||
}
|
||||
}
|
||||
|
||||
async makeAxiosRequest(options, finalCall = false) {
|
||||
try {
|
||||
let res;
|
||||
if (this.auth_method === "ntlm") {
|
||||
options.httpsAgent.keepAlive = true;
|
||||
|
||||
res = await httpNtlm(options, {
|
||||
username: this.basic_auth_user,
|
||||
password: this.basic_auth_pass,
|
||||
domain: this.authDomain,
|
||||
workstation: this.authWorkstation ? this.authWorkstation : undefined
|
||||
});
|
||||
|
||||
} else {
|
||||
res = await axios.request(options);
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
// Fix #2253
|
||||
// Read more: https://stackoverflow.com/questions/1759956/curl-error-18-transfer-closed-with-outstanding-read-data-remaining
|
||||
if (!finalCall && typeof e.message === "string" && e.message.includes("maxContentLength size of -1 exceeded")) {
|
||||
log.debug("monitor", "makeAxiosRequest with gzip");
|
||||
options.headers["Accept-Encoding"] = "gzip, deflate";
|
||||
return this.makeAxiosRequest(options, true);
|
||||
} else {
|
||||
if (typeof e.message === "string" && e.message.includes("maxContentLength size of -1 exceeded")) {
|
||||
e.message = "response timeout: incomplete response within a interval";
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Stop monitor */
|
||||
stop() {
|
||||
clearTimeout(this.heartbeatInterval);
|
||||
|
@ -893,7 +937,15 @@ class Monitor extends BeanModel {
|
|||
* @param {number} duration Hours
|
||||
* @param {number} monitorID ID of monitor to calculate
|
||||
*/
|
||||
static async calcUptime(duration, monitorID) {
|
||||
static async calcUptime(duration, monitorID, forceNoCache = false) {
|
||||
|
||||
if (!forceNoCache) {
|
||||
let cachedUptime = UptimeCacheList.getUptime(monitorID, duration);
|
||||
if (cachedUptime != null) {
|
||||
return cachedUptime;
|
||||
}
|
||||
}
|
||||
|
||||
const timeLogger = new TimeLogger();
|
||||
|
||||
const startTime = R.isoDateTime(dayjs.utc().subtract(duration, "hour"));
|
||||
|
@ -952,6 +1004,9 @@ class Monitor extends BeanModel {
|
|||
}
|
||||
}
|
||||
|
||||
// Cache
|
||||
UptimeCacheList.addUptime(monitorID, duration, uptime);
|
||||
|
||||
return uptime;
|
||||
}
|
||||
|
||||
|
@ -1051,7 +1106,13 @@ class Monitor extends BeanModel {
|
|||
|
||||
for (let notification of notificationList) {
|
||||
try {
|
||||
await Notification.send(JSON.parse(notification.config), msg, await monitor.toJSON(false), bean.toJSON());
|
||||
// Prevent if the msg is undefined, notifications such as Discord cannot send out.
|
||||
const heartbeatJSON = bean.toJSON();
|
||||
if (!heartbeatJSON["msg"]) {
|
||||
heartbeatJSON["msg"] = "N/A";
|
||||
}
|
||||
|
||||
await Notification.send(JSON.parse(notification.config), msg, await monitor.toJSON(false), heartbeatJSON);
|
||||
} catch (e) {
|
||||
log.error("monitor", "Cannot send notification to " + notification.name);
|
||||
log.error("monitor", e);
|
||||
|
@ -1184,6 +1245,15 @@ class Monitor extends BeanModel {
|
|||
LIMIT 1`, [ monitorID ]);
|
||||
return maintenance.count !== 0;
|
||||
}
|
||||
|
||||
validate() {
|
||||
if (this.interval > MAX_INTERVAL_SECOND) {
|
||||
throw new Error(`Interval cannot be more than ${MAX_INTERVAL_SECOND} seconds`);
|
||||
}
|
||||
if (this.interval < MIN_INTERVAL_SECOND) {
|
||||
throw new Error(`Interval cannot be less than ${MIN_INTERVAL_SECOND} seconds`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Monitor;
|
||||
|
|
|
@ -281,12 +281,14 @@ class StatusPage extends BeanModel {
|
|||
|
||||
let activeCondition = Maintenance.getActiveMaintenanceSQLCondition();
|
||||
let maintenanceBeanList = R.convertToBeans("maintenance", await R.getAll(`
|
||||
SELECT maintenance.*
|
||||
FROM maintenance, maintenance_status_page msp, maintenance_timeslot
|
||||
WHERE msp.maintenance_id = maintenance.id
|
||||
AND maintenance_timeslot.maintenance_id = maintenance.id
|
||||
AND msp.status_page_id = ?
|
||||
AND ${activeCondition}
|
||||
SELECT DISTINCT maintenance.*
|
||||
FROM maintenance
|
||||
JOIN maintenance_status_page
|
||||
ON maintenance_status_page.maintenance_id = maintenance.id
|
||||
AND maintenance_status_page.status_page_id = ?
|
||||
LEFT JOIN maintenance_timeslot
|
||||
ON maintenance_timeslot.maintenance_id = maintenance.id
|
||||
WHERE ${activeCondition}
|
||||
ORDER BY maintenance.end_date
|
||||
`, [ statusPageId ]));
|
||||
|
||||
|
|
20
server/modules/dayjs/plugin/timezone.d.ts
vendored
Normal file
20
server/modules/dayjs/plugin/timezone.d.ts
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { PluginFunc, ConfigType } from 'dayjs'
|
||||
|
||||
declare const plugin: PluginFunc
|
||||
export = plugin
|
||||
|
||||
declare module 'dayjs' {
|
||||
interface Dayjs {
|
||||
tz(timezone?: string, keepLocalTime?: boolean): Dayjs
|
||||
offsetName(type?: 'short' | 'long'): string | undefined
|
||||
}
|
||||
|
||||
interface DayjsTimezone {
|
||||
(date: ConfigType, timezone?: string): Dayjs
|
||||
(date: ConfigType, format: string, timezone?: string): Dayjs
|
||||
guess(): string
|
||||
setDefault(timezone?: string): void
|
||||
}
|
||||
|
||||
const tz: DayjsTimezone
|
||||
}
|
115
server/modules/dayjs/plugin/timezone.js
Normal file
115
server/modules/dayjs/plugin/timezone.js
Normal file
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* Copy from node_modules/dayjs/plugin/timezone.js
|
||||
* Try to fix https://github.com/louislam/uptime-kuma/issues/2318
|
||||
* Source: https://github.com/iamkun/dayjs/tree/dev/src/plugin/utc
|
||||
* License: MIT
|
||||
*/
|
||||
!function (t, e) {
|
||||
// eslint-disable-next-line no-undef
|
||||
typeof exports == "object" && typeof module != "undefined" ? module.exports = e() : typeof define == "function" && define.amd ? define(e) : (t = typeof globalThis != "undefined" ? globalThis : t || self).dayjs_plugin_timezone = e();
|
||||
}(this, (function () {
|
||||
"use strict";
|
||||
let t = {
|
||||
year: 0,
|
||||
month: 1,
|
||||
day: 2,
|
||||
hour: 3,
|
||||
minute: 4,
|
||||
second: 5
|
||||
};
|
||||
let e = {};
|
||||
return function (n, i, o) {
|
||||
let r;
|
||||
let a = function (t, n, i) {
|
||||
void 0 === i && (i = {});
|
||||
let o = new Date(t);
|
||||
let r = function (t, n) {
|
||||
void 0 === n && (n = {});
|
||||
let i = n.timeZoneName || "short";
|
||||
let o = t + "|" + i;
|
||||
let r = e[o];
|
||||
return r || (r = new Intl.DateTimeFormat("en-US", {
|
||||
hour12: !1,
|
||||
timeZone: t,
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
timeZoneName: i
|
||||
}), e[o] = r), r;
|
||||
}(n, i);
|
||||
return r.formatToParts(o);
|
||||
};
|
||||
let u = function (e, n) {
|
||||
let i = a(e, n);
|
||||
let r = [];
|
||||
let u = 0;
|
||||
for (; u < i.length; u += 1) {
|
||||
let f = i[u];
|
||||
let s = f.type;
|
||||
let m = f.value;
|
||||
let c = t[s];
|
||||
c >= 0 && (r[c] = parseInt(m, 10));
|
||||
}
|
||||
let d = r[3];
|
||||
let l = d === 24 ? 0 : d;
|
||||
let v = r[0] + "-" + r[1] + "-" + r[2] + " " + l + ":" + r[4] + ":" + r[5] + ":000";
|
||||
let h = +e;
|
||||
return (o.utc(v).valueOf() - (h -= h % 1e3)) / 6e4;
|
||||
};
|
||||
let f = i.prototype;
|
||||
f.tz = function (t, e) {
|
||||
void 0 === t && (t = r);
|
||||
let n = this.utcOffset();
|
||||
let i = this.toDate();
|
||||
let a = i.toLocaleString("en-US", { timeZone: t }).replace("\u202f", " ");
|
||||
let u = Math.round((i - new Date(a)) / 1e3 / 60);
|
||||
let f = o(a).$set("millisecond", this.$ms).utcOffset(15 * -Math.round(i.getTimezoneOffset() / 15) - u, !0);
|
||||
if (e) {
|
||||
let s = f.utcOffset();
|
||||
f = f.add(n - s, "minute");
|
||||
}
|
||||
return f.$x.$timezone = t, f;
|
||||
}, f.offsetName = function (t) {
|
||||
let e = this.$x.$timezone || o.tz.guess();
|
||||
let n = a(this.valueOf(), e, { timeZoneName: t }).find((function (t) {
|
||||
return t.type.toLowerCase() === "timezonename";
|
||||
}));
|
||||
return n && n.value;
|
||||
};
|
||||
let s = f.startOf;
|
||||
f.startOf = function (t, e) {
|
||||
if (!this.$x || !this.$x.$timezone) {
|
||||
return s.call(this, t, e);
|
||||
}
|
||||
let n = o(this.format("YYYY-MM-DD HH:mm:ss:SSS"));
|
||||
return s.call(n, t, e).tz(this.$x.$timezone, !0);
|
||||
}, o.tz = function (t, e, n) {
|
||||
let i = n && e;
|
||||
let a = n || e || r;
|
||||
let f = u(+o(), a);
|
||||
if (typeof t != "string") {
|
||||
return o(t).tz(a);
|
||||
}
|
||||
let s = function (t, e, n) {
|
||||
let i = t - 60 * e * 1e3;
|
||||
let o = u(i, n);
|
||||
if (e === o) {
|
||||
return [ i, e ];
|
||||
}
|
||||
let r = u(i -= 60 * (o - e) * 1e3, n);
|
||||
return o === r ? [ i, o ] : [ t - 60 * Math.min(o, r) * 1e3, Math.max(o, r) ];
|
||||
}(o.utc(t, i).valueOf(), f, a);
|
||||
let m = s[0];
|
||||
let c = s[1];
|
||||
let d = o(m).utcOffset(c);
|
||||
return d.$x.$timezone = a, d;
|
||||
}, o.tz.guess = function () {
|
||||
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
}, o.tz.setDefault = function (t) {
|
||||
r = t;
|
||||
};
|
||||
};
|
||||
}));
|
|
@ -64,7 +64,7 @@ class Discord extends NotificationProvider {
|
|||
},
|
||||
{
|
||||
name: "Error",
|
||||
value: heartbeatJSON["msg"],
|
||||
value: heartbeatJSON["msg"] == null ? "N/A" : heartbeatJSON["msg"],
|
||||
},
|
||||
],
|
||||
}],
|
||||
|
@ -91,7 +91,7 @@ class Discord extends NotificationProvider {
|
|||
},
|
||||
{
|
||||
name: monitorJSON["type"] === "push" ? "Service Type" : "Service URL",
|
||||
value: monitorJSON["type"] === "push" ? "Heartbeat" : address.startsWith("http") ? "[Visit Service](" + address + ")" : address,
|
||||
value: monitorJSON["type"] === "push" ? "Heartbeat" : address,
|
||||
},
|
||||
{
|
||||
name: "Time (UTC)",
|
||||
|
|
31
server/notification-providers/kook.js
Normal file
31
server/notification-providers/kook.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
|
||||
class Kook extends NotificationProvider {
|
||||
|
||||
name = "Kook";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
let url = "https://www.kookapp.cn/api/v3/message/create";
|
||||
let data = {
|
||||
target_id: notification.kookGuildID,
|
||||
content: msg,
|
||||
};
|
||||
let config = {
|
||||
headers: {
|
||||
"Authorization": "Bot " + notification.kookBotToken,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
};
|
||||
try {
|
||||
await axios.post(url, data, config);
|
||||
return okMsg;
|
||||
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Kook;
|
|
@ -10,7 +10,7 @@ class Pushover extends NotificationProvider {
|
|||
let pushoverlink = "https://api.pushover.net/1/messages.json";
|
||||
|
||||
let data = {
|
||||
"message": "<b>Uptime Kuma Alert</b>\n\n<b>Message</b>:" + msg,
|
||||
"message": "<b>Message</b>:" + msg,
|
||||
"user": notification.pushoveruserkey,
|
||||
"token": notification.pushoverapptoken,
|
||||
"sound": notification.pushoversounds,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const { setSettings, setting } = require("../util-server");
|
||||
const { getMonitorRelativeURL } = require("../../src/util");
|
||||
const { getMonitorRelativeURL, UP } = require("../../src/util");
|
||||
|
||||
class Slack extends NotificationProvider {
|
||||
|
||||
|
@ -46,24 +46,31 @@ class Slack extends NotificationProvider {
|
|||
"channel": notification.slackchannel,
|
||||
"username": notification.slackusername,
|
||||
"icon_emoji": notification.slackiconemo,
|
||||
"blocks": [{
|
||||
"type": "header",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Uptime Kuma Alert",
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "section",
|
||||
"fields": [{
|
||||
"type": "mrkdwn",
|
||||
"text": "*Message*\n" + msg,
|
||||
},
|
||||
"attachments": [
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
"text": "*Time (UTC)*\n" + time,
|
||||
}],
|
||||
}],
|
||||
"color": (heartbeatJSON["status"] === UP) ? "#2eb886" : "#e01e5a",
|
||||
"blocks": [
|
||||
{
|
||||
"type": "header",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Uptime Kuma Alert",
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "section",
|
||||
"fields": [{
|
||||
"type": "mrkdwn",
|
||||
"text": "*Message*\n" + msg,
|
||||
},
|
||||
{
|
||||
"type": "mrkdwn",
|
||||
"text": "*Time (UTC)*\n" + time,
|
||||
}],
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
if (notification.slackbutton) {
|
||||
|
@ -74,17 +81,19 @@ class Slack extends NotificationProvider {
|
|||
|
||||
// Button
|
||||
if (baseURL) {
|
||||
data.blocks.push({
|
||||
"type": "actions",
|
||||
"elements": [{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Visit Uptime Kuma",
|
||||
},
|
||||
"value": "Uptime-Kuma",
|
||||
"url": baseURL + getMonitorRelativeURL(monitorJSON.id),
|
||||
}],
|
||||
data.attachments.forEach(element => {
|
||||
element.blocks.push({
|
||||
"type": "actions",
|
||||
"elements": [{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Visit Uptime Kuma",
|
||||
},
|
||||
"value": "Uptime-Kuma",
|
||||
"url": baseURL + getMonitorRelativeURL(monitorJSON.id),
|
||||
}],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -16,20 +16,29 @@ class Webhook extends NotificationProvider {
|
|||
msg,
|
||||
};
|
||||
let finalData;
|
||||
let config = {};
|
||||
let config = {
|
||||
headers: {}
|
||||
};
|
||||
|
||||
if (notification.webhookContentType === "form-data") {
|
||||
finalData = new FormData();
|
||||
finalData.append("data", JSON.stringify(data));
|
||||
|
||||
config = {
|
||||
headers: finalData.getHeaders(),
|
||||
};
|
||||
|
||||
config.headers = finalData.getHeaders();
|
||||
} else {
|
||||
finalData = data;
|
||||
}
|
||||
|
||||
if (notification.webhookAdditionalHeaders) {
|
||||
try {
|
||||
config.headers = {
|
||||
...config.headers,
|
||||
...JSON.parse(notification.webhookAdditionalHeaders)
|
||||
};
|
||||
} catch (err) {
|
||||
throw "Additional Headers is not a valid JSON";
|
||||
}
|
||||
}
|
||||
|
||||
await axios.post(notification.webhookURL, finalData, config);
|
||||
return okMsg;
|
||||
|
||||
|
|
116
server/notification-providers/zoho-cliq.js
Normal file
116
server/notification-providers/zoho-cliq.js
Normal file
|
@ -0,0 +1,116 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
|
||||
class ZohoCliq extends NotificationProvider {
|
||||
|
||||
name = "ZohoCliq";
|
||||
|
||||
/**
|
||||
* Generate the message to send
|
||||
* @param {const} status The status constant
|
||||
* @param {string} monitorName Name of monitor
|
||||
* @returns {string}
|
||||
*/
|
||||
_statusMessageFactory = (status, monitorName) => {
|
||||
if (status === DOWN) {
|
||||
return `🔴 Application [${monitorName}] went down\n`;
|
||||
} else if (status === UP) {
|
||||
return `✅ Application [${monitorName}] is back online\n`;
|
||||
}
|
||||
return "Notification\n";
|
||||
};
|
||||
|
||||
/**
|
||||
* Send the notification
|
||||
* @param {string} webhookUrl URL to send the request to
|
||||
* @param {Array} payload Payload generated by _notificationPayloadFactory
|
||||
*/
|
||||
_sendNotification = async (webhookUrl, payload) => {
|
||||
await axios.post(webhookUrl, { text: payload.join("\n") });
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate payload for notification
|
||||
* @param {const} status The status of the monitor
|
||||
* @param {string} monitorMessage Message to send
|
||||
* @param {string} monitorName Name of monitor affected
|
||||
* @param {string} monitorUrl URL of monitor affected
|
||||
* @returns {Array}
|
||||
*/
|
||||
_notificationPayloadFactory = ({
|
||||
status,
|
||||
monitorMessage,
|
||||
monitorName,
|
||||
monitorUrl,
|
||||
}) => {
|
||||
const payload = [];
|
||||
payload.push("### Uptime Kuma\n");
|
||||
payload.push(this._statusMessageFactory(status, monitorName));
|
||||
payload.push(`*Description:* ${monitorMessage}`);
|
||||
|
||||
if (monitorName) {
|
||||
payload.push(`*Monitor:* ${monitorName}`);
|
||||
}
|
||||
|
||||
if (monitorUrl && monitorUrl !== "https://") {
|
||||
payload.push(`*URL:* [${monitorUrl}](${monitorUrl})`);
|
||||
}
|
||||
|
||||
return payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a general notification
|
||||
* @param {string} webhookUrl URL to send request to
|
||||
* @param {string} msg Message to send
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
_handleGeneralNotification = (webhookUrl, msg) => {
|
||||
const payload = this._notificationPayloadFactory({
|
||||
monitorMessage: msg
|
||||
});
|
||||
|
||||
return this._sendNotification(webhookUrl, payload);
|
||||
};
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
if (heartbeatJSON == null) {
|
||||
await this._handleGeneralNotification(notification.webhookUrl, msg);
|
||||
return okMsg;
|
||||
}
|
||||
|
||||
let url;
|
||||
switch (monitorJSON["type"]) {
|
||||
case "http":
|
||||
case "keywork":
|
||||
url = monitorJSON["url"];
|
||||
break;
|
||||
case "docker":
|
||||
url = monitorJSON["docker_host"];
|
||||
break;
|
||||
default:
|
||||
url = monitorJSON["hostname"];
|
||||
break;
|
||||
}
|
||||
|
||||
const payload = this._notificationPayloadFactory({
|
||||
monitorMessage: heartbeatJSON.msg,
|
||||
monitorName: monitorJSON.name,
|
||||
monitorUrl: url,
|
||||
status: heartbeatJSON.status
|
||||
});
|
||||
|
||||
await this._sendNotification(notification.webhookUrl, payload);
|
||||
return okMsg;
|
||||
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ZohoCliq;
|
|
@ -14,6 +14,7 @@ const GoogleChat = require("./notification-providers/google-chat");
|
|||
const Gorush = require("./notification-providers/gorush");
|
||||
const Gotify = require("./notification-providers/gotify");
|
||||
const HomeAssistant = require("./notification-providers/home-assistant");
|
||||
const Kook = require("./notification-providers/kook");
|
||||
const Line = require("./notification-providers/line");
|
||||
const LineNotify = require("./notification-providers/linenotify");
|
||||
const LunaSea = require("./notification-providers/lunasea");
|
||||
|
@ -44,6 +45,7 @@ const WeCom = require("./notification-providers/wecom");
|
|||
const GoAlert = require("./notification-providers/goalert");
|
||||
const SMSManager = require("./notification-providers/smsmanager");
|
||||
const ServerChan = require("./notification-providers/serverchan");
|
||||
const ZohoCliq = require("./notification-providers/zoho-cliq");
|
||||
|
||||
class Notification {
|
||||
|
||||
|
@ -70,6 +72,7 @@ class Notification {
|
|||
new Gorush(),
|
||||
new Gotify(),
|
||||
new HomeAssistant(),
|
||||
new Kook(),
|
||||
new Line(),
|
||||
new LineNotify(),
|
||||
new LunaSea(),
|
||||
|
@ -100,6 +103,7 @@ class Notification {
|
|||
new Webhook(),
|
||||
new WeCom(),
|
||||
new GoAlert(),
|
||||
new ZohoCliq()
|
||||
];
|
||||
|
||||
for (let item of list) {
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
// https://github.com/ben-bradley/ping-lite/blob/master/ping-lite.js
|
||||
// Fixed on Windows
|
||||
const net = require("net");
|
||||
const spawn = require("child_process").spawn;
|
||||
const events = require("events");
|
||||
const fs = require("fs");
|
||||
const util = require("./util-server");
|
||||
|
||||
module.exports = Ping;
|
||||
|
||||
/**
|
||||
* Constructor for ping class
|
||||
* @param {string} host Host to ping
|
||||
* @param {object} [options] Options for the ping command
|
||||
* @param {array|string} [options.args] - Arguments to pass to the ping command
|
||||
*/
|
||||
function Ping(host, options) {
|
||||
if (!host) {
|
||||
throw new Error("You must specify a host to ping!");
|
||||
}
|
||||
|
||||
this._host = host;
|
||||
this._options = options = (options || {});
|
||||
|
||||
events.EventEmitter.call(this);
|
||||
|
||||
const timeout = 10;
|
||||
|
||||
if (util.WIN) {
|
||||
this._bin = "c:/windows/system32/ping.exe";
|
||||
this._args = (options.args) ? options.args : [ "-n", "1", "-w", timeout * 1000, host ];
|
||||
this._regmatch = /[><=]([0-9.]+?)ms/;
|
||||
|
||||
} else if (util.LIN) {
|
||||
this._bin = "/bin/ping";
|
||||
|
||||
const defaultArgs = [ "-n", "-w", timeout, "-c", "1", host ];
|
||||
|
||||
if (net.isIPv6(host) || options.ipv6) {
|
||||
defaultArgs.unshift("-6");
|
||||
}
|
||||
|
||||
this._args = (options.args) ? options.args : defaultArgs;
|
||||
this._regmatch = /=([0-9.]+?) ms/;
|
||||
|
||||
} else if (util.MAC) {
|
||||
|
||||
if (net.isIPv6(host) || options.ipv6) {
|
||||
this._bin = "/sbin/ping6";
|
||||
} else {
|
||||
this._bin = "/sbin/ping";
|
||||
}
|
||||
|
||||
this._args = (options.args) ? options.args : [ "-n", "-t", timeout, "-c", "1", host ];
|
||||
this._regmatch = /=([0-9.]+?) ms/;
|
||||
|
||||
} else if (util.BSD) {
|
||||
this._bin = "/sbin/ping";
|
||||
|
||||
const defaultArgs = [ "-n", "-t", timeout, "-c", "1", host ];
|
||||
|
||||
if (net.isIPv6(host) || options.ipv6) {
|
||||
defaultArgs.unshift("-6");
|
||||
}
|
||||
|
||||
this._args = (options.args) ? options.args : defaultArgs;
|
||||
this._regmatch = /=([0-9.]+?) ms/;
|
||||
|
||||
} else {
|
||||
throw new Error("Could not detect your ping binary.");
|
||||
}
|
||||
|
||||
if (!fs.existsSync(this._bin)) {
|
||||
throw new Error("Could not detect " + this._bin + " on your system");
|
||||
}
|
||||
|
||||
this._i = 0;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Ping.prototype.__proto__ = events.EventEmitter.prototype;
|
||||
|
||||
/**
|
||||
* Callback for send
|
||||
* @callback pingCB
|
||||
* @param {any} err Any error encountered
|
||||
* @param {number} ms Ping time in ms
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send a ping
|
||||
* @param {pingCB} callback Callback to call with results
|
||||
*/
|
||||
Ping.prototype.send = function (callback) {
|
||||
let self = this;
|
||||
callback = callback || function (err, ms) {
|
||||
if (err) {
|
||||
return self.emit("error", err);
|
||||
}
|
||||
return self.emit("result", ms);
|
||||
};
|
||||
|
||||
let _ended;
|
||||
let _exited;
|
||||
let _errored;
|
||||
|
||||
this._ping = spawn(this._bin, this._args, { windowsHide: true }); // spawn the binary
|
||||
|
||||
this._ping.on("error", function (err) { // handle binary errors
|
||||
_errored = true;
|
||||
callback(err);
|
||||
});
|
||||
|
||||
this._ping.stdout.on("data", function (data) { // log stdout
|
||||
if (util.WIN) {
|
||||
data = convertOutput(data);
|
||||
}
|
||||
this._stdout = (this._stdout || "") + data;
|
||||
});
|
||||
|
||||
this._ping.stdout.on("end", function () {
|
||||
_ended = true;
|
||||
if (_exited && !_errored) {
|
||||
onEnd.call(self._ping);
|
||||
}
|
||||
});
|
||||
|
||||
this._ping.stderr.on("data", function (data) { // log stderr
|
||||
if (util.WIN) {
|
||||
data = convertOutput(data);
|
||||
}
|
||||
this._stderr = (this._stderr || "") + data;
|
||||
});
|
||||
|
||||
this._ping.on("exit", function (code) { // handle complete
|
||||
_exited = true;
|
||||
if (_ended && !_errored) {
|
||||
onEnd.call(self._ping);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Function} callback
|
||||
*
|
||||
* Generated by Trelent
|
||||
*/
|
||||
function onEnd() {
|
||||
let stdout = this.stdout._stdout;
|
||||
let stderr = this.stderr._stderr;
|
||||
let ms;
|
||||
|
||||
if (stderr) {
|
||||
return callback(new Error(stderr));
|
||||
}
|
||||
|
||||
if (!stdout) {
|
||||
return callback(new Error("No stdout detected"));
|
||||
}
|
||||
|
||||
ms = stdout.match(self._regmatch); // parse out the ##ms response
|
||||
ms = (ms && ms[1]) ? Number(ms[1]) : ms;
|
||||
|
||||
callback(null, ms, stdout);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Ping every interval
|
||||
* @param {pingCB} callback Callback to call with results
|
||||
*/
|
||||
Ping.prototype.start = function (callback) {
|
||||
let self = this;
|
||||
this._i = setInterval(function () {
|
||||
self.send(callback);
|
||||
}, (self._options.interval || 5000));
|
||||
self.send(callback);
|
||||
};
|
||||
|
||||
/** Stop sending pings */
|
||||
Ping.prototype.stop = function () {
|
||||
clearInterval(this._i);
|
||||
};
|
||||
|
||||
/**
|
||||
* Try to convert to UTF-8 for Windows, as the ping's output on Windows is not UTF-8 and could be in other languages
|
||||
* Thank @pemassi
|
||||
* https://github.com/louislam/uptime-kuma/issues/570#issuecomment-941984094
|
||||
* @param {any} data
|
||||
* @returns {string}
|
||||
*/
|
||||
function convertOutput(data) {
|
||||
if (util.WIN) {
|
||||
if (data) {
|
||||
return util.convertToUTF8(data);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
|
@ -7,7 +7,7 @@ const { UptimeKumaServer } = require("./uptime-kuma-server");
|
|||
|
||||
class Proxy {
|
||||
|
||||
static SUPPORTED_PROXY_PROTOCOLS = [ "http", "https", "socks", "socks5", "socks4" ];
|
||||
static SUPPORTED_PROXY_PROTOCOLS = [ "http", "https", "socks", "socks5", "socks5h", "socks4" ];
|
||||
|
||||
/**
|
||||
* Saves and updates given proxy entity
|
||||
|
@ -126,6 +126,7 @@ class Proxy {
|
|||
break;
|
||||
case "socks":
|
||||
case "socks5":
|
||||
case "socks5h":
|
||||
case "socks4":
|
||||
agent = new SocksProxyAgent({
|
||||
...httpAgentOptions,
|
||||
|
|
|
@ -8,7 +8,7 @@ console.log("Welcome to Uptime Kuma");
|
|||
// As the log function need to use dayjs, it should be very top
|
||||
const dayjs = require("dayjs");
|
||||
dayjs.extend(require("dayjs/plugin/utc"));
|
||||
dayjs.extend(require("dayjs/plugin/timezone"));
|
||||
dayjs.extend(require("./modules/dayjs/plugin/timezone"));
|
||||
dayjs.extend(require("dayjs/plugin/customParseFormat"));
|
||||
|
||||
// Check Node.js Version
|
||||
|
@ -135,7 +135,9 @@ const { cloudflaredSocketHandler, autoStart: cloudflaredAutoStart, stop: cloudfl
|
|||
const { proxySocketHandler } = require("./socket-handlers/proxy-socket-handler");
|
||||
const { dockerSocketHandler } = require("./socket-handlers/docker-socket-handler");
|
||||
const { maintenanceSocketHandler } = require("./socket-handlers/maintenance-socket-handler");
|
||||
const { generalSocketHandler } = require("./socket-handlers/general-socket-handler");
|
||||
const { Settings } = require("./settings");
|
||||
const { CacheableDnsHttpAgent } = require("./cacheable-dns-http-agent");
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
|
@ -203,6 +205,7 @@ let needSetup = false;
|
|||
|
||||
if (isDev) {
|
||||
app.post("/test-webhook", async (request, response) => {
|
||||
log.debug("test", request.headers);
|
||||
log.debug("test", request.body);
|
||||
response.send("OK");
|
||||
});
|
||||
|
@ -631,6 +634,9 @@ let needSetup = false;
|
|||
|
||||
bean.import(monitor);
|
||||
bean.user_id = socket.userID;
|
||||
|
||||
bean.validate();
|
||||
|
||||
await R.store(bean);
|
||||
|
||||
await updateMonitorNotification(bean.id, notificationIDList);
|
||||
|
@ -708,6 +714,7 @@ let needSetup = false;
|
|||
bean.authDomain = monitor.authDomain;
|
||||
bean.grpcUrl = monitor.grpcUrl;
|
||||
bean.grpcProtobuf = monitor.grpcProtobuf;
|
||||
bean.grpcServiceName = monitor.grpcServiceName;
|
||||
bean.grpcMethod = monitor.grpcMethod;
|
||||
bean.grpcBody = monitor.grpcBody;
|
||||
bean.grpcMetadata = monitor.grpcMetadata;
|
||||
|
@ -718,6 +725,8 @@ let needSetup = false;
|
|||
bean.radiusCallingStationId = monitor.radiusCallingStationId;
|
||||
bean.radiusSecret = monitor.radiusSecret;
|
||||
|
||||
bean.validate();
|
||||
|
||||
await R.store(bean);
|
||||
|
||||
await updateMonitorNotification(bean.id, monitor.notificationIDList);
|
||||
|
@ -932,13 +941,21 @@ let needSetup = false;
|
|||
try {
|
||||
checkLogin(socket);
|
||||
|
||||
let bean = await R.findOne("monitor", " id = ? ", [ tag.id ]);
|
||||
let bean = await R.findOne("tag", " id = ? ", [ tag.id ]);
|
||||
if (bean == null) {
|
||||
callback({
|
||||
ok: false,
|
||||
msg: "Tag not found",
|
||||
});
|
||||
return;
|
||||
}
|
||||
bean.name = tag.name;
|
||||
bean.color = tag.color;
|
||||
await R.store(bean);
|
||||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Saved",
|
||||
tag: await bean.toJSON(),
|
||||
});
|
||||
|
||||
|
@ -1108,6 +1125,8 @@ let needSetup = false;
|
|||
await setSettings("general", data);
|
||||
server.entryPage = data.entryPage;
|
||||
|
||||
await CacheableDnsHttpAgent.update();
|
||||
|
||||
// Also need to apply timezone globally
|
||||
if (data.serverTimezone) {
|
||||
await server.setTimezone(data.serverTimezone);
|
||||
|
@ -1479,6 +1498,7 @@ let needSetup = false;
|
|||
proxySocketHandler(socket);
|
||||
dockerSocketHandler(socket);
|
||||
maintenanceSocketHandler(socket);
|
||||
generalSocketHandler(socket, server);
|
||||
|
||||
log.debug("server", "added all socket handlers");
|
||||
|
||||
|
@ -1601,6 +1621,13 @@ async function afterLogin(socket, user) {
|
|||
for (let monitorID in monitorList) {
|
||||
await Monitor.sendStats(io, monitorID, user.id);
|
||||
}
|
||||
|
||||
// Set server timezone from client browser if not set
|
||||
// It should be run once only
|
||||
if (! await Settings.get("initServerTimezone")) {
|
||||
log.debug("server", "emit initServerTimezone");
|
||||
socket.emit("initServerTimezone");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1739,6 +1766,7 @@ async function shutdownFunction(signal) {
|
|||
|
||||
stopBackgroundJobs();
|
||||
await cloudflaredStop();
|
||||
Settings.stopCacheCleaner();
|
||||
}
|
||||
|
||||
/** Final function called before application exits */
|
||||
|
|
|
@ -158,6 +158,13 @@ class Settings {
|
|||
delete Settings.cacheList[key];
|
||||
}
|
||||
}
|
||||
|
||||
static stopCacheCleaner() {
|
||||
if (Settings.cacheCleaner) {
|
||||
clearInterval(Settings.cacheCleaner);
|
||||
Settings.cacheCleaner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const { checkLogin, setSetting, setting, doubleCheckPassword } = require("../util-server");
|
||||
const { CloudflaredTunnel } = require("node-cloudflared-tunnel");
|
||||
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||
const { log } = require("../../src/util");
|
||||
const io = UptimeKumaServer.getInstance().io;
|
||||
|
||||
const prefix = "cloudflared_";
|
||||
|
@ -107,7 +108,7 @@ module.exports.autoStart = async (token) => {
|
|||
|
||||
/** Stop cloudflared */
|
||||
module.exports.stop = async () => {
|
||||
console.log("Stop cloudflared");
|
||||
log.info("cloudflared", "Stop cloudflared");
|
||||
if (cloudflared) {
|
||||
cloudflared.stop();
|
||||
}
|
||||
|
|
20
server/socket-handlers/general-socket-handler.js
Normal file
20
server/socket-handlers/general-socket-handler.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
const { log } = require("../../src/util");
|
||||
const { Settings } = require("../settings");
|
||||
const { sendInfo } = require("../client");
|
||||
const { checkLogin } = require("../util-server");
|
||||
|
||||
module.exports.generalSocketHandler = (socket, server) => {
|
||||
|
||||
socket.on("initServerTimezone", async (timezone) => {
|
||||
try {
|
||||
checkLogin(socket);
|
||||
log.debug("generalSocketHandler", "Timezone: " + timezone);
|
||||
await Settings.set("initServerTimezone", true);
|
||||
await server.setTimezone(timezone);
|
||||
await sendInfo(socket);
|
||||
} catch (e) {
|
||||
log.warn("initServerTimezone", e.message);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
|
@ -244,6 +244,8 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||
socket.userID,
|
||||
]);
|
||||
|
||||
apicache.clear();
|
||||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Deleted Successfully.",
|
||||
|
@ -269,6 +271,8 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||
maintenanceID,
|
||||
]);
|
||||
|
||||
apicache.clear();
|
||||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Paused Successfully.",
|
||||
|
@ -294,6 +298,8 @@ module.exports.maintenanceSocketHandler = (socket) => {
|
|||
maintenanceID,
|
||||
]);
|
||||
|
||||
apicache.clear();
|
||||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Resume Successfully",
|
||||
|
|
39
server/uptime-cache-list.js
Normal file
39
server/uptime-cache-list.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
const { log } = require("../src/util");
|
||||
class UptimeCacheList {
|
||||
/**
|
||||
* list[monitorID][duration]
|
||||
*/
|
||||
static list = {};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param monitorID
|
||||
* @param duration
|
||||
* @return number
|
||||
*/
|
||||
static getUptime(monitorID, duration) {
|
||||
if (UptimeCacheList.list[monitorID] && UptimeCacheList.list[monitorID][duration]) {
|
||||
log.debug("UptimeCacheList", "getUptime: " + monitorID + " " + duration);
|
||||
return UptimeCacheList.list[monitorID][duration];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static addUptime(monitorID, duration, uptime) {
|
||||
log.debug("UptimeCacheList", "addUptime: " + monitorID + " " + duration);
|
||||
if (!UptimeCacheList.list[monitorID]) {
|
||||
UptimeCacheList.list[monitorID] = {};
|
||||
}
|
||||
UptimeCacheList.list[monitorID][duration] = uptime;
|
||||
}
|
||||
|
||||
static clearCache(monitorID) {
|
||||
log.debug("UptimeCacheList", "clearCache: " + monitorID);
|
||||
delete UptimeCacheList.list[monitorID];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
UptimeCacheList,
|
||||
};
|
|
@ -83,12 +83,12 @@ class UptimeKumaServer {
|
|||
}
|
||||
}
|
||||
|
||||
CacheableDnsHttpAgent.registerGlobalAgent();
|
||||
|
||||
this.io = new Server(this.httpServer);
|
||||
}
|
||||
|
||||
async initAfterDatabaseReady() {
|
||||
await CacheableDnsHttpAgent.update();
|
||||
|
||||
process.env.TZ = await this.getTimezone();
|
||||
dayjs.tz.setDefault(process.env.TZ);
|
||||
log.debug("DEBUG", "Timezone: " + process.env.TZ);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const tcpp = require("tcp-ping");
|
||||
const Ping = require("./ping-lite");
|
||||
const ping = require("@louislam/ping");
|
||||
const { R } = require("redbean-node");
|
||||
const { log, genSecret } = require("../src/util");
|
||||
const passwordHash = require("./password-hash");
|
||||
|
@ -13,12 +13,14 @@ const { badgeConstants } = require("./config");
|
|||
const mssql = require("mssql");
|
||||
const { Client } = require("pg");
|
||||
const postgresConParse = require("pg-connection-string").parse;
|
||||
const mysql = require("mysql2");
|
||||
const { MongoClient } = require("mongodb");
|
||||
const { NtlmClient } = require("axios-ntlm");
|
||||
const { Settings } = require("./settings");
|
||||
const grpc = require("@grpc/grpc-js");
|
||||
const protojs = require("protobufjs");
|
||||
const radiusClient = require("node-radius-client");
|
||||
const redis = require("redis");
|
||||
const {
|
||||
dictionaries: {
|
||||
rfc2865: { file, attributes },
|
||||
|
@ -26,12 +28,7 @@ const {
|
|||
} = require("node-radius-utils");
|
||||
const dayjs = require("dayjs");
|
||||
|
||||
// From ping-lite
|
||||
exports.WIN = /^win/.test(process.platform);
|
||||
exports.LIN = /^linux/.test(process.platform);
|
||||
exports.MAC = /^darwin/.test(process.platform);
|
||||
exports.FBSD = /^freebsd/.test(process.platform);
|
||||
exports.BSD = /bsd$/.test(process.platform);
|
||||
const isWindows = process.platform === /^win/.test(process.platform);
|
||||
|
||||
/**
|
||||
* Init or reset JWT secret
|
||||
|
@ -105,18 +102,23 @@ exports.ping = async (hostname) => {
|
|||
*/
|
||||
exports.pingAsync = function (hostname, ipv6 = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const ping = new Ping(hostname, {
|
||||
ipv6
|
||||
});
|
||||
|
||||
ping.send(function (err, ms, stdout) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else if (ms === null) {
|
||||
reject(new Error(stdout));
|
||||
ping.promise.probe(hostname, {
|
||||
v6: ipv6,
|
||||
min_reply: 1,
|
||||
timeout: 10,
|
||||
}).then((res) => {
|
||||
// If ping failed, it will set field to unknown
|
||||
if (res.alive) {
|
||||
resolve(res.time);
|
||||
} else {
|
||||
resolve(Math.round(ms));
|
||||
if (isWindows) {
|
||||
reject(new Error(exports.convertToUTF8(res.output)));
|
||||
} else {
|
||||
reject(new Error(res.output));
|
||||
}
|
||||
}
|
||||
}).catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -248,19 +250,19 @@ exports.dnsResolve = function (hostname, resolverServer, resolverPort, rrtype) {
|
|||
* @param {string} query The query to validate the database with
|
||||
* @returns {Promise<(string[]|Object[]|Object)>}
|
||||
*/
|
||||
exports.mssqlQuery = function (connectionString, query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
mssql.connect(connectionString).then(pool => {
|
||||
return pool.request()
|
||||
.query(query);
|
||||
}).then(result => {
|
||||
resolve(result);
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
}).finally(() => {
|
||||
mssql.close();
|
||||
});
|
||||
});
|
||||
exports.mssqlQuery = async function (connectionString, query) {
|
||||
let pool;
|
||||
try {
|
||||
pool = new mssql.ConnectionPool(connectionString);
|
||||
await pool.connect();
|
||||
await pool.request().query(query);
|
||||
pool.close();
|
||||
} catch (e) {
|
||||
if (pool) {
|
||||
pool.close();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -295,6 +297,28 @@ exports.postgresQuery = function (connectionString, query) {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a query on MySQL/MariaDB
|
||||
* @param {string} connectionString The database connection string
|
||||
* @param {string} query The query to validate the database with
|
||||
* @returns {Promise<(string[]|Object[]|Object)>}
|
||||
*/
|
||||
exports.mysqlQuery = function (connectionString, query) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const connection = mysql.createConnection(connectionString);
|
||||
connection.promise().query(query)
|
||||
.then(res => {
|
||||
resolve(res);
|
||||
})
|
||||
.catch(err => {
|
||||
reject(err);
|
||||
})
|
||||
.finally(() => {
|
||||
connection.end();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect to and Ping a MongoDB database
|
||||
* @param {string} connectionString The database connection string
|
||||
|
@ -356,6 +380,30 @@ exports.radius = function (
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Redis server ping
|
||||
* @param {string} dsn The redis connection string
|
||||
*/
|
||||
exports.redisPingAsync = function (dsn) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const client = redis.createClient({
|
||||
url: dsn,
|
||||
});
|
||||
client.on("error", (err) => {
|
||||
reject(err);
|
||||
});
|
||||
client.connect().then(() => {
|
||||
client.ping().then((res, err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve value of setting based on key
|
||||
* @param {string} key Key of setting to retrieve
|
||||
|
@ -472,6 +520,10 @@ const parseCertificateInfo = function (info) {
|
|||
* @returns {Object} Object containing certificate information
|
||||
*/
|
||||
exports.checkCertificate = function (res) {
|
||||
if (!res.request.res.socket) {
|
||||
throw new Error("No socket found");
|
||||
}
|
||||
|
||||
const info = res.request.res.socket.getPeerCertificate(true);
|
||||
const valid = res.request.res.socket.authorized || false;
|
||||
|
||||
|
@ -776,22 +828,31 @@ module.exports.grpcQuery = async (options) => {
|
|||
cb);
|
||||
}, false, false);
|
||||
return new Promise((resolve, _) => {
|
||||
return grpcService[`${grpcMethod}`](JSON.parse(grpcBody), function (err, response) {
|
||||
const responseData = JSON.stringify(response);
|
||||
if (err) {
|
||||
return resolve({
|
||||
code: err.code,
|
||||
errorMessage: err.details,
|
||||
data: ""
|
||||
});
|
||||
} else {
|
||||
log.debug("monitor:", `gRPC response: ${response}`);
|
||||
return resolve({
|
||||
code: 1,
|
||||
errorMessage: "",
|
||||
data: responseData
|
||||
});
|
||||
}
|
||||
});
|
||||
try {
|
||||
return grpcService[`${grpcMethod}`](JSON.parse(grpcBody), function (err, response) {
|
||||
const responseData = JSON.stringify(response);
|
||||
if (err) {
|
||||
return resolve({
|
||||
code: err.code,
|
||||
errorMessage: err.details,
|
||||
data: ""
|
||||
});
|
||||
} else {
|
||||
log.debug("monitor:", `gRPC response: ${JSON.stringify(response)}`);
|
||||
return resolve({
|
||||
code: 1,
|
||||
errorMessage: "",
|
||||
data: responseData
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
return resolve({
|
||||
code: -1,
|
||||
errorMessage: `Error ${err}. Please review your gRPC configuration option. The service name must not include package name value, and the method name must follow camelCase format`,
|
||||
data: ""
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
|
|
@ -2,4 +2,8 @@ html[lang='fa'] {
|
|||
#app {
|
||||
font-family: 'IRANSans', 'Iranian Sans','B Nazanin', 'Tahoma', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, segoe ui, Roboto, helvetica neue, Arial, noto sans, sans-serif, apple color emoji, segoe ui emoji, segoe ui symbol, noto color emoji;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul.multiselect__content {
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ export default {
|
|||
emits: [ "added" ],
|
||||
data() {
|
||||
return {
|
||||
model: null,
|
||||
modal: null,
|
||||
processing: false,
|
||||
id: null,
|
||||
connectionTypes: [ "socket", "tcp" ],
|
||||
|
|
|
@ -206,6 +206,16 @@ export default {
|
|||
.search-icon {
|
||||
padding: 10px;
|
||||
color: #c0c0c0;
|
||||
|
||||
// Clear filter button (X)
|
||||
svg[data-icon="times"] {
|
||||
cursor: pointer;
|
||||
transition: all ease-in-out 0.1s;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<option value="http">HTTP</option>
|
||||
<option value="socks">SOCKS</option>
|
||||
<option value="socks5">SOCKS v5</option>
|
||||
<option value="socks5h">SOCKS v5 (+DNS)</option>
|
||||
<option value="socks4">SOCKS v4</option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -41,7 +41,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
displayText() {
|
||||
if (this.item.value === "") {
|
||||
if (this.item.value === "" || this.item.value === undefined) {
|
||||
return this.item.name;
|
||||
} else {
|
||||
return `${this.item.name}: ${this.item.value}`;
|
||||
|
|
376
src/components/TagEditDialog.vue
Normal file
376
src/components/TagEditDialog.vue
Normal file
|
@ -0,0 +1,376 @@
|
|||
<template>
|
||||
<form @submit.prevent="submit">
|
||||
<div ref="modal" class="modal fade" tabindex="-1" data-bs-backdrop="static">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 id="exampleModalLabel" class="modal-title">
|
||||
{{ $t("Edit Tag") }}
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label for="tag-name" class="form-label">{{ $t("Name") }}</label>
|
||||
<input id="tag-name" v-model="tag.name" type="text" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="tag-color" class="form-label">{{ $t("Color") }}</label>
|
||||
<div class="d-flex">
|
||||
<div class="col-8 pe-1">
|
||||
<vue-multiselect
|
||||
v-model="selectedColor"
|
||||
:options="colorOptions"
|
||||
:multiple="false"
|
||||
:searchable="true"
|
||||
:placeholder="$t('color')"
|
||||
track-by="color"
|
||||
label="name"
|
||||
select-label=""
|
||||
deselect-label=""
|
||||
>
|
||||
<template #option="{ option }">
|
||||
<div
|
||||
class="mx-2 py-1 px-3 rounded d-inline-flex"
|
||||
style="height: 24px; color: white;"
|
||||
:style="{ backgroundColor: option.color + ' !important' }"
|
||||
>
|
||||
<span>{{ option.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #singleLabel="{ option }">
|
||||
<div
|
||||
class="py-1 px-3 rounded d-inline-flex"
|
||||
style="height: 24px; color: white;"
|
||||
:style="{ backgroundColor: option.color + ' !important' }"
|
||||
>
|
||||
<span>{{ option.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</vue-multiselect>
|
||||
</div>
|
||||
<div class="col-4 ps-1">
|
||||
<input id="tag-color-hex" v-model="tag.color" type="text" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="tag-monitors" class="form-label">{{ $tc("Monitor", selectedMonitors.length) }}</label>
|
||||
<div class="tag-monitors-list">
|
||||
<router-link v-for="monitor in selectedMonitors" :key="monitor.id" class="d-flex align-items-center justify-content-between text-decoration-none tag-monitors-list-row py-2 px-3" :to="monitorURL(monitor.id)" @click="modal.hide()">
|
||||
<span>{{ monitor.name }}</span>
|
||||
<button type="button" class="btn-rm-monitor btn btn-outline-danger ms-2 py-1" @click.stop.prevent="removeMonitor(monitor.id)">
|
||||
<font-awesome-icon class="" icon="times" />
|
||||
</button>
|
||||
</router-link>
|
||||
</div>
|
||||
<div v-if="allMonitorList.length > 0" class="pt-3 px-3">
|
||||
<label class="form-label">{{ $t("Add a monitor") }}:</label>
|
||||
<select v-model="selectedAddMonitor" class="form-control">
|
||||
<option v-for="monitor in allMonitorList" :key="monitor.id" :value="monitor">{{ monitor.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button v-if="tag" type="button" class="btn btn-danger" :disabled="processing" @click="deleteConfirm">
|
||||
{{ $t("Delete") }}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" :disabled="processing">
|
||||
<div v-if="processing" class="spinner-border spinner-border-sm me-1"></div>
|
||||
{{ $t("Save") }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<Confirm ref="confirmDelete" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="deleteTag">
|
||||
{{ $t("confirmDeleteTagMsg") }}
|
||||
</Confirm>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Modal } from "bootstrap";
|
||||
import Confirm from "./Confirm.vue";
|
||||
import VueMultiselect from "vue-multiselect";
|
||||
import { colorOptions } from "../util-frontend";
|
||||
import { useToast } from "vue-toastification";
|
||||
import { getMonitorRelativeURL } from "../util.ts";
|
||||
const toast = useToast();
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VueMultiselect,
|
||||
Confirm,
|
||||
},
|
||||
props: {
|
||||
updated: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
modal: null,
|
||||
processing: false,
|
||||
selectedColor: {
|
||||
name: null,
|
||||
color: null,
|
||||
},
|
||||
tag: {
|
||||
id: null,
|
||||
name: "",
|
||||
color: "",
|
||||
// Do not set default value here, please scroll to show()
|
||||
},
|
||||
monitors: [],
|
||||
removingMonitor: [],
|
||||
addingMonitor: [],
|
||||
selectedAddMonitor: null,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
colorOptions() {
|
||||
if (!colorOptions(this).find(option => option.color === this.tag.color)) {
|
||||
return colorOptions(this).concat(
|
||||
{
|
||||
name: "custom",
|
||||
color: this.tag.color
|
||||
});
|
||||
} else {
|
||||
return colorOptions(this);
|
||||
}
|
||||
},
|
||||
selectedMonitors() {
|
||||
return this.monitors
|
||||
.concat(Object.values(this.$root.monitorList).filter(monitor => this.addingMonitor.includes(monitor.id)))
|
||||
.filter(monitor => !this.removingMonitor.includes(monitor.id));
|
||||
},
|
||||
allMonitorList() {
|
||||
return Object.values(this.$root.monitorList).filter(monitor => !this.selectedMonitors.includes(monitor));
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
// Set color option to "Custom" when a unknown color is entered
|
||||
"tag.color"(to, from) {
|
||||
if (colorOptions(this).find(x => x.color === to) == null) {
|
||||
this.selectedColor.name = this.$t("Custom");
|
||||
this.selectedColor.color = to;
|
||||
}
|
||||
},
|
||||
selectedColor(to, from) {
|
||||
if (to != null) {
|
||||
this.tag.color = to.color;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Selected a monitor and add to the list.
|
||||
*/
|
||||
selectedAddMonitor(monitor) {
|
||||
if (monitor) {
|
||||
if (this.removingMonitor.includes(monitor.id)) {
|
||||
this.removingMonitor = this.removingMonitor.filter(id => id !== monitor.id);
|
||||
} else {
|
||||
this.addingMonitor.push(monitor.id);
|
||||
}
|
||||
this.selectedAddMonitor = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.modal = new Modal(this.$refs.modal);
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Show confirmation for deleting a tag
|
||||
*/
|
||||
deleteConfirm() {
|
||||
this.$refs.confirmDelete.show();
|
||||
},
|
||||
|
||||
/**
|
||||
* Load tag information for display in the edit dialog
|
||||
* @param {Object} tag tag object to edit
|
||||
* @returns {void}
|
||||
*/
|
||||
show(tag) {
|
||||
if (tag) {
|
||||
this.selectedColor = this.colorOptions.find(x => x.color === tag.color) ?? {
|
||||
name: this.$t("Custom"),
|
||||
color: tag.color
|
||||
};
|
||||
this.tag.id = tag.id;
|
||||
this.tag.name = tag.name;
|
||||
this.tag.color = tag.color;
|
||||
this.monitors = this.monitorsByTag(tag.id);
|
||||
this.removingMonitor = [];
|
||||
this.addingMonitor = [];
|
||||
this.selectedAddMonitor = null;
|
||||
}
|
||||
|
||||
this.modal.show();
|
||||
},
|
||||
|
||||
/**
|
||||
* Submit tag and monitorTag changes to server
|
||||
* @returns {void}
|
||||
*/
|
||||
async submit() {
|
||||
this.processing = true;
|
||||
let editResult = true;
|
||||
|
||||
for (let addId of this.addingMonitor) {
|
||||
await this.addMonitorTagAsync(this.tag.id, addId, "").then((res) => {
|
||||
if (!res.ok) {
|
||||
toast.error(res.msg);
|
||||
editResult = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (let removeId of this.removingMonitor) {
|
||||
this.monitors.find(monitor => monitor.id === removeId)?.tags.forEach(async (monitorTag) => {
|
||||
await this.deleteMonitorTagAsync(this.tag.id, removeId, monitorTag.value).then((res) => {
|
||||
if (!res.ok) {
|
||||
toast.error(res.msg);
|
||||
editResult = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.$root.getSocket().emit("editTag", this.tag, (res) => {
|
||||
this.$root.toastRes(res);
|
||||
this.processing = false;
|
||||
|
||||
if (res.ok && editResult) {
|
||||
this.updated();
|
||||
this.modal.hide();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete the editing tag from server
|
||||
* @returns {void}
|
||||
*/
|
||||
deleteTag() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("deleteTag", this.tag.id, (res) => {
|
||||
this.$root.toastRes(res);
|
||||
this.processing = false;
|
||||
|
||||
if (res.ok) {
|
||||
this.updated();
|
||||
this.modal.hide();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a monitor from the monitors list locally
|
||||
* @param {number} id id of the tag to remove
|
||||
* @returns {void}
|
||||
*/
|
||||
removeMonitor(id) {
|
||||
if (this.addingMonitor.includes(id)) {
|
||||
this.addingMonitor = this.addingMonitor.filter(x => x !== id);
|
||||
} else {
|
||||
this.removingMonitor.push(id);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get monitors which has a specific tag locally
|
||||
* @param {number} tagId id of the tag to filter
|
||||
* @returns {Object[]} list of monitors which has a specific tag
|
||||
*/
|
||||
monitorsByTag(tagId) {
|
||||
return Object.values(this.$root.monitorList).filter((monitor) => {
|
||||
return monitor.tags.find(monitorTag => monitorTag.tag_id === tagId);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get URL of monitor
|
||||
* @param {number} id ID of monitor
|
||||
* @returns {string} Relative URL of monitor
|
||||
*/
|
||||
monitorURL(id) {
|
||||
return getMonitorRelativeURL(id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a tag to a monitor asynchronously
|
||||
* @param {number} tagId ID of tag to add
|
||||
* @param {number} monitorId ID of monitor to add tag to
|
||||
* @param {string} value Value of tag
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
addMonitorTagAsync(tagId, monitorId, value) {
|
||||
return new Promise((resolve) => {
|
||||
this.$root.getSocket().emit("addMonitorTag", tagId, monitorId, value, resolve);
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Delete a tag from a monitor asynchronously
|
||||
* @param {number} tagId ID of tag to remove
|
||||
* @param {number} monitorId ID of monitor to remove tag from
|
||||
* @param {string} value Value of tag
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
deleteMonitorTagAsync(tagId, monitorId, value) {
|
||||
return new Promise((resolve) => {
|
||||
this.$root.getSocket().emit("deleteMonitorTag", tagId, monitorId, value, resolve);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../assets/vars.scss";
|
||||
|
||||
.dark {
|
||||
.modal-dialog .form-text, .modal-dialog p {
|
||||
color: $dark-font-color;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-rm-monitor {
|
||||
padding-left: 11px;
|
||||
padding-right: 11px;
|
||||
}
|
||||
|
||||
.tag-monitors-list {
|
||||
max-height: 40vh;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.tag-monitors-list .tag-monitors-list-row {
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
|
||||
|
||||
.dark & {
|
||||
border-bottom: 1px solid $dark-border-color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $highlight-white;
|
||||
}
|
||||
|
||||
.dark &:hover {
|
||||
background-color: $dark-bg2;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -130,6 +130,7 @@
|
|||
import { Modal } from "bootstrap";
|
||||
import VueMultiselect from "vue-multiselect";
|
||||
import { useToast } from "vue-toastification";
|
||||
import { colorOptions } from "../util-frontend";
|
||||
import Tag from "../components/Tag.vue";
|
||||
const toast = useToast();
|
||||
|
||||
|
@ -176,24 +177,7 @@ export default {
|
|||
return this.preSelectedTags.concat(this.newTags).filter(tag => !this.deleteTags.find(monitorTag => monitorTag.id === tag.id));
|
||||
},
|
||||
colorOptions() {
|
||||
return [
|
||||
{ name: this.$t("Gray"),
|
||||
color: "#4B5563" },
|
||||
{ name: this.$t("Red"),
|
||||
color: "#DC2626" },
|
||||
{ name: this.$t("Orange"),
|
||||
color: "#D97706" },
|
||||
{ name: this.$t("Green"),
|
||||
color: "#059669" },
|
||||
{ name: this.$t("Blue"),
|
||||
color: "#2563EB" },
|
||||
{ name: this.$t("Indigo"),
|
||||
color: "#4F46E5" },
|
||||
{ name: this.$t("Purple"),
|
||||
color: "#7C3AED" },
|
||||
{ name: this.$t("Pink"),
|
||||
color: "#DB2777" },
|
||||
];
|
||||
return colorOptions(this);
|
||||
},
|
||||
validateDraftTag() {
|
||||
let nameInvalid = false;
|
||||
|
@ -204,7 +188,7 @@ export default {
|
|||
nameInvalid = false;
|
||||
valueInvalid = false;
|
||||
invalid = false;
|
||||
} else if (this.existingTags.filter(tag => tag.name === this.newDraftTag.name).length > 0) {
|
||||
} else if (this.existingTags.filter(tag => tag.name === this.newDraftTag.name).length > 0 && this.newDraftTag.select == null) {
|
||||
// Try to create new tag with existing name
|
||||
nameInvalid = true;
|
||||
invalid = true;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<span :class="className" :title="24 + $t('-hour')">{{ uptime }}</span>
|
||||
<span :class="className" :title="title">{{ uptime }}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -75,6 +75,14 @@ export default {
|
|||
|
||||
return "";
|
||||
},
|
||||
|
||||
title() {
|
||||
if (this.type === "720") {
|
||||
return `30${this.$t("-day")}`;
|
||||
}
|
||||
|
||||
return `24${this.$t("-hour")}`;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
36
src/components/notifications/Kook.vue
Normal file
36
src/components/notifications/Kook.vue
Normal file
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="kook-bot-token" class="form-label">{{ $t("Bot Token") }}</label>
|
||||
<HiddenInput id="kook-bot-token" v-model="$parent.notification.kookBotToken" :required="true" autocomplete="new-password"></HiddenInput>
|
||||
<i18n-t tag="div" keypath="wayToGetKookBotToken" class="form-text">
|
||||
<a href="https://developer.kookapp.cn/bot" target="_blank">https://developer.kookapp.cn/bot</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="kook-guild-id" class="form-label">{{ $t("Guild ID") }}</label>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<input id="kook-guild-id" v-model="$parent.notification.kookGuildID" type="text" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="form-text">
|
||||
<p style="margin-top: 8px;">
|
||||
{{ $t("wayToGetKookGuildID") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
|
||||
<a href="https://developer.kookapp.cn" target="_blank">https://developer.kookapp.cn</a>
|
||||
</i18n-t>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="smsmanager-key" class="form-label">API Key</label>
|
||||
<label for="smsmanager-key" class="form-label">{{ $t("API Key") }}</label>
|
||||
<div class="form-text">
|
||||
{{ $t("SMSManager API Docs") }}
|
||||
<a href="https://smsmanager.cz/api/http#send" target="_blank">{{ $t("here") }}</a>
|
||||
|
@ -17,9 +17,9 @@
|
|||
<div class="mb-3">
|
||||
<label for="smsmanager-messageType" class="form-label">{{ $t("Gateway Type") }}</label>
|
||||
<select id="smsmanager-messageType" v-model="$parent.notification.messageType" class="form-select">
|
||||
<option value="economy">Economy</option>
|
||||
<option value="lowcost">Lowcost</option>
|
||||
<option value="high" selected>High</option>
|
||||
<option value="economy">{{ $t("Economy") }}</option>
|
||||
<option value="lowcost">{{ $t("Lowcost") }}</option>
|
||||
<option value="high" selected>{{ $t("High") }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
|
|
|
@ -1,22 +1,32 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="webhook-url" class="form-label">{{ $t("Post URL") }}</label>
|
||||
<input id="webhook-url" v-model="$parent.notification.webhookURL" type="url" pattern="https?://.+" class="form-control" required>
|
||||
<input
|
||||
id="webhook-url"
|
||||
v-model="$parent.notification.webhookURL"
|
||||
type="url"
|
||||
pattern="https?://.+"
|
||||
class="form-control"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="webhook-content-type" class="form-label">{{ $t("Content Type") }}</label>
|
||||
<select id="webhook-content-type" v-model="$parent.notification.webhookContentType" class="form-select" required>
|
||||
<option value="json">
|
||||
application/json
|
||||
</option>
|
||||
<option value="form-data">
|
||||
multipart/form-data
|
||||
</option>
|
||||
<label for="webhook-content-type" class="form-label">{{
|
||||
$t("Content Type")
|
||||
}}</label>
|
||||
<select
|
||||
id="webhook-content-type"
|
||||
v-model="$parent.notification.webhookContentType"
|
||||
class="form-select"
|
||||
required
|
||||
>
|
||||
<option value="json">application/json</option>
|
||||
<option value="form-data">multipart/form-data</option>
|
||||
</select>
|
||||
|
||||
<div class="form-text">
|
||||
<p>{{ $t("webhookJsonDesc", ["\"application/json\""]) }}</p>
|
||||
<p>{{ $t("webhookJsonDesc", ['"application/json"']) }}</p>
|
||||
<i18n-t tag="p" keypath="webhookFormDataDesc">
|
||||
<template #multipart>"multipart/form-data"</template>
|
||||
<template #decodeFunction>
|
||||
|
@ -25,4 +35,44 @@
|
|||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<i18n-t
|
||||
tag="label"
|
||||
class="form-label"
|
||||
for="additionalHeaders"
|
||||
keypath="webhookAdditionalHeadersTitle"
|
||||
>
|
||||
</i18n-t>
|
||||
<textarea
|
||||
id="additionalHeaders"
|
||||
v-model="$parent.notification.webhookAdditionalHeaders"
|
||||
class="form-control"
|
||||
:placeholder="headersPlaceholder"
|
||||
></textarea>
|
||||
<div class="form-text">
|
||||
<i18n-t tag="p" keypath="webhookAdditionalHeadersDesc"> </i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
headersPlaceholder() {
|
||||
return this.$t("Example:", [
|
||||
`
|
||||
{
|
||||
"HeaderName": "HeaderValue"
|
||||
}`,
|
||||
]);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
textarea {
|
||||
min-height: 200px;
|
||||
}
|
||||
</style>
|
||||
|
|
18
src/components/notifications/ZohoCliq.vue
Normal file
18
src/components/notifications/ZohoCliq.vue
Normal file
|
@ -0,0 +1,18 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="zcliq-webhookurl" class="form-label">{{ $t("Webhook URL") }}</label>
|
||||
<input
|
||||
id="zcliq-webhookurl"
|
||||
v-model="$parent.notification.webhookUrl"
|
||||
type="text"
|
||||
class="form-control"
|
||||
required
|
||||
/>
|
||||
<i18n-t tag="div" keypath="wayToGetZohoCliqURL" class="form-text">
|
||||
<a
|
||||
href="https://www.zoho.com/cliq/help/platform/webhook-tokens.html"
|
||||
target="_blank"
|
||||
>{{ $t("here") }}</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</template>
|
|
@ -12,6 +12,7 @@ import GoogleChat from "./GoogleChat.vue";
|
|||
import Gorush from "./Gorush.vue";
|
||||
import Gotify from "./Gotify.vue";
|
||||
import HomeAssistant from "./HomeAssistant.vue";
|
||||
import Kook from "./Kook.vue";
|
||||
import Line from "./Line.vue";
|
||||
import LineNotify from "./LineNotify.vue";
|
||||
import LunaSea from "./LunaSea.vue";
|
||||
|
@ -42,6 +43,7 @@ import Telegram from "./Telegram.vue";
|
|||
import Webhook from "./Webhook.vue";
|
||||
import WeCom from "./WeCom.vue";
|
||||
import GoAlert from "./GoAlert.vue";
|
||||
import ZohoCliq from "./ZohoCliq.vue";
|
||||
|
||||
/**
|
||||
* Manage all notification form.
|
||||
|
@ -63,6 +65,7 @@ const NotificationFormList = {
|
|||
"gorush": Gorush,
|
||||
"gotify": Gotify,
|
||||
"HomeAssistant": HomeAssistant,
|
||||
"Kook": Kook,
|
||||
"line": Line,
|
||||
"LineNotify": LineNotify,
|
||||
"lunasea": LunaSea,
|
||||
|
@ -93,6 +96,7 @@ const NotificationFormList = {
|
|||
"WeCom": WeCom,
|
||||
"GoAlert": GoAlert,
|
||||
"ServerChan": ServerChan,
|
||||
"ZohoCliq": ZohoCliq
|
||||
};
|
||||
|
||||
export default NotificationFormList;
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
v-model="settings.searchEngineIndex"
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="flexRadioDefault"
|
||||
name="searchEngineIndex"
|
||||
:value="true"
|
||||
required
|
||||
/>
|
||||
|
@ -63,7 +63,7 @@
|
|||
v-model="settings.searchEngineIndex"
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="flexRadioDefault"
|
||||
name="searchEngineIndex"
|
||||
:value="false"
|
||||
required
|
||||
/>
|
||||
|
@ -150,6 +150,46 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DNS Cache -->
|
||||
<div class="mb-4">
|
||||
<label class="form-label">
|
||||
{{ $t("Enable DNS Cache") }}
|
||||
<div class="form-text">
|
||||
⚠️ {{ $t("dnsCacheDescription") }}
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div class="form-check">
|
||||
<input
|
||||
id="dnsCacheEnable"
|
||||
v-model="settings.dnsCache"
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="dnsCache"
|
||||
:value="true"
|
||||
required
|
||||
/>
|
||||
<label class="form-check-label" for="dnsCacheEnable">
|
||||
{{ $t("Enable") }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input
|
||||
id="dnsCacheDisable"
|
||||
v-model="settings.dnsCache"
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="dnsCache"
|
||||
:value="false"
|
||||
required
|
||||
/>
|
||||
<label class="form-check-label" for="dnsCacheDisable">
|
||||
{{ $t("Disable") }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Save Button -->
|
||||
<div>
|
||||
<button class="btn btn-primary" type="submit">
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
settings.keepDataPeriodDays,
|
||||
])
|
||||
}}
|
||||
{{ $t("infiniteRetention") }}
|
||||
</label>
|
||||
<input
|
||||
id="keepDataPeriodDays"
|
||||
|
@ -14,9 +15,12 @@
|
|||
type="number"
|
||||
class="form-control"
|
||||
required
|
||||
min="1"
|
||||
min="0"
|
||||
step="1"
|
||||
/>
|
||||
<div v-if="settings.keepDataPeriodDays < 0" class="form-text">
|
||||
{{ $t("dataRetentionTimeError") }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-4">
|
||||
<button class="btn btn-primary" type="button" @click="saveSettings()">
|
||||
|
|
171
src/components/settings/Tags.vue
Normal file
171
src/components/settings/Tags.vue
Normal file
|
@ -0,0 +1,171 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="tags-list my-3">
|
||||
<div v-for="(tag, index) in tagsList" :key="tag.id" class="d-flex align-items-center mx-4 py-1 tags-list-row" :disabled="processing" @click="editTag(index)">
|
||||
<div class="col-5 ps-1">
|
||||
<Tag :item="tag" />
|
||||
</div>
|
||||
<div class="col-5 px-1">
|
||||
<div>{{ monitorsByTag(tag.id).length }} {{ $tc("Monitor", monitorsByTag(tag.id).length) }}</div>
|
||||
</div>
|
||||
<div class="col-2 pe-3 d-flex justify-content-end">
|
||||
<button type="button" class="btn ms-2 py-1">
|
||||
<font-awesome-icon class="" icon="edit" />
|
||||
</button>
|
||||
<button type="button" class="btn-rm-tag btn btn-outline-danger ms-2 py-1" :disabled="processing" @click.stop="deleteConfirm(index)">
|
||||
<font-awesome-icon class="" icon="trash" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TagEditDialog ref="tagEditDialog" :updated="tagsUpdated" />
|
||||
<Confirm ref="confirmDelete" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="deleteTag">
|
||||
{{ $t("confirmDeleteTagMsg") }}
|
||||
</Confirm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useToast } from "vue-toastification";
|
||||
import TagEditDialog from "../../components/TagEditDialog.vue";
|
||||
import Tag from "../Tag.vue";
|
||||
import Confirm from "../Confirm.vue";
|
||||
const toast = useToast();
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Confirm,
|
||||
TagEditDialog,
|
||||
Tag,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
processing: false,
|
||||
tagsList: null,
|
||||
deletingTag: null,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
settings() {
|
||||
return this.$parent.$parent.$parent.settings;
|
||||
},
|
||||
saveSettings() {
|
||||
return this.$parent.$parent.$parent.saveSettings;
|
||||
},
|
||||
settingsLoaded() {
|
||||
return this.$parent.$parent.$parent.settingsLoaded;
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.getExistingTags();
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Reflect tag changes in the UI by fetching data. Callback for the edit tag dialog.
|
||||
* @returns {void}
|
||||
*/
|
||||
tagsUpdated() {
|
||||
this.getExistingTags();
|
||||
this.$root.getMonitorList();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get list of tags from server
|
||||
* @returns {void}
|
||||
*/
|
||||
getExistingTags() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("getTags", (res) => {
|
||||
this.processing = false;
|
||||
if (res.ok) {
|
||||
this.tagsList = res.tags;
|
||||
} else {
|
||||
toast.error(res.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Show confirmation for deleting a tag
|
||||
* @param {number} index index of the tag to delete in the local tagsList
|
||||
* @returns {void}
|
||||
*/
|
||||
deleteConfirm(index) {
|
||||
this.deletingTag = this.tagsList[index];
|
||||
this.$refs.confirmDelete.show();
|
||||
},
|
||||
|
||||
/**
|
||||
* Show dialog for editing a tag
|
||||
* @param {number} index index of the tag to edit in the local tagsList
|
||||
* @returns {void}
|
||||
*/
|
||||
editTag(index) {
|
||||
this.$refs.tagEditDialog.show(this.tagsList[index]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete the tag "deletingTag" from server
|
||||
* @returns {void}
|
||||
*/
|
||||
deleteTag() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("deleteTag", this.deletingTag.id, (res) => {
|
||||
this.$root.toastRes(res);
|
||||
this.processing = false;
|
||||
|
||||
if (res.ok) {
|
||||
this.tagsUpdated();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get monitors which has a specific tag locally
|
||||
* @param {number} tagId id of the tag to filter
|
||||
* @returns {Object[]} list of monitors which has a specific tag
|
||||
*/
|
||||
monitorsByTag(tagId) {
|
||||
return Object.values(this.$root.monitorList).filter((monitor) => {
|
||||
return monitor.tags.find(monitorTag => monitorTag.tag_id === tagId);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../assets/vars.scss";
|
||||
|
||||
.btn-rm-tag {
|
||||
padding-left: 11px;
|
||||
padding-right: 11px;
|
||||
}
|
||||
|
||||
.tags-list .tags-list-row {
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
|
||||
|
||||
.dark & {
|
||||
border-bottom: 1px solid $dark-border-color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $highlight-white;
|
||||
}
|
||||
|
||||
.dark &:hover {
|
||||
background-color: $dark-bg2;
|
||||
}
|
||||
}
|
||||
|
||||
.tags-list .tags-list-row:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -6,6 +6,7 @@ const languageList = {
|
|||
"zh-HK": "繁體中文 (香港)",
|
||||
"bg-BG": "Български",
|
||||
"de-DE": "Deutsch (Deutschland)",
|
||||
"de-CH": "Deutsch (Schweiz)",
|
||||
"nl-NL": "Nederlands",
|
||||
"nb-NO": "Norsk",
|
||||
"es-ES": "Español",
|
||||
|
|
|
@ -2,8 +2,8 @@ export default {
|
|||
languageName: "Български",
|
||||
checkEverySecond: "Ще се извършва на всеки {0} секунди",
|
||||
retryCheckEverySecond: "Ще се извършва на всеки {0} секунди",
|
||||
retriesDescription: "Максимакен брой опити преди маркиране на услугата като недостъпна и изпращане на известие",
|
||||
ignoreTLSError: "Игнорирай TLS/SSL грешки за HTTPS уебсайтове",
|
||||
retriesDescription: "Максимален брой опити преди маркиране на услугата като недостъпна и изпращане на известие",
|
||||
ignoreTLSError: "Игнорирай TLS/SSL грешки за HTTPS уеб сайтове",
|
||||
upsideDownModeDescription: "Обръща статуса от достъпен на недостъпен. Ако услугата е достъпна, ще се вижда като НЕДОСТЪПНА.",
|
||||
maxRedirectDescription: "Максимален брой пренасочвания, които да бъдат следвани. Въведете 0 за да изключите пренасочване.",
|
||||
acceptedStatusCodesDescription: "Изберете статус кодове, които да се считат за успешен отговор.",
|
||||
|
@ -95,7 +95,7 @@ export default {
|
|||
"Repeat New Password": "Повторете новата парола",
|
||||
"Update Password": "Актуализирай паролата",
|
||||
"Disable Auth": "Изключи удостоверяване",
|
||||
"Enable Auth": "Включи удостоверяване",
|
||||
"Enable Auth": "Активирай удостоверяване",
|
||||
"disableauth.message1": "Сигурни ли сте, че желаете да <strong>изключите удостоверяването</strong>?",
|
||||
"disableauth.message2": "Използва се в случаите, когато <strong>има настроен алтернативен метод за удостоверяване</strong> преди Uptime Kuma, например Cloudflare Access, Authelia или друг механизъм за удостоверяване.",
|
||||
"Please use this option carefully!": "Моля, използвайте с повишено внимание.",
|
||||
|
@ -126,7 +126,7 @@ export default {
|
|||
Import: "Импорт",
|
||||
respTime: "Време за отговор (ms)",
|
||||
notAvailableShort: "Няма",
|
||||
"Default enabled": "Включен по подразбиране",
|
||||
"Default enabled": "Активирано по подразбиране",
|
||||
"Apply on all existing monitors": "Приложи върху всички съществуващи монитори",
|
||||
Create: "Създай",
|
||||
"Clear Data": "Изтрий данни",
|
||||
|
@ -145,8 +145,8 @@ export default {
|
|||
"Keep both": "Запази двете",
|
||||
"Verify Token": "Провери токен код",
|
||||
"Setup 2FA": "Настройка 2FA",
|
||||
"Enable 2FA": "Включи 2FA",
|
||||
"Disable 2FA": "Изключи 2FA",
|
||||
"Enable 2FA": "Активирай 2FA",
|
||||
"Disable 2FA": "Деактивирай 2FA",
|
||||
"2FA Settings": "Настройка за 2FA",
|
||||
"Two Factor Authentication": "Двуфакторно удостоверяване",
|
||||
Active: "Активно",
|
||||
|
@ -194,7 +194,7 @@ export default {
|
|||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Поддържа 50+ услуги за инвестяване)",
|
||||
apprise: "Apprise (Поддържа 50+ услуги за известяване)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
|
@ -281,19 +281,19 @@ export default {
|
|||
wayToGetLineChannelToken: "Необходимо е първо да посетите {0}, за да създадете (Messaging API) за доставчик и канал, след което може да вземете токен кода за канал и потребителско ID от споменатите по-горе елементи на менюто.",
|
||||
"Icon URL": "URL адрес за иконка",
|
||||
aboutIconURL: "Може да предоставите линк към картинка в поле \"URL Адрес за иконка\" за да отмените картинката на профила по подразбиране. Няма да се използва, ако вече сте настроили емотикон.",
|
||||
aboutMattermostChannelName: "Може да замените канала по подразбиране, към който публикува уеб куката, като въведете името на канала в полето \"Канал име\". Tрябва да бъде активирано в настройките за уеб кука на Mattermost. Например: #other-channel",
|
||||
aboutMattermostChannelName: "Може да замените канала по подразбиране, към който публикува уеб куката, като въведете името на канала в полето \"Канал име\". Трябва да бъде активирано в настройките за уеб кука на Mattermost. Например: #other-channel",
|
||||
matrix: "Matrix",
|
||||
promosmsTypeEco: "SMS ECO - евтин, но бавен. Често е претоварен. Само за получатели от Полша.",
|
||||
promosmsTypeFlash: "SMS FLASH - Съобщението автоматично се показва на устройството на получателя. Само за получатели от Полша.",
|
||||
promosmsTypeFull: "SMS FULL - Високо ниво на SMS услуга. Може да използвате Вашето име като подател (Необходимо е първо да регистрирате името). Надежден метод за съобщения тип тревога.",
|
||||
promosmsTypeSpeed: "SMS SPEED - Най-висок приоритет в системата. Много бърза и надеждна, но същвременно скъпа услуга. (Около два пъти по-висока цена в сравнение с SMS FULL).",
|
||||
promosmsTypeSpeed: "SMS SPEED - Най-висок приоритет в системата. Много бърза и надеждна, но същевременно скъпа услуга. (Около два пъти по-висока цена в сравнение с SMS FULL).",
|
||||
promosmsPhoneNumber: "Телефонен номер (за получатели от Полша, може да пропуснете въвеждането на код за населено място)",
|
||||
promosmsSMSSender: "SMS Подател име: Предварително регистрирано име или някое от имената по подразбиране: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
"Feishu WebHookUrl": "Feishu URL адрес за уеб кука",
|
||||
matrixHomeserverURL: "Сървър URL адрес (започва с http(s):// и порт по желание)",
|
||||
"Internal Room Id": "ID на вътрешна стая",
|
||||
matrixDesc1: "Може да намерите \"ID на вътрешна стая\" в разширените настройки на стаята във вашия Matrix клиент. Примерен изглед: !QMdRCpUIfLwsfjxye6:home.server.",
|
||||
matrixDesc2: "Силно препоръчваме да създадете НОВ потребител и да НЕ използвате токен кодът на вашия личен Matrix потребирел, т.к. той позволява пълен достъп до вашия акаунт и всички стаи към които сте се присъединили. Вместо това създайте нов потребител и го поканете само в стаята, където желаете да получавате известията. Токен код за достъп ще получите изпълнявайки {0}",
|
||||
matrixDesc2: "Силно препоръчваме да създадете НОВ потребител и да НЕ използвате токен кодът на вашия личен Matrix потребител, т.к. той позволява пълен достъп до вашия акаунт и всички стаи към които сте се присъединили. Вместо това създайте нов потребител и го поканете само в стаята, където желаете да получавате известията. Токен код за достъп ще получите изпълнявайки {0}",
|
||||
Method: "Метод",
|
||||
Body: "Съобщение",
|
||||
Headers: "Хедъри",
|
||||
|
@ -316,7 +316,7 @@ export default {
|
|||
Security: "Сигурност",
|
||||
"Steam API Key": "Steam API ключ",
|
||||
"Shrink Database": "Редуцирай базата данни",
|
||||
"Pick a RR-Type...": "Изберете вида на ресурсния запис за мониторитане...",
|
||||
"Pick a RR-Type...": "Изберете вида на ресурсния запис за мониториране...",
|
||||
"Pick Accepted Status Codes...": "Изберете статус кодове, които да се считат за успешен отговор...",
|
||||
Default: "По подразбиране",
|
||||
"HTTP Options": "HTTP Опции",
|
||||
|
@ -375,12 +375,12 @@ export default {
|
|||
deleteStatusPageMsg: "Сигурни ли сте, че желаете да изтриете тази статус страница?",
|
||||
Proxies: "Прокси",
|
||||
default: "По подразбиране",
|
||||
enabled: "Включено",
|
||||
enabled: "Активирано",
|
||||
setAsDefault: "Зададен по подразбиране",
|
||||
deleteProxyMsg: "Сигурни ли сте, че желаете да изтриете това прокси за всички монитори?",
|
||||
proxyDescription: "За да функционират трябва да бъдат зададени към монитор.",
|
||||
enableProxyDescription: "Това прокси няма да има ефект върху заявките за мониторинг, докато не бъде активирано. Може да контролирате временното деактивиране на проксито от всички монитори чрез статуса на активиране.",
|
||||
setAsDefaultProxyDescription: "Това прокси ще бъде включено по подразбиране за новите монитори. Може да го изключите по отделно за всеки един монитор.",
|
||||
setAsDefaultProxyDescription: "Това прокси ще бъде активно по подразбиране за новите монитори. Може да го изключите по отделно за всеки един монитор.",
|
||||
"Certificate Chain": "Верига на сертификата",
|
||||
Valid: "Валиден",
|
||||
Invalid: "Невалиден",
|
||||
|
@ -432,7 +432,7 @@ export default {
|
|||
Backup: "Архивиране",
|
||||
About: "Относно",
|
||||
wayToGetCloudflaredURL: "(Свалете \"cloudflared\" от {0})",
|
||||
cloudflareWebsite: "Cloudflare уебсайт",
|
||||
cloudflareWebsite: "Cloudflare уеб сайт",
|
||||
"Message:": "Съобщение:",
|
||||
"Don't know how to get the token? Please read the guide:": "Не знаете как да вземете токен? Моля, прочетете ръководството:",
|
||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Текущата връзка може да прекъсне ако в момента сте свързани чрез \"Cloudflare Tunnel\". Сигурни ли сте, че желаете да го спрете? Въведете Вашата текуща парола за да потвърдите.",
|
||||
|
@ -623,12 +623,56 @@ export default {
|
|||
lastDay4: "4-ти последен ден на месеца",
|
||||
"No Maintenance": "Няма поддръжка",
|
||||
pauseMaintenanceMsg: "Сигурни ли сте, че желаете да направите пауза?",
|
||||
"maintenanceStatus-under-maintenance": "В режим подръжка",
|
||||
"maintenanceStatus-inactive": "Неактивен",
|
||||
"maintenanceStatus-scheduled": "Планиран",
|
||||
"maintenanceStatus-ended": "Прилючена",
|
||||
"maintenanceStatus-unknown": "Неизвестен",
|
||||
"maintenanceStatus-under-maintenance": "В режим поддръжка",
|
||||
"maintenanceStatus-inactive": "Неактивна",
|
||||
"maintenanceStatus-scheduled": "Планирана",
|
||||
"maintenanceStatus-ended": "Приключена",
|
||||
"maintenanceStatus-unknown": "Неизвестна",
|
||||
"Display Timezone": "Покажи часова зона",
|
||||
"Server Timezone": "Часова зона на сървъра",
|
||||
statusPageMaintenanceEndDate: "Край",
|
||||
enableGRPCTls: "Разреши изпращане на gRPC заявка с TLS връзка",
|
||||
grpcMethodDescription: "Името на метода се форматира в \"cammelCase\", например sayHello, check, и т.н.",
|
||||
smseagle: "SMSEagle",
|
||||
smseagleTo: "Тел. номер(а)",
|
||||
smseagleGroup: "Име на група/и от тел. указател",
|
||||
smseagleContact: "Име(на) от тел. указател",
|
||||
smseagleRecipientType: "Получател тип",
|
||||
smseagleRecipient: "Получател(и) (при повече от един разделете със запетая)",
|
||||
smseagleToken: "API токен за достъп",
|
||||
smseagleUrl: "Вашият SMSEagle URL на устройството",
|
||||
smseagleEncoding: "Изпрати като Unicode",
|
||||
smseaglePriority: "Приоритет на съобщението (0-9, по подразбиране = 0)",
|
||||
IconUrl: "Икона URL адрес",
|
||||
webhookAdditionalHeadersTitle: "Допълнителни хедъри",
|
||||
webhookAdditionalHeadersDesc: "Задава допълнителни хедъри, изпратени с уеб куката.",
|
||||
"Enable DNS Cache": "Активирай DNS кеширане",
|
||||
Enable: "Активирай",
|
||||
Disable: "Деактивирай",
|
||||
dnsCacheDescription: "Възможно е да не работи в IPv6 среда - деактивирайте, ако срещнете проблеми.",
|
||||
"Single Maintenance Window": "Единичен времеви интервал за поддръжка",
|
||||
"Maintenance Time Window of a Day": "Времеви интервал от деня за поддръжка",
|
||||
"Effective Date Range": "Интервал от дни на влизане в сила",
|
||||
"Schedule Maintenance": "Планирай поддръжка",
|
||||
"Date and Time": "Дата и час",
|
||||
"DateTime Range": "Изтрий времеви интервал",
|
||||
Strategy: "Стратегия",
|
||||
"Free Mobile User Identifier": "Free Mobile потребителски идентификатор",
|
||||
"Free Mobile API Key": "Free Mobile API ключ",
|
||||
"Enable TLS": "Активирай TLS",
|
||||
"Proto Service Name": "Proto име на услугата",
|
||||
"Proto Method": "Proto метод",
|
||||
"Proto Content": "Proto съдържание",
|
||||
Economy: "Икономичен",
|
||||
Lowcost: "Евтин",
|
||||
high: "висок",
|
||||
"General Monitor Type": "Общ тип монитор",
|
||||
"Passive Monitor Type": "Пасивет тип монитор",
|
||||
"Specific Monitor Type": "Специфичен тип монитор",
|
||||
ZohoCliq: "ZohoCliq",
|
||||
wayToGetZohoCliqURL: "Можете да научите как се създава URL адрес за уеб кука {0}.",
|
||||
Kook: "Kook",
|
||||
wayToGetKookBotToken: "Създайте приложение и вземете вашия бот токен на {0}",
|
||||
wayToGetKookGuildID: "Превключете в 'Developer Mode' в 'Kook' настройките, след което десен клик върху 'guild' за да вземете неговото 'ID'",
|
||||
"Guild ID": "Guild ID",
|
||||
};
|
||||
|
|
|
@ -582,4 +582,45 @@ export default {
|
|||
goAlert: "GoAlert",
|
||||
backupOutdatedWarning: "Zastaralé: V poslední době byla funkčnost aplikace značně rozšířena, nicméně součást pro zálohování nepokrývá všechny možnosti. Z tohoto důvodu není možné vygenerovat úplnou zálohu a zajistit obnovení všech dat.",
|
||||
backupRecommend: "Prosím, zálohujte si ručně celý svazek nebo datovou složku (./data/).",
|
||||
"Optional": "Volitelný",
|
||||
squadcast: "Squadcast",
|
||||
SendKey: "SendKey",
|
||||
"SMSManager API Docs": "SMSManager API Docs ",
|
||||
"Gateway Type": "Gateway Typ",
|
||||
SMSManager: "SMSManager",
|
||||
"You can divide numbers with": "Čísla můžete dělit pomocí",
|
||||
"or": "nebo",
|
||||
recurringInterval: "Interval",
|
||||
"Recurring": "Opakující se",
|
||||
strategyManual: "Aktivní/Neaktivní Ručně",
|
||||
warningTimezone: "Používá se časové pásmo serveru",
|
||||
weekdayShortMon: "Po",
|
||||
weekdayShortTue: "Út",
|
||||
weekdayShortWed: "St",
|
||||
weekdayShortThu: "Čt",
|
||||
weekdayShortFri: "Pá",
|
||||
weekdayShortSat: "So",
|
||||
weekdayShortSun: "Ne",
|
||||
dayOfWeek: "Den v týdnu",
|
||||
dayOfMonth: "Den v měsíci",
|
||||
lastDay: "Poslední den",
|
||||
lastDay1: "1. poslední den v měsíci",
|
||||
lastDay2: "2. poslední den v měsíci",
|
||||
lastDay3: "3. poslední den v měsíci",
|
||||
lastDay4: "4. poslední den v měsíci",
|
||||
"No Maintenance": "Žádna údržba",
|
||||
pauseMaintenanceMsg: "Jsi si jistý, že chceš pozastavit údržbu?",
|
||||
"maintenanceStatus-under-maintenance": "Údržba",
|
||||
"maintenanceStatus-inactive": "Neaktivní",
|
||||
"maintenanceStatus-scheduled": "Naplánováno",
|
||||
"maintenanceStatus-ended": "Ukončeno",
|
||||
"maintenanceStatus-unknown": "Neznámý",
|
||||
"Display Timezone": "Zobrazit časové pásmo",
|
||||
"Server Timezone": "Časové pásmo serveru",
|
||||
statusPageMaintenanceEndDate: "Konec",
|
||||
IconUrl: "Adresa URL ikony",
|
||||
"Enable DNS Cache": "Povolit DNS Cache",
|
||||
"Enable": "Povolit",
|
||||
"Disable": "Zakázat",
|
||||
dnsCacheDescription: "V některých prostředích IPv6 nemusí fungovat. Pokud narazíte na nějaké problémy, vypněte jej.",
|
||||
};
|
||||
|
|
634
src/languages/de-CH.js
Normal file
634
src/languages/de-CH.js
Normal file
|
@ -0,0 +1,634 @@
|
|||
export default {
|
||||
languageName: "Deutsch (Schweiz)",
|
||||
Settings: "Einstellungen",
|
||||
Dashboard: "Dashboard",
|
||||
"New Update": "Update verfügbar",
|
||||
Language: "Sprache",
|
||||
Appearance: "Erscheinungsbild",
|
||||
Theme: "Erscheinungsbild",
|
||||
General: "Allgemein",
|
||||
Version: "Version",
|
||||
"Check Update On GitHub": "Auf GitHub nach Updates suchen",
|
||||
List: "Liste",
|
||||
Add: "Hinzufügen",
|
||||
"Add New Monitor": "Neuen Monitor hinzufügen",
|
||||
"Quick Stats": "Übersicht",
|
||||
Up: "Aktiv",
|
||||
Down: "Inaktiv",
|
||||
Pending: "Ausstehend",
|
||||
Unknown: "Unbekannt",
|
||||
Pause: "Pausieren",
|
||||
pauseDashboardHome: "Pausiert",
|
||||
Name: "Name",
|
||||
Status: "Status",
|
||||
DateTime: "Datum / Uhrzeit",
|
||||
Message: "Nachricht",
|
||||
"No important events": "Keine wichtigen Ereignisse",
|
||||
Resume: "Fortsetzen",
|
||||
Edit: "Bearbeiten",
|
||||
Delete: "Löschen",
|
||||
Current: "Aktuell",
|
||||
Uptime: "Verfügbarkeit",
|
||||
"Cert Exp.": "Zertifikatsablauf",
|
||||
day: "Tag | Tage",
|
||||
"-day": "-Tage",
|
||||
hour: "Stunde",
|
||||
"-hour": "-Stunden",
|
||||
checkEverySecond: "Überprüfe alle {0} Sekunden",
|
||||
Response: "Antwortzeit",
|
||||
Ping: "Ping",
|
||||
"Monitor Type": "Monitor-Typ",
|
||||
Keyword: "Suchwort",
|
||||
"Friendly Name": "Anzeigename",
|
||||
URL: "URL",
|
||||
Hostname: "Hostname",
|
||||
Port: "Port",
|
||||
"Heartbeat Interval": "Prüfintervall",
|
||||
Retries: "Wiederholungen",
|
||||
retriesDescription: "Maximale Anzahl von Wiederholungen, bevor der Dienst als inaktiv markiert und eine Benachrichtigung gesendet wird.",
|
||||
Advanced: "Erweitert",
|
||||
ignoreTLSError: "Ignoriere TLS-/SSL-Fehler von Webseiten",
|
||||
"Upside Down Mode": "Umgekehrter Modus",
|
||||
upsideDownModeDescription: "Im umgekehrten Modus wird der Dienst als inaktiv angezeigt, wenn er erreichbar ist.",
|
||||
"Max. Redirects": "Max. Weiterleitungen",
|
||||
maxRedirectDescription: "Maximale Anzahl von Weiterleitungen, denen gefolgt werden soll. Auf 0 setzen, um Weiterleitungen zu deaktivieren.",
|
||||
"Accepted Status Codes": "Erlaubte HTTP-Statuscodes",
|
||||
acceptedStatusCodesDescription: "Statuscodes auswählen, die als erfolgreiche Verbindung gelten sollen.",
|
||||
Save: "Speichern",
|
||||
Notifications: "Benachrichtigungen",
|
||||
"Not available, please setup.": "Nicht verfügbar, bitte einrichten.",
|
||||
"Setup Notification": "Benachrichtigung einrichten",
|
||||
Light: "Hell",
|
||||
Dark: "Dunkel",
|
||||
Auto: "Auto",
|
||||
"Theme - Heartbeat Bar": "Erscheinungsbild - Zeitleiste",
|
||||
Normal: "Normal",
|
||||
Bottom: "Unten",
|
||||
None: "Keine",
|
||||
Timezone: "Zeitzone",
|
||||
"Search Engine Visibility": "Sichtbarkeit für Suchmaschinen",
|
||||
"Allow indexing": "Indizierung zulassen",
|
||||
"Discourage search engines from indexing site": "Suchmaschinen darum bitten, die Seite nicht zu indizieren",
|
||||
"Change Password": "Passwort ändern",
|
||||
"Current Password": "Aktuelles Passwort",
|
||||
"New Password": "Neues Passwort",
|
||||
"Repeat New Password": "Neues Passwort wiederholen",
|
||||
passwordNotMatchMsg: "Passwörter stimmen nicht überein.",
|
||||
"Update Password": "Passwort aktualisieren",
|
||||
"Disable Auth": "Authentifizierung deaktivieren",
|
||||
"Enable Auth": "Authentifizierung aktivieren",
|
||||
"disableauth.message1": "Bist du sicher das du die <strong>Authentifizierung deaktivieren</strong> möchtest?",
|
||||
"disableauth.message2": "Dies ist für Szenarien gedacht, <strong>in denen man eine externe Authentifizierung</strong> vor Uptime Kuma geschaltet hat, wie z.B. Cloudflare Access, Authelia oder andere Authentifizierungsmechanismen.",
|
||||
"Please use this option carefully!": "Bitte mit Vorsicht nutzen.",
|
||||
Logout: "Ausloggen",
|
||||
notificationDescription: "Benachrichtigungen müssen einem Monitor zugewiesen werden, damit diese funktionieren.",
|
||||
Leave: "Verlassen",
|
||||
"I understand, please disable": "Ich verstehe, bitte deaktivieren",
|
||||
Confirm: "Bestätigen",
|
||||
Yes: "Ja",
|
||||
No: "Nein",
|
||||
Username: "Benutzername",
|
||||
Password: "Passwort",
|
||||
"Remember me": "Angemeldet bleiben",
|
||||
Login: "Einloggen",
|
||||
"No Monitors, please": "Keine Monitore, bitte",
|
||||
"add one": "hinzufügen",
|
||||
"Notification Type": "Benachrichtigungsdienst",
|
||||
Email: "E-Mail",
|
||||
Test: "Test",
|
||||
"Certificate Info": "Zertifikatsinformation",
|
||||
keywordDescription: "Ein Suchwort in der HTML- oder JSON-Ausgabe finden. Bitte beachte: es wird zwischen Gross-/Kleinschreibung unterschieden.",
|
||||
deleteMonitorMsg: "Bist du sicher, dass du den Monitor löschen möchtest?",
|
||||
deleteNotificationMsg: "Möchtest du diese Benachrichtigung wirklich für alle Monitore löschen?",
|
||||
resolverserverDescription: "Cloudflare ist als der Standardserver festgelegt. Dieser kann jederzeit geändert werden.",
|
||||
"Resolver Server": "Auflösungsserver",
|
||||
rrtypeDescription: "Wähle den RR-Typ aus, welchen du überwachen möchtest.",
|
||||
"Last Result": "Letztes Ergebnis",
|
||||
pauseMonitorMsg: "Bist du sicher, dass du den Monitor pausieren möchtest?",
|
||||
clearEventsMsg: "Bist du sicher, dass du alle Ereignisse für diesen Monitor löschen möchtest?",
|
||||
clearHeartbeatsMsg: "Bist du sicher, dass du alle Statistiken für diesen Monitor löschen möchtest?",
|
||||
"Clear Data": "Lösche Daten",
|
||||
Events: "Ereignisse",
|
||||
Heartbeats: "Statistiken",
|
||||
confirmClearStatisticsMsg: "Bist du dir sicher, dass du ALLE Statistiken löschen möchtest?",
|
||||
"Create your admin account": "Erstelle dein Admin-Konto",
|
||||
"Repeat Password": "Passwort erneut eingeben",
|
||||
"Resource Record Type": "Ressourcen Record Typ",
|
||||
Export: "Export",
|
||||
Import: "Import",
|
||||
respTime: "Antw.-Zeit (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
"Default enabled": "Standardmässig aktiviert",
|
||||
"Apply on all existing monitors": "Auf alle existierenden Monitore anwenden",
|
||||
enableDefaultNotificationDescription: "Für jeden neuen Monitor wird diese Benachrichtigung standardmässig aktiviert. Die Benachrichtigung kann weiterhin für jeden Monitor separat deaktiviert werden.",
|
||||
Create: "Erstellen",
|
||||
"Auto Get": "Auto Get",
|
||||
backupDescription: "Es können alle Monitore und Benachrichtigungen in einer JSON-Datei gesichert werden.",
|
||||
backupDescription2: "PS: Verlaufs- und Ereignisdaten sind nicht enthalten.",
|
||||
backupDescription3: "Sensible Daten wie Benachrichtigungs-Token sind in der Exportdatei enthalten, bitte bewahre sie sorgfältig auf.",
|
||||
alertNoFile: "Bitte wähle eine Datei zum Importieren aus.",
|
||||
alertWrongFileType: "Bitte wähle eine JSON-Datei aus.",
|
||||
"Clear all statistics": "Lösche alle Statistiken",
|
||||
importHandleDescription: "Wähle 'Vorhandene überspringen' aus, wenn jeder Monitor oder jede Benachrichtigung mit demselben Namen übersprungen werden soll. 'Überschreiben' löscht jeden vorhandenen Monitor sowie Benachrichtigungen.",
|
||||
"Skip existing": "Vorhandene überspringen",
|
||||
Overwrite: "Überschreiben",
|
||||
Options: "Optionen",
|
||||
confirmImportMsg: "Möchtest du das Backup wirklich importieren? Bitte stelle sicher, dass die richtige Import-Option ausgewählt ist.",
|
||||
"Keep both": "Beide behalten",
|
||||
twoFAVerifyLabel: "Bitte trage deinen Token ein, um zu verifizieren, dass 2FA funktioniert",
|
||||
"Verify Token": "Token verifizieren",
|
||||
"Setup 2FA": "2FA einrichten",
|
||||
"Enable 2FA": "2FA aktivieren",
|
||||
"Disable 2FA": "2FA deaktivieren",
|
||||
"2FA Settings": "2FA-Einstellungen",
|
||||
confirmEnableTwoFAMsg: "Bist du sicher, dass du 2FA aktivieren möchtest?",
|
||||
confirmDisableTwoFAMsg: "Bist du sicher, dass du 2FA deaktivieren möchtest?",
|
||||
tokenValidSettingsMsg: "Token gültig! Du kannst jetzt die 2FA-Einstellungen speichern.",
|
||||
"Two Factor Authentication": "Zwei-Faktor-Authentifizierung",
|
||||
Active: "Aktiv",
|
||||
Inactive: "Inaktiv",
|
||||
Token: "Token",
|
||||
"Show URI": "URI anzeigen",
|
||||
Tags: "Tags",
|
||||
"Add New below or Select...": "Einen bestehenden Tag auswählen oder neuen hinzufügen...",
|
||||
"Tag with this name already exist.": "Ein Tag mit diesem Namen existiert bereits.",
|
||||
"Tag with this value already exist.": "Ein Tag mit diesem Wert existiert bereits.",
|
||||
color: "Farbe",
|
||||
"value (optional)": "Wert (optional)",
|
||||
Gray: "Grau",
|
||||
Red: "Rot",
|
||||
Orange: "Orange",
|
||||
Green: "Grün",
|
||||
Blue: "Blau",
|
||||
Indigo: "Indigo",
|
||||
Purple: "Lila",
|
||||
Pink: "Pink",
|
||||
"Search...": "Suchen...",
|
||||
"Heartbeat Retry Interval": "Überprüfungsintervall",
|
||||
"Resend Notification if Down X times consequently": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander",
|
||||
retryCheckEverySecond: "Alle {0} Sekunden neu versuchen",
|
||||
resendEveryXTimes: "Erneut versenden alle {0} mal",
|
||||
resendDisabled: "Erneut versenden deaktiviert",
|
||||
"Import Backup": "Backup importieren",
|
||||
"Export Backup": "Backup exportieren",
|
||||
"Avg. Ping": "Ping ø",
|
||||
"Avg. Response": "Antwortzeit ø",
|
||||
"Entry Page": "Einstiegsseite",
|
||||
statusPageNothing: "Noch ist hier nichts. Bitte füge eine Gruppe oder einen Monitor hinzu.",
|
||||
"No Services": "Keine Dienste",
|
||||
"All Systems Operational": "Alle Systeme betriebsbereit",
|
||||
"Partially Degraded Service": "Teilweise beeinträchtigter Dienst",
|
||||
"Degraded Service": "Eingeschränkter Dienst",
|
||||
"Add Group": "Gruppe hinzufügen",
|
||||
"Add a monitor": "Monitor hinzufügen",
|
||||
"Edit Status Page": "Bearbeite Status-Seite",
|
||||
"Go to Dashboard": "Gehe zum Dashboard",
|
||||
"Status Page": "Status-Seite",
|
||||
"Status Pages": "Status-Seiten",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "E-Mail (SMTP)",
|
||||
discord: "Discord",
|
||||
teams: "Microsoft Teams",
|
||||
signal: "Signal",
|
||||
gotify: "Gotify",
|
||||
slack: "Slack",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Unterstützung für 50+ Benachrichtigungsdienste)",
|
||||
GoogleChat: "Google Chat (nur Google Workspace)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"Primary Base URL": "Primär URL",
|
||||
"Push URL": "Push URL",
|
||||
needPushEvery: "Du solltest diese URL alle {0} Sekunden aufrufen",
|
||||
pushOptionalParams: "Optionale Parameter: {0}",
|
||||
defaultNotificationName: "Mein {notification} Alarm ({number})",
|
||||
here: "hier",
|
||||
Required: "Erforderlich",
|
||||
"Bot Token": "Bot Token",
|
||||
wayToGetTelegramToken: "Hier kannst du einen Token erhalten {0}.",
|
||||
"Chat ID": "Chat ID",
|
||||
supportTelegramChatID: "Unterstützt Direkt Chat / Gruppe / Kanal Chat-ID's",
|
||||
wayToGetTelegramChatID: "Du kannst die Chat-ID erhalten, indem du eine Nachricht an den Bot sendest und zu dieser URL gehst, um die chat_id: zu sehen.",
|
||||
"YOUR BOT TOKEN HERE": "HIER DEIN BOT TOKEN",
|
||||
chatIDNotFound: "Chat-ID wurde nicht gefunden: bitte sende zuerst eine Nachricht an diesen Bot",
|
||||
"Post URL": "Post URL",
|
||||
"Content Type": "Content Type",
|
||||
webhookJsonDesc: "{0} ist gut für alle modernen HTTP-Server, wie z.B. Express.js, geeignet",
|
||||
webhookFormDataDesc: "{multipart} ist gut für PHP. Das JSON muss mit {decodeFunction} verarbeitet werden",
|
||||
secureOptionNone: "Keine / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "TLS-Fehler ignorieren",
|
||||
"From Email": "Absender E-Mail",
|
||||
emailCustomSubject: "Benutzerdefinierter Betreff",
|
||||
"To Email": "Empfänger E-Mail",
|
||||
smtpCC: "CC",
|
||||
smtpBCC: "BCC",
|
||||
"Discord Webhook URL": "Discord Webhook URL",
|
||||
wayToGetDiscordURL: "Du kannst diese erhalten, indem du zu den Servereinstellungen gehst -> Integrationen -> Neuer Webhook",
|
||||
"Bot Display Name": "Bot-Anzeigename",
|
||||
"Prefix Custom Message": "Benutzerdefinierter Nachrichten Präfix",
|
||||
"Hello @everyone is...": "Hallo {'@'}everyone ist...",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "Wie eine Webhook-URL erstellt werden kann, erfährst du {0}.",
|
||||
Number: "Nummer",
|
||||
Recipients: "Empfänger",
|
||||
needSignalAPI: "Es wird ein Signal Client mit REST-API benötigt.",
|
||||
wayToCheckSignalURL: "Du kannst diese URL aufrufen, um zu sehen, wie du eine einrichtest:",
|
||||
signalImportant: "WICHTIG: Gruppen und Nummern können in Empfängern nicht gemischt werden!",
|
||||
"Application Token": "Anwendungstoken",
|
||||
"Server URL": "Server URL",
|
||||
Priority: "Priorität",
|
||||
"Icon Emoji": "Icon Emoji",
|
||||
"Channel Name": "Kanalname",
|
||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||
aboutWebhooks: "Weitere Informationen zu Webhooks auf: {0}",
|
||||
aboutChannelName: "Gebe den Kanalnamen ein in {0} Feld Kanalname, falls du den Webhook-Kanal umgehen möchtest. Ex: #other-channel",
|
||||
aboutKumaURL: "Wenn das Feld für die Uptime Kuma URL leer gelassen wird, wird standardmässig die GitHub Projekt Seite verwendet.",
|
||||
emojiCheatSheet: "Emoji Cheat Sheet: {0}",
|
||||
"User Key": "Benutzerschlüssel",
|
||||
Device: "Gerät",
|
||||
"Message Title": "Nachrichtentitel",
|
||||
"Notification Sound": "Benachrichtigungston",
|
||||
"More info on:": "Mehr Infos auf: {0}",
|
||||
pushoverDesc1: "Notfallpriorität (2) hat standardmässig 30 Sekunden Auszeit zwischen den Versuchen und läuft nach 1 Stunde ab.",
|
||||
pushoverDesc2: "Fülle das Geräte Feld aus, wenn du Benachrichtigungen an verschiedene Geräte senden möchtest.",
|
||||
"SMS Type": "SMS Typ",
|
||||
octopushTypePremium: "Premium (Schnell - zur Benachrichtigung empfohlen)",
|
||||
octopushTypeLowCost: "Kostengünstig (Langsam - manchmal vom Betreiber gesperrt)",
|
||||
checkPrice: "Prüfe {0} Preise:",
|
||||
octopushLegacyHint: "Verwendest du die Legacy-Version von Octopush (2011-2020) oder die neue Version?",
|
||||
"Check octopush prices": "Vergleiche die Oktopush Preise {0}.",
|
||||
octopushPhoneNumber: "Telefonnummer (Internationales Format, z.B : +49612345678) ",
|
||||
octopushSMSSender: "Name des SMS-Absenders : 3-11 alphanumerische Zeichen und Leerzeichen (a-zA-Z0-9)",
|
||||
"LunaSea Device ID": "LunaSea Geräte ID",
|
||||
"Apprise URL": "Apprise URL",
|
||||
"Example:": "Beispiel: {0}",
|
||||
"Read more:": "Weiterlesen: {0}",
|
||||
"Status:": "Status: {0}",
|
||||
"Read more": "Weiterlesen",
|
||||
appriseInstalled: "Apprise ist installiert.",
|
||||
appriseNotInstalled: "Apprise ist nicht installiert. {0}",
|
||||
"Access Token": "Access Token",
|
||||
"Channel access token": "Channel access token",
|
||||
"Line Developers Console": "Line Developers Console",
|
||||
lineDevConsoleTo: "Line Developers Console - {0}",
|
||||
"Basic Settings": "Basic Settings",
|
||||
"User ID": "User ID",
|
||||
"Messaging API": "Messaging API",
|
||||
wayToGetLineChannelToken: "Rufe zuerst {0} auf, erstelle dann einen Provider und Channel (Messaging API). Als nächstes kannst du den Channel access token und die User ID aus den oben genannten Menüpunkten abrufen.",
|
||||
"Icon URL": "Icon URL",
|
||||
aboutIconURL: "Du kannst einen Link zu einem Bild in 'Icon URL' übergeben um das Standardprofilbild zu überschreiben. Wird nicht verwendet, wenn ein Icon Emoji gesetzt ist.",
|
||||
aboutMattermostChannelName: "Du kannst den Standardkanal, auf dem der Webhook gesendet wird überschreiben, indem der Kanalnamen in das Feld 'Channel Name' eingeben wird. Dies muss in den Mattermost Webhook-Einstellungen aktiviert werden. Ex: #other-channel",
|
||||
matrix: "Matrix",
|
||||
promosmsTypeEco: "SMS ECO - billig, aber langsam und oft überladen. Auf polnische Empfänger beschränkt.",
|
||||
promosmsTypeFlash: "SMS FLASH - Die Nachricht wird automatisch auf dem Empfängergerät angezeigt. Auf polnische Empfänger beschränkt.",
|
||||
promosmsTypeFull: "SMS FULL - Premium Stufe von SMS, es kann der Absendernamen verwendet werden (Der Name musst zuerst registriert werden). Zuverlässig für Warnungen.",
|
||||
promosmsTypeSpeed: "SMS SPEED - Höchste Priorität im System. Sehr schnell und zuverlässig, aber teuer (Ungefähr das doppelte von SMS FULL).",
|
||||
promosmsPhoneNumber: "Telefonnummer (für polnische Empfänger können die Vorwahlen übersprungen werden)",
|
||||
promosmsSMSSender: "Name des SMS-Absenders : vorregistrierter Name oder einer der Standardwerte: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
"Feishu WebHookUrl": "Feishu Webhook URL",
|
||||
matrixHomeserverURL: "Heimserver URL (mit http(s):// und optionalen Ports)",
|
||||
"Internal Room Id": "Interne Raum-ID",
|
||||
matrixDesc1: "Die interne Raum-ID findest du im erweiterten Bereich der Raumeinstellungen im Matrix-Client. Es sollte aussehen wie z.B. !QMdRCpUIfLwsfjxye6:home.server.",
|
||||
matrixDesc2: "Es wird dringend empfohlen einen neuen Benutzer anzulegen und nicht den Zugriffstoken deines eigenen Matrix-Benutzers zu verwenden. Anderenfalls ermöglicht es vollen Zugriff auf dein Konto und alle Räume, denen du beigetreten bist. Erstelle stattdessen einen neuen Benutzer und lade ihn nur in den Raum ein, in dem du die Benachrichtigung erhalten möchtest. Du kannst den Zugriffstoken erhalten, indem du Folgendes ausführst {0}",
|
||||
Method: "Method",
|
||||
Body: "Body",
|
||||
Headers: "Headers",
|
||||
PushUrl: "Push URL",
|
||||
HeadersInvalidFormat: "Der Header ist kein gültiges JSON: ",
|
||||
BodyInvalidFormat: "Der Body ist kein gültiges JSON: ",
|
||||
"Monitor History": "Monitor Verlauf",
|
||||
clearDataOlderThan: "Bewahre die Aufzeichnungsdaten für {0} Tage auf.",
|
||||
PasswordsDoNotMatch: "Passwörter stimmen nicht überein.",
|
||||
records: "Einträge",
|
||||
"One record": "Ein Eintrag",
|
||||
steamApiKeyDescription: "Um einen Steam Game Server zu überwachen, wird ein Steam Web-API-Schlüssel benötigt. Dieser kann hier registriert werden: ",
|
||||
"Current User": "Aktueller Benutzer",
|
||||
recent: "Letzte",
|
||||
Done: "Fertig",
|
||||
Info: "Info",
|
||||
Security: "Sicherheit",
|
||||
"Steam API Key": "Steam API Key",
|
||||
"Shrink Database": "Datenbank verkleinern",
|
||||
"Pick a RR-Type...": "Wähle ein RR-Typ aus...",
|
||||
"Pick Accepted Status Codes...": "Wähle akzeptierte Statuscodes aus...",
|
||||
Default: "Standard",
|
||||
"HTTP Options": "HTTP Optionen",
|
||||
"Create Incident": "Vorfall erstellen",
|
||||
Title: "Titel",
|
||||
Content: "Inhalt",
|
||||
Style: "Stil",
|
||||
info: "info",
|
||||
warning: "warnung",
|
||||
danger: "gefahr",
|
||||
primary: "primär",
|
||||
light: "hell",
|
||||
dark: "dunkel",
|
||||
Post: "Eintrag",
|
||||
"Please input title and content": "Bitte Titel und Inhalt eingeben",
|
||||
Created: "Erstellt",
|
||||
"Last Updated": "Zuletzt aktualisiert",
|
||||
Unpin: "Loslösen",
|
||||
"Switch to Light Theme": "Zu hellem Thema wechseln",
|
||||
"Switch to Dark Theme": "Zum dunklen Thema wechseln",
|
||||
"Show Tags": "Tags anzeigen",
|
||||
"Hide Tags": "Tags ausblenden",
|
||||
Description: "Beschreibung",
|
||||
"No monitors available.": "Keine Monitore verfügbar.",
|
||||
"Add one": "Hinzufügen",
|
||||
"No Monitors": "Keine Monitore",
|
||||
"Untitled Group": "Gruppe ohne Titel",
|
||||
Services: "Dienste",
|
||||
Discard: "Verwerfen",
|
||||
Cancel: "Abbrechen",
|
||||
"Powered by": "Powered by",
|
||||
shrinkDatabaseDescription: "Löse VACUUM für die SQLite Datenbank aus. Wenn die Datenbank nach 1.10.0 erstellt wurde, ist AUTO_VACUUM bereits aktiviert und diese Aktion ist nicht erforderlich.",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
serwersmsAPIUser: "API Benutzername (inkl. webapi_ prefix)",
|
||||
serwersmsAPIPassword: "API Passwort",
|
||||
serwersmsPhoneNumber: "Telefonnummer",
|
||||
serwersmsSenderName: "Name des SMS-Absenders (über Kundenportal registriert)",
|
||||
stackfield: "Stackfield",
|
||||
clicksendsms: "ClickSend SMS",
|
||||
apiCredentials: "API Zugangsdaten",
|
||||
smtpDkimSettings: "DKIM Einstellungen",
|
||||
smtpDkimDesc: "Details zur Konfiguration sind in der Nodemailer DKIM {0} zu finden.",
|
||||
documentation: "Dokumentation",
|
||||
smtpDkimDomain: "Domain Name",
|
||||
smtpDkimKeySelector: "Schlüssel Auswahl",
|
||||
smtpDkimPrivateKey: "Privater Schlüssel",
|
||||
smtpDkimHashAlgo: "Hash-Algorithmus (Optional)",
|
||||
smtpDkimheaderFieldNames: "Zu validierende Header-Schlüssel (optional)",
|
||||
smtpDkimskipFields: "Zu ignorierende Header Schlüssel (optional)",
|
||||
PushByTechulus: "Push by Techulus",
|
||||
gorush: "Gorush",
|
||||
alerta: "Alerta",
|
||||
alertaApiEndpoint: "API Endpunkt",
|
||||
alertaEnvironment: "Umgebung",
|
||||
alertaApiKey: "API Schlüssel",
|
||||
alertaAlertState: "Alarmstatus",
|
||||
alertaRecoverState: "Wiederherstellungsstatus",
|
||||
deleteStatusPageMsg: "Bist du sicher, dass du diese Status-Seite löschen willst?",
|
||||
Proxies: "Proxies",
|
||||
default: "Standard",
|
||||
enabled: "Aktiviert",
|
||||
setAsDefault: "Als Standard setzen",
|
||||
deleteProxyMsg: "Bist du sicher, dass du diesen Proxy für alle Monitore löschen willst?",
|
||||
proxyDescription: "Proxies müssen einem Monitor zugewiesen werden, um zu funktionieren.",
|
||||
enableProxyDescription: "Dieser Proxy wird keinen Effekt auf Monitor-Anfragen haben, bis er aktiviert ist. Du kannst ihn temporär von allen Monitoren nach Aktivierungsstatus deaktivieren.",
|
||||
setAsDefaultProxyDescription: "Dieser Proxy wird standardmässig für alle neuen Monitore aktiviert sein. Du kannst den Proxy immer noch für jeden Monitor einzeln deaktivieren.",
|
||||
"Certificate Chain": "Zertifikatskette",
|
||||
Valid: "Gültig",
|
||||
Invalid: "Ungültig",
|
||||
AccessKeyId: "AccessKey ID",
|
||||
SecretAccessKey: "AccessKey Secret",
|
||||
PhoneNumbers: "Telefonnummern",
|
||||
TemplateCode: "Vorlagencode",
|
||||
SignName: "Signaturname",
|
||||
"Sms template must contain parameters: ": "SMS Vorlage muss folgende Parameter enthalten: ",
|
||||
"Bark Endpoint": "Bark Endpunkt",
|
||||
WebHookUrl: "Webhook URL",
|
||||
SecretKey: "Geheimer Schlüssel",
|
||||
"For safety, must use secret key": "Zur Sicherheit muss ein geheimer Schlüssel verwendet werden",
|
||||
"Device Token": "Gerätetoken",
|
||||
Platform: "Platform",
|
||||
iOS: "iOS",
|
||||
Android: "Android",
|
||||
Huawei: "Huawei",
|
||||
High: "Hoch",
|
||||
Retry: "Wiederholungen",
|
||||
Topic: "Thema",
|
||||
"WeCom Bot Key": "WeCom Bot Schlüssel",
|
||||
"Setup Proxy": "Proxy einrichten",
|
||||
"Proxy Protocol": "Proxy Protokoll",
|
||||
"Proxy Server": "Proxy-Server",
|
||||
"Proxy server has authentication": "Proxy-Server hat Authentifizierung",
|
||||
User: "Benutzer",
|
||||
Installed: "Installiert",
|
||||
"Not installed": "Nicht installiert",
|
||||
Running: "Läuft",
|
||||
"Not running": "Gestoppt",
|
||||
"Remove Token": "Token entfernen",
|
||||
Start: "Start",
|
||||
Stop: "Stop",
|
||||
"Uptime Kuma": "Uptime Kuma",
|
||||
"Add New Status Page": "Neue Status-Seite hinzufügen",
|
||||
Slug: "Slug",
|
||||
"Accept characters:": "Akzeptierte Zeichen:",
|
||||
startOrEndWithOnly: "Nur mit {0} anfangen und enden",
|
||||
"No consecutive dashes": "Keine aufeinanderfolgenden Bindestriche",
|
||||
Next: "Weiter",
|
||||
"The slug is already taken. Please choose another slug.": "Der Slug ist bereits in Verwendung. Bitte wähle einen anderen.",
|
||||
"No Proxy": "Kein Proxy",
|
||||
Authentication: "Authentifizierung",
|
||||
"HTTP Basic Auth": "HTTP Basisauthentifizierung",
|
||||
"New Status Page": "Neue Status-Seite",
|
||||
"Page Not Found": "Seite nicht gefunden",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
Backup: "Sicherung",
|
||||
About: "Über",
|
||||
wayToGetCloudflaredURL: "(Lade Cloudflare von {0} herunter)",
|
||||
cloudflareWebsite: "Cloudflare Website",
|
||||
"Message:": "Nachricht:",
|
||||
"Don't know how to get the token? Please read the guide:": "Du weisst nicht, wie man den Token bekommt? Lies die Anleitung dazu:",
|
||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "Die aktuelle Verbindung kann unterbrochen werden, wenn du aktuell über Cloudflare Tunnel verbunden bist. Bist du sicher, dass du es stoppen willst? Gib zur Bestätigung dein aktuelles Passwort ein.",
|
||||
"Other Software": "Andere Software",
|
||||
"For example: nginx, Apache and Traefik.": "Zum Beispiel: nginx, Apache und Traefik.",
|
||||
"Please read": "Bitte lesen",
|
||||
"Subject:": "Betreff:",
|
||||
"Valid To:": "Gültig bis:",
|
||||
"Days Remaining:": "Tage verbleibend:",
|
||||
"Issuer:": "Aussteller:",
|
||||
"Fingerprint:": "Fingerabdruck:",
|
||||
"No status pages": "Keine Status-Seiten",
|
||||
"Domain Name Expiry Notification": "Benachrichtigung bei Ablauf des Domainnamens",
|
||||
Customize: "Anpassen",
|
||||
"Custom Footer": "Eigener Footer",
|
||||
"Custom CSS": "Eigenes CSS",
|
||||
"Footer Text": "Fusszeile",
|
||||
"Show Powered By": "Zeige 'Powered By'",
|
||||
"Date Created": "Erstellt am",
|
||||
"Domain Names": "Domainnamen",
|
||||
signedInDisp: "Angemeldet als {0}",
|
||||
signedInDispDisabled: "Authentifizierung deaktiviert.",
|
||||
dnsPortDescription: "DNS server port. Standard ist 53. Der Port kann jederzeit geändert werden.",
|
||||
topic: "Thema",
|
||||
topicExplanation: "MQTT Thema für den monitor",
|
||||
successMessage: "Erfolgsnachricht",
|
||||
successMessageExplanation: "MQTT Nachricht, die als Erfolg angesehen wird",
|
||||
error: "Fehler",
|
||||
critical: "kritisch",
|
||||
wayToGetPagerDutyKey: "Dieser kann unter Service -> Service Directory -> (Select a service) -> Integrations -> Add integration gefunden werden. Hier muss nach \"Events API V2\" gesucht werden. Mehr informationen {0}",
|
||||
"Integration Key": "Schlüssel der Integration",
|
||||
"Integration URL": "URL der Integration",
|
||||
"Auto resolve or acknowledged": "Automatisch lösen oder bestätigen",
|
||||
"do nothing": "nichts tun",
|
||||
"auto acknowledged": "automatisch bestätigen",
|
||||
"auto resolve": "automatisch lösen",
|
||||
"Bark Group": "Bark Gruppe",
|
||||
"Bark Sound": "Bark Klang",
|
||||
"HTTP Headers": "HTTP Kopfzeilen",
|
||||
"Trust Proxy": "Vertrauenswürdiger Proxy",
|
||||
Proxy: "Proxy",
|
||||
HomeAssistant: "Home Assistant",
|
||||
onebotHttpAddress: "OneBot HTTP Adresse",
|
||||
onebotMessageType: "OneBot Nachrichtentyp",
|
||||
onebotGroupMessage: "Gruppe",
|
||||
onebotPrivateMessage: "Privat",
|
||||
onebotUserOrGroupId: "Gruppe/Nutzer ID",
|
||||
onebotSafetyTips: "Zur Sicherheit ein access token setzen",
|
||||
"PushDeer Key": "PushDeer Schlüssel",
|
||||
RadiusSecret: "Radius Geheimnis",
|
||||
RadiusSecretDescription: "Geteiltes Geheimnis zwischen Client und Server",
|
||||
RadiusCalledStationId: "ID der angesprochenen Station",
|
||||
RadiusCalledStationIdDescription: "Identifikation des angesprochenen Geräts",
|
||||
RadiusCallingStationId: "ID der ansprechenden Station",
|
||||
RadiusCallingStationIdDescription: "Identifikation des ansprechenden Geräts",
|
||||
"Certificate Expiry Notification": "Benachrichtigung ablaufendes Zertifikat",
|
||||
"API Username": "API Nutzername",
|
||||
"API Key": "API Schlüssel",
|
||||
"Recipient Number": "Empfängernummer",
|
||||
"From Name/Number": "Von Name/Nummer",
|
||||
"Leave blank to use a shared sender number.": "Leer lassen um eine geteilte Absendernummer zu nutzen.",
|
||||
"Octopush API Version": "Octopush API Version",
|
||||
"Legacy Octopush-DM": "Legacy Octopush-DM",
|
||||
endpoint: "Endpunkt",
|
||||
octopushAPIKey: "\"API Schlüssel\" der HTTP API Zugangsdaten im control panel",
|
||||
octopushLogin: "\"Login\" der HTTP API Zugangsdaten im control panel",
|
||||
promosmsLogin: "API Login Name",
|
||||
promosmsPassword: "API Password",
|
||||
"pushoversounds pushover": "Pushover (Standard)",
|
||||
"pushoversounds bike": "Fahrrad",
|
||||
"pushoversounds bugle": "Signalhorn",
|
||||
"pushoversounds cashregister": "Kasse",
|
||||
"pushoversounds classical": "Klassisch",
|
||||
"pushoversounds cosmic": "Kosmisch",
|
||||
"pushoversounds falling": "Abfallend",
|
||||
"pushoversounds gamelan": "Gamelan",
|
||||
"pushoversounds incoming": "Eingang",
|
||||
"pushoversounds intermission": "Pause",
|
||||
"pushoversounds magic": "Magisch",
|
||||
"pushoversounds mechanical": "Mechanisch",
|
||||
"pushoversounds pianobar": "Piano Bar",
|
||||
"pushoversounds siren": "Sirene",
|
||||
"pushoversounds spacealarm": "Space Alarm",
|
||||
"pushoversounds tugboat": "Schlepper Horn",
|
||||
"pushoversounds alien": "Ausserirdisch (lang)",
|
||||
"pushoversounds climb": "Ansteigende (lang)",
|
||||
"pushoversounds persistent": "Hartnäckig (lang)",
|
||||
"pushoversounds echo": "Pushover Echo (lang)",
|
||||
"pushoversounds updown": "Auf und Ab (lang)",
|
||||
"pushoversounds vibrate": "Nur vibrieren",
|
||||
"pushoversounds none": "Nichts (Stille)",
|
||||
pushyAPIKey: "Geheimer API Schlüssel",
|
||||
pushyToken: "Gerätetoken",
|
||||
"Show update if available": "Verfügbare Updates anzeigen",
|
||||
"Also check beta release": "Auch nach beta Versionen schauen",
|
||||
"Using a Reverse Proxy?": "Wird ein Reverse Proxy genutzt?",
|
||||
"Check how to config it for WebSocket": "Prüfen, wie er für die Nutzung mit WebSocket konfiguriert wird",
|
||||
"Steam Game Server": "Steam Game Server",
|
||||
"Most likely causes:": "Wahrscheinliche Ursachen:",
|
||||
"The resource is no longer available.": "Die Quelle ist nicht mehr verfügbar.",
|
||||
"There might be a typing error in the address.": "Es gibt einen Tippfehler in der Adresse.",
|
||||
"What you can try:": "Was du versuchen kannst:",
|
||||
"Retype the address.": "Schreibe die Adresse erneut.",
|
||||
"Go back to the previous page.": "Gehe zur vorigen Seite.",
|
||||
"Coming Soon": "Kommt bald",
|
||||
wayToGetClickSendSMSToken: "Du kannst einen API Nutzernamen und Schlüssel unter {0} erhalten.",
|
||||
"Connection String": "Verbindungstext",
|
||||
Query: "Abfrage",
|
||||
settingsCertificateExpiry: "TLS Zertifikatsablauf",
|
||||
certificationExpiryDescription: "HTTPS Monitore senden eine Benachrichtigung, wenn das Zertifikat abläuft in:",
|
||||
"Setup Docker Host": "Docker Host einrichten",
|
||||
"Connection Type": "Verbindungstyp",
|
||||
"Docker Daemon": "Docker Daemon",
|
||||
deleteDockerHostMsg: "Bist du sicher diesen docker host für alle Monitore zu löschen?",
|
||||
socket: "Socket",
|
||||
tcp: "TCP / HTTP",
|
||||
"Docker Container": "Docker Container",
|
||||
"Container Name / ID": "Container Name / ID",
|
||||
"Docker Host": "Docker Host",
|
||||
"Docker Hosts": "Docker Hosts",
|
||||
"ntfy Topic": "ntfy Thema",
|
||||
Domain: "Domain",
|
||||
Workstation: "Workstation",
|
||||
disableCloudflaredNoAuthMsg: "Du bist im nicht-authentifizieren Modus, ein Passwort wird nicht benötigt.",
|
||||
trustProxyDescription: "Vertraue 'X-Forwarded-*' headern. Wenn man die richtige client IP haben möchte und Uptime Kuma hinter einem Proxy wie Nginx or Apache läuft, wollte dies aktiviert werden.",
|
||||
wayToGetLineNotifyToken: "Du kannst hier ein Token erhalten: {0}",
|
||||
Examples: "Beispiele",
|
||||
"Home Assistant URL": "Home Assistant URL",
|
||||
"Long-Lived Access Token": "Lange gültiges Access Token",
|
||||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Lange gültige Access Token können durch klicken auf den Profilnamen (unten links) und dann einen Klick auf Create Token am Ende erstellt werden. ",
|
||||
"Notification Service": "Benachrichtigungsdienst",
|
||||
"default: notify all devices": "standard: Alle Geräte benachrichtigen",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Eine Liste der Benachrichtigungsdienste kann im Home Assistant unter \"Developer Tools > Services\" gefunden werden, wnen man nach \"notification\" sucht um den Geräte-/Telefonnamen zu finden.",
|
||||
"Automations can optionally be triggered in Home Assistant:": "Automatisierungen können optional im Home Assistant ausgelöst werden:",
|
||||
"Trigger type:": "Auslöser:",
|
||||
"Event type:": "Ereignistyp:",
|
||||
"Event data:": "Ereignis daten:",
|
||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "Dann eine Aktion wählen, zum Beispiel eine Scene wählen in der ein RGB Licht rot ist.",
|
||||
"Frontend Version": "Frontend Version",
|
||||
"Frontend Version do not match backend version!": "Die Frontend Version stimmt nicht mit der backend version überein!",
|
||||
Maintenance: "Wartung",
|
||||
statusMaintenance: "Wartung",
|
||||
"Schedule maintenance": "Geplante Wartung",
|
||||
"Affected Monitors": "Betroffene Monitore",
|
||||
"Pick Affected Monitors...": "Wähle betroffene Monitore...",
|
||||
"Start of maintenance": "Beginn der Wartung",
|
||||
"All Status Pages": "Alle Status Seiten",
|
||||
"Select status pages...": "Wähle Status Seiten...",
|
||||
recurringIntervalMessage: "einmal pro Tag ausgeführt | Wird alle {0} Tage ausgführt",
|
||||
affectedMonitorsDescription: "Wähle alle Monitore die von der Wartung betroffen sind",
|
||||
affectedStatusPages: "Zeige diese Nachricht auf ausgewählten Status Seiten",
|
||||
atLeastOneMonitor: "Wähle mindestens einen Monitor",
|
||||
deleteMaintenanceMsg: "Möchtest du diese Wartung löschen?",
|
||||
"Base URL": "Basis URL",
|
||||
goAlertInfo: "GoAlert ist eine Open-Source Applikation für Rufbereitschaftsplanung, automatische Eskalation und Benachrichtigung (z.B. SMS oder Telefonanrufe). Beauftragen Sie automatisch die richtige Person, auf die richtige Art und Weise und zum richtigen Zeitpunkt. {0}",
|
||||
goAlertIntegrationKeyInfo: "Bekommt einen generischen API Schlüssel in folgenden Format \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\". Normalerweise entspricht dies dem Wert des Token aus der URL.",
|
||||
goAlert: "GoAlert",
|
||||
backupOutdatedWarning: "Veraltet: Eine menge Neuerungen sind eingeflossen und diese Funktion wurde etwas vernachlässigt worden. Es kann kein vollständiges Backup erstellt oder eingespielt werden.",
|
||||
backupRecommend: "Bitte Backup das Volume oder den Ordner (./ data /) selbst.",
|
||||
Optional: "Optional",
|
||||
squadcast: "Squadcast",
|
||||
SendKey: "SendKey",
|
||||
"SMSManager API Docs": "SMSManager API Dokumente",
|
||||
"Gateway Type": "Gateway Type",
|
||||
SMSManager: "SMSManager",
|
||||
"You can divide numbers with": "Du kannst Zahlen teilen mit",
|
||||
or: "oder",
|
||||
recurringInterval: "Intervall",
|
||||
Recurring: "Wiederkehrend",
|
||||
strategyManual: "Active/Inactive Manually",
|
||||
warningTimezone: "Es wird die Zeitzone des Servers genutzt",
|
||||
weekdayShortMon: "Mo",
|
||||
weekdayShortTue: "Di",
|
||||
weekdayShortWed: "Mi",
|
||||
weekdayShortThu: "Do",
|
||||
weekdayShortFri: "Fr",
|
||||
weekdayShortSat: "Sa",
|
||||
weekdayShortSun: "So",
|
||||
dayOfWeek: "Tag der Woche",
|
||||
dayOfMonth: "Tag im Monat",
|
||||
lastDay: "Letzter Tag",
|
||||
lastDay1: "Letzter Tag im Monat",
|
||||
lastDay2: "Vorletzer Tag im Monat",
|
||||
lastDay3: "3. letzter Tag im Monat",
|
||||
lastDay4: "4. letzter Tag im Monat",
|
||||
"No Maintenance": "Keine Wartung",
|
||||
pauseMaintenanceMsg: "Möchtest du wirklich pausieren?",
|
||||
"maintenanceStatus-under-maintenance": "Unter Wartung",
|
||||
"maintenanceStatus-inactive": "Inaktiv",
|
||||
"maintenanceStatus-scheduled": "Geplant",
|
||||
"maintenanceStatus-ended": "Ende",
|
||||
"maintenanceStatus-unknown": "Unbekannt",
|
||||
"Display Timezone": "Zeitzone anzeigen",
|
||||
"Server Timezone": "Server Zeitzone",
|
||||
statusPageMaintenanceEndDate: "Ende",
|
||||
};
|
|
@ -96,7 +96,7 @@ export default {
|
|||
"Notification Type": "Benachrichtigungsdienst",
|
||||
Email: "E-Mail",
|
||||
Test: "Test",
|
||||
"Certificate Info": "Zertifikatsinfo",
|
||||
"Certificate Info": "Zertifikatsinformation",
|
||||
keywordDescription: "Ein Suchwort in der HTML- oder JSON-Ausgabe finden. Bitte beachte: es wird zwischen Groß-/Kleinschreibung unterschieden.",
|
||||
deleteMonitorMsg: "Bist du sicher, dass du den Monitor löschen möchtest?",
|
||||
deleteNotificationMsg: "Möchtest du diese Benachrichtigung wirklich für alle Monitore löschen?",
|
||||
|
@ -181,7 +181,7 @@ export default {
|
|||
"Degraded Service": "Eingeschränkter Dienst",
|
||||
"Add Group": "Gruppe hinzufügen",
|
||||
"Add a monitor": "Monitor hinzufügen",
|
||||
"Edit Status Page": "Bearbeite Status-Seite",
|
||||
"Edit Status Page": "Statusseite bearbeiten",
|
||||
"Go to Dashboard": "Gehe zum Dashboard",
|
||||
"Status Page": "Status-Seite",
|
||||
"Status Pages": "Status-Seiten",
|
||||
|
@ -204,7 +204,7 @@ export default {
|
|||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"Primary Base URL": "Primär URL",
|
||||
"Primary Base URL": "Primäre Basis-URL",
|
||||
"Push URL": "Push URL",
|
||||
needPushEvery: "Du solltest diese URL alle {0} Sekunden aufrufen",
|
||||
pushOptionalParams: "Optionale Parameter: {0}",
|
||||
|
@ -383,7 +383,7 @@ export default {
|
|||
deleteProxyMsg: "Bist du sicher, dass du diesen Proxy für alle Monitore löschen willst?",
|
||||
proxyDescription: "Proxies müssen einem Monitor zugewiesen werden, um zu funktionieren.",
|
||||
enableProxyDescription: "Dieser Proxy wird keinen Effekt auf Monitor-Anfragen haben, bis er aktiviert ist. Du kannst ihn temporär von allen Monitoren nach Aktivierungsstatus deaktivieren.",
|
||||
setAsDefaultProxyDescription: "Dieser Proxy wird standardmäßig für alle neuen Monitore aktiviert sein. Du kannst den Proxy immernoch für jeden Monitor einzeln deaktivieren.",
|
||||
setAsDefaultProxyDescription: "Dieser Proxy wird standardmäßig für alle neuen Monitore aktiviert sein. Du kannst den Proxy immer noch für jeden Monitor einzeln deaktivieren.",
|
||||
"Certificate Chain": "Zertifikatskette",
|
||||
Valid: "Gültig",
|
||||
Invalid: "Ungültig",
|
||||
|
@ -496,7 +496,7 @@ export default {
|
|||
"API Key": "API Schlüssel",
|
||||
"Recipient Number": "Empfängernummer",
|
||||
"From Name/Number": "Von Name/Nummer",
|
||||
"Leave blank to use a shared sender number.": "Leer lassen um eine geteilte Sendernummer zu nutzen.",
|
||||
"Leave blank to use a shared sender number.": "Leer lassen um eine geteilte Absendernummer zu nutzen.",
|
||||
"Octopush API Version": "Octopush API Version",
|
||||
"Legacy Octopush-DM": "Legacy Octopush-DM",
|
||||
endpoint: "Endpunkt",
|
||||
|
@ -530,7 +530,7 @@ export default {
|
|||
pushyAPIKey: "Geheimer API Schlüssel",
|
||||
pushyToken: "Gerätetoken",
|
||||
"Show update if available": "Verfügbare Updates anzeigen",
|
||||
"Also check beta release": "Auch nach beta Versionen schauen",
|
||||
"Also check beta release": "Auch nach Beta Versionen schauen",
|
||||
"Using a Reverse Proxy?": "Wird ein Reverse Proxy genutzt?",
|
||||
"Check how to config it for WebSocket": "Prüfen, wie er für die Nutzung mit WebSocket konfiguriert wird",
|
||||
"Steam Game Server": "Steam Game Server",
|
||||
|
@ -568,9 +568,9 @@ export default {
|
|||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Lange gültige Access Token können durch klicken auf den Profilnamen (unten links) und dann einen Klick auf Create Token am Ende erstellt werden. ",
|
||||
"Notification Service": "Benachrichtigungsdienst",
|
||||
"default: notify all devices": "standard: Alle Geräte benachrichtigen",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Eine Liste der Benachrichtigungsdiesnte kann im Home Assistant unter \"Developer Tools > Services\" gefunden werden, wnen man nach \"notification\" sucht um den Geräte-/Telefonnamen zu finden.",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Eine Liste der Benachrichtigungsdienste kann im Home Assistant unter \"Developer Tools > Services\" gefunden werden, wnen man nach \"notification\" sucht um den Geräte-/Telefonnamen zu finden.",
|
||||
"Automations can optionally be triggered in Home Assistant:": "Automatisierungen können optional im Home Assistant ausgelöst werden:",
|
||||
"Trigger type:": "Auslösertyp:",
|
||||
"Trigger type:": "Auslöser:",
|
||||
"Event type:": "Ereignistyp:",
|
||||
"Event data:": "Ereignis daten:",
|
||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "Dann eine Aktion wählen, zum Beispiel eine Scene wählen in der ein RGB Licht rot ist.",
|
||||
|
@ -583,18 +583,18 @@ export default {
|
|||
"Pick Affected Monitors...": "Wähle betroffene Monitore...",
|
||||
"Start of maintenance": "Beginn der Wartung",
|
||||
"All Status Pages": "Alle Status Seiten",
|
||||
"Select status pages...": "Wähle Status Seiten...",
|
||||
recurringIntervalMessage: "einmal pro Tag ausgeführt | Wird alle {0} Tage ausgführt",
|
||||
affectedMonitorsDescription: "Wähle alle Monitore die von der Wartung betroffen sind",
|
||||
affectedStatusPages: "Zeige diese Nachricht auf ausgewählten Status Seiten",
|
||||
"Select status pages...": "Statusseiten auswählen...",
|
||||
recurringIntervalMessage: "Einmal pro Tag ausgeführt | Wird alle {0} Tage ausgführt",
|
||||
affectedMonitorsDescription: "Wähle Monitore aus, die von der aktuellen Wartung betroffen sind",
|
||||
affectedStatusPages: "Diese Wartungsmeldung auf ausgewählten Statusseiten anzeigen",
|
||||
atLeastOneMonitor: "Wähle mindestens einen Monitor",
|
||||
deleteMaintenanceMsg: "Möchtest du diese Wartung löschen?",
|
||||
"Base URL": "Basis URL",
|
||||
goAlertInfo: "GoAlert ist eine Open-Source Applikation für Rufbereitschaft Planung, automaitsche Esklaltion und Benachrichtigung (z.B. SMS oder Telefonanrufe). Beauftragen Sie automatisch die richtige Person, auf die richtige Art und Weise und zum richtigen Zeitpunkt! {0}",
|
||||
goAlertIntegrationKeyInfo: "Bekomm einenen gernerischen API Schlüssel in folgeden Format \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\". Normalerweise der Wert des Token aus der URL.",
|
||||
goAlertInfo: "GoAlert ist eine Open-Source Applikation für Rufbereitschaftsplanung, automatische Eskalation und Benachrichtigung (z.B. SMS oder Telefonanrufe). Beauftragen Sie automatisch die richtige Person, auf die richtige Art und Weise und zum richtigen Zeitpunkt. {0}",
|
||||
goAlertIntegrationKeyInfo: "Bekommt einen generischen API Schlüssel in folgenden Format \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\". Normalerweise entspricht dies dem Wert des Token aus der URL.",
|
||||
goAlert: "GoAlert",
|
||||
backupOutdatedWarning: "Veraltet: Eine menge Neuerungen sind eingeflossen und diese Funktion wurde etwas vernachlässigt worden. Es kann kein vollständiges Backup erstellt oder eingspielt werden.",
|
||||
backupRecommend: "Bitte Backup das Volume oder den Ordner (./ data /) selbst.",
|
||||
backupOutdatedWarning: "Veraltet: Da viele Funktionen hinzugefügt wurden und diese Sicherungsfunktion nicht mehr gepflegt wird, kann sie keine vollständige Sicherung erstellen oder wiederherstellen.",
|
||||
backupRecommend: "Bitte sichere stattdessen das Volume oder den Datenordner (./data/) direkt.",
|
||||
Optional: "Optional",
|
||||
squadcast: "Squadcast",
|
||||
SendKey: "SendKey",
|
||||
|
@ -605,8 +605,11 @@ export default {
|
|||
or: "oder",
|
||||
recurringInterval: "Intervall",
|
||||
Recurring: "Wiederkehrend",
|
||||
strategyManual: "Active/Inactive Manually",
|
||||
warningTimezone: "Es wird die Zeitzone des Servers genutzt",
|
||||
"Single Maintenance Window": "Einzigartiges Wartungsfenster",
|
||||
"Maintenance Time Window of a Day": "Zeitfenster für die Wartung",
|
||||
"Effective Date Range": "Bereich der Wirksamkeitsdaten",
|
||||
strategyManual: "Aktiv/Inaktiv Manuell",
|
||||
warningTimezone: "Es wird die Zeitzone des Servers verwendet",
|
||||
weekdayShortMon: "Mo",
|
||||
weekdayShortTue: "Di",
|
||||
weekdayShortWed: "Mi",
|
||||
|
@ -622,6 +625,7 @@ export default {
|
|||
lastDay3: "3. letzter Tag im Monat",
|
||||
lastDay4: "4. letzter Tag im Monat",
|
||||
"No Maintenance": "Keine Wartung",
|
||||
"Schedule Maintenance": "Wartung planen",
|
||||
pauseMaintenanceMsg: "Möchtest du wirklich pausieren?",
|
||||
"maintenanceStatus-under-maintenance": "Unter Wartung",
|
||||
"maintenanceStatus-inactive": "Inaktiv",
|
||||
|
@ -630,5 +634,8 @@ export default {
|
|||
"maintenanceStatus-unknown": "Unbekannt",
|
||||
"Display Timezone": "Zeitzone anzeigen",
|
||||
"Server Timezone": "Server Zeitzone",
|
||||
"Date and Time": "Datum und Zeit",
|
||||
"DateTime Range": "Datums- und Zeitbereich",
|
||||
Strategy: "Strategie",
|
||||
statusPageMaintenanceEndDate: "Ende",
|
||||
};
|
||||
|
|
|
@ -194,6 +194,7 @@ export default {
|
|||
here: "εδώ",
|
||||
Required: "Απαιτείται",
|
||||
telegram: "Telegram",
|
||||
"ZohoCliq": "ZohoCliq",
|
||||
"Bot Token": "Διακριτικό Bot",
|
||||
wayToGetTelegramToken: "Μπορείτε να πάρετε ένα διακριτικό από {0}.",
|
||||
"Chat ID": "Chat ID",
|
||||
|
@ -224,6 +225,7 @@ export default {
|
|||
teams: "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "Μπορείτε να μάθετε πώς να δημιουργείτε μια διεύθυνση URL webhook {0}.",
|
||||
wayToGetZohoCliqURL: "Μπορείτε να μάθετε πώς να δημιουργείτε μια διεύθυνση URL webhook {0}.",
|
||||
signal: "Signal",
|
||||
Number: "Αριθμός",
|
||||
Recipients: "Αποδέκτες",
|
||||
|
|
|
@ -74,6 +74,7 @@ export default {
|
|||
Current: "Current",
|
||||
Uptime: "Uptime",
|
||||
"Cert Exp.": "Cert Exp.",
|
||||
Monitor: "Monitor | Monitors",
|
||||
day: "day | days",
|
||||
"-day": "-day",
|
||||
hour: "hour",
|
||||
|
@ -190,6 +191,7 @@ export default {
|
|||
Indigo: "Indigo",
|
||||
Purple: "Purple",
|
||||
Pink: "Pink",
|
||||
Custom: "Custom",
|
||||
"Search...": "Search...",
|
||||
"Avg. Ping": "Avg. Ping",
|
||||
"Avg. Response": "Avg. Response",
|
||||
|
@ -209,6 +211,7 @@ export default {
|
|||
here: "here",
|
||||
Required: "Required",
|
||||
telegram: "Telegram",
|
||||
"ZohoCliq": "ZohoCliq",
|
||||
"Bot Token": "Bot Token",
|
||||
wayToGetTelegramToken: "You can get a token from {0}.",
|
||||
"Chat ID": "Chat ID",
|
||||
|
@ -221,6 +224,8 @@ export default {
|
|||
"Content Type": "Content Type",
|
||||
webhookJsonDesc: "{0} is good for any modern HTTP servers such as Express.js",
|
||||
webhookFormDataDesc: "{multipart} is good for PHP. The JSON will need to be parsed with {decodeFunction}",
|
||||
webhookAdditionalHeadersTitle: "Additional Headers",
|
||||
webhookAdditionalHeadersDesc: "Sets additional headers sent with the webhook.",
|
||||
smtp: "Email (SMTP)",
|
||||
secureOptionNone: "None / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
|
@ -239,6 +244,7 @@ export default {
|
|||
teams: "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "You can learn how to create a webhook URL {0}.",
|
||||
wayToGetZohoCliqURL: "You can learn how to create a webhook URL {0}.",
|
||||
signal: "Signal",
|
||||
Number: "Number",
|
||||
Recipients: "Recipients",
|
||||
|
@ -268,6 +274,10 @@ export default {
|
|||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
GoogleChat: "Google Chat (Google Workspace only)",
|
||||
pushbullet: "Pushbullet",
|
||||
Kook: "Kook",
|
||||
wayToGetKookBotToken: "Create application and get your bot token at {0}",
|
||||
wayToGetKookGuildID: "Switch on 'Developer Mode' in Kook setting, and right click the guild to get its ID",
|
||||
"Guild ID": "Guild ID",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "User Key",
|
||||
|
@ -607,16 +617,16 @@ export default {
|
|||
goAlert: "GoAlert",
|
||||
backupOutdatedWarning: "Deprecated: Since a lot of features added and this backup feature is a bit unmaintained, it cannot generate or restore a complete backup.",
|
||||
backupRecommend: "Please backup the volume or the data folder (./data/) directly instead.",
|
||||
"Optional": "Optional",
|
||||
Optional: "Optional",
|
||||
squadcast: "Squadcast",
|
||||
SendKey: "SendKey",
|
||||
"SMSManager API Docs": "SMSManager API Docs ",
|
||||
"Gateway Type": "Gateway Type",
|
||||
SMSManager: "SMSManager",
|
||||
"You can divide numbers with": "You can divide numbers with",
|
||||
"or": "or",
|
||||
or: "or",
|
||||
recurringInterval: "Interval",
|
||||
"Recurring": "Recurring",
|
||||
Recurring: "Recurring",
|
||||
strategyManual: "Active/Inactive Manually",
|
||||
warningTimezone: "It is using the server's timezone",
|
||||
weekdayShortMon: "Mon",
|
||||
|
@ -644,4 +654,30 @@ export default {
|
|||
"Server Timezone": "Server Timezone",
|
||||
statusPageMaintenanceEndDate: "End",
|
||||
IconUrl: "Icon URL",
|
||||
"Enable DNS Cache": "Enable DNS Cache",
|
||||
Enable: "Enable",
|
||||
Disable: "Disable",
|
||||
dnsCacheDescription: "It may be not working in some IPv6 environments, disable it if you encounter any issues.",
|
||||
"Single Maintenance Window": "Single Maintenance Window",
|
||||
"Maintenance Time Window of a Day": "Maintenance Time Window of a Day",
|
||||
"Effective Date Range": "Effective Date Range",
|
||||
"Schedule Maintenance": "Schedule Maintenance",
|
||||
"Date and Time": "Date and Time",
|
||||
"DateTime Range": "DateTime Range",
|
||||
Strategy: "Strategy",
|
||||
"Free Mobile User Identifier": "Free Mobile User Identifier",
|
||||
"Free Mobile API Key": "Free Mobile API Key",
|
||||
"Enable TLS": "Enable TLS",
|
||||
"Proto Service Name": "Proto Service Name",
|
||||
"Proto Method": "Proto Method",
|
||||
"Proto Content": "Proto Content",
|
||||
Economy: "Economy",
|
||||
Lowcost: "Lowcost",
|
||||
high: "high",
|
||||
"General Monitor Type": "General Monitor Type",
|
||||
"Passive Monitor Type": "Passive Monitor Type",
|
||||
"Specific Monitor Type": "Specific Monitor Type",
|
||||
dataRetentionTimeError: "Retention period must be 0 or greater",
|
||||
infiniteRetention: "Set to 0 for infinite retention.",
|
||||
confirmDeleteTagMsg: "Are you sure you want to delete this tag? Monitors associated with this tag will not be deleted.",
|
||||
};
|
||||
|
|
|
@ -191,6 +191,7 @@ export default {
|
|||
here: "Hemen",
|
||||
Required: "Beharrezkoa",
|
||||
telegram: "Telegram",
|
||||
"ZohoCliq": "ZohoCliq",
|
||||
"Bot Token": "Bot Tokena",
|
||||
wayToGetTelegramToken: "You can get a token from {0}.",
|
||||
"Chat ID": "Txat IDa",
|
||||
|
@ -221,6 +222,7 @@ export default {
|
|||
teams: "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "You can learn how to create a webhook URL {0}.",
|
||||
wayToGetZohoCliqURL: "You can learn how to create a webhook URL {0}.",
|
||||
signal: "Signal",
|
||||
Number: "Zenbakia",
|
||||
Recipients: "Recipients",
|
||||
|
|
|
@ -1,31 +1,49 @@
|
|||
export default {
|
||||
languageName: "Français",
|
||||
checkEverySecond: "Vérifier toutes les {0} secondes",
|
||||
retryCheckEverySecond: "Réessayer toutes les {0} secondes.",
|
||||
retriesDescription: "Nombre d'essais avant que le service soit déclaré hors-ligne.",
|
||||
retryCheckEverySecond: "Réessayer toutes les {0} secondes",
|
||||
resendEveryXTimes: "Renvoyez toutes les {0} fois",
|
||||
resendDisabled: "Renvoi désactivé",
|
||||
retriesDescription: "Nombre d'essais avant que le service ne soit déclaré hors ligne et qu'une notification soit envoyée.",
|
||||
ignoreTLSError: "Ignorer les erreurs liées au certificat SSL/TLS",
|
||||
upsideDownModeDescription: "Si le service est en ligne, il sera alors noté hors-ligne et vice-versa.",
|
||||
maxRedirectDescription: "Nombre maximal de redirections avant que le service soit noté hors-ligne.",
|
||||
acceptedStatusCodesDescription: "Codes HTTP considérés comme en ligne",
|
||||
upsideDownModeDescription: "Si le service est en ligne, il sera alors noté hors ligne et vice-versa.",
|
||||
maxRedirectDescription: "Nombre maximal de redirections avant que le service ne soit marqué comme hors ligne.",
|
||||
enableGRPCTls: "Autoriser l'envoi d'une requête gRPC avec une connexion TLS",
|
||||
grpcMethodDescription: "Le nom de la méthode est converti au format CamelCase tel que sayHello, check, etc.",
|
||||
acceptedStatusCodesDescription: "Codes HTTP qui considèrent le service comme étant disponible.",
|
||||
Maintenance: "Maintenance",
|
||||
statusMaintenance: "Maintenance",
|
||||
"Schedule maintenance": "Planifier la maintenance",
|
||||
"Affected Monitors": "Sondes concernées",
|
||||
"Pick Affected Monitors...": "Sélectionner les sondes concernées...",
|
||||
"Start of maintenance": "Début de la maintenance",
|
||||
"All Status Pages": "Toutes les pages d'état",
|
||||
"Select status pages...": "Sélectionner les pages d'état...",
|
||||
recurringIntervalMessage: "Exécuter une fois par jour | Exécuter une fois tous les {0} jours",
|
||||
affectedMonitorsDescription: "Sélectionnez les sondes concernées par la maintenance en cours",
|
||||
affectedStatusPages: "Afficher ce message de maintenance sur les pages d'état sélectionnées",
|
||||
atLeastOneMonitor: "Sélectionnez au moins une sonde concernée",
|
||||
passwordNotMatchMsg: "Les mots de passe ne correspondent pas",
|
||||
notificationDescription: "Une fois ajoutée, vous devez l'activer manuellement dans les paramètres de vos hôtes.",
|
||||
keywordDescription: "Le mot clé sera recherché dans la réponse HTML/JSON reçue du site internet.",
|
||||
pauseDashboardHome: "En pause",
|
||||
deleteMonitorMsg: "Êtes-vous sûr de vouloir supprimer cette sonde ?",
|
||||
deleteMonitorMsg: "Êtes-vous sûr de vouloir supprimer cette sonde ?",
|
||||
deleteMaintenanceMsg: "Voulez-vous vraiment supprimer cette maintenance ?",
|
||||
deleteNotificationMsg: "Êtes-vous sûr de vouloir supprimer ce type de notifications ? Une fois désactivée, les services qui l'utilisent ne pourront plus envoyer de notifications.",
|
||||
dnsPortDescription: "Port du serveur DNS. La valeur par défaut est 53. Vous pouvez modifier le port à tout moment.",
|
||||
resolverserverDescription: "Le DNS de Cloudflare est utilisé par défaut, mais vous pouvez le changer si vous le souhaitez.",
|
||||
rrtypeDescription: "Veuillez sélectionner un type d'enregistrement DNS",
|
||||
pauseMonitorMsg: "Êtes-vous sûr de vouloir mettre en pause cette sonde ?",
|
||||
pauseMonitorMsg: "Êtes-vous sûr de vouloir mettre en pause cette sonde ?",
|
||||
enableDefaultNotificationDescription: "Pour chaque nouvelle sonde, cette notification sera activée par défaut. Vous pouvez toujours désactiver la notification séparément pour chaque sonde.",
|
||||
clearEventsMsg: "Êtes-vous sûr de vouloir supprimer tous les événements pour cette sonde ?",
|
||||
clearHeartbeatsMsg: "Êtes-vous sûr de vouloir supprimer toutes les vérifications pour cette sonde ?",
|
||||
clearEventsMsg: "Êtes-vous sûr de vouloir supprimer tous les événements pour cette sonde ?",
|
||||
clearHeartbeatsMsg: "Êtes-vous sûr de vouloir supprimer toutes les vérifications pour cette sonde ?",
|
||||
confirmClearStatisticsMsg: "Êtes-vous sûr de vouloir supprimer toutes les statistiques ?",
|
||||
importHandleDescription: "Choisissez 'Ignorer l'existant' si vous voulez ignorer chaque sonde ou notification portant le même nom. L'option 'Écraser' supprime toutes les sondes et notifications existantes.",
|
||||
importHandleDescription: "Choisissez « Ignorer l'existant » si vous voulez ignorer chaque sonde ou notification portant le même nom. L'option « Écraser » supprime toutes les sondes et notifications existantes.",
|
||||
confirmImportMsg: "Êtes-vous sûr de vouloir importer la sauvegarde ? Veuillez vous assurer que vous avez sélectionné la bonne option d'importation.",
|
||||
twoFAVerifyLabel: "Veuillez saisir votre jeton pour vérifier que le système 2FA fonctionne.",
|
||||
tokenValidSettingsMsg: "Le jeton est valide. Vous pouvez maintenant sauvegarder les paramètres 2FA.",
|
||||
confirmEnableTwoFAMsg: "Êtes-vous sûr de vouloir activer le 2FA ?",
|
||||
confirmDisableTwoFAMsg: "Êtes-vous sûr de vouloir désactiver le 2FA ?",
|
||||
tokenValidSettingsMsg: "Le jeton est valide. Vous pouvez maintenant sauvegarder les paramètres de double authentification (2FA).",
|
||||
confirmEnableTwoFAMsg: "Êtes-vous sûr de vouloir activer la double authentification (2FA) ?",
|
||||
confirmDisableTwoFAMsg: "Êtes-vous sûr de vouloir désactiver la double authentification (2FA) ?",
|
||||
Settings: "Paramètres",
|
||||
Dashboard: "Tableau de bord",
|
||||
"New Update": "Mise à jour disponible",
|
||||
|
@ -33,8 +51,9 @@ export default {
|
|||
Appearance: "Apparence",
|
||||
Theme: "Thème",
|
||||
General: "Général",
|
||||
"Primary Base URL": "URL principale",
|
||||
Version: "Version",
|
||||
"Check Update On GitHub": "Consulter les mises à jour sur Github",
|
||||
"Check Update On GitHub": "Consulter les mises à jour sur GitHub",
|
||||
List: "Lister",
|
||||
Add: "Ajouter",
|
||||
"Add New Monitor": "Ajouter une nouvelle sonde",
|
||||
|
@ -43,25 +62,25 @@ export default {
|
|||
Down: "Hors ligne",
|
||||
Pending: "En attente",
|
||||
Unknown: "Inconnu",
|
||||
Pause: "En Pause",
|
||||
Pause: "En pause",
|
||||
Name: "Nom",
|
||||
Status: "État",
|
||||
DateTime: "Heure",
|
||||
Message: "Messages",
|
||||
"No important events": "Pas d'évènements important",
|
||||
"No important events": "Aucun évènement important",
|
||||
Resume: "Reprendre",
|
||||
Edit: "Modifier",
|
||||
Delete: "Supprimer",
|
||||
Current: "Actuellement",
|
||||
Uptime: "Uptime",
|
||||
Uptime: "Disponibilité",
|
||||
"Cert Exp.": "Expiration SSL",
|
||||
day: "jour | jours",
|
||||
"-day": "-jours",
|
||||
hour: "-heure",
|
||||
"-hour": "-heures",
|
||||
"-day": " jours",
|
||||
hour: "heure",
|
||||
"-hour": " heure",
|
||||
Response: "Temps de réponse",
|
||||
Ping: "Ping",
|
||||
"Monitor Type": "Type de Sonde",
|
||||
"Monitor Type": "Type de sonde",
|
||||
Keyword: "Mot-clé",
|
||||
"Friendly Name": "Nom d'affichage",
|
||||
URL: "URL",
|
||||
|
@ -70,25 +89,29 @@ export default {
|
|||
"Heartbeat Interval": "Intervalle de vérification",
|
||||
Retries: "Essais",
|
||||
"Heartbeat Retry Interval": "Réessayer l'intervalle de vérification",
|
||||
"Resend Notification if Down X times consequently": "Renvoyer une notification si hors ligne X fois",
|
||||
Advanced: "Avancé",
|
||||
"Upside Down Mode": "Mode inversé",
|
||||
"Max. Redirects": "Nombre maximum de redirections",
|
||||
"Accepted Status Codes": "Codes HTTP acceptés",
|
||||
"Push URL": "Push URL",
|
||||
needPushEvery: "Vous devez appeler cette URL toutes les {0} secondes.",
|
||||
pushOptionalParams: "Paramètres facultatifs : {0}",
|
||||
Save: "Sauvegarder",
|
||||
Notifications: "Notifications",
|
||||
"Not available, please setup.": "Pas de système de notification disponible, merci de le configurer",
|
||||
"Not available, please setup.": "Non disponible, merci de le configurer.",
|
||||
"Setup Notification": "Créer une notification",
|
||||
Light: "Clair",
|
||||
Dark: "Sombre",
|
||||
Auto: "Automatique",
|
||||
"Theme - Heartbeat Bar": "Voir les services surveillés",
|
||||
"Theme - Heartbeat Bar": "Thème - barres d'état",
|
||||
Normal: "Normal",
|
||||
Bottom: "En dessous",
|
||||
None: "Aucun",
|
||||
Timezone: "Fuseau Horaire",
|
||||
Timezone: "Fuseau horaire",
|
||||
"Search Engine Visibility": "Visibilité par les moteurs de recherche",
|
||||
"Allow indexing": "Autoriser l'indexation par des moteurs de recherche",
|
||||
"Discourage search engines from indexing site": "Refuser l'indexation par des moteurs de recherche",
|
||||
"Allow indexing": "Autoriser l'indexation",
|
||||
"Discourage search engines from indexing site": "Refuser l'indexation",
|
||||
"Change Password": "Changer le mot de passe",
|
||||
"Current Password": "Mot de passe actuel",
|
||||
"New Password": "Nouveau mot de passe",
|
||||
|
@ -96,26 +119,29 @@ export default {
|
|||
"Update Password": "Mettre à jour le mot de passe",
|
||||
"Disable Auth": "Désactiver l'authentification",
|
||||
"Enable Auth": "Activer l'authentification",
|
||||
Logout: "Se déconnecter",
|
||||
"disableauth.message1": "Voulez-vous vraiment <strong>désactiver l'authentification</strong> ?",
|
||||
"disableauth.message2": "Cette fonctionnalité est conçue pour les scénarios <strong>où vous avez l'intention d'implémenter une authentification tierce</strong> devant Uptime Kuma, comme Cloudflare Access, Authelia ou d'autres mécanismes d'authentification.",
|
||||
"Please use this option carefully!": "Veuillez utiliser cette option avec précaution !",
|
||||
Logout: "Déconnexion",
|
||||
Leave: "Quitter",
|
||||
"I understand, please disable": "Je comprends, désactivez-le",
|
||||
"I understand, please disable": "Je comprends, désactivez-la",
|
||||
Confirm: "Confirmer",
|
||||
Yes: "Oui",
|
||||
No: "Non",
|
||||
Username: "Nom d'utilisateur",
|
||||
Password: "Mot de passe",
|
||||
"Remember me": "Se souvenir de moi",
|
||||
Login: "Se connecter",
|
||||
Login: "Connexion",
|
||||
"No Monitors, please": "Pas de sondes, veuillez",
|
||||
"add one": "en ajouter une",
|
||||
"Notification Type": "Type de notification",
|
||||
Email: "Email",
|
||||
Email: "Courriel",
|
||||
Test: "Tester",
|
||||
"Certificate Info": "Informations sur le certificat SSL",
|
||||
"Resolver Server": "Serveur DNS utilisé",
|
||||
"Resource Record Type": "Type d'enregistrement DNS recherché",
|
||||
"Last Result": "Dernier résultat",
|
||||
"Create your admin account": "Créez votre compte administrateur",
|
||||
"Create your admin account": "Créer votre compte administrateur",
|
||||
"Repeat Password": "Répéter le mot de passe",
|
||||
"Import Backup": "Importation de la sauvegarde",
|
||||
"Export Backup": "Exportation de la sauvegarde",
|
||||
|
@ -127,9 +153,9 @@ export default {
|
|||
"Apply on all existing monitors": "Appliquer sur toutes les sondes existantes",
|
||||
Create: "Créer",
|
||||
"Clear Data": "Effacer les données",
|
||||
Events: "Evénements",
|
||||
Events: "Événements",
|
||||
Heartbeats: "Vérifications",
|
||||
"Auto Get": "Récuperer automatiquement",
|
||||
"Auto Get": "Récupérer automatiquement",
|
||||
backupDescription: "Vous pouvez sauvegarder toutes les sondes et toutes les notifications dans un fichier JSON.",
|
||||
backupDescription2: "PS : Les données relatives à l'historique et aux événements ne sont pas incluses.",
|
||||
backupDescription3: "Les données sensibles telles que les jetons de notification sont incluses dans le fichier d'exportation, veuillez les conserver soigneusement.",
|
||||
|
@ -137,15 +163,15 @@ export default {
|
|||
alertWrongFileType: "Veuillez sélectionner un fichier JSON à importer.",
|
||||
"Clear all statistics": "Effacer toutes les statistiques",
|
||||
"Skip existing": "Sauter l'existant",
|
||||
Overwrite: "Ecraser",
|
||||
Overwrite: "Écraser",
|
||||
Options: "Options",
|
||||
"Keep both": "Garder les deux",
|
||||
"Verify Token": "Vérifier le jeton",
|
||||
"Setup 2FA": "Configurer 2FA",
|
||||
"Enable 2FA": "Activer 2FA",
|
||||
"Disable 2FA": "Désactiver 2FA",
|
||||
"2FA Settings": "Paramètres 2FA",
|
||||
"Two Factor Authentication": "Authentification à deux facteurs",
|
||||
"Setup 2FA": "Configurer la double authentification (2FA)",
|
||||
"Enable 2FA": "Activer la double authentification (2FA)",
|
||||
"Disable 2FA": "Désactiver la double authentification (2FA)",
|
||||
"2FA Settings": "Paramètres de la la double authentification (2FA)",
|
||||
"Two Factor Authentication": "Double authentification",
|
||||
Active: "Actif",
|
||||
Inactive: "Inactif",
|
||||
Token: "Jeton",
|
||||
|
@ -179,52 +205,49 @@ export default {
|
|||
"Go to Dashboard": "Accéder au tableau de bord",
|
||||
"Status Page": "Page de statut",
|
||||
"Status Pages": "Pages de statut",
|
||||
"New Status Page": "Ajouter page de statut",
|
||||
"Add New Status Page": "Ajouter une page de statut",
|
||||
"No status pages": "Aucune page de statut.",
|
||||
"Accept characters:": "Caractères acceptés:",
|
||||
startOrEndWithOnly: "Commence uniquement par {0}",
|
||||
"No consecutive dashes": "Pas de double tirets",
|
||||
Next: "Continuer",
|
||||
"Setup Proxy": "Configuer Proxy",
|
||||
defaultNotificationName: "Ma notification {notification} numéro ({number})",
|
||||
here: "ici",
|
||||
Required: "Requis",
|
||||
telegram: "Telegram",
|
||||
"Bot Token": "Bot Token",
|
||||
"ZohoCliq": "ZohoCliq",
|
||||
"Bot Token": "Jeton du robot",
|
||||
wayToGetTelegramToken: "Vous pouvez obtenir un token depuis {0}.",
|
||||
"Chat ID": "Chat ID",
|
||||
supportTelegramChatID: "Supporte les messages privés / en groupe / l'ID du salon",
|
||||
wayToGetTelegramChatID: "Vous pouvez obtenir l'ID du chat en envoyant un message avec le bot puis en récupérant l'URL pour voir l'ID du salon :",
|
||||
"YOUR BOT TOKEN HERE": "VOTRE TOKEN BOT ICI",
|
||||
chatIDNotFound: "ID du salon introuvable, envoyez un message via le bot avant",
|
||||
supportTelegramChatID: "Prend en charge les messages privés / messages de groupe / l'ID d'un salon",
|
||||
wayToGetTelegramChatID: "Vous pouvez obtenir le Chat ID en envoyant un message avec le robot puis en récupérant l'URL pour voir l'ID du salon :",
|
||||
"YOUR BOT TOKEN HERE": "VOTRE JETON ROBOT ICI",
|
||||
chatIDNotFound: "ID du salon introuvable, envoyez un message via le robot avant",
|
||||
webhook: "Webhook",
|
||||
"Post URL": "Post URL",
|
||||
"Content Type": "Type de contenu",
|
||||
webhookJsonDesc: "{0} est bien/bon pour tous les serveurs HTTP modernes comme express.js",
|
||||
webhookFormDataDesc: "{multipart} est bien/bon pour du PHP, vous avez juste besoin de mettre le json via/depuis {decodeFunction}",
|
||||
smtp: "Email (SMTP)",
|
||||
secureOptionNone: "Aucun/STARTTLS (25, 587)",
|
||||
webhookJsonDesc: "{0} est bien pour tous les serveurs HTTP modernes comme Express.js",
|
||||
webhookFormDataDesc: "{multipart} est bien pour du PHP. Le JSON aura besoin d'être parsé avec {decodeFunction}",
|
||||
webhookAdditionalHeadersTitle: "En-têtes supplémentaires",
|
||||
webhookAdditionalHeadersDesc: "Définit des en-têtes supplémentaires envoyés avec le webhook.",
|
||||
smtp: "Courriel (SMTP)",
|
||||
secureOptionNone: "Aucun / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "Ignorer les erreurs TLS",
|
||||
"From Email": "Depuis l'Email",
|
||||
"To Email": "Vers l'Email",
|
||||
"From Email": "Depuis l'adresse",
|
||||
emailCustomSubject: "Objet personnalisé",
|
||||
"To Email": "Vers l'adresse",
|
||||
smtpCC: "CC",
|
||||
smtpBCC: "BCC",
|
||||
smtpBCC: "CCI",
|
||||
discord: "Discord",
|
||||
"Discord Webhook URL": "Discord Webhook URL",
|
||||
wayToGetDiscordURL: "Vous pouvez l'obtenir en allant dans 'Paramètres du Serveur' -> 'Intégrations' -> 'Créer un Webhook'",
|
||||
"Bot Display Name": "Nom du bot (affiché)",
|
||||
"Prefix Custom Message": "Prefixe du message personnalisé",
|
||||
"Discord Webhook URL": "URL vers le webhook Discord",
|
||||
wayToGetDiscordURL: "Vous pouvez l'obtenir en allant dans « Paramètres du serveur » -> « Intégrations » -> « Créer un Webhook »",
|
||||
"Bot Display Name": "Nom du robot (affiché)",
|
||||
"Prefix Custom Message": "Préfixe du message personnalisé",
|
||||
"Hello @everyone is...": "Bonjour {'@'}everyone il...",
|
||||
teams: "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "Vous pouvez apprendre comment créer un Webhook {0}.",
|
||||
"Webhook URL": "URL vers le webhook",
|
||||
wayToGetTeamsURL: "Vous pouvez apprendre comment créer une URL Webhook {0}.",
|
||||
wayToGetZohoCliqURL: "Vous pouvez apprendre comment créer une URL Webhook {0}.",
|
||||
signal: "Signal",
|
||||
Number: "Numéro",
|
||||
Recipients: "Destinataires",
|
||||
needSignalAPI: "Vous avez besoin d'un client Signal avec l'API REST.",
|
||||
wayToCheckSignalURL: "Vous pouvez regarder l'URL sur comment le mettre en place :",
|
||||
wayToCheckSignalURL: "Vous pouvez regarder l'URL suivante pour savoir comment la mettre en place :",
|
||||
signalImportant: "IMPORTANT : Vous ne pouvez pas mixer les groupes et les numéros en destinataires !",
|
||||
gotify: "Gotify",
|
||||
"Application Token": "Jeton d'application",
|
||||
|
@ -233,19 +256,26 @@ export default {
|
|||
slack: "Slack",
|
||||
"Icon Emoji": "Icon Emoji",
|
||||
"Channel Name": "Nom du salon",
|
||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||
aboutWebhooks: "Plus d'informations sur les Webhooks ici : {0}",
|
||||
aboutChannelName: "Mettez le nom du salon dans {0} dans 'Channel Name' si vous voulez bypass le salon Webhook. Ex : #autre-salon",
|
||||
"Uptime Kuma URL": "URL vers Uptime Kuma",
|
||||
aboutWebhooks: "Plus d'informations sur les webhooks ici : {0}",
|
||||
aboutChannelName: "Mettez le nom du salon dans {0} dans « Nom du salon » si vous voulez contourner le salon webhook. Ex. : #autre-salon",
|
||||
aboutKumaURL: "Si vous laissez l'URL d'Uptime Kuma vierge, elle redirigera vers la page du projet GitHub.",
|
||||
emojiCheatSheet: "Aide emoji : {0}",
|
||||
emojiCheatSheet: "Aide sur les émojis : {0}",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
PushByTechulus: "Push by Techulus",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
clicksendsms: "ClickSend SMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Prend en charge plus de 50 services de notification)",
|
||||
apprise: "Apprise (prend en charge plus de 50 services de notification)",
|
||||
GoogleChat: "Google Chat (Google Workspace uniquement)",
|
||||
pushbullet: "Pushbullet",
|
||||
Kook: "Kook",
|
||||
wayToGetKookBotToken: "Créez une application et récupérer le jeton de robot à l'addresse {0}",
|
||||
wayToGetKookGuildID: "Passez en « mode développeur » dans les paramètres de Kook, et cliquez droit sur le Guild pour obtenir son identifiant",
|
||||
"Guild ID": "Identifiant de Guild",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "Clé d'utilisateur",
|
||||
|
@ -253,91 +283,75 @@ export default {
|
|||
"Message Title": "Titre du message",
|
||||
"Notification Sound": "Son de notification",
|
||||
"More info on:": "Plus d'informations sur : {0}",
|
||||
pushoverDesc1: "Priorité d'urgence (2) a par défaut 30 secondes de délai dépassé entre les tentatives et expierera après 1 heure.",
|
||||
pushoverDesc2: "Si vous voulez envoyer des notifications sur différents Appareils, remplissez le champ 'Device'.",
|
||||
"SMS Type": "SMS Type",
|
||||
octopushTypePremium: "Premium (Rapide - recommandé pour les alertes)",
|
||||
octopushTypeLowCost: "À bas prix (Lent, bloqué de temps en temps par l'opérateur)",
|
||||
"Check octopush prices": "Vérifier les prix d'octopush {0}.",
|
||||
octopushPhoneNumber: "Numéro de téléphone (format int., ex : +33612345678) ",
|
||||
octopushSMSSender: "Nom de l'envoyer : 3-11 caractères alphanumériques avec espace (a-zA-Z0-9)",
|
||||
"LunaSea Device ID": "LunaSea Device ID",
|
||||
"Apprise URL": "Apprise URL",
|
||||
"Example:": "Exemple : {0}",
|
||||
pushoverDesc1: "Priorité d'urgence (2) a un délai par défaut de 30 secondes entre les tentatives et expire après une heure.",
|
||||
pushoverDesc2: "Si vous voulez envoyer des notifications sur différents appareils, remplissez le champ « Appareil ».",
|
||||
"SMS Type": "Type de SMS",
|
||||
octopushTypePremium: "Premium (rapide - recommandé pour les alertes)",
|
||||
octopushTypeLowCost: "Économique (lent, bloqué de temps en temps par l'opérateur)",
|
||||
checkPrice: "Vérification {0} tarifs :",
|
||||
apiCredentials: "Identifiants de l'API",
|
||||
octopushLegacyHint: "Voulez-vous utiliser l'ancienne version d'Octopush (2011-2020) ou la nouvelle version ?",
|
||||
"Check octopush prices": "Vérifier les prix d'Octopush {0}.",
|
||||
octopushPhoneNumber: "Numéro de téléphone (format international, ex. : +33612345678)",
|
||||
octopushSMSSender: "Nom de l'expéditeur : 3-11 caractères alphanumériques avec espace (a-zA-Z0-9)",
|
||||
"LunaSea Device ID": "Identifiant d'appareil LunaSea",
|
||||
"Apprise URL": "URL d'Apprise",
|
||||
"Example:": "Exemple : {0}",
|
||||
"Read more:": "En savoir plus : {0}",
|
||||
"Status:": "Status : {0}",
|
||||
"Status:": "État : {0}",
|
||||
"Read more": "En savoir plus",
|
||||
appriseInstalled: "Apprise est installé.",
|
||||
appriseNotInstalled: "Apprise n'est pas installé. {0}",
|
||||
"Access Token": "Token d'accès",
|
||||
"Channel access token": "Token d'accès au canal",
|
||||
"Line Developers Console": "Ligne console de développeurs",
|
||||
lineDevConsoleTo: "Ligne console de développeurs - {0}",
|
||||
"Access Token": "Jeton d'accès",
|
||||
"Channel access token": "Jeton d'accès au canal",
|
||||
"Line Developers Console": "Console développeurs Line",
|
||||
lineDevConsoleTo: "Console développeurs Line - {0}",
|
||||
"Basic Settings": "Paramètres de base",
|
||||
"User ID": "Identifiant utilisateur",
|
||||
"Messaging API": "Messaging API",
|
||||
wayToGetLineChannelToken: "Premièrement accéder à {0}, créez un Provider et un Salon (Messaging API), puis vous pourrez avoir le Token d'accès du salon ainsi que l'Identifiant utilisateur depuis le même menu.",
|
||||
"Icon URL": "Icon URL",
|
||||
aboutIconURL: "Vous pouvez mettre un lien vers l'image dans \"Icon URL\" pour remplacer l'image de profil par défaut. Ne sera pas utilisé si Icon Emoji est défini.",
|
||||
aboutMattermostChannelName: "Vous pouvez remplacer le salon par défaut que le Webhook utilise en mettant le nom du salon dans le champ \"Channel Name\". Vous aurez besoin de l'activer depuis les paramètres de Mattermost. Ex : #autre-salon",
|
||||
"Messaging API": "Messaging API", // Ne pas traduire, il s'agit du type de salon affiché sur la console développeurs Line
|
||||
wayToGetLineChannelToken: "Premièrement accédez à {0}, créez un <i>provider</i> et définissez un type de salon à « Messaging API ». Vous pourrez alors avoir puis vous pourrez avoir le jeton d'accès du salon et l'identifiant utilisateur demandés.",
|
||||
"Icon URL": "URL vers l'icône",
|
||||
aboutIconURL: "Vous pouvez mettre un lien vers une image dans « URL vers l'icône » pour remplacer l'image de profil par défaut. Elle ne sera utilisé que si « Icône émoji » n'est pas défini.",
|
||||
aboutMattermostChannelName: "Vous pouvez remplacer le salon par défaut que le webhook utilise en mettant le nom du salon dans le champ « Nom du salon ». Vous aurez besoin de l'activer depuis les paramètres de Mattermost. Ex. : #autre-salon",
|
||||
matrix: "Matrix",
|
||||
promosmsTypeEco: "SMS ECO - Pas cher mais lent et souvent surchargé. Limité uniquement aux déstinataires Polonais.",
|
||||
promosmsTypeFlash: "SMS FLASH - Le message sera automatiquement affiché sur l'appareil du destinataire. Limité uniquement aux déstinataires Polonais.",
|
||||
promosmsTypeFull: "SMS FULL - Version Premium des SMS, Vous pouvez mettre le nom de l'expéditeur (Vous devez vous enregistrer avant). Fiable pour les alertes.",
|
||||
promosmsTypeSpeed: "SMS SPEED - La plus haute des priorités dans le système. Très rapide et fiable mais cher (environ le double du prix d'un SMS FULL).",
|
||||
promosmsPhoneNumber: "Numéro de téléphone (Poiur les déstinataires Polonais, vous pouvez enlever les codes interna.)",
|
||||
promosmsSMSSender: "SMS Expéditeur : Nom pré-enregistré ou l'un de base : InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
"Primary Base URL": "URL principale",
|
||||
emailCustomSubject: "Sujet personalisé",
|
||||
clicksendsms: "ClickSend SMS",
|
||||
checkPrice: "Vérification {0} tarifs :",
|
||||
apiCredentials: "Crédentials de l'API",
|
||||
octopushLegacyHint: "Vous utilisez l'ancienne version d'Octopush (2011-2020) ou la nouvelle version ?",
|
||||
promosmsTypeEco: "SMS ECO - Bon marché mais lent et souvent surchargé. Limité uniquement aux destinataires polonais.",
|
||||
promosmsTypeFlash: "SMS FLASH - Le message sera automatiquement affiché sur l'appareil du destinataire. Limité uniquement aux destinataires Polonais.",
|
||||
promosmsTypeFull: "SMS FULL - Version premium des SMS. Vous pouvez mettre le nom de l'expéditeur (vous devez l'enregistrer au préalable). Fiable pour les alertes.",
|
||||
promosmsTypeSpeed: "SMS SPEED - Priorité élevée pour le système. Très rapide et fiable mais coûteux (environ le double du prix d'un SMS FULL).",
|
||||
promosmsPhoneNumber: "Numéro de téléphone (pour les destinataires polonais, vous pouvez ignorer l'indicatif international)",
|
||||
promosmsSMSSender: "Nom de l'expéditeur du SMS : Nom pré-enregistré ou l'un de base : InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
"Feishu WebHookUrl": "Feishu WebHookURL",
|
||||
matrixHomeserverURL: "L'URL du serveur (avec http(s):// et le port de manière facultatif)",
|
||||
matrixHomeserverURL: "L'URL du serveur (avec http(s):// et le port de manière facultative)",
|
||||
"Internal Room Id": "ID de la salle interne",
|
||||
matrixDesc1: "Vous pouvez trouver l'ID de salle interne en regardant dans la section avancée des paramètres dans le client Matrix. C'est censé ressembler à !QMdRCpUIfLwsfjxye6:home.server.",
|
||||
matrixDesc2: "Il est fortement recommandé de créer un nouvel utilisateur et de ne pas utiliser le jeton d'accès de votre propre utilisateur Matrix, car il vous donnera un accès complet à votre compte et à toutes les salles que vous avez rejointes. Au lieu de cela, créez un nouvel utilisateur et invitez-le uniquement dans la salle dans laquelle vous souhaitez recevoir la notification. Vous pouvez obtenir le jeton d'accès en exécutant {0}",
|
||||
matrixDesc2: "Il est fortement recommandé de créer un nouvel utilisateur et de ne pas utiliser le jeton d'accès de votre propre utilisateur Matrix, car il vous donnera un accès complet à votre compte et à toutes les salles que vous avez rejointes. Pour cela, créez un nouvel utilisateur et invitez-le uniquement dans la salle dans laquelle vous souhaitez recevoir la notification. Vous pouvez obtenir le jeton d'accès en exécutant {0}",
|
||||
Method: "Méthode",
|
||||
Body: "Le corps",
|
||||
Body: "Corps",
|
||||
Headers: "En-têtes",
|
||||
PushUrl: "Push URL",
|
||||
HeadersInvalidFormat: "Les en-têtes de la requête ne sont pas dans un format JSON valide: ",
|
||||
BodyInvalidFormat: "Le corps de la requête n'est pas dans un format JSON valide: ",
|
||||
PushUrl: "URL Push",
|
||||
HeadersInvalidFormat: "Les en-têtes de la requête ne sont pas dans un format JSON valide : ",
|
||||
BodyInvalidFormat: "Le corps de la requête n'est pas dans un format JSON valide : ",
|
||||
"Monitor History": "Historique de la sonde",
|
||||
clearDataOlderThan: "Garder l'historique des données de la sonde durant {0} jours.",
|
||||
clearDataOlderThan: "Conserver l'historique des données de la sonde durant {0} jours.",
|
||||
PasswordsDoNotMatch: "Les mots de passe ne correspondent pas.",
|
||||
records: "Enregistrements",
|
||||
records: "enregistrements",
|
||||
"One record": "Un enregistrement",
|
||||
steamApiKeyDescription: "Pour surveiller un serveur Steam, vous avez besoin d'une clé Steam Web-API. Vous pouvez enregistrer votre clé ici : ",
|
||||
steamApiKeyDescription: "Pour surveiller un serveur Steam, vous avez besoin d'une clé Steam Web-API. Vous pouvez enregistrer votre clé ici : ",
|
||||
"Current User": "Utilisateur actuel",
|
||||
topic: "Topic",
|
||||
topicExplanation: "Topic MQTT à surveiller",
|
||||
successMessage: "Message de réussite",
|
||||
successMessageExplanation: "Message MQTT qui sera considéré comme un succès",
|
||||
recent: "Récent",
|
||||
alertaApiEndpoint: "API Endpoint",
|
||||
alertaEnvironment: "Environement",
|
||||
alertaApiKey: "Clé de l'API",
|
||||
alertaAlertState: "État de l'Alerte",
|
||||
alertaRecoverState: "État de récupération",
|
||||
resendEveryXTimes: "Renvoyez toutes les {0} fois",
|
||||
resendDisabled: "Renvoi désactivé",
|
||||
dnsPortDescription: "Port du serveur DNS. La valeur par défaut est 53. Vous pouvez modifier le port à tout moment.",
|
||||
"Resend Notification if Down X times consequently": "Renvoyer la notification a partir d'un certain temps",
|
||||
"Push URL": "Push URL",
|
||||
needPushEvery: "Vous devez appeler cette URL toutes les {0} secondes.",
|
||||
pushOptionalParams: "parametres optionnels: {0}",
|
||||
"disableauth.message1": "Voulez-vous vraiment <strong>désactiver l'authentification</strong>?",
|
||||
"disableauth.message2": "Il est conçu pour les scénarios <strong>où vous avez l'intention d'implémenter une authentification tierce</strong> devant Uptime Kuma, comme Cloudflare Access, Authelia ou d'autres mécanismes d'authentification.",
|
||||
"Please use this option carefully!": "Veuillez utiliser cette option avec précaution !",
|
||||
PushByTechulus: "Pousser par Techulus",
|
||||
GoogleChat: "Google Chat (Google Workspace uniquement)",
|
||||
Done: "Fait",
|
||||
Info: "Info",
|
||||
Security: "Sécurité",
|
||||
"Steam API Key": "Clé API Steam",
|
||||
"Steam API Key": "Clé d'API Steam",
|
||||
"Shrink Database": "Réduire la base de données",
|
||||
"Pick a RR-Type...": "Pick a RR-Type...",
|
||||
"Pick Accepted Status Codes...": "Pick Accepted Status Codes...",
|
||||
"Pick a RR-Type...": "Choisissez un type d'enregistrement...",
|
||||
"Pick Accepted Status Codes...": "Choisissez les codes de statut acceptés...",
|
||||
Default: "Défaut",
|
||||
"HTTP Options": "HTTP Options",
|
||||
"HTTP Options": "Options HTTP",
|
||||
"Create Incident": "Créer un incident",
|
||||
Title: "Titre",
|
||||
Content: "Contenu",
|
||||
|
@ -351,151 +365,160 @@ export default {
|
|||
light: "Blanc",
|
||||
dark: "Noir",
|
||||
Post: "Post",
|
||||
"Please input title and content": "Veuillez entrer le titre et le contenu",
|
||||
Created: "Created",
|
||||
"Please input title and content": "Veuillez saisir le titre et le contenu",
|
||||
Created: "Créé",
|
||||
"Last Updated": "Dernière mise à jour",
|
||||
Unpin: "Détacher",
|
||||
Unpin: "Retirer",
|
||||
"Switch to Light Theme": "Passer au thème clair",
|
||||
"Switch to Dark Theme": "Passer au thème sombre",
|
||||
"Show Tags": "Voir les étiquettes",
|
||||
"Show Tags": "Afficher les étiquettes",
|
||||
"Hide Tags": "Masquer les étiquettes",
|
||||
Description: "Description",
|
||||
"No monitors available.": "Aucun moniteur disponible.",
|
||||
"Add one": "En rajouter un",
|
||||
"No Monitors": "Aucun moniteur",
|
||||
"No monitors available.": "Aucune sonde disponible.",
|
||||
"Add one": "En rajouter une",
|
||||
"No Monitors": "Aucune sonde",
|
||||
"Untitled Group": "Groupe sans titre",
|
||||
Services: "Services",
|
||||
Discard: "Annuler",
|
||||
Discard: "Abandonner",
|
||||
Cancel: "Annuler",
|
||||
shrinkDatabaseDescription: "Déclencher la base de données VACUUM pour SQLite. Si votre base de données est créée après 1.10.0, AUTO_VACUUM est déjà activé et cette action n'est pas nécessaire.",
|
||||
"Powered by": "Propulsé par",
|
||||
shrinkDatabaseDescription: "Déclenche la commande VACUUM pour SQLite. Si votre base de données a été créée après la version 1.10.0, AUTO_VACUUM est déjà activé et cette action n'est pas nécessaire.",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
serwersmsAPIUser: "Nom d'utilisateur de l'API (incl. webapi_ prefix)",
|
||||
serwersmsAPIPassword: "Mot de passe API",
|
||||
serwersmsPhoneNumber: "Numéro de téléphone",
|
||||
serwersmsSenderName: "Nom de l'expéditeur du SMS (enregistré via le portail client)",
|
||||
smseagle: "SMSEagle",
|
||||
smseagleTo: "Numéro(s) de téléphone",
|
||||
smseagleGroup: "Nom(s) de groupe(s) de répertoire",
|
||||
smseagleContact: "Nom(s) de contact du répertoire",
|
||||
smseagleRecipientType: "Type de destinataire",
|
||||
smseagleRecipient: "Destinataire(s) (les multiples doivent être séparés par une virgule)",
|
||||
smseagleToken: "Jeton d'accès à l'API",
|
||||
smseagleUrl: "L'URL de votre appareil SMSEagle",
|
||||
smseagleEncoding: "Envoyer en Unicode",
|
||||
smseaglePriority: "Priorité des messages (0-9, par défaut = 0)",
|
||||
stackfield: "Stackfield",
|
||||
Customize: "Personnaliser",
|
||||
"Custom Footer": "Pied de page personnalisé",
|
||||
"Custom CSS": "CSS personnalisé",
|
||||
deleteStatusPageMsg: "Voulez-vous vraiment supprimer cette page d'état ?",
|
||||
Proxies: "Proxies",
|
||||
default: "Défaut",
|
||||
enabled: "Activé",
|
||||
setAsDefault: "Définir par défaut",
|
||||
deleteProxyMsg: "Voulez-vous vraiment supprimer ce proxy pour tous les moniteurs ?",
|
||||
proxyDescription: "Les proxys doivent être affectés à un moniteur pour fonctionner.",
|
||||
enableProxyDescription: "Ce proxy n'aura pas d'effet sur les demandes de moniteur tant qu'il n'est pas activé. Vous pouvez contrôler la désactivation temporaire du proxy de tous les moniteurs en fonction de l'état d'activation.",
|
||||
setAsDefaultProxyDescription: "Ce proxy sera activé par défaut pour les nouveaux moniteurs. Vous pouvez toujours désactiver le proxy séparément pour chaque moniteur.",
|
||||
Valid: "Valide",
|
||||
Invalid: "Non valide",
|
||||
User: "Utilisateur",
|
||||
Installed: "Installé",
|
||||
"Not installed": "Pas installé",
|
||||
"Remove Token": "Supprimer le jeton",
|
||||
Slug: "Chemin",
|
||||
"The slug is already taken. Please choose another slug.": "Le chemin est déjà pris. Veuillez choisir un autre chemin.",
|
||||
Authentication: "Authentication",
|
||||
"Page Not Found": "Page non trouvée",
|
||||
Backup: "Sauvegarde",
|
||||
About: "À propos de",
|
||||
"Footer Text": "Texte de pied de page",
|
||||
"Domain Names": "Noms de domaine",
|
||||
signedInDisp: "Connecté en tant que {0}",
|
||||
signedInDispDisabled: "Authentification désactivée.",
|
||||
"Show update if available": "Afficher la mise à jour si disponible",
|
||||
"Also check beta release": "Vérifiez également la version bêta",
|
||||
"Steam Game Server": "Serveur de jeu Steam",
|
||||
"Most likely causes:": "Causes les plus probables:",
|
||||
"The resource is no longer available.": "La ressource n'est plus disponible.",
|
||||
"There might be a typing error in the address.": "Il se peut qu'il y ait une erreur de frappe dans l'adresse.",
|
||||
"What you can try:": "Ce que vous pouvez essayer:",
|
||||
"Retype the address.": "Retapez l'adresse.",
|
||||
"Go back to the previous page.": "Retournez à la page précédente.",
|
||||
"Coming Soon": "À venir",
|
||||
settingsCertificateExpiry: "Expiration du certificat TLS",
|
||||
certificationExpiryDescription: "Les moniteurs HTTPS déclenchent une notification lorsque le certificat TLS expire dans:",
|
||||
"Setup Docker Host": "Configurer l'hôte Docker",
|
||||
"Connection Type": "Type de connexion",
|
||||
deleteDockerHostMsg: "Voulez-vous vraiment supprimer cet hôte Docker pour tous les moniteurs ?",
|
||||
"Container Name / ID": "Nom / ID du conteneur",
|
||||
"Docker Host": "Hôte Docker",
|
||||
"Docker Hosts": "Hôtes Docker",
|
||||
Domain: "Domaine",
|
||||
trustProxyDescription: "Faire confiance aux en-têtes 'X-Forwarded-*'. Si vous souhaitez obtenir la bonne adresse IP client et que votre Uptime Kuma est en retard, comme Nginx ou Apache, vous devez l'activer.",
|
||||
wayToGetLineNotifyToken: "Vous pouvez obtenir un jeton d'accès auprès de {0}",
|
||||
Examples: "Exemples",
|
||||
"Home Assistant URL": "Home Assistant URL",
|
||||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Un jeton d'accès de longue durée peut être créé en cliquant sur le nom de votre profil (en bas à gauche) et en faisant défiler vers le bas, puis cliquez sur Créer un jeton. ",
|
||||
"Notification Service": "Service de notifications",
|
||||
"default: notify all devices": "par défaut: notifier tous les appareils",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Une liste des services de notification peut être trouvée dans Home Assistant sous \"Outils de développement > Services\" recherchez \"notification\" pour trouver le nom de votre appareil/téléphone.",
|
||||
"Automations can optionally be triggered in Home Assistant:": "Les automatisations peuvent éventuellement être déclenchées dans Home Assistant:",
|
||||
"Trigger type:": "Type de déclencheur:",
|
||||
"Event type:": "Type d'événement:",
|
||||
"Event data:": "Données d'événement:",
|
||||
topic: "Topic",
|
||||
topicExplanation: "MQTT sujet à surveiller",
|
||||
successMessage: "Message de réussite",
|
||||
successMessageExplanation: "MQTT message qui sera considéré comme un succès",
|
||||
"Powered by": "Propulsé par",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
stackfield: "Stackfield",
|
||||
smtpDkimSettings: "Paramètres DKIM",
|
||||
smtpDkimDesc: "Veuillez vous référer au Nodemailer DKIM {0} pour l'utilisation.",
|
||||
documentation: "Documentation",
|
||||
documentation: "documentation",
|
||||
smtpDkimDomain: "Nom de domaine",
|
||||
smtpDkimKeySelector: "Sélecteur de clé",
|
||||
smtpDkimPrivateKey: "Clé privée",
|
||||
smtpDkimHashAlgo: "Algorithme de hachage (facultatif)",
|
||||
smtpDkimheaderFieldNames: "Clés d'en-tête à signer (facultatif)",
|
||||
smtpDkimskipFields: "Clés d'en-tête à ne pas signer (facultatif)",
|
||||
wayToGetPagerDutyKey: "Vous pouvez l'obtenir en allant dans Service -> Annuaire des services -> (Sélectionner un service) -> Intégrations -> Ajouter une intégration. Ici, vous pouvez rechercher \"Events API V2\". Plus d'infos {0}",
|
||||
wayToGetPagerDutyKey: "Vous pouvez l'obtenir en allant dans Service -> Annuaire des services -> (sélectionner un service) -> Intégrations -> Ajouter une intégration. Ici, vous pouvez rechercher \"Events API V2\". Plus d'infos {0}",
|
||||
"Integration Key": "Clé d'intégration",
|
||||
"Integration URL": "URL d'intégration",
|
||||
"Auto resolve or acknowledged": "Résolution automatique ou accusé de réception",
|
||||
"do nothing": "ne fais rien",
|
||||
"auto acknowledged": "accusé de réception automatique",
|
||||
"auto resolve": "résolution automatique",
|
||||
gorush: "Gorush",
|
||||
alerta: "Alerta",
|
||||
alertaApiEndpoint: "API Endpoint",
|
||||
alertaEnvironment: "Environnement",
|
||||
alertaApiKey: "Clé de l'API",
|
||||
alertaAlertState: "État de l'alerte",
|
||||
alertaRecoverState: "État de récupération",
|
||||
deleteStatusPageMsg: "Voulez-vous vraiment supprimer cette page d'état ?",
|
||||
Proxies: "Proxies",
|
||||
default: "Défaut",
|
||||
enabled: "Activé",
|
||||
setAsDefault: "Définir par défaut",
|
||||
deleteProxyMsg: "Voulez-vous vraiment supprimer ce proxy pour toutes les sondes ?",
|
||||
proxyDescription: "Les proxies doivent être affectés à une sonde pour fonctionner.",
|
||||
enableProxyDescription: "Ce proxy n'aura pas d'effet sur les demandes de sonde tant qu'il n'est pas activé. Vous pouvez contrôler la désactivation temporaire du proxy de toutes les sondes en fonction de l'état d'activation.",
|
||||
setAsDefaultProxyDescription: "Ce proxy sera activé par défaut pour les nouvelles sondes. Vous pouvez toujours désactiver le proxy séparément pour chaque sonde.",
|
||||
"Certificate Chain": "Chaîne de certificats",
|
||||
Valid: "Valide",
|
||||
Invalid: "Non valide",
|
||||
AccessKeyId: "ID de clé d'accès",
|
||||
SecretAccessKey: "Clé secrète d'accès",
|
||||
PhoneNumbers: "Les numéros de téléphone",
|
||||
PhoneNumbers: "Numéros de téléphone",
|
||||
TemplateCode: "Modèle de code",
|
||||
SignName: "Signature",
|
||||
"Sms template must contain parameters: ": "Le modèle de SMS doit contenir des paramètres : ",
|
||||
"Sms template must contain parameters: ": "Le modèle de SMS doit contenir des paramètres : ",
|
||||
"Bark Endpoint": "Endpoint Bark",
|
||||
"Bark Group": "Groupe Bark",
|
||||
"Bark Sound": "Son Bark",
|
||||
WebHookUrl: "WebHookUrl",
|
||||
SecretKey: "Clé secrète",
|
||||
"For safety, must use secret key": "Pour la sécurité, doit utiliser la clé secrète",
|
||||
"For safety, must use secret key": "Par sécurité, utilisation obligatoire de la clé secrète",
|
||||
"Device Token": "Jeton d'appareil",
|
||||
Platform: "Plateforme",
|
||||
iOS: "iOS",
|
||||
Android: "Android",
|
||||
Huawei: "Huawei",
|
||||
High: "Haute",
|
||||
Retry: "Recommencez",
|
||||
Topic: "Topic",
|
||||
"Proxy server has authentication": "Le serveur proxy a une authentification",
|
||||
"WeCom Bot Key": "Clé de robot WeCom",
|
||||
"Setup Proxy": "Configurer le proxy",
|
||||
"Proxy Protocol": "Protocole proxy",
|
||||
"Proxy Server": "Serveur proxy",
|
||||
"Proxy server has authentication": "Une authentification est nécessaire pour le serveur proxy",
|
||||
User: "Utilisateur",
|
||||
Installed: "Installé",
|
||||
"Not installed": "Non installé",
|
||||
Running: "Fonctionne",
|
||||
"Not running": "Ne fonctionne pas",
|
||||
Start: "Start",
|
||||
Stop: "Stop",
|
||||
"Remove Token": "Supprimer le jeton",
|
||||
Start: "Démarrer",
|
||||
Stop: "Arrêter",
|
||||
"Uptime Kuma": "Uptime Kuma",
|
||||
"No Proxy": "Pas de Proxy",
|
||||
"Add New Status Page": "Ajouter une page de statut",
|
||||
Slug: "Chemin",
|
||||
"Accept characters:": "Caractères acceptés : ",
|
||||
startOrEndWithOnly: "Commence uniquement par {0}",
|
||||
"No consecutive dashes": "Pas de double tirets",
|
||||
Next: "Continuer",
|
||||
"The slug is already taken. Please choose another slug.": "Un chemin existe déjà. Veuillez en choisir un autre.",
|
||||
"No Proxy": "Pas de proxy",
|
||||
Authentication: "Authentification",
|
||||
"HTTP Basic Auth": "Authentification de base HTTP",
|
||||
"New Status Page": "Nouvelle page de statut",
|
||||
"Page Not Found": "Page non trouvée",
|
||||
"Reverse Proxy": "Proxy inverse",
|
||||
wayToGetCloudflaredURL: "(Télécharger cloudflared depuis {0})",
|
||||
cloudflareWebsite: "le site Cloudflare ",
|
||||
"Message:": "Message:",
|
||||
"Don't know how to get the token? Please read the guide:": "Vous ne savez pas comment obtenir le jeton ? Veuillez lire le guide:",
|
||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "La connexion actuelle peut être perdue si vous vous connectez actuellement via Cloudflare Tunnel. Êtes-vous sûr de vouloir l'arrêter ? Tapez votre mot de passe actuel pour le confirmer.",
|
||||
Backup: "Sauvegarde",
|
||||
About: "À propos",
|
||||
wayToGetCloudflaredURL: "(télécharger cloudflared depuis {0})",
|
||||
cloudflareWebsite: "Site web de Cloudflare",
|
||||
"Message:": "Message : ",
|
||||
"Don't know how to get the token? Please read the guide:": "Vous ne savez pas comment obtenir le jeton ? Lisez le guide :",
|
||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "La connexion actuelle peut être perdue si vous vous connectez actuellement via un tunnel Cloudflare. Êtes-vous sûr de vouloir l'arrêter ? Tapez votre mot de passe actuel pour le confirmer.",
|
||||
"HTTP Headers": "En-têtes HTTP",
|
||||
"Trust Proxy": "Proxy de confiance",
|
||||
"Other Software": "Autres logiciels",
|
||||
"For example: nginx, Apache and Traefik.": "Par exemple : nginx, Apache et Traefik.",
|
||||
"Please read": "S'il vous plaît Lisez",
|
||||
"Valid To:": "Valable pour:",
|
||||
"Days Remaining:": "Jours restant:",
|
||||
"Domain Name Expiry Notification": "Notification d'expiration de nom de domaine",
|
||||
"For example: nginx, Apache and Traefik.": "Par exemple : nginx, Apache et Traefik.",
|
||||
"Please read": "Veuillez lire",
|
||||
"Subject:": "Objet : ",
|
||||
"Valid To:": "Valable jusqu'au : ",
|
||||
"Days Remaining:": "Jours restants : ",
|
||||
"Issuer:": "Émetteur : ",
|
||||
"Fingerprint:": "Empreinte : ",
|
||||
"No status pages": "Aucune page de statut.",
|
||||
"Domain Name Expiry Notification": "Notification d'expiration du nom de domaine",
|
||||
Proxy: "Proxy",
|
||||
"Date Created": "Date de création",
|
||||
HomeAssistant: "Home Assistant",
|
||||
onebotHttpAddress: "Adresse HTTP OneBot",
|
||||
onebotMessageType: "Type de message OneBot",
|
||||
onebotGroupMessage: "Groupe",
|
||||
onebotPrivateMessage: "Privé",
|
||||
onebotUserOrGroupId: "ID de groupe/utilisateur",
|
||||
onebotSafetyTips: "Pour des raisons de sécurité, vous devez définir un jeton d'accès",
|
||||
"PushDeer Key": "Clé PushDeer",
|
||||
"Show Powered By": "Afficher \"Propulsé par\"",
|
||||
"Footer Text": "Texte de pied de page",
|
||||
"Show Powered By": "Afficher « Propulsé par »",
|
||||
"Domain Names": "Noms de domaine",
|
||||
signedInDisp: "Connecté en tant que {0}",
|
||||
signedInDispDisabled: "Authentification désactivée.",
|
||||
RadiusSecret: "Radius Secret",
|
||||
RadiusSecretDescription: "Secret partagé entre le client et le serveur",
|
||||
RadiusCalledStationId: "Identifiant de la station appelée",
|
||||
RadiusCalledStationIdDescription: "Identifiant de l'appareil appelé",
|
||||
|
@ -503,58 +526,107 @@ export default {
|
|||
RadiusCallingStationIdDescription: "Identifiant de l'appareil appelant",
|
||||
"Certificate Expiry Notification": "Notification d'expiration du certificat",
|
||||
"API Username": "Nom d'utilisateur de l'API",
|
||||
"API Key": "clé API",
|
||||
"API Key": "Clé API",
|
||||
"Recipient Number": "Numéro du destinataire",
|
||||
"From Name/Number": "De Nom/Numéro",
|
||||
"From Name/Number": "De nom/numéro",
|
||||
"Leave blank to use a shared sender number.": "Laisser vide pour utiliser un numéro d'expéditeur partagé.",
|
||||
"Octopush API Version": "Version de l'API Octopush",
|
||||
"Legacy Octopush-DM": "Ancien Octopush-DM",
|
||||
endpoint: "endpoint",
|
||||
octopushAPIKey: "\"Clé API\" à partir des informations d'identification de l'API HTTP dans le panneau de configuration",
|
||||
octopushLogin: "\"Connexion\" à partir des informations d'identification de l'API HTTP dans le panneau de configuration",
|
||||
octopushLogin: "\"Identifiant\" à partir des informations d'identification de l'API HTTP dans le panneau de configuration",
|
||||
promosmsLogin: "Nom de connexion API",
|
||||
promosmsPassword: "Mot de passe API",
|
||||
"pushoversounds pushover": "Pushover (par défaut)",
|
||||
"pushoversounds bike": "Vélo",
|
||||
"pushoversounds bugle": "Clairon",
|
||||
"pushoversounds cashregister": "Caisse enregistreuse",
|
||||
"pushoversounds classical": "Classique",
|
||||
"pushoversounds cosmic": "Cosmique",
|
||||
"pushoversounds falling": "Chute",
|
||||
"pushoversounds gamelan": "Gamelan",
|
||||
"pushoversounds incoming": "Arrivée",
|
||||
"pushoversounds intermission": "Intermission",
|
||||
"pushoversounds magic": "Magique",
|
||||
"pushoversounds mechanical": "Mécanique",
|
||||
"pushoversounds pianobar": "Piano-bar",
|
||||
"pushoversounds siren": "Sirène",
|
||||
"pushoversounds spacealarm": "Alarme spatiale",
|
||||
"pushoversounds tugboat": "Remorqueur",
|
||||
"pushoversounds alien": "Alarme alienne (version longue)",
|
||||
"pushoversounds climb": "Escalade (version longue)",
|
||||
"pushoversounds persistent": "Persistent (version longue)",
|
||||
"pushoversounds echo": "Pushover Echo (version longue)",
|
||||
"pushoversounds updown": "Up Down (version longue)",
|
||||
"pushoversounds vibrate": "Vibration seulement",
|
||||
"pushoversounds none": "Aucun (silencieux)",
|
||||
pushyAPIKey: "Clé API secrète",
|
||||
pushyToken: "Jeton d'appareil",
|
||||
"Show update if available": "Afficher la mise à jour si disponible",
|
||||
"Also check beta release": "Vérifiez également la version bêta",
|
||||
"Using a Reverse Proxy?": "Utiliser un proxy inverse ?",
|
||||
"Check how to config it for WebSocket": "Vérifiez comment le configurer pour WebSocket",
|
||||
"Check how to config it for WebSocket": "Vérifier comment le configurer pour WebSocket",
|
||||
"Steam Game Server": "Serveur de jeu Steam",
|
||||
"Most likely causes:": "Causes les plus probables : ",
|
||||
"The resource is no longer available.": "La ressource n'est plus disponible.",
|
||||
"There might be a typing error in the address.": "Il se peut qu'il y ait une erreur de frappe dans l'adresse.",
|
||||
"What you can try:": "Ce que vous pouvez essayer :",
|
||||
"Retype the address.": "Retaper l'adresse.",
|
||||
"Go back to the previous page.": "Retourner à la page précédente.",
|
||||
"Coming Soon": "Prochainement",
|
||||
wayToGetClickSendSMSToken: "Vous pouvez obtenir le nom d'utilisateur API et la clé API à partir de {0} .",
|
||||
"Connection String": "Chaîne de connexion",
|
||||
Query: "Requête",
|
||||
settingsCertificateExpiry: "Expiration du certificat TLS",
|
||||
certificationExpiryDescription: "Les sondes HTTPS émettent une notification lorsque le certificat TLS expire dans :",
|
||||
"Setup Docker Host": "Configurer l'hôte Docker",
|
||||
"Connection Type": "Type de connexion",
|
||||
"Docker Daemon": "Deamon Docker",
|
||||
deleteDockerHostMsg: "Voulez-vous vraiment supprimer cet hôte Docker pour toutes les sondes ?",
|
||||
socket: "Socket",
|
||||
tcp: "TCP / HTTP",
|
||||
"Docker Container": "Conteneur Docker",
|
||||
"Container Name / ID": "Nom / ID du conteneur",
|
||||
"Docker Host": "Hôte Docker",
|
||||
"Docker Hosts": "Hôtes Docker",
|
||||
"ntfy Topic": "Topic ntfy",
|
||||
Domain: "Domaine",
|
||||
Workstation: "Poste de travail",
|
||||
disableCloudflaredNoAuthMsg: "Vous êtes en mode No Auth, un mot de passe n'est pas nécessaire.",
|
||||
trustProxyDescription: "Faire confiance aux en-têtes 'X-Forwarded-*'. Si vous souhaitez obtenir la bonne adresse IP client et que votre Uptime Kuma se situe derrière (nginx ou Apache) vous devez l'activer.",
|
||||
wayToGetLineNotifyToken: "Vous pouvez obtenir un jeton d'accès auprès de {0}",
|
||||
Examples: "Exemples",
|
||||
"Home Assistant URL": "URL vers Home Assistant",
|
||||
"Long-Lived Access Token": "Jeton d'accès de longue durée",
|
||||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Un jeton d'accès de longue durée peut être créé en cliquant sur le nom de votre profil (en bas à gauche) et en faisant défiler vers le bas, puis cliquez sur Créer un jeton. ",
|
||||
"Notification Service": "Service de notifications",
|
||||
"default: notify all devices": "par défaut: notifier tous les appareils",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "Une liste des services de notification peut être trouvée dans Home Assistant sous \"Outils de développement > Services\" recherchez \"notification\" pour trouver le nom de votre appareil/téléphone.",
|
||||
"Automations can optionally be triggered in Home Assistant:": "Les automatisations peuvent éventuellement être déclenchées dans Home Assistant : ",
|
||||
"Trigger type:": "Type de déclencheur : ",
|
||||
"Event type:": "Type d'événement : ",
|
||||
"Event data:": "Données d'événement : ",
|
||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "Ensuite, choisissez une action, par exemple basculer la scène là où une lumière RVB est rouge.",
|
||||
"Frontend Version": "Frontend Version",
|
||||
"Frontend Version do not match backend version!": "La version frontale ne correspond pas à la version principale !",
|
||||
"Frontend Version": "Version frontend",
|
||||
"Frontend Version do not match backend version!": "La version frontend ne correspond pas à la version backend !",
|
||||
"Base URL": "URL de base",
|
||||
goAlertInfo: "GoAlert est une application open source pour la planification des appels, les escalades automatisées et les notifications (comme les SMS ou les appels vocaux). Engagez automatiquement la bonne personne, de la bonne manière et au bon moment ! {0}",
|
||||
goAlertInfo: "GoAlert est une application open source pour la planification des appels, les escalades automatisées et les notifications (comme les SMS ou les appels vocaux). Impliquez automatiquement la bonne personne, de la bonne manière et au bon moment ! {0}",
|
||||
goAlertIntegrationKeyInfo: "Obtenez la clé d'intégration d'API générique pour le service dans ce format \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\" généralement la valeur du paramètre de jeton de l'URL copiée.",
|
||||
goAlert: "GoAlert",
|
||||
backupOutdatedWarning: "Obsolète : étant donné que de nombreuses fonctionnalités ont été ajoutées et que cette fonctionnalité de sauvegarde est un peu non maintenue, elle ne peut pas générer ou restaurer une sauvegarde complète.",
|
||||
backupOutdatedWarning: "Obsolète : étant donné que de nombreuses fonctionnalités ont été ajoutées et que cette fonctionnalité de sauvegarde est non maintenue, elle ne peut pas générer ou restaurer une sauvegarde complète.",
|
||||
backupRecommend: "Veuillez sauvegarder le volume ou le dossier de données (./data/) directement à la place.",
|
||||
Optional: "Optionnel",
|
||||
squadcast: "Squadcast",
|
||||
Maintenance: "Maintenance",
|
||||
statusMaintenance: "Maintenance",
|
||||
"Schedule maintenance": "Planifier la maintenance",
|
||||
"Affected Monitors": "Moniteurs concernés",
|
||||
"Pick Affected Monitors...": "Sélectionnez les moniteurs concernés...",
|
||||
"Start of maintenance": "Début de la maintenance",
|
||||
"All Status Pages": "Toutes les pages d'état",
|
||||
"Select status pages...": "Sélectionnez les pages d'état...",
|
||||
recurringIntervalMessage: "Exécuter une fois par jour | Exécuter une fois tous les {0} jours",
|
||||
affectedMonitorsDescription: "Sélectionnez les moniteurs concernés par la maintenance en cours",
|
||||
affectedStatusPages: "Afficher ce message de maintenance sur les pages d'état sélectionnées",
|
||||
atLeastOneMonitor: "Sélectionnez au moins un moniteur concerné",
|
||||
deleteMaintenanceMsg: "Voulez-vous vraiment supprimer cette maintenance ?",
|
||||
pushyAPIKey: "Clé API secrète",
|
||||
pushyToken: "Jeton d'appareil",
|
||||
SendKey: "SendKey",
|
||||
"SMSManager API Docs": "Documentations de l'API SMSManager ",
|
||||
"Gateway Type": "Type de passerelle",
|
||||
SMSManager: "SMSManager",
|
||||
"You can divide numbers with": "Vous pouvez diviser des nombres avec",
|
||||
or: "ou",
|
||||
recurringInterval: "Intervalle",
|
||||
Recurring: "Récurrent",
|
||||
"Single Maintenance Window": "Fenêtre de maintenance unique",
|
||||
"Maintenance Time Window of a Day": "Fenêtre de temps de maintenance",
|
||||
"Effective Date Range": "Plage de dates d'effet",
|
||||
strategyManual: "activer/desactiver manuellement",
|
||||
warningTimezone: "Il utilise le fuseau horaire du serveur",
|
||||
strategyManual: "Activer/désactiver manuellement",
|
||||
warningTimezone: "Utilisation du fuseau horaire du serveur",
|
||||
weekdayShortMon: "Lun",
|
||||
weekdayShortTue: "Mar",
|
||||
weekdayShortWed: "Mer",
|
||||
|
@ -566,10 +638,10 @@ export default {
|
|||
dayOfMonth: "Jour du mois",
|
||||
lastDay: "Dernier jour",
|
||||
lastDay1: "Dernier jour du mois",
|
||||
lastDay2: "2ème dernier jour du mois",
|
||||
lastDay2: "Avant-dernier jour du mois",
|
||||
lastDay3: "3ème dernier jour du mois",
|
||||
lastDay4: "4ème dernier jour du mois",
|
||||
"No Maintenance": "Aucune Maintenance",
|
||||
"No Maintenance": "Aucune maintenance",
|
||||
pauseMaintenanceMsg: "Voulez-vous vraiment mettre en pause ?",
|
||||
"maintenanceStatus-under-maintenance": "En maintenance",
|
||||
"maintenanceStatus-inactive": "Inactif",
|
||||
|
@ -578,10 +650,31 @@ export default {
|
|||
"maintenanceStatus-unknown": "Inconnue",
|
||||
"Display Timezone": "Afficher le fuseau horaire",
|
||||
"Server Timezone": "Fuseau horaire du serveur",
|
||||
statusPageMaintenanceEndDate: "Fin",
|
||||
IconUrl: "URL vers l'icône",
|
||||
"Enable DNS Cache": "Activer le cache DNS",
|
||||
Enable: "Activer",
|
||||
Disable: "Désactiver",
|
||||
dnsCacheDescription: "Il peut ne pas fonctionner dans certains environnements IPv6, désactivez-le si vous rencontrez des problèmes.",
|
||||
"Single Maintenance Window": "Créneau de maintenance unique",
|
||||
"Maintenance Time Window of a Day": "Créneau de la maintenance",
|
||||
"Effective Date Range": "Plage de dates d'effet",
|
||||
"Schedule Maintenance": "Créer une maintenance",
|
||||
"Date and Time": "Date et heure",
|
||||
"DateTime Range": "Plage de dates et d'heures",
|
||||
Strategy: "Stratégie",
|
||||
statusPageMaintenanceEndDate: "Fin",
|
||||
"Free Mobile User Identifier": "Identifiant d'utilisateur Free Mobile",
|
||||
"Free Mobile API Key": "Clé API Free Mobile",
|
||||
"Free Mobile API Key": "Clé d'API Free Mobile",
|
||||
"Enable TLS": "Activer le TLS",
|
||||
"Proto Service Name": "Nom du service proto",
|
||||
"Proto Method": "Méthode Proto",
|
||||
"Proto Content": "Contenu proto",
|
||||
"Economy": "Économique",
|
||||
"Lowcost": "Faible coût",
|
||||
"high": "Haute",
|
||||
"General Monitor Type": "Type de sonde générale",
|
||||
"Passive Monitor Type": "Type de sonde passive",
|
||||
"Specific Monitor Type": "Type de sonde spécifique",
|
||||
dataRetentionTimeError: "La durée de conservation doit être supérieure ou égale à 0",
|
||||
infiniteRetention: "Définissez la valeur à 0 pour une durée de conservation infinie.",
|
||||
};
|
||||
|
|
672
src/languages/he-IL.js
Normal file
672
src/languages/he-IL.js
Normal file
|
@ -0,0 +1,672 @@
|
|||
export default {
|
||||
languageName: "עברית",
|
||||
checkEverySecond: "בדוק כל {0} שניות",
|
||||
retryCheckEverySecond: "נסה שוב כל {0} שניות",
|
||||
resendEveryXTimes: "התראה שוב כל {0} פעמים",
|
||||
resendDisabled: "השליחה מחדש מושבתת",
|
||||
retriesDescription: "מקסימום ניסיונות חוזרים לפני שהשירות יסומן כלא פעיל ונשלחת התראה",
|
||||
ignoreTLSError: "התעלם משגיאת TLS/SSL עבור אתרי HTTPS",
|
||||
upsideDownModeDescription: "הפוך את הסטטוס על הפוך. אם ניתן להגיע לשירות, הוא לא פעיל.",
|
||||
maxRedirectDescription: "המספר המרבי של הפניות מחדש לעקוב. הגדר ל-0 כדי להשבית הפניות מחדש.",
|
||||
enableGRPCTls: "אפשר לשלוח בקשת gRPC עם חיבור TLS",
|
||||
grpcMethodDescription: "שם השיטה מומר לפורמט cammelCase כגון sayHello, check וכו.",
|
||||
acceptedStatusCodesDescription: "בחר קודי סטטוס שנחשבים לתגובה מוצלחת.",
|
||||
Maintenance: "תחזוקה",
|
||||
statusMaintenance: "תחזוקה",
|
||||
"Schedule maintenance": "תחזוקה מתוכננת",
|
||||
"Affected Monitors": "מוניטורים מושפעים",
|
||||
"Pick Affected Monitors...": "בחר המוניטרים מושפעים...",
|
||||
"Start of maintenance": "תחילת תחזוקה",
|
||||
"All Status Pages": "כל דפי הסטטוס",
|
||||
"Select status pages...": "בחר דפי סטטוס...",
|
||||
recurringIntervalMessage: "רוץ פעם ביום | הפעל אחת ל-{0} ימים",
|
||||
affectedMonitorsDescription: "בחר מוניטורים שמושפעים מהתחזוקה הנוכחית",
|
||||
affectedStatusPages: "הצג הודעת תחזוקה זו בדפי סטטוס שנבחרו",
|
||||
atLeastOneMonitor: "בחר לפחות מוניטור אחד מושפע",
|
||||
passwordNotMatchMsg: "הסיסמאות לא תואמות",
|
||||
notificationDescription: "יש להקצות התראות למוניטור כדי שהן יעבדו.",
|
||||
keywordDescription: "חפש מילת מפתח בתגובת HTML או JSON רגילה. החיפוש תלוי רישיות.",
|
||||
pauseDashboardHome: "עצור",
|
||||
deleteMonitorMsg: "האם אתה בטוח שברצונך למחוק את המוניטור הזה?",
|
||||
deleteMaintenanceMsg: "האם אתה בטוח שברצונך למחוק את התחזוקה הזו?",
|
||||
deleteNotificationMsg: "האם אתה בטוח שברצונך למחוק את ההודעה הזו עבור כל מוניטרים?",
|
||||
dnsPortDescription: "יציאת שרת DNS. ברירת המחדל היא 53. אתה יכול לשנות את היציאה בכל עת.",
|
||||
resolverserverDescription: "Cloudflare הוא שרת ברירת המחדל. אתה יכול לשנות את שרת הפותר בכל עת.",
|
||||
rrtypeDescription: "בחר את סוג ה-RR שברצונך לפקח עליו",
|
||||
pauseMonitorMsg: "האם אתה בטוח רוצה להשהות?",
|
||||
enableDefaultNotificationDescription: "הודעה זו תופעל כברירת מחדל עבור מוניטרים חדשים. אתה עדיין יכול להשבית את ההודעה בנפרד עבור כל מוניטור.",
|
||||
clearEventsMsg: "האם אתה בטוח שברצונך למחוק את כל האירועים עבור המוניטור הזה?",
|
||||
clearHeartbeatsMsg: "האם אתה בטוח שברצונך למחוק את כל פעימות הלב עבור המוניטור הזה?",
|
||||
confirmClearStatisticsMsg: "האם אתה בטוח שברצונך למחוק את כל הנתונים הסטטיסטיים?",
|
||||
importHandleDescription: "בחר 'דלג על קיים' אם ברצונך לדלג על כל מוניטור או התראה באותו שם. 'החלף' ימחק כל מוניטור והתראה קיימים.",
|
||||
confirmImportMsg: "האם אתה בטוח שברצונך לייבא את הגיבוי? אנא ודא שבחרת באפשרות הייבוא הנכונה.",
|
||||
twoFAVerifyLabel: "אנא הזן את האסימון שלך כדי לאמת מערכת אדוש:",
|
||||
tokenValidSettingsMsg: "האסימון תקף! כעת אתה יכול לשמור את הגדרות האדוש.",
|
||||
confirmEnableTwoFAMsg: "האם אתה בטוח שברצונך להפעיל את מערכת אדוש?",
|
||||
confirmDisableTwoFAMsg: "Are you sure you want to disable 2FA?",
|
||||
Settings: "הגדרות",
|
||||
Dashboard: "פאנל ניהול",
|
||||
"New Update": "עדכון חדש",
|
||||
Language: "שפה",
|
||||
Appearance: "נראות",
|
||||
Theme: "ערכת נושא",
|
||||
General: "כללי",
|
||||
"Primary Base URL": "כתובת האתר הראשית של הבסיס",
|
||||
Version: "גרסה",
|
||||
"Check Update On GitHub": "לבדוק עדכונים בגיטהאב",
|
||||
List: "רשימה",
|
||||
Add: "הוסף",
|
||||
"Add New Monitor": "הוספת מוניטור חדש",
|
||||
"Quick Stats": "נתונים בקצרה",
|
||||
Up: "פעיל",
|
||||
Down: "לא פעיל",
|
||||
Pending: "ממתין",
|
||||
Unknown: "לא יודע",
|
||||
Pause: "עצור",
|
||||
Name: "שם",
|
||||
Status: "סטטוס",
|
||||
DateTime: "תאריך שעה",
|
||||
Message: "הודעה",
|
||||
"No important events": "אין אירועים חשובים",
|
||||
Resume: "המשך",
|
||||
Edit: "עריכה",
|
||||
Delete: "מחיקה",
|
||||
Current: "עכשיו",
|
||||
Uptime: "זמן פעילות",
|
||||
"Cert Exp.": "Cert Exp.",
|
||||
day: "יום | ימים",
|
||||
"-day": "-יום",
|
||||
hour: "שעה",
|
||||
"-hour": "-שעה",
|
||||
Response: "תגובה",
|
||||
Ping: "פינג",
|
||||
"Monitor Type": "סוג מוניטור",
|
||||
Keyword: "מילת מפתח",
|
||||
"Friendly Name": "שם ידידותי",
|
||||
URL: "כתובת אתר",
|
||||
Hostname: "שם המארח",
|
||||
Port: "פורט",
|
||||
"Heartbeat Interval": "מרווח פעימות",
|
||||
Retries: "נסיונות חוזרים",
|
||||
"Heartbeat Retry Interval": "מרווח נסיונות חוזר של פעימות",
|
||||
"Resend Notification if Down X times consequently": "שלח שוב הודעה אם ירד X פעמים כתוצאה מכך",
|
||||
Advanced: "מתקדם",
|
||||
"Upside Down Mode": "מצב הפוך",
|
||||
"Max. Redirects": "מקסימום הפניות מחדש",
|
||||
"Accepted Status Codes": "קודי סטטוס מקובלים",
|
||||
"Push URL": "דחף כתובת URL",
|
||||
needPushEvery: "עליך להתקשר לכתובת האתר הזו כל {0} שניות.",
|
||||
pushOptionalParams: "פרמטרים אופציונליים: {0}",
|
||||
Save: "שמירה",
|
||||
Notifications: "התראות",
|
||||
"Not available, please setup.": "לא זמין, אנא הגדר.",
|
||||
"Setup Notification": "הודעת הגדרה",
|
||||
Light: "בהיר",
|
||||
Dark: "חושך",
|
||||
Auto: "אוטומטי",
|
||||
"Theme - Heartbeat Bar": "ערכת נושא - Heartbeat Bar",
|
||||
Normal: "נורמלי",
|
||||
Bottom: "למטה",
|
||||
None: "כלום",
|
||||
Timezone: "אזור זמן",
|
||||
"Search Engine Visibility": "נראות במנועי חיפוש",
|
||||
"Allow indexing": "אפשר הוספה לאינדקס",
|
||||
"Discourage search engines from indexing site": "לא לעודד מנועי חיפוש לאינדקס אתרים",
|
||||
"Change Password": "שנה סיסמא",
|
||||
"Current Password": "סיסמה נוכחית",
|
||||
"New Password": "סיסמה חדשה",
|
||||
"Repeat New Password": "חזור על סיסמה חדשה",
|
||||
"Update Password": "עדכן סיסמה",
|
||||
"Disable Auth": "השבתת אבטחה",
|
||||
"Enable Auth": "הפעלת אבטחה",
|
||||
"disableauth.message1": "האם אתה בטוח שברצונך <strong>להשבית את האבטחה</strong>?",
|
||||
"disableauth.message2": "הוא מיועד לתרחישים <strong>שבהם אתה מתכוון ליישם אימות של צד שלישי</strong> מול Uptime Kuma כגון Cloudflare Access, Authelia או מנגנוני אימות אחרים.",
|
||||
"Please use this option carefully!": "אנא השתמש באפשרות זו בזהירות!",
|
||||
Logout: "התנתקות",
|
||||
Leave: "יציאה",
|
||||
"I understand, please disable": "אני מבין, אני רוצה להשבית",
|
||||
Confirm: "אישור",
|
||||
Yes: "כן",
|
||||
No: "לא",
|
||||
Username: "שם משתמש",
|
||||
Password: "סיסמה",
|
||||
"Remember me": "זכור אותי",
|
||||
Login: "התחברות",
|
||||
"No Monitors, please": "בלי מוניטורים, בבקשה",
|
||||
"add one": "להוסיף אחד",
|
||||
"Notification Type": "סוג התראה",
|
||||
Email: "אימייל",
|
||||
Test: "Test",
|
||||
"Certificate Info": "פרטי תעודת אבטחה",
|
||||
"Resolver Server": "שרת פותר",
|
||||
"Resource Record Type": "סוג רשומת משאבים",
|
||||
"Last Result": "תוצאה אחרונה",
|
||||
"Create your admin account": "צור את חשבון הניהול שלך",
|
||||
"Repeat Password": "חזור על הסיסמה",
|
||||
"Import Backup": "ייבוא גיבוי",
|
||||
"Export Backup": "ייצוא גיבוי",
|
||||
Export: "ייצוא",
|
||||
Import: "ייבוא",
|
||||
respTime: "רפ. זמן (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
"Default enabled": "ברירת המחדל מופעלת",
|
||||
"Apply on all existing monitors": "החל על כל המסכים הקיימים",
|
||||
Create: "ליצור",
|
||||
"Clear Data": "נקה נתונים",
|
||||
Events: "אירועים",
|
||||
Heartbeats: "פעימות לב",
|
||||
"Auto Get": "קבל אוטומטי",
|
||||
backupDescription: "אתה יכול לגבות את כל המסכים וההתראות לקובץ JSON.",
|
||||
backupDescription2: "הערה: היסטוריה ונתוני אירועים אינם כלולים.",
|
||||
backupDescription3: "נתונים רגישים כגון אסימוני הודעה כלולים בקובץ הייצוא; נא לאחסן יצוא בצורה מאובטחת.",
|
||||
alertNoFile: "אנא בחר קובץ לייבוא.",
|
||||
alertWrongFileType: "אנא בחר קובץ JSON.",
|
||||
"Clear all statistics": "נקה את כל הנתונים הסטטיסטיים",
|
||||
"Skip existing": "דילוג על הקיים",
|
||||
Overwrite: "החלף",
|
||||
Options: "אפשרויות",
|
||||
"Keep both": "שמור את שניהם",
|
||||
"Verify Token": "אמת את האסימון",
|
||||
"Setup 2FA": "הגדרת מערכת אדוש",
|
||||
"Enable 2FA": "הפעלת אדוש",
|
||||
"Disable 2FA": "כיבוי אדוש",
|
||||
"2FA Settings": "הגדרות אדוש",
|
||||
"Two Factor Authentication": "אימות דו-שלבי (מערכת אדוש)",
|
||||
Active: "מופעל",
|
||||
Inactive: "קבוי",
|
||||
Token: "אסימון",
|
||||
"Show URI": "הצג URI",
|
||||
Tags: "תגים",
|
||||
"Add New below or Select...": "הוסף חדש למטה או בחר...",
|
||||
"Tag with this name already exist.": "תג בשם זה כבר קיים.",
|
||||
"Tag with this value already exist.": "תג עם ערך זה כבר קיים.",
|
||||
color: "צבע",
|
||||
"value (optional)": "ערך (אופציונלי)",
|
||||
Gray: "אפור",
|
||||
Red: "אדום",
|
||||
Orange: "כתום",
|
||||
Green: "ירוק",
|
||||
Blue: "כחול",
|
||||
Indigo: "כחול כהה",
|
||||
Purple: "סגול",
|
||||
Pink: "כתום",
|
||||
"Search...": "לחפש...",
|
||||
"Avg. Ping": "פינג ממוצע",
|
||||
"Avg. Response": "ממוצע תגובה",
|
||||
"Entry Page": "דף כניסה",
|
||||
statusPageNothing: "אין כאן שום דבר, בבקשה הוסף קבוצה או מוניטור.",
|
||||
"No Services": "אין שירותים",
|
||||
"All Systems Operational": "כל המערכות עובדות",
|
||||
"Partially Degraded Service": "שירות פגום חלקית",
|
||||
"Degraded Service": "שירות פגום",
|
||||
"Add Group": "הוסף קבוצה",
|
||||
"Add a monitor": "הוסף מוניטור",
|
||||
"Edit Status Page": "ערוך דף סטטוס",
|
||||
"Go to Dashboard": "מעבר לפאנל",
|
||||
"Status Page": "דף סטטוס",
|
||||
"Status Pages": "דפי סטטוס",
|
||||
defaultNotificationName: "התראת {notification} שלי ({number})",
|
||||
here: "פה",
|
||||
Required: "נדרש",
|
||||
telegram: "טלגרם",
|
||||
"Bot Token": "אסימון בוט",
|
||||
wayToGetTelegramToken: "אתה יכול לקבל אסימון מ-{0}.",
|
||||
"Chat ID": "מזהה צ'אט",
|
||||
supportTelegramChatID: "תמיכה בצ'אט ישיר / קבוצה / מזהה הצ'אט של הערוץ",
|
||||
wayToGetTelegramChatID: "אתה יכול לקבל את מזהה הצ'אט שלך על ידי שליחת הודעה לבוט ומעבר לכתובת האתר הזו כדי להציג את ה-chat_id:",
|
||||
"YOUR BOT TOKEN HERE": "אסימון הבוט שלך כאן",
|
||||
chatIDNotFound: "מזהה צ'אט לא נמצא; אנא שלח הודעה לבוט זה תחילה",
|
||||
webhook: "Webhook",
|
||||
"Post URL": "כתובת אתר של פוסט",
|
||||
"Content Type": "סוג התוכן",
|
||||
webhookJsonDesc: "{0} מתאים לכל שרתי HTTP מודרניים כגון Express.js",
|
||||
webhookFormDataDesc: "{multipart} טוב ל-PHP. יהיה צורך לנתח את ה-JSON באמצעות {decodeFunction}",
|
||||
webhookAdditionalHeadersTitle: "כותרות נוספות",
|
||||
webhookAdditionalHeadersDesc: "מגדיר כותרות נוספות שנשלחות עם ה-webhook.",
|
||||
smtp: "אימייל (SMTP)",
|
||||
secureOptionNone: "None / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "התעלם משגיאת TLS",
|
||||
"From Email": "אמייל שולח",
|
||||
emailCustomSubject: "נושא מותאם אישית",
|
||||
"To Email": "למייל",
|
||||
smtpCC: "עותק",
|
||||
smtpBCC: "עותק מוסתר",
|
||||
discord: "דיסקורד",
|
||||
"Discord Webhook URL": "כתובת אתר של Discord Webhook",
|
||||
wayToGetDiscordURL: "אתה יכול לקבל זאת על ידי מעבר להגדרות שרת -> אינטגרציות -> צור Webhook",
|
||||
"Bot Display Name": "שם תצוגה של בוט",
|
||||
"Prefix Custom Message": "קידומת הודעה מותאמת אישית",
|
||||
"Hello @everyone is...": "שלום {'@'}כולם...",
|
||||
teams: "Microsoft Teams",
|
||||
"Webhook URL": "כתובת האתר של Webhook",
|
||||
wayToGetTeamsURL: "אתה יכול ללמוד כיצד ליצור כתובת אתר ל-webhook {0}.",
|
||||
signal: "אוֹת",
|
||||
Number: "מספר",
|
||||
Recipients: "נמענים",
|
||||
needSignalAPI: "אתה צריך שיהיה לך לקוח איתות עם REST API.",
|
||||
wayToCheckSignalURL: "אתה יכול לבדוק את כתובת האתר הזו כדי לראות כיצד להגדיר אחת:",
|
||||
signalImportant: "חשוב: לא ניתן לערבב קבוצות ומספרים בנמענים!",
|
||||
gotify: "Gotify",
|
||||
"Application Token": "אסימון אפליקציה",
|
||||
"Server URL": "כתובת האתר של השרת",
|
||||
Priority: "עדיפות",
|
||||
slack: "Slack",
|
||||
"Icon Emoji": "אייקון אימוג'י",
|
||||
"Channel Name": "שם הערוץ",
|
||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||
aboutWebhooks: "מידע נוסף על Webhooks ב: {0}",
|
||||
aboutChannelName: "הזן את שם הערוץ בשדה {0} שם ערוץ אם ברצונך לעקוף את ערוץ Webhook. לדוגמה: #ערוץ אחר",
|
||||
aboutKumaURL: "אם תשאיר את השדה Uptime Kuma URL ריק, הוא יעבור כברירת מחדל לעמוד Project GitHub.",
|
||||
emojiCheatSheet: "גיליון הונאה של אמוג'י: {0}",
|
||||
"rocket.chat": "Rocket.Chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
PushByTechulus: "Push by Techulus",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
clicksendsms: "ClickSend SMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (תומך ב-50+ שירותי התראות)",
|
||||
GoogleChat: "Google Chat (Google Workspace בלבד)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "מפתח משתמש",
|
||||
Device: "התקן",
|
||||
"Message Title": "כותרת ההודעה",
|
||||
"Notification Sound": "צליל התראה",
|
||||
"More info on:": "מידע נוסף על: {0}",
|
||||
pushoverDesc1: "לעדיפות חירום (2) יש פסק זמן של 30 שניות ברירת מחדל בין ניסיונות חוזרים, והיא תפוג לאחר שעה.",
|
||||
pushoverDesc2: "אם ברצונך לשלוח התראות למכשירים שונים, מלא את שדה התקן.",
|
||||
"SMS Type": "סוג SMS",
|
||||
octopushTypePremium: "פרימיום (מהיר - מומלץ להתראה)",
|
||||
octopushTypeLowCost: "עלות נמוכה (איטית - לפעמים חסומה על ידי המפעיל)",
|
||||
checkPrice: "בדוק מחירים של {0}:",
|
||||
apiCredentials: "אישורי API",
|
||||
octopushLegacyHint: "האם אתה משתמש בגרסה הישנה של Octopush (2011-2020) או בגרסה החדשה?",
|
||||
"Check octopush prices": "בדוק מחירי תמנון {0}.",
|
||||
octopushPhoneNumber: "מספר טלפון (פורמט אינטלי, למשל: +33612345678)",
|
||||
octopushSMSSender: "שם שולח SMS: 3-11 תווים אלפאנומריים ורווח (a-zA-Z0-9)",
|
||||
"LunaSea Device ID": "מזהה מכשיר LunaSea",
|
||||
"Apprise URL": "Apprise URL",
|
||||
"Example:": "דוגמה: {0}",
|
||||
"Read more:": "קרא עוד: {0}",
|
||||
"Status:": "סטטוס: {0}",
|
||||
"Read more": "קרא עוד",
|
||||
appriseInstalled: "Apprise מותקן.",
|
||||
appriseNotInstalled: "Apprise אינו מותקן. {0}",
|
||||
"Access Token": "אסימון גישה",
|
||||
"Channel access token": "אסימון גישה לערוץ",
|
||||
"Line Developers Console": "קונסולת מפתחים",
|
||||
lineDevConsoleTo: "קו מפתחי קונסולת - {0}",
|
||||
"Basic Settings": "הגדרות בסיסיות",
|
||||
"User ID": "תעודת זהות של משתמש",
|
||||
"Messaging API": "Messaging API",
|
||||
wayToGetLineChannelToken: "תחילה גש ל-{0}, צור ספק וערוץ (Messaging API), לאחר מכן תוכל לקבל את אסימון הגישה לערוץ ומזהה המשתמש מפריטי התפריט שהוזכרו לעיל.",
|
||||
"Icon URL": "כתובת אתר של סמל",
|
||||
aboutIconURL: "אתה יכול לספק קישור לתמונה ב\"כתובת URL של סמל\" כדי לעקוף את תמונת הפרופיל המוגדרת כברירת מחדל. לא ישמש אם Icon Emoji מוגדר.",
|
||||
aboutMattermostChannelName: "אתה יכול לעקוף את ערוץ ברירת המחדל שאליו ה-Webhook מפרסם על ידי הזנת שם הערוץ בשדה \"שם ערוץ\". זה צריך להיות מופעל בהגדרות Mattermos Webhook. לדוגמה: #ערוץ אחר",
|
||||
matrix: "Matrix",
|
||||
promosmsTypeEco: "SMS ECO - זול אך איטי ולעיתים עמוס מדי. מוגבל רק לנמענים פולנים.",
|
||||
promosmsTypeFlash: "SMS FLASH - ההודעה תוצג אוטומטית במכשיר הנמען. מוגבל לנמענים פולנים בלבד.",
|
||||
promosmsTypeFull: "SMS FULL - שכבת פרימיום של SMS, אתה יכול להשתמש בשם השולח שלך (עליך לרשום את השם תחילה). אמין להתראות.",
|
||||
promosmsTypeSpeed: "SMS SPEED - העדיפות הגבוהה ביותר במערכת. מאוד מהיר ואמין אבל יקר (בערך פי שניים ממחיר מלא של SMS).",
|
||||
promosmsPhoneNumber: "מספר טלפון (לנמען פולני ניתן לדלג על אזורי חיוג)",
|
||||
promosmsSMSSender: "שם שולח SMS: שם רשום מראש או אחת מברירות המחדל: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
"Feishu WebHookUrl": "Feishu WebHookURL",
|
||||
matrixHomeserverURL: "כתובת האתר של שרת הבית (עם http(s):// ויציאה אופציונלית)",
|
||||
"Internal Room Id": "מזהה חדר פנימי",
|
||||
matrixDesc1: "אתה יכול למצוא את מזהה החדר הפנימי על ידי עיון בחלק המתקדם של לקוח Matrix שלך בהגדרות החדר. זה צריך להיראות כמו !QMdRCpUIfLwsfjxye6:home.server.",
|
||||
matrixDesc2: "מומלץ מאוד ליצור משתמש חדש ולא להשתמש באסימון הגישה של משתמש מטריקס משלך שכן הוא יאפשר גישה מלאה לחשבון שלך ולכל החדרים שהצטרפת אליהם. במקום זאת, צור משתמש חדש והזמן אותו רק לחדר שבו תרצה לקבל את ההתראה. תוכל לקבל את אסימון הגישה על ידי הפעלת {0}",
|
||||
Method: "Method",
|
||||
Body: "Body",
|
||||
Headers: "Headers",
|
||||
PushUrl: "Push URL",
|
||||
HeadersInvalidFormat: "כותרות הבקשה אינן JSON חוקיות:",
|
||||
BodyInvalidFormat: "גוף הבקשה אינו JSON חוקי:",
|
||||
"Monitor History": "מעקב אחר היסטוריה",
|
||||
clearDataOlderThan: "שמור את נתוני היסטוריית הצג למשך {0} ימים.",
|
||||
PasswordsDoNotMatch: "סיסמאות לא תואמות.",
|
||||
records: "רשומות",
|
||||
"One record": "שיא אחד",
|
||||
steamApiKeyDescription: "לניטור שרת משחקי Steam אתה צריך מפתח Steam Web-API. אתה יכול לרשום את מפתח ה-API שלך כאן:",
|
||||
"Current User": "משתמש נוכחי",
|
||||
topic: "נושא",
|
||||
topicExplanation: "נושא MQTT למעקב",
|
||||
successMessage: "הודעת הצלחה",
|
||||
successMessageExplanation: "הודעת MQTT שתיחשב כהצלחה",
|
||||
recent: "לאחרונה",
|
||||
Done: "בוצע",
|
||||
Info: "מידע",
|
||||
Security: "אבטחה",
|
||||
"Steam API Key": "מפתח API Steam",
|
||||
"Shrink Database": "מסד נתונים מכווץ",
|
||||
"Pick a RR-Type...": "בחר סוג RR ...",
|
||||
"Pick Accepted Status Codes...": "בחר קודי סטטוס מקובלים ...",
|
||||
Default: "בְּרִירַת מֶחדָל",
|
||||
"HTTP Options": "אפשרויות HTTP",
|
||||
"Create Incident": "ליצור אירוע",
|
||||
Title: "כותרת",
|
||||
Content: "תוֹכֶן",
|
||||
Style: "Style",
|
||||
info: "מידע",
|
||||
warning: "אַזהָרָה",
|
||||
danger: "סַכָּנָה",
|
||||
error: "שְׁגִיאָה",
|
||||
critical: "קריטי",
|
||||
primary: "יְסוֹדִי",
|
||||
light: "אוֹר",
|
||||
dark: "אפל",
|
||||
Post: "הודעה",
|
||||
"Please input title and content": "אנא הזן כותרת ותוכן",
|
||||
Created: "נוצר",
|
||||
"Last Updated": "עודכן לאחרונה",
|
||||
Unpin: "ענן חוף",
|
||||
"Switch to Light Theme": "לעבור לנושא האור",
|
||||
"Switch to Dark Theme": "לעבור לנושא אפל",
|
||||
"Show Tags": "Show Tags",
|
||||
"Hide Tags": "הסתר תגיות",
|
||||
Description: "תיאור",
|
||||
"No monitors available.": "אין צגים זמינים.",
|
||||
"Add one": "הוסף אחד",
|
||||
"No Monitors": "אין צגים",
|
||||
"Untitled Group": "קבוצה ללא כותרת",
|
||||
Services: "שירותים",
|
||||
Discard: "להשליך",
|
||||
Cancel: "לְבַטֵל",
|
||||
"Powered by": "פועל על",
|
||||
shrinkDatabaseDescription: "ואקום מסד נתונים להפעיל עבור SQLITE.אם בסיס הנתונים שלך נוצר לאחר 1.10.0, Auto_VACUUM כבר מופעל ואין צורך בפעולה זו.",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
serwersmsAPIUser: "API Username (incl. webapi_ prefix)",
|
||||
serwersmsAPIPassword: "סיסמת API",
|
||||
serwersmsPhoneNumber: "מספר טלפון",
|
||||
serwersmsSenderName: "שם שולח SMS (רשום באמצעות פורטל לקוחות)",
|
||||
smseagle: "SMSEagle",
|
||||
smseagleTo: "מספרי טלפון)",
|
||||
smseagleGroup: "שם קבוצת ספר טלפונים",
|
||||
smseagleContact: "שם איש קשר בספר הטלפונים",
|
||||
smseagleRecipientType: "Rסוג הנמען",
|
||||
smseagleRecipient: "נמענים (ים) (יש להפריד בין מרובים לפסיק)",
|
||||
smseagleToken: "API Access Token",
|
||||
smseagleUrl: "כתובת האתר של מכשיר ה- SMSeagege שלך",
|
||||
smseagleEncoding: "שלח כ- Unicode",
|
||||
smseaglePriority: "עדיפות הודעה (0-9, ברירת מחדל = 0)",
|
||||
stackfield: "סטאקפילד",
|
||||
Customize: "התאמה אישית",
|
||||
"Custom Footer": "כותרת תחתונה מותאמת אישית",
|
||||
"Custom CSS": "CSS מותאם אישית",
|
||||
smtpDkimSettings: "הגדרות DKIM",
|
||||
smtpDkimDesc: "אנא עיין ב- NodeMailer DKIM {0} לשימוש.",
|
||||
documentation: "ווקיפדיית מדריכים",
|
||||
smtpDkimDomain: "שם דומיין",
|
||||
smtpDkimKeySelector: "בורר מפתח",
|
||||
smtpDkimPrivateKey: "טוראי של פרטיy",
|
||||
smtpDkimHashAlgo: "אלגוריתם hash (אופציונלי)",
|
||||
smtpDkimheaderFieldNames: "מפתחות כותרת לחתום (אופציונלי)",
|
||||
smtpDkimskipFields: "מפתחות כותרת לא לחתום (אופציונלי)",
|
||||
wayToGetPagerDutyKey: "אתה יכול להשיג זאת על ידי מעבר לשירות -> ספריית שירות -> (בחר שירות) -> אינטגרציות -> הוסף אינטגרציה.כאן תוכלו לחפש \"אירועים API v2 \".מידע נוסף {0}",
|
||||
"Integration Key": "מפתח אינטגרציה",
|
||||
"Integration URL": "URL אינטגרציה",
|
||||
"Auto resolve or acknowledged": "פיתרון אוטומטי או הודה",
|
||||
"do nothing": "לעשות כלום",
|
||||
"auto acknowledged": "Auto הודה",
|
||||
"auto resolve": "פתרון אוטומטי",
|
||||
gorush: "Gorush",
|
||||
alerta: "Alerta",
|
||||
alertaApiEndpoint: "נקודת קצה של API",
|
||||
alertaEnvironment: "סביבה",
|
||||
alertaApiKey: "מפתח API",
|
||||
alertaAlertState: "מצב התראה",
|
||||
alertaRecoverState: "לשחזר מדינה",
|
||||
deleteStatusPageMsg: "האם אתה בטוח רוצה למחוק את דף הסטטוס הזה?",
|
||||
Proxies: "Proxies",
|
||||
default: "בְּרִירַת מֶחדָל",
|
||||
enabled: "מופעל",
|
||||
setAsDefault: "נקבע כברירת מחדל",
|
||||
deleteProxyMsg: "האם אתה בטוח רוצה למחוק את הפרוקסי הזה לכל המסכים?",
|
||||
proxyDescription: "Proxies must be assigned to a monitor to function.",
|
||||
enableProxyDescription: "פרוקסי זה לא ישפיע על בקשות צג עד שהוא יופעל.אתה יכול לשלוט באופן זמני להשבית את ה- Proxy מכל המסכים לפי מצב ההפעלה.",
|
||||
setAsDefaultProxyDescription: "פרוקסי זה יופעל כברירת מחדל עבור צגים חדשים.אתה עדיין יכול להשבית את ה- Proxy בנפרד עבור כל צג.",
|
||||
"Certificate Chain": "שרשרת אישורים",
|
||||
Valid: "תָקֵף",
|
||||
Invalid: "לא חוקי",
|
||||
AccessKeyId: "מזהה AccessKey",
|
||||
SecretAccessKey: "גישהלמפתחסוד",
|
||||
PhoneNumbers: "מספר טלפוןs",
|
||||
TemplateCode: "TemplateCode",
|
||||
SignName: "שם שם",
|
||||
"Sms template must contain parameters: ": "תבנית SMS חייבת להכיל פרמטרים: ",
|
||||
"Bark Endpoint": "Bark Endpoint",
|
||||
"Bark Group": "Bark Group",
|
||||
"Bark Sound": "Bark Sound",
|
||||
WebHookUrl: "WebHookUrl",
|
||||
SecretKey: "מפתח סודי",
|
||||
"For safety, must use secret key": "לבטיחות, חייב להשתמש במפתח סודיy",
|
||||
"Device Token": "אסימון מכשיר",
|
||||
Platform: "פּלַטפוֹרמָה",
|
||||
iOS: "iOS",
|
||||
Android: "דְמוּי אָדָם",
|
||||
Huawei: "huawei",
|
||||
High: "High",
|
||||
Retry: "נסה שוב",
|
||||
Topic: "נוֹשֵׂא",
|
||||
"WeCom Bot Key": "WeCom Bot Key",
|
||||
"Setup Proxy": "הגדרת פרוקסי",
|
||||
"Proxy Protocol": "פרוטוקול פרוקסי",
|
||||
"Proxy Server": "שרת פרוקסי",
|
||||
"Proxy server has authentication": "לשרת ה- Proxy יש אימות",
|
||||
User: "מִשׁתַמֵשׁ",
|
||||
Installed: "מוּתקָן",
|
||||
"Not installed": "לא מותקן",
|
||||
Running: "רץ",
|
||||
"Not running": "לא רץ",
|
||||
"Remove Token": "הסר אסימון",
|
||||
Start: "הַתחָלָה",
|
||||
Stop: "תפסיק",
|
||||
"Uptime Kuma": "Uptime Kuma",
|
||||
"Add New Status Page": "הוסף דף סטטוס חדש",
|
||||
Slug: "Slug",
|
||||
"Accept characters:": "קבל תווים:",
|
||||
startOrEndWithOnly: "התחל או סוף עם {0} בלבד",
|
||||
"No consecutive dashes": "אין מקפים רצופים",
|
||||
Next: "הַבָּא",
|
||||
"The slug is already taken. Please choose another slug.": "השבלול כבר נלקח.אנא בחר שבלול נוסף.",
|
||||
"No Proxy": "אין פרוקסי",
|
||||
Authentication: "אבטחה",
|
||||
"HTTP Basic Auth": "HTTP בסיסי Auth",
|
||||
"New Status Page": "דף סטטוס חדש",
|
||||
"Page Not Found": "הדף לא נמצא",
|
||||
"Reverse Proxy": "פרוקסי הפוך",
|
||||
Backup: "גיבוי",
|
||||
About: "אודות",
|
||||
wayToGetCloudflaredURL: "(הורד את CloudFlared מ- {0})",
|
||||
cloudflareWebsite: "אתר CloudFlare",
|
||||
"Message:": "הוֹדָעָה:",
|
||||
"Don't know how to get the token? Please read the guide:": "לא יודע איך להשיג את האסימון?אנא קרא את המדריך:",
|
||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "החיבור הנוכחי עשוי ללכת לאיבוד אם אתה מתחבר כרגע באמצעות מנהרת CloudFlare.האם אתה בטוח רוצה לעצור את זה?הקלד את הסיסמה הנוכחית שלך כדי לאשר אותה.",
|
||||
"HTTP Headers": "כותרות HTTP",
|
||||
"Trust Proxy": "אמון בפרוקסי",
|
||||
"Other Software": "תוכנה אחרת",
|
||||
"For example: nginx, Apache and Traefik.": "למשל: Nginx, Apache ו- Traefik.",
|
||||
"Please read": "בבקשה תקרא",
|
||||
"Subject:": "נושא:",
|
||||
"Valid To:": "תקף ל:",
|
||||
"Days Remaining:": "ימים שנותרו:",
|
||||
"Issuer:": "המנפיק:",
|
||||
"Fingerprint:": "טביעת אצבע:",
|
||||
"No status pages": "אין דפי סטטוס",
|
||||
"Domain Name Expiry Notification": "הודעה על תום שם תחום",
|
||||
Proxy: "פרוקסי",
|
||||
"Date Created": "תאריך יצירה",
|
||||
HomeAssistant: "Home Assistant",
|
||||
onebotHttpAddress: "כתובת HTTP של OneBot ",
|
||||
onebotMessageType: "סוג ההודעה OneBot",
|
||||
onebotGroupMessage: "קְבוּצָה",
|
||||
onebotPrivateMessage: "פְּרָטִי",
|
||||
onebotUserOrGroupId: "מזהה קבוצה/משתמש ",
|
||||
onebotSafetyTips: "לבטיחות, חייב לקבוע אסימון גישה ",
|
||||
"PushDeer Key": "PushDeer Key",
|
||||
"Footer Text": "טקסט כותרת תחתונה ",
|
||||
"Show Powered By": "הצג מופעל על ידי ",
|
||||
"Domain Names": "שמות דומיין ",
|
||||
signedInDisp: "חתום כ- {0} ",
|
||||
signedInDispDisabled: "Auth מושבת.",
|
||||
RadiusSecret: "רדיוס סוד",
|
||||
RadiusSecretDescription: "סוד משותף בין לקוח לשרת",
|
||||
RadiusCalledStationId: "נקרא מזהה תחנה",
|
||||
RadiusCalledStationIdDescription: "מזהה של המכשיר הנקרא ",
|
||||
RadiusCallingStationId: "מזהה תחנת שיחה ",
|
||||
RadiusCallingStationIdDescription: "מזהה של מכשיר השיחה ",
|
||||
"Certificate Expiry Notification": "הודעת תפוגה של אישור",
|
||||
"API Username": "שם משתמש API",
|
||||
"API Key": "מפתח API",
|
||||
"Recipient Number": "מספר הנמען",
|
||||
"From Name/Number": "משם/מספר",
|
||||
"Leave blank to use a shared sender number.": "השאר ריק כדי להשתמש במספר שולח משותף.",
|
||||
"Octopush API Version": "גרסת API של תמנון",
|
||||
"Legacy Octopush-DM": "Legacy Octopush-DM",
|
||||
endpoint: "נקודת קצה",
|
||||
octopushAPIKey: "\"מפתח API \" מתוך תעודות API של HTTP בלוח הבקרה",
|
||||
octopushLogin: "\"כניסה \" מתעודות API של HTTP בלוח הבקרה",
|
||||
promosmsLogin: "שם כניסה של API",
|
||||
promosmsPassword: "סיסמת API",
|
||||
"pushoversounds pushover": "Pushover (ברירת מחדל)",
|
||||
"pushoversounds bike": "אופניים",
|
||||
"pushoversounds bugle": "חֲצוֹצְרָה",
|
||||
"pushoversounds cashregister": "קופה רושמת",
|
||||
"pushoversounds classical": "קלַאסִי",
|
||||
"pushoversounds cosmic": "קוֹסמִי",
|
||||
"pushoversounds falling": "נופל",
|
||||
"pushoversounds gamelan": "gamelan",
|
||||
"pushoversounds incoming": "נִכנָס",
|
||||
"pushoversounds intermission": "Intermission",
|
||||
"pushoversounds magic": "קֶסֶם",
|
||||
"pushoversounds mechanical": "מֵכָנִי",
|
||||
"pushoversounds pianobar": "בר פסנתר",
|
||||
"pushoversounds siren": "סִירֶנָה",
|
||||
"pushoversounds spacealarm": "אזעקת חלל",
|
||||
"pushoversounds tugboat": "סירת משיכה",
|
||||
"pushoversounds alien": "אזעקת חייזרים (ארוכה)",
|
||||
"pushoversounds climb": "לטפס (ארוך)",
|
||||
"pushoversounds persistent": "מתמיד (ארוך)",
|
||||
"pushoversounds echo": "הד Pushover (ארוך)",
|
||||
"pushoversounds updown": "למעלה (ארוך)",
|
||||
"pushoversounds vibrate": "לרטוט בלבד",
|
||||
"pushoversounds none": "אף אחד (שקט)",
|
||||
pushyAPIKey: "מפתח API סודי",
|
||||
pushyToken: "אסימון מכשיר",
|
||||
"Show update if available": "הצג עדכון אם זמין",
|
||||
"Also check beta release": "בדוק גם את שחרור הבטא",
|
||||
"Using a Reverse Proxy?": "באמצעות פרוקסי הפוך?",
|
||||
"Check how to config it for WebSocket": "בדוק כיצד להגדיר אותו ל- WebSocket",
|
||||
"Steam Game Server": "שרת משחק קיטור",
|
||||
"Most likely causes:": "ככל הנראה גורם:",
|
||||
"The resource is no longer available.": "המשאב כבר לא זמין.",
|
||||
"There might be a typing error in the address.": "יתכן שיש שגיאת הקלדה בכתובת.",
|
||||
"What you can try:": "מה שאתה יכול לנסות:",
|
||||
"Retype the address.": "הקלד מחדש את הכתובת.",
|
||||
"Go back to the previous page.": "חזור לדף הקודם.",
|
||||
"Coming Soon": "בקרוב",
|
||||
wayToGetClickSendSMSToken: "אתה יכול לקבל שם משתמש API ומפתח API מ- {0}.",
|
||||
"Connection String": "מחרוזת חיבור",
|
||||
Query: "שאילתא",
|
||||
settingsCertificateExpiry: "תפוגת תעודת TLS",
|
||||
certificationExpiryDescription: "HTTPS עוקב אחר התראה על התראה כאשר תעודת TLS פגה ב:",
|
||||
"Setup Docker Host": "הגדרת מארח Docker",
|
||||
"Connection Type": "סוג חיבור",
|
||||
"Docker Daemon": "Docker Daemon",
|
||||
deleteDockerHostMsg: "האם אתה בטוח רוצה למחוק את המארח של Docker לכל המוניטורים?",
|
||||
socket: "Socket",
|
||||
tcp: "TCP / HTTP",
|
||||
"Docker Container": "מיכל Docker",
|
||||
"Container Name / ID": "שם מכולה / מזהה",
|
||||
"Docker Host": "מארח דוקר",
|
||||
"Docker Hosts": "מארחי Docker",
|
||||
"ntfy Topic": "ntfy Topic",
|
||||
Domain: "תְחוּם",
|
||||
Workstation: "עמדת עבודה",
|
||||
disableCloudflaredNoAuthMsg: "אתה לא נמצא במצב AUTH, אין צורך בסיסמה.",
|
||||
trustProxyDescription: "סמוך על כותרות 'x-forwarded-*'.אם אתה רוצה להשיג את ה- IP של הלקוח הנכון וה- Uptime Kuma שלך מאחור כמו Nginx או Apache, עליך לאפשר זאת.",
|
||||
wayToGetLineNotifyToken: "אתה יכול לקבל אסימון גישה מ- {0}",
|
||||
Examples: "דוגמאות",
|
||||
"Home Assistant URL": "כתובת URL עוזרת ביתית",
|
||||
"Long-Lived Access Token": "אסימון גישה ארוכת שנים",
|
||||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "ניתן ליצור אסימון גישה לאורך זמן על ידי לחיצה על שם הפרופיל שלך (שמאל למטה) וגלילה לתחתית ואז לחץ על צור אסימון. ",
|
||||
"Notification Service": "Notification Service",
|
||||
"default: notify all devices": "default: notify all devices",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "רשימה של שירותי הודעה ניתן למצוא בעוזר הבית תחת \"כלי מפתחים> שירותים \" חפש \"הודעה \" כדי למצוא את שם המכשיר/טלפון שלך.",
|
||||
"Automations can optionally be triggered in Home Assistant:": "אוטומציות יכולות להיות מופעלות באופן אופציונלי לעוזר הבית:",
|
||||
"Trigger type:": "סוג ההדק:",
|
||||
"Event type:": "סוג אירוע:",
|
||||
"Event data:": "נתוני אירועים:",
|
||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "ואז בחר פעולה, למשל העבר את הסצינה למקום בו אור RGB הוא אדום.",
|
||||
"Frontend Version": "גרסת Frontend",
|
||||
"Frontend Version do not match backend version!": "גרסת Frontend לא תואמת את גרסת Backend!",
|
||||
"Base URL": "Base URL",
|
||||
goAlertInfo: "SAETRERT הוא יישום קוד פתוח לתזמון שיחה, הסלמות והודעות אוטומטיות (כמו SMS או שיחות קוליות).לעסוק אוטומטית את האדם הנכון, בדרך הנכונה ובזמן הנכון!{0}",
|
||||
goAlertIntegrationKeyInfo: "קבל מפתח אינטגרציה של API גנרי לשירות בפורמט זה \"AAAAAAAA-BBB-CCCC-DDDD-EEEEEEEEEEE \" בדרך כלל הערך של פרמטר האסימון של URL שהועתק.",
|
||||
goAlert: "GoAlert",
|
||||
backupOutdatedWarning: "מיושם: מכיוון שהרבה תכונות שנוספו ותכונת הגיבוי הזו מעט לא מצומצמת, היא לא יכולה לייצר או לשחזר גיבוי שלם.",
|
||||
backupRecommend: "אנא גבה את עוצמת הקול או את תיקיית הנתונים (./data/) ישירות במקום.",
|
||||
Optional: "אופציונאלי",
|
||||
squadcast: "Squadcast",
|
||||
SendKey: "SendKey",
|
||||
"SMSManager API Docs": "מסמכי API של SmsManager ",
|
||||
"Gateway Type": "סוג שער",
|
||||
SMSManager: "SMSManager",
|
||||
"You can divide numbers with": "אתה יכול לחלק מספרים עם",
|
||||
or: "אוֹ",
|
||||
recurringInterval: "הפסקה",
|
||||
Recurring: "מחזורי",
|
||||
strategyManual: "פעיל/לא פעיל באופן ידני",
|
||||
warningTimezone: "זה משתמש באזור הזמן של השרת",
|
||||
weekdayShortMon: "שני",
|
||||
weekdayShortTue: "שלישי",
|
||||
weekdayShortWed: "רביעי",
|
||||
weekdayShortThu: "חמישי",
|
||||
weekdayShortFri: "שישי",
|
||||
weekdayShortSat: "שבת",
|
||||
weekdayShortSun: "ראשון",
|
||||
dayOfWeek: "יום בשבוע",
|
||||
dayOfMonth: "יום בחודש",
|
||||
lastDay: "Last Day",
|
||||
lastDay1: "היום האחרון של החודש",
|
||||
lastDay2: "יום שני האחרון של החודש",
|
||||
lastDay3: "יום 3 האחרון של החודש",
|
||||
lastDay4: "היום הרביעי האחרון בחודש",
|
||||
"No Maintenance": "אין תחזוקה",
|
||||
pauseMaintenanceMsg: "האם אתה בטוח רוצה להשהות?",
|
||||
"maintenanceStatus-under-maintenance": "מתבצעות עבודות תחזוקה",
|
||||
"maintenanceStatus-inactive": "לא פעיל",
|
||||
"maintenanceStatus-scheduled": "מתוזמן",
|
||||
"maintenanceStatus-ended": "הסתיים",
|
||||
"maintenanceStatus-unknown": "לא ידוע",
|
||||
"Display Timezone": "הצג אזור זמן",
|
||||
"Server Timezone": "אזור זמן של שרת",
|
||||
statusPageMaintenanceEndDate: "סוך",
|
||||
IconUrl: "קישור לתמונת אייקון",
|
||||
"Enable DNS Cache": "הפעל מטמון DNS",
|
||||
Enable: "הפעל",
|
||||
Disable: "השבת",
|
||||
dnsCacheDescription: "ייתכן שהוא לא עובד בסביבות IPv6 מסוימות, השבת אותו אם אתה נתקל בבעיות כלשהן.",
|
||||
"Single Maintenance Window": "חלון תחזוקה בודד",
|
||||
"Maintenance Time Window of a Day": "חלון זמן תחזוקה ביום",
|
||||
"Effective Date Range": "טווח תאריכים אפקטיבי",
|
||||
"Schedule Maintenance": "לוח זמנים לתחזוקה",
|
||||
"Date and Time": "תאריך ושעה",
|
||||
"DateTime Range": "טווח תאריכים וזמן",
|
||||
Strategy: "אסטרטגיה",
|
||||
"Free Mobile User Identifier": "מזהה משתמש נייד בחינם",
|
||||
"Free Mobile API Key": "מפתח API חינם לנייד",
|
||||
"Enable TLS": "אפשר TLS",
|
||||
"Proto Service Name": "שם שירות פרוטו",
|
||||
"Proto Method": "שיטת פרוטו",
|
||||
"Proto Content": "תוכן פרוטו",
|
||||
Economy: "חיסכון",
|
||||
Lowcost: "זול",
|
||||
high: "גבוהה",
|
||||
"General Monitor Type": "מוניטור כללי",
|
||||
"Passive Monitor Type": "מוניטור פסיבי",
|
||||
"Specific Monitor Type": "סוג מוניטור ספציפי",
|
||||
};
|
|
@ -5,7 +5,7 @@ export default {
|
|||
retriesDescription: "จำนวนครั้งสูงสุดที่จะลองก่อนบริการถูกระบุว่าไม่สามารถใช้งานได้และส่งการแจ้งเตือน",
|
||||
ignoreTLSError: "ไม่สนใจข้อผิดพลาด TLS/SSL สำหรับเว็บไซต์ HTTPS",
|
||||
upsideDownModeDescription: "กลับด้านสถานะ เช่น ถ้าบริการสามารถใช้งานได้จะถูกเปลี่ยนเป็นใช้งานไม่ได้",
|
||||
maxRedirectDescription: "จำนวนครั้งสูงสุดที่จะเปลี่ยนเส้นทาง, ตั่งเป็น 0 เพื่อปิดการเปลี่ยนเส้นทาง",
|
||||
maxRedirectDescription: "จำนวนครั้งสูงสุดที่จะเปลี่ยนเส้นทาง, ตั้งเป็น 0 เพื่อปิดการเปลี่ยนเส้นทาง",
|
||||
acceptedStatusCodesDescription: "เลือกรหัสสถานะที่ถือว่าการตอบกลับสำเร็จ",
|
||||
passwordNotMatchMsg: "รหัสผ่านไม่ตรงกัน",
|
||||
notificationDescription: "การแจ้งเตือนต้องกำหนดให้มอนิเตอร์เพื่อให้สามารถใช้งานได้",
|
||||
|
@ -16,7 +16,7 @@ export default {
|
|||
resolverserverDescription: "Cloudflare เป็นเซิร์ฟเวอร์ค้นหาเริ่มต้น, คุณสามารถเปลี่ยนเซิร์ฟเวอร์ได้ตลอดเวลา",
|
||||
rrtypeDescription: "เลือกประเภท DNS Record ที่คุณต้องการจะมอนิเตอร์",
|
||||
pauseMonitorMsg: "คุณแน่ใจหรือไม่ที่จะหยุดมอนิเตอร์ชั่วคราว?",
|
||||
enableDefaultNotificationDescription: "การแจ้งเตือนนี้จะถูกเปิดโดนค่าเริ่มต้นสำหรับมอนิเตอร์ใหม่, คุณสามารถปิดการแจ้งเตือนสำหรับแต่ละมอนิเตอร์ได้",
|
||||
enableDefaultNotificationDescription: "การแจ้งเตือนนี้จะถูกเปิดโดยค่าเริ่มต้นสำหรับมอนิเตอร์ใหม่, คุณสามารถปิดการแจ้งเตือนสำหรับแต่ละมอนิเตอร์ได้",
|
||||
clearEventsMsg: "คุณแน่ใจหรือไม่ที่จะลบเหตุการณ์ทั้งหมดสำหรับมอนิเตอร์นี้?",
|
||||
clearHeartbeatsMsg: "คุณแน่ใจหรือไม่ที่จะลบประวัติการตรวจสอบทั้งหมดสำหรับมอนิเตอร์นี้?",
|
||||
confirmClearStatisticsMsg: "คุณแน่ใจหรือไม่ที่จะลบสถิติทั้งหมด?",
|
||||
|
@ -49,12 +49,12 @@ export default {
|
|||
Status: "สถานะ",
|
||||
DateTime: "วันที่และเวลา",
|
||||
Message: "ข้อความ",
|
||||
"No important events": "ไม่มีกิจกรรมที่สำคัญ",
|
||||
"No important events": "ไม่มีเหตการณ์ที่สำคัญ",
|
||||
Resume: "ดำเนินการต่อ",
|
||||
Edit: "แก้ไข",
|
||||
Delete: "ลบ",
|
||||
Current: "ปัจจุบัน",
|
||||
Uptime: "เวลาที่ใช้งาน",
|
||||
Uptime: "เวลาที่ใช้งานได้",
|
||||
"Cert Exp.": "วันหมดอายุใบรับรอง",
|
||||
days: "วัน",
|
||||
day: "วัน",
|
||||
|
@ -69,7 +69,7 @@ export default {
|
|||
URL: "URL",
|
||||
Hostname: "ชื่อโฮสต์",
|
||||
Port: "พอร์ต",
|
||||
"Heartbeat Interval": "ระยะห่างระหว่างการทดสอบ",
|
||||
"Heartbeat Interval": "ระยะเวลาระหว่างการทดสอบ",
|
||||
Retries: "จำนวนครั้งที่จะลองใหม่",
|
||||
"Heartbeat Retry Interval": "ระยะห่างระหว่างการทดสอบใหม่หลังจากไม่สำเร็จ",
|
||||
Advanced: "ขั้นสูง",
|
||||
|
@ -112,7 +112,7 @@ export default {
|
|||
No: "ไม่",
|
||||
Username: "ชื่อผู้ใช้",
|
||||
Password: "รหัสผ่าน",
|
||||
"Remember me": "คงอยู่ในระบบ",
|
||||
"Remember me": "จดจำฉันไว้",
|
||||
Login: "เข้าสู่ระบบ",
|
||||
"No Monitors, please": "ไม่มีมอนิเตอร์, กรุณา",
|
||||
"add one": "สร้าง",
|
||||
|
@ -120,7 +120,7 @@ export default {
|
|||
Email: "อีเมล",
|
||||
Test: "ทดสอบ",
|
||||
"Certificate Info": "ข้อมูลใบรับรอง",
|
||||
"Resolver Server": "เซิร์ฟเวอร์ทีค้นหา",
|
||||
"Resolver Server": "เซิร์ฟเวอร์ที่ค้นหา",
|
||||
"Resource Record Type": "ประเภท DNS Record",
|
||||
"Last Result": "ผลล่าสุด",
|
||||
"Create your admin account": "สร้างบัญชีผู้ดูแลระบบ",
|
||||
|
@ -138,8 +138,8 @@ export default {
|
|||
Events: "เหตุการณ์",
|
||||
Heartbeats: "ประวัติการตรวจสอบ",
|
||||
"Auto Get": "ดึงอัตโนมัติ",
|
||||
backupDescription: "คุณสามารถสำรองข้อมูลการแจ้งเตือนและมอนิเตอร์ทั้งหมดได้ในไฟล์ JSON",
|
||||
backupDescription2: "หมายเหตุ : ประวัติและข้อมูลกิจกรรมจะไม่ถูกสำรอง",
|
||||
backupDescription: "คุณสามารถสำรองข้อมูลการแจ้งเตือนและมอนิเตอร์ทั้งหมดไว้ได้ในไฟล์ JSON",
|
||||
backupDescription2: "หมายเหตุ : ประวัติและข้อมูลเหตการณ์จะไม่ถูกสำรอง",
|
||||
backupDescription3: "ข้อมูลที่ละเอียดอ่อนเช่นกุญแจการแจ้งเตือนจะรวมอยู่ในไฟล์ข้อมูลสำรอง, โปรดเก็บข้อมูลสำรองอย่างปลอดภัย",
|
||||
alertNoFile: "กรุณาเลือกไฟล์ที่จะใช้งาน",
|
||||
alertWrongFileType: "กรุณาเลือกไฟล์ที่เป็น JSON",
|
||||
|
@ -153,7 +153,7 @@ export default {
|
|||
"Enable 2FA": "เปิดใช้งาน 2FA",
|
||||
"Disable 2FA": "ปิดใช้งาน 2FA",
|
||||
"2FA Settings": "ตั้งค่า 2FA",
|
||||
"Two Factor Authentication": "การตรวจสอบสิทธิ์สองปัจจัย",
|
||||
"Two Factor Authentication": "การยืนยันตัวตนแบบสองขั้นตอน",
|
||||
Active: "ใช้งาน",
|
||||
Inactive: "ไม่ใช้งาน",
|
||||
Token: "กุญแจ",
|
||||
|
@ -189,7 +189,7 @@ export default {
|
|||
"Status Pages": "หน้าสถานะ",
|
||||
defaultNotificationName: "การแจ้งเตือน {notification} ของฉัน ({number})",
|
||||
here: "ที่นี่",
|
||||
Required: "ต้องการ",
|
||||
Required: "จำเป็น",
|
||||
telegram: "Telegram",
|
||||
"Bot Token": "กุญแจของบอท",
|
||||
wayToGetTelegramToken: "คุณสามารถรับกุญแจได้จาก {0}.",
|
||||
|
@ -202,7 +202,7 @@ export default {
|
|||
"Post URL": "URL โพสต์",
|
||||
"Content Type": "ประเภทเนื้อหา",
|
||||
webhookJsonDesc: "{0} ดีสำหรับเซิร์ฟเวอร์ HTTP สมัยใหม่เช่น Express.js",
|
||||
webhookFormDataDesc: "{multipart} ดีสำหรับ PHP, JSON จะต้องถูกประมวลผลด้วย {decodeFunction}",
|
||||
webhookFormDataDesc: "{multipart} ดีสำหรับ PHP, ข้อมูล JSON จะต้องถูกประมวลผลด้วย {decodeFunction}",
|
||||
smtp: "Email (SMTP)",
|
||||
secureOptionNone: "None / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
|
@ -224,7 +224,7 @@ export default {
|
|||
signal: "Signal",
|
||||
Number: "หมายเลข",
|
||||
Recipients: "ผู้รับ",
|
||||
needSignalAPI: "คุณต้องมี Signal Client ที่มี Rest APIl",
|
||||
needSignalAPI: "คุณต้องมี Signal Client ที่มี Rest API",
|
||||
wayToCheckSignalURL: "คุณสามารถตรวจสอบ URL นี้เพื่อดูวิธีตั้งค่า :",
|
||||
signalImportant: "สำคัญ: คุณไม่สามารถผสมกลุ่มและตัวเลขในผู้รับได้!",
|
||||
gotify: "Gotify",
|
||||
|
@ -236,7 +236,7 @@ export default {
|
|||
"Channel Name": "ชื่อห้อง",
|
||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||
aboutWebhooks: "ข้อมูลเพิ่มเติมสำหรับ Webhooks : {0}",
|
||||
aboutChannelName: "ใส่ชื่อห้องบน {0} ในช่องชื่อห้องถ้าต้องการที่จะข้าม Webhook, เช่น: #ช่องอื่นๆ",
|
||||
aboutChannelName: "ใส่ชื่อห้องใน {0} ในช่องชื่อห้องถ้าต้องการที่จะข้าม Webhook, เช่น: #ช่องอื่นๆ",
|
||||
aboutKumaURL: "ถ้าคุณไม่ใส่ข้อมูลในช่อง Uptime Kuma URL ค่าเริ่มต้นจะเป็นจะเป็น Uptime Kuma Github",
|
||||
emojiCheatSheet: "ตาราง Emoji : {0}",
|
||||
"rocket.chat": "Rocket.Chat",
|
||||
|
@ -248,7 +248,7 @@ export default {
|
|||
clicksendsms: "ClickSend SMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (รองรับการแจ้งเตือนมากกว่า 50 บริการ)",
|
||||
GoogleChat: "Google Chat (Google Workspace only)",
|
||||
GoogleChat: "Google Chat (สำหรับ Google Workspace เท่านั้น)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
|
@ -257,8 +257,8 @@ export default {
|
|||
"Message Title": "หัวข้อข้อความ",
|
||||
"Notification Sound": "เสียงแจ้งเตือน",
|
||||
"More info on:": "ข้อมูลเพิ่มเติม : {0}",
|
||||
pushoverDesc1: "ลำดับความสำตคญฉุกเฉิน (2) มีการหมดเวลาเริ่มต้น 30 วินาทีระหว่างลองใหม่และจะหมดอายุหลังจาก 1 ชั่วโมง",
|
||||
pushoverDesc2: "ถ้าคุณต้องการจะส่งการแจ้งเตือนไปยังอุปกรณ์อื่น ๆ สามารถกำหนดได้ที่ช่องอุปกรณ์",
|
||||
pushoverDesc1: "ลำดับความสำคัญฉุกเฉิน (2) มีการหมดเวลาเริ่มต้น 30 วินาทีระหว่างการลองใหม่และจะหมดอายุหลังจาก 1 ชั่วโมง",
|
||||
pushoverDesc2: "ถ้าคุณต้องการจะส่งการแจ้งเตือนไปยังอุปกรณ์อื่นๆ สามารถกำหนดได้ที่ช่องอุปกรณ์",
|
||||
"SMS Type": "ประเภท SMS",
|
||||
octopushTypePremium: "พรีเมี่ยม (เร็ว - แนะนำสำหรับการแจ้งเตือน)",
|
||||
octopushTypeLowCost: "ต้นทุนต่ำ (ช้า - บางครั้งจะถูกบล็อกโดยผู้ให้บริการ)",
|
||||
|
@ -274,8 +274,8 @@ export default {
|
|||
"Read more:": "อ่านเพิ่มเติม : {0}",
|
||||
"Status:": "สถานะ : {0}",
|
||||
"Read more": "อ่านเพิ่มเติม",
|
||||
appriseInstalled: "Apprise ถูกติดตั่งแล้ว",
|
||||
appriseNotInstalled: "Apprise ยังไม่ถูกติดตั่ง {0}",
|
||||
appriseInstalled: "Apprise ถูกติดตั้งแล้ว",
|
||||
appriseNotInstalled: "Apprise ยังไม่ถูกติดตั้ง {0}",
|
||||
"Access Token": "กุญแจการเข้าถึง",
|
||||
"Channel access token": "กุญแจการเข้าถึงของช่อง",
|
||||
"Line Developers Console": "Line Developers Console",
|
||||
|
@ -285,11 +285,11 @@ export default {
|
|||
"Messaging API": "Messaging API",
|
||||
wayToGetLineChannelToken: "ขั้นแรกให้เข้า {0} สร้างผู้ให้บริการและช่องทาง (Messaging API) จากนั้นคุณจะได้รับกุญแจการเข้าถึงช่องและไอดีผู้ใช้จากรายการเมนูที่กล่าวถึงข้างต้น",
|
||||
"Icon URL": "Icon URL",
|
||||
aboutIconURL: "คุณสามารถระบุลิงก์ไปยังรูปภาพใน \"URL ไอคอน\" เพื่อแทนที่รูปภาพโปรไฟล์เริ่มต้น จะไม่ถูกใช้หากมีการตั้งค่า Icon Emoji",
|
||||
aboutMattermostChannelName: "คุณลบล้างช่องเริ่มต้นที่ Webhook โพสต์ได้ด้วยการป้อนชื่อช่องลงในช่อง \"ชื่อช่อง\" ต้องเปิดใช้งานในการตั้งค่า Mattermost Webhook เช่น #ช่องอื่นๆ",
|
||||
aboutIconURL: "คุณสามารถระบุลิงก์รูปภาพใน \"URL ไอคอน\" เพื่อแทนที่รูปภาพโปรไฟล์เริ่มต้น จะไม่ถูกใช้หากมีการตั้งค่า Icon Emoji",
|
||||
aboutMattermostChannelName: "คุณลบช่องเริ่มต้นที่ Webhook โพสต์ได้ด้วยการป้อนชื่อช่องลงในช่อง \"ชื่อช่อง\" ต้องเปิดใช้งานในการตั้งค่า Mattermost Webhook เช่น #ช่องอื่นๆ",
|
||||
matrix: "Matrix",
|
||||
promosmsTypeEco: "SMS ECO - ราคาถูก แต่ช้าและมักจะโอเวอร์โหลด จำกัดเฉพาะผู้รับโปแลนด์",
|
||||
promosmsTypeFlash: "SMS FLASH - ข้อความจะแสดงบนอุปกรณ์ของผู้รับโดยอัตโนมัติ จำกัดเฉพาะผู้รับโปแลนด์",
|
||||
promosmsTypeEco: "SMS ECO - ราคาถูก แต่ช้าและมักจะโอเวอร์โหลด จำกัดเฉพาะผู้รับในโปแลนด์",
|
||||
promosmsTypeFlash: "SMS FLASH - ข้อความจะแสดงบนอุปกรณ์ของผู้รับโดยอัตโนมัติ จำกัดเฉพาะผู้รับในโปแลนด์",
|
||||
promosmsTypeFull: "SMS FULL - SMS ระดับพรีเมียม คุณสามารถใช้ชื่อผู้ส่งของคุณได้ (คุณต้องลงทะเบียนชื่อก่อน) เชื่อถือได้สำหรับการแจ้งเตือน",
|
||||
promosmsTypeSpeed: "SMS SPEED - ลำดับความสำคัญสูงสุดในระบบ รวดเร็วและเชื่อถือได้ แต่มีค่าใช้จ่ายสูง (ประมาณสองเท่าของราคาเต็ม SMS)",
|
||||
promosmsPhoneNumber: "หมายเลขโทรศัพท์ (สำหรับผู้รับโปแลนด์ คุณสามารถข้ามรหัสพื้นที่ได้)",
|
||||
|
@ -298,7 +298,7 @@ export default {
|
|||
matrixHomeserverURL: "URL ของโฮมเซิร์ฟเวอร์ (พร้อม http(s):// และพอร์ตเสริม)",
|
||||
"Internal Room Id": "รหัสห้องภายใน",
|
||||
matrixDesc1: "คุณค้นหารหัสห้องภายในได้โดยดูในส่วนขั้นสูงของการตั้งค่าห้องในไคลเอ็นต์ Matrix มันควรจะมีลักษณะเช่น !PMdRCpsIfLwsfjIye6:kiznick.server.",
|
||||
matrixDesc2: "ขอแนะนำเป็นอย่างยิ่งให้คุณสร้างผู้ใช้ใหม่และอย่าใช้โทเค็นการเข้าถึงของผู้ใช้ Matrix ของคุณเอง เนื่องจากจะทำให้สามารถเข้าถึงบัญชีของคุณและห้องทั้งหมดที่คุณเข้าร่วมได้อย่างเต็มที่ ให้สร้างผู้ใช้ใหม่และเชิญเฉพาะห้องที่คุณต้องการรับการแจ้งเตือนแทน คุณสามารถรับโทเค็นเพื่อการเข้าถึงได้โดยเรียกใช้ {0}",
|
||||
matrixDesc2: "ขอแนะนำเป็นอย่างยิ่งให้คุณสร้างผู้ใช้ใหม่และอย่าใช้โทเค็นการเข้าถึงของผู้ใช้ Matrix ของคุณเอง เนื่องจากจะทำให้สามารถเข้าถึงบัญชีของคุณและห้องทั้งหมดที่คุณเข้าร่วม ให้สร้างผู้ใช้ใหม่และเชิญเฉพาะห้องที่คุณต้องการรับการแจ้งเตือนแทน คุณสามารถรับโทเค็นเพื่อการเข้าถึงได้โดยเรียกใช้ {0}",
|
||||
Method: "วิธี",
|
||||
Body: "เนื้อหา",
|
||||
Headers: "ส่วนหัว",
|
||||
|
@ -310,12 +310,12 @@ export default {
|
|||
PasswordsDoNotMatch: "รหัสผ่านไม่ตรงกัน",
|
||||
records: "บันทึก",
|
||||
"One record": "หนึ่งบันทึก",
|
||||
steamApiKeyDescription: "สำหรับการมอนิเตอร์ Steam Game Server คุณต้องมี Steam Web-API key, คุณสามารถรสมัครได้จากที่นี่ : ",
|
||||
steamApiKeyDescription: "สำหรับการมอนิเตอร์ Steam Game Server คุณต้องมี Steam Web-API key, คุณสามารถสมัครได้จากที่นี่ : ",
|
||||
"Current User": "ผู้ใช้ปัจจุบัน",
|
||||
topic: "หัวข้อ",
|
||||
topicExplanation: "MQTT หัวข้อที่จะมอนิเตอร์",
|
||||
topicExplanation: "หัวข้อ MQTT ที่จะมอนิเตอร์",
|
||||
successMessage: "ข้อความที่จะถือว่าประสบความสำเร็จ",
|
||||
successMessageExplanation: "MQTT ข้อความที่จะถือว่าประสบความสำเร็จ",
|
||||
successMessageExplanation: "ข้อความ MQTT ที่จะถือว่าประสบความสำเร็จ",
|
||||
recent: "ล่าสุด",
|
||||
Done: "สำเร็จ",
|
||||
Info: "ข้อมูล",
|
||||
|
@ -354,7 +354,7 @@ export default {
|
|||
Discard: "ทิ้ง",
|
||||
Cancel: "ยกเลิก",
|
||||
"Powered by": "ขับเคลื่อนโดย",
|
||||
shrinkDatabaseDescription: "ทริกเกอร์ฐานข้อมูล VACUUM สำหรับ SQLite หากฐานข้อมูลของคุณถูกสร้างขึ้นหลังจาก 1.10.0 แสดงว่า AUTO_VACUUM เปิดใช้งานอยู่แล้วและไม่จำเป็นต้องดำเนินการนี้",
|
||||
shrinkDatabaseDescription: "ทริกเกอร์ฐานข้อมูล VACUUM สำหรับ SQLite หากฐานข้อมูลของคุณถูกสร้างขึ้นหลังจากเวอร์ชั่น 1.10.0 แสดงว่า AUTO_VACUUM เปิดใช้งานอยู่แล้วและไม่จำเป็นต้องดำเนินการนี้",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
serwersmsAPIUser: "API Username (incl. webapi_ prefix)",
|
||||
serwersmsAPIPassword: "API Password",
|
||||
|
@ -364,14 +364,14 @@ export default {
|
|||
Customize: "ปรับแต่ง",
|
||||
"Custom Footer": "ส่วนท้ายที่กำหนดเอง",
|
||||
"Custom CSS": "CSS ที่กำหนดเอง",
|
||||
smtpDkimSettings: "ตั้งค่า DKIM",
|
||||
smtpDkimSettings: "การตั้งค่า DKIM",
|
||||
smtpDkimDesc: "โปรดดู Nodemailer DKIM {0} สำหรับการใช้งาน",
|
||||
documentation: "เอกสาร",
|
||||
documentation: "คู่มือการใช้งาน",
|
||||
smtpDkimDomain: "ชื่อโดเมน",
|
||||
smtpDkimKeySelector: "Key Selector",
|
||||
smtpDkimPrivateKey: "Private Key",
|
||||
smtpDkimHashAlgo: "อัลกอริทึมแฮช (ไม่บังคับ)",
|
||||
smtpDkimheaderFieldNames: "คีย์ส่วนหัวเพื่อลงชื่อ (ไม่บังคับ)",
|
||||
smtpDkimheaderFieldNames: "คีย์ส่วนหัวสำหรับลงชื่อ (ไม่บังคับ)",
|
||||
smtpDkimskipFields: "Header Keys ไม่ต้องเซ็น (ไม่บังคับ)",
|
||||
gorush: "Gorush",
|
||||
alerta: "Alerta",
|
||||
|
@ -383,11 +383,11 @@ export default {
|
|||
deleteStatusPageMsg: "คุณแน่ใจหรือไม่ว่าต้องการลบหน้าสถานะนี้",
|
||||
Proxies: "พร็อกซี",
|
||||
default: "ค่าเริ่มต้น",
|
||||
enabled: "เปิดใช้งาน",
|
||||
setAsDefault: "ตั่งเป็นค่าเริ่มต้น",
|
||||
enabled: "เปิดใช้งานแล้ว",
|
||||
setAsDefault: "ตั้งเป็นค่าเริ่มต้น",
|
||||
deleteProxyMsg: "คุณแน่ใจหรือไม่ว่าต้องการลบพร็อกซีสำหรับมอนิเตอร์ทั้งหมด?",
|
||||
proxyDescription: "พร็อกซีจะต้องตั้งค่าให้มอนิเตอร์เพื่อให้ใช้งานได้",
|
||||
enableProxyDescription: "พร็อกซีนี้จะไม่ส่งผลต่อมอนิเตอร์จนกว่าจะเปิดใช้งาน คุณสามารถควบคุมการปิดใช้งานพร็อกซีชั่วคราวจากมอนิเตอร์ทั้งหมดได้โดยสถานะการเปิดใช้งาน",
|
||||
proxyDescription: "ต้องตั้งค่ามอนิเตอร์ให้ใช้พร็อกซีเพื่อให้ใช้งานได้",
|
||||
enableProxyDescription: "พร็อกซีนี้จะไม่ส่งผลต่อมอนิเตอร์จนกว่าจะเปิดใช้งาน คุณสามารถควบคุมการปิดใช้งานพร็อกซีชั่วคราวจากมอนิเตอร์ทั้งหมดได้ที่ส่วนสถานะการเปิดใช้งาน",
|
||||
setAsDefaultProxyDescription: "พร็อกซีนี้จะถูกเปิดโดนค่าเริ่มต้นสำหรับมอนิเตอร์ใหม่, คุณสามารถปิดการแจ้งเตือนสำหรับแต่ละมอนิเตอร์ได้",
|
||||
"Certificate Chain": "ห่วงโซ่ใบรับรอง",
|
||||
Valid: "ถูกต้อง",
|
||||
|
@ -413,7 +413,7 @@ export default {
|
|||
"WeCom Bot Key": "WeCom Bot Key",
|
||||
"Setup Proxy": "ติดตั้งพร็อกซี่",
|
||||
"Proxy Protocol": "โปรโตคอลพร็อกซี่",
|
||||
"Proxy Server": "พร็อกซีเซิร์ฟ",
|
||||
"Proxy Server": "เซิร์ฟเวอร์พร็อกซี",
|
||||
"Proxy server has authentication": "พร็อกซีเซิร์ฟเวอร์มีการตรวจสอบสิทธิ์",
|
||||
User: "ผู้ใช้",
|
||||
Installed: "ติดตั้งแล้ว",
|
||||
|
@ -430,29 +430,29 @@ export default {
|
|||
startOrEndWithOnly: "เริ่มหรือจบด้วย {0} เท่านั้น",
|
||||
"No consecutive dashes": "ไม่มีขีดกลางติดต่อกัน",
|
||||
Next: "ต่อไป",
|
||||
"The slug is already taken. Please choose another slug.": "ชื่อนี้ถูกใช้งานไปแล้ว กรุณาใช้ชื่ออื่น",
|
||||
"The slug is already taken. Please choose another slug.": "ชื่อนี้ถูกใช้งานแล้ว กรุณาใช้ชื่ออื่น",
|
||||
"No Proxy": "ไม่มีพร็อกซี่",
|
||||
"HTTP Basic Auth": "HTTP Basic Auth",
|
||||
"New Status Page": "หน้าสถานะใหม่",
|
||||
"Page Not Found": "ไม่พบหน้านี้",
|
||||
"Reverse Proxy": "พร็อกซีย้อนกลับ",
|
||||
Backup: "สำรอง",
|
||||
Backup: "สำรองข้อมูล",
|
||||
About: "เกี่ยวกับ",
|
||||
wayToGetCloudflaredURL: "(ดาวโหลด cloudflared จาก {0})",
|
||||
cloudflareWebsite: "เว็บไซต์ Cloudflare",
|
||||
"Message:": "ข้อความ :",
|
||||
"Don't know how to get the token? Please read the guide:": "ไม่รู้วิธีการรับกุญแจ?, กรุณาอ่านคู่มือ",
|
||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "การเชื่อมต่อปัจุบันอาจขาดหายหากคุณกำลังเชื่อมต่อ Cloudflare Tunnel คุณแน่ใจหรือไม่ที่จะหยุด, พิมรหัสผ่านของคุณเพื่อยืนยัน",
|
||||
"Other Software": "ซอฟต์แวร์อื่น ๆ ",
|
||||
"Other Software": "ซอฟต์แวร์อื่นๆ ",
|
||||
"For example: nginx, Apache and Traefik.": "เช่น: nginx, Apache และ Traefik",
|
||||
"Please read": "กรุณาอ่าน",
|
||||
"Subject:": "เรื่อง :",
|
||||
"Valid To:": "ถูกต้องถึง :",
|
||||
"Valid To:": "ใช้ได้ถึง :",
|
||||
"Days Remaining:": "จำนวนวันที่เหลือ :",
|
||||
"Issuer:": "ผู้ออก :",
|
||||
"Fingerprint:": "ลายนิ้วมือ :",
|
||||
"No status pages": "ไม่มีหน้าสถานะ",
|
||||
"Domain Name Expiry Notification": "แจ้งเตือนการหมดอายุโดเมน",
|
||||
"Domain Name Expiry Notification": "แจ้งเตือนการหมดอายุของโดเมน",
|
||||
Proxy: "Proxy",
|
||||
"Date Created": "วันที่สร้าง",
|
||||
onebotHttpAddress: "ที่อยู่ HTTP OneBot ",
|
||||
|
@ -466,8 +466,8 @@ export default {
|
|||
"Show Powered By": "แสดงข้อความ \"ขับเคลื่อนโดย\"",
|
||||
"Domain Names": "Domain Names",
|
||||
signedInDisp: "เข้าใช้งานในฐานะ {0}",
|
||||
signedInDispDisabled: "ปิดการตรวจสอบสิทธิ์",
|
||||
"Certificate Expiry Notification": "แจ้งเตือนการรับรองหมดอายุ",
|
||||
signedInDispDisabled: "ปิดการยืนยันตัวตน",
|
||||
"Certificate Expiry Notification": "แจ้งเตือนใบรับรองหมดอายุ",
|
||||
"API Username": "API Username",
|
||||
"API Key": "API Key",
|
||||
"Recipient Number": "หมายเลขผู้รับ",
|
||||
|
@ -476,8 +476,8 @@ export default {
|
|||
"Octopush API Version": "Octopush API Version",
|
||||
"Legacy Octopush-DM": "Legacy Octopush-DM",
|
||||
endpoint: "endpoint",
|
||||
octopushAPIKey: "\"API key\" จากข้อมูลรับรอง HTTP API ในแผงควบคุม",
|
||||
octopushLogin: "\"Login\" จากข้อมูลรับรอง HTTP API ในแผงควบคุม",
|
||||
octopushAPIKey: "\"API key\" จากข้อมูลยืนยันตัวตน HTTP API ในแผงควบคุม",
|
||||
octopushLogin: "\"Login\" จากข้อมูลยืนยันตัวตน HTTP API ในแผงควบคุม",
|
||||
promosmsLogin: "API Login Name",
|
||||
promosmsPassword: "API Password",
|
||||
"pushoversounds pushover": "Pushover (default)",
|
||||
|
@ -507,16 +507,16 @@ export default {
|
|||
pushyToken: "Device token",
|
||||
"Show update if available": "แสดงการอัปเดตถ้ามี",
|
||||
"Also check beta release": "ตรวจสอบรุ่นเบต้า",
|
||||
"Using a Reverse Proxy?": "ใช้ Reverse Proxy?",
|
||||
"Using a Reverse Proxy?": "ใช้ Reverse Proxy อยู่ใช่มั้ย?",
|
||||
"Check how to config it for WebSocket": "ตรวจสอบวิธีการตั้งค่าสำหรับ WebSocket",
|
||||
"Steam Game Server": "Steam Game Server",
|
||||
"Most likely causes:": "สาเหตุที่เป็นไปได้มากที่สุด :",
|
||||
"The resource is no longer available.": "ทรัพยากรไม่สามารถใช้งานได้อีกต่อไป",
|
||||
"There might be a typing error in the address.": "อาจมีข้อผิดพลาดในการพิมพ์ที่อยู่",
|
||||
"What you can try:": "สิ่งที่คุณสามารถลอง :",
|
||||
"What you can try:": "สิ่งที่คุณสามารถลองทำ :",
|
||||
"Retype the address.": "พิมพ์ที่อยู่อีกครั้ง",
|
||||
"Go back to the previous page.": "กลับไปที่หน้าก่อนหน้า",
|
||||
"Coming Soon": "เร็ว ๆ นี้",
|
||||
"Go back to the previous page.": "กลับไปหน้าที่แล้ว",
|
||||
"Coming Soon": "เร็วๆ นี้",
|
||||
wayToGetClickSendSMSToken: "คุณสามารถรับ API Username และ API Key ได้จาก {0}",
|
||||
wayToGetLineNotifyToken: "คุณสามารถรับ access token ได้จาก {0}",
|
||||
resendEveryXTimes: "ส่งซ้ำทุก {0} ครั้ง",
|
||||
|
@ -525,7 +525,7 @@ export default {
|
|||
"Resend Notification if Down X times consequently": "ส่งการแจ้งเตือนซ้ำถ้าออฟไลน์ครบ X ครั้ง",
|
||||
error: "เกิดข้อผิดพลาด",
|
||||
critical: "วิกฤต",
|
||||
wayToGetPagerDutyKey: "คุณสามารถรับได้โดยการไปที่ Service -> Service Directory -> (Select a service) -> Integrations -> Add integration, และค้นหา \"Events API V2\", สำหรับข้อมูลเพิ่มเติม {0}",
|
||||
wayToGetPagerDutyKey: "คุณสามารถรับคีย์ได้โดยการไปที่ Service -> Service Directory -> (Select a service) -> Integrations -> Add integration, และค้นหา \"Events API V2\", สำหรับข้อมูลเพิ่มเติม {0}",
|
||||
"Integration Key": "Integration Key",
|
||||
"Integration URL": "Integration URL",
|
||||
"Auto resolve or acknowledged": "แก้ไขอัตโนมัติหรือยอมรับ",
|
||||
|
@ -539,16 +539,16 @@ export default {
|
|||
"Trust Proxy": "Trust Proxy",
|
||||
HomeAssistant: "Home Assistant",
|
||||
RadiusSecret: "Radius Secret",
|
||||
RadiusSecretDescription: "แบ่งปันข้อมูลลับระหว่างผู้ใช้งานและเซิร์ฟเวอร์",
|
||||
RadiusSecretDescription: "แบ่งปันคีย์ลับระหว่างผู้ใช้งานและเซิร์ฟเวอร์",
|
||||
RadiusCalledStationId: "Called Station Id",
|
||||
RadiusCalledStationIdDescription: "Identifier of the called device",
|
||||
RadiusCallingStationId: "Calling Station Id",
|
||||
RadiusCallingStationIdDescription: "Identifier of the calling device",
|
||||
"Connection String": "Connection String",
|
||||
Query: "Query",
|
||||
settingsCertificateExpiry: "วันหมดอายุใบรับรอง TLS",
|
||||
certificationExpiryDescription: "การตรวจสอบ HTTPS แจ้งเตือนใบอนุญาติ TLS จะหมดอายุใน:",
|
||||
"Setup Docker Host": "Setup Docker Host",
|
||||
settingsCertificateExpiry: "วันหมดอายุของใบรับรอง TLS",
|
||||
certificationExpiryDescription: "การตรวจสอบ HTTPS จะแจ้งเตือนถ้าใบอนุญาติ TLS จะหมดอายุใน:",
|
||||
"Setup Docker Host": "ติดตั้ง Docker Host",
|
||||
"Connection Type": "ประเภทการเชื่อมต่อ",
|
||||
"Docker Daemon": "Docker Daemon",
|
||||
deleteDockerHostMsg: "คุณแน่ใจหรือไม่ที่จะลบ Docker host นี้สำหรับการมอนิเตอร์ทั้งหมด?",
|
||||
|
@ -565,14 +565,14 @@ export default {
|
|||
trustProxyDescription: "เชื่อ Header 'X-Forwarded-*' ถ้าคุณต้องการไอพีที่ถูกต้องและ Uptime Kuma อยู่ข้างหลัง Nginx หรือ Apache, คุณควรเปิดใช้งาน",
|
||||
Examples: "ตัวอย่าง",
|
||||
"Home Assistant URL": "Home Assistant URL",
|
||||
"Long-Lived Access Token": "Access Token แบบมีอายุ",
|
||||
"Long-Lived Access Token": "Access Token แบบมีอายุนาน",
|
||||
"Long-Lived Access Token can be created by clicking on your profile name (bottom left) and scrolling to the bottom then click Create Token. ": "Access Token แบบมีอายุนานสามารถสร้างได้โดยคลิกชื่อบนโปรไฟล์ (ล่างซ้าย) และเลื่อนไปข้างล่างจากนั้นคลิก \"Create Token\"",
|
||||
"Notification Service": "บริการแจ้งเตือน",
|
||||
"default: notify all devices": "ค่าเริ่มต้น: แจ้งเตือนทุกอุปกรณ์",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "รายการแจ้งเตือนสามารถหาได้ใน Home Assistant ในเมนู \"Developer Tools > Services\" ค้นหา \"notification\" เพื่อหาชื่ออุปกรณ์หรือชื่อโทรศัพท์",
|
||||
"A list of Notification Services can be found in Home Assistant under \"Developer Tools > Services\" search for \"notification\" to find your device/phone name.": "รายการแจ้งเตือนสามารถหาได้ใน Home Assistant ในเมนู \"Developer Tools > Services\" แล้วค้นหา \"notification\" เพื่อหาชื่ออุปกรณ์หรือชื่อโทรศัพท์",
|
||||
"Automations can optionally be triggered in Home Assistant:": "สามารถเลือกสั่งงานระบบอัตโนมัติได้ใน Home Assistant:",
|
||||
"Trigger type:": "ชนิดสิ่งกระตุ้น:",
|
||||
"Event type:": "ชนิดกิจกรรม:",
|
||||
"Event type:": "ชนิดเหตการณ์:",
|
||||
"Event data:": "ข้อมูลกิจกรรม:",
|
||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "จากนั้นเลือกการกระทำ, ตัวอย่าง เช่น เปลี่ยนเป็นไฟสีแดง",
|
||||
"Frontend Version": "เวอร์ชั่น Frontend",
|
||||
|
|
|
@ -582,4 +582,97 @@ export default {
|
|||
goAlert: "GoAlert",
|
||||
backupOutdatedWarning: "Kullanımdan Kaldırıldı: Birçok özellik eklendiğinden ve bu yedekleme özelliği biraz bakımsız olduğundan, tam bir yedekleme oluşturamaz veya geri yükleyemez.",
|
||||
backupRecommend: "Lütfen bunun yerine birimi veya veri klasörünü (./data/) doğrudan yedekleyin.",
|
||||
enableGRPCTls: "TLS bağlantısıyla gRPC isteği göndermeye izin ver",
|
||||
grpcMethodDescription: "Yöntem adı, sayHello, check, vb. gibi cammelCase biçimine dönüştürülür.",
|
||||
Maintenance: "Bakım",
|
||||
statusMaintenance: "Bakım",
|
||||
"Schedule maintenance": "Bakım Planla",
|
||||
"Affected Monitors": "Etkilenen Monitörler",
|
||||
"Pick Affected Monitors...": "Etkilenen Monitörleri Seçin...",
|
||||
"Start of maintenance": "Bakım başlangıcı",
|
||||
"All Status Pages": "Tüm Durum Sayfaları",
|
||||
"Select status pages...": "Durum sayfalarını seçin...",
|
||||
recurringIntervalMessage: "Her gün bir kez çalıştırın | {0} günde bir çalıştırın",
|
||||
affectedMonitorsDescription: "Geçerli bakımdan etkilenen monitörleri seçin",
|
||||
affectedStatusPages: "Bu bakım mesajını seçili durum sayfalarında göster",
|
||||
atLeastOneMonitor: "Etkilenen en az bir monitör seçin",
|
||||
deleteMaintenanceMsg: "Bu bakımı silmek istediğinizden emin misiniz?",
|
||||
ZohoCliq: "ZohoCliq",
|
||||
webhookAdditionalHeadersTitle: "Ek Başlıklar",
|
||||
webhookAdditionalHeadersDesc: "Webhook ile gönderilen ek başlıkları ayarlar.",
|
||||
wayToGetZohoCliqURL: "Bir webhook URL'sinin nasıl oluşturulacağını öğrenebilirsiniz {0}.",
|
||||
Kook: "Kook",
|
||||
wayToGetKookBotToken: "Uygulama oluşturun ve {0} adresinde bot tokenı alın",
|
||||
wayToGetKookGuildID: "Kook ayarında \"Geliştirici Modu\"nu açın ve kimliğini almak için guild'e sağ tıklayın",
|
||||
"Guild ID": "Guild ID",
|
||||
smseagle: "SMSEagle",
|
||||
smseagleTo: "Telefon numara(ları)",
|
||||
smseagleGroup: "Telefon defteri grubu ad(lar)ı",
|
||||
smseagleContact: "Telefon rehberi kişi ad(lar)ı",
|
||||
smseagleRecipientType: "Alıcı Türü",
|
||||
smseagleRecipient: "Alıcı(lar) (birden çok olanlar virgülle ayrılmalıdır)",
|
||||
smseagleToken: "API Erişim Tokenı",
|
||||
smseagleUrl: "SMSEagle cihaz URL\"niz",
|
||||
smseagleEncoding: "Unicode olarak gönder",
|
||||
smseaglePriority: "Mesaj önceliği (0-9, varsayılan = 0)",
|
||||
Optional: "İsteğe bağlı",
|
||||
squadcast: "Squadcast",
|
||||
SendKey: "SendKey",
|
||||
"SMSManager API Docs": "SMSManager API Dökümanları ",
|
||||
"Gateway Type": "Ağ Geçidi Türü",
|
||||
SMSManager: "SMSManager",
|
||||
"You can divide numbers with": "Sayıları aşağıdakilerle bölebilirsiniz",
|
||||
or: "veya",
|
||||
recurringInterval: "Sıklık",
|
||||
Recurring: "Yineleme",
|
||||
strategyManual: "Manuel olarak Aktif/Pasif",
|
||||
warningTimezone: "Sunucunun kullandığı saat dilimi",
|
||||
weekdayShortMon: "Pzt",
|
||||
weekdayShortTue: "Sal",
|
||||
weekdayShortWed: "Çar",
|
||||
weekdayShortThu: "Per",
|
||||
weekdayShortFri: "Cum",
|
||||
weekdayShortSat: "Cmt",
|
||||
weekdayShortSun: "Paz",
|
||||
dayOfWeek: "Haftanın Günleri",
|
||||
dayOfMonth: "Ayın Günleri",
|
||||
lastDay: "Son Gün",
|
||||
lastDay1: "Ayın Son Günü",
|
||||
lastDay2: "Ayın 2. Son Günü",
|
||||
lastDay3: "Ayın 3. Son Günü",
|
||||
lastDay4: "Ayın 4. Son Günü",
|
||||
"No Maintenance": "Bakım Yok",
|
||||
pauseMaintenanceMsg: "Duraklatmak istediğinizden emin misiniz?",
|
||||
"maintenanceStatus-under-maintenance": "Bakımda",
|
||||
"maintenanceStatus-inactive": "Etkin Değil",
|
||||
"maintenanceStatus-scheduled": "Planlanmış",
|
||||
"maintenanceStatus-ended": "Bitti",
|
||||
"maintenanceStatus-unknown": "Bilinmiyor",
|
||||
"Display Timezone": "Saat dilimini göster",
|
||||
"Server Timezone": "Sunucu Saat Dilimi",
|
||||
statusPageMaintenanceEndDate: "Bitiş Zamanı",
|
||||
IconUrl: "Icon URL",
|
||||
"Enable DNS Cache": "DNS Önbelleğini Etkinleştir",
|
||||
Enable: "Etkin",
|
||||
Disable: "Devre Dışı",
|
||||
dnsCacheDescription: "Bazı IPv6 ortamlarında çalışmıyor olabilir, herhangi bir sorunla karşılaşırsanız devre dışı bırakın.",
|
||||
"Single Maintenance Window": "Tek Seferlik Bakım",
|
||||
"Maintenance Time Window of a Day": "Bür Günlük Bakım",
|
||||
"Effective Date Range": "Bakim Tarih Aralığı",
|
||||
"Schedule Maintenance": "Bakım Planla",
|
||||
"Date and Time": "Tarih ve Saat",
|
||||
"DateTime Range": "Tarih ve Saat Aralığı",
|
||||
Strategy: "Strateji",
|
||||
"Free Mobile User Identifier": "Ücretsiz Mobil Kullanıcı ID",
|
||||
"Free Mobile API Key": "Ücretsiz Mobil API Anahtarı",
|
||||
"Enable TLS": "TLS'yi Etkinleştir",
|
||||
"Proto Service Name": "Proto Service İsmi",
|
||||
"Proto Method": "Proto Method",
|
||||
"Proto Content": "Proto İçeriği",
|
||||
Economy: "Ekonomik",
|
||||
Lowcost: "Düşük maliyetli",
|
||||
high: "Yüksek",
|
||||
"General Monitor Type": "Genel Monitör Tipi",
|
||||
"Passive Monitor Type": "Pasif Monitör Tipi",
|
||||
"Specific Monitor Type": "Özel Monitör Tipi",
|
||||
};
|
||||
|
|
|
@ -2,17 +2,35 @@ export default {
|
|||
languageName: "简体中文",
|
||||
checkEverySecond: "检测频率 {0} 秒",
|
||||
retryCheckEverySecond: "重试间隔 {0} 秒",
|
||||
resendEveryXTimes: "每 {0} 次失败则重复发送一次",
|
||||
resendDisabled: "为 0 时禁用重复发送",
|
||||
retriesDescription: "服务被标记为故障并发送通知之前的最大重试次数",
|
||||
ignoreTLSError: "忽略 HTTPS 站点的 TLS/SSL 错误",
|
||||
upsideDownModeDescription: "反转状态监控,如果服务可访问,则认为是故障。",
|
||||
maxRedirectDescription: "允许的最大重定向次数。设置为 0 禁用重定向。",
|
||||
enableGRPCTls: "允许通过 TLS 连接发送 gRPC 请求",
|
||||
grpcMethodDescription: "方法名会转换为小驼峰格式,例如 sayHello、check 等等",
|
||||
acceptedStatusCodesDescription: "选择被视为成功响应的状态码。",
|
||||
Maintenance: "维护",
|
||||
statusMaintenance: "维护",
|
||||
"Schedule maintenance": "计划维护",
|
||||
"Affected Monitors": "受影响的监控项",
|
||||
"Pick Affected Monitors...": "选择受影响的监控项…",
|
||||
"Start of maintenance": "维护开始",
|
||||
"All Status Pages": "所有状态页面",
|
||||
"Select status pages...": "选择状态页面…",
|
||||
recurringIntervalMessage: "每天一次 | 每 {0} 天一次",
|
||||
affectedMonitorsDescription: "选择受当前维护影响的监控项",
|
||||
affectedStatusPages: "在所选状态页面上显示此维护消息",
|
||||
atLeastOneMonitor: "至少选择一个受影响的监控项",
|
||||
passwordNotMatchMsg: "两次输入的密码不一致。",
|
||||
notificationDescription: "通知必须被分配给监控项才能正常工作。",
|
||||
keywordDescription: "在纯 HTML 或 JSON 响应中搜索关键字,区分大小写。",
|
||||
pauseDashboardHome: "暂停",
|
||||
deleteMonitorMsg: "确定要删除此监控项吗?",
|
||||
deleteMaintenanceMsg: "确定要删除此维护吗?",
|
||||
deleteNotificationMsg: "确定要为所有监控项删除此通知吗?",
|
||||
dnsPortDescription: "DNS 服务器端口,默认为 53,您可以在任何时候更改此端口.",
|
||||
resolverserverDescription: "默认服务器是 Cloudflare。您随时可以修改解析服务器。",
|
||||
rrtypeDescription: "选择要监控的资源记录类型",
|
||||
pauseMonitorMsg: "确定要暂停吗?",
|
||||
|
@ -34,7 +52,6 @@ export default {
|
|||
Theme: "主题",
|
||||
General: "常规",
|
||||
"Primary Base URL": "站点主 URL",
|
||||
About: "关于",
|
||||
Version: "版本",
|
||||
"Check Update On GitHub": "检查 GitHub 上的更新",
|
||||
List: "列表",
|
||||
|
@ -72,6 +89,7 @@ export default {
|
|||
"Heartbeat Interval": "心跳间隔",
|
||||
Retries: "重试次数",
|
||||
"Heartbeat Retry Interval": "心跳重试间隔",
|
||||
"Resend Notification if Down X times consequently": "连续失败时重复发送通知的间隔次数",
|
||||
Advanced: "高级",
|
||||
"Upside Down Mode": "反转监控",
|
||||
"Max. Redirects": "最大重定向次数",
|
||||
|
@ -125,7 +143,6 @@ export default {
|
|||
"Last Result": "上次结果",
|
||||
"Create your admin account": "创建管理员账户",
|
||||
"Repeat Password": "重复密码",
|
||||
Backup: "备份",
|
||||
"Import Backup": "导入备份",
|
||||
"Export Backup": "导出备份",
|
||||
Export: "导出",
|
||||
|
@ -160,7 +177,7 @@ export default {
|
|||
Token: "令牌",
|
||||
"Show URI": "显示 URI",
|
||||
Tags: "标签",
|
||||
"Add New below or Select...": "在下面添加或选择...",
|
||||
"Add New below or Select...": "在下面添加或选择…",
|
||||
"Tag with this name already exist.": "相同名称的标签已存在。",
|
||||
"Tag with this value already exist.": "相同内容的标签已存在。",
|
||||
color: "颜色",
|
||||
|
@ -173,7 +190,7 @@ export default {
|
|||
Indigo: "靛蓝",
|
||||
Purple: "紫色",
|
||||
Pink: "粉色",
|
||||
"Search...": "搜索...",
|
||||
"Search...": "搜索…",
|
||||
"Avg. Ping": "平均 Ping",
|
||||
"Avg. Response": "平均响应",
|
||||
"Entry Page": "入口页面",
|
||||
|
@ -192,6 +209,7 @@ export default {
|
|||
here: "这里",
|
||||
Required: "必填",
|
||||
telegram: "Telegram",
|
||||
"ZohoCliq": "ZohoCliq",
|
||||
"Bot Token": "Bot Token",
|
||||
wayToGetTelegramToken: "您可以从 {0} 获取 Token。",
|
||||
"Chat ID": "Chat ID",
|
||||
|
@ -204,6 +222,8 @@ export default {
|
|||
"Content Type": "Content Type",
|
||||
webhookJsonDesc: "{0} 适合现代的 HTTP 服务器,例如 Express.js",
|
||||
webhookFormDataDesc: "{multipart} 适合 PHP,其中 JSON 需要使用 {decodeFunction} 解码",
|
||||
webhookAdditionalHeadersTitle: "额外 Header",
|
||||
webhookAdditionalHeadersDesc: "设置通过此 Webhook 发送的额外 Header。",
|
||||
smtp: "电子邮件(SMTP)",
|
||||
secureOptionNone: "无 / STARTTLS(常用端口 25、587)",
|
||||
secureOptionTLS: "TLS(常用端口 465)",
|
||||
|
@ -221,7 +241,8 @@ export default {
|
|||
"Hello @everyone is...": "{'@'}everyone,……",
|
||||
teams: "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "您可以在 {0} 了解如何获取 Webhook URL。",
|
||||
wayToGetTeamsURL: "您可以在{0}了解如何获取 Webhook URL。",
|
||||
wayToGetZohoCliqURL: "您可以在{0}了解如何创建 Webhook URL。",
|
||||
signal: "Signal",
|
||||
Number: "号码",
|
||||
Recipients: "收件人",
|
||||
|
@ -243,6 +264,7 @@ export default {
|
|||
"rocket.chat": "Rocket.Chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
PushByTechulus: "Push by Techulus",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
clicksendsms: "ClickSend SMS",
|
||||
|
@ -250,6 +272,11 @@ export default {
|
|||
apprise: "Apprise (支持 50+ 种通知服务)",
|
||||
GoogleChat: "Google Chat(仅 Google Workspace)",
|
||||
pushbullet: "Pushbullet",
|
||||
AliyunSMS: "阿里云短信服务",
|
||||
Kook: "Kook",
|
||||
wayToGetKookBotToken: "在 {0} 创建应用并获取机器人 Token",
|
||||
wayToGetKookGuildID: "在 Kook 设置中打开“开发者模式”,然后右键点击频道可获取其 ID",
|
||||
"Guild ID": "频道 ID",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "User Key",
|
||||
|
@ -294,6 +321,7 @@ export default {
|
|||
promosmsTypeSpeed: "SMS SPEED - 最高优先级。非常快速可靠,但更贵(大约两倍 SMS FULL 的价格)。",
|
||||
promosmsPhoneNumber: "电话号码(波兰地区收信人可以不填区号)",
|
||||
promosmsSMSSender: "短信发信人名称:已注册的名称或以下默认值之一:InfoSMS、SMS Info、MaxSMS、INFO、SMS",
|
||||
Feishu: "飞书",
|
||||
"Feishu WebHookUrl": "飞书 WebHook URL",
|
||||
matrixHomeserverURL: "服务器 URL(包含 http(s):// 和可选的端口号)",
|
||||
"Internal Room Id": "内部房间 ID",
|
||||
|
@ -312,14 +340,18 @@ export default {
|
|||
"One record": "一条记录",
|
||||
steamApiKeyDescription: "要监控 Steam 游戏服务器,您需要 Steam Web-API 密钥。您可以在这里注册您的 API 密钥: ",
|
||||
"Current User": "当前用户",
|
||||
topic: "Topic",
|
||||
topicExplanation: "要监控的 MQTT Topic",
|
||||
successMessage: "成功消息",
|
||||
successMessageExplanation: "视为成功的 MQTT 消息",
|
||||
recent: "最近",
|
||||
Done: "完成",
|
||||
Info: "信息",
|
||||
Security: "安全性",
|
||||
"Steam API Key": "Steam API 密钥",
|
||||
"Shrink Database": "压缩数据库",
|
||||
"Pick a RR-Type...": "选择资源记录类型...",
|
||||
"Pick Accepted Status Codes...": "选择有效的状态码...",
|
||||
"Pick a RR-Type...": "选择资源记录类型…",
|
||||
"Pick Accepted Status Codes...": "选择有效的状态码…",
|
||||
Default: "默认",
|
||||
"HTTP Options": "HTTP 选项",
|
||||
"Create Incident": "创建事件",
|
||||
|
@ -329,6 +361,8 @@ export default {
|
|||
info: "信息",
|
||||
warning: "警告",
|
||||
danger: "危险",
|
||||
error: "错误",
|
||||
critical: "关键",
|
||||
primary: "主要",
|
||||
light: "明亮",
|
||||
dark: "黑暗",
|
||||
|
@ -356,7 +390,20 @@ export default {
|
|||
serwersmsAPIPassword: "API 密码",
|
||||
serwersmsPhoneNumber: "电话号码",
|
||||
serwersmsSenderName: "SMS 发信人名称(需要在客户中心注册)",
|
||||
smseagle: "SMSEagle",
|
||||
smseagleTo: "电话号码",
|
||||
smseagleGroup: "通讯录群组名",
|
||||
smseagleContact: "通讯录联系人",
|
||||
smseagleRecipientType: "收信人类型",
|
||||
smseagleRecipient: "收信人(多个需用半角逗号分隔)",
|
||||
smseagleToken: "API Access token",
|
||||
smseagleUrl: "您的 SMSEagle 设备 URL",
|
||||
smseagleEncoding: "以 Unicode 发送",
|
||||
smseaglePriority: "消息优先级(0-9,默认为 0)",
|
||||
stackfield: "Stackfield",
|
||||
Customize: "自定义",
|
||||
"Custom Footer": "自定义底部",
|
||||
"Custom CSS": "自定义 CSS",
|
||||
smtpDkimSettings: "DKIM 设置",
|
||||
smtpDkimDesc: "请访问 Nodemailer DKIM {0} 了解配置方法。",
|
||||
documentation: "文档",
|
||||
|
@ -366,16 +413,13 @@ export default {
|
|||
smtpDkimHashAlgo: "哈希算法(可选)",
|
||||
smtpDkimheaderFieldNames: "包含在哈希计算对象内的 Header 列表(可选)",
|
||||
smtpDkimskipFields: "不包含在哈希计算对象内的 Header 列表(可选)",
|
||||
Feishu: "飞书",
|
||||
AliyunSMS: "阿里云短信服务",
|
||||
"Sms template must contain parameters: ": "短信模板必须包含以下变量:",
|
||||
DingDing: "钉钉自定义机器人",
|
||||
WebHookUrl: "钉钉自定义机器人 Webhook 地址",
|
||||
SecretKey: "钉钉自定义机器人加签密钥",
|
||||
"For safety, must use secret key": "出于安全考虑,必须使用加签密钥",
|
||||
WeCom: "企业微信群机器人",
|
||||
"WeCom Bot Key": "企业微信群机器人 Key",
|
||||
PushByTechulus: "Push by Techulus",
|
||||
wayToGetPagerDutyKey: "您可以在 Service -> Service Directory -> (选择一个 Service) -> Integrations -> Add integration 页面中搜索“Events API V2”以获取此 Integration Key,更多信息请看{0}",
|
||||
"Integration Key": "Integration Key",
|
||||
"Integration URL": "Integration URL",
|
||||
"Auto resolve or acknowledged": "自动标记为已解决或已读",
|
||||
"do nothing": "不做任何操作",
|
||||
"auto acknowledged": "自动标记为已读",
|
||||
"auto resolve": "自动标记为已解决",
|
||||
gorush: "Gorush",
|
||||
alerta: "Alerta",
|
||||
alertaApiEndpoint: "API 接入点",
|
||||
|
@ -392,9 +436,6 @@ export default {
|
|||
proxyDescription: "代理必须配置到至少一个监控项后才会工作。",
|
||||
enableProxyDescription: "此代理必须启用才能对监控项的网络请求起作用。您可以通过修改激活状态,临时在所有监控项中禁用此代理。",
|
||||
setAsDefaultProxyDescription: "此代理会对新创建的监控项默认激活,您仍可以在监控项配置中单独禁用此代理。",
|
||||
"Proxy Protocol": "代理协议",
|
||||
"Proxy Server": "代理服务器",
|
||||
"Server Address": "服务器地址",
|
||||
"Certificate Chain": "证书链",
|
||||
Valid: "有效",
|
||||
Invalid: "无效",
|
||||
|
@ -403,9 +444,14 @@ export default {
|
|||
PhoneNumbers: "PhoneNumbers",
|
||||
TemplateCode: "TemplateCode",
|
||||
SignName: "SignName",
|
||||
"Sms template must contain parameters: ": "短信模板必须包含以下变量:",
|
||||
"Bark Endpoint": "Bark 接入点",
|
||||
"Bark Group": "Bark 群组",
|
||||
"Bark Sound": "Bark 铃声",
|
||||
DingDing: "钉钉自定义机器人",
|
||||
WebHookUrl: "钉钉自定义机器人 Webhook 地址",
|
||||
SecretKey: "钉钉自定义机器人加签密钥",
|
||||
"For safety, must use secret key": "出于安全考虑,必须使用加签密钥",
|
||||
"Device Token": "Apple Device Token",
|
||||
Platform: "平台",
|
||||
iOS: "iOS",
|
||||
|
@ -414,21 +460,18 @@ export default {
|
|||
High: "高",
|
||||
Retry: "重试次数",
|
||||
Topic: "Gorush Topic",
|
||||
WeCom: "企业微信群机器人",
|
||||
"WeCom Bot Key": "企业微信群机器人 Key",
|
||||
"Setup Proxy": "设置代理",
|
||||
"Proxy Protocol": "代理协议",
|
||||
"Proxy Server": "代理服务器",
|
||||
"Server Address": "服务器地址",
|
||||
"Proxy server has authentication": "代理服务器启用了身份验证功能",
|
||||
User: "用户名",
|
||||
Installed: "已安装",
|
||||
"Not installed": "未安装",
|
||||
Running: "运行中",
|
||||
"Not running": "未运行",
|
||||
"Message:": "信息:",
|
||||
wayToGetCloudflaredURL: "(可从 {0} 下载 cloudflared)",
|
||||
cloudflareWebsite: "Cloudflare 网站",
|
||||
"Don't know how to get the token? Please read the guide:": "不知道如何获取 Token?请阅读指南:",
|
||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "如果您正在通过 Cloudflare Tunnel 访问网站,则停止可能会导致当前连接断开。您确定要停止吗?请输入密码以确认。",
|
||||
"Other Software": "其他软件",
|
||||
"For example: nginx, Apache and Traefik.": "例如:nginx、Apache 和 Traefik。",
|
||||
"Please read": "请阅读",
|
||||
"Remove Token": "移除 Token",
|
||||
Start: "启动",
|
||||
Stop: "停止",
|
||||
|
@ -446,6 +489,18 @@ export default {
|
|||
"New Status Page": "新的状态页",
|
||||
"Page Not Found": "未找到该页面",
|
||||
"Reverse Proxy": "反向代理",
|
||||
Backup: "备份",
|
||||
About: "关于",
|
||||
wayToGetCloudflaredURL: "(可从 {0} 下载 cloudflared)",
|
||||
cloudflareWebsite: "Cloudflare 网站",
|
||||
"Message:": "信息:",
|
||||
"Don't know how to get the token? Please read the guide:": "不知道如何获取 Token?请阅读指南:",
|
||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "如果您正在通过 Cloudflare Tunnel 访问网站,则停止可能会导致当前连接断开。您确定要停止吗?请输入密码以确认。",
|
||||
"HTTP Headers": "HTTP 头",
|
||||
"Trust Proxy": "可信的代理类字段",
|
||||
"Other Software": "其他软件",
|
||||
"For example: nginx, Apache and Traefik.": "例如:nginx、Apache 和 Traefik。",
|
||||
"Please read": "请阅读",
|
||||
"Subject:": "颁发给:",
|
||||
"Valid To:": "有效期至:",
|
||||
"Days Remaining:": "剩余有效天数:",
|
||||
|
@ -455,26 +510,28 @@ export default {
|
|||
"Domain Name Expiry Notification": "域名到期时通知",
|
||||
Proxy: "代理",
|
||||
"Date Created": "创建于",
|
||||
HomeAssistant: "Home Assistant",
|
||||
onebotHttpAddress: "OneBot HTTP 地址",
|
||||
onebotMessageType: "OneBot 消息类型",
|
||||
onebotGroupMessage: "群聊",
|
||||
onebotPrivateMessage: "私聊",
|
||||
onebotUserOrGroupId: "群组/用户ID",
|
||||
onebotUserOrGroupId: "群组/用户 ID",
|
||||
onebotSafetyTips: "出于安全原因,请务必设置 AccessToken",
|
||||
topic: "Topic",
|
||||
topicExplanation: "MQTT 传递给监控的 Topic",
|
||||
successMessage: "成功时消息",
|
||||
successMessageExplanation: "MQTT 成功时所传递的消息",
|
||||
Customize: "自定义",
|
||||
"Custom Footer": "自定义底部",
|
||||
"Custom CSS": "自定义 CSS",
|
||||
"PushDeer Key": "PushDeer Key",
|
||||
"Footer Text": "底部自定义文本",
|
||||
"Show Powered By": "显示 Powered By",
|
||||
"Domain Names": "域名",
|
||||
signedInDisp: "当前用户: {0}",
|
||||
signedInDispDisabled: "已禁用身份验证",
|
||||
RadiusSecret: "Radius 共享机密",
|
||||
RadiusSecretDescription: "客户端和服务器之间共享的密钥",
|
||||
RadiusCalledStationId: "NAS 网络访问服务器号码(Called Station Id)",
|
||||
RadiusCalledStationIdDescription: "所访问的服务器的标识",
|
||||
RadiusCallingStationId: "呼叫方号码(Calling Station Id)",
|
||||
RadiusCallingStationIdDescription: "发出请求的设备的标识",
|
||||
"Certificate Expiry Notification": "证书到期时通知",
|
||||
"API Username": "API 凭证 Username",
|
||||
"API Key": "API 凭证 Key",
|
||||
"API Username": "API Username",
|
||||
"API Key": "API Key",
|
||||
"Recipient Number": "收件人手机号码",
|
||||
"From Name/Number": "发件人名称/手机号码",
|
||||
"Leave blank to use a shared sender number.": "留空以使用平台共享的发件人手机号码",
|
||||
|
@ -522,38 +579,11 @@ export default {
|
|||
"Retype the address.": "重新输入地址;",
|
||||
"Go back to the previous page.": "返回到上一页面。",
|
||||
"Coming Soon": "即将推出",
|
||||
wayToGetClickSendSMSToken: "您可以从 {0} 获取 API 凭证 Username 和 凭证 Key。",
|
||||
signedInDisp: "当前用户: {0}",
|
||||
signedInDispDisabled: "已禁用身份验证",
|
||||
dnsPortDescription: "DNS 服务器端口,默认为 53,你可以在任何时候更改此端口.",
|
||||
error: "错误",
|
||||
critical: "关键",
|
||||
wayToGetPagerDutyKey: "你可以在 Service -> Service Directory -> (选择一个 Service) -> Integrations -> Add integration 页面中搜索 \"Events API V2\" 以获取此 Integration Key,更多信息请参见 {0}",
|
||||
"Integration Key": "Integration Key",
|
||||
"Integration URL": "Integration URL",
|
||||
"Auto resolve or acknowledged": "自动标记为已解决或已读",
|
||||
"do nothing": "不做任何操作",
|
||||
"auto acknowledged": "自动标记为已读",
|
||||
"auto resolve": "自动标记为已解决",
|
||||
wayToGetClickSendSMSToken: "您可以在{0}获取 API Username 和 API Key。",
|
||||
"Connection String": "连接字符串",
|
||||
Query: "查询语句",
|
||||
settingsCertificateExpiry: "TLS 证书过期通知",
|
||||
certificationExpiryDescription: "HTTPS 监控项发现被监控目标的 TLS 证书剩余有效期少于以下天数时将发出通知:",
|
||||
"ntfy Topic": "ntfy 主题",
|
||||
Domain: "域名",
|
||||
Workstation: "工作站",
|
||||
resendEveryXTimes: "每 {0} 次失败则重复发送一次",
|
||||
resendDisabled: "为 0 时禁用重复发送",
|
||||
"Resend Notification if Down X times consequently": "连续失败时重复发送通知的间隔次数",
|
||||
"HTTP Headers": "HTTP 头",
|
||||
"Trust Proxy": "可信的代理类字段",
|
||||
HomeAssistant: "Home Assistant",
|
||||
RadiusSecret: "Radius 共享机密",
|
||||
RadiusSecretDescription: "客户端和服务器之间共享的密钥",
|
||||
RadiusCalledStationId: "NAS 网络访问服务器号码(Called Station Id)",
|
||||
RadiusCalledStationIdDescription: "所访问的服务器的标识",
|
||||
RadiusCallingStationId: "呼叫方号码(Calling Station Id)",
|
||||
RadiusCallingStationIdDescription: "发出请求的设备的标识",
|
||||
"Setup Docker Host": "配置 Docker 宿主信息",
|
||||
"Connection Type": "连接方式",
|
||||
"Docker Daemon": "Docker 守护进程",
|
||||
|
@ -564,6 +594,9 @@ export default {
|
|||
"Container Name / ID": "容器名称 / ID",
|
||||
"Docker Host": "Docker 宿主",
|
||||
"Docker Hosts": "Docker 宿主",
|
||||
"ntfy Topic": "ntfy Topic",
|
||||
Domain: "域名",
|
||||
Workstation: "工作站",
|
||||
disableCloudflaredNoAuthMsg: "您现在正处于 No Auth 模式,无需输入密码",
|
||||
trustProxyDescription: "信任 'X-Forwarded-*' 头。如果您的 Uptime Kuma 是通过 Nginx 或 Apache 等反代服务对外提供访问的话,则您应当启用本功能以获取正确的客户端 IP。",
|
||||
wayToGetLineNotifyToken: "您可以在 {0} 获取 Access token",
|
||||
|
@ -580,7 +613,7 @@ export default {
|
|||
"Event data:": "事件数据:",
|
||||
"Then choose an action, for example switch the scene to where an RGB light is red.": "然后您可以选择关联操作,例如切换到 RGB 灯发出红光的场景",
|
||||
"Frontend Version": "前端版本",
|
||||
"Frontend Version do not match backend version!": "前端版本与后端版本不符!",
|
||||
"Frontend Version do not match backend version!": "前端版本与后端版本不匹配!",
|
||||
"Base URL": "API 基础地址",
|
||||
goAlertInfo: "GoAlert 是一个用于呼叫调度、自动汇报和通知(如 SMS 或语音呼叫)的开源应用程序。在正确的时间以正确的方式自动让正确的人参与!{0}",
|
||||
goAlertIntegrationKeyInfo: "使用形如 aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee 的通用 API 集成密钥,通常是复制来的链接中的 token 参数值。",
|
||||
|
@ -594,5 +627,57 @@ export default {
|
|||
"Gateway Type": "网关类型",
|
||||
SMSManager: "SMSManager",
|
||||
"You can divide numbers with": "可用的分隔符:",
|
||||
"or": "或",
|
||||
or: "或",
|
||||
recurringInterval: "时间间隔",
|
||||
Recurring: "重复",
|
||||
strategyManual: "手动启用/禁用",
|
||||
warningTimezone: "使用服务器时区",
|
||||
weekdayShortMon: "周一",
|
||||
weekdayShortTue: "周二",
|
||||
weekdayShortWed: "周三",
|
||||
weekdayShortThu: "周四",
|
||||
weekdayShortFri: "周五",
|
||||
weekdayShortSat: "周六",
|
||||
weekdayShortSun: "周日",
|
||||
dayOfWeek: "每周计划",
|
||||
dayOfMonth: "每月计划",
|
||||
lastDay: "结束日",
|
||||
lastDay1: "每月最后一天",
|
||||
lastDay2: "每月倒数第二天",
|
||||
lastDay3: "每月倒数第三天",
|
||||
lastDay4: "每月倒数第四天",
|
||||
"No Maintenance": "无维护计划",
|
||||
pauseMaintenanceMsg: "确定要暂停吗?",
|
||||
"maintenanceStatus-under-maintenance": "正在维护",
|
||||
"maintenanceStatus-inactive": "未启用",
|
||||
"maintenanceStatus-scheduled": "已计划",
|
||||
"maintenanceStatus-ended": "已结束",
|
||||
"maintenanceStatus-unknown": "未知",
|
||||
"Display Timezone": "显示时区",
|
||||
"Server Timezone": "服务器时区",
|
||||
statusPageMaintenanceEndDate: "结束时间",
|
||||
IconUrl: "图标 URL",
|
||||
"Enable DNS Cache": "启用 DNS 缓存",
|
||||
Enable: "启用",
|
||||
Disable: "禁用",
|
||||
dnsCacheDescription: "可能无法在某些 IPv6 环境工作,如果遇到问题请禁用。",
|
||||
"Single Maintenance Window": "单一时间窗口",
|
||||
"Maintenance Time Window of a Day": "每日维护时间窗口",
|
||||
"Effective Date Range": "生效日期范围",
|
||||
"Schedule Maintenance": "计划维护",
|
||||
"Date and Time": "日期时间",
|
||||
"DateTime Range": "日期时间范围",
|
||||
Strategy: "策略",
|
||||
"Free Mobile User Identifier": "Free Mobile User Identifier",
|
||||
"Free Mobile API Key": "Free Mobile API Key",
|
||||
"Enable TLS": "启用 TLS",
|
||||
"Proto Service Name": "Proto 服务名称",
|
||||
"Proto Method": "Proto 方法",
|
||||
"Proto Content": "Proto 内容",
|
||||
Economy: "经济",
|
||||
Lowcost: "低价",
|
||||
high: "高价",
|
||||
"General Monitor Type": "常规监控类型",
|
||||
"Passive Monitor Type": "被动监控类型",
|
||||
"Specific Monitor Type": "针对监控类型",
|
||||
};
|
||||
|
|
|
@ -382,4 +382,7 @@ export default {
|
|||
setAsDefaultProxyDescription: "預設情況下,新監測器將啟用此代理伺服器。您仍可分別停用各監測器的代理伺服器。",
|
||||
Maintenance: "維護",
|
||||
statusMaintenance: "維護中",
|
||||
"Enable DNS Cache": "啟用 DNS 快取",
|
||||
"Enable": "啟用",
|
||||
"Disable": "停用",
|
||||
};
|
||||
|
|
|
@ -8,6 +8,8 @@ export default {
|
|||
ignoreTLSError: "忽略 HTTPS 網站的 TLS/SSL 錯誤",
|
||||
upsideDownModeDescription: "反轉顯示狀態。若服務可以連線,將顯示離線。",
|
||||
maxRedirectDescription: "最大重新導向跟隨次數。設為 0 將停用重新導向。",
|
||||
enableGRPCTls: "允許以 TLS 連線傳送 gRPC 要求",
|
||||
grpcMethodDescription: "方法名稱將轉換至駝峰式命名,如 sayHello、check 等。",
|
||||
acceptedStatusCodesDescription: "選擇視為成功回應的狀態碼。",
|
||||
Maintenance: "維護",
|
||||
statusMaintenance: "維護",
|
||||
|
@ -219,13 +221,15 @@ export default {
|
|||
"Content Type": "內容類型",
|
||||
webhookJsonDesc: "{0} 適合任何現代的 HTTP 伺服器,如 Express.js",
|
||||
webhookFormDataDesc: "{multipart} 適合 PHP。 JSON 必須先經由 {decodeFunction} 剖析。",
|
||||
webhookAdditionalHeadersTitle: "額外標頭",
|
||||
webhookAdditionalHeadersDesc: "設定與 webhook 一同傳送的額外標頭。",
|
||||
smtp: "Email (SMTP)",
|
||||
secureOptionNone: "無 / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "忽略 TLS 錯誤",
|
||||
"From Email": "寄件人",
|
||||
emailCustomSubject: "自訂主旨",
|
||||
"To Email": "收件人",
|
||||
"To Email": "收件者",
|
||||
smtpCC: "CC",
|
||||
smtpBCC: "BCC",
|
||||
discord: "Discord",
|
||||
|
@ -239,10 +243,10 @@ export default {
|
|||
wayToGetTeamsURL: "您可以前往此頁面以了解如何建立 Webhook 網址 {0}。",
|
||||
signal: "Signal",
|
||||
Number: "號碼",
|
||||
Recipients: "收件人",
|
||||
Recipients: "收件者",
|
||||
needSignalAPI: "您需要有 REST API 的 Signal 客戶端。",
|
||||
wayToCheckSignalURL: "您可以前往下列網址以了解如何設定:",
|
||||
signalImportant: "注意: 不得混合收件人的群組和號碼!",
|
||||
signalImportant: "注意: 不得混合收件者的群組和號碼!",
|
||||
gotify: "Gotify",
|
||||
"Application Token": "應用程式權杖",
|
||||
"Server URL": "伺服器網址",
|
||||
|
@ -304,11 +308,11 @@ export default {
|
|||
aboutIconURL: "您可以在 \"圖示網址\" 中提供圖片網址以覆蓋預設個人檔案圖片。若已設定 Emoji 圖示,將忽略此設定。",
|
||||
aboutMattermostChannelName: "您可以在 \"頻道名稱\" 欄位中填寫頻道名稱以覆蓋 Webhook 的預設頻道。必須在 Mattermost 的 Webhook 設定中啟用。例如:#其他頻道",
|
||||
matrix: "Matrix",
|
||||
promosmsTypeEco: "SMS ECO - 便宜,但是很慢且經常過載。僅限位於波蘭的收件人。",
|
||||
promosmsTypeFlash: "SMS FLASH - 訊息會自動在收件人的裝置上顯示。僅限位於波蘭的收件人。",
|
||||
promosmsTypeEco: "SMS ECO - 便宜,但是很慢且經常過載。僅限位於波蘭的收件者。",
|
||||
promosmsTypeFlash: "SMS FLASH - 訊息會自動在收件者的裝置上顯示。僅限位於波蘭的收件者。",
|
||||
promosmsTypeFull: "SMS FULL - 高級版,您可以使用您的寄件人名稱 (必須先註冊名稱。對於警報來說十分可靠。",
|
||||
promosmsTypeSpeed: "SMS SPEED - 系統中的最高優先度。快速、可靠,但昂貴 (約 SMS FULL 的兩倍價格)。",
|
||||
promosmsPhoneNumber: "電話號碼 (若收件人位於波蘭則無需輸入區域代碼)",
|
||||
promosmsPhoneNumber: "電話號碼 (若收件者位於波蘭則無需輸入區域代碼)",
|
||||
promosmsSMSSender: "簡訊寄件人名稱:預先註冊的名稱或以下的預設名稱:InfoSMS、SMS Info、MaxSMS、INFO、SMS",
|
||||
"Feishu WebHookUrl": "飛書 WebHook 網址",
|
||||
matrixHomeserverURL: "Homeserver 網址 (開頭為 http(s)://,結尾可能帶連接埠)",
|
||||
|
@ -320,7 +324,7 @@ export default {
|
|||
Headers: "標頭",
|
||||
PushUrl: "Push 網址",
|
||||
HeadersInvalidFormat: "要求標頭不是有效的 JSON:",
|
||||
BodyInvalidFormat: "請求主體不是有效的 JSON:",
|
||||
BodyInvalidFormat: "要求主體不是有效的 JSON:",
|
||||
"Monitor History": "監測器歷史紀錄",
|
||||
clearDataOlderThan: "保留 {0} 天內的監測器歷史紀錄。",
|
||||
PasswordsDoNotMatch: "密碼不相符。",
|
||||
|
@ -378,6 +382,16 @@ export default {
|
|||
serwersmsAPIPassword: "API 密碼",
|
||||
serwersmsPhoneNumber: "電話號碼",
|
||||
serwersmsSenderName: "SMS 寄件人名稱 (由客戶入口網站註冊)",
|
||||
smseagle: "SMSEagle",
|
||||
smseagleTo: "電話號碼",
|
||||
smseagleGroup: "電話簿群組名稱",
|
||||
smseagleContact: "電話簿聯絡人名稱",
|
||||
smseagleRecipientType: "收件者類型",
|
||||
smseagleRecipient: "收件者 (用逗號分隔)",
|
||||
smseagleToken: "API 存取權杖",
|
||||
smseagleUrl: "您的 SMSEagle 裝置網址",
|
||||
smseagleEncoding: "以 Unicode 傳送",
|
||||
smseaglePriority: "訊息優先度 (0-9,預設 = 0)",
|
||||
stackfield: "Stackfield",
|
||||
Customize: "自訂",
|
||||
"Custom Footer": "自訂頁尾",
|
||||
|
@ -631,4 +645,28 @@ export default {
|
|||
"Display Timezone": "顯示時區",
|
||||
"Server Timezone": "伺服器時區",
|
||||
statusPageMaintenanceEndDate: "結束",
|
||||
IconUrl: "圖示網址",
|
||||
"Enable DNS Cache": "啟用 DNS 快取",
|
||||
Enable: "啟用",
|
||||
Disable: "停用",
|
||||
dnsCacheDescription: "在某些 IPv6 環境可能會無法運作,如果您遇到任何問題,請停用。",
|
||||
"Single Maintenance Window": "單一維護時段",
|
||||
"Maintenance Time Window of a Day": "每日的維護時段",
|
||||
"Effective Date Range": "有效的日期範圍",
|
||||
"Schedule Maintenance": "排程維護",
|
||||
"Date and Time": "時間和日期",
|
||||
"DateTime Range": "DateTime 範圍",
|
||||
Strategy: "策略",
|
||||
"Free Mobile User Identifier": "Free Mobile User Identifier",
|
||||
"Free Mobile API Key": "Free Mobile API 金鑰",
|
||||
"Enable TLS": "啟用 TLS",
|
||||
"Proto Service Name": "Proto 服務名稱",
|
||||
"Proto Method": "Proto 方式",
|
||||
"Proto Content": "Proto 內容",
|
||||
Economy: "節約",
|
||||
Lowcost: "低費率",
|
||||
high: "高",
|
||||
"General Monitor Type": "一般監測器類型",
|
||||
"Passive Monitor Type": "被動監測器類型",
|
||||
"Specific Monitor Type": "指定監測器類型",
|
||||
};
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
<nav v-if="$root.isMobile && $root.loggedIn" class="bottom-nav">
|
||||
<router-link to="/dashboard" class="nav-link">
|
||||
<div><font-awesome-icon icon="tachometer-alt" /></div>
|
||||
{{ $t("Dashboard") }}
|
||||
{{ $t("Home") }}
|
||||
</router-link>
|
||||
|
||||
<router-link to="/list" class="nav-link">
|
||||
|
|
|
@ -17,7 +17,7 @@ import lang from "./mixins/lang";
|
|||
import { router } from "./router";
|
||||
import { appName } from "./util.ts";
|
||||
import dayjs from "dayjs";
|
||||
import timezone from "dayjs/plugin/timezone";
|
||||
import timezone from "./modules/dayjs/plugin/timezone";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
dayjs.extend(utc);
|
||||
|
|
|
@ -2,6 +2,7 @@ import { io } from "socket.io-client";
|
|||
import { useToast } from "vue-toastification";
|
||||
import jwtDecode from "jwt-decode";
|
||||
import Favico from "favico.js";
|
||||
import dayjs from "dayjs";
|
||||
const toast = useToast();
|
||||
|
||||
let socket;
|
||||
|
@ -271,6 +272,10 @@ export default {
|
|||
socket.on("cloudflared_message", (res) => this.cloudflared.message = res);
|
||||
socket.on("cloudflared_errorMessage", (res) => this.cloudflared.errorMessage = res);
|
||||
socket.on("cloudflared_token", (res) => this.cloudflared.cloudflareTunnelToken = res);
|
||||
|
||||
socket.on("initServerTimezone", () => {
|
||||
socket.emit("initServerTimezone", dayjs.tz.guess());
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -585,7 +590,7 @@ export default {
|
|||
for (let monitorID in this.lastHeartbeatList) {
|
||||
let lastHeartBeat = this.lastHeartbeatList[monitorID];
|
||||
|
||||
if (this.monitorList[monitorID].maintenance) {
|
||||
if (this.monitorList[monitorID] && this.monitorList[monitorID].maintenance) {
|
||||
result[monitorID] = {
|
||||
text: this.$t("statusMaintenance"),
|
||||
color: "maintenance",
|
||||
|
|
25
src/modules/dayjs/constant.js
Normal file
25
src/modules/dayjs/constant.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
export let SECONDS_A_MINUTE = 60;
|
||||
export let SECONDS_A_HOUR = SECONDS_A_MINUTE * 60;
|
||||
export let SECONDS_A_DAY = SECONDS_A_HOUR * 24;
|
||||
export let SECONDS_A_WEEK = SECONDS_A_DAY * 7;
|
||||
export let MILLISECONDS_A_SECOND = 1e3;
|
||||
export let MILLISECONDS_A_MINUTE = SECONDS_A_MINUTE * MILLISECONDS_A_SECOND;
|
||||
export let MILLISECONDS_A_HOUR = SECONDS_A_HOUR * MILLISECONDS_A_SECOND;
|
||||
export let MILLISECONDS_A_DAY = SECONDS_A_DAY * MILLISECONDS_A_SECOND;
|
||||
export let MILLISECONDS_A_WEEK = SECONDS_A_WEEK * MILLISECONDS_A_SECOND; // English locales
|
||||
|
||||
export let MS = "millisecond";
|
||||
export let S = "second";
|
||||
export let MIN = "minute";
|
||||
export let H = "hour";
|
||||
export let D = "day";
|
||||
export let W = "week";
|
||||
export let M = "month";
|
||||
export let Q = "quarter";
|
||||
export let Y = "year";
|
||||
export let DATE = "date";
|
||||
export let FORMAT_DEFAULT = "YYYY-MM-DDTHH:mm:ssZ";
|
||||
export let INVALID_DATE_STRING = "Invalid Date"; // regex
|
||||
|
||||
export let REGEX_PARSE = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/;
|
||||
export let REGEX_FORMAT = /\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g;
|
20
src/modules/dayjs/plugin/timezone/index.d.ts
vendored
Normal file
20
src/modules/dayjs/plugin/timezone/index.d.ts
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { PluginFunc, ConfigType } from 'dayjs/esm'
|
||||
|
||||
declare const plugin: PluginFunc
|
||||
export = plugin
|
||||
|
||||
declare module 'dayjs/esm' {
|
||||
interface Dayjs {
|
||||
tz(timezone?: string, keepLocalTime?: boolean): Dayjs
|
||||
offsetName(type?: 'short' | 'long'): string | undefined
|
||||
}
|
||||
|
||||
interface DayjsTimezone {
|
||||
(date: ConfigType, timezone?: string): Dayjs
|
||||
(date: ConfigType, format: string, timezone?: string): Dayjs
|
||||
guess(): string
|
||||
setDefault(timezone?: string): void
|
||||
}
|
||||
|
||||
const tz: DayjsTimezone
|
||||
}
|
188
src/modules/dayjs/plugin/timezone/index.js
Normal file
188
src/modules/dayjs/plugin/timezone/index.js
Normal file
|
@ -0,0 +1,188 @@
|
|||
/**
|
||||
* Copy from node_modules/dayjs/plugin/timezone.js
|
||||
* Try to fix https://github.com/louislam/uptime-kuma/issues/2318
|
||||
* Source: https://github.com/iamkun/dayjs/tree/dev/src/plugin/utc
|
||||
* License: MIT
|
||||
*/
|
||||
import { MIN, MS } from "../../constant";
|
||||
let typeToPos = {
|
||||
year: 0,
|
||||
month: 1,
|
||||
day: 2,
|
||||
hour: 3,
|
||||
minute: 4,
|
||||
second: 5
|
||||
}; // Cache time-zone lookups from Intl.DateTimeFormat,
|
||||
// as it is a *very* slow method.
|
||||
|
||||
let dtfCache = {};
|
||||
|
||||
let getDateTimeFormat = function getDateTimeFormat(timezone, options) {
|
||||
if (options === void 0) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
let timeZoneName = options.timeZoneName || "short";
|
||||
let key = timezone + "|" + timeZoneName;
|
||||
let dtf = dtfCache[key];
|
||||
|
||||
if (!dtf) {
|
||||
dtf = new Intl.DateTimeFormat("en-US", {
|
||||
hour12: false,
|
||||
timeZone: timezone,
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
timeZoneName: timeZoneName
|
||||
});
|
||||
dtfCache[key] = dtf;
|
||||
}
|
||||
|
||||
return dtf;
|
||||
};
|
||||
|
||||
export default (function (o, c, d) {
|
||||
let defaultTimezone;
|
||||
|
||||
let makeFormatParts = function makeFormatParts(timestamp, timezone, options) {
|
||||
if (options === void 0) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
let date = new Date(timestamp);
|
||||
let dtf = getDateTimeFormat(timezone, options);
|
||||
return dtf.formatToParts(date);
|
||||
};
|
||||
|
||||
let tzOffset = function tzOffset(timestamp, timezone) {
|
||||
let formatResult = makeFormatParts(timestamp, timezone);
|
||||
let filled = [];
|
||||
|
||||
for (let i = 0; i < formatResult.length; i += 1) {
|
||||
let _formatResult$i = formatResult[i];
|
||||
let type = _formatResult$i.type;
|
||||
let value = _formatResult$i.value;
|
||||
let pos = typeToPos[type];
|
||||
|
||||
if (pos >= 0) {
|
||||
filled[pos] = parseInt(value, 10);
|
||||
}
|
||||
}
|
||||
|
||||
let hour = filled[3]; // Workaround for the same behavior in different node version
|
||||
// https://github.com/nodejs/node/issues/33027
|
||||
|
||||
/* istanbul ignore next */
|
||||
|
||||
let fixedHour = hour === 24 ? 0 : hour;
|
||||
let utcString = filled[0] + "-" + filled[1] + "-" + filled[2] + " " + fixedHour + ":" + filled[4] + ":" + filled[5] + ":000";
|
||||
let utcTs = d.utc(utcString).valueOf();
|
||||
let asTS = +timestamp;
|
||||
let over = asTS % 1000;
|
||||
asTS -= over;
|
||||
return (utcTs - asTS) / (60 * 1000);
|
||||
}; // find the right offset a given local time. The o input is our guess, which determines which
|
||||
// offset we'll pick in ambiguous cases (e.g. there are two 3 AMs b/c Fallback DST)
|
||||
// https://github.com/moment/luxon/blob/master/src/datetime.js#L76
|
||||
|
||||
let fixOffset = function fixOffset(localTS, o0, tz) {
|
||||
// Our UTC time is just a guess because our offset is just a guess
|
||||
let utcGuess = localTS - o0 * 60 * 1000; // Test whether the zone matches the offset for this ts
|
||||
|
||||
let o2 = tzOffset(utcGuess, tz); // If so, offset didn't change and we're done
|
||||
|
||||
if (o0 === o2) {
|
||||
return [ utcGuess, o0 ];
|
||||
} // If not, change the ts by the difference in the offset
|
||||
|
||||
utcGuess -= (o2 - o0) * 60 * 1000; // If that gives us the local time we want, we're done
|
||||
|
||||
let o3 = tzOffset(utcGuess, tz);
|
||||
|
||||
if (o2 === o3) {
|
||||
return [ utcGuess, o2 ];
|
||||
} // If it's different, we're in a hole time.
|
||||
// The offset has changed, but the we don't adjust the time
|
||||
|
||||
return [ localTS - Math.min(o2, o3) * 60 * 1000, Math.max(o2, o3) ];
|
||||
};
|
||||
|
||||
let proto = c.prototype;
|
||||
|
||||
proto.tz = function (timezone, keepLocalTime) {
|
||||
if (timezone === void 0) {
|
||||
timezone = defaultTimezone;
|
||||
}
|
||||
|
||||
let oldOffset = this.utcOffset();
|
||||
let date = this.toDate();
|
||||
let target = date.toLocaleString("en-US", {
|
||||
timeZone: timezone
|
||||
}).replace("\u202f", " ");
|
||||
let diff = Math.round((date - new Date(target)) / 1000 / 60);
|
||||
let ins = d(target).$set(MS, this.$ms).utcOffset(-Math.round(date.getTimezoneOffset() / 15) * 15 - diff, true);
|
||||
|
||||
if (keepLocalTime) {
|
||||
let newOffset = ins.utcOffset();
|
||||
ins = ins.add(oldOffset - newOffset, MIN);
|
||||
}
|
||||
|
||||
ins.$x.$timezone = timezone;
|
||||
return ins;
|
||||
};
|
||||
|
||||
proto.offsetName = function (type) {
|
||||
// type: short(default) / long
|
||||
let zone = this.$x.$timezone || d.tz.guess();
|
||||
let result = makeFormatParts(this.valueOf(), zone, {
|
||||
timeZoneName: type
|
||||
}).find(function (m) {
|
||||
return m.type.toLowerCase() === "timezonename";
|
||||
});
|
||||
return result && result.value;
|
||||
};
|
||||
|
||||
let oldStartOf = proto.startOf;
|
||||
|
||||
proto.startOf = function (units, startOf) {
|
||||
if (!this.$x || !this.$x.$timezone) {
|
||||
return oldStartOf.call(this, units, startOf);
|
||||
}
|
||||
|
||||
let withoutTz = d(this.format("YYYY-MM-DD HH:mm:ss:SSS"));
|
||||
let startOfWithoutTz = oldStartOf.call(withoutTz, units, startOf);
|
||||
return startOfWithoutTz.tz(this.$x.$timezone, true);
|
||||
};
|
||||
|
||||
d.tz = function (input, arg1, arg2) {
|
||||
let parseFormat = arg2 && arg1;
|
||||
let timezone = arg2 || arg1 || defaultTimezone;
|
||||
let previousOffset = tzOffset(+d(), timezone);
|
||||
|
||||
if (typeof input !== "string") {
|
||||
// timestamp number || js Date || Day.js
|
||||
return d(input).tz(timezone);
|
||||
}
|
||||
|
||||
let localTs = d.utc(input, parseFormat).valueOf();
|
||||
|
||||
let _fixOffset = fixOffset(localTs, previousOffset, timezone);
|
||||
let targetTs = _fixOffset[0];
|
||||
let targetOffset = _fixOffset[1];
|
||||
|
||||
let ins = d(targetTs).utcOffset(targetOffset);
|
||||
ins.$x.$timezone = timezone;
|
||||
return ins;
|
||||
};
|
||||
|
||||
d.tz.guess = function () {
|
||||
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
};
|
||||
|
||||
d.tz.setDefault = function (timezone) {
|
||||
defaultTimezone = timezone;
|
||||
};
|
||||
});
|
|
@ -473,6 +473,12 @@ table {
|
|||
|
||||
.dropdown-clear-data {
|
||||
float: right;
|
||||
|
||||
ul {
|
||||
width: 100%;
|
||||
min-width: unset;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<div class="my-3">
|
||||
<label for="type" class="form-label">{{ $t("Monitor Type") }}</label>
|
||||
<select id="type" v-model="monitor.type" class="form-select">
|
||||
<optgroup label="General Monitor Type">
|
||||
<optgroup :label="$t('General Monitor Type')">
|
||||
<option value="http">
|
||||
HTTP(s)
|
||||
</option>
|
||||
|
@ -35,13 +35,13 @@
|
|||
</option>
|
||||
</optgroup>
|
||||
|
||||
<optgroup label="Passive Monitor Type">
|
||||
<optgroup :label="$t('Passive Monitor Type')">
|
||||
<option value="push">
|
||||
Push
|
||||
</option>
|
||||
</optgroup>
|
||||
|
||||
<optgroup label="Specific Monitor Type">
|
||||
<optgroup :label="$t('Specific Monitor Type')">
|
||||
<option value="steam">
|
||||
{{ $t("Steam Game Server") }}
|
||||
</option>
|
||||
|
@ -49,17 +49,23 @@
|
|||
MQTT
|
||||
</option>
|
||||
<option value="sqlserver">
|
||||
SQL Server
|
||||
Microsoft SQL Server
|
||||
</option>
|
||||
<option value="postgres">
|
||||
PostgreSQL
|
||||
</option>
|
||||
<option value="mysql">
|
||||
MySQL/MariaDB
|
||||
</option>
|
||||
<option value="mongodb">
|
||||
MongoDB
|
||||
</option>
|
||||
<option value="radius">
|
||||
Radius
|
||||
</option>
|
||||
<option value="redis">
|
||||
Redis
|
||||
</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
@ -247,8 +253,8 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<!-- SQL Server and PostgreSQL -->
|
||||
<template v-if="monitor.type === 'sqlserver' || monitor.type === 'postgres'">
|
||||
<!-- SQL Server / PostgreSQL / MySQL -->
|
||||
<template v-if="monitor.type === 'sqlserver' || monitor.type === 'postgres' || monitor.type === 'mysql'">
|
||||
<div class="my-3">
|
||||
<label for="sqlConnectionString" class="form-label">{{ $t("Connection String") }}</label>
|
||||
|
||||
|
@ -258,12 +264,22 @@
|
|||
<template v-if="monitor.type === 'postgres'">
|
||||
<input id="sqlConnectionString" v-model="monitor.databaseConnectionString" type="text" class="form-control" placeholder="postgres://username:password@host:port/database">
|
||||
</template>
|
||||
<template v-if="monitor.type === 'mysql'">
|
||||
<input id="sqlConnectionString" v-model="monitor.databaseConnectionString" type="text" class="form-control" placeholder="mysql://username:password@host:port/database">
|
||||
</template>
|
||||
</div>
|
||||
<div class="my-3">
|
||||
<label for="sqlQuery" class="form-label">{{ $t("Query") }}</label>
|
||||
<textarea id="sqlQuery" v-model="monitor.databaseQuery" class="form-control" placeholder="Example: select getdate()"></textarea>
|
||||
</div>
|
||||
</template>
|
||||
<!-- Redis -->
|
||||
<template v-if="monitor.type === 'redis'">
|
||||
<div class="my-3">
|
||||
<label for="redisConnectionString" class="form-label">{{ $t("Connection String") }}</label>
|
||||
<input id="redisConnectionString" v-model="monitor.databaseConnectionString" type="text" class="form-control" placeholder="redis://user:password@host:port">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- MongoDB -->
|
||||
<template v-if="monitor.type === 'mongodb'">
|
||||
|
@ -279,7 +295,7 @@
|
|||
<!-- Interval -->
|
||||
<div class="my-3">
|
||||
<label for="interval" class="form-label">{{ $t("Heartbeat Interval") }} ({{ $t("checkEverySecond", [ monitor.interval ]) }})</label>
|
||||
<input id="interval" v-model="monitor.interval" type="number" class="form-control" required min="20" step="1">
|
||||
<input id="interval" v-model="monitor.interval" type="number" class="form-control" required :min="minInterval" step="1" :max="maxInterval">
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
|
@ -295,7 +311,7 @@
|
|||
{{ $t("Heartbeat Retry Interval") }}
|
||||
<span>({{ $t("retryCheckEverySecond", [ monitor.retryInterval ]) }})</span>
|
||||
</label>
|
||||
<input id="retry-interval" v-model="monitor.retryInterval" type="number" class="form-control" required min="20" step="1">
|
||||
<input id="retry-interval" v-model="monitor.retryInterval" type="number" class="form-control" required :min="minInterval" step="1">
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
|
@ -583,7 +599,7 @@ import NotificationDialog from "../components/NotificationDialog.vue";
|
|||
import DockerHostDialog from "../components/DockerHostDialog.vue";
|
||||
import ProxyDialog from "../components/ProxyDialog.vue";
|
||||
import TagsManager from "../components/TagsManager.vue";
|
||||
import { genSecret, isDev } from "../util.ts";
|
||||
import { genSecret, isDev, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND } from "../util.ts";
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
|
@ -599,6 +615,8 @@ export default {
|
|||
|
||||
data() {
|
||||
return {
|
||||
minInterval: MIN_INTERVAL_SECOND,
|
||||
maxInterval: MAX_INTERVAL_SECOND,
|
||||
processing: false,
|
||||
monitor: {
|
||||
notificationIDList: {},
|
||||
|
|
|
@ -185,6 +185,14 @@ export default {
|
|||
<style lang="scss" scoped>
|
||||
@import "../assets/vars.scss";
|
||||
|
||||
.mobile {
|
||||
.item {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -267,6 +275,11 @@ export default {
|
|||
.buttons {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.btn-group {
|
||||
width: 310px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-if="$root.isMobile" class="shadow-box mb-3">
|
||||
<router-link to="/manage-status-page" class="nav-link">
|
||||
<font-awesome-icon icon="stream" /> {{ $t("Status Pages") }}
|
||||
</router-link>
|
||||
<router-link to="/maintenance" class="nav-link">
|
||||
<font-awesome-icon icon="wrench" /> {{ $t("Maintenance") }}
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<h1 v-show="show" class="mb-3">
|
||||
{{ $t("Settings") }}
|
||||
</h1>
|
||||
|
||||
<div class="shadow-box">
|
||||
<div class="shadow-box shadow-box-settings">
|
||||
<div class="row">
|
||||
<div v-if="showSubMenu" class="settings-menu col-lg-3 col-md-5">
|
||||
<router-link
|
||||
|
@ -86,6 +95,9 @@ export default {
|
|||
"reverse-proxy": {
|
||||
title: this.$t("Reverse Proxy"),
|
||||
},
|
||||
tags: {
|
||||
title: this.$t("Tags"),
|
||||
},
|
||||
"monitor-history": {
|
||||
title: this.$t("Monitor History"),
|
||||
},
|
||||
|
@ -148,6 +160,10 @@ export default {
|
|||
this.settings.entryPage = "dashboard";
|
||||
}
|
||||
|
||||
if (this.settings.dnsCache === undefined) {
|
||||
this.settings.dnsCache = false;
|
||||
}
|
||||
|
||||
if (this.settings.keepDataPeriodDays === undefined) {
|
||||
this.settings.keepDataPeriodDays = 180;
|
||||
}
|
||||
|
@ -176,14 +192,36 @@ export default {
|
|||
* @param {string} [currentPassword] Only need for disableAuth to true
|
||||
*/
|
||||
saveSettings(callback, currentPassword) {
|
||||
this.$root.getSocket().emit("setSettings", this.settings, currentPassword, (res) => {
|
||||
this.$root.toastRes(res);
|
||||
this.loadSettings();
|
||||
let valid = this.validateSettings();
|
||||
if (valid.success) {
|
||||
this.$root.getSocket().emit("setSettings", this.settings, currentPassword, (res) => {
|
||||
this.$root.toastRes(res);
|
||||
this.loadSettings();
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$root.toastError(valid.msg);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Ensure settings are valid
|
||||
* @returns {Object} Contains success state and error msg
|
||||
*/
|
||||
validateSettings() {
|
||||
if (this.settings.keepDataPeriodDays < 0) {
|
||||
return {
|
||||
success: false,
|
||||
msg: this.$t("dataRetentionTimeError"),
|
||||
};
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
msg: "",
|
||||
};
|
||||
},
|
||||
}
|
||||
};
|
||||
|
@ -192,7 +230,7 @@ export default {
|
|||
<style lang="scss" scoped>
|
||||
@import "../assets/vars.scss";
|
||||
|
||||
.shadow-box {
|
||||
.shadow-box-settings {
|
||||
padding: 20px;
|
||||
min-height: calc(100vh - 155px);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import Appearance from "./components/settings/Appearance.vue";
|
|||
import General from "./components/settings/General.vue";
|
||||
const Notifications = () => import("./components/settings/Notifications.vue");
|
||||
import ReverseProxy from "./components/settings/ReverseProxy.vue";
|
||||
import Tags from "./components/settings/Tags.vue";
|
||||
import MonitorHistory from "./components/settings/MonitorHistory.vue";
|
||||
const Security = () => import("./components/settings/Security.vue");
|
||||
import Proxies from "./components/settings/Proxies.vue";
|
||||
|
@ -95,6 +96,10 @@ const routes = [
|
|||
path: "reverse-proxy",
|
||||
component: ReverseProxy,
|
||||
},
|
||||
{
|
||||
path: "tags",
|
||||
component: Tags,
|
||||
},
|
||||
{
|
||||
path: "monitor-history",
|
||||
component: MonitorHistory,
|
||||
|
|
|
@ -78,3 +78,29 @@ export function getResBaseURL() {
|
|||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tag color options
|
||||
* Shared between components
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
export function colorOptions(self) {
|
||||
return [
|
||||
{ name: self.$t("Gray"),
|
||||
color: "#4B5563" },
|
||||
{ name: self.$t("Red"),
|
||||
color: "#DC2626" },
|
||||
{ name: self.$t("Orange"),
|
||||
color: "#D97706" },
|
||||
{ name: self.$t("Green"),
|
||||
color: "#059669" },
|
||||
{ name: self.$t("Blue"),
|
||||
color: "#2563EB" },
|
||||
{ name: self.$t("Indigo"),
|
||||
color: "#4F46E5" },
|
||||
{ name: self.$t("Purple"),
|
||||
color: "#7C3AED" },
|
||||
{ name: self.$t("Pink"),
|
||||
color: "#DB2777" },
|
||||
];
|
||||
}
|
||||
|
|
14
src/util.js
14
src/util.js
|
@ -7,7 +7,7 @@
|
|||
// Backend uses the compiled file util.js
|
||||
// Frontend uses util.ts
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
|
||||
exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.MIN_INTERVAL_SECOND = exports.MAX_INTERVAL_SECOND = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
|
||||
const dayjs = require("dayjs");
|
||||
exports.isDev = process.env.NODE_ENV === "development";
|
||||
exports.appName = "Uptime Kuma";
|
||||
|
@ -22,6 +22,8 @@ exports.STATUS_PAGE_MAINTENANCE = 3;
|
|||
exports.SQL_DATE_FORMAT = "YYYY-MM-DD";
|
||||
exports.SQL_DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
|
||||
exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = "YYYY-MM-DD HH:mm";
|
||||
exports.MAX_INTERVAL_SECOND = 2073600; // 24 days
|
||||
exports.MIN_INTERVAL_SECOND = 20; // 20 seconds
|
||||
/** Flip the status of s */
|
||||
function flipStatus(s) {
|
||||
if (s === exports.UP) {
|
||||
|
@ -99,12 +101,18 @@ class Logger {
|
|||
* @param level Log level. One of INFO, WARN, ERROR, DEBUG or can be customized.
|
||||
*/
|
||||
log(module, msg, level) {
|
||||
if (this.hideLog[level] && this.hideLog[level].includes(module)) {
|
||||
if (this.hideLog[level] && this.hideLog[level].includes(module.toLowerCase())) {
|
||||
return;
|
||||
}
|
||||
module = module.toUpperCase();
|
||||
level = level.toUpperCase();
|
||||
const now = dayjs.tz(new Date()).format();
|
||||
let now;
|
||||
if (dayjs.tz) {
|
||||
now = dayjs.tz(new Date()).format();
|
||||
}
|
||||
else {
|
||||
now = dayjs().format();
|
||||
}
|
||||
const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg;
|
||||
if (level === "INFO") {
|
||||
console.info(formattedMessage);
|
||||
|
|
12
src/util.ts
12
src/util.ts
|
@ -26,6 +26,9 @@ export const SQL_DATE_FORMAT = "YYYY-MM-DD";
|
|||
export const SQL_DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
|
||||
export const SQL_DATETIME_FORMAT_WITHOUT_SECOND = "YYYY-MM-DD HH:mm";
|
||||
|
||||
export const MAX_INTERVAL_SECOND = 2073600; // 24 days
|
||||
export const MIN_INTERVAL_SECOND = 20; // 20 seconds
|
||||
|
||||
/** Flip the status of s */
|
||||
export function flipStatus(s: number) {
|
||||
if (s === UP) {
|
||||
|
@ -112,14 +115,19 @@ class Logger {
|
|||
* @param level Log level. One of INFO, WARN, ERROR, DEBUG or can be customized.
|
||||
*/
|
||||
log(module: string, msg: any, level: string) {
|
||||
if (this.hideLog[level] && this.hideLog[level].includes(module)) {
|
||||
if (this.hideLog[level] && this.hideLog[level].includes(module.toLowerCase())) {
|
||||
return;
|
||||
}
|
||||
|
||||
module = module.toUpperCase();
|
||||
level = level.toUpperCase();
|
||||
|
||||
const now = dayjs.tz(new Date()).format();
|
||||
let now;
|
||||
if (dayjs.tz) {
|
||||
now = dayjs.tz(new Date()).format();
|
||||
} else {
|
||||
now = dayjs().format();
|
||||
}
|
||||
const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg;
|
||||
|
||||
if (level === "INFO") {
|
||||
|
|
44
test/cypress/unit/i18n.spec.js
Normal file
44
test/cypress/unit/i18n.spec.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { currentLocale } from "../../../src/i18n";
|
||||
|
||||
describe("Test i18n.js", () => {
|
||||
|
||||
it("currentLocale()", () => {
|
||||
const setLanguage = (language) => {
|
||||
Object.defineProperty(window.navigator, 'language', {
|
||||
value: language,
|
||||
writable: true
|
||||
});
|
||||
}
|
||||
setLanguage('en-EN');
|
||||
|
||||
expect(currentLocale()).equal("en");
|
||||
|
||||
setLanguage('zh-HK');
|
||||
expect(currentLocale()).equal("zh-HK");
|
||||
|
||||
// Note that in Safari on iOS prior to 10.2, the country code returned is lowercase: "en-us", "fr-fr" etc.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language
|
||||
setLanguage('zh-hk');
|
||||
expect(currentLocale()).equal("en");
|
||||
|
||||
setLanguage('en-US');
|
||||
expect(currentLocale()).equal("en");
|
||||
|
||||
setLanguage('ja-ZZ');
|
||||
expect(currentLocale()).equal("ja");
|
||||
|
||||
setLanguage('zz-ZZ');
|
||||
expect(currentLocale()).equal("en");
|
||||
|
||||
setLanguage('zz-ZZ');
|
||||
expect(currentLocale()).equal("en");
|
||||
|
||||
setLanguage('en');
|
||||
localStorage.locale = "en";
|
||||
expect(currentLocale()).equal("en");
|
||||
|
||||
localStorage.locale = "zh-HK";
|
||||
expect(currentLocale()).equal("zh-HK");
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in a new issue