mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-11 07:02:36 +02:00
Merge branch 'master' of https://github.com/iomataani/uptime-kuma
This commit is contained in:
commit
2c7a1ca884
127 changed files with 7641 additions and 2925 deletions
|
@ -27,7 +27,8 @@ CNAME
|
|||
install.sh
|
||||
SECURITY.md
|
||||
tsconfig.json
|
||||
|
||||
.env
|
||||
/tmp
|
||||
|
||||
### .gitignore content (commented rules are duplicated)
|
||||
|
||||
|
|
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
|
@ -1,6 +1,6 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
github: louislam # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
#patreon: # Replace with a single Patreon username
|
||||
open_collective: uptime-kuma # Replace with a single Open Collective username
|
||||
#ko_fi: # Replace with a single Ko-fi username
|
||||
|
|
3
.github/ISSUE_TEMPLATE/ask-for-help.md
vendored
3
.github/ISSUE_TEMPLATE/ask-for-help.md
vendored
|
@ -9,6 +9,9 @@ assignees: ''
|
|||
**Is it a duplicate question?**
|
||||
Please search in Issues without filters: https://github.com/louislam/uptime-kuma/issues?q=
|
||||
|
||||
**Describe your problem**
|
||||
Please describe what you are asking for
|
||||
|
||||
**Info**
|
||||
Uptime Kuma Version:
|
||||
Using Docker?: Yes/No
|
||||
|
|
35
.github/workflows/auto-test.yml
vendored
Normal file
35
.github/workflows/auto-test.yml
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: Auto Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
auto-test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
node-version: [14.x, 16.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
- run: npm run install-legacy
|
||||
- run: npm run build
|
||||
- run: npm test
|
||||
env:
|
||||
HEADLESS_TEST: 1
|
||||
JUST_FOR_TEST: ${{ secrets.JUST_FOR_TEST }}
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -12,3 +12,4 @@ dist-ssr
|
|||
/private
|
||||
/out
|
||||
/tmp
|
||||
.env
|
||||
|
|
|
@ -6,7 +6,7 @@ The project was created with vite.js (vue3). Then I created a sub-directory call
|
|||
|
||||
The frontend code build into "dist" directory. The server (express.js) exposes the "dist" directory as root of the endpoint. This is how production is working.
|
||||
|
||||
# Key Technical Skills
|
||||
## Key Technical Skills
|
||||
|
||||
- Node.js (You should know what are promise, async/await and arrow function etc.)
|
||||
- Socket.io
|
||||
|
@ -15,7 +15,7 @@ The frontend code build into "dist" directory. The server (express.js) exposes t
|
|||
- Bootstrap
|
||||
- SQLite
|
||||
|
||||
# Directories
|
||||
## Directories
|
||||
|
||||
- data (App data)
|
||||
- dist (Frontend build)
|
||||
|
@ -25,49 +25,50 @@ The frontend code build into "dist" directory. The server (express.js) exposes t
|
|||
- src (Frontend source code)
|
||||
- test (unit test)
|
||||
|
||||
# Can I create a pull request for Uptime Kuma?
|
||||
## Can I create a pull request for Uptime Kuma?
|
||||
|
||||
Generally, if the pull request is working fine and it do not affect any existing logic, workflow and perfomance, I will merge into the master branch once it is tested.
|
||||
|
||||
If you are not sure, feel free to create an empty pull request draft first.
|
||||
|
||||
## Pull Request Examples
|
||||
### Pull Request Examples
|
||||
|
||||
### ✅ High - Medium Priority
|
||||
#### ✅ High - Medium Priority
|
||||
|
||||
- Add a new notification
|
||||
- Add a chart
|
||||
- Fix a bug
|
||||
- Translations
|
||||
|
||||
### *️⃣ Requires one more reviewer
|
||||
#### *️⃣ Requires one more reviewer
|
||||
|
||||
I do not have such knowledge to test it.
|
||||
|
||||
- Add k8s supports
|
||||
|
||||
### *️⃣ Low Priority
|
||||
#### *️⃣ Low Priority
|
||||
|
||||
It changed my current workflow and require further studies.
|
||||
|
||||
- Change my release approach
|
||||
|
||||
### ❌ Won't Merge
|
||||
#### ❌ Won't Merge
|
||||
|
||||
- Duplicated pull request
|
||||
- Buggy
|
||||
- Existing logic is completely modified or deleted
|
||||
- A function that is completely out of scope
|
||||
|
||||
# Project Styles
|
||||
## 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.
|
||||
|
||||
- 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
|
||||
- Single container for Docker users, no very complex docker-composer file. Just map the volume and expose the port, then good to go
|
||||
- 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. Env var is not encouraged.
|
||||
- Easy to use
|
||||
|
||||
# Coding Styles
|
||||
## Coding Styles
|
||||
|
||||
- 4 spaces indentation
|
||||
- Follow `.editorconfig`
|
||||
|
@ -79,20 +80,20 @@ I personally do not like something need to learn so much and need to config so m
|
|||
- SQLite: underscore_type
|
||||
- CSS/SCSS: dash-type
|
||||
|
||||
# Tools
|
||||
## Tools
|
||||
|
||||
- Node.js >= 14
|
||||
- Git
|
||||
- IDE that supports ESLint and EditorConfig (I am using Intellji Idea)
|
||||
- A SQLite tool (SQLite Expert Personal is suggested)
|
||||
|
||||
# Install dependencies
|
||||
## Install dependencies
|
||||
|
||||
```bash
|
||||
npm ci
|
||||
```
|
||||
|
||||
# How to start the Backend Dev Server
|
||||
## How to start the Backend Dev Server
|
||||
|
||||
(2021-09-23 Update)
|
||||
|
||||
|
@ -102,7 +103,7 @@ npm run start-server-dev
|
|||
|
||||
It binds to `0.0.0.0:3001` by default.
|
||||
|
||||
## Backend Details
|
||||
### Backend Details
|
||||
|
||||
It is mainly a socket.io app + express.js.
|
||||
|
||||
|
@ -115,24 +116,26 @@ express.js is just used for serving the frontend built files (index.html, .js an
|
|||
- scoket-handler (Socket.io Handlers)
|
||||
- server.js (Server main logic)
|
||||
|
||||
# How to start the Frontend Dev Server
|
||||
## How to start the Frontend Dev Server
|
||||
|
||||
1. Set the env var `NODE_ENV` to "development".
|
||||
2. Start the frontend dev server by the following command.
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
It binds to `0.0.0.0:3000` by default.
|
||||
|
||||
You can use Vue.js devtools Chrome extension for debugging.
|
||||
|
||||
## Build the frontend
|
||||
### Build the frontend
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Frontend Details
|
||||
### Frontend Details
|
||||
|
||||
Uptime Kuma Frontend is a single page application (SPA). Most paths are handled by Vue Router.
|
||||
|
||||
|
@ -142,12 +145,36 @@ As you can see, most data in frontend is stored in root level, even though you c
|
|||
|
||||
The data and socket logic are in `src/mixins/socket.js`.
|
||||
|
||||
|
||||
# Database Migration
|
||||
## Database Migration
|
||||
|
||||
1. Create `patch-{name}.sql` in `./db/`
|
||||
2. Add your patch filename in the `patchList` list in `./server/database.js`
|
||||
|
||||
# Unit Test
|
||||
## Unit Test
|
||||
|
||||
Yes, no unit test for now. I know it is very important, but at the same time my spare time is very limited. I want to implement my ideas first. I will go back to this in some points.
|
||||
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.
|
||||
|
||||
## Update Dependencies
|
||||
|
||||
Install `ncu`
|
||||
https://github.com/raineorshine/npm-check-updates
|
||||
|
||||
```bash
|
||||
ncu -u -t patch
|
||||
npm install
|
||||
```
|
||||
|
||||
Since previously updating vite 2.5.10 to 2.6.0 broke the application completely, from now on, it should update patch release version only.
|
||||
|
||||
Patch release = the third digit ([Semantic Versioning](https://semver.org/))
|
||||
|
||||
## Translations
|
||||
|
||||
Please read: https://github.com/louislam/uptime-kuma/tree/master/src/languages
|
||||
|
|
22
README.md
22
README.md
|
@ -2,14 +2,13 @@
|
|||
|
||||
<a target="_blank" href="https://github.com/louislam/uptime-kuma"><img src="https://img.shields.io/github/stars/louislam/uptime-kuma" /></a> <a target="_blank" href="https://hub.docker.com/r/louislam/uptime-kuma"><img src="https://img.shields.io/docker/pulls/louislam/uptime-kuma" /></a> <a target="_blank" href="https://hub.docker.com/r/louislam/uptime-kuma"><img src="https://img.shields.io/docker/v/louislam/uptime-kuma/latest?label=docker%20image%20ver." /></a> <a target="_blank" href="https://github.com/louislam/uptime-kuma"><img src="https://img.shields.io/github/last-commit/louislam/uptime-kuma" /></a> <a target="_blank" href="https://opencollective.com/uptime-kuma"><img src="https://opencollective.com/uptime-kuma/total/badge.svg?label=Backers&color=brightgreen" /></a>
|
||||
|
||||
|
||||
<div align="center" width="100%">
|
||||
<img src="./public/icon.svg" width="128" alt="" />
|
||||
</div>
|
||||
|
||||
It is a self-hosted monitoring tool like "Uptime Robot".
|
||||
|
||||
<img src="https://louislam.net/uptimekuma/1.jpg" width="512" alt="" />
|
||||
<img src="https://uptime.kuma.pet/img/dark.jpg" width="700" alt="" />
|
||||
|
||||
## 🥔 Live Demo
|
||||
|
||||
|
@ -17,17 +16,20 @@ Try it!
|
|||
|
||||
https://demo.uptime.kuma.pet
|
||||
|
||||
It is a 5 minutes live demo, all data will be deleted after that. The server is located at Tokyo, if you live far away from here, it may affact your experience. I suggest that you should install to try it.
|
||||
It is a 10 minutes live demo, all data will be deleted after that. The server is located at Tokyo, if you live far away from here, it may affact your experience. I suggest that you should install to try it.
|
||||
|
||||
VPS is sponsored by Uptime Kuma sponsors on [Open Collective](https://opencollective.com/uptime-kuma)! Thank you so much!
|
||||
|
||||
## ⭐ Features
|
||||
|
||||
* Monitoring uptime for HTTP(s) / TCP / Ping / DNS Record.
|
||||
* Monitoring uptime for HTTP(s) / TCP / Ping / DNS Record / Push.
|
||||
* Fancy, Reactive, Fast UI/UX.
|
||||
* Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [70+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/issues/284).
|
||||
* Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [70+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications).
|
||||
* 20 seconds interval.
|
||||
* [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/languages)
|
||||
* Simple Status Page
|
||||
* Ping Chart
|
||||
* Certificate Info
|
||||
|
||||
## 🔧 How to Install
|
||||
|
||||
|
@ -86,9 +88,13 @@ https://github.com/louislam/uptime-kuma/projects/1
|
|||
|
||||
## 🖼 More Screenshots
|
||||
|
||||
Dark Mode:
|
||||
Light Mode:
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/1336778/128710166-908f8d88-9256-43f3-9c49-bfc2c56011d2.png" width="400" alt="" />
|
||||
<img src="https://uptime.kuma.pet/img/light.jpg" width="512" alt="" />
|
||||
|
||||
Status Page:
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/1336778/134628766-a3fe0981-0926-4285-ab46-891a21c3e4cb.png" width="512" alt="" />
|
||||
|
||||
Settings Page:
|
||||
|
||||
|
@ -112,9 +118,11 @@ If you love this project, please consider giving me a ⭐.
|
|||
## 🗣️ Discussion
|
||||
|
||||
### Issues Page
|
||||
|
||||
You can discuss or ask for help in [Issues](https://github.com/louislam/uptime-kuma/issues).
|
||||
|
||||
### Subreddit
|
||||
|
||||
My Reddit account: louislamlam
|
||||
You can mention me if you ask question on Reddit.
|
||||
https://www.reddit.com/r/UptimeKuma/
|
||||
|
|
18
SECURITY.md
18
SECURITY.md
|
@ -5,11 +5,27 @@
|
|||
Use this section to tell people about which versions of your project are
|
||||
currently being supported with security updates.
|
||||
|
||||
### Uptime Kuma Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.x.x | :white_check_mark: |
|
||||
| 1.7.X | :white_check_mark: |
|
||||
| < 1.7 | ❌ |
|
||||
|
||||
### Upgradable Docker Tags
|
||||
|
||||
| Tag | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1 | :white_check_mark: |
|
||||
| 1-debian | :white_check_mark: |
|
||||
| 1-alpine | :white_check_mark: |
|
||||
| latest | :white_check_mark: |
|
||||
| debian | :white_check_mark: |
|
||||
| alpine | :white_check_mark: |
|
||||
| All other tags | ❌ |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report security issues to uptime@kuma.pet.
|
||||
|
||||
Do not use the issue tracker or discuss it in the public as it will cause more damage.
|
||||
|
|
11
babel.config.js
Normal file
11
babel.config.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
const config = {};
|
||||
|
||||
if (process.env.TEST_FRONTEND) {
|
||||
config.presets = ["@babel/preset-env"];
|
||||
}
|
||||
|
||||
if (process.env.TEST_BACKEND) {
|
||||
config.plugins = ["babel-plugin-rewire"];
|
||||
}
|
||||
|
||||
module.exports = config;
|
5
config/jest-backend.config.js
Normal file
5
config/jest-backend.config.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
"rootDir": "..",
|
||||
"testRegex": "./test/backend.spec.js",
|
||||
};
|
||||
|
5
config/jest-frontend.config.js
Normal file
5
config/jest-frontend.config.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
"rootDir": "..",
|
||||
"testRegex": "./test/frontend.spec.js",
|
||||
};
|
||||
|
6
config/jest-puppeteer.config.js
Normal file
6
config/jest-puppeteer.config.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
"launch": {
|
||||
"headless": process.env.HEADLESS_TEST || false,
|
||||
"userDataDir": "./data/test-chrome-profile",
|
||||
}
|
||||
};
|
11
config/jest.config.js
Normal file
11
config/jest.config.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
module.exports = {
|
||||
"verbose": true,
|
||||
"preset": "jest-puppeteer",
|
||||
"globals": {
|
||||
"__DEV__": true
|
||||
},
|
||||
"testRegex": "./test/e2e.spec.js",
|
||||
"rootDir": "..",
|
||||
"testTimeout": 30000,
|
||||
};
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import legacy from "@vitejs/plugin-legacy"
|
||||
import vue from "@vitejs/plugin-vue"
|
||||
import { defineConfig } from "vite"
|
||||
import legacy from "@vitejs/plugin-legacy";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import { defineConfig } from "vite";
|
||||
|
||||
const postCssScss = require("postcss-scss")
|
||||
const postcssRTLCSS = require('postcss-rtlcss');
|
||||
const postCssScss = require("postcss-scss");
|
||||
const postcssRTLCSS = require("postcss-rtlcss");
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
|
@ -20,5 +20,5 @@ export default defineConfig({
|
|||
"map": false,
|
||||
"plugins": [postcssRTLCSS]
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
});
|
|
@ -1,10 +1,12 @@
|
|||
FROM louislam/uptime-kuma:base-debian AS build
|
||||
WORKDIR /app
|
||||
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
|
||||
|
||||
COPY . .
|
||||
RUN npm install --legacy-peer-deps && \
|
||||
RUN npm ci && \
|
||||
npm run build && \
|
||||
npm prune --production && \
|
||||
npm ci --production && \
|
||||
chmod +x /app/extra/entrypoint.sh
|
||||
|
||||
|
||||
|
@ -45,5 +47,5 @@ RUN chmod +x /app/extra/upload-github-release-asset.sh
|
|||
|
||||
# Dist only
|
||||
RUN cd /app && tar -zcvf $DIST dist
|
||||
RUN /app/extra/upload-github-release-asset.sh github_api_token=$GITHUB_TOKEN owner=louislam repo=uptime-kuma tag=$VERSION filename=$DIST
|
||||
RUN /app/extra/upload-github-release-asset.sh github_api_token=$GITHUB_TOKEN owner=louislam repo=uptime-kuma tag=$VERSION filename=/app/$DIST
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
FROM louislam/uptime-kuma:base-alpine AS build
|
||||
WORKDIR /app
|
||||
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
|
||||
|
||||
COPY . .
|
||||
RUN npm install --legacy-peer-deps && \
|
||||
RUN npm ci && \
|
||||
npm run build && \
|
||||
npm prune --production && \
|
||||
npm ci --production && \
|
||||
chmod +x /app/extra/entrypoint.sh
|
||||
|
||||
|
6
ecosystem.config.js
Normal file
6
ecosystem.config.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
apps: [{
|
||||
name: "uptime-kuma",
|
||||
script: "./server/server.js",
|
||||
}]
|
||||
}
|
57
extra/download-dist.js
Normal file
57
extra/download-dist.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
console.log("Downloading dist");
|
||||
const https = require("https");
|
||||
const tar = require("tar");
|
||||
|
||||
const packageJSON = require("../package.json");
|
||||
const fs = require("fs");
|
||||
const version = packageJSON.version;
|
||||
|
||||
const filename = "dist.tar.gz";
|
||||
|
||||
const url = `https://github.com/louislam/uptime-kuma/releases/download/${version}/${filename}`;
|
||||
download(url);
|
||||
|
||||
function download(url) {
|
||||
console.log(url);
|
||||
|
||||
https.get(url, (response) => {
|
||||
if (response.statusCode === 200) {
|
||||
console.log("Extracting dist...");
|
||||
|
||||
if (fs.existsSync("./dist")) {
|
||||
|
||||
if (fs.existsSync("./dist-backup")) {
|
||||
fs.rmdirSync("./dist-backup", {
|
||||
recursive: true
|
||||
});
|
||||
}
|
||||
|
||||
fs.renameSync("./dist", "./dist-backup");
|
||||
}
|
||||
|
||||
const tarStream = tar.x({
|
||||
cwd: "./",
|
||||
});
|
||||
|
||||
tarStream.on("close", () => {
|
||||
fs.rmdirSync("./dist-backup", {
|
||||
recursive: true
|
||||
});
|
||||
console.log("Done");
|
||||
});
|
||||
|
||||
tarStream.on("error", () => {
|
||||
if (fs.existsSync("./dist-backup")) {
|
||||
fs.renameSync("./dist-backup", "./dist");
|
||||
}
|
||||
console.log("Done");
|
||||
});
|
||||
|
||||
response.pipe(tarStream);
|
||||
} else if (response.statusCode === 302) {
|
||||
download(response.headers.location);
|
||||
} else {
|
||||
console.log("dist not found");
|
||||
}
|
||||
});
|
||||
}
|
|
@ -19,6 +19,7 @@ if (! newVersion) {
|
|||
const exists = tagExists(newVersion);
|
||||
|
||||
if (! exists) {
|
||||
|
||||
// Process package.json
|
||||
pkg.version = newVersion;
|
||||
pkg.scripts.setup = pkg.scripts.setup.replaceAll(oldVersion, newVersion);
|
||||
|
@ -29,8 +30,11 @@ if (! exists) {
|
|||
|
||||
commit(newVersion);
|
||||
tag(newVersion);
|
||||
|
||||
updateWiki(oldVersion, newVersion);
|
||||
|
||||
} else {
|
||||
console.log("version exists")
|
||||
console.log("version exists");
|
||||
}
|
||||
|
||||
function commit(version) {
|
||||
|
@ -38,16 +42,16 @@ function commit(version) {
|
|||
|
||||
let res = child_process.spawnSync("git", ["commit", "-m", msg, "-a"]);
|
||||
let stdout = res.stdout.toString().trim();
|
||||
console.log(stdout)
|
||||
console.log(stdout);
|
||||
|
||||
if (stdout.includes("no changes added to commit")) {
|
||||
throw new Error("commit error")
|
||||
throw new Error("commit error");
|
||||
}
|
||||
}
|
||||
|
||||
function tag(version) {
|
||||
let res = child_process.spawnSync("git", ["tag", version]);
|
||||
console.log(res.stdout.toString().trim())
|
||||
console.log(res.stdout.toString().trim());
|
||||
}
|
||||
|
||||
function tagExists(version) {
|
||||
|
@ -59,3 +63,38 @@ function tagExists(version) {
|
|||
|
||||
return res.stdout.toString().trim() === version;
|
||||
}
|
||||
|
||||
function updateWiki(oldVersion, newVersion) {
|
||||
const wikiDir = "./tmp/wiki";
|
||||
const howToUpdateFilename = "./tmp/wiki/🆙-How-to-Update.md";
|
||||
|
||||
safeDelete(wikiDir);
|
||||
|
||||
child_process.spawnSync("git", ["clone", "https://github.com/louislam/uptime-kuma.wiki.git", wikiDir]);
|
||||
let content = fs.readFileSync(howToUpdateFilename).toString();
|
||||
content = content.replaceAll(`git checkout ${oldVersion}`, `git checkout ${newVersion}`);
|
||||
fs.writeFileSync(howToUpdateFilename, content);
|
||||
|
||||
child_process.spawnSync("git", ["add", "-A"], {
|
||||
cwd: wikiDir,
|
||||
});
|
||||
|
||||
child_process.spawnSync("git", ["commit", "-m", `Update to ${newVersion} from ${oldVersion}`], {
|
||||
cwd: wikiDir,
|
||||
});
|
||||
|
||||
console.log("Pushing to Github");
|
||||
child_process.spawnSync("git", ["push"], {
|
||||
cwd: wikiDir,
|
||||
});
|
||||
|
||||
safeDelete(wikiDir);
|
||||
}
|
||||
|
||||
function safeDelete(dir) {
|
||||
if (fs.existsSync(dir)) {
|
||||
fs.rmdirSync(dir, {
|
||||
recursive: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
module.exports = {
|
||||
"launch": {
|
||||
"headless": false
|
||||
}
|
||||
};
|
5577
package-lock.json
generated
5577
package-lock.json
generated
File diff suppressed because it is too large
Load diff
58
package.json
58
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.7.3",
|
||||
"version": "1.8.0",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -15,25 +15,29 @@
|
|||
"lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
|
||||
"lint:style": "stylelint \"**/*.{vue,css,scss}\" --ignore-path .gitignore",
|
||||
"lint": "npm run lint:js && npm run lint:style",
|
||||
"dev": "vite --host",
|
||||
"dev": "vite --host --config ./config/vite.config.js",
|
||||
"start": "npm run start-server",
|
||||
"start-server": "node server/server.js",
|
||||
"start-server-dev": "cross-env NODE_ENV=development node server/server.js",
|
||||
"build": "vite build",
|
||||
"prepare-test": "npm run build && node server/server.js --port=3002 --data-dir=./data/test/",
|
||||
"test": "jest",
|
||||
"build": "vite build --config ./config/vite.config.js",
|
||||
"test": "node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/ --test",
|
||||
"test-with-build": "npm run build && npm test",
|
||||
"jest": "node test/prepare-jest.js && npm run jest-frontend && npm run jest-backend && jest --config=./config/jest.config.js",
|
||||
"jest-frontend": "cross-env TEST_FRONTEND=1 jest --config=./config/jest-frontend.config.js",
|
||||
"jest-backend": "cross-env TEST_BACKEND=1 jest --config=./config/jest-backend.config.js",
|
||||
"tsc": "tsc",
|
||||
"vite-preview-dist": "vite preview --host",
|
||||
"vite-preview-dist": "vite preview --host --config ./config/vite.config.js",
|
||||
"build-docker": "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-alpine": "docker buildx build -f 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:1.7.3-alpine --target release . --push",
|
||||
"build-docker-debian": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:1.7.3 -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:1.7.3-debian --target release . --push",
|
||||
"build-docker-nightly": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push",
|
||||
"build-docker-alpine": "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:1.8.0-alpine --target release . --push",
|
||||
"build-docker-debian": "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:1.8.0 -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:1.8.0-debian --target release . --push",
|
||||
"build-docker-nightly": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push",
|
||||
"build-docker-nightly-alpine": "docker buildx build -f dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly-alpine --target nightly . --push",
|
||||
"build-docker-nightly-amd64": "docker buildx build --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain",
|
||||
"build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain",
|
||||
"upload-artifacts": "docker buildx build --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
||||
"setup": "git checkout 1.7.3 && npm install --legacy-peer-deps && node node_modules/esbuild/install.js && npm run build && npm prune",
|
||||
"setup": "git checkout 1.8.0 && npm ci --production && npm run download-dist",
|
||||
"download-dist": "node extra/download-dist.js",
|
||||
"update-version": "node extra/update-version.js",
|
||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||
"reset-password": "node extra/reset-password.js",
|
||||
|
@ -52,12 +56,13 @@
|
|||
"@fortawesome/free-regular-svg-icons": "~5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "~3.0.0-4",
|
||||
"@louislam/sqlite3": "~5.0.6",
|
||||
"@popperjs/core": "~2.10.1",
|
||||
"@louislam/sqlite3": "~6.0.0",
|
||||
"@popperjs/core": "~2.10.2",
|
||||
"args-parser": "~1.3.0",
|
||||
"axios": "~0.21.4",
|
||||
"bcryptjs": "~2.4.3",
|
||||
"bootstrap": "~5.1.1",
|
||||
"chardet": "^1.3.0",
|
||||
"chart.js": "~3.5.1",
|
||||
"chartjs-adapter-dayjs": "~1.0.0",
|
||||
"command-exists": "~1.2.9",
|
||||
|
@ -67,18 +72,20 @@
|
|||
"express-basic-auth": "~1.2.0",
|
||||
"form-data": "~4.0.0",
|
||||
"http-graceful-shutdown": "~3.1.4",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"jsonwebtoken": "~8.5.1",
|
||||
"nodemailer": "~6.6.5",
|
||||
"notp": "~2.0.3",
|
||||
"password-hash": "~1.2.2",
|
||||
"postcss-rtlcss": "~3.4.1",
|
||||
"postcss-scss": "~4.0.0",
|
||||
"postcss-scss": "~4.0.1",
|
||||
"prom-client": "~13.2.0",
|
||||
"prometheus-api-metrics": "~3.2.0",
|
||||
"qrcode": "~1.4.4",
|
||||
"redbean-node": "0.1.2",
|
||||
"socket.io": "~4.2.0",
|
||||
"socket.io-client": "~4.2.0",
|
||||
"tar": "^6.1.11",
|
||||
"tcp-ping": "~0.1.1",
|
||||
"thirty-two": "~1.0.2",
|
||||
"timezones-list": "~3.0.1",
|
||||
|
@ -87,7 +94,7 @@
|
|||
"vue-chart-3": "~0.5.8",
|
||||
"vue-confirm-dialog": "~1.0.2",
|
||||
"vue-contenteditable": "~3.0.4",
|
||||
"vue-i18n": "~9.1.7",
|
||||
"vue-i18n": "~9.1.9",
|
||||
"vue-image-crop-upload": "~3.0.3",
|
||||
"vue-multiselect": "~3.0.0-alpha.2",
|
||||
"vue-qrcode": "~1.0.0",
|
||||
|
@ -97,11 +104,13 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "~7.15.7",
|
||||
"@babel/preset-env": "^7.15.8",
|
||||
"@types/bootstrap": "~5.1.6",
|
||||
"@vitejs/plugin-legacy": "~1.5.3",
|
||||
"@vitejs/plugin-vue": "~1.9.1",
|
||||
"@vue/compiler-sfc": "~3.2.16",
|
||||
"core-js": "~3.18.0",
|
||||
"@vitejs/plugin-legacy": "~1.6.1",
|
||||
"@vitejs/plugin-vue": "~1.9.2",
|
||||
"@vue/compiler-sfc": "~3.2.19",
|
||||
"babel-plugin-rewire": "~1.2.0",
|
||||
"core-js": "~3.18.1",
|
||||
"cross-env": "~7.0.3",
|
||||
"dns2": "~2.0.1",
|
||||
"eslint": "~7.32.0",
|
||||
|
@ -113,15 +122,6 @@
|
|||
"stylelint": "~13.13.1",
|
||||
"stylelint-config-standard": "~22.0.0",
|
||||
"typescript": "~4.4.3",
|
||||
"vite": "~2.5.10"
|
||||
},
|
||||
"jest": {
|
||||
"verbose": true,
|
||||
"preset": "jest-puppeteer",
|
||||
"globals": {
|
||||
"__DEV__": true
|
||||
},
|
||||
"testRegex": "./test/*.spec.js",
|
||||
"rootDir": "."
|
||||
"vite": "~2.6.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
const { setSetting } = require("./util-server");
|
||||
const axios = require("axios");
|
||||
const { isDev } = require("../src/util");
|
||||
|
||||
exports.version = require("../package.json").version;
|
||||
exports.latestVersion = null;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
const { TimeLogger } = require("../src/util");
|
||||
const { R } = require("redbean-node");
|
||||
const { io } = require("./server");
|
||||
const { setting } = require("./util-server");
|
||||
const checkVersion = require("./check-version");
|
||||
|
||||
async function sendNotificationList(socket) {
|
||||
const timeLogger = new TimeLogger();
|
||||
|
@ -14,10 +16,10 @@ async function sendNotificationList(socket) {
|
|||
]);
|
||||
|
||||
for (let bean of list) {
|
||||
result.push(bean.export())
|
||||
result.push(bean.export());
|
||||
}
|
||||
|
||||
io.to(socket.userID).emit("notificationList", result)
|
||||
io.to(socket.userID).emit("notificationList", result);
|
||||
|
||||
timeLogger.print("Send Notification List");
|
||||
|
||||
|
@ -39,7 +41,7 @@ async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite =
|
|||
LIMIT 100
|
||||
`, [
|
||||
monitorID,
|
||||
])
|
||||
]);
|
||||
|
||||
let result = list.reverse();
|
||||
|
||||
|
@ -69,7 +71,7 @@ async function sendImportantHeartbeatList(socket, monitorID, toUser = false, ove
|
|||
LIMIT 500
|
||||
`, [
|
||||
monitorID,
|
||||
])
|
||||
]);
|
||||
|
||||
timeLogger.print(`[Monitor: ${monitorID}] sendImportantHeartbeatList`);
|
||||
|
||||
|
@ -81,8 +83,18 @@ async function sendImportantHeartbeatList(socket, monitorID, toUser = false, ove
|
|||
|
||||
}
|
||||
|
||||
async function sendInfo(socket) {
|
||||
socket.emit("info", {
|
||||
version: checkVersion.version,
|
||||
latestVersion: checkVersion.latestVersion,
|
||||
primaryBaseURL: await setting("primaryBaseURL")
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
sendNotificationList,
|
||||
sendImportantHeartbeatList,
|
||||
sendHeartbeatList,
|
||||
}
|
||||
sendInfo
|
||||
};
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@ const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalCli
|
|||
const { R } = require("redbean-node");
|
||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||
const { Notification } = require("../notification");
|
||||
const { demoMode } = require("../server");
|
||||
const version = require("../../package.json").version;
|
||||
const apicache = require("../modules/apicache");
|
||||
|
||||
/**
|
||||
* status:
|
||||
|
@ -166,7 +168,9 @@ class Monitor extends BeanModel {
|
|||
}
|
||||
}
|
||||
|
||||
debug("Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms");
|
||||
if (process.env.TIMELOGGER === "1") {
|
||||
debug("Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms");
|
||||
}
|
||||
|
||||
if (this.type === "http") {
|
||||
bean.status = UP;
|
||||
|
@ -288,51 +292,13 @@ class Monitor extends BeanModel {
|
|||
|
||||
let beatInterval = this.interval;
|
||||
|
||||
// * ? -> ANY STATUS = important [isFirstBeat]
|
||||
// UP -> PENDING = not important
|
||||
// * UP -> DOWN = important
|
||||
// UP -> UP = not important
|
||||
// PENDING -> PENDING = not important
|
||||
// * PENDING -> DOWN = important
|
||||
// PENDING -> UP = not important
|
||||
// DOWN -> PENDING = this case not exists
|
||||
// DOWN -> DOWN = not important
|
||||
// * DOWN -> UP = important
|
||||
let isImportant = isFirstBeat ||
|
||||
(previousBeat.status === UP && bean.status === DOWN) ||
|
||||
(previousBeat.status === DOWN && bean.status === UP) ||
|
||||
(previousBeat.status === PENDING && bean.status === DOWN);
|
||||
let isImportant = Monitor.isImportantBeat(isFirstBeat, previousBeat.status, bean.status);
|
||||
|
||||
// Mark as important if status changed, ignore pending pings,
|
||||
// Don't notify if disrupted changes to up
|
||||
if (isImportant) {
|
||||
bean.important = true;
|
||||
|
||||
// Send only if the first beat is DOWN
|
||||
if (!isFirstBeat || bean.status === DOWN) {
|
||||
let notificationList = await R.getAll("SELECT notification.* FROM notification, monitor_notification WHERE monitor_id = ? AND monitor_notification.notification_id = notification.id ", [
|
||||
this.id,
|
||||
]);
|
||||
|
||||
let text;
|
||||
if (bean.status === UP) {
|
||||
text = "✅ Up";
|
||||
} else {
|
||||
text = "🔴 Down";
|
||||
}
|
||||
|
||||
let msg = `[${this.name}] [${text}] ${bean.msg}`;
|
||||
|
||||
for (let notification of notificationList) {
|
||||
try {
|
||||
await Notification.send(JSON.parse(notification.config), msg, await this.toJSON(), bean.toJSON());
|
||||
} catch (e) {
|
||||
console.error("Cannot send notification to " + notification.name);
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await Monitor.sendNotification(isFirstBeat, this, bean);
|
||||
} else {
|
||||
bean.important = false;
|
||||
}
|
||||
|
@ -357,6 +323,14 @@ class Monitor extends BeanModel {
|
|||
previousBeat = bean;
|
||||
|
||||
if (! this.isStop) {
|
||||
|
||||
if (demoMode) {
|
||||
if (beatInterval < 20) {
|
||||
console.log("beat interval too low, reset to 20s");
|
||||
beatInterval = 20;
|
||||
}
|
||||
}
|
||||
|
||||
this.heartbeatInterval = setTimeout(beat, beatInterval * 1000);
|
||||
}
|
||||
|
||||
|
@ -530,6 +504,54 @@ class Monitor extends BeanModel {
|
|||
const uptime = await this.calcUptime(duration, monitorID);
|
||||
io.to(userID).emit("uptime", monitorID, duration, uptime);
|
||||
}
|
||||
|
||||
static isImportantBeat(isFirstBeat, previousBeatStatus, currentBeatStatus) {
|
||||
// * ? -> ANY STATUS = important [isFirstBeat]
|
||||
// UP -> PENDING = not important
|
||||
// * UP -> DOWN = important
|
||||
// UP -> UP = not important
|
||||
// PENDING -> PENDING = not important
|
||||
// * PENDING -> DOWN = important
|
||||
// PENDING -> UP = not important
|
||||
// DOWN -> PENDING = this case not exists
|
||||
// DOWN -> DOWN = not important
|
||||
// * DOWN -> UP = important
|
||||
let isImportant = isFirstBeat ||
|
||||
(previousBeatStatus === UP && currentBeatStatus === DOWN) ||
|
||||
(previousBeatStatus === DOWN && currentBeatStatus === UP) ||
|
||||
(previousBeatStatus === PENDING && currentBeatStatus === DOWN);
|
||||
return isImportant;
|
||||
}
|
||||
|
||||
static async sendNotification(isFirstBeat, monitor, bean) {
|
||||
if (!isFirstBeat || bean.status === DOWN) {
|
||||
let notificationList = await R.getAll("SELECT notification.* FROM notification, monitor_notification WHERE monitor_id = ? AND monitor_notification.notification_id = notification.id ", [
|
||||
monitor.id,
|
||||
]);
|
||||
|
||||
let text;
|
||||
if (bean.status === UP) {
|
||||
text = "✅ Up";
|
||||
} else {
|
||||
text = "🔴 Down";
|
||||
}
|
||||
|
||||
let msg = `[${monitor.name}] [${text}] ${bean.msg}`;
|
||||
|
||||
for (let notification of notificationList) {
|
||||
try {
|
||||
await Notification.send(JSON.parse(notification.config), msg, await monitor.toJSON(), bean.toJSON());
|
||||
} catch (e) {
|
||||
console.error("Cannot send notification to " + notification.name);
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear Status Page Cache
|
||||
apicache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Monitor;
|
||||
|
|
108
server/notification-providers/aliyun-sms.js
Normal file
108
server/notification-providers/aliyun-sms.js
Normal file
|
@ -0,0 +1,108 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
const { default: axios } = require("axios");
|
||||
const Crypto = require("crypto");
|
||||
const qs = require("qs");
|
||||
|
||||
class AliyunSMS extends NotificationProvider {
|
||||
name = "AliyunSMS";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
if (heartbeatJSON != null) {
|
||||
let msgBody = JSON.stringify({
|
||||
name: monitorJSON["name"],
|
||||
time: heartbeatJSON["time"],
|
||||
status: this.statusToString(heartbeatJSON["status"]),
|
||||
msg: heartbeatJSON["msg"],
|
||||
});
|
||||
if (this.sendSms(notification, msgBody)) {
|
||||
return okMsg;
|
||||
}
|
||||
} else {
|
||||
let msgBody = JSON.stringify({
|
||||
name: "",
|
||||
time: "",
|
||||
status: "",
|
||||
msg: msg,
|
||||
});
|
||||
if (this.sendSms(notification, msgBody)) {
|
||||
return okMsg;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
|
||||
async sendSms(notification, msgbody) {
|
||||
let params = {
|
||||
PhoneNumbers: notification.phonenumber,
|
||||
TemplateCode: notification.templateCode,
|
||||
SignName: notification.signName,
|
||||
TemplateParam: msgbody,
|
||||
AccessKeyId: notification.accessKeyId,
|
||||
Format: "JSON",
|
||||
SignatureMethod: "HMAC-SHA1",
|
||||
SignatureVersion: "1.0",
|
||||
SignatureNonce: Math.random().toString(),
|
||||
Timestamp: new Date().toISOString(),
|
||||
Action: "SendSms",
|
||||
Version: "2017-05-25",
|
||||
};
|
||||
|
||||
params.Signature = this.sign(params, notification.secretAccessKey);
|
||||
let config = {
|
||||
method: "POST",
|
||||
url: "http://dysmsapi.aliyuncs.com/",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
data: qs.stringify(params),
|
||||
};
|
||||
|
||||
let result = await axios(config);
|
||||
if (result.data.Message == "OK") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Aliyun request sign */
|
||||
sign(param, AccessKeySecret) {
|
||||
let param2 = {};
|
||||
let data = [];
|
||||
|
||||
let oa = Object.keys(param).sort();
|
||||
|
||||
for (let i = 0; i < oa.length; i++) {
|
||||
let key = oa[i];
|
||||
param2[key] = param[key];
|
||||
}
|
||||
|
||||
for (let key in param2) {
|
||||
data.push(`${encodeURIComponent(key)}=${encodeURIComponent(param2[key])}`);
|
||||
}
|
||||
|
||||
let StringToSign = `POST&${encodeURIComponent("/")}&${encodeURIComponent(data.join("&"))}`;
|
||||
return Crypto
|
||||
.createHmac("sha1", `${AccessKeySecret}&`)
|
||||
.update(Buffer.from(StringToSign))
|
||||
.digest("base64");
|
||||
}
|
||||
|
||||
statusToString(status) {
|
||||
switch (status) {
|
||||
case DOWN:
|
||||
return "DOWN";
|
||||
case UP:
|
||||
return "UP";
|
||||
default:
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AliyunSMS;
|
79
server/notification-providers/dingding.js
Normal file
79
server/notification-providers/dingding.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
const { default: axios } = require("axios");
|
||||
const Crypto = require("crypto");
|
||||
|
||||
class DingDing extends NotificationProvider {
|
||||
name = "DingDing";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
if (heartbeatJSON != null) {
|
||||
let params = {
|
||||
msgtype: "markdown",
|
||||
markdown: {
|
||||
title: monitorJSON["name"],
|
||||
text: `## [${this.statusToString(heartbeatJSON["status"])}] \n > ${heartbeatJSON["msg"]} \n > Time(UTC):${heartbeatJSON["time"]}`,
|
||||
}
|
||||
};
|
||||
if (this.sendToDingDing(notification, params)) {
|
||||
return okMsg;
|
||||
}
|
||||
} else {
|
||||
let params = {
|
||||
msgtype: "text",
|
||||
text: {
|
||||
content: msg
|
||||
}
|
||||
};
|
||||
if (this.sendToDingDing(notification, params)) {
|
||||
return okMsg;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
|
||||
async sendToDingDing(notification, params) {
|
||||
let timestamp = Date.now();
|
||||
|
||||
let config = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
url: `${notification.webHookUrl}×tamp=${timestamp}&sign=${encodeURIComponent(this.sign(timestamp, notification.secretKey))}`,
|
||||
data: JSON.stringify(params),
|
||||
};
|
||||
|
||||
let result = await axios(config);
|
||||
if (result.data.errmsg == "ok") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** DingDing sign */
|
||||
sign(timestamp, secretKey) {
|
||||
return Crypto
|
||||
.createHmac("sha256", Buffer.from(secretKey, "utf8"))
|
||||
.update(Buffer.from(`${timestamp}\n${secretKey}`, "utf8"))
|
||||
.digest("base64");
|
||||
}
|
||||
|
||||
statusToString(status) {
|
||||
switch (status) {
|
||||
case DOWN:
|
||||
return "DOWN";
|
||||
case UP:
|
||||
return "UP";
|
||||
default:
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DingDing;
|
|
@ -7,7 +7,7 @@ class Discord extends NotificationProvider {
|
|||
name = "discord";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
const discordDisplayName = notification.discordUsername || "Uptime Kuma";
|
||||
|
|
83
server/notification-providers/feishu.js
Normal file
83
server/notification-providers/feishu.js
Normal file
|
@ -0,0 +1,83 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
|
||||
class Feishu extends NotificationProvider {
|
||||
name = "Feishu";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
let feishuWebHookUrl = notification.feishuWebHookUrl;
|
||||
|
||||
try {
|
||||
if (heartbeatJSON == null) {
|
||||
let testdata = {
|
||||
msg_type: "text",
|
||||
content: {
|
||||
text: msg,
|
||||
},
|
||||
};
|
||||
await axios.post(feishuWebHookUrl, testdata);
|
||||
return okMsg;
|
||||
}
|
||||
|
||||
if (heartbeatJSON["status"] == DOWN) {
|
||||
let downdata = {
|
||||
msg_type: "post",
|
||||
content: {
|
||||
post: {
|
||||
zh_cn: {
|
||||
title: "UptimeKuma Alert: " + monitorJSON["name"],
|
||||
content: [
|
||||
[
|
||||
{
|
||||
tag: "text",
|
||||
text:
|
||||
"[Down] " +
|
||||
heartbeatJSON["msg"] +
|
||||
"\nTime (UTC): " +
|
||||
heartbeatJSON["time"],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
await axios.post(feishuWebHookUrl, downdata);
|
||||
return okMsg;
|
||||
}
|
||||
|
||||
if (heartbeatJSON["status"] == UP) {
|
||||
let updata = {
|
||||
msg_type: "post",
|
||||
content: {
|
||||
post: {
|
||||
zh_cn: {
|
||||
title: "UptimeKuma Alert: " + monitorJSON["name"],
|
||||
content: [
|
||||
[
|
||||
{
|
||||
tag: "text",
|
||||
text:
|
||||
"[Up] " +
|
||||
heartbeatJSON["msg"] +
|
||||
"\nTime (UTC): " +
|
||||
heartbeatJSON["time"],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
await axios.post(feishuWebHookUrl, updata);
|
||||
return okMsg;
|
||||
}
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Feishu;
|
|
@ -6,7 +6,7 @@ class Gotify extends NotificationProvider {
|
|||
name = "gotify";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
if (notification.gotifyserverurl && notification.gotifyserverurl.endsWith("/")) {
|
||||
notification.gotifyserverurl = notification.gotifyserverurl.slice(0, -1);
|
||||
|
|
|
@ -7,7 +7,7 @@ class Line extends NotificationProvider {
|
|||
name = "line";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
let lineAPIUrl = "https://api.line.me/v2/bot/message/push";
|
||||
let config = {
|
||||
|
|
|
@ -7,7 +7,7 @@ class LunaSea extends NotificationProvider {
|
|||
name = "lunasea";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
let lunaseadevice = "https://notify.lunasea.app/v1/custom/device/" + notification.lunaseaDevice
|
||||
|
||||
try {
|
||||
|
|
45
server/notification-providers/matrix.js
Normal file
45
server/notification-providers/matrix.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const Crypto = require("crypto");
|
||||
const { debug } = require("../../src/util");
|
||||
|
||||
class Matrix extends NotificationProvider {
|
||||
name = "matrix";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
const size = 20;
|
||||
const randomString = encodeURIComponent(
|
||||
Crypto
|
||||
.randomBytes(size)
|
||||
.toString("base64")
|
||||
.slice(0, size)
|
||||
);
|
||||
|
||||
debug("Random String: " + randomString);
|
||||
|
||||
const roomId = encodeURIComponent(notification.internalRoomId);
|
||||
|
||||
debug("Matrix Room ID: " + roomId);
|
||||
|
||||
try {
|
||||
let config = {
|
||||
headers: {
|
||||
"Authorization": `Bearer ${notification.accessToken}`,
|
||||
}
|
||||
};
|
||||
let data = {
|
||||
"msgtype": "m.text",
|
||||
"body": msg
|
||||
};
|
||||
|
||||
await axios.put(`${notification.homeserverUrl}/_matrix/client/r0/rooms/${roomId}/send/m.room.message/${randomString}`, data, config);
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Matrix;
|
|
@ -7,7 +7,7 @@ class Mattermost extends NotificationProvider {
|
|||
name = "mattermost";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
const mattermostUserName = notification.mattermostusername || "Uptime Kuma";
|
||||
// If heartbeatJSON is null, assume we're testing.
|
||||
|
|
|
@ -6,30 +6,54 @@ class Octopush extends NotificationProvider {
|
|||
name = "octopush";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
let config = {
|
||||
headers: {
|
||||
"api-key": notification.octopushAPIKey,
|
||||
"api-login": notification.octopushLogin,
|
||||
"cache-control": "no-cache"
|
||||
}
|
||||
};
|
||||
let data = {
|
||||
"recipients": [
|
||||
{
|
||||
"phone_number": notification.octopushPhoneNumber
|
||||
// Default - V2
|
||||
if (notification.octopushVersion == 2 || !notification.octopushVersion) {
|
||||
let config = {
|
||||
headers: {
|
||||
"api-key": notification.octopushAPIKey,
|
||||
"api-login": notification.octopushLogin,
|
||||
"cache-control": "no-cache"
|
||||
}
|
||||
],
|
||||
//octopush not supporting non ascii char
|
||||
"text": msg.replace(/[^\x00-\x7F]/g, ""),
|
||||
"type": notification.octopushSMSType,
|
||||
"purpose": "alert",
|
||||
"sender": notification.octopushSenderName
|
||||
};
|
||||
};
|
||||
let data = {
|
||||
"recipients": [
|
||||
{
|
||||
"phone_number": notification.octopushPhoneNumber
|
||||
}
|
||||
],
|
||||
//octopush not supporting non ascii char
|
||||
"text": msg.replace(/[^\x00-\x7F]/g, ""),
|
||||
"type": notification.octopushSMSType,
|
||||
"purpose": "alert",
|
||||
"sender": notification.octopushSenderName
|
||||
};
|
||||
await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config)
|
||||
} else if (notification.octopushVersion == 1) {
|
||||
let data = {
|
||||
"user_login": notification.octopushDMLogin,
|
||||
"api_key": notification.octopushDMAPIKey,
|
||||
"sms_recipients": notification.octopushDMPhoneNumber,
|
||||
"sms_sender": notification.octopushDMSenderName,
|
||||
"sms_type": (notification.octopushDMSMSType == "sms_premium") ? "FR" : "XXX",
|
||||
"transactional": "1",
|
||||
//octopush not supporting non ascii char
|
||||
"sms_text": msg.replace(/[^\x00-\x7F]/g, ""),
|
||||
};
|
||||
|
||||
let config = {
|
||||
headers: {
|
||||
"cache-control": "no-cache"
|
||||
},
|
||||
params: data
|
||||
};
|
||||
await axios.post("https://www.octopush-dm.com/api/sms/json", {}, config)
|
||||
} else {
|
||||
throw new Error("Unknown Octopush version!");
|
||||
}
|
||||
|
||||
await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config)
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
|
|
41
server/notification-providers/promosms.js
Normal file
41
server/notification-providers/promosms.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
|
||||
class PromoSMS extends NotificationProvider {
|
||||
|
||||
name = "promosms";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
let config = {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Basic " + Buffer.from(notification.promosmsLogin + ":" + notification.promosmsPassword).toString('base64'),
|
||||
"Accept": "text/json",
|
||||
}
|
||||
};
|
||||
let data = {
|
||||
"recipients": [ notification.promosmsPhoneNumber ],
|
||||
//Lets remove non ascii char
|
||||
"text": msg.replace(/[^\x00-\x7F]/g, ""),
|
||||
"type": Number(notification.promosmsSMSType),
|
||||
"sender": notification.promosmsSenderName
|
||||
};
|
||||
|
||||
let resp = await axios.post("https://promosms.com/api/rest/v3_2/sms", data, config);
|
||||
|
||||
if (resp.data.response.status !== 0) {
|
||||
let error = "Something gone wrong. Api returned " + resp.data.response.status + ".";
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PromoSMS;
|
|
@ -8,7 +8,7 @@ class Pushbullet extends NotificationProvider {
|
|||
name = "pushbullet";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
let pushbulletUrl = "https://api.pushbullet.com/v2/pushes";
|
||||
|
|
|
@ -6,7 +6,7 @@ class Pushover extends NotificationProvider {
|
|||
name = "pushover";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
let pushoverlink = "https://api.pushover.net/1/messages.json"
|
||||
|
||||
try {
|
||||
|
|
|
@ -6,7 +6,7 @@ class Pushy extends NotificationProvider {
|
|||
name = "pushy";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
await axios.post(`https://api.pushy.me/push?api_key=${notification.pushyAPIKey}`, {
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const Slack = require("./slack");
|
||||
const { setting } = require("../util-server");
|
||||
const { getMonitorRelativeURL, UP, DOWN } = require("../../src/util");
|
||||
|
||||
class RocketChat extends NotificationProvider {
|
||||
|
||||
name = "rocket.chat";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
if (heartbeatJSON == null) {
|
||||
let data = {
|
||||
"text": "Uptime Kuma Rocket.chat testing successful.",
|
||||
"text": msg,
|
||||
"channel": notification.rocketchannel,
|
||||
"username": notification.rocketusername,
|
||||
"icon_emoji": notification.rocketiconemo,
|
||||
}
|
||||
await axios.post(notification.rocketwebhookURL, data)
|
||||
};
|
||||
await axios.post(notification.rocketwebhookURL, data);
|
||||
return okMsg;
|
||||
}
|
||||
|
||||
const time = heartbeatJSON["time"];
|
||||
|
||||
let data = {
|
||||
"text": "Uptime Kuma Alert",
|
||||
"channel": notification.rocketchannel,
|
||||
|
@ -28,16 +32,32 @@ class RocketChat extends NotificationProvider {
|
|||
"attachments": [
|
||||
{
|
||||
"title": "Uptime Kuma Alert *Time (UTC)*\n" + time,
|
||||
"title_link": notification.rocketbutton,
|
||||
"text": "*Message*\n" + msg,
|
||||
"color": "#32cd32"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Color
|
||||
if (heartbeatJSON.status === DOWN) {
|
||||
data.attachments[0].color = "#ff0000";
|
||||
} else {
|
||||
data.attachments[0].color = "#32cd32";
|
||||
}
|
||||
await axios.post(notification.rocketwebhookURL, data)
|
||||
|
||||
if (notification.rocketbutton) {
|
||||
await Slack.deprecateURL(notification.rocketbutton);
|
||||
}
|
||||
|
||||
const baseURL = await setting("primaryBaseURL");
|
||||
|
||||
if (baseURL) {
|
||||
data.attachments[0].title_link = baseURL + getMonitorRelativeURL(monitorJSON.id);
|
||||
}
|
||||
|
||||
await axios.post(notification.rocketwebhookURL, data);
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error)
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ class Signal extends NotificationProvider {
|
|||
name = "signal";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
let data = {
|
||||
|
|
|
@ -1,27 +1,47 @@
|
|||
const NotificationProvider = require("./notification-provider");
|
||||
const axios = require("axios");
|
||||
const { setSettings, setting } = require("../util-server");
|
||||
const { getMonitorRelativeURL } = require("../../src/util");
|
||||
|
||||
class Slack extends NotificationProvider {
|
||||
|
||||
name = "slack";
|
||||
|
||||
/**
|
||||
* Deprecated property notification.slackbutton
|
||||
* Set it as primary base url if this is not yet set.
|
||||
*/
|
||||
static async deprecateURL(url) {
|
||||
let currentPrimaryBaseURL = await setting("primaryBaseURL");
|
||||
|
||||
if (!currentPrimaryBaseURL) {
|
||||
console.log("Move the url to be the primary base URL");
|
||||
await setSettings("general", {
|
||||
primaryBaseURL: url,
|
||||
});
|
||||
} else {
|
||||
console.log("Already there, no need to move the primary base URL");
|
||||
}
|
||||
}
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
try {
|
||||
if (heartbeatJSON == null) {
|
||||
let data = {
|
||||
"text": "Uptime Kuma Slack testing successful.",
|
||||
"text": msg,
|
||||
"channel": notification.slackchannel,
|
||||
"username": notification.slackusername,
|
||||
"icon_emoji": notification.slackiconemo,
|
||||
}
|
||||
await axios.post(notification.slackwebhookURL, data)
|
||||
};
|
||||
await axios.post(notification.slackwebhookURL, data);
|
||||
return okMsg;
|
||||
}
|
||||
|
||||
const time = heartbeatJSON["time"];
|
||||
const textMsg = "Uptime Kuma Alert";
|
||||
let data = {
|
||||
"text": "Uptime Kuma Alert",
|
||||
"text": monitorJSON ? textMsg + `: ${monitorJSON.name}` : textMsg,
|
||||
"channel": notification.slackchannel,
|
||||
"username": notification.slackusername,
|
||||
"icon_emoji": notification.slackiconemo,
|
||||
|
@ -42,26 +62,35 @@ class Slack extends NotificationProvider {
|
|||
"type": "mrkdwn",
|
||||
"text": "*Time (UTC)*\n" + time,
|
||||
}],
|
||||
},
|
||||
{
|
||||
"type": "actions",
|
||||
"elements": [
|
||||
{
|
||||
"type": "button",
|
||||
"text": {
|
||||
"type": "plain_text",
|
||||
"text": "Visit Uptime Kuma",
|
||||
},
|
||||
"value": "Uptime-Kuma",
|
||||
"url": notification.slackbutton || "https://github.com/louislam/uptime-kuma",
|
||||
},
|
||||
],
|
||||
}],
|
||||
};
|
||||
|
||||
if (notification.slackbutton) {
|
||||
await Slack.deprecateURL(notification.slackbutton);
|
||||
}
|
||||
await axios.post(notification.slackwebhookURL, data)
|
||||
|
||||
const baseURL = await setting("primaryBaseURL");
|
||||
|
||||
// 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),
|
||||
}],
|
||||
});
|
||||
}
|
||||
|
||||
await axios.post(notification.slackwebhookURL, data);
|
||||
return okMsg;
|
||||
} catch (error) {
|
||||
this.throwGeneralAxiosError(error)
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const nodemailer = require("nodemailer");
|
||||
const NotificationProvider = require("./notification-provider");
|
||||
const { DOWN, UP } = require("../../src/util");
|
||||
|
||||
class SMTP extends NotificationProvider {
|
||||
|
||||
|
@ -20,6 +21,56 @@ class SMTP extends NotificationProvider {
|
|||
pass: notification.smtpPassword,
|
||||
};
|
||||
}
|
||||
// Lets start with default subject and empty string for custom one
|
||||
let subject = msg;
|
||||
|
||||
// Change the subject if:
|
||||
// - The msg ends with "Testing" or
|
||||
// - Actual Up/Down Notification
|
||||
if ((monitorJSON && heartbeatJSON) || msg.endsWith("Testing")) {
|
||||
let customSubject = "";
|
||||
|
||||
// Our subject cannot end with whitespace it's often raise spam score
|
||||
// Once I got "Cannot read property 'trim' of undefined", better be safe than sorry
|
||||
if (notification.customSubject) {
|
||||
customSubject = notification.customSubject.trim();
|
||||
}
|
||||
|
||||
// If custom subject is not empty, change subject for notification
|
||||
if (customSubject !== "") {
|
||||
|
||||
// Replace "MACROS" with corresponding variable
|
||||
let replaceName = new RegExp("{{NAME}}", "g");
|
||||
let replaceHostnameOrURL = new RegExp("{{HOSTNAME_OR_URL}}", "g");
|
||||
let replaceStatus = new RegExp("{{STATUS}}", "g");
|
||||
|
||||
// Lets start with dummy values to simplify code
|
||||
let monitorName = "Test";
|
||||
let monitorHostnameOrURL = "testing.hostname";
|
||||
let serviceStatus = "⚠️ Test";
|
||||
|
||||
if (monitorJSON !== null) {
|
||||
monitorName = monitorJSON["name"];
|
||||
|
||||
if (monitorJSON["type"] === "http" || monitorJSON["type"] === "keyword") {
|
||||
monitorHostnameOrURL = monitorJSON["url"];
|
||||
} else {
|
||||
monitorHostnameOrURL = monitorJSON["hostname"];
|
||||
}
|
||||
}
|
||||
|
||||
if (heartbeatJSON !== null) {
|
||||
serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up";
|
||||
}
|
||||
|
||||
// Break replace to one by line for better readability
|
||||
customSubject = customSubject.replace(replaceStatus, serviceStatus);
|
||||
customSubject = customSubject.replace(replaceName, monitorName);
|
||||
customSubject = customSubject.replace(replaceHostnameOrURL, monitorHostnameOrURL);
|
||||
|
||||
subject = customSubject;
|
||||
}
|
||||
}
|
||||
|
||||
let transporter = nodemailer.createTransport(config);
|
||||
|
||||
|
@ -34,7 +85,7 @@ class SMTP extends NotificationProvider {
|
|||
cc: notification.smtpCC,
|
||||
bcc: notification.smtpBCC,
|
||||
to: notification.smtpTo,
|
||||
subject: msg,
|
||||
subject: subject,
|
||||
text: bodyTextContent,
|
||||
tls: {
|
||||
rejectUnauthorized: notification.smtpIgnoreTLSError || false,
|
||||
|
|
|
@ -87,7 +87,7 @@ class Teams extends NotificationProvider {
|
|||
};
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
if (heartbeatJSON == null) {
|
||||
|
|
|
@ -6,7 +6,7 @@ class Telegram extends NotificationProvider {
|
|||
name = "telegram";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
await axios.get(`https://api.telegram.org/bot${notification.telegramBotToken}/sendMessage`, {
|
||||
|
|
|
@ -7,7 +7,7 @@ class Webhook extends NotificationProvider {
|
|||
name = "webhook";
|
||||
|
||||
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
|
||||
let okMsg = "Sent Successfully. ";
|
||||
let okMsg = "Sent Successfully.";
|
||||
|
||||
try {
|
||||
let data = {
|
||||
|
|
|
@ -5,7 +5,9 @@ const Gotify = require("./notification-providers/gotify");
|
|||
const Line = require("./notification-providers/line");
|
||||
const LunaSea = require("./notification-providers/lunasea");
|
||||
const Mattermost = require("./notification-providers/mattermost");
|
||||
const Matrix = require("./notification-providers/matrix");
|
||||
const Octopush = require("./notification-providers/octopush");
|
||||
const PromoSMS = require("./notification-providers/promosms");
|
||||
const Pushbullet = require("./notification-providers/pushbullet");
|
||||
const Pushover = require("./notification-providers/pushover");
|
||||
const Pushy = require("./notification-providers/pushy");
|
||||
|
@ -16,6 +18,9 @@ const SMTP = require("./notification-providers/smtp");
|
|||
const Teams = require("./notification-providers/teams");
|
||||
const Telegram = require("./notification-providers/telegram");
|
||||
const Webhook = require("./notification-providers/webhook");
|
||||
const Feishu = require("./notification-providers/feishu");
|
||||
const AliyunSms = require("./notification-providers/aliyun-sms");
|
||||
const DingDing = require("./notification-providers/dingding");
|
||||
|
||||
class Notification {
|
||||
|
||||
|
@ -28,13 +33,18 @@ class Notification {
|
|||
|
||||
const list = [
|
||||
new Apprise(),
|
||||
new AliyunSms(),
|
||||
new DingDing(),
|
||||
new Discord(),
|
||||
new Teams(),
|
||||
new Gotify(),
|
||||
new Line(),
|
||||
new LunaSea(),
|
||||
new Feishu(),
|
||||
new Mattermost(),
|
||||
new Matrix(),
|
||||
new Octopush(),
|
||||
new PromoSMS(),
|
||||
new Pushbullet(),
|
||||
new Pushover(),
|
||||
new Pushy(),
|
||||
|
|
|
@ -4,10 +4,7 @@ const net = require("net");
|
|||
const spawn = require("child_process").spawn;
|
||||
const events = require("events");
|
||||
const fs = require("fs");
|
||||
const WIN = /^win/.test(process.platform);
|
||||
const LIN = /^linux/.test(process.platform);
|
||||
const MAC = /^darwin/.test(process.platform);
|
||||
const FBSD = /^freebsd/.test(process.platform);
|
||||
const util = require("./util-server");
|
||||
|
||||
module.exports = Ping;
|
||||
|
||||
|
@ -23,12 +20,12 @@ function Ping(host, options) {
|
|||
|
||||
const timeout = 10;
|
||||
|
||||
if (WIN) {
|
||||
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 (LIN) {
|
||||
} else if (util.LIN) {
|
||||
this._bin = "/bin/ping";
|
||||
|
||||
const defaultArgs = [ "-n", "-w", timeout, "-c", "1", host ];
|
||||
|
@ -40,7 +37,7 @@ function Ping(host, options) {
|
|||
this._args = (options.args) ? options.args : defaultArgs;
|
||||
this._regmatch = /=([0-9.]+?) ms/;
|
||||
|
||||
} else if (MAC) {
|
||||
} else if (util.MAC) {
|
||||
|
||||
if (net.isIPv6(host) || options.ipv6) {
|
||||
this._bin = "/sbin/ping6";
|
||||
|
@ -51,7 +48,7 @@ function Ping(host, options) {
|
|||
this._args = (options.args) ? options.args : [ "-n", "-t", timeout, "-c", "1", host ];
|
||||
this._regmatch = /=([0-9.]+?) ms/;
|
||||
|
||||
} else if (FBSD) {
|
||||
} else if (util.FBSD) {
|
||||
this._bin = "/sbin/ping";
|
||||
|
||||
const defaultArgs = [ "-n", "-t", timeout, "-c", "1", host ];
|
||||
|
@ -101,6 +98,9 @@ Ping.prototype.send = function (callback) {
|
|||
});
|
||||
|
||||
this._ping.stdout.on("data", function (data) { // log stdout
|
||||
if (util.WIN) {
|
||||
data = convertOutput(data);
|
||||
}
|
||||
this._stdout = (this._stdout || "") + data;
|
||||
});
|
||||
|
||||
|
@ -112,6 +112,9 @@ Ping.prototype.send = function (callback) {
|
|||
});
|
||||
|
||||
this._ping.stderr.on("data", function (data) { // log stderr
|
||||
if (util.WIN) {
|
||||
data = convertOutput(data);
|
||||
}
|
||||
this._stderr = (this._stderr || "") + data;
|
||||
});
|
||||
|
||||
|
@ -157,3 +160,19 @@ Ping.prototype.start = function (callback) {
|
|||
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 data
|
||||
* @returns {string}
|
||||
*/
|
||||
function convertOutput(data) {
|
||||
if (util.WIN) {
|
||||
if (data) {
|
||||
return util.convertToUTF8(data);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ const commonLabels = [
|
|||
"monitor_url",
|
||||
"monitor_hostname",
|
||||
"monitor_port",
|
||||
]
|
||||
];
|
||||
|
||||
const monitor_cert_days_remaining = new PrometheusClient.Gauge({
|
||||
name: "monitor_cert_days_remaining",
|
||||
|
@ -41,45 +41,46 @@ class Prometheus {
|
|||
monitor_url: monitor.url,
|
||||
monitor_hostname: monitor.hostname,
|
||||
monitor_port: monitor.port
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
update(heartbeat, tlsInfo) {
|
||||
|
||||
if (typeof tlsInfo !== "undefined") {
|
||||
try {
|
||||
let is_valid = 0
|
||||
let is_valid = 0;
|
||||
if (tlsInfo.valid == true) {
|
||||
is_valid = 1
|
||||
is_valid = 1;
|
||||
} else {
|
||||
is_valid = 0
|
||||
is_valid = 0;
|
||||
}
|
||||
monitor_cert_is_valid.set(this.monitorLabelValues, is_valid)
|
||||
monitor_cert_is_valid.set(this.monitorLabelValues, is_valid);
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
try {
|
||||
monitor_cert_days_remaining.set(this.monitorLabelValues, tlsInfo.certInfo.daysRemaining)
|
||||
monitor_cert_days_remaining.set(this.monitorLabelValues, tlsInfo.certInfo.daysRemaining);
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
monitor_status.set(this.monitorLabelValues, heartbeat.status)
|
||||
monitor_status.set(this.monitorLabelValues, heartbeat.status);
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof heartbeat.ping === "number") {
|
||||
monitor_response_time.set(this.monitorLabelValues, heartbeat.ping)
|
||||
monitor_response_time.set(this.monitorLabelValues, heartbeat.ping);
|
||||
} else {
|
||||
// Is it good?
|
||||
monitor_response_time.set(this.monitorLabelValues, -1)
|
||||
monitor_response_time.set(this.monitorLabelValues, -1);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,4 +88,4 @@ class Prometheus {
|
|||
|
||||
module.exports = {
|
||||
Prometheus
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@ const server = require("../server");
|
|||
const apicache = require("../modules/apicache");
|
||||
const Monitor = require("../model/monitor");
|
||||
const dayjs = require("dayjs");
|
||||
const { UP } = require("../../src/util");
|
||||
const { UP, flipStatus, debug } = require("../../src/util");
|
||||
let router = express.Router();
|
||||
|
||||
let cache = apicache.middleware;
|
||||
|
@ -18,9 +18,10 @@ router.get("/api/entry-page", async (_, response) => {
|
|||
|
||||
router.get("/api/push/:pushToken", async (request, response) => {
|
||||
try {
|
||||
|
||||
let pushToken = request.params.pushToken;
|
||||
let msg = request.query.msg || "OK";
|
||||
let ping = request.query.ping;
|
||||
let ping = request.query.ping || null;
|
||||
|
||||
let monitor = await R.findOne("monitor", " push_token = ? AND active = 1 ", [
|
||||
pushToken
|
||||
|
@ -30,12 +31,40 @@ router.get("/api/push/:pushToken", async (request, response) => {
|
|||
throw new Error("Monitor not found or not active.");
|
||||
}
|
||||
|
||||
const previousHeartbeat = await R.getRow(`
|
||||
SELECT status, time FROM heartbeat
|
||||
WHERE id = (select MAX(id) from heartbeat where monitor_id = ?)
|
||||
`, [
|
||||
monitor.id
|
||||
]);
|
||||
|
||||
let status = UP;
|
||||
if (monitor.isUpsideDown()) {
|
||||
status = flipStatus(status);
|
||||
}
|
||||
|
||||
let isFirstBeat = true;
|
||||
let previousStatus = status;
|
||||
let duration = 0;
|
||||
|
||||
let bean = R.dispense("heartbeat");
|
||||
bean.monitor_id = monitor.id;
|
||||
bean.time = R.isoDateTime(dayjs.utc());
|
||||
bean.status = UP;
|
||||
|
||||
if (previousHeartbeat) {
|
||||
isFirstBeat = false;
|
||||
previousStatus = previousHeartbeat.status;
|
||||
duration = dayjs(bean.time).diff(dayjs(previousHeartbeat.time), "second");
|
||||
}
|
||||
|
||||
debug("PreviousStatus: " + previousStatus);
|
||||
debug("Current Status: " + status);
|
||||
|
||||
bean.important = Monitor.isImportantBeat(isFirstBeat, previousStatus, status);
|
||||
bean.monitor_id = monitor.id;
|
||||
bean.status = status;
|
||||
bean.msg = msg;
|
||||
bean.ping = ping;
|
||||
bean.duration = duration;
|
||||
|
||||
await R.store(bean);
|
||||
|
||||
|
@ -45,6 +74,11 @@ router.get("/api/push/:pushToken", async (request, response) => {
|
|||
response.json({
|
||||
ok: true,
|
||||
});
|
||||
|
||||
if (bean.important) {
|
||||
await Monitor.sendNotification(isFirstBeat, monitor, bean);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
response.json({
|
||||
ok: false,
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
console.log("Welcome to Uptime Kuma");
|
||||
const args = require("args-parser")(process.argv);
|
||||
const { sleep, debug, getRandomInt, genSecret } = require("../src/util");
|
||||
|
||||
debug(args);
|
||||
|
||||
if (! process.env.NODE_ENV) {
|
||||
process.env.NODE_ENV = "production";
|
||||
}
|
||||
|
||||
console.log("Node Env: " + process.env.NODE_ENV);
|
||||
// Demo Mode?
|
||||
const demoMode = args["demo"] || false;
|
||||
exports.demoMode = demoMode;
|
||||
|
||||
const { sleep, debug, getRandomInt, genSecret } = require("../src/util");
|
||||
console.log("Node Env: " + process.env.NODE_ENV);
|
||||
|
||||
console.log("Importing Node libraries");
|
||||
const fs = require("fs");
|
||||
|
@ -37,7 +43,7 @@ console.log("Importing this project modules");
|
|||
debug("Importing Monitor");
|
||||
const Monitor = require("./model/monitor");
|
||||
debug("Importing Settings");
|
||||
const { getSettings, setSettings, setting, initJWTSecret, checkLogin } = require("./util-server");
|
||||
const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest, FBSD } = require("./util-server");
|
||||
|
||||
debug("Importing Notification");
|
||||
const { Notification } = require("./notification");
|
||||
|
@ -50,22 +56,33 @@ const { basicAuth } = require("./auth");
|
|||
const { login } = require("./auth");
|
||||
const passwordHash = require("./password-hash");
|
||||
|
||||
const args = require("args-parser")(process.argv);
|
||||
|
||||
const checkVersion = require("./check-version");
|
||||
console.info("Version: " + checkVersion.version);
|
||||
|
||||
// If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available and the unspecified IPv4 address (0.0.0.0) otherwise.
|
||||
// Dual-stack support for (::)
|
||||
const hostname = process.env.HOST || args.host;
|
||||
const port = parseInt(process.env.PORT || args.port || 3001);
|
||||
let hostname = process.env.UPTIME_KUMA_HOST || args.host;
|
||||
|
||||
// Also read HOST if not FreeBSD, as HOST is a system environment variable in FreeBSD
|
||||
if (!hostname && !FBSD) {
|
||||
hostname = process.env.HOST;
|
||||
}
|
||||
|
||||
if (hostname) {
|
||||
console.log("Custom hostname: " + hostname);
|
||||
}
|
||||
|
||||
const port = parseInt(process.env.UPTIME_KUMA_PORT || process.env.PORT || args.port || 3001);
|
||||
|
||||
// SSL
|
||||
const sslKey = process.env.SSL_KEY || args["ssl-key"] || undefined;
|
||||
const sslCert = process.env.SSL_CERT || args["ssl-cert"] || undefined;
|
||||
const sslKey = process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || args["ssl-key"] || undefined;
|
||||
const sslCert = process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || args["ssl-cert"] || undefined;
|
||||
|
||||
// Demo Mode?
|
||||
const demoMode = args["demo"] || false;
|
||||
/**
|
||||
* Run unit test after the server is ready
|
||||
* @type {boolean}
|
||||
*/
|
||||
const testMode = !!args["test"] || false;
|
||||
|
||||
if (demoMode) {
|
||||
console.log("==== Demo Mode ====");
|
||||
|
@ -91,7 +108,7 @@ const io = new Server(server);
|
|||
module.exports.io = io;
|
||||
|
||||
// Must be after io instantiation
|
||||
const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList } = require("./client");
|
||||
const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo } = require("./client");
|
||||
const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler");
|
||||
|
||||
app.use(express.json());
|
||||
|
@ -181,10 +198,7 @@ exports.entryPage = "dashboard";
|
|||
console.log("Adding socket handler");
|
||||
io.on("connection", async (socket) => {
|
||||
|
||||
socket.emit("info", {
|
||||
version: checkVersion.version,
|
||||
latestVersion: checkVersion.latestVersion,
|
||||
});
|
||||
sendInfo(socket);
|
||||
|
||||
totalClient++;
|
||||
|
||||
|
@ -871,6 +885,8 @@ exports.entryPage = "dashboard";
|
|||
msg: "Saved"
|
||||
});
|
||||
|
||||
sendInfo(socket);
|
||||
|
||||
} catch (e) {
|
||||
callback({
|
||||
ok: false,
|
||||
|
@ -1043,6 +1059,10 @@ exports.entryPage = "dashboard";
|
|||
notificationIDList: {},
|
||||
};
|
||||
|
||||
if (monitorListData[i].pushToken) {
|
||||
monitor.pushToken = monitorListData[i].pushToken;
|
||||
}
|
||||
|
||||
let bean = R.dispense("monitor");
|
||||
|
||||
let notificationIDList = monitor.notificationIDList;
|
||||
|
@ -1223,6 +1243,10 @@ exports.entryPage = "dashboard";
|
|||
}
|
||||
startMonitors();
|
||||
checkVersion.startInterval();
|
||||
|
||||
if (testMode) {
|
||||
startUnitTest();
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
||||
|
|
|
@ -5,6 +5,15 @@ const { debug } = require("../src/util");
|
|||
const passwordHash = require("./password-hash");
|
||||
const dayjs = require("dayjs");
|
||||
const { Resolver } = require("dns");
|
||||
const child_process = require("child_process");
|
||||
const iconv = require("iconv-lite");
|
||||
const chardet = require("chardet");
|
||||
|
||||
// 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);
|
||||
|
||||
/**
|
||||
* Init or reset JWT secret
|
||||
|
@ -292,3 +301,33 @@ exports.checkLogin = (socket) => {
|
|||
throw new Error("You are not logged in.");
|
||||
}
|
||||
};
|
||||
|
||||
exports.startUnitTest = async () => {
|
||||
console.log("Starting unit test...");
|
||||
const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm";
|
||||
const child = child_process.spawn(npm, ["run", "jest"]);
|
||||
|
||||
child.stdout.on("data", (data) => {
|
||||
console.log(data.toString());
|
||||
});
|
||||
|
||||
child.stderr.on("data", (data) => {
|
||||
console.log(data.toString());
|
||||
});
|
||||
|
||||
child.on("close", function (code) {
|
||||
console.log("Jest exit code: " + code);
|
||||
process.exit(code);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param body : Buffer
|
||||
* @returns {string}
|
||||
*/
|
||||
exports.convertToUTF8 = (body) => {
|
||||
const guessEncoding = chardet.detect(body);
|
||||
debug("Guess Encoding: " + guessEncoding);
|
||||
const str = iconv.decode(body, guessEncoding);
|
||||
return str.toString();
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
@import "node_modules/bootstrap/scss/bootstrap";
|
||||
|
||||
#app {
|
||||
font-family: 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;
|
||||
font-family: BlinkMacSystemFont, segoe ui, Roboto, helvetica neue, Arial, noto sans, sans-serif, apple color emoji, segoe ui emoji, segoe ui symbol, noto color emoji;
|
||||
}
|
||||
|
||||
h1 {
|
||||
|
@ -321,7 +321,7 @@ h2 {
|
|||
.item {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
padding: 14px 15px;
|
||||
padding: 13px 15px 10px 15px;
|
||||
border-radius: 10px;
|
||||
transition: all ease-in-out 0.15s;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ export default {
|
|||
beatMargin: 4,
|
||||
move: false,
|
||||
maxBeat: -1,
|
||||
};
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
|
@ -69,12 +69,12 @@ export default {
|
|||
if (start < 0) {
|
||||
// Add empty placeholder
|
||||
for (let i = start; i < 0; i++) {
|
||||
placeholders.push(0);
|
||||
placeholders.push(0)
|
||||
}
|
||||
start = 0;
|
||||
}
|
||||
|
||||
return placeholders.concat(this.beatList.slice(start));
|
||||
return placeholders.concat(this.beatList.slice(start))
|
||||
},
|
||||
|
||||
wrapStyle() {
|
||||
|
@ -84,7 +84,7 @@ export default {
|
|||
return {
|
||||
padding: `${topBottom}px ${leftRight}px`,
|
||||
width: "100%",
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
barStyle() {
|
||||
|
@ -94,12 +94,12 @@ export default {
|
|||
return {
|
||||
transition: "all ease-in-out 0.25s",
|
||||
transform: `translateX(${width}px)`,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
return {
|
||||
transform: "translateX(0)",
|
||||
};
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
@ -109,7 +109,7 @@ export default {
|
|||
height: this.beatHeight + "px",
|
||||
margin: this.beatMargin + "px",
|
||||
"--hover-scale": this.hoverScale,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
@ -120,7 +120,7 @@ export default {
|
|||
|
||||
setTimeout(() => {
|
||||
this.move = false;
|
||||
}, 300);
|
||||
}, 300)
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
|
@ -162,7 +162,7 @@ export default {
|
|||
methods: {
|
||||
resize() {
|
||||
if (this.$refs.wrap) {
|
||||
this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2));
|
||||
this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2))
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -170,7 +170,7 @@ export default {
|
|||
return `${this.$root.datetime(beat.time)} - ${beat.msg}`;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -183,9 +183,6 @@ export default {
|
|||
}
|
||||
|
||||
.hp-bar-big {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.beat {
|
||||
display: inline-block;
|
||||
background-color: $primary;
|
||||
|
|
|
@ -60,7 +60,6 @@ export default {
|
|||
|
||||
this.$root.login(this.username, this.password, this.token, (res) => {
|
||||
this.processing = false;
|
||||
console.log(res);
|
||||
|
||||
if (res.tokenRequired) {
|
||||
this.tokenRequired = true;
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
<div class="list-header">
|
||||
<div class="placeholder"></div>
|
||||
<div class="search-wrapper">
|
||||
<a v-if="!searchText" class="search-icon">
|
||||
<a v-if="searchText == ''" class="search-icon">
|
||||
<font-awesome-icon icon="search" />
|
||||
</a>
|
||||
<a v-if="searchText" class="search-icon" @click="clearSearchText">
|
||||
<a v-if="searchText != ''" class="search-icon" @click="clearSearchText">
|
||||
<font-awesome-icon icon="times" />
|
||||
</a>
|
||||
<input v-model="searchText" class="form-control search-input" :placeholder="$t('Search...')" />
|
||||
|
@ -19,21 +19,21 @@
|
|||
|
||||
<router-link v-for="(item, index) in sortedMonitorList" :key="index" :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }">
|
||||
<div class="row">
|
||||
<div class="col-6 col-md-8 small-padding" :class="{ 'monitorItem': $root.userHeartbeatBar === 'bottom' || $root.userHeartbeatBar === 'none' }">
|
||||
<div class="col-9 col-md-8 small-padding" :class="{ 'monitorItem': $root.userHeartbeatBar == 'bottom' || $root.userHeartbeatBar == 'none' }">
|
||||
<div class="info">
|
||||
<Uptime :monitor="item" type="24" :pill="true" />
|
||||
<span class="ms-1">{{ item.name }}</span>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div class="tags">
|
||||
<Tag v-for="tag in item.tags" :key="tag" :item="tag" :size="'sm'" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="$root.userHeartbeatBar === 'normal'" :key="$root.userHeartbeatBar" class="col-6 col-md-4 small-padding">
|
||||
<div v-show="$root.userHeartbeatBar == 'normal'" :key="$root.userHeartbeatBar" class="col-3 col-md-4">
|
||||
<HeartbeatBar size="small" :monitor-id="item.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="$root.userHeartbeatBar === 'bottom'" class="row">
|
||||
<div v-if="$root.userHeartbeatBar == 'bottom'" class="row">
|
||||
<div class="col-12">
|
||||
<HeartbeatBar size="small" :monitor-id="item.id" />
|
||||
</div>
|
||||
|
@ -47,6 +47,7 @@
|
|||
import HeartbeatBar from "../components/HeartbeatBar.vue";
|
||||
import Uptime from "../components/Uptime.vue";
|
||||
import Tag from "../components/Tag.vue";
|
||||
import { getMonitorRelativeURL } from "../util.ts";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -95,7 +96,7 @@ export default {
|
|||
|
||||
// Simple filter by search text
|
||||
// finds monitor name, tag name or tag value
|
||||
if (this.searchText) {
|
||||
if (this.searchText != "") {
|
||||
const loweredSearchText = this.searchText.toLowerCase();
|
||||
result = result.filter(monitor => {
|
||||
return monitor.name.toLowerCase().includes(loweredSearchText)
|
||||
|
@ -109,7 +110,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
monitorURL(id) {
|
||||
return "/dashboard/" + id;
|
||||
return getMonitorRelativeURL(id);
|
||||
},
|
||||
clearSearchText() {
|
||||
this.searchText = "";
|
||||
|
|
|
@ -68,11 +68,11 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Modal } from "bootstrap"
|
||||
import { ucfirst } from "../util.ts"
|
||||
import { Modal } from "bootstrap";
|
||||
import { ucfirst } from "../util.ts";
|
||||
|
||||
import Confirm from "./Confirm.vue";
|
||||
import NotificationFormList from "./notifications"
|
||||
import NotificationFormList from "./notifications";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -93,41 +93,40 @@ export default {
|
|||
isDefault: false,
|
||||
// Do not set default value here, please scroll to show()
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
currentForm() {
|
||||
if (!this.notification.type) {
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
return NotificationFormList[this.notification.type]
|
||||
return NotificationFormList[this.notification.type];
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
"notification.type"(to, from) {
|
||||
let oldName;
|
||||
|
||||
if (from) {
|
||||
oldName = `My ${ucfirst(from)} Alert (1)`;
|
||||
oldName = this.getUniqueDefaultName(from);
|
||||
} else {
|
||||
oldName = "";
|
||||
}
|
||||
|
||||
if (! this.notification.name || this.notification.name === oldName) {
|
||||
this.notification.name = `My ${ucfirst(to)} Alert (1)`
|
||||
this.notification.name = this.getUniqueDefaultName(to);
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.modal = new Modal(this.$refs.modal)
|
||||
this.modal = new Modal(this.$refs.modal);
|
||||
},
|
||||
methods: {
|
||||
|
||||
deleteConfirm() {
|
||||
this.modal.hide();
|
||||
this.$refs.confirmDelete.show()
|
||||
this.$refs.confirmDelete.show();
|
||||
},
|
||||
|
||||
show(notificationID) {
|
||||
|
@ -146,19 +145,19 @@ export default {
|
|||
name: "",
|
||||
type: null,
|
||||
isDefault: false,
|
||||
}
|
||||
};
|
||||
|
||||
// Set Default value here
|
||||
this.notification.type = this.notificationTypes[0];
|
||||
}
|
||||
|
||||
this.modal.show()
|
||||
this.modal.show();
|
||||
},
|
||||
|
||||
submit() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("addNotification", this.notification, this.id, (res) => {
|
||||
this.$root.toastRes(res)
|
||||
this.$root.toastRes(res);
|
||||
this.processing = false;
|
||||
|
||||
if (res.ok) {
|
||||
|
@ -170,30 +169,45 @@ export default {
|
|||
}
|
||||
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
test() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("testNotification", this.notification, (res) => {
|
||||
this.$root.toastRes(res)
|
||||
this.$root.toastRes(res);
|
||||
this.processing = false;
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
deleteNotification() {
|
||||
this.processing = true;
|
||||
this.$root.getSocket().emit("deleteNotification", this.id, (res) => {
|
||||
this.$root.toastRes(res)
|
||||
this.$root.toastRes(res);
|
||||
this.processing = false;
|
||||
|
||||
if (res.ok) {
|
||||
this.modal.hide()
|
||||
this.modal.hide();
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @param {keyof NotificationFormList} notificationKey
|
||||
* @return {string}
|
||||
*/
|
||||
getUniqueDefaultName(notificationKey) {
|
||||
let index = 1;
|
||||
let name = "";
|
||||
do {
|
||||
name = this.$t("defaultNotificationName", {
|
||||
notification: this.$t(notificationKey).replace(/\(.+\)/, "").trim(),
|
||||
number: index++
|
||||
});
|
||||
} while (this.$root.notificationList.find(it => it.name === name));
|
||||
return name;
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -11,18 +11,18 @@ export default {
|
|||
computed: {
|
||||
color() {
|
||||
if (this.status === 0) {
|
||||
return "danger"
|
||||
return "danger";
|
||||
}
|
||||
|
||||
if (this.status === 1) {
|
||||
return "primary"
|
||||
return "primary";
|
||||
}
|
||||
|
||||
if (this.status === 2) {
|
||||
return "warning"
|
||||
return "warning";
|
||||
}
|
||||
|
||||
return "secondary"
|
||||
return "secondary";
|
||||
},
|
||||
|
||||
text() {
|
||||
|
@ -41,11 +41,11 @@ export default {
|
|||
return this.$t("Unknown");
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
span {
|
||||
width: 64px;
|
||||
min-width: 64px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<h4 class="mb-3">{{ $t("Tags") }}</h4>
|
||||
<div class="mb-3 p-1">
|
||||
<h4 class="mt-5 mb-3">{{ $t("Tags") }}</h4>
|
||||
<div v-if="selectedTags.length > 0" class="mb-2 p-1">
|
||||
<tag
|
||||
v-for="item in selectedTags"
|
||||
:key="item.id"
|
||||
|
@ -124,8 +124,8 @@
|
|||
import { Modal } from "bootstrap";
|
||||
import VueMultiselect from "vue-multiselect";
|
||||
import Tag from "../components/Tag.vue";
|
||||
import { useToast } from "vue-toastification"
|
||||
const toast = useToast()
|
||||
import { useToast } from "vue-toastification";
|
||||
const toast = useToast();
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -186,7 +186,7 @@ export default {
|
|||
color: "#7C3AED" },
|
||||
{ name: this.$t("Pink"),
|
||||
color: "#DB2777" },
|
||||
]
|
||||
];
|
||||
},
|
||||
validateDraftTag() {
|
||||
let nameInvalid = false;
|
||||
|
@ -227,7 +227,7 @@ export default {
|
|||
invalid,
|
||||
nameInvalid,
|
||||
valueInvalid,
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
@ -243,7 +243,7 @@ export default {
|
|||
if (res.ok) {
|
||||
this.existingTags = res.tags;
|
||||
} else {
|
||||
toast.error(res.msg)
|
||||
toast.error(res.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -277,7 +277,7 @@ export default {
|
|||
name: this.newDraftTag.select.name,
|
||||
value: this.newDraftTag.value,
|
||||
new: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Add new Tag
|
||||
|
@ -286,7 +286,7 @@ export default {
|
|||
name: this.newDraftTag.name.trim(),
|
||||
value: this.newDraftTag.value,
|
||||
new: true,
|
||||
})
|
||||
});
|
||||
}
|
||||
this.clearDraftTag();
|
||||
},
|
||||
|
@ -348,7 +348,7 @@ export default {
|
|||
if (tag.name == newTag.name && tag.color == newTag.color) {
|
||||
tag.id = newTagResult.id;
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
tagId = newTag.id;
|
||||
}
|
||||
|
|
|
@ -22,33 +22,33 @@ export default {
|
|||
return Math.round(this.$root.uptimeList[key] * 10000) / 100 + "%";
|
||||
}
|
||||
|
||||
return this.$t("notAvailableShort");
|
||||
return this.$t("notAvailableShort")
|
||||
},
|
||||
|
||||
color() {
|
||||
if (this.lastHeartBeat.status === 0) {
|
||||
return "danger";
|
||||
return "danger"
|
||||
}
|
||||
|
||||
if (this.lastHeartBeat.status === 1) {
|
||||
return "primary";
|
||||
return "primary"
|
||||
}
|
||||
|
||||
if (this.lastHeartBeat.status === 2) {
|
||||
return "warning";
|
||||
return "warning"
|
||||
}
|
||||
|
||||
return "secondary";
|
||||
return "secondary"
|
||||
},
|
||||
|
||||
lastHeartBeat() {
|
||||
if (this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
|
||||
return this.$root.lastHeartbeatList[this.monitor.id];
|
||||
return this.$root.lastHeartbeatList[this.monitor.id]
|
||||
}
|
||||
|
||||
return {
|
||||
status: -1,
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
className() {
|
||||
|
@ -59,7 +59,7 @@ export default {
|
|||
return "";
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
25
src/components/notifications/AliyunSms.vue
Normal file
25
src/components/notifications/AliyunSms.vue
Normal file
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="accessKeyId" class="form-label">{{ $t("AccessKeyId") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="accessKeyId" v-model="$parent.notification.accessKeyId" type="text" class="form-control" required>
|
||||
|
||||
<label for="secretAccessKey" class="form-label">{{ $t("SecretAccessKey") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="secretAccessKey" v-model="$parent.notification.secretAccessKey" type="text" class="form-control" required>
|
||||
|
||||
<label for="phonenumber" class="form-label">{{ $t("Phonenumber") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="phonenumber" v-model="$parent.notification.phonenumber" type="text" class="form-control" required>
|
||||
|
||||
<label for="templateCode" class="form-label">{{ $t("TemplateCode") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="templateCode" v-model="$parent.notification.templateCode" type="text" class="form-control" required>
|
||||
|
||||
<label for="signName" class="form-label">{{ $t("SignName") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="signName" v-model="$parent.notification.signName" type="text" class="form-control" required>
|
||||
|
||||
<div class="form-text">
|
||||
<p>Sms template must contain parameters: <br> <code>${name} ${time} ${status} ${msg}</code></p>
|
||||
<i18n-t tag="p" keypath="Read more:">
|
||||
<a href="https://help.aliyun.com/document_detail/101414.html" target="_blank">https://help.aliyun.com/document_detail/101414.html</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -1,20 +1,21 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="apprise-url" class="form-label">Apprise URL</label>
|
||||
<label for="apprise-url" class="form-label">{{ $t("Apprise URL") }}</label>
|
||||
<input id="apprise-url" v-model="$parent.notification.appriseURL" type="text" class="form-control" required>
|
||||
<div class="form-text">
|
||||
<p>Example: twilio://AccountSid:AuthToken@FromPhoneNo</p>
|
||||
<p>
|
||||
Read more: <a href="https://github.com/caronc/apprise/wiki#notification-services" target="_blank">https://github.com/caronc/apprise/wiki#notification-services</a>
|
||||
</p>
|
||||
<p>{{ $t("Example:", ["twilio://AccountSid:AuthToken@FromPhoneNo"]) }}</p>
|
||||
<i18n-t tag="p" keypath="Read more:">
|
||||
<a href="https://github.com/caronc/apprise/wiki#notification-services" target="_blank">https://github.com/caronc/apprise/wiki#notification-services</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<p>
|
||||
Status:
|
||||
<span v-if="appriseInstalled" class="text-primary">Apprise is installed</span>
|
||||
<span v-else class="text-danger">Apprise is not installed. <a href="https://github.com/caronc/apprise" target="_blank">Read more</a></span>
|
||||
</p>
|
||||
<i18n-t tag="p" keypath="Status:">
|
||||
<span v-if="appriseInstalled" class="text-primary">{{ $t("appriseInstalled") }}</span>
|
||||
<i18n-t v-else tag="span" keypath="appriseNotInstalled" class="text-danger">
|
||||
<a href="https://github.com/caronc/apprise" target="_blank">{{ $t("Read more") }}</a>
|
||||
</i18n-t>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -23,12 +24,12 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
appriseInstalled: false
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.$root.getSocket().emit("checkApprise", (installed) => {
|
||||
this.appriseInstalled = installed;
|
||||
})
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
16
src/components/notifications/DingDing.vue
Normal file
16
src/components/notifications/DingDing.vue
Normal file
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="WebHookUrl" class="form-label">{{ $t("WebHookUrl") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="WebHookUrl" v-model="$parent.notification.webHookUrl" type="text" class="form-control" required>
|
||||
|
||||
<label for="secretKey" class="form-label">{{ $t("SecretKey") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="secretKey" v-model="$parent.notification.secretKey" type="text" class="form-control" required>
|
||||
|
||||
<div class="form-text">
|
||||
<p>For safety, must use secret key</p>
|
||||
<i18n-t tag="p" keypath="Read more:">
|
||||
<a href="https://developers.dingtalk.com/document/robots/custom-robot-access" target="_blank">https://developers.dingtalk.com/document/robots/custom-robot-access</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -1,20 +1,19 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="discord-webhook-url" class="form-label">Discord Webhook URL</label>
|
||||
<label for="discord-webhook-url" class="form-label">{{ $t("Discord Webhook URL") }}</label>
|
||||
<input id="discord-webhook-url" v-model="$parent.notification.discordWebhookUrl" type="text" class="form-control" required autocomplete="false">
|
||||
<div class="form-text">
|
||||
You can get this by going to Server Settings -> Integrations -> Create Webhook
|
||||
{{ $t("wayToGetDiscordURL") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="discord-username" class="form-label">Bot Display Name</label>
|
||||
<label for="discord-username" class="form-label">{{ $t("Bot Display Name") }}</label>
|
||||
<input id="discord-username" v-model="$parent.notification.discordUsername" type="text" class="form-control" autocomplete="false" :placeholder="$root.appName">
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="discord-prefix-message" class="form-label">Prefix Custom Message</label>
|
||||
<input id="discord-prefix-message" v-model="$parent.notification.discordPrefixMessage" type="text" class="form-control" autocomplete="false" placeholder="Hello @everyone is...">
|
||||
<label for="discord-prefix-message" class="form-label">{{ $t("Prefix Custom Message") }}</label>
|
||||
<input id="discord-prefix-message" v-model="$parent.notification.discordPrefixMessage" type="text" class="form-control" autocomplete="false" :placeholder="$t('Hello @everyone is...')">
|
||||
</div>
|
||||
</template>
|
||||
|
|
15
src/components/notifications/Feishu.vue
Normal file
15
src/components/notifications/Feishu.vue
Normal file
|
@ -0,0 +1,15 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="Feishu-WebHookUrl" class="form-label">{{ $t("Feishu WebHookUrl") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="Feishu-WebHookUrl" v-model="$parent.notification.feishuWebHookUrl" type="text" class="form-control" required>
|
||||
<div class="form-text">
|
||||
<p><span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}</p>
|
||||
</div>
|
||||
<i18n-t tag="div" keypath="wayToGetTeamsURL" class="form-text">
|
||||
<a
|
||||
href="https://www.feishu.cn/hc/zh-CN/articles/360024984973"
|
||||
target="_blank"
|
||||
>{{ $t("here") }}</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</template>
|
|
@ -1,17 +1,17 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="gotify-application-token" class="form-label">Application Token</label>
|
||||
<label for="gotify-application-token" class="form-label">{{ $t("Application Token") }}</label>
|
||||
<HiddenInput id="gotify-application-token" v-model="$parent.notification.gotifyapplicationToken" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="gotify-server-url" class="form-label">Server URL</label>
|
||||
<label for="gotify-server-url" class="form-label">{{ $t("Server URL") }}</label>
|
||||
<div class="input-group mb-3">
|
||||
<input id="gotify-server-url" v-model="$parent.notification.gotifyserverurl" type="text" class="form-control" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="gotify-priority" class="form-label">Priority</label>
|
||||
<label for="gotify-priority" class="form-label">{{ $t("Priority") }}</label>
|
||||
<input id="gotify-priority" v-model="$parent.notification.gotifyPriority" type="number" class="form-control" required min="0" max="10" step="1">
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="line-channel-access-token" class="form-label">Channel access token</label>
|
||||
<label for="line-channel-access-token" class="form-label">{{ $t("Channel access token") }}</label>
|
||||
<HiddenInput id="line-channel-access-token" v-model="$parent.notification.lineChannelAccessToken" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
</div>
|
||||
<div class="form-text">
|
||||
Line Developers Console - <b>Basic Settings</b>
|
||||
</div>
|
||||
<i18n-t tag="div" keypath="lineDevConsoleTo" class="form-text">
|
||||
<b>{{ $t("Basic Settings") }}</b>
|
||||
</i18n-t>
|
||||
<div class="mb-3" style="margin-top: 12px;">
|
||||
<label for="line-user-id" class="form-label">User ID</label>
|
||||
<input id="line-user-id" v-model="$parent.notification.lineUserID" type="text" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-text">
|
||||
Line Developers Console - <b>Messaging API</b>
|
||||
</div>
|
||||
<div class="form-text" style="margin-top: 8px;">
|
||||
First access the <a href="https://developers.line.biz/console/" target="_blank">Line Developers Console</a>, create a provider and channel (Messaging API), then you can get the channel access token and user id from the above mentioned menu items.
|
||||
</div>
|
||||
<i18n-t tag="div" keypath="lineDevConsoleTo" class="form-text">
|
||||
<b>{{ $t("Messaging API") }}</b>
|
||||
</i18n-t>
|
||||
<i18n-t tag="div" keypath="wayToGetLineChannelToken" class="form-text" style="margin-top: 8px;">
|
||||
<a href="https://developers.line.biz/console/" target="_blank">{{ $t("Line Developers Console") }}</a>
|
||||
</i18n-t>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -25,5 +25,5 @@ export default {
|
|||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="lunasea-device" class="form-label">LunaSea Device ID<span style="color: red;"><sup>*</sup></span></label>
|
||||
<label for="lunasea-device" class="form-label">{{ $t("LunaSea Device ID") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="lunasea-device" v-model="$parent.notification.lunaseaDevice" type="text" class="form-control" required>
|
||||
<div class="form-text">
|
||||
<p><span style="color: red;"><sup>*</sup></span>Required</p>
|
||||
<p><span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
34
src/components/notifications/Matrix.vue
Normal file
34
src/components/notifications/Matrix.vue
Normal file
|
@ -0,0 +1,34 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="homeserver-url" class="form-label">Homeserver URL (with http(s):// and optionally port)</label><span style="color: red;"><sup>*</sup></span>
|
||||
<input id="homeserver-url" v-model="$parent.notification.homeserverUrl" type="text" class="form-control" :required="true">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="internal-room-id" class="form-label">Internal Room Id</label><span style="color: red;"><sup>*</sup></span>
|
||||
<input id="internal-room-id" v-model="$parent.notification.internalRoomId" type="text" class="form-control" required="true">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="access-token" class="form-label">Access Token</label><span style="color: red;"><sup>*</sup></span>
|
||||
<HiddenInput id="access-token" v-model="$parent.notification.accessToken" :required="true" autocomplete="one-time-code" :maxlength="500"></HiddenInput>
|
||||
</div>
|
||||
|
||||
<div class="form-text">
|
||||
<span style="color: red;"><sup>*</sup></span>Required
|
||||
<p style="margin-top: 8px;">
|
||||
You can find the internal room ID by looking in the advanced section of the room settings in your Matrix client. It should look like !QMdRCpUIfLwsfjxye6:home.server.
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
It is highly recommended you create a new user and do not use your own Matrix user's access token as it will allow full access to your account and all the rooms you joined. Instead, create a new user and only invite it to the room that you want to receive the notification in. You can get the access token by running <code>curl -XPOST -d '{"type": "m.login.password", "identifier": {"user": "botusername", "type": "m.id.user"}, "password": "passwordforuser"}' "https://home.server/_matrix/client/r0/login"</code>.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -1,32 +1,32 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="mattermost-webhook-url" class="form-label">Webhook URL<span style="color:red;"><sup>*</sup></span></label>
|
||||
<label for="mattermost-webhook-url" class="form-label">{{ $t("Webhook URL") }}<span style="color:red;"><sup>*</sup></span></label>
|
||||
<input id="mattermost-webhook-url" v-model="$parent.notification.mattermostWebhookUrl" type="text" class="form-control" required>
|
||||
<label for="mattermost-username" class="form-label">Username</label>
|
||||
<label for="mattermost-username" class="form-label">{{ $t("Username") }}</label>
|
||||
<input id="mattermost-username" v-model="$parent.notification.mattermostusername" type="text" class="form-control">
|
||||
<label for="mattermost-iconurl" class="form-label">Icon URL</label>
|
||||
<label for="mattermost-iconurl" class="form-label">{{ $t("Icon URL") }}</label>
|
||||
<input id="mattermost-iconurl" v-model="$parent.notification.mattermosticonurl" type="text" class="form-control">
|
||||
<label for="mattermost-iconemo" class="form-label">Icon Emoji</label>
|
||||
<label for="mattermost-iconemo" class="form-label">{{ $t("Icon Emoji") }}</label>
|
||||
<input id="mattermost-iconemo" v-model="$parent.notification.mattermosticonemo" type="text" class="form-control">
|
||||
<label for="mattermost-channel" class="form-label">Channel Name</label>
|
||||
<label for="mattermost-channel" class="form-label">{{ $t("Channel Name") }}</label>
|
||||
<input id="mattermost-channel-name" v-model="$parent.notification.mattermostchannel" type="text" class="form-control">
|
||||
<div class="form-text">
|
||||
<span style="color:red;"><sup>*</sup></span>Required
|
||||
<span style="color:red;"><sup>*</sup></span>{{ $t("Required") }}
|
||||
<i18n-t tag="p" keypath="aboutWebhooks" style="margin-top: 8px;">
|
||||
<a href="https://docs.mattermost.com/developer/webhooks-incoming.html" target="_blank">https://docs.mattermost.com/developer/webhooks-incoming.html</a>
|
||||
</i18n-t>
|
||||
<p style="margin-top: 8px;">
|
||||
More info about webhooks on: <a href="https://docs.mattermost.com/developer/webhooks-incoming.html" target="_blank">https://docs.mattermost.com/developer/webhooks-incoming.html</a>
|
||||
{{ $t("aboutMattermostChannelName") }}
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
You can override the default channel that webhook posts to by entering the channel name into "Channel Name" field. This needs to be enabled in Mattermost webhook settings. Ex: #other-channel
|
||||
{{ $t("aboutKumaURL") }}
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
If you leave the Uptime Kuma URL field blank, it will default to the Project Github page.
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
You can provide a link to a picture in "Icon URL" to override the default profile picture. Will not be used if Icon Emoji is set.
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
Emoji cheat sheet: <a href="https://www.webfx.com/tools/emoji-cheat-sheet/" target="_blank">https://www.webfx.com/tools/emoji-cheat-sheet/</a> Note: emoji takes preference over Icon URL.
|
||||
{{ $t("aboutIconURL") }}
|
||||
</p>
|
||||
<i18n-t tag="p" keypath="emojiCheatSheet" style="margin-top: 8px;">
|
||||
<a href="https://www.webfx.com/tools/emoji-cheat-sheet/" target="_blank">https://www.webfx.com/tools/emoji-cheat-sheet/</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,4 +1,14 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="octopush-version" class="form-label">Octopush API Version</label>
|
||||
<select id="octopush-version" v-model="$parent.notification.octopushVersion" class="form-select">
|
||||
<option value="2">Octopush (endpoint: api.octopush.com)</option>
|
||||
<option value="1">Legacy Octopush-DM (endpoint: www.octopush-dm.com)</option>
|
||||
</select>
|
||||
<div class="form-text">
|
||||
Do you use the legacy version of Octopush (2011-2020) or the new version?
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="octopush-key" class="form-label">API KEY</label>
|
||||
<HiddenInput id="octopush-key" v-model="$parent.notification.octopushAPIKey" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
|
@ -6,27 +16,27 @@
|
|||
<input id="octopush-login" v-model="$parent.notification.octopushLogin" type="text" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="octopush-type-sms" class="form-label">SMS Type</label>
|
||||
<label for="octopush-type-sms" class="form-label">{{ $t("SMS Type") }}</label>
|
||||
<select id="octopush-type-sms" v-model="$parent.notification.octopushSMSType" class="form-select">
|
||||
<option value="sms_premium">Premium (Fast - recommended for alerting)</option>
|
||||
<option value="sms_low_cost">Low Cost (Slow, sometimes blocked by operator)</option>
|
||||
<option value="sms_premium">{{ $t("octopushTypePremium") }}</option>
|
||||
<option value="sms_low_cost">{{ $t("octopushTypeLowCost") }}</option>
|
||||
</select>
|
||||
<div class="form-text">
|
||||
Check octopush prices <a href="https://octopush.com/tarifs-sms-international/" target="_blank">https://octopush.com/tarifs-sms-international/</a>.
|
||||
</div>
|
||||
<i18n-t tag="div" keypath="Check octopush prices" class="form-text">
|
||||
<a href="https://octopush.com/tarifs-sms-international/" target="_blank">https://octopush.com/tarifs-sms-international/</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="octopush-phone-number" class="form-label">Phone number (intl format, eg : +33612345678) </label>
|
||||
<label for="octopush-phone-number" class="form-label">{{ $t("octopushPhoneNumber") }}</label>
|
||||
<input id="octopush-phone-number" v-model="$parent.notification.octopushPhoneNumber" type="text" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="octopush-sender-name" class="form-label">SMS Sender Name : 3-11 alphanumeric characters and space (a-zA-Z0-9)</label>
|
||||
<label for="octopush-sender-name" class="form-label">{{ $t("octopushSMSSender") }}</label>
|
||||
<input id="octopush-sender-name" v-model="$parent.notification.octopushSenderName" type="text" minlength="3" maxlength="11" class="form-control">
|
||||
</div>
|
||||
|
||||
<p style="margin-top: 8px;">
|
||||
More info on: <a href="https://octopush.com/api-sms-documentation/envoi-de-sms/" target="_blank">https://octopush.com/api-sms-documentation/envoi-de-sms/</a>
|
||||
</p>
|
||||
<i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
|
||||
<a href="https://octopush.com/api-sms-documentation/envoi-de-sms/" target="_blank">https://octopush.com/api-sms-documentation/envoi-de-sms/</a>
|
||||
</i18n-t>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -36,5 +46,5 @@ export default {
|
|||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
39
src/components/notifications/PromoSMS.vue
Normal file
39
src/components/notifications/PromoSMS.vue
Normal file
|
@ -0,0 +1,39 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="promosms-login" class="form-label">API LOGIN</label>
|
||||
<input id="promosms-login" v-model="$parent.notification.promosmsLogin" type="text" class="form-control" required>
|
||||
<label for="promosms-key" class="form-label">API PASSWORD</label>
|
||||
<HiddenInput id="promosms-key" v-model="$parent.notification.promosmsPassword" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="promosms-type-sms" class="form-label">{{ $t("SMS Type") }}</label>
|
||||
<select id="promosms-type-sms" v-model="$parent.notification.promosmsSMSType" class="form-select">
|
||||
<option value="0">{{ $t("promosmsTypeFlash") }}</option>
|
||||
<option value="1">{{ $t("promosmsTypeEco") }}</option>
|
||||
<option value="2">{{ $t("promosmsTypeFull") }}</option>
|
||||
<option value="3">{{ $t("promosmsTypeSpeed") }}</option>
|
||||
</select>
|
||||
<i18n-t tag="div" keypath="Check PromoSMS prices" class="form-text">
|
||||
<a href="https://promosms.com/cennik/" target="_blank">https://promosms.com/cennik/</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="promosms-phone-number" class="form-label">{{ $t("promosmsPhoneNumber") }}</label>
|
||||
<input id="promosms-phone-number" v-model="$parent.notification.promosmsPhoneNumber" type="text" class="form-control" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="promosms-sender-name" class="form-label">{{ $t("promosmsSMSSender") }}</label>
|
||||
<input id="promosms-sender-name" v-model="$parent.notification.promosmsSenderName" type="text" minlength="3" maxlength="11" class="form-control">
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HiddenInput from "../HiddenInput.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -1,12 +1,12 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="pushbullet-access-token" class="form-label">Access Token</label>
|
||||
<label for="pushbullet-access-token" class="form-label">{{ $t("Access Token") }}</label>
|
||||
<HiddenInput id="pushbullet-access-token" v-model="$parent.notification.pushbulletAccessToken" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
</div>
|
||||
|
||||
<p style="margin-top: 8px;">
|
||||
More info on: <a href="https://docs.pushbullet.com" target="_blank">https://docs.pushbullet.com</a>
|
||||
</p>
|
||||
<i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
|
||||
<a href="https://docs.pushbullet.com" target="_blank">https://docs.pushbullet.com</a>
|
||||
</i18n-t>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -16,5 +16,5 @@ export default {
|
|||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="pushover-user" class="form-label">User Key<span style="color: red;"><sup>*</sup></span></label>
|
||||
<label for="pushover-user" class="form-label">{{ $t("User Key") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<HiddenInput id="pushover-user" v-model="$parent.notification.pushoveruserkey" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
<label for="pushover-app-token" class="form-label">Application Token<span style="color: red;"><sup>*</sup></span></label>
|
||||
<label for="pushover-app-token" class="form-label">{{ $t("Application Token") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<HiddenInput id="pushover-app-token" v-model="$parent.notification.pushoverapptoken" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
<label for="pushover-device" class="form-label">Device</label>
|
||||
<label for="pushover-device" class="form-label">{{ $t("Device") }}</label>
|
||||
<input id="pushover-device" v-model="$parent.notification.pushoverdevice" type="text" class="form-control">
|
||||
<label for="pushover-device" class="form-label">Message Title</label>
|
||||
<label for="pushover-device" class="form-label">{{ $t("Message Title") }}</label>
|
||||
<input id="pushover-title" v-model="$parent.notification.pushovertitle" type="text" class="form-control">
|
||||
<label for="pushover-priority" class="form-label">Priority</label>
|
||||
<label for="pushover-priority" class="form-label">{{ $t("Priority") }}</label>
|
||||
<select id="pushover-priority" v-model="$parent.notification.pushoverpriority" class="form-select">
|
||||
<option>-2</option>
|
||||
<option>-1</option>
|
||||
|
@ -16,7 +16,7 @@
|
|||
<option>1</option>
|
||||
<option>2</option>
|
||||
</select>
|
||||
<label for="pushover-sound" class="form-label">Notification Sound</label>
|
||||
<label for="pushover-sound" class="form-label">{{ $t("Notification Sound") }}</label>
|
||||
<select id="pushover-sound" v-model="$parent.notification.pushoversounds" class="form-select">
|
||||
<option>pushover</option>
|
||||
<option>bike</option>
|
||||
|
@ -42,15 +42,15 @@
|
|||
<option>none</option>
|
||||
</select>
|
||||
<div class="form-text">
|
||||
<span style="color: red;"><sup>*</sup></span>Required
|
||||
<span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}
|
||||
<i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
|
||||
<a href="https://pushover.net/api" target="_blank">https://pushover.net/api</a>
|
||||
</i18n-t>
|
||||
<p style="margin-top: 8px;">
|
||||
More info on: <a href="https://pushover.net/api" target="_blank">https://pushover.net/api</a>
|
||||
{{ $t("pushoverDesc1") }}
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
Emergency priority (2) has default 30 second timeout between retries and will expire after 1 hour.
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
If you want to send notifications to different devices, fill out Device field.
|
||||
{{ $t("pushoverDesc2") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
<HiddenInput id="pushy-user-key" v-model="$parent.notification.pushyToken" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin-top: 8px;">
|
||||
More info on: <a href="https://pushy.me/docs/api/send-notifications" target="_blank">https://pushy.me/docs/api/send-notifications</a>
|
||||
</p>
|
||||
<i18n-t tag="p" keypath="More info on:" style="margin-top: 8px;">
|
||||
<a href="https://pushy.me/docs/api/send-notifications" target="_blank">https://pushy.me/docs/api/send-notifications</a>
|
||||
</i18n-t>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -22,5 +22,5 @@ export default {
|
|||
components: {
|
||||
HiddenInput,
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -1,29 +1,27 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="rocket-webhook-url" class="form-label">Webhook URL<span style="color: red;"><sup>*</sup></span></label>
|
||||
<label for="rocket-webhook-url" class="form-label">{{ $t("Webhook URL") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="rocket-webhook-url" v-model="$parent.notification.rocketwebhookURL" type="text" class="form-control" required>
|
||||
<label for="rocket-username" class="form-label">Username</label>
|
||||
<label for="rocket-username" class="form-label">{{ $t("Username") }}</label>
|
||||
<input id="rocket-username" v-model="$parent.notification.rocketusername" type="text" class="form-control">
|
||||
<label for="rocket-iconemo" class="form-label">Icon Emoji</label>
|
||||
<label for="rocket-iconemo" class="form-label">{{ $t("Icon Emoji") }}</label>
|
||||
<input id="rocket-iconemo" v-model="$parent.notification.rocketiconemo" type="text" class="form-control">
|
||||
<label for="rocket-channel" class="form-label">Channel Name</label>
|
||||
<label for="rocket-channel" class="form-label">{{ $t("Channel Name") }}</label>
|
||||
<input id="rocket-channel-name" v-model="$parent.notification.rocketchannel" type="text" class="form-control">
|
||||
<label for="rocket-button-url" class="form-label">Uptime Kuma URL</label>
|
||||
<input id="rocket-button" v-model="$parent.notification.rocketbutton" type="text" class="form-control">
|
||||
<div class="form-text">
|
||||
<span style="color: red;"><sup>*</sup></span>Required
|
||||
<span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}
|
||||
<i18n-t tag="p" keypath="aboutWebhooks" style="margin-top: 8px;">
|
||||
<a href="https://docs.rocket.chat/guides/administration/administration/integrations" target="_blank">https://api.slack.com/messaging/webhooks</a>
|
||||
</i18n-t>
|
||||
<p style="margin-top: 8px;">
|
||||
More info about webhooks on: <a href="https://docs.rocket.chat/guides/administration/administration/integrations" target="_blank">https://api.slack.com/messaging/webhooks</a>
|
||||
{{ $t("aboutChannelName", [$t("rocket.chat")]) }}
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
Enter the channel name on Rocket.chat Channel Name field if you want to bypass the webhook channel. Ex: #other-channel
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
If you leave the Uptime Kuma URL field blank, it will default to the Project Github page.
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
Emoji cheat sheet: <a href="https://www.webfx.com/tools/emoji-cheat-sheet/" target="_blank">https://www.webfx.com/tools/emoji-cheat-sheet/</a>
|
||||
{{ $t("aboutKumaURL") }}
|
||||
</p>
|
||||
<i18n-t tag="p" keypath="emojiCheatSheet" style="margin-top: 8px;">
|
||||
<a href="https://www.webfx.com/tools/emoji-cheat-sheet/" target="_blank">https://www.webfx.com/tools/emoji-cheat-sheet/</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
<div class="mb-3">
|
||||
<label for="secure" class="form-label">Secure</label>
|
||||
<select id="secure" v-model="$parent.notification.smtpSecure" class="form-select">
|
||||
<option :value="false">None / STARTTLS (25, 587)</option>
|
||||
<option :value="true">TLS (465)</option>
|
||||
<option :value="false">{{ $t("secureOptionNone") }}</option>
|
||||
<option :value="true">{{ $t("secureOptionTLS") }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
|||
<div class="form-check">
|
||||
<input id="ignore-tls-error" v-model="$parent.notification.smtpIgnoreTLSError" class="form-check-input" type="checkbox" value="">
|
||||
<label class="form-check-label" for="ignore-tls-error">
|
||||
Ignore TLS Error
|
||||
{{ $t("Ignore TLS Error") }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -37,26 +37,38 @@
|
|||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="from-email" class="form-label">From Email</label>
|
||||
<label for="from-email" class="form-label">{{ $t("From Email") }}</label>
|
||||
<input id="from-email" v-model="$parent.notification.smtpFrom" type="text" class="form-control" required autocomplete="false" placeholder=""Uptime Kuma" <example@kuma.pet>">
|
||||
<div class="form-text">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="to-email" class="form-label">To Email</label>
|
||||
<label for="to-email" class="form-label">{{ $t("To Email") }}</label>
|
||||
<input id="to-email" v-model="$parent.notification.smtpTo" type="text" class="form-control" autocomplete="false" placeholder="example2@kuma.pet, example3@kuma.pet" :required="!hasRecipient">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="to-cc" class="form-label">CC</label>
|
||||
<label for="to-cc" class="form-label">{{ $t("smtpCC") }}</label>
|
||||
<input id="to-cc" v-model="$parent.notification.smtpCC" type="text" class="form-control" autocomplete="false" :required="!hasRecipient">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="to-bcc" class="form-label">BCC</label>
|
||||
<label for="to-bcc" class="form-label">{{ $t("smtpBCC") }}</label>
|
||||
<input id="to-bcc" v-model="$parent.notification.smtpBCC" type="text" class="form-control" autocomplete="false" :required="!hasRecipient">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="subject-email" class="form-label">{{ $t("emailCustomSubject") }}</label>
|
||||
<input id="subject-email" v-model="$parent.notification.customSubject" type="text" class="form-control" autocomplete="false" placeholder="">
|
||||
<div v-pre class="form-text">
|
||||
(leave blank for default one)<br />
|
||||
{{NAME}}: Service Name<br />
|
||||
{{HOSTNAME_OR_URL}}: Hostname or URL<br />
|
||||
{{URL}}: URL<br />
|
||||
{{STATUS}}: Status<br />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="signal-url" class="form-label">Post URL</label>
|
||||
<label for="signal-url" class="form-label">{{ $t("Post URL") }}</label>
|
||||
<input id="signal-url" v-model="$parent.notification.signalURL" type="url" pattern="https?://.+" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="signal-number" class="form-label">Number</label>
|
||||
<label for="signal-number" class="form-label">{{ $t("Number") }}</label>
|
||||
<input id="signal-number" v-model="$parent.notification.signalNumber" type="text" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="signal-recipients" class="form-label">Recipients</label>
|
||||
<label for="signal-recipients" class="form-label">{{ $t("Recipients") }}</label>
|
||||
<input id="signal-recipients" v-model="$parent.notification.signalRecipients" type="text" class="form-control" required>
|
||||
|
||||
<div class="form-text">
|
||||
You need to have a signal client with REST API.
|
||||
<p style="margin-top: 8px;">
|
||||
{{ $t("needSignalAPI") }}
|
||||
</p>
|
||||
|
||||
<p style="margin-top: 8px;">
|
||||
You can check this url to view how to setup one:
|
||||
{{ $t("wayToCheckSignalURL") }}
|
||||
</p>
|
||||
|
||||
<p style="margin-top: 8px;">
|
||||
|
@ -25,7 +27,7 @@
|
|||
</p>
|
||||
|
||||
<p style="margin-top: 8px;">
|
||||
IMPORTANT: You cannot mix groups and numbers in recipients!
|
||||
{{ $t("signalImportant") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,29 +1,28 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="slack-webhook-url" class="form-label">Webhook URL<span style="color: red;"><sup>*</sup></span></label>
|
||||
<label for="slack-webhook-url" class="form-label">{{ $t("Webhook URL") }}<span style="color: red;"><sup>*</sup></span></label>
|
||||
<input id="slack-webhook-url" v-model="$parent.notification.slackwebhookURL" type="text" class="form-control" required>
|
||||
<label for="slack-username" class="form-label">Username</label>
|
||||
<label for="slack-username" class="form-label">{{ $t("Username") }}</label>
|
||||
<input id="slack-username" v-model="$parent.notification.slackusername" type="text" class="form-control">
|
||||
<label for="slack-iconemo" class="form-label">Icon Emoji</label>
|
||||
<label for="slack-iconemo" class="form-label">{{ $t("Icon Emoji") }}</label>
|
||||
<input id="slack-iconemo" v-model="$parent.notification.slackiconemo" type="text" class="form-control">
|
||||
<label for="slack-channel" class="form-label">Channel Name</label>
|
||||
<label for="slack-channel" class="form-label">{{ $t("Channel Name") }}</label>
|
||||
<input id="slack-channel-name" v-model="$parent.notification.slackchannel" type="text" class="form-control">
|
||||
<label for="slack-button-url" class="form-label">Uptime Kuma URL</label>
|
||||
<input id="slack-button" v-model="$parent.notification.slackbutton" type="text" class="form-control">
|
||||
|
||||
<div class="form-text">
|
||||
<span style="color: red;"><sup>*</sup></span>Required
|
||||
<span style="color: red;"><sup>*</sup></span>{{ $t("Required") }}
|
||||
<i18n-t tag="p" keypath="aboutWebhooks" style="margin-top: 8px;">
|
||||
<a href="https://api.slack.com/messaging/webhooks" target="_blank">https://api.slack.com/messaging/webhooks</a>
|
||||
</i18n-t>
|
||||
<p style="margin-top: 8px;">
|
||||
More info about webhooks on: <a href="https://api.slack.com/messaging/webhooks" target="_blank">https://api.slack.com/messaging/webhooks</a>
|
||||
{{ $t("aboutChannelName", [$t("slack")]) }}
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
Enter the channel name on Slack Channel Name field if you want to bypass the webhook channel. Ex: #other-channel
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
If you leave the Uptime Kuma URL field blank, it will default to the Project Github page.
|
||||
</p>
|
||||
<p style="margin-top: 8px;">
|
||||
Emoji cheat sheet: <a href="https://www.webfx.com/tools/emoji-cheat-sheet/" target="_blank">https://www.webfx.com/tools/emoji-cheat-sheet/</a>
|
||||
{{ $t("aboutKumaURL") }}
|
||||
</p>
|
||||
<i18n-t tag="p" keypath="emojiCheatSheet" style="margin-top: 8px;">
|
||||
<a href="https://www.webfx.com/tools/emoji-cheat-sheet/" target="_blank">https://www.webfx.com/tools/emoji-cheat-sheet/</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="teams-webhookurl" class="form-label">Webhook URL</label>
|
||||
<label for="teams-webhookurl" class="form-label">{{ $t("Webhook URL") }}</label>
|
||||
<input
|
||||
id="teams-webhookurl"
|
||||
v-model="$parent.notification.webhookUrl"
|
||||
|
@ -8,12 +8,11 @@
|
|||
class="form-control"
|
||||
required
|
||||
/>
|
||||
<div class="form-text">
|
||||
You can learn how to create a webhook url
|
||||
<i18n-t tag="div" keypath="wayToGetTeamsURL" class="form-text">
|
||||
<a
|
||||
href="https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook"
|
||||
target="_blank"
|
||||
>here</a>.
|
||||
</div>
|
||||
>{{ $t("here") }}</a>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="telegram-bot-token" class="form-label">Bot Token</label>
|
||||
<label for="telegram-bot-token" class="form-label">{{ $t("Bot Token") }}</label>
|
||||
<HiddenInput id="telegram-bot-token" v-model="$parent.notification.telegramBotToken" :required="true" autocomplete="one-time-code"></HiddenInput>
|
||||
<div class="form-text">
|
||||
You can get a token from <a href="https://t.me/BotFather" target="_blank">https://t.me/BotFather</a>.
|
||||
{{ $t("You can get a token from") }} <a href="https://t.me/BotFather" target="_blank">https://t.me/BotFather</a>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="telegram-chat-id" class="form-label">Chat ID</label>
|
||||
<label for="telegram-chat-id" class="form-label">{{ $t("Chat ID") }}</label>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<input id="telegram-chat-id" v-model="$parent.notification.telegramChatID" type="text" class="form-control" required>
|
||||
|
@ -18,10 +18,10 @@
|
|||
</div>
|
||||
|
||||
<div class="form-text">
|
||||
Support Direct Chat / Group / Channel's Chat ID
|
||||
{{ $t("supportTelegramChatID") }}
|
||||
|
||||
<p style="margin-top: 8px;">
|
||||
You can get your chat id by sending message to the bot and go to this url to view the chat_id:
|
||||
{{ $t("wayToGetTelegramChatID") }}
|
||||
</p>
|
||||
|
||||
<p style="margin-top: 8px;">
|
||||
|
@ -49,7 +49,7 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
telegramGetUpdatesURL() {
|
||||
let token = "<YOUR BOT TOKEN HERE>"
|
||||
let token = `<${this.$t("YOUR BOT TOKEN HERE")}>`
|
||||
|
||||
if (this.$parent.notification.telegramBotToken) {
|
||||
token = this.$parent.notification.telegramBotToken;
|
||||
|
@ -71,11 +71,11 @@ export default {
|
|||
} else if (update.message) {
|
||||
this.notification.telegramChatID = update.message.chat.id;
|
||||
} else {
|
||||
throw new Error("Chat ID is not found, please send a message to this bot first")
|
||||
throw new Error(this.$t("chatIDNotFound"))
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Error("Chat ID is not found, please send a message to this bot first")
|
||||
throw new Error(this.$t("chatIDNotFound"))
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div class="mb-3">
|
||||
<label for="webhook-url" class="form-label">Post URL</label>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="webhook-content-type" class="form-label">Content Type</label>
|
||||
<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
|
||||
|
@ -17,7 +17,12 @@
|
|||
|
||||
<div class="form-text">
|
||||
<p>"application/json" is good for any modern http servers such as express.js</p>
|
||||
<p>"multipart/form-data" is good for PHP, you just need to parse the json by <strong>json_decode($_POST['data'])</strong></p>
|
||||
<i18n-t tag="p" keypath="webhookFormDataDesc">
|
||||
<template #multipart>"multipart/form-data"</template>
|
||||
<template #decodeFunction>
|
||||
<strong>json_decode($_POST['data'])</strong>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -10,11 +10,16 @@ import Teams from "./Teams.vue";
|
|||
import Pushover from "./Pushover.vue";
|
||||
import Pushy from "./Pushy.vue";
|
||||
import Octopush from "./Octopush.vue";
|
||||
import PromoSMS from "./PromoSMS.vue";
|
||||
import LunaSea from "./LunaSea.vue";
|
||||
import Feishu from "./Feishu.vue";
|
||||
import Apprise from "./Apprise.vue";
|
||||
import Pushbullet from "./Pushbullet.vue";
|
||||
import Line from "./Line.vue";
|
||||
import Mattermost from "./Mattermost.vue";
|
||||
import Matrix from "./Matrix.vue";
|
||||
import AliyunSMS from "./AliyunSms.vue";
|
||||
import DingDing from "./DingDing.vue";
|
||||
|
||||
/**
|
||||
* Manage all notification form.
|
||||
|
@ -34,11 +39,16 @@ const NotificationFormList = {
|
|||
"pushover": Pushover,
|
||||
"pushy": Pushy,
|
||||
"octopush": Octopush,
|
||||
"promosms": PromoSMS,
|
||||
"lunasea": LunaSea,
|
||||
"Feishu": Feishu,
|
||||
"AliyunSMS": AliyunSMS,
|
||||
"apprise": Apprise,
|
||||
"pushbullet": Pushbullet,
|
||||
"line": Line,
|
||||
"mattermost": Mattermost
|
||||
"mattermost": Mattermost,
|
||||
"matrix": Matrix,
|
||||
"DingDing": DingDing
|
||||
}
|
||||
|
||||
export default NotificationFormList
|
||||
|
|
26
src/i18n.js
26
src/i18n.js
|
@ -1,24 +1,26 @@
|
|||
import { createI18n } from "vue-i18n";
|
||||
import bgBG from "./languages/bg-BG";
|
||||
import { createI18n } from "vue-i18n/index";
|
||||
import daDK from "./languages/da-DK";
|
||||
import deDE from "./languages/de-DE";
|
||||
import en from "./languages/en";
|
||||
import fa from "./languages/fa";
|
||||
import esEs from "./languages/es-ES";
|
||||
import ptBR from "./languages/pt-BR";
|
||||
import etEE from "./languages/et-EE";
|
||||
import fa from "./languages/fa";
|
||||
import frFR from "./languages/fr-FR";
|
||||
import hu from "./languages/hu";
|
||||
import itIT from "./languages/it-IT";
|
||||
import idID from "./languages/id-ID";
|
||||
import ja from "./languages/ja";
|
||||
import koKR from "./languages/ko-KR";
|
||||
import nlNL from "./languages/nl-NL";
|
||||
import nbNO from "./languages/nb-NO";
|
||||
import pl from "./languages/pl";
|
||||
import ptBR from "./languages/pt-BR";
|
||||
import bgBG from "./languages/bg-BG";
|
||||
import ruRU from "./languages/ru-RU";
|
||||
import sr from "./languages/sr";
|
||||
import srLatn from "./languages/sr-latn";
|
||||
import trTR from "./languages/tr-TR";
|
||||
import svSE from "./languages/sv-SE";
|
||||
import trTR from "./languages/tr-TR";
|
||||
import zhCN from "./languages/zh-CN";
|
||||
import zhHK from "./languages/zh-HK";
|
||||
|
||||
|
@ -28,12 +30,14 @@ const languageList = {
|
|||
"bg-BG": bgBG,
|
||||
"de-DE": deDE,
|
||||
"nl-NL": nlNL,
|
||||
"nb-NO": nbNO,
|
||||
"es-ES": esEs,
|
||||
"fa": fa,
|
||||
"pt-BR": ptBR,
|
||||
"fr-FR": frFR,
|
||||
"hu": hu,
|
||||
"it-IT": itIT,
|
||||
"id-ID" : idID,
|
||||
"ja": ja,
|
||||
"da-DK": daDK,
|
||||
"sr": sr,
|
||||
|
@ -48,12 +52,16 @@ const languageList = {
|
|||
};
|
||||
|
||||
const rtlLangs = ["fa"];
|
||||
|
||||
export const currentLocale = () => localStorage.locale || "en";
|
||||
|
||||
export const currentLocale = () => localStorage.locale
|
||||
|| languageList[navigator.language] && navigator.language
|
||||
|| languageList[navigator.language.substring(0, 2)] && navigator.language.substring(0, 2)
|
||||
|| "en";
|
||||
|
||||
export const localeDirection = () => {
|
||||
return rtlLangs.includes(currentLocale()) ? "rtl" : "ltr"
|
||||
}
|
||||
return rtlLangs.includes(currentLocale()) ? "rtl" : "ltr";
|
||||
};
|
||||
|
||||
export const i18n = createI18n({
|
||||
locale: currentLocale(),
|
||||
fallbackLocale: "en",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
export default {
|
||||
languageName: "Български",
|
||||
checkEverySecond: "Проверявай на всеки {0} секунди.",
|
||||
retryCheckEverySecond: "Повторен опит на всеки {0} секунди.",
|
||||
checkEverySecond: "Ще се извършва на всеки {0} секунди",
|
||||
retryCheckEverySecond: "Ще се извършва на всеки {0} секунди",
|
||||
retriesDescription: "Максимакен брой опити преди услугата да бъде маркирана като недостъпна и да бъде изпратено известие",
|
||||
ignoreTLSError: "Игнорирай TLS/SSL грешки за HTTPS уебсайтове",
|
||||
upsideDownModeDescription: "Обърни статуса от достъпен на недостъпен. Ако услугата е достъпна се вижда НЕДОСТЪПНА.",
|
||||
|
@ -9,57 +9,57 @@ export default {
|
|||
acceptedStatusCodesDescription: "Изберете статус кодове, които се считат за успешен отговор.",
|
||||
passwordNotMatchMsg: "Повторената парола не съвпада.",
|
||||
notificationDescription: "Моля, задайте известието към монитор(и), за да функционира.",
|
||||
keywordDescription: "Търсете ключова дума в обикновен html или JSON отговор - чувствителна е към регистъра",
|
||||
keywordDescription: "Търси ключова дума в чист html или JSON отговор - чувствителна е към регистъра",
|
||||
pauseDashboardHome: "Пауза",
|
||||
deleteMonitorMsg: "Наистина ли желаете да изтриете този монитор?",
|
||||
deleteNotificationMsg: "Наистина ли желаете да изтриете известието за всички монитори?",
|
||||
resoverserverDescription: "Cloudflare е сървърът по подразбиране, можете да промените сървъра по всяко време.",
|
||||
deleteNotificationMsg: "Наистина ли желаете да изтриете това известяване за всички монитори?",
|
||||
resoverserverDescription: "Cloudflare е сървърът по подразбиране, но можете да го промените по всяко време.",
|
||||
rrtypeDescription: "Изберете ресурсния запис, който желаете да наблюдавате",
|
||||
pauseMonitorMsg: "Наистина ли желаете да поставите в режим пауза?",
|
||||
enableDefaultNotificationDescription: "За всеки нов монитор това известие ще бъде активирано по подразбиране. Можете да изключите известието за всеки отделен монитор.",
|
||||
enableDefaultNotificationDescription: "За всеки нов монитор това известяване ще бъде активирано по подразбиране. Можете да го изключите за всеки отделен монитор.",
|
||||
clearEventsMsg: "Наистина ли желаете да изтриете всички събития за този монитор?",
|
||||
clearHeartbeatsMsg: "Наистина ли желаете да изтриете всички записи за честотни проверки на този монитор?",
|
||||
confirmClearStatisticsMsg: "Наистина ли желаете да изтриете всички статистически данни?",
|
||||
importHandleDescription: "Изберете 'Пропусни съществуващите', ако искате да пропуснете всеки монитор или известие със същото име. 'Презапис' ще изтрие всеки съществуващ монитор и известие.",
|
||||
confirmImportMsg: "Сигурни ли сте за импортирането на архива? Моля, уверете се, че сте избрали правилната опция за импортиране.",
|
||||
importHandleDescription: "Изберете 'Пропусни съществуващите', ако желаете да пропуснете всеки монитор или известяване със същото име. 'Презапис' ще изтрие всеки съществуващ монитор и известяване.",
|
||||
confirmImportMsg: "Сигурни ли сте, че желаете импортирането на архива? Моля, уверете се, че сте избрали правилната опция за импортиране.",
|
||||
twoFAVerifyLabel: "Моля, въведете вашия токен код, за да проверите дали 2FA работи",
|
||||
tokenValidSettingsMsg: "Токен кодът е валиден! Вече можете да запазите настройките за 2FA.",
|
||||
confirmEnableTwoFAMsg: "Сигурни ли сте, че желаете да активирате 2FA?",
|
||||
confirmDisableTwoFAMsg: "Сигурни ли сте, че желаете да изключите 2FA?",
|
||||
Settings: "Настройки",
|
||||
Dashboard: "Табло",
|
||||
"New Update": "Нова актуализация",
|
||||
"New Update": "Налична е актуализация",
|
||||
Language: "Език",
|
||||
Appearance: "Изглед",
|
||||
Theme: "Тема",
|
||||
General: "Общи",
|
||||
Version: "Версия",
|
||||
"Check Update On GitHub": "Провери за актуализация в GitHub",
|
||||
"Check Update On GitHub": "Проверка за актуализация в GitHub",
|
||||
List: "Списък",
|
||||
Add: "Добави",
|
||||
"Add New Monitor": "Добави монитор",
|
||||
"Quick Stats": "Кратка статистика",
|
||||
Up: "Достъпни",
|
||||
Down: "Недостъпни",
|
||||
Pending: "В изчакване",
|
||||
Unknown: "Неизвестни",
|
||||
Pause: "В пауза",
|
||||
Up: "Достъпен",
|
||||
Down: "Недостъпен",
|
||||
Pending: "Изчаква",
|
||||
Unknown: "Неизвестен",
|
||||
Pause: "Пауза",
|
||||
Name: "Име",
|
||||
Status: "Статус",
|
||||
DateTime: "Дата и час",
|
||||
Message: "Съобщение",
|
||||
Message: "Отговор",
|
||||
"No important events": "Няма важни събития",
|
||||
Resume: "Възобнови",
|
||||
Edit: "Редактирай",
|
||||
Delete: "Изтрий",
|
||||
Current: "Текущ",
|
||||
Uptime: "Време на работа",
|
||||
Uptime: "Достъпност",
|
||||
"Cert Exp.": "Вал. сертификат",
|
||||
days: "дни",
|
||||
day: "ден",
|
||||
"-day": "-ден",
|
||||
"-day": "-дни",
|
||||
hour: "час",
|
||||
"-hour": "-час",
|
||||
"-hour": "-часa",
|
||||
Response: "Отговор",
|
||||
Ping: "Пинг",
|
||||
"Monitor Type": "Монитор тип",
|
||||
|
@ -78,7 +78,7 @@ export default {
|
|||
Save: "Запази",
|
||||
Notifications: "Известявания",
|
||||
"Not available, please setup.": "Не е налично. Моля, настройте.",
|
||||
"Setup Notification": "Настройка за известяване",
|
||||
"Setup Notification": "Настройки за известявания",
|
||||
Light: "Светла",
|
||||
Dark: "Тъмна",
|
||||
Auto: "Автоматично",
|
||||
|
@ -98,9 +98,9 @@ export default {
|
|||
"Disable Auth": "Изключи удостоверяване",
|
||||
"Enable Auth": "Включи удостоверяване",
|
||||
Logout: "Изход от профила",
|
||||
Leave: "Напускам",
|
||||
Leave: "Отказ",
|
||||
"I understand, please disable": "Разбирам. Моля, изключи",
|
||||
Confirm: "Потвърди",
|
||||
Confirm: "Потвърдете",
|
||||
Yes: "Да",
|
||||
No: "Не",
|
||||
Username: "Потребител",
|
||||
|
@ -127,7 +127,7 @@ export default {
|
|||
"Default enabled": "Включен по подразбиране",
|
||||
"Apply on all existing monitors": "Приложи върху всички съществуващи монитори",
|
||||
Create: "Създай",
|
||||
"Clear Data": "Изчисти данни",
|
||||
"Clear Data": "Изтрий данни",
|
||||
Events: "Събития",
|
||||
Heartbeats: "Проверки",
|
||||
"Auto Get": "Автоматияно получаване",
|
||||
|
@ -136,7 +136,7 @@ export default {
|
|||
backupDescription3: "Чувствителни данни, като токен кодове за известяване, се съдържат в експортирания файл. Моля, бъдете внимателни с неговото съхранение.",
|
||||
alertNoFile: "Моля, изберете файл за импортиране.",
|
||||
alertWrongFileType: "Моля, изберете JSON файл.",
|
||||
"Clear all statistics": "Изчисти всички статистики",
|
||||
"Clear all statistics": "Изтрий цялата статистика",
|
||||
"Skip existing": "Пропусни съществуващите",
|
||||
Overwrite: "Презапиши",
|
||||
Options: "Опции",
|
||||
|
@ -152,7 +152,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: "цвят",
|
||||
|
@ -171,11 +171,30 @@ export default {
|
|||
"Entry Page": "Основна страница",
|
||||
statusPageNothing: "Все още няма нищо тук. Моля, добавете група или монитор.",
|
||||
"No Services": "Няма Услуги",
|
||||
"All Systems Operational": "Всички системи функционират",
|
||||
"Partially Degraded Service": "Частично влошена услуга",
|
||||
"Degraded Service": "Влошена услуга",
|
||||
"All Systems Operational": "Всички услуги са достъпни",
|
||||
"Partially Degraded Service": "Част от услугите са недостъпни",
|
||||
"Degraded Service": "Всички услуги са недостъпни",
|
||||
"Add Group": "Добави група",
|
||||
"Add a monitor": "Добави монитор",
|
||||
"Edit Status Page": "Редактирай статус страница",
|
||||
"Edit Status Page": "Редактиране Статус страница",
|
||||
"Go to Dashboard": "Към Таблото",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "Email (SMTP)",
|
||||
discord: "Discord",
|
||||
teams: "Microsoft Teams",
|
||||
signal: "Signal",
|
||||
gotify: "Gotify",
|
||||
slack: "Slack",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Поддържа 50+ услуги за инвестяване)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"Status Page": "Статус страница",
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export default {
|
||||
languageName: "Danish",
|
||||
languageName: "Danish (Danmark)",
|
||||
Settings: "Indstillinger",
|
||||
Dashboard: "Dashboard",
|
||||
"New Update": "Opdatering tilgængelig",
|
||||
|
@ -170,7 +170,7 @@ export default {
|
|||
"Avg. Ping": "Gns. Ping",
|
||||
"Avg. Response": "Gns. Respons",
|
||||
"Entry Page": "Entry Side",
|
||||
"statusPageNothing": "Intet her, tilføj venligst en Gruppe eller en Overvåger.",
|
||||
statusPageNothing: "Intet her, tilføj venligst en Gruppe eller en Overvåger.",
|
||||
"No Services": "Ingen Tjenester",
|
||||
"All Systems Operational": "Alle Systemer i Drift",
|
||||
"Partially Degraded Service": "Delvist Forringet Service",
|
||||
|
@ -179,4 +179,23 @@ export default {
|
|||
"Add a monitor": "Tilføj en Overvåger",
|
||||
"Edit Status Page": "Rediger Statusside",
|
||||
"Go to Dashboard": "Gå til Dashboard",
|
||||
"Status Page": "Status Page",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "Email (SMTP)",
|
||||
discord: "Discord",
|
||||
teams: "Microsoft Teams",
|
||||
signal: "Signal",
|
||||
gotify: "Gotify",
|
||||
slack: "Slack",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
};
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
export default {
|
||||
languageName: "German",
|
||||
languageName: "Deutsch (Deutschland)",
|
||||
Settings: "Einstellungen",
|
||||
Dashboard: "Dashboard",
|
||||
"New Update": "Update Verfügbar",
|
||||
"New Update": "Update verfügbar",
|
||||
Language: "Sprache",
|
||||
Appearance: "Erscheinung",
|
||||
Theme: "Thema",
|
||||
General: "Allgemein",
|
||||
Version: "Version",
|
||||
"Check Update On GitHub": "Überprüfen von Updates auf Github",
|
||||
"Check Update On GitHub": "Auf GitHub nach Updates suchen",
|
||||
List: "Liste",
|
||||
Add: "Hinzufügen",
|
||||
"Add New Monitor": "Neuer Monitor",
|
||||
|
@ -38,21 +38,21 @@ export default {
|
|||
checkEverySecond: "Überprüfe alle {0} Sekunden",
|
||||
Response: "Antwortzeit",
|
||||
Ping: "Ping",
|
||||
"Monitor Type": "Monitor Typ",
|
||||
Keyword: "Schlüsselwort",
|
||||
"Monitor Type": "Monitor-Typ",
|
||||
Keyword: "Suchwort",
|
||||
"Friendly Name": "Anzeigename",
|
||||
URL: "URL",
|
||||
Hostname: "Hostname",
|
||||
Port: "Port",
|
||||
"Heartbeat Interval": "Taktintervall",
|
||||
"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": "Umgedrehter Modus",
|
||||
upsideDownModeDescription: "Drehe den Modus um, ist der Dienst erreichbar, wird er als Inaktiv angezeigt.",
|
||||
ignoreTLSError: "Ignoriere TLS-/SSL-Fehler von Webseiten",
|
||||
"Upside Down Mode": "Invertierter Modus",
|
||||
upsideDownModeDescription: "Im invertierten Modus wird der Dienst als inaktiv angezeigt, wenn er erreichbar ist.",
|
||||
"Max. Redirects": "Max. Weiterleitungen",
|
||||
maxRedirectDescription: "Maximale Anzahl von Weiterleitungen, denen gefolgt werden soll. Setzte auf 0, um Weiterleitungen zu deaktivieren.",
|
||||
maxRedirectDescription: "Maximale Anzahl von Weiterleitungen, denen gefolgt werden soll. Auf 0 setzen, um Weiterleitungen zu deaktivieren.",
|
||||
"Accepted Status Codes": "Erlaubte HTTP-Statuscodes",
|
||||
acceptedStatusCodesDescription: "Wähle die Statuscodes aus, welche trotzdem als erfolgreich gewertet werden sollen.",
|
||||
Save: "Speichern",
|
||||
|
@ -62,27 +62,27 @@ export default {
|
|||
Light: "Hell",
|
||||
Dark: "Dunkel",
|
||||
Auto: "Auto",
|
||||
"Theme - Heartbeat Bar": "Thema - Taktleiste",
|
||||
"Theme - Heartbeat Bar": "Thema - Zeitleiste",
|
||||
Normal: "Normal",
|
||||
Bottom: "Unten",
|
||||
None: "Keine",
|
||||
Timezone: "Zeitzone",
|
||||
"Search Engine Visibility": "Suchmaschinensichtbarkeit",
|
||||
"Search Engine Visibility": "Sichtbarkeit für Suchmaschinen",
|
||||
"Allow indexing": "Indizierung zulassen",
|
||||
"Discourage search engines from indexing site": "Halte Suchmaschinen von der Indexierung der Seite ab",
|
||||
"Change Password": "Passwort ändern",
|
||||
"Current Password": "Dezeitiges Passwort",
|
||||
"Current Password": "Derzeitiges Passwort",
|
||||
"New Password": "Neues Passwort",
|
||||
"Repeat New Password": "Wiederhole neues Passwort",
|
||||
"Repeat New Password": "Neues Passwort wiederholen",
|
||||
passwordNotMatchMsg: "Passwörter stimmen nicht überein. ",
|
||||
"Update Password": "Ändere Passwort",
|
||||
"Update Password": "Passwort aktualisieren",
|
||||
"Disable Auth": "Authentifizierung deaktivieren",
|
||||
"Enable Auth": "Authentifizierung aktivieren",
|
||||
Logout: "Ausloggen",
|
||||
notificationDescription: "Weise den Monitor(en) eine Benachrichtigung zu, damit diese Funktion greift.",
|
||||
Leave: "Verlassen",
|
||||
"I understand, please disable": "Ich verstehe, bitte deaktivieren",
|
||||
Confirm: "Bestätige",
|
||||
Confirm: "Bestätigen",
|
||||
Yes: "Ja",
|
||||
No: "Nein",
|
||||
Username: "Benutzername",
|
||||
|
@ -91,30 +91,30 @@ export default {
|
|||
Login: "Einloggen",
|
||||
"No Monitors, please": "Keine Monitore, bitte",
|
||||
"add one": "hinzufügen",
|
||||
"Notification Type": "Benachrichtigungs Dienst",
|
||||
"Notification Type": "Benachrichtigungsdienst",
|
||||
Email: "E-Mail",
|
||||
Test: "Test",
|
||||
"Certificate Info": "Zertifikatsinfo",
|
||||
keywordDescription: "Suche nach einem Schlüsselwort in der HTML oder JSON Ausgabe. Bitte beachte, es wird in der Groß-/Kleinschreibung unterschieden.",
|
||||
deleteMonitorMsg: "Bist du sicher das du den Monitor löschen möchtest?",
|
||||
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?",
|
||||
resoverserverDescription: "Cloudflare ist als der Standardserver festgelegt, dieser kann jederzeit geändern 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 das du den Monitor pausieren möchtest?",
|
||||
clearEventsMsg: "Bist du sicher das du alle Ereignisse für diesen Monitor löschen möchtest?",
|
||||
clearHeartbeatsMsg: "Bist du sicher das du alle Statistiken für diesen Monitor löschen möchtest?",
|
||||
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 sicher das du ALLE Statistiken löschen möchtest?",
|
||||
"Create your admin account": "Erstelle dein Admin Konto",
|
||||
confirmClearStatisticsMsg: "Bist du dir sicher, dass du ALLE Statistiken löschen möchtest?",
|
||||
"Create your admin account": "Erstelle dein Admin-Konto",
|
||||
"Repeat Password": "Wiederhole das Passwort",
|
||||
"Resource Record Type": "Resource Record Type",
|
||||
Export: "Export",
|
||||
Import: "Import",
|
||||
respTime: "Antw. Zeit (ms)",
|
||||
respTime: "Antw.-Zeit (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
"Default enabled": "Standardmäßig aktiviert",
|
||||
"Apply on all existing monitors": "Auf alle existierenden Monitore anwenden",
|
||||
|
@ -124,35 +124,35 @@ export default {
|
|||
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 Benachrichtigungstoken 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.",
|
||||
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 Benachrichtigung mit demselben Namen übersprungen werden soll. 'Überschreiben' löscht jeden vorhandenen Monitor sowie Benachrichtigungen.",
|
||||
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.",
|
||||
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 das 2FA funktioniert",
|
||||
twoFAVerifyLabel: "Bitte trage deinen Token ein, um zu verifizieren, dass 2FA funktioniert",
|
||||
"Verify Token": "Token verifizieren",
|
||||
"Setup 2FA": "2FA Einrichten",
|
||||
"Enable 2FA": "2FA Aktivieren",
|
||||
"Setup 2FA": "2FA einrichten",
|
||||
"Enable 2FA": "2FA aktivieren",
|
||||
"Disable 2FA": "2FA deaktivieren",
|
||||
"2FA Settings": "2FA Einstellungen",
|
||||
confirmEnableTwoFAMsg: "Bist du sicher das du 2FA aktivieren möchtest?",
|
||||
confirmDisableTwoFAMsg: "Bist du sicher das du 2FA deaktivieren möchtest?",
|
||||
tokenValidSettingsMsg: "Token gültig! Du kannst jetzt die 2FA Einstellungen speichern.",
|
||||
"Two Factor Authentication": "Zwei Faktor Authentifizierung",
|
||||
"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",
|
||||
"Show URI": "URI anzeigen",
|
||||
Tags: "Tags",
|
||||
"Add New below or Select...": "Füge neuen hinzu oder wähle aus...",
|
||||
"Tag with this name already exist.": "Ein Tag mit dem Namen existiert bereits.",
|
||||
"Tag with this value already exist.": "Ein Tag mit dem Wert existiert bereits.",
|
||||
"Add New below or Select...": "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)",
|
||||
"value (optional)": "Wert (optional)",
|
||||
Gray: "Grau",
|
||||
Red: "Rot",
|
||||
Orange: "Orange",
|
||||
|
@ -162,20 +162,39 @@ export default {
|
|||
Purple: "Lila",
|
||||
Pink: "Pink",
|
||||
"Search...": "Suchen...",
|
||||
"Heartbeat Retry Interval": "Takt-Wiederholungsintervall",
|
||||
"Heartbeat Retry Interval": "Heartbeat-Wiederholungsintervall",
|
||||
retryCheckEverySecond: "Versuche alle {0} Sekunden",
|
||||
"Import Backup": "Import Backup",
|
||||
"Export Backup": "Export Backup",
|
||||
"Avg. Ping": "Durchsch. Ping",
|
||||
"Avg. Response": "Durchsch. Antwort",
|
||||
"Import Backup": "Backup importieren",
|
||||
"Export Backup": "Backup exportieren",
|
||||
"Avg. Ping": "Durchschn. Ping",
|
||||
"Avg. Response": "Durchschn. Antwort",
|
||||
"Entry Page": "Einstiegsseite",
|
||||
statusPageNothing: "Nichts ist hier, bitte füge eine Gruppe oder Monitor hinzu.",
|
||||
statusPageNothing: "Noch ist hier nichts. Bitte füge eine Gruppe oder einen Monitor hinzu.",
|
||||
"No Services": "Keine Dienste",
|
||||
"All Systems Operational": "Alle Systeme Betriebsbereit",
|
||||
"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 Statusseite",
|
||||
"Edit Status Page": "Bearbeite Status-Seite",
|
||||
"Go to Dashboard": "Gehe zum Dashboard",
|
||||
"Status Page": "Status-Seite",
|
||||
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)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@ export default {
|
|||
enableDefaultNotificationDescription: "For every new monitor this notification will be enabled by default. You can still disable the notification separately for each monitor.",
|
||||
clearEventsMsg: "Are you sure want to delete all events for this monitor?",
|
||||
clearHeartbeatsMsg: "Are you sure want to delete all heartbeats for this monitor?",
|
||||
confirmClearStatisticsMsg: "Are you sure want to delete ALL statistics?",
|
||||
confirmClearStatisticsMsg: "Are you sure you want to delete ALL statistics?",
|
||||
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
|
||||
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
|
||||
twoFAVerifyLabel: "Please type in your token to verify that 2FA is working",
|
||||
|
@ -178,21 +178,109 @@ export default {
|
|||
"Add a monitor": "Add a monitor",
|
||||
"Edit Status Page": "Edit Status Page",
|
||||
"Go to Dashboard": "Go to Dashboard",
|
||||
"Status Page": "Status Page",
|
||||
// Start notification form
|
||||
defaultNotificationName: "My {notification} Alert ({number})",
|
||||
here: "here",
|
||||
"Required": "Required",
|
||||
"telegram": "Telegram",
|
||||
"Bot Token": "Bot Token",
|
||||
"You can get a token from": "You can get a token from",
|
||||
"Chat ID": "Chat ID",
|
||||
supportTelegramChatID: "Support Direct Chat / Group / Channel's Chat ID",
|
||||
wayToGetTelegramChatID: "You can get your chat id by sending message to the bot and go to this url to view the chat_id:",
|
||||
"YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE",
|
||||
chatIDNotFound: "Chat ID is not found, please send a message to this bot first",
|
||||
"webhook": "Webhook",
|
||||
"Post URL": "Post URL",
|
||||
"Content Type": "Content Type",
|
||||
webhookJsonDesc: "{0} is good for any modern http servers such as express.js",
|
||||
webhookFormDataDesc: "{multipart} is good for PHP, you just need to parse the json by {decodeFunction}",
|
||||
"smtp": "Email (SMTP)",
|
||||
secureOptionNone: "None / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "Ignore TLS Error",
|
||||
"From Email": "From Email",
|
||||
emailCustomSubject: "Custom Subject",
|
||||
"To Email": "To Email",
|
||||
smtpCC: "CC",
|
||||
smtpBCC: "BCC",
|
||||
"discord": "Discord",
|
||||
"Discord Webhook URL": "Discord Webhook URL",
|
||||
wayToGetDiscordURL: "You can get this by going to Server Settings -> Integrations -> Create Webhook",
|
||||
"Bot Display Name": "Bot Display Name",
|
||||
"Prefix Custom Message": "Prefix Custom Message",
|
||||
"Hello @everyone is...": "Hello {'@'}everyone is...",
|
||||
"teams": "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "You can learn how to create a webhook url {0}.",
|
||||
"signal": "Signal",
|
||||
"Number": "Number",
|
||||
"Recipients": "Recipients",
|
||||
needSignalAPI: "You need to have a signal client with REST API.",
|
||||
wayToCheckSignalURL: "You can check this url to view how to setup one:",
|
||||
signalImportant: "IMPORTANT: You cannot mix groups and numbers in recipients!",
|
||||
"gotify": "Gotify",
|
||||
"Application Token": "Application Token",
|
||||
"Server URL": "Server URL",
|
||||
"Priority": "Priority",
|
||||
"slack": "Slack",
|
||||
"Icon Emoji": "Icon Emoji",
|
||||
"Channel Name": "Channel Name",
|
||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||
aboutWebhooks: "More info about webhooks on: {0}",
|
||||
aboutChannelName: "Enter the channel name on {0} Channel Name field if you want to bypass the webhook channel. Ex: #other-channel",
|
||||
aboutKumaURL: "If you leave the Uptime Kuma URL field blank, it will default to the Project Github page.",
|
||||
emojiCheatSheet: "Emoji cheat sheet: {0}",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
"pushover": "Pushover",
|
||||
"pushy": "Pushy",
|
||||
"octopush": "Octopush",
|
||||
"lunasea": "LunaSea",
|
||||
"apprise": "Apprise (Support 50+ Notification services)",
|
||||
"pushbullet": "Pushbullet",
|
||||
"line": "Line Messenger",
|
||||
"mattermost": "Mattermost",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "User Key",
|
||||
"Device": "Device",
|
||||
"Message Title": "Message Title",
|
||||
"Notification Sound": "Notification Sound",
|
||||
"More info on:": "More info on: {0}",
|
||||
pushoverDesc1: "Emergency priority (2) has default 30 second timeout between retries and will expire after 1 hour.",
|
||||
pushoverDesc2: "If you want to send notifications to different devices, fill out Device field.",
|
||||
"SMS Type": "SMS Type",
|
||||
octopushTypePremium: "Premium (Fast - recommended for alerting)",
|
||||
octopushTypeLowCost: "Low Cost (Slow, sometimes blocked by operator)",
|
||||
"Check octopush prices": "Check octopush prices {0}.",
|
||||
octopushPhoneNumber: "Phone number (intl format, eg : +33612345678) ",
|
||||
octopushSMSSender: "SMS Sender Name : 3-11 alphanumeric characters and space (a-zA-Z0-9)",
|
||||
"LunaSea Device ID": "LunaSea Device ID",
|
||||
"Apprise URL": "Apprise URL",
|
||||
"Example:": "Example: {0}",
|
||||
"Read more:": "Read more: {0}",
|
||||
"Status:": "Status: {0}",
|
||||
"Read more": "Read more",
|
||||
appriseInstalled: "Apprise is installed.",
|
||||
appriseNotInstalled: "Apprise is not installed. {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: "First access the {0}, create a provider and channel (Messaging API), then you can get the channel access token and user id from the above mentioned menu items.",
|
||||
"Icon URL": "Icon URL",
|
||||
aboutIconURL: "You can provide a link to a picture in \"Icon URL\" to override the default profile picture. Will not be used if Icon Emoji is set.",
|
||||
aboutMattermostChannelName: "You can override the default channel that webhook posts to by entering the channel name into \"Channel Name\" field. This needs to be enabled in Mattermost webhook settings. Ex: #other-channel",
|
||||
"matrix": "Matrix",
|
||||
promosmsTypeEco: "SMS ECO - cheap but slow and often overloaded. Limited only to Polish recipients.",
|
||||
promosmsTypeFlash: "SMS FLASH - Message will automatically show on recipient device. Limited only to Polish recipients.",
|
||||
promosmsTypeFull: "SMS FULL - Premium tier of SMS, You can use Your Sender Name (You need to register name first). Reliable for alerts.",
|
||||
promosmsTypeSpeed: "SMS SPEED - Highest priority in system. Very quick and reliable but costly (about twice of SMS FULL price).",
|
||||
promosmsPhoneNumber: "Phone number (for Polish recipient You can skip area codes)",
|
||||
promosmsSMSSender: "SMS Sender Name : Pre-registred name or one of defaults: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
"Feishu WebHookUrl": "Feishu WebHookUrl",
|
||||
// End notification form
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ export default {
|
|||
pauseMonitorMsg: "¿Seguro que quieres pausar?",
|
||||
Settings: "Ajustes",
|
||||
Dashboard: "Panel",
|
||||
"New Update": "Vueva actualización",
|
||||
"New Update": "Nueva actualización",
|
||||
Language: "Idioma",
|
||||
Appearance: "Apariencia",
|
||||
Theme: "Tema",
|
||||
|
@ -61,11 +61,11 @@ export default {
|
|||
Retries: "Reintentos",
|
||||
Advanced: "Avanzado",
|
||||
"Upside Down Mode": "Modo invertido",
|
||||
"Max. Redirects": "Máx. redirecciones",
|
||||
"Max. Redirects": "Redirecciones Máximas",
|
||||
"Accepted Status Codes": "Códigos de estado aceptados",
|
||||
Save: "Guardar",
|
||||
Notifications: "Notificaciones",
|
||||
"Not available, please setup.": "No disponible, por favor configurar.",
|
||||
"Not available, please setup.": "No disponible, por favor configúrelo.",
|
||||
"Setup Notification": "Configurar notificación",
|
||||
Light: "Claro",
|
||||
Dark: "Oscuro",
|
||||
|
@ -83,11 +83,11 @@ export default {
|
|||
"New Password": "Nueva contraseña",
|
||||
"Repeat New Password": "Repetir nueva contraseña",
|
||||
"Update Password": "Actualizar contraseña",
|
||||
"Disable Auth": "Deshabilitar Autenticación ",
|
||||
"Enable Auth": "Habilitar Autenticación ",
|
||||
"Disable Auth": "Deshabilitar Autenticación",
|
||||
"Enable Auth": "Habilitar Autenticación",
|
||||
Logout: "Cerrar sesión",
|
||||
Leave: "Salir",
|
||||
"I understand, please disable": "Lo comprendo, por favor deshabilitar",
|
||||
"I understand, please disable": "Entiendo, por favor deshabilitar",
|
||||
Confirm: "Confirmar",
|
||||
Yes: "Sí",
|
||||
No: "No",
|
||||
|
@ -100,7 +100,7 @@ export default {
|
|||
"Notification Type": "Tipo de notificación",
|
||||
Email: "Email",
|
||||
Test: "Test",
|
||||
"Certificate Info": "Información del certificado ",
|
||||
"Certificate Info": "Información del certificado",
|
||||
"Resolver Server": "Servidor de resolución",
|
||||
"Resource Record Type": "Tipo de Registro",
|
||||
"Last Result": "Último resultado",
|
||||
|
@ -108,75 +108,94 @@ export default {
|
|||
"Repeat Password": "Repetir contraseña",
|
||||
respTime: "Tiempo de resp. (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
Create: "Create",
|
||||
clearEventsMsg: "Are you sure want to delete all events for this monitor?",
|
||||
clearHeartbeatsMsg: "Are you sure want to delete all heartbeats for this monitor?",
|
||||
confirmClearStatisticsMsg: "Are you sure want to delete ALL statistics?",
|
||||
"Clear Data": "Clear Data",
|
||||
Events: "Events",
|
||||
Heartbeats: "Heartbeats",
|
||||
"Auto Get": "Auto Get",
|
||||
enableDefaultNotificationDescription: "For every new monitor this notification will be enabled by default. You can still disable the notification separately for each monitor.",
|
||||
"Default enabled": "Default enabled",
|
||||
"Also apply to existing monitors": "Also apply to existing monitors",
|
||||
Export: "Export",
|
||||
Import: "Import",
|
||||
backupDescription: "You can backup all monitors and all notifications into a JSON file.",
|
||||
backupDescription2: "PS: History and event data is not included.",
|
||||
backupDescription3: "Sensitive data such as notification tokens is included in the export file, please keep it carefully.",
|
||||
alertNoFile: "Please select a file to import.",
|
||||
alertWrongFileType: "Please select a JSON file.",
|
||||
twoFAVerifyLabel: "Please type in your token to verify that 2FA is working",
|
||||
tokenValidSettingsMsg: "Token is valid! You can now save the 2FA settings.",
|
||||
confirmEnableTwoFAMsg: "Are you sure you want to enable 2FA?",
|
||||
confirmDisableTwoFAMsg: "Are you sure you want to disable 2FA?",
|
||||
"Apply on all existing monitors": "Apply on all existing monitors",
|
||||
"Verify Token": "Verify Token",
|
||||
"Setup 2FA": "Setup 2FA",
|
||||
"Enable 2FA": "Enable 2FA",
|
||||
"Disable 2FA": "Disable 2FA",
|
||||
"2FA Settings": "2FA Settings",
|
||||
"Two Factor Authentication": "Two Factor Authentication",
|
||||
Active: "Active",
|
||||
Inactive: "Inactive",
|
||||
Create: "Crear",
|
||||
clearEventsMsg: "¿Está seguro de que desea eliminar todos los eventos de este monitor?",
|
||||
clearHeartbeatsMsg: "¿Está seguro de que desea eliminar todos los latidos de este monitor?",
|
||||
confirmClearStatisticsMsg: "¿Está seguro de que desea eliminar TODAS las estadísticas?",
|
||||
"Clear Data": "Borrar Datos",
|
||||
Events: "Eventos",
|
||||
Heartbeats: "Latidos",
|
||||
"Auto Get": "Obtener automáticamente",
|
||||
enableDefaultNotificationDescription: "Para cada nuevo monitor, esta notificación estará habilitada de forma predeterminada. Aún puede deshabilitar la notificación por separado para cada monitor.",
|
||||
"Default enabled": "Habilitado por defecto",
|
||||
"Also apply to existing monitors": "También se aplica a monitores existentes",
|
||||
Export: "Exportar",
|
||||
Import: "Importar",
|
||||
backupDescription: "Puede hacer una copia de seguridad de todos los monitores y todas las notificaciones en un archivo JSON.",
|
||||
backupDescription2: "PD: el historial y los datos de eventos no están incluidos.",
|
||||
backupDescription3: "Los datos confidenciales, como los tokens de notificación, se incluyen en el archivo de exportación. Guárdelo con cuidado.",
|
||||
alertNoFile: "Seleccione un archivo para importar.",
|
||||
alertWrongFileType: "Seleccione un archivo JSON.",
|
||||
twoFAVerifyLabel: "Ingrese su token para verificar que 2FA está funcionando",
|
||||
tokenValidSettingsMsg: "¡El token es válido! Ahora puede guardar la configuración de 2FA.",
|
||||
confirmEnableTwoFAMsg: "¿Estás seguro de que quieres habilitar 2FA?",
|
||||
confirmDisableTwoFAMsg: "¿Estás seguro de que quieres desactivar 2FA?",
|
||||
"Apply on all existing monitors": "Aplicar en todos los monitores existentes",
|
||||
"Verify Token": "Verificar token",
|
||||
"Setup 2FA": "Configurar 2FA",
|
||||
"Enable 2FA": "Habilitar 2FA",
|
||||
"Disable 2FA": "Desactivar 2FA",
|
||||
"2FA Settings": "Ajustes 2FA",
|
||||
"Two Factor Authentication": "Autenticación de dos factores",
|
||||
Active: "Activo",
|
||||
Inactive: "Inactivo",
|
||||
Token: "Token",
|
||||
"Show URI": "Show URI",
|
||||
"Clear all statistics": "Clear all Statistics",
|
||||
retryCheckEverySecond: "Retry every {0} seconds.",
|
||||
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
|
||||
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
|
||||
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
|
||||
"Import Backup": "Import Backup",
|
||||
"Export Backup": "Export Backup",
|
||||
"Skip existing": "Skip existing",
|
||||
Overwrite: "Overwrite",
|
||||
Options: "Options",
|
||||
"Keep both": "Keep both",
|
||||
Tags: "Tags",
|
||||
"Add New below or Select...": "Add New below or Select...",
|
||||
"Tag with this name already exist.": "Tag with this name already exist.",
|
||||
"Tag with this value already exist.": "Tag with this value already exist.",
|
||||
"Show URI": "Mostrar URI",
|
||||
"Clear all statistics": "Borrar todas las estadísticas",
|
||||
retryCheckEverySecond: "Reintentar cada {0} segundo.",
|
||||
importHandleDescription: "Elija 'Omitir existente' si desea omitir todos los monitores o notificaciones con el mismo nombre. 'Sobrescribir' eliminará todos los monitores y notificaciones existentes.",
|
||||
confirmImportMsg: "¿Estás seguro de importar la copia de seguridad? Asegúrese de haber seleccionado la opción de importación correcta.",
|
||||
"Heartbeat Retry Interval": "Intervalo de reintento de latido",
|
||||
"Import Backup": "Importar copia de seguridad",
|
||||
"Export Backup": "Exportar copia de seguridad",
|
||||
"Skip existing": "Omitir existente",
|
||||
Overwrite: "Sobrescribir",
|
||||
Options: "Opciones",
|
||||
"Keep both": "Mantén ambos",
|
||||
Tags: "Etiquetas",
|
||||
"Add New below or Select...": "Agregar nuevo a continuación o Seleccionar...",
|
||||
"Tag with this name already exist.": "La etiqueta con este nombre ya existe.",
|
||||
"Tag with this value already exist.": "La etiqueta con este valor ya existe.",
|
||||
color: "color",
|
||||
"value (optional)": "value (optional)",
|
||||
Gray: "Gray",
|
||||
Red: "Red",
|
||||
Orange: "Orange",
|
||||
Green: "Green",
|
||||
Blue: "Blue",
|
||||
Indigo: "Indigo",
|
||||
Purple: "Purple",
|
||||
Pink: "Pink",
|
||||
"Search...": "Search...",
|
||||
"Avg. Ping": "Avg. Ping",
|
||||
"Avg. Response": "Avg. Response",
|
||||
"Entry Page": "Entry Page",
|
||||
statusPageNothing: "Nothing here, please add a group or a monitor.",
|
||||
"No Services": "No Services",
|
||||
"All Systems Operational": "All Systems Operational",
|
||||
"Partially Degraded Service": "Partially Degraded Service",
|
||||
"Degraded Service": "Degraded Service",
|
||||
"Add Group": "Add Group",
|
||||
"Add a monitor": "Add a monitor",
|
||||
"Edit Status Page": "Edit Status Page",
|
||||
"Go to Dashboard": "Go to Dashboard",
|
||||
"value (optional)": "valor (opcional)",
|
||||
Gray: "Gris",
|
||||
Red: "Rojo",
|
||||
Orange: "Naranja",
|
||||
Green: "Verde",
|
||||
Blue: "Azul",
|
||||
Indigo: "Índigo",
|
||||
Purple: "Morado",
|
||||
Pink: "Rosa",
|
||||
"Search...": "Buscar...",
|
||||
"Avg. Ping": "Ping promedio",
|
||||
"Avg. Response": "Respuesta promedio",
|
||||
"Entry Page": "Página de entrada",
|
||||
statusPageNothing: "No hay nada aquí, agregue un grupo o un monitor.",
|
||||
"No Services": "Sin servicio",
|
||||
"All Systems Operational": "Todos los sistemas están operativos",
|
||||
"Partially Degraded Service": "Servicio parcialmente degradado",
|
||||
"Degraded Service": "Servicio degradado",
|
||||
"Add Group": "Agregar Grupo",
|
||||
"Add a monitor": "Agregar un monitor",
|
||||
"Edit Status Page": "Editar página de estado",
|
||||
"Go to Dashboard": "Ir al panel de control",
|
||||
"Status Page": "Página de estado",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "Email (SMTP)",
|
||||
discord: "Discord",
|
||||
teams: "Microsoft Teams",
|
||||
signal: "Signal",
|
||||
gotify: "Gotify",
|
||||
slack: "Slack",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Admite más de 50 servicios de notificación)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ export default {
|
|||
rrtypeDescription: "Vali kirje tüüp, mida soovid jälgida.",
|
||||
pauseMonitorMsg: "Kas soovid peatada seire?",
|
||||
Settings: "Seaded",
|
||||
"Status Page": "Ülevaade", // hääletuse tulemus, teine: seisundileht, kolmas: Olukord/Olek
|
||||
"Status Page": "Ülevaade",
|
||||
Dashboard: "Töölaud",
|
||||
"New Update": "Uuem tarkvara versioon on saadaval.",
|
||||
Language: "Keel",
|
||||
|
@ -44,7 +44,7 @@ export default {
|
|||
Edit: "Muuda",
|
||||
Delete: "Eemalda",
|
||||
Current: "Hetkeseisund",
|
||||
Uptime: "Eluiga", // todo: launchpad?
|
||||
Uptime: "Eluiga",
|
||||
"Cert Exp.": "Sert. aegumine",
|
||||
days: "päeva",
|
||||
day: "päev",
|
||||
|
@ -109,7 +109,7 @@ export default {
|
|||
"Create your admin account": "Admininstraatori konto loomine",
|
||||
"Repeat Password": "korda salasõna",
|
||||
respTime: "Reageerimisaeg (ms)",
|
||||
notAvailableShort: "N/A", // tõlkimata, umbkaudu rahvusvaheline termin peaks sobima piisavalt
|
||||
notAvailableShort: "N/A",
|
||||
enableDefaultNotificationDescription: "Kõik järgnevalt lisatud seired kasutavad seda teavitusteenuset. Seiretelt võib teavitusteenuse ühekaupa eemaldada.",
|
||||
clearEventsMsg: "Kas soovid seire kõik sündmused kustutada?",
|
||||
clearHeartbeatsMsg: "Kas soovid seire kõik tuksed kustutada?",
|
||||
|
@ -122,7 +122,7 @@ export default {
|
|||
"Clear Data": "Eemalda andmed",
|
||||
Events: "Sündmused",
|
||||
Heartbeats: "Tuksed",
|
||||
"Auto Get": "Hangi automaatselt", // hangi? kõlab liiga otsetõlge
|
||||
"Auto Get": "Hangi automaatselt",
|
||||
backupDescription: "Varunda kõik seired ja teavitused JSON faili.",
|
||||
backupDescription2: "PS: Varukoopia EI sisalda seirete ajalugu ja sündmustikku.",
|
||||
backupDescription3: "Varukoopiad sisaldavad teavitusteenusete pääsuvõtmeid.",
|
||||
|
@ -140,7 +140,7 @@ export default {
|
|||
"Two Factor Authentication": "Kaksikautentimine",
|
||||
Active: "kasutusel",
|
||||
Inactive: "seadistamata",
|
||||
Token: "kaksikautentimise kood", // needs to compensate for no title
|
||||
Token: "kaksikautentimise kood",
|
||||
"Show URI": "Näita URId",
|
||||
"Clear all statistics": "Tühjenda ajalugu",
|
||||
importHandleDescription: "'kombineeri' täiendab varukoopiast ja kirjutab üle samanimelised seireid ja teavitusteenused; 'lisa praegustele' jätab olemasolevad puutumata; 'asenda' kustutab ja asendab kõik seired ja teavitusteenused.",
|
||||
|
@ -150,14 +150,14 @@ export default {
|
|||
"Export Backup": "Varukoopia eksportimine",
|
||||
"Skip existing": "lisa praegustele",
|
||||
Overwrite: "asenda",
|
||||
Options: "Mestimisviis", // reusal of key would be chaos
|
||||
Options: "Mestimisviis",
|
||||
"Keep both": "kombineeri",
|
||||
Tags: "Sildid",
|
||||
"Add New below or Select...": "Leia või lisa all uus…",
|
||||
"Tag with this name already exist.": "Selle nimega silt on juba olemas.",
|
||||
"Tag with this value already exist.": "Selle väärtusega silt on juba olemas.",
|
||||
color: "värvus",
|
||||
"value (optional)": "väärtus (fakultatiivne)", // milline sõna!
|
||||
"value (optional)": "väärtus (fakultatiivne)",
|
||||
Gray: "hall",
|
||||
Red: "punane",
|
||||
Orange: "oranž",
|
||||
|
@ -167,7 +167,7 @@ export default {
|
|||
Purple: "lilla",
|
||||
Pink: "roosa",
|
||||
"Search...": "Otsi…",
|
||||
"Avg. Ping": "Keskmine ping", // pikk, aga nagunii kahel real
|
||||
"Avg. Ping": "Keskmine ping",
|
||||
"Avg. Response": "Keskmine reaktsiooniaeg",
|
||||
"Entry Page": "Avaleht",
|
||||
statusPageNothing: "Kippu ega kõppu; siia saab lisada seireid või -gruppe.",
|
||||
|
@ -178,4 +178,23 @@ export default {
|
|||
"Add Group": "Lisa grupp",
|
||||
"Edit Status Page": "Muuda lehte",
|
||||
"Go to Dashboard": "Töölauale",
|
||||
checkEverySecond: "Kontrolli peale tõrget {0} sekundilise vahega.",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "elektronpost (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 (vahendab üle 65 teavitusteenust)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "LINE",
|
||||
mattermost: "Mattermost",
|
||||
};
|
||||
|
|
|
@ -186,5 +186,23 @@ export default {
|
|||
First: "اولین",
|
||||
Last: "آخرین",
|
||||
Info: "اطلاعات",
|
||||
"Powered By": "نیرو گرفته از",
|
||||
"Powered by": "نیرو گرفته از",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "Email (SMTP)",
|
||||
discord: "Discord",
|
||||
teams: "Microsoft Teams",
|
||||
signal: "Signal",
|
||||
gotify: "Gotify",
|
||||
slack: "Slack",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
};
|
||||
|
|
|
@ -1,5 +1,31 @@
|
|||
export default {
|
||||
languageName: "Français (France)",
|
||||
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.",
|
||||
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",
|
||||
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 ?",
|
||||
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.",
|
||||
resoverserverDescription: "Le DNS de cloudflare est utilisé par défaut, mais vous pouvez le changer si vous le souhaitez.",
|
||||
rrtypeDescription: "Veuillez séléctionner un type d'enregistrement DNS",
|
||||
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 tous les vérifications pour cette sonde ?",
|
||||
confirmClearStatisticsMsg: "Êtes-vous sûr de vouloir supprimer tous 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.",
|
||||
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 ?",
|
||||
Settings: "Paramètres",
|
||||
Dashboard: "Tableau de bord",
|
||||
"New Update": "Mise à jour disponible",
|
||||
|
@ -18,7 +44,6 @@ export default {
|
|||
Pending: "En attente",
|
||||
Unknown: "Inconnu",
|
||||
Pause: "En Pause",
|
||||
pauseDashboardHome: "Éléments mis en pause",
|
||||
Name: "Nom",
|
||||
Status: "État",
|
||||
DateTime: "Heure",
|
||||
|
@ -29,32 +54,27 @@ export default {
|
|||
Delete: "Supprimer",
|
||||
Current: "Actuellement",
|
||||
Uptime: "Uptime",
|
||||
"Cert Exp.": "Certificat expiré",
|
||||
days: "Jours",
|
||||
day: "Jour",
|
||||
"-day": "Journée",
|
||||
hour: "Heure",
|
||||
"-hour": "Heures",
|
||||
checkEverySecond: "Vérifier toutes les {0} secondes",
|
||||
"Cert Exp.": "Expiration SSL",
|
||||
days: "jours",
|
||||
day: "jour",
|
||||
"-day": "-jours",
|
||||
hour: "-heure",
|
||||
"-hour": "-heures",
|
||||
Response: "Temps de réponse",
|
||||
Ping: "Ping",
|
||||
"Monitor Type": "Type de Sonde",
|
||||
Keyword: "Mot-clé",
|
||||
"Friendly Name": "Nom d'affichage",
|
||||
URL: "URL",
|
||||
Hostname: "Nom d'hôte",
|
||||
Hostname: "Nom d'hôte / adresse IP",
|
||||
Port: "Port",
|
||||
"Heartbeat Interval": "Intervale de vérification",
|
||||
Retries: "Essais",
|
||||
retriesDescription: "Nombre d'essais avant que le service soit déclaré hors-ligne.",
|
||||
"Heartbeat Retry Interval": "Réessayer l'intervale de vérification",
|
||||
Advanced: "Avancé",
|
||||
ignoreTLSError: "Ignorer les erreurs liées au certificat SSL/TLS",
|
||||
"Upside Down Mode": "Mode inversé",
|
||||
upsideDownModeDescription: "Si le service est en ligne, il sera alors noté hors-ligne et vice-versa.",
|
||||
"Max. Redirects": "Nombre maximum de redirections",
|
||||
maxRedirectDescription: "Nombre maximal de redirections avant que le service soit noté hors-ligne.",
|
||||
"Accepted Status Codes": "Codes HTTP",
|
||||
acceptedStatusCodesDescription: "Codes HTTP considérés comme en ligne",
|
||||
"Accepted Status Codes": "Codes HTTP acceptés",
|
||||
Save: "Sauvegarder",
|
||||
Notifications: "Notifications",
|
||||
"Not available, please setup.": "Pas de système de notification disponible, merci de le configurer",
|
||||
|
@ -63,9 +83,9 @@ export default {
|
|||
Dark: "Sombre",
|
||||
Auto: "Automatique",
|
||||
"Theme - Heartbeat Bar": "Voir les services surveillés",
|
||||
Normal: "Général",
|
||||
Normal: "Normal",
|
||||
Bottom: "En dessous",
|
||||
None: "Rien",
|
||||
None: "Aucun",
|
||||
Timezone: "Fuseau Horaire",
|
||||
"Search Engine Visibility": "Visibilité par les moteurs de recherche",
|
||||
"Allow indexing": "Autoriser l'indexation par des moteurs de recherche",
|
||||
|
@ -74,14 +94,12 @@ export default {
|
|||
"Current Password": "Mot de passe actuel",
|
||||
"New Password": "Nouveau mot de passe",
|
||||
"Repeat New Password": "Répéter votre nouveau mot de passe",
|
||||
passwordNotMatchMsg: "Les mots de passe ne correspondent pas",
|
||||
"Update Password": "Mettre à jour le mot de passe",
|
||||
"Disable Auth": "Désactiver l'authentification",
|
||||
"Enable Auth": "Activer l'authentification",
|
||||
Logout: "Se déconnecter",
|
||||
notificationDescription: "Une fois ajoutée, vous devez l'activer manuellement dans les paramètres de vos hôtes.",
|
||||
Leave: "Quitter",
|
||||
"I understand, please disable": "J'ai compris, désactivez-le",
|
||||
"I understand, please disable": "Je comprends, désactivez-le",
|
||||
Confirm: "Confirmer",
|
||||
Yes: "Oui",
|
||||
No: "Non",
|
||||
|
@ -94,43 +112,35 @@ export default {
|
|||
"Notification Type": "Type de notification",
|
||||
Email: "Email",
|
||||
Test: "Tester",
|
||||
keywordDescription: "Le mot clé sera recherché dans la réponse HTML/JSON reçue du site internet.",
|
||||
"Certificate Info": "Informations sur le certificat SSL",
|
||||
deleteMonitorMsg: "Êtes-vous sûr de vouloir supprimer cette sonde ?",
|
||||
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.",
|
||||
"Resolver Server": "Serveur DNS utilisé",
|
||||
"Resource Record Type": "Type d'enregistrement DNS recherché",
|
||||
resoverserverDescription: "Le DNS de cloudflare est utilisé par défaut, mais vous pouvez le changer si vous le souhaitez.",
|
||||
rrtypeDescription: "Veuillez séléctionner un type d'enregistrement DNS",
|
||||
pauseMonitorMsg: "Etes vous sur de vouloir mettre en pause cette sonde ?",
|
||||
"Last Result": "Dernier résultat",
|
||||
"Create your admin account": "Créez votre compte administrateur",
|
||||
"Repeat Password": "Répéter le mot de passe",
|
||||
"Import Backup": "Importation de la sauvegarde",
|
||||
"Export Backup": "Exportation de la sauvegarde",
|
||||
Export: "Exporter",
|
||||
Import: "Importer",
|
||||
respTime: "Temps de réponse (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
"Default enabled": "Activé par défaut",
|
||||
"Apply on all existing monitors": "Appliquer sur toutes les sondes existantes",
|
||||
Create: "Créer",
|
||||
clearEventsMsg: "Êtes-vous sûr de vouloir supprimer tous les événements pour cette sonde ?",
|
||||
clearHeartbeatsMsg: "Êtes-vous sûr de vouloir supprimer tous les vérifications pour cette sonde ? Are you sure want to delete all heartbeats for this monitor?",
|
||||
confirmClearStatisticsMsg: "tes-vous sûr de vouloir supprimer tous les statistiques ?",
|
||||
"Clear Data": "Effacer les données",
|
||||
Events: "Evénements",
|
||||
Heartbeats: "Vérfications",
|
||||
"Auto Get": "Auto Get",
|
||||
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.",
|
||||
"Default enabled": "Activé par défaut",
|
||||
"Also apply to existing monitors": "S'applique également aux sondes existantes",
|
||||
Export: "Exporter",
|
||||
Import: "Importer",
|
||||
"Auto Get": "Récuperer 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.",
|
||||
alertNoFile: "Veuillez sélectionner un fichier à importer.",
|
||||
alertWrongFileType: "Veuillez sélectionner un fichier JSON à importer.",
|
||||
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 ?",
|
||||
"Apply on all existing monitors": "Appliquer sur toutes les sondes existantes",
|
||||
"Clear all statistics": "Effacer toutes les statistiques",
|
||||
"Skip existing": "Sauter l'existant",
|
||||
Overwrite: "Ecraser",
|
||||
Options: "Options",
|
||||
"Keep both": "Garder les deux",
|
||||
"Verify Token": "Vérifier le jeton",
|
||||
"Setup 2FA": "Configurer 2FA",
|
||||
"Enable 2FA": "Activer 2FA",
|
||||
|
@ -141,23 +151,12 @@ export default {
|
|||
Inactive: "Inactif",
|
||||
Token: "Jeton",
|
||||
"Show URI": "Afficher l'URI",
|
||||
"Clear all statistics": "Effacer touutes les statistiques",
|
||||
retryCheckEverySecond: "Réessayer toutes les {0} secondes.",
|
||||
importHandleDescription: "Choisissez 'Ignorer l'existant' si vous voulez ignorer chaque sonde ou notification portant le même nom. L'option 'Écraser' supprime tous les sondes et notifications existantes.",
|
||||
confirmImportMsg: "Êtes-vous sûr d'importer la sauvegarde ? Veuillez vous assurer que vous avez sélectionné la bonne option d'importation.",
|
||||
"Heartbeat Retry Interval": "Réessayer l'intervale de vérification",
|
||||
"Import Backup": "Importation de la sauvegarde",
|
||||
"Export Backup": "Exportation de la sauvegarde",
|
||||
"Skip existing": "Sauter l'existant",
|
||||
Overwrite: "Ecraser",
|
||||
Options: "Options",
|
||||
"Keep both": "Garder les deux",
|
||||
Tags: "Étiquettes",
|
||||
"Add New below or Select...": "Ajouter nouveau ci-dessous ou sélectionner...",
|
||||
"Add New below or Select...": "Ajoutez-en un en dessous ou sélectionnez-le ici...",
|
||||
"Tag with this name already exist.": "Une étiquette portant ce nom existe déjà.",
|
||||
"Tag with this value already exist.": "Une étiquette avec cette valeur existe déjà.",
|
||||
color: "couleur",
|
||||
"value (optional)": "valeur (facultatif)",
|
||||
color: "Couleur",
|
||||
"value (optional)": "Valeur (facultatif)",
|
||||
Gray: "Gris",
|
||||
Red: "Rouge",
|
||||
Orange: "Orange",
|
||||
|
@ -170,7 +169,7 @@ export default {
|
|||
"Avg. Ping": "Ping moyen",
|
||||
"Avg. Response": "Réponse moyenne",
|
||||
"Entry Page": "Page d'accueil",
|
||||
"statusPageNothing": "Rien ici, veuillez ajouter un groupe ou une sonde.",
|
||||
statusPageNothing: "Rien ici, veuillez ajouter un groupe ou une sonde.",
|
||||
"No Services": "Aucun service",
|
||||
"All Systems Operational": "Tous les systèmes sont opérationnels",
|
||||
"Partially Degraded Service": "Service partiellement dégradé",
|
||||
|
@ -179,4 +178,107 @@ export default {
|
|||
"Add a monitor": "Ajouter une sonde",
|
||||
"Edit Status Page": "Modifier la page de statut",
|
||||
"Go to Dashboard": "Accéder au tableau de bord",
|
||||
"Status Page": "Status Page",
|
||||
// Start notification form
|
||||
defaultNotificationName: "Ma notification {notification} numéro ({number})",
|
||||
here: "ici",
|
||||
"Required": "Requis",
|
||||
"telegram": "Telegram",
|
||||
"Bot Token": "Bot Token",
|
||||
"You can get a token from": "Vous pouvez obtenir un token depuis",
|
||||
"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",
|
||||
"webhook": "Webhook",
|
||||
"Post URL": "Post URL",
|
||||
"Content Type": "Content Type",
|
||||
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)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "Ignorer les erreurs TLS",
|
||||
"From Email": "Depuis l'Email",
|
||||
"To Email": "Vers l'Email",
|
||||
smtpCC: "CC",
|
||||
smtpBCC: "BCC",
|
||||
"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": "Prefix Custom Message",
|
||||
"Hello @everyone is...": "Bonjour {'@'}everyone il...",
|
||||
"teams": "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "Vous pouvez apprendre comment créer un 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 :",
|
||||
signalImportant: "IMPORTANT: Vous ne pouvez pas mixer les groupes et les numéros en destinataires !",
|
||||
"gotify": "Gotify",
|
||||
"Application Token": "Application Token",
|
||||
"Server URL": "Server URL",
|
||||
"Priority": "Priorité",
|
||||
"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",
|
||||
aboutKumaURL: "Si vous laissez l'URL d'Uptime Kuma vierge, elle redirigera vers la page du projet GitHub.",
|
||||
emojiCheatSheet: "Emoji cheat sheet : {0}",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "Clé d'utilisateur",
|
||||
"Device": "Appareil",
|
||||
"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: "A 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érn., 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}",
|
||||
"Read more:": "En savoir plus : {0}",
|
||||
"Status:": "Status : {0}",
|
||||
"Read more": "En savoir plus",
|
||||
appriseInstalled: "Apprise est intallé.",
|
||||
appriseNotInstalled: "Apprise n'est pas intallé. {0}",
|
||||
"Access Token": "Access Token",
|
||||
"Channel access token": "Channel access token",
|
||||
"Line Developers Console": "Line Developers Console",
|
||||
lineDevConsoleTo: "Line Developers Console - {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",
|
||||
"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",
|
||||
// End notification form
|
||||
};
|
||||
|
|
|
@ -178,4 +178,23 @@ export default {
|
|||
"Add a monitor": "Figyelő hozzáadása",
|
||||
"Edit Status Page": "Sátusz oldal szerkesztése",
|
||||
"Go to Dashboard": "Menj az irányítópulthoz",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "Email (SMTP)",
|
||||
discord: "Discord",
|
||||
teams: "Microsoft Teams",
|
||||
signal: "Signal",
|
||||
gotify: "Gotify",
|
||||
slack: "Slack",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"Status Page": "Status Page",
|
||||
};
|
||||
|
|
285
src/languages/id-ID.js
Normal file
285
src/languages/id-ID.js
Normal file
|
@ -0,0 +1,285 @@
|
|||
export default {
|
||||
languageName: "Indonesia",
|
||||
checkEverySecond: "Cek Setiap {0} detik.",
|
||||
retryCheckEverySecond: "Coba lagi setiap {0} detik.",
|
||||
retriesDescription: "Percobaan ulang maksimum sebelum layanan dinyatakan tidak aktif dan notifikasi dikirim",
|
||||
ignoreTLSError: "Abaikan kesalahan TLS/SSL untuk situs web HTTPS",
|
||||
upsideDownModeDescription: "Balikkan statusnya. Jika layanan dapat dijangkau, TIDAK AKTIF.",
|
||||
maxRedirectDescription: "Jumlah maksimum pengalihan untuk diikuti. Setel ke 0 untuk menonaktifkan pengalihan.",
|
||||
acceptedStatusCodesDescription: "Pilih kode status yang dianggap sebagai respons yang berhasil.",
|
||||
passwordNotMatchMsg: "Sandi kedua tidak cocok.",
|
||||
notificationDescription: "Harap atur notifikasi ke monitor agar berfungsi.",
|
||||
keywordDescription: "Cari kata kunci dalam code html atau JSON huruf besar-kecil berpengaruh",
|
||||
pauseDashboardHome: "Jeda",
|
||||
deleteMonitorMsg: "Apakah anda mau menghapus monitor ini?",
|
||||
deleteNotificationMsg: "Apakah anda mau menghapus notifikasi ini untuk semua monitor?",
|
||||
resoverserverDescription: "Cloudflare adalah server default, Anda dapat mengubah server resolver kapan saja.",
|
||||
rrtypeDescription: "Pilih RR-Type yang mau anda monitor",
|
||||
pauseMonitorMsg: "Apakah anda yakin mau menjeda?",
|
||||
enableDefaultNotificationDescription: "Untuk setiap monitor baru, notifikasi ini akan diaktifkan secara default. Anda masih dapat menonaktifkan notifikasi secara terpisah untuk setiap monitor.",
|
||||
clearEventsMsg: "Apakah anda yakin mau menghapus semua event di monitor ini?",
|
||||
clearHeartbeatsMsg: "Apakah anda yakin mau menghapus semua heartbeats di monitor ini?",
|
||||
confirmClearStatisticsMsg: "Apakah anda yakin mau menghapus semua statistik?",
|
||||
importHandleDescription: "Pilih 'Lewati yang ada' jika Anda ingin melewati setiap monitor atau notifikasi dengan nama yang sama. 'Timpa' akan menghapus setiap monitor dan notifikasi yang ada.",
|
||||
confirmImportMsg: "Apakah Anda yakin untuk mengimpor cadangan? Pastikan Anda telah memilih opsi impor yang tepat.",
|
||||
twoFAVerifyLabel: "Silakan ketik token Anda untuk memverifikasi bahwa 2FA berfungsi",
|
||||
tokenValidSettingsMsg: "Tokennya valid! Anda sekarang dapat menyimpan pengaturan 2FA.",
|
||||
confirmEnableTwoFAMsg: "Apakah Anda yakin ingin mengaktifkan 2FA?",
|
||||
confirmDisableTwoFAMsg: "Apakah Anda yakin ingin menonaktifkan 2FA?",
|
||||
Settings: "Pengaturan",
|
||||
Dashboard: "Dashboard",
|
||||
"New Update": "Update Baru",
|
||||
Language: "Bahasa",
|
||||
Appearance: "Tampilan",
|
||||
Theme: "Tema",
|
||||
General: "General",
|
||||
Version: "Versi",
|
||||
"Check Update On GitHub": "Cek Update di GitHub",
|
||||
List: "List",
|
||||
Add: "Tambah",
|
||||
"Add New Monitor": "Tambah Monitor Baru",
|
||||
"Quick Stats": "Statistik Cepat",
|
||||
Up: "Aktif",
|
||||
Down: "Tidak Aktif",
|
||||
Pending: "Tertunda",
|
||||
Unknown: "Tidak diketahui",
|
||||
Pause: "Jeda",
|
||||
Name: "Nama",
|
||||
Status: "Status",
|
||||
DateTime: "Tanggal Waktu",
|
||||
Message: "Pesan",
|
||||
"No important events": "Tidak ada Event penting",
|
||||
Resume: "Melanjutkan",
|
||||
Edit: "Rubah",
|
||||
Delete: "Hapus",
|
||||
Current: "Saat ini",
|
||||
Uptime: "Waktu aktif",
|
||||
"Cert Exp.": "Cert Exp.",
|
||||
days: "hari-hari",
|
||||
day: "hari",
|
||||
"-day": "-hari",
|
||||
hour: "Jam",
|
||||
"-hour": "-Jam",
|
||||
Response: "Respon",
|
||||
Ping: "Ping",
|
||||
"Monitor Type": "Tipe Monitor",
|
||||
Keyword: "Keyword",
|
||||
"Friendly Name": "Friendly Name",
|
||||
URL: "URL",
|
||||
Hostname: "Hostname",
|
||||
Port: "Port",
|
||||
"Heartbeat Interval": "Interval Heartbeat ",
|
||||
Retries: "Retries",
|
||||
"Heartbeat Retry Interval": "Interval Heartbeat Mencoba kembali ",
|
||||
Advanced: "Advanced",
|
||||
"Upside Down Mode": "Mode Terbalik",
|
||||
"Max. Redirects": "Maksimal Redirect/Pengalihan",
|
||||
"Accepted Status Codes": "Kode Status yang Diterima",
|
||||
Save: "Simpan",
|
||||
Notifications: "Notifikasi",
|
||||
"Not available, please setup.": "Tidak tersedia, silakan atur.",
|
||||
"Setup Notification": "Setel Notifikasi",
|
||||
Light: "Terang",
|
||||
Dark: "Gelap",
|
||||
Auto: "Automatis",
|
||||
"Theme - Heartbeat Bar": "Theme - Heartbeat Bar",
|
||||
Normal: "Normal",
|
||||
Bottom: "Bawah",
|
||||
None: "Tidak ada",
|
||||
Timezone: "Zona Waktu",
|
||||
"Search Engine Visibility": "Visibilitas Mesin Pencari",
|
||||
"Allow indexing": "Mengizinkan untuk diindex",
|
||||
"Discourage search engines from indexing site": "Mencegah mesin pencari untuk mengindex site",
|
||||
"Change Password": "Ganti Sandi",
|
||||
"Current Password": "Sandi Lama",
|
||||
"New Password": "Sandi Baru",
|
||||
"Repeat New Password": "Ulangi Sandi Baru",
|
||||
"Update Password": "Perbarui Kata Sandi",
|
||||
"Disable Auth": "Nonaktifkan auth",
|
||||
"Enable Auth": "Aktifkan Auth",
|
||||
Logout: "Keluar",
|
||||
Leave: "Pergi",
|
||||
"I understand, please disable": "Saya mengerti, silahkan dinonaktifkan",
|
||||
Confirm: "Konfirmasi",
|
||||
Yes: "Ya",
|
||||
No: "Tidak",
|
||||
Username: "Nama Pengguna",
|
||||
Password: "Sandi",
|
||||
"Remember me": "Ingat saya",
|
||||
Login: "Masuk",
|
||||
"No Monitors, please": "Tidak ada monitor, silahkan",
|
||||
"add one": "tambah baru",
|
||||
"Notification Type": "Tipe Notifikasi",
|
||||
Email: "Email",
|
||||
Test: "Test",
|
||||
"Certificate Info": "Info Sertifikasi ",
|
||||
"Resolver Server": "Resolver Server",
|
||||
"Resource Record Type": "Resource Record Type",
|
||||
"Last Result": "Hasil Terakhir",
|
||||
"Create your admin account": "Buat admin akun anda",
|
||||
"Repeat Password": "Ulangi Sandi",
|
||||
"Import Backup": "Impor Backup",
|
||||
"Export Backup": "Expor Backup",
|
||||
Export: "Expor",
|
||||
Import: "Impor",
|
||||
respTime: "Tanggapan. Waktu (milidetik)",
|
||||
notAvailableShort: "N/A",
|
||||
"Default enabled": "Default diaktifkan",
|
||||
"Apply on all existing monitors": "Terapkan pada semua monitor yang ada",
|
||||
Create: "Buat",
|
||||
"Clear Data": "Bersihkan Data",
|
||||
Events: "Event",
|
||||
Heartbeats: "Heartbeats",
|
||||
"Auto Get": "Auto Get",
|
||||
backupDescription: "Anda dapat mencadangkan semua monitor dan semua notifikasi ke dalam file JSON.",
|
||||
backupDescription2: "Catatan: Data sejarah dan event tidak disertakan.",
|
||||
backupDescription3: "Data sensitif seperti notifikasi token disertakan dalam file ekspor, harap simpan dengan hati-hati.",
|
||||
alertNoFile: "Silakan pilih file untuk diimpor.",
|
||||
alertWrongFileType: "Silakan pilih file JSON .",
|
||||
"Clear all statistics": "Hapus semua statistik",
|
||||
"Skip existing": "Lewati yang ada",
|
||||
Overwrite: "Timpa",
|
||||
Options: "Opsi",
|
||||
"Keep both": "Simpan keduanya",
|
||||
"Verify Token": "Verifikasi Token",
|
||||
"Setup 2FA": "Pengaturan 2FA",
|
||||
"Enable 2FA": "Aktifkan 2FA",
|
||||
"Disable 2FA": "Nonaktifkan 2FA",
|
||||
"2FA Settings": "Settings 2FA",
|
||||
"Two Factor Authentication": "Otentikasi Dua Faktor",
|
||||
Active: "Aktif",
|
||||
Inactive: "Tidak Aktif",
|
||||
Token: "Token",
|
||||
"Show URI": "Lihat URI",
|
||||
Tags: "Tag",
|
||||
"Add New below or Select...": "Tambahkan Baru di bawah atau Pilih...",
|
||||
"Tag with this name already exist.": "Tag dengan nama ini sudah ada.",
|
||||
"Tag with this value already exist.": "Tag dengan nilai ini sudah ada.",
|
||||
color: "warna",
|
||||
"value (optional)": "nilai (harus diisi)",
|
||||
Gray: "Abu Abu",
|
||||
Red: "Merah",
|
||||
Orange: "Oranye",
|
||||
Green: "Hijau",
|
||||
Blue: "Biru",
|
||||
Indigo: "Indigo",
|
||||
Purple: "Ungu",
|
||||
Pink: "Merah Muda",
|
||||
"Search...": "Cari...",
|
||||
"Avg. Ping": "Rata-rata. Ping",
|
||||
"Avg. Response": "Rata-rata. Respon",
|
||||
"Entry Page": "Halaman Masuk",
|
||||
statusPageNothing: "Tidak ada di sini, silakan tambahkan grup atau monitor.",
|
||||
"No Services": "Tidak ada Layanan",
|
||||
"All Systems Operational": "Semua Sistem Berfungsi",
|
||||
"Partially Degraded Service": "Layanan Terdegradasi Sebagian",
|
||||
"Degraded Service": "Layanan Terdegradasi",
|
||||
"Add Group": "Tambah Grup",
|
||||
"Add a monitor": "Tambah monitor",
|
||||
"Edit Status Page": "Edit Halaman Status",
|
||||
"Go to Dashboard": "Lihat Dashboard",
|
||||
"Status Page": "Halaman Status",
|
||||
// Start notification form
|
||||
defaultNotificationName: "{notification} saya Peringatan ({number})",
|
||||
here: "di sini",
|
||||
"Required": "Dibutuhkan",
|
||||
"telegram": "Telegram",
|
||||
"Bot Token": "Bot Token",
|
||||
"You can get a token from": "Anda bisa mendapatkan token dari",
|
||||
"Chat ID": "Chat ID",
|
||||
supportTelegramChatID: "Mendukung Obrolan Langsung / Grup / Channel Chat ID",
|
||||
wayToGetTelegramChatID: "Anda bisa mendapatkan chat id Anda dengan mengirim pesan ke bot dan pergi ke url ini untuk melihat chat_id:",
|
||||
"YOUR BOT TOKEN HERE": "BOT TOKEN ANDA DI SINI",
|
||||
chatIDNotFound: "Chat ID tidak ditemukan, tolong kirim pesan ke bot ini dulu",
|
||||
"webhook": "Webhook",
|
||||
"Post URL": "Post URL",
|
||||
"Content Type": "Tipe konten",
|
||||
webhookJsonDesc: "{0} bagus untuk server http modern seperti express.js",
|
||||
webhookFormDataDesc: "{multipart} bagus untuk PHP, Anda hanya perlu mengurai json dengan {decodeFunction}",
|
||||
"smtp": "Email (SMTP)",
|
||||
secureOptionNone: "None / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "Ignore TLS Error",
|
||||
"From Email": "From Email",
|
||||
"To Email": "To Email",
|
||||
smtpCC: "CC",
|
||||
smtpBCC: "BCC",
|
||||
"discord": "Discord",
|
||||
"Discord Webhook URL": "Discord Webhook URL",
|
||||
wayToGetDiscordURL: "Anda bisa mendapatkan ini dengan pergi ke Server Settings -> Integrations -> Create Webhook",
|
||||
"Bot Display Name": "Nama Bot",
|
||||
"Prefix Custom Message": "Prefix Pesan",
|
||||
"Hello @everyone is...": "Hallo {'@'}everyone is...",
|
||||
"teams": "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "Anda dapat mempelajari cara membuat url webhook {0}.",
|
||||
"signal": "Sinyal",
|
||||
"Number": "Nomer",
|
||||
"Recipients": "Penerima",
|
||||
needSignalAPI: "Anda harus memiliki klien sinyal dengan REST API.",
|
||||
wayToCheckSignalURL: "Anda dapat memeriksa url ini untuk melihat cara menyiapkannya:",
|
||||
signalImportant: "PENTING: Anda tidak dapat mencampur grup dan nomor di penerima!",
|
||||
"gotify": "Gotify",
|
||||
"Application Token": "Token Aplikasi",
|
||||
"Server URL": "Server URL",
|
||||
"Priority": "Prioritas",
|
||||
"slack": "Slack",
|
||||
"Icon Emoji": "Icon Emoji",
|
||||
"Channel Name": "Nama Channel",
|
||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||
aboutWebhooks: "Info lain tentang webhook: {0}",
|
||||
aboutChannelName: "Masukan nama channel di {0} Kolom Nama Channel jika Anda ingin melewati channel webhook. Contoh: #other-channel",
|
||||
aboutKumaURL: "Jika Anda membiarkan bidang URL Uptime Kuma kosong, itu akan menjadi default ke halaman Project Github.",
|
||||
emojiCheatSheet: "Emoji cheat sheet: {0}",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Mendukung 50+ layanan notifikasi)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "Kunci pengguna",
|
||||
"Device": "Perangkat",
|
||||
"Message Title": "Judul Pesan",
|
||||
"Notification Sound": "Suara Nofifikasi",
|
||||
"More info on:": "Info lebih lanjut tentang: {0}",
|
||||
pushoverDesc1: "Prioritas darurat (2) memiliki batas waktu default 30 detik antara percobaan ulang dan akan kadaluwarsa setelah 1 jam.",
|
||||
pushoverDesc2: "Jika Anda ingin mengirim pemberitahuan ke perangkat yang berbeda, isi kolom Perangkat.",
|
||||
"SMS Type": "Tipe SMS",
|
||||
octopushTypePremium: "Premium (Cepat - direkomendasikan untuk mengingatkan)",
|
||||
octopushTypeLowCost: "Low Cost (Lambat, terkadang diblokir oleh operator)",
|
||||
"Check octopush prices": "Cek harga octopush {0}.",
|
||||
octopushPhoneNumber: "Nomer Telpon/HP (format internasional, contoh : +33612345678) ",
|
||||
octopushSMSSender: "Nama Pengirim SMS : 3-11 karakter alfanumerik dan spasi (a-zA-Z0-9)",
|
||||
"LunaSea Device ID": "LunaSea Device ID",
|
||||
"Apprise URL": "Apprise URL",
|
||||
"Example:": "Contoh: {0}",
|
||||
"Read more:": "Baca lebih lajut: {0}",
|
||||
"Status:": "Status: {0}",
|
||||
"Read more": "Baca lebih lajut",
|
||||
appriseInstalled: "Apprise diinstall.",
|
||||
appriseNotInstalled: "Apprise tidak diinstall. {0}",
|
||||
"Access Token": "Access Token",
|
||||
"Channel access token": "Channel access token",
|
||||
"Line Developers Console": "Line Developers Console",
|
||||
lineDevConsoleTo: "Line Developers Console - {0}",
|
||||
"Basic Settings": "Pengaturan dasar",
|
||||
"User ID": "User ID",
|
||||
"Messaging API": "Messaging API",
|
||||
wayToGetLineChannelToken: "Pertama akses {0}, buat penyedia dan saluran (Messaging API), lalu Anda bisa mendapatkan token akses saluran dan id pengguna dari item menu yang disebutkan di atas.",
|
||||
"Icon URL": "Icon URL",
|
||||
aboutIconURL: "Anda dapat memberikan tautan ke gambar di \"Icon URL\" untuk mengganti gambar profil default. Tidak akan digunakan jika Ikon Emoji diset.",
|
||||
aboutMattermostChannelName: "Anda dapat mengganti channel default tujuan posting webhook dengan memasukkan nama channel ke dalam Kolom \"Channel Name\". Ini perlu diaktifkan di pengaturan webhook Mattermost. contoh: #other-channel",
|
||||
"matrix": "Matrix",
|
||||
promosmsTypeEco: "SMS ECO - murah tapi lambat dan sering kelebihan beban. Terbatas hanya untuk penerima Polandia.",
|
||||
promosmsTypeFlash: "SMS FLASH - Pesan akan otomatis muncul di perangkat penerima. Terbatas hanya untuk penerima Polandia.",
|
||||
promosmsTypeFull: "SMS FULL - SMS tingkat premium, Anda dapat menggunakan Nama Pengirim Anda (Anda harus mendaftarkan nama terlebih dahulu). Dapat diandalkan untuk peringatan.",
|
||||
promosmsTypeSpeed: "SMS SPEED - Prioritas tertinggi dalam sistem. Sangat cepat dan dapat diandalkan tetapi mahal (sekitar dua kali lipat dari harga SMS FULL).",
|
||||
promosmsPhoneNumber: "Nomor telepon (untuk penerima Polandia Anda dapat melewati kode area)",
|
||||
promosmsSMSSender: "Nama Pengirim SMS : Nama pra-registrasi atau salah satu default: InfoSMS, Info SMS, MaxSMS, INFO, SMS",
|
||||
"Feishu WebHookUrl": "Feishu WebHookUrl",
|
||||
// End notification form
|
||||
};
|
|
@ -169,7 +169,7 @@ export default {
|
|||
"Avg. Ping": "Tempo di risposta al ping medio",
|
||||
"Avg. Response": "Tempo di risposta medio",
|
||||
"Entry Page": "Entry Page",
|
||||
"statusPageNothing": "Non c'è nulla qui, aggiungere un gruppo oppure un monitoraggio.",
|
||||
statusPageNothing: "Non c'è nulla qui, aggiungere un gruppo oppure un monitoraggio.",
|
||||
"No Services": "Nessun Servizio",
|
||||
"All Systems Operational": "Tutti i sistemi sono operativi",
|
||||
"Partially Degraded Service": "Servizio parzialmente degradato",
|
||||
|
@ -178,21 +178,109 @@ export default {
|
|||
"Add a monitor": "Aggiungi un monitoraggio",
|
||||
"Edit Status Page": "Modifica pagina di stato",
|
||||
"Go to Dashboard": "Vai al Cruscotto",
|
||||
"Status Page": "Pagina di stato",
|
||||
// Start notification form
|
||||
defaultNotificationName: "My {notification} Alert ({number})",
|
||||
here: "qui",
|
||||
"Required": "Richiesto",
|
||||
"telegram": "Telegram",
|
||||
"Bot Token": "Token del Bot",
|
||||
"You can get a token from": "Puoi ricevere un token da",
|
||||
"Chat ID": "ID Chat",
|
||||
supportTelegramChatID: "Supporta Chat dirette / di Gruppo / ID Canale",
|
||||
wayToGetTelegramChatID: "Puoi ricereve l'ID chat mandando un messaggio al bot andando in questo url per visualizzare il chat_id:",
|
||||
"YOUR BOT TOKEN HERE": "QUI IL TOKEN DEL BOT",
|
||||
chatIDNotFound: "Non trovo l'ID chat. Prima bisogna mandare un messaggio al bot",
|
||||
"webhook": "Webhook",
|
||||
"smtp": "E-Mail (SMTP)",
|
||||
"Post URL": "Post URL",
|
||||
"Content Type": "Content Type",
|
||||
webhookJsonDesc: "{0} va bene per qualsiasi server http moderno ad esempio express.js",
|
||||
webhookFormDataDesc: "{multipart} va bene per PHP, c'è solo bisogno di analizzare il json con {decodeFunction}",
|
||||
"smtp": "E-mail (SMTP)",
|
||||
secureOptionNone: "Nessuno / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "Ignora gli errori TLS",
|
||||
"From Email": "Mittente",
|
||||
emailCustomSubject: "Oggetto personalizzato",
|
||||
"To Email": "Destinatario",
|
||||
smtpCC: "CC",
|
||||
smtpBCC: "CCn",
|
||||
"discord": "Discord",
|
||||
"Discord Webhook URL": "URL Webhook di Discord",
|
||||
wayToGetDiscordURL: "È possibile recuperarlo da Impostazioni server -> Integrazioni -> Creare Webhook",
|
||||
"Bot Display Name": "Nome del Bot",
|
||||
"Prefix Custom Message": "Prefisso per il messaggio personalizzato",
|
||||
"Hello @everyone is...": "Ciao a {'@'}everyone ...",
|
||||
"teams": "Microsoft Teams",
|
||||
"Webhook URL": "URL Webhook",
|
||||
wayToGetTeamsURL: "È possibile imparare a creare un URL Webhook {0}.",
|
||||
"signal": "Signal",
|
||||
"Number": "Numero",
|
||||
"Recipients": "Destinatari",
|
||||
needSignalAPI: "È necessario avere un client Signal con le API REST.",
|
||||
wayToCheckSignalURL: "Controllare questo url per capire come impostarne uno:",
|
||||
signalImportant: "IMPORTANTE: Non è possibile mischiare gruppi e numeri all'interno dei destinatari!",
|
||||
"gotify": "Gotify",
|
||||
"Application Token": "Token Applicazione",
|
||||
"Server URL": "URL Server",
|
||||
"Priority": "Priorità",
|
||||
"slack": "Slack",
|
||||
"Icon Emoji": "Icona Emoji",
|
||||
"Channel Name": "Nome Canale",
|
||||
"Uptime Kuma URL": "Indirizzo Uptime Kuma",
|
||||
aboutWebhooks: "Maggiori informazioni riguardo ai webhooks su: {0}",
|
||||
aboutChannelName: "Inserire il nome del canale nel campo \"Nome Canale\" {0} se si vuole bypassare il canale webhook. Ad esempio: #altro-canale",
|
||||
aboutKumaURL: "Se si lascia bianco il campo Indirizzo Uptime Kuma, la pagina GitHub sarà il valore predefinito.",
|
||||
emojiCheatSheet: "Lista Emoji: {0}",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
"pushover": "Pushover",
|
||||
"pushy": "Pushy",
|
||||
"octopush": "Octopush",
|
||||
"lunasea": "LunaSea",
|
||||
"apprise": "Apprise (supporta oltre 50 servizi di notifica)",
|
||||
"pushbullet": "Pushbullet",
|
||||
"line": "Line Messenger",
|
||||
"mattermost": "Mattermost",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Supporta più di 50 servizi di notifica)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "Chiave Utente",
|
||||
"Device": "Dispositivo",
|
||||
"Message Title": "Titolo Messaggio",
|
||||
"Notification Sound": "Suono di Notifica",
|
||||
"More info on:": "Maggiori informazioni su: {0}",
|
||||
pushoverDesc1: "Emergency priority (2) has default 30 second timeout between retries and will expire after 1 hour.",
|
||||
pushoverDesc2: "If you want to send notifications to different devices, fill out Device field.",
|
||||
"SMS Type": "Tipo SMS",
|
||||
octopushTypePremium: "Premium (Fast - recommended for alerting)",
|
||||
octopushTypeLowCost: "Low Cost (Slow, sometimes blocked by operator)",
|
||||
"Check octopush prices": "Check octopush prices {0}.",
|
||||
octopushPhoneNumber: "Phone number (intl format, eg : +33612345678) ",
|
||||
octopushSMSSender: "SMS Sender Name : 3-11 alphanumeric characters and space (a-zA-Z0-9)",
|
||||
"LunaSea Device ID": "LunaSea Device ID",
|
||||
"Apprise URL": "Apprise URL",
|
||||
"Example:": "Example: {0}",
|
||||
"Read more:": "Read more: {0}",
|
||||
"Status:": "Status: {0}",
|
||||
"Read more": "Read more",
|
||||
appriseInstalled: "Apprise is installed.",
|
||||
appriseNotInstalled: "Apprise is not installed. {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: "First access the {0}, create a provider and channel (Messaging API), then you can get the channel access token and user id from the above mentioned menu items.",
|
||||
"Icon URL": "Icon URL",
|
||||
aboutIconURL: "You can provide a link to a picture in \"Icon URL\" to override the default profile picture. Will not be used if Icon Emoji is set.",
|
||||
aboutMattermostChannelName: "You can override the default channel that webhook posts to by entering the channel name into \"Channel Name\" field. This needs to be enabled in Mattermost webhook settings. Ex: #other-channel",
|
||||
"matrix": "Matrix",
|
||||
promosmsTypeEco: "SMS ECO - cheap but slow and often overloaded. Limited only to Polish recipients.",
|
||||
promosmsTypeFlash: "SMS FLASH - Message will automatically show on recipient device. Limited only to Polish recipients.",
|
||||
promosmsTypeFull: "SMS FULL - Premium tier of SMS, You can use Your Sender Name (You need to register name first). Reliable for alerts.",
|
||||
promosmsTypeSpeed: "SMS SPEED - Highest priority in system. Very quick and reliable but costly (about twice of SMS FULL price).",
|
||||
promosmsPhoneNumber: "Phone number (for Polish recipient You can skip area codes)",
|
||||
promosmsSMSSender: "SMS Sender Name : Pre-registred name or one of defaults: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
"Feishu WebHookUrl": "Feishu WebHookUrl",
|
||||
// End notification form
|
||||
};
|
||||
|
|
|
@ -179,4 +179,23 @@ export default {
|
|||
"Add a monitor": "Add a monitor",
|
||||
"Edit Status Page": "Edit Status Page",
|
||||
"Go to Dashboard": "Go to Dashboard",
|
||||
"Status Page": "Status Page",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "Email (SMTP)",
|
||||
discord: "Discord",
|
||||
teams: "Microsoft Teams",
|
||||
signal: "Signal",
|
||||
gotify: "Gotify",
|
||||
slack: "Slack",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
};
|
||||
|
|
|
@ -1,20 +1,31 @@
|
|||
export default {
|
||||
languageName: "한국어",
|
||||
checkEverySecond: "{0} 초마다 체크해요.",
|
||||
checkEverySecond: "{0}초마다 확인해요.",
|
||||
retryCheckEverySecond: "{0}초마다 다시 확인해요.",
|
||||
retriesDescription: "서비스가 중단된 후 알림을 보내기 전 최대 재시도 횟수",
|
||||
ignoreTLSError: "HTTPS 웹사이트에서 TLS/SSL 에러 무시하기",
|
||||
upsideDownModeDescription: "서버 상태를 반대로 표시해요. 서버가 작동하면 오프라인으로 표시할 거에요.",
|
||||
maxRedirectDescription: "최대 리다이렉트 횟수에요. 0을 입력하면 리다이렉트를 꺼요.",
|
||||
upsideDownModeDescription: "서버 상태를 반대로 표시해요. 서버가 작동하면 오프라인으로 표시할 거예요.",
|
||||
maxRedirectDescription: "최대 리다이렉트 횟수예요. 0을 입력하면 리다이렉트를 꺼요.",
|
||||
acceptedStatusCodesDescription: "응답 성공으로 간주할 상태 코드를 정해요.",
|
||||
passwordNotMatchMsg: "비밀번호 재입력이 일치하지 않아요.",
|
||||
notificationDescription: "모니터링에 알림을 설정할 수 있어요.",
|
||||
keywordDescription: "Html 이나 JSON에서 대소문자를 구분해 키워드를 검색해요.",
|
||||
keywordDescription: "HTML 이나 JSON에서 대소문자를 구분해 키워드를 검색해요.",
|
||||
pauseDashboardHome: "일시 정지",
|
||||
deleteMonitorMsg: "정말 이 모니터링을 삭제할까요?",
|
||||
deleteNotificationMsg: "정말 이 알림을 모든 모니터링에서 삭제할까요?",
|
||||
resoverserverDescription: "Cloudflare가 기본 서버에요, 원한다면 언제나 다른 resolver 서버로 변경할 수 있어요.",
|
||||
resoverserverDescription: "Cloudflare가 기본 서버예요, 원한다면 언제나 다른 Resolver 서버로 변경할 수 있어요.",
|
||||
rrtypeDescription: "모니터링할 RR-Type을 선택해요.",
|
||||
pauseMonitorMsg: "정말 이 모니터링을 일시 정지 할까요?",
|
||||
pauseMonitorMsg: "정말 이 모니터링을 일시 정지할까요?",
|
||||
enableDefaultNotificationDescription: "새로 추가하는 모든 모니터링에 이 알림을 기본적으로 활성화해요. 각 모니터에 대해 별도로 알림을 비활성화할 수 있어요.",
|
||||
clearEventsMsg: "정말 이 모니터링에 대한 모든 이벤트를 삭제할까요?",
|
||||
clearHeartbeatsMsg: "정말 이 모니터링에 대한 모든 하트비트를 삭제할까요?",
|
||||
confirmClearStatisticsMsg: "정말 모든 통계를 삭제할까요?",
|
||||
importHandleDescription: "이름이 같은 모든 모니터링이나 알림을 건너뛰려면 '기존값 건너뛰기'를 선택해주세요. '덮어쓰기'는 기존의 모든 모니터링과 알림을 삭제해요.",
|
||||
confirmImportMsg: "정말 백업을 가져올까요? 가져오기 옵션을 제대로 설정했는지 다시 확인해주세요.",
|
||||
twoFAVerifyLabel: "토큰을 입력해 2단계 인증이 작동하는지 확인해주세요.",
|
||||
tokenValidSettingsMsg: "토큰이 유효해요! 이제 2단계 인증 설정을 저장할 수 있어요.",
|
||||
confirmEnableTwoFAMsg: "정말 2단계 인증을 활성화할까요?",
|
||||
confirmDisableTwoFAMsg: "정말 2단계 인증을 비활성화할까요?",
|
||||
Settings: "설정",
|
||||
Dashboard: "대시보드",
|
||||
"New Update": "새로운 업데이트",
|
||||
|
@ -59,13 +70,14 @@ export default {
|
|||
Port: "포트",
|
||||
"Heartbeat Interval": "하트비트 주기",
|
||||
Retries: "재시도",
|
||||
"Heartbeat Retry Interval": "하트비드 재시도 주기",
|
||||
Advanced: "고급",
|
||||
"Upside Down Mode": "상태 반전 모드",
|
||||
"Max. Redirects": "최대 리다이렉트",
|
||||
"Accepted Status Codes": "응답 성공 상태 코드",
|
||||
Save: "저장",
|
||||
Notifications: "알림",
|
||||
"Not available, please setup.": "존재하지 않아요, 새로운거 하나 만드는건 어때요?",
|
||||
"Not available, please setup.": "존재하지 않아요, 새로운 거 하나 만드는 건 어때요?",
|
||||
"Setup Notification": "알림 설정",
|
||||
Light: "라이트",
|
||||
Dark: "다크",
|
||||
|
@ -73,7 +85,7 @@ export default {
|
|||
"Theme - Heartbeat Bar": "테마 - 하트비트 바",
|
||||
Normal: "기본값",
|
||||
Bottom: "가운데",
|
||||
None: "제거",
|
||||
None: "없애기",
|
||||
Timezone: "시간대",
|
||||
"Search Engine Visibility": "검색 엔진 활성화",
|
||||
"Allow indexing": "인덱싱 허용",
|
||||
|
@ -83,8 +95,8 @@ export default {
|
|||
"New Password": "새로운 비밀번호",
|
||||
"Repeat New Password": "새로운 비밀번호 재입력",
|
||||
"Update Password": "비밀번호 변경",
|
||||
"Disable Auth": "인증 끄기",
|
||||
"Enable Auth": "인증 켜기",
|
||||
"Disable Auth": "인증 비활성화",
|
||||
"Enable Auth": "인증 활성화",
|
||||
Logout: "로그아웃",
|
||||
Leave: "나가기",
|
||||
"I understand, please disable": "기능에 대해 이해했으니 꺼주세요.",
|
||||
|
@ -106,77 +118,165 @@ export default {
|
|||
"Last Result": "최근 결과",
|
||||
"Create your admin account": "관리자 계정 만들기",
|
||||
"Repeat Password": "비밀번호 재입력",
|
||||
"Import Backup": "백업 가져오기",
|
||||
"Export Backup": "백업 내보내기",
|
||||
Export: "내보내기",
|
||||
Import: "가져오기",
|
||||
respTime: "응답 시간 (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
Create: "Create",
|
||||
clearEventsMsg: "Are you sure want to delete all events for this monitor?",
|
||||
clearHeartbeatsMsg: "Are you sure want to delete all heartbeats for this monitor?",
|
||||
confirmClearStatisticsMsg: "Are you sure want to delete ALL statistics?",
|
||||
"Clear Data": "Clear Data",
|
||||
Events: "Events",
|
||||
Heartbeats: "Heartbeats",
|
||||
"Auto Get": "Auto Get",
|
||||
enableDefaultNotificationDescription: "For every new monitor this notification will be enabled by default. You can still disable the notification separately for each monitor.",
|
||||
"Default enabled": "Default enabled",
|
||||
"Also apply to existing monitors": "Also apply to existing monitors",
|
||||
Export: "Export",
|
||||
Import: "Import",
|
||||
backupDescription: "You can backup all monitors and all notifications into a JSON file.",
|
||||
backupDescription2: "PS: History and event data is not included.",
|
||||
backupDescription3: "Sensitive data such as notification tokens is included in the export file, please keep it carefully.",
|
||||
alertNoFile: "Please select a file to import.",
|
||||
alertWrongFileType: "Please select a JSON file.",
|
||||
twoFAVerifyLabel: "Please type in your token to verify that 2FA is working",
|
||||
tokenValidSettingsMsg: "Token is valid! You can now save the 2FA settings.",
|
||||
confirmEnableTwoFAMsg: "Are you sure you want to enable 2FA?",
|
||||
confirmDisableTwoFAMsg: "Are you sure you want to disable 2FA?",
|
||||
"Apply on all existing monitors": "Apply on all existing monitors",
|
||||
"Verify Token": "Verify Token",
|
||||
"Setup 2FA": "Setup 2FA",
|
||||
"Enable 2FA": "Enable 2FA",
|
||||
"Disable 2FA": "Disable 2FA",
|
||||
"2FA Settings": "2FA Settings",
|
||||
"Two Factor Authentication": "Two Factor Authentication",
|
||||
Active: "Active",
|
||||
Inactive: "Inactive",
|
||||
Token: "Token",
|
||||
"Show URI": "Show URI",
|
||||
"Clear all statistics": "Clear all Statistics",
|
||||
retryCheckEverySecond: "Retry every {0} seconds.",
|
||||
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
|
||||
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
|
||||
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
|
||||
"Import Backup": "Import Backup",
|
||||
"Export Backup": "Export Backup",
|
||||
"Skip existing": "Skip existing",
|
||||
Overwrite: "Overwrite",
|
||||
Options: "Options",
|
||||
"Keep both": "Keep both",
|
||||
Tags: "Tags",
|
||||
"Add New below or Select...": "Add New below or Select...",
|
||||
"Tag with this name already exist.": "Tag with this name already exist.",
|
||||
"Tag with this value already exist.": "Tag with this value already exist.",
|
||||
color: "color",
|
||||
"value (optional)": "value (optional)",
|
||||
Gray: "Gray",
|
||||
Red: "Red",
|
||||
Orange: "Orange",
|
||||
Green: "Green",
|
||||
Blue: "Blue",
|
||||
Indigo: "Indigo",
|
||||
Purple: "Purple",
|
||||
Pink: "Pink",
|
||||
"Search...": "Search...",
|
||||
"Avg. Ping": "Avg. Ping",
|
||||
"Avg. Response": "Avg. Response",
|
||||
"Entry Page": "Entry Page",
|
||||
statusPageNothing: "Nothing here, please add a group or a monitor.",
|
||||
"No Services": "No Services",
|
||||
"All Systems Operational": "All Systems Operational",
|
||||
"Partially Degraded Service": "Partially Degraded Service",
|
||||
"Degraded Service": "Degraded Service",
|
||||
"Add Group": "Add Group",
|
||||
"Add a monitor": "Add a monitor",
|
||||
"Edit Status Page": "Edit Status Page",
|
||||
"Go to Dashboard": "Go to Dashboard",
|
||||
"Default enabled": "기본 알림으로 설정",
|
||||
"Apply on all existing monitors": "기존 모니터링에 모두 적용하기",
|
||||
Create: "생성하기",
|
||||
"Clear Data": "데이터 삭제",
|
||||
Events: "이벤트",
|
||||
Heartbeats: "하트비트",
|
||||
"Auto Get": "자동 Get",
|
||||
backupDescription: "모든 모니터링과 알림을 JSON 파일 형식에 저장할 수 있어요.",
|
||||
backupDescription2: "히스토리와 이벤트 데이터는 포함되어 있지 않아요.",
|
||||
backupDescription3: "알림 토큰과 같은 보안 데이터가 내보내기 파일에 포함되어 있으므로 관리에 주의해주세요.",
|
||||
alertNoFile: "가져오기를 하기 위해 파일을 선택해주세요.",
|
||||
alertWrongFileType: "JSON 파일을 선택해주세요.",
|
||||
"Clear all statistics": "모든 통계치 삭제",
|
||||
"Skip existing": "기존값 건너뛰기",
|
||||
Overwrite: "덮어쓰기",
|
||||
Options: "옵션",
|
||||
"Keep both": "두개 모두 보존",
|
||||
"Verify Token": "토큰 검증",
|
||||
"Setup 2FA": "2단계 인증 설정하기",
|
||||
"Enable 2FA": "2단계 인증 활성화",
|
||||
"Disable 2FA": "2단계 인증 비활성화",
|
||||
"2FA Settings": "2단계 인증 설정",
|
||||
"Two Factor Authentication": "2단계 인증",
|
||||
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": "상태 페이지",
|
||||
defaultNotificationName: "내 {notification} 알림 ({number})",
|
||||
here: "여기",
|
||||
Required: "필수",
|
||||
telegram: "Telegram",
|
||||
"Bot Token": "봇 토큰",
|
||||
"You can get a token from": "토큰은 여기서 얻을 수 있어요:",
|
||||
"Chat ID": "채팅 ID",
|
||||
supportTelegramChatID: "Direct Chat / Group / Channel's Chat ID를 지원해요.",
|
||||
wayToGetTelegramChatID: "봇에 메시지를 보내 채팅 ID를 얻고 밑에 URL로 이동해 chat_id를 볼 수 있어요.",
|
||||
"YOUR BOT TOKEN HERE": "YOUR BOT TOKEN HERE",
|
||||
chatIDNotFound: "채팅 ID를 찾을 수 없어요. 먼저 봇에게 메시지를 보내주세요.",
|
||||
webhook: "Webhook",
|
||||
"Post URL": "Post URL",
|
||||
"Content Type": "Content Type",
|
||||
webhookJsonDesc: "{0}은 express.js와 같은 최신 HTTP 서버에 적합해요.",
|
||||
webhookFormDataDesc: "{multipart}은 PHP에 적합해요. {decodeFunction}를 기준으로 json을 디코딩하면 돼요.",
|
||||
smtp: "Email (SMTP)",
|
||||
secureOptionNone: "없음 / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "TLS 에러 무시하기",
|
||||
"From Email": "보내는 이메일",
|
||||
"To Email": "받는 이메일",
|
||||
smtpCC: "참조",
|
||||
smtpBCC: "숨은 참조",
|
||||
discord: "Discord",
|
||||
"Discord Webhook URL": "Discord Webhook URL",
|
||||
wayToGetDiscordURL: "서버 설정 -> 연동 -> 웹후크 보기 -> 새 웹후크에서 얻을 수 있어요.",
|
||||
"Bot Display Name": "표시 이름",
|
||||
"Prefix Custom Message": "접두사 메시지",
|
||||
"Hello @everyone is...": "{'@'}everyone 서버 상태 알림이에요...",
|
||||
teams: "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "{0}에서 Webhook을 어떻게 만드는지 알아봐요.",
|
||||
signal: "Signal",
|
||||
Number: "숫자",
|
||||
Recipients: "받는 사람",
|
||||
needSignalAPI: "REST API를 사용하는 Signal 클라이언트가 있어야 해요.",
|
||||
wayToCheckSignalURL: "밑에 URL을 확인해 URL 설정 방법을 볼 수 있어요.",
|
||||
signalImportant: "중요: 받는 사람의 그룹과 숫자는 섞을 수 없어요!",
|
||||
gotify: "Gotify",
|
||||
"Application Token": "애플리케이션 토큰",
|
||||
"Server URL": "서버 URL",
|
||||
Priority: "Priority",
|
||||
slack: "Slack",
|
||||
"Icon Emoji": "아이콘 이모지",
|
||||
"Channel Name": "채널 이름",
|
||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||
aboutWebhooks: "Webhook에 대한 설명: {0}",
|
||||
aboutChannelName: "Webhook 채널을 우회하려면 {0} 채널 이름칸에 채널 이름을 입력해주세요. 예: #기타-채널",
|
||||
aboutKumaURL: "Uptime Kuma URL칸을 공백으로 두면 기본적으로 Project Github 페이지로 설정해요.",
|
||||
emojiCheatSheet: "이모지 목록 시트: {0}",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (50개 이상 알림 서비스)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "사용자 키",
|
||||
Device: "장치",
|
||||
"Message Title": "메시지 제목",
|
||||
"Notification Sound": "알림음",
|
||||
"More info on:": "자세한 정보: {0}",
|
||||
pushoverDesc1: "긴급 우선 순위 (2)는 재시도 사이에 기본적으로 30초의 타임아웃이 있고, 1시간 후에 만료돼요.",
|
||||
pushoverDesc2: "다른 장치에 알림을 보내려면 장치칸을 입력해주세요.",
|
||||
"SMS Type": "SMS 종류",
|
||||
octopushTypePremium: "프리미엄 (빠름) - 알림 기능에 적합해요)",
|
||||
octopushTypeLowCost: "저렴한 요금 (느림) - 가끔 차단될 수 있어요)",
|
||||
"Check octopush prices": "{0}에서 Octopush 가격을 확인할 수 있어요.",
|
||||
octopushPhoneNumber: "휴대전화 번호 (intl format, eg : +33612345678) ",
|
||||
octopushSMSSender: "보내는 사람 이름 : 3-11개의 영숫자 및 여백공간 (a-z, A-Z, 0-9)",
|
||||
"LunaSea Device ID": "LunaSea 장치 ID",
|
||||
"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": "Line 개발자 콘솔",
|
||||
lineDevConsoleTo: "Line 개발자 콘솔 - {0}",
|
||||
"Basic Settings": "기본 설정 메뉴",
|
||||
"User ID": "사용자 ID",
|
||||
"Messaging API": "Messaging API 메뉴",
|
||||
wayToGetLineChannelToken: "먼저 {0}에 액세스하고, 공급자 및 채널 (Messaging API)을 만든 다음, 각 메뉴 밑에 언급된 메뉴에서 채널 액세스 토큰과 사용자 ID를 얻을 수 있어요.",
|
||||
"Icon URL": "아이콘 URL",
|
||||
aboutIconURL: "\"Icon URL\"에 사진 링크를 입력해 프로필 사진을 설정할 수 있어요. 아이콘 이모지가 설정되어 있으면 적용되지 않을 거예요.",
|
||||
aboutMattermostChannelName: "채널 이름을 입력하면 Webhook이 게시할 기본 채널을 재설정할 수 있어요. 이 설정은 Mattermost 웹훅 설정에서 활성화해야 해요. 예: #기타-채널",
|
||||
matrix: "매트릭스",
|
||||
promosmsTypeEco: "SMS ECO - 저렴하지만 느리고 가끔 과부하에 걸려요. 폴란드 수신자만 사용할 수 있어요. ",
|
||||
promosmsTypeFlash: "SMS FLASH - 메시지가 받는 사람 장치에 자동으로 표시돼요. 폴란드 수신자만 사용할 수 있어요.",
|
||||
promosmsTypeFull: "SMS FULL - SMS 프리미엄 티어, 보내는 사람 이름을 먼저 등록해야 해요. 알림 기능에 적합해요.",
|
||||
promosmsTypeSpeed: "SMS SPEED - 시스템에서 가장 높은 우선순위예요. 매우 빠르고 신뢰할 수 있지만 비용이 많이 들어요 (SMS 전체 가격의 약 두 배).",
|
||||
promosmsPhoneNumber: "전화 번호 (폴란드 수신자라면 지역번호를 적지 않아도 돼요.)",
|
||||
promosmsSMSSender: "SMS 보내는 사람 이름 : 미리 등록된 이름 혹은 기본값 중 하나예요: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
};
|
||||
|
|
284
src/languages/nb-NO.js
Normal file
284
src/languages/nb-NO.js
Normal file
|
@ -0,0 +1,284 @@
|
|||
export default {
|
||||
languageName: "Norsk",
|
||||
checkEverySecond: "Sjekk hvert {0} sekund.",
|
||||
retryCheckEverySecond: "Prøv igjen hvert {0} sekund.",
|
||||
retriesDescription: "Maksimalt antall forsøk før tjenesten er merket som nede og et varsel sendes",
|
||||
ignoreTLSError: "Ignorer TLS/SSL-feil for HTTPS-nettsteder",
|
||||
upsideDownModeDescription: "Snu statusen opp ned. Hvis tjenesten er tilgjengelig, er den NED.",
|
||||
maxRedirectDescription: "Maksimalt antall viderekoblinger å følge. Sett til 0 for å deaktivere viderekoblinger.",
|
||||
acceptedStatusCodesDescription: "Velg statuskoder som anses som et vellykket svar.",
|
||||
passwordNotMatchMsg: "Passordene stemmer ikke overens.",
|
||||
notificationDescription: "Tilordne et varsel for å overvåkningen for å få det til å fungere.",
|
||||
keywordDescription: "Søk etter nøkkelord i vanlig HTML eller JSON, og det er versalfølsom",
|
||||
pauseDashboardHome: "Pause",
|
||||
deleteMonitorMsg: "Er du sikker på at du vil slette denne overvåkningen?",
|
||||
deleteNotificationMsg: "Er du sikker på at du vil slette dette varselet for alle overvåkningene?",
|
||||
resoverserverDescription: "Cloudflare er standardserveren, kan du når som helst endre DNS-serveren.",
|
||||
rrtypeDescription: "Velg RR-typen du vil overvåke",
|
||||
pauseMonitorMsg: "Er du sikker på at du vil sette en pause?",
|
||||
enableDefaultNotificationDescription: "For hver ny overvåkning vil denne varslingen være aktivert som standard. Du kan fortsatt deaktivere varselet separat for hver overvåkning.",
|
||||
clearEventsMsg: "Er du sikker på at du vil slette alle hendelser for denne overvåkningen?",
|
||||
clearHeartbeatsMsg: "Er du sikker på at du vil slette alle hjerteslag for denne overvåkningen?",
|
||||
confirmClearStatisticsMsg: "Er du sikker på at du vil slette ALL statistikk?",
|
||||
importHandleDescription: "Velg 'Hopp over eksisterende' hvis du vil hoppe over hver overvåkning eller varsel med samme navn. 'Overskriv' sletter alle eksisterende overvåkninger og varsler.",
|
||||
confirmImportMsg: "Er du sikker på å importere sikkerhetskopien? Sørg for at du har valgt riktig importalternativ.",
|
||||
twoFAVerifyLabel: "Skriv inn tokenet ditt for å bekrefte at 2FA fungerer",
|
||||
tokenValidSettingsMsg: "Token er gyldig! Du kan nå lagre 2FA-innstillingene.",
|
||||
confirmEnableTwoFAMsg: "Er du sikker på at du vil aktivere 2FA?",
|
||||
confirmDisableTwoFAMsg: "Er du sikker på at du vil deaktivere 2FA?",
|
||||
Settings: "Innstillinger",
|
||||
Dashboard: "Dashboard",
|
||||
"New Update": "Ny Oppdatering",
|
||||
Language: "Språk",
|
||||
Appearance: "Utseende",
|
||||
Theme: "Tema",
|
||||
General: "Generelt",
|
||||
Version: "Versjon",
|
||||
"Check Update On GitHub": "Sjekk oppdatering på GitHub",
|
||||
List: "Liste",
|
||||
Add: "Legg til",
|
||||
"Add New Monitor": "Legg til ny overvåkning",
|
||||
"Quick Stats": "Statistikk",
|
||||
Up: "Oppe",
|
||||
Down: "Nede",
|
||||
Pending: "Avventer",
|
||||
Unknown: "Ukjent",
|
||||
Pause: "Pause",
|
||||
Name: "Navn",
|
||||
Status: "Status",
|
||||
DateTime: "Dato tid",
|
||||
Message: "Melding",
|
||||
"No important events": "Ingen viktige hendelser",
|
||||
Resume: "Fortsett",
|
||||
Edit: "Endre",
|
||||
Delete: "Slett",
|
||||
Current: "Nåværende",
|
||||
Uptime: "Oppetid",
|
||||
"Cert Exp.": "Sertifikat utløper",
|
||||
days: "dager",
|
||||
day: "dag",
|
||||
"-day": "-dag",
|
||||
hour: "time",
|
||||
"-hour": "-time",
|
||||
Response: "Respons",
|
||||
Ping: "Ping",
|
||||
"Monitor Type": "Overvåkningstype",
|
||||
Keyword: "Stikkord",
|
||||
"Friendly Name": "Vennlig navn",
|
||||
URL: "URL",
|
||||
Hostname: "Vertsnavn",
|
||||
Port: "Port",
|
||||
"Heartbeat Interval": "Hjerteslagsintervall",
|
||||
Retries: "Forsøk",
|
||||
"Heartbeat Retry Interval": "Hjerteslagsforsøkintervall",
|
||||
Advanced: "Avansert",
|
||||
"Upside Down Mode": "Opp-ned-modus",
|
||||
"Max. Redirects": "Maks. viderekoblinger",
|
||||
"Accepted Status Codes": "Godkjente statuskoder",
|
||||
Save: "Lagre",
|
||||
Notifications: "Varsler",
|
||||
"Not available, please setup.": "Ikke tilgjengelig, sett opp.",
|
||||
"Setup Notification": "Sett opp varsel",
|
||||
Light: "Lys",
|
||||
Dark: "Mørk",
|
||||
Auto: "Auto",
|
||||
"Theme - Heartbeat Bar": "Theme - Heartbeat Bar",
|
||||
Normal: "Normal",
|
||||
Bottom: "Bunn",
|
||||
None: "Ingen",
|
||||
Timezone: "Tidssone",
|
||||
"Search Engine Visibility": "Søkemotor synlighet",
|
||||
"Allow indexing": "Tillat indeksering",
|
||||
"Discourage search engines from indexing site": "Avskrekk søkemotorer fra å indeksere nettstedet",
|
||||
"Change Password": "Endre passord",
|
||||
"Current Password": "Nåværende passord",
|
||||
"New Password": "Nytt passord",
|
||||
"Repeat New Password": "Gjenta nytt passord",
|
||||
"Update Password": "Oppdater passord",
|
||||
"Disable Auth": "Deaktiver autentisering",
|
||||
"Enable Auth": "Aktiver autentisering",
|
||||
Logout: "Logg ut",
|
||||
Leave: "Forlat",
|
||||
"I understand, please disable": "Jeg forstår, deaktiver",
|
||||
Confirm: "Bekreft",
|
||||
Yes: "Ja",
|
||||
No: "Nei",
|
||||
Username: "Brukernavn",
|
||||
Password: "Passord",
|
||||
"Remember me": "Husk meg",
|
||||
Login: "Logg inn",
|
||||
"No Monitors, please": "Ingen overvåkning, vær så snill",
|
||||
"add one": "legg til en",
|
||||
"Notification Type": "Meldingstype",
|
||||
Email: "E-post",
|
||||
Test: "Test",
|
||||
"Certificate Info": "Sertifikatinformasjon",
|
||||
"Resolver Server": "DNS-server",
|
||||
"Resource Record Type": "DNS-posttype",
|
||||
"Last Result": "Siste resultat",
|
||||
"Create your admin account": "Opprett en administratorkonto",
|
||||
"Repeat Password": "Gjenta passord",
|
||||
"Import Backup": "Importer sikkerhetskopi",
|
||||
"Export Backup": "Eksporter sikkerhetskopi",
|
||||
Export: "Eksporter",
|
||||
Import: "Importer",
|
||||
respTime: "Svartid (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
"Default enabled": "Standard aktivert",
|
||||
"Apply on all existing monitors": "Påfør på alle eksisterende overvåkninger",
|
||||
Create: "Opprett",
|
||||
"Clear Data": "Slett data",
|
||||
Events: "Hendelser",
|
||||
Heartbeats: "Hjerteslag",
|
||||
"Auto Get": "Auto Get",
|
||||
backupDescription: "Du kan sikkerhetskopiere alle overvåkninger og alle varsler til en JSON-fil.",
|
||||
backupDescription2: "PS: Historikk og hendelsesdata er ikke inkludert.",
|
||||
backupDescription3: "Følsomme data som varslingstokener er inkludert i eksportfilen. Vennligst oppbevar dem nøye.",
|
||||
alertNoFile: "Velg en fil som skal importeres.",
|
||||
alertWrongFileType: "Velg en JSON-fil.",
|
||||
"Clear all statistics": "Fjern all statistikk",
|
||||
"Skip existing": "Hopp over eksisterende",
|
||||
Overwrite: "Overskriv",
|
||||
Options: "Alternativer",
|
||||
"Keep both": "Behold begge",
|
||||
"Verify Token": "Bekreft token",
|
||||
"Setup 2FA": "Konfigurer 2FA",
|
||||
"Enable 2FA": "Aktiver 2FA",
|
||||
"Disable 2FA": "Deaktiver 2FA",
|
||||
"2FA Settings": "2FA Innstillinger",
|
||||
"Two Factor Authentication": "To-faktor autentisering",
|
||||
Active: "Aktiv",
|
||||
Inactive: "Inaktiv",
|
||||
Token: "Token",
|
||||
"Show URI": "Vis URI",
|
||||
Tags: "Etiketter",
|
||||
"Add New below or Select...": "Legg til nytt nedenfor eller Velg ...",
|
||||
"Tag with this name already exist.": "Etikett med dette navnet eksisterer allerede.",
|
||||
"Tag with this value already exist.": "Etikett med denne verdien finnes allerede.",
|
||||
color: "farge",
|
||||
"value (optional)": "verdi (valgfritt)",
|
||||
Gray: "Grå",
|
||||
Red: "Rød",
|
||||
Orange: "Oransje",
|
||||
Green: "Grønn",
|
||||
Blue: "Blå",
|
||||
Indigo: "Indigo",
|
||||
Purple: "Lilla",
|
||||
Pink: "Rosa",
|
||||
"Search...": "Søk...",
|
||||
"Avg. Ping": "Gj.sn. Ping",
|
||||
"Avg. Response": "Gj.sn. Respons",
|
||||
"Entry Page": "Oppføringsside",
|
||||
statusPageNothing: "Ingenting her, vennligst legg til en gruppe eller en overvåkning.",
|
||||
"No Services": "Ingen tjenester",
|
||||
"All Systems Operational": "Alle systemer i drift",
|
||||
"Partially Degraded Service": "Delvis degradert drift",
|
||||
"Degraded Service": "Degradert drift",
|
||||
"Add Group": "Legg til gruppe",
|
||||
"Add a monitor": "Legg til en overvåkning",
|
||||
"Edit Status Page": "Rediger statusside",
|
||||
"Go to Dashboard": "Gå til Dashboard",
|
||||
"Status Page": "Statusside",
|
||||
// Start notification form
|
||||
defaultNotificationName: "Min {notification} varsling ({number})",
|
||||
here: "here",
|
||||
"Required": "Obligatorisk",
|
||||
"telegram": "Telegram",
|
||||
"Bot Token": "Bot Token",
|
||||
"You can get a token from": "Du kan få et token fra",
|
||||
"Chat ID": "Chat ID",
|
||||
supportTelegramChatID: "Support Direct Chat / Group / Channel's Chat ID",
|
||||
wayToGetTelegramChatID: "Du kan få chat-ID-en din ved å sende meldingen til boten og gå til denne nettadressen for å se chat_id:",
|
||||
"YOUR BOT TOKEN HERE": "DITT BOT TOKEN HER",
|
||||
chatIDNotFound: "Chat-ID ble ikke funnet. Send en melding til denne boten først",
|
||||
"webhook": "Webhook",
|
||||
"Post URL": "Post URL",
|
||||
"Content Type": "Content Type",
|
||||
webhookJsonDesc: "{0} er bra for alle moderne HTTP-servere som express.js",
|
||||
webhookFormDataDesc: "{multipart} er bra for PHP, du trenger bare å analysere JSON etter {decodeFunction}",
|
||||
"smtp": "E-post (SMTP)",
|
||||
secureOptionNone: "None / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "Ignorer TLS feilmelding",
|
||||
"From Email": "Fra E-post",
|
||||
"To Email": "Til E-post",
|
||||
smtpCC: "CC",
|
||||
smtpBCC: "BCC",
|
||||
"discord": "Discord",
|
||||
"Discord Webhook URL": "Discord Webhook URL",
|
||||
wayToGetDiscordURL: "Du kan få dette ved å gå til Serverinnstillinger -> Integrasjoner -> Webhooks -> Ny webhook",
|
||||
"Bot Display Name": "Bot Visningsnavn",
|
||||
"Prefix Custom Message": "Prefiks tilpasset melding",
|
||||
"Hello @everyone is...": "Hei {'@'}everyone det er...",
|
||||
"teams": "Microsoft Teams",
|
||||
"Webhook URL": "Webhook URL",
|
||||
wayToGetTeamsURL: "Du kan lære hvordan du oppretter en webhook-URL {0}.",
|
||||
"signal": "Signal",
|
||||
"Number": "Nummer",
|
||||
"Recipients": "Mottakere",
|
||||
needSignalAPI: "Du må ha en Signal-klient med REST API.",
|
||||
wayToCheckSignalURL: "Du kan sjekke denne nettadressen for å se hvordan du konfigurerer en:",
|
||||
signalImportant: "VIKTIG: Du kan ikke blande grupper og nummere i mottakere!",
|
||||
"gotify": "Gotify",
|
||||
"Application Token": "Application Token",
|
||||
"Server URL": "Server URL",
|
||||
"Priority": "Prioritet",
|
||||
"slack": "Slack",
|
||||
"Icon Emoji": "Icon Emoji",
|
||||
"Channel Name": "Kanal navn",
|
||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||
aboutWebhooks: "Mer informasjon om webhooks på: {0}",
|
||||
aboutChannelName: "Skriv inn kanalnavnet på {0} Kanalnavn-feltet hvis du vil omgå webhook-kanalen. Eks: #other-channel",
|
||||
aboutKumaURL: "Hvis du lar Uptime Kuma URL feltet være blank, den blir som standard til Github-siden for dette prosjektet.",
|
||||
emojiCheatSheet: "Emoji cheat sheet: {0}",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "User Key",
|
||||
"Device": "Device",
|
||||
"Message Title": "Message Title",
|
||||
"Notification Sound": "Notification Sound",
|
||||
"More info on:": "More info on: {0}",
|
||||
pushoverDesc1: "Emergency priority (2) has default 30 second timeout between retries and will expire after 1 hour.",
|
||||
pushoverDesc2: "If you want to send notifications to different devices, fill out Device field.",
|
||||
"SMS Type": "SMS Type",
|
||||
octopushTypePremium: "Premium (Fast - recommended for alerting)",
|
||||
octopushTypeLowCost: "Low Cost (Slow, sometimes blocked by operator)",
|
||||
"Check octopush prices": "Check octopush prices {0}.",
|
||||
octopushPhoneNumber: "Phone number (intl format, eg : +33612345678) ",
|
||||
octopushSMSSender: "SMS Sender Name : 3-11 alphanumeric characters and space (a-zA-Z0-9)",
|
||||
"LunaSea Device ID": "LunaSea Device ID",
|
||||
"Apprise URL": "Apprise URL",
|
||||
"Example:": "Example: {0}",
|
||||
"Read more:": "Read more: {0}",
|
||||
"Status:": "Status: {0}",
|
||||
"Read more": "Read more",
|
||||
appriseInstalled: "Apprise is installed.",
|
||||
appriseNotInstalled: "Apprise is not installed. {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: "First access the {0}, create a provider and channel (Messaging API), then you can get the channel access token and user id from the above mentioned menu items.",
|
||||
"Icon URL": "Icon URL",
|
||||
aboutIconURL: "You can provide a link to a picture in \"Icon URL\" to override the default profile picture. Will not be used if Icon Emoji is set.",
|
||||
aboutMattermostChannelName: "You can override the default channel that webhook posts to by entering the channel name into \"Channel Name\" field. This needs to be enabled in Mattermost webhook settings. Ex: #other-channel",
|
||||
"matrix": "Matrix",
|
||||
promosmsTypeEco: "SMS ECO - cheap but slow and often overloaded. Limited only to Polish recipients.",
|
||||
promosmsTypeFlash: "SMS FLASH - Message will automatically show on recipient device. Limited only to Polish recipients.",
|
||||
promosmsTypeFull: "SMS FULL - Premium tier of SMS, You can use Your Sender Name (You need to register name first). Reliable for alerts.",
|
||||
promosmsTypeSpeed: "SMS SPEED - Highest priority in system. Very quick and reliable but costly (about twice of SMS FULL price).",
|
||||
promosmsPhoneNumber: "Phone number (for Polish recipient You can skip area codes)",
|
||||
promosmsSMSSender: "SMS Sender Name : Pre-registred name or one of defaults: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||
// End notification form
|
||||
};
|
|
@ -179,4 +179,23 @@ export default {
|
|||
"Add a monitor": "Add a monitor",
|
||||
"Edit Status Page": "Edit Status Page",
|
||||
"Go to Dashboard": "Go to Dashboard",
|
||||
"Status Page": "Status Page",
|
||||
telegram: "Telegram",
|
||||
webhook: "Webhook",
|
||||
smtp: "Email (SMTP)",
|
||||
discord: "Discord",
|
||||
teams: "Microsoft Teams",
|
||||
signal: "Signal",
|
||||
gotify: "Gotify",
|
||||
slack: "Slack",
|
||||
"rocket.chat": "Rocket.chat",
|
||||
pushover: "Pushover",
|
||||
pushy: "Pushy",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue