mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-10-01 01:25:45 -04:00
Merge remote-tracking branch 'origin/master' into feature/#1221-clickable-hostaname-on-status-page
This commit is contained in:
commit
baa592bce3
@ -8,6 +8,7 @@
|
||||
"declaration-empty-line-before": null,
|
||||
"alpha-value-notation": "number",
|
||||
"color-function-notation": "legacy",
|
||||
"shorthand-property-no-redundant-values": null
|
||||
"shorthand-property-no-redundant-values": null,
|
||||
"color-hex-length": null,
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ const viteCompressionFilter = /\.(js|mjs|json|css|html|svg)$/i;
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
define: {
|
||||
"FRONTEND_VERSION": JSON.stringify(process.env.npm_package_version),
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
legacy({
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Simple docker-composer.yml
|
||||
# Simple docker-compose.yml
|
||||
# You can change your port or volume location
|
||||
|
||||
version: '3.3'
|
||||
|
@ -41,7 +41,7 @@ function updateWiki(newVersion) {
|
||||
|
||||
function safeDelete(dir) {
|
||||
if (fs.existsSync(dir)) {
|
||||
fs.rmdirSync(dir, {
|
||||
fs.rm(dir, {
|
||||
recursive: true,
|
||||
});
|
||||
}
|
||||
|
11816
package-lock.json
generated
11816
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
95
package.json
95
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.17.0-beta.1",
|
||||
"version": "1.17.1",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -39,7 +39,7 @@
|
||||
"build-docker-nightly-alpine": "docker buildx build -f docker/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 -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain",
|
||||
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
||||
"setup": "git checkout 1.16.1 && npm ci --production && npm run download-dist",
|
||||
"setup": "git checkout 1.17.1 && npm ci --production && npm run download-dist",
|
||||
"download-dist": "node extra/download-dist.js",
|
||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||
"reset-password": "node extra/reset-password.js",
|
||||
@ -61,23 +61,14 @@
|
||||
"build-dist-and-restart": "npm run build && npm run start-server-dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||
"@fortawesome/free-regular-svg-icons": "~5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "~3.0.0-5",
|
||||
"@louislam/sqlite3": "~15.0.6",
|
||||
"@popperjs/core": "~2.10.2",
|
||||
"args-parser": "~1.3.0",
|
||||
"axios": "~0.26.1",
|
||||
"axios-cached-dns-resolve": "^3.0.6",
|
||||
"axios-ntlm": "^1.3.0",
|
||||
"badge-maker": "^3.3.1",
|
||||
"bcryptjs": "~2.4.3",
|
||||
"bootstrap": "5.1.3",
|
||||
"bree": "~7.1.5",
|
||||
"chardet": "^1.3.0",
|
||||
"chart.js": "~3.6.2",
|
||||
"chartjs-adapter-dayjs": "~1.0.0",
|
||||
"check-password-strength": "^2.0.5",
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"chroma-js": "^2.1.2",
|
||||
@ -85,11 +76,9 @@
|
||||
"compare-versions": "~3.6.0",
|
||||
"compression": "^1.7.4",
|
||||
"dayjs": "^1.11.0",
|
||||
"esm-wallaby": "^3.2.26",
|
||||
"express": "~4.17.3",
|
||||
"express-basic-auth": "~1.2.1",
|
||||
"express-static-gzip": "^2.1.7",
|
||||
"favico.js": "^0.3.10",
|
||||
"form-data": "~4.0.0",
|
||||
"http-graceful-shutdown": "~3.1.7",
|
||||
"http-proxy-agent": "^5.0.0",
|
||||
@ -104,21 +93,58 @@
|
||||
"nodemailer": "~6.6.5",
|
||||
"notp": "~2.0.3",
|
||||
"password-hash": "~1.2.2",
|
||||
"postcss-rtlcss": "~3.4.1",
|
||||
"postcss-scss": "~4.0.3",
|
||||
"prismjs": "^1.27.0",
|
||||
"prom-client": "~13.2.0",
|
||||
"prometheus-api-metrics": "~3.2.1",
|
||||
"qrcode": "~1.5.0",
|
||||
"redbean-node": "0.1.4",
|
||||
"socket.io": "~4.4.1",
|
||||
"socket.io-client": "~4.4.1",
|
||||
"socks-proxy-agent": "^6.1.1",
|
||||
"tar": "^6.1.11",
|
||||
"tcp-ping": "~0.1.1",
|
||||
"thirty-two": "~1.0.2",
|
||||
"thirty-two": "~1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/github": "~5.0.1",
|
||||
"@babel/eslint-parser": "~7.17.0",
|
||||
"@babel/preset-env": "^7.15.8",
|
||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||
"@fortawesome/free-regular-svg-icons": "~5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "~5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "~3.0.0-5",
|
||||
"@popperjs/core": "~2.10.2",
|
||||
"@types/bootstrap": "~5.1.9",
|
||||
"@vitejs/plugin-legacy": "~1.8.2",
|
||||
"@vitejs/plugin-vue": "~2.3.3",
|
||||
"@vue/compiler-sfc": "~3.2.36",
|
||||
"aedes": "^0.46.3",
|
||||
"babel-plugin-rewire": "~1.2.0",
|
||||
"bootstrap": "5.1.3",
|
||||
"chart.js": "~3.6.2",
|
||||
"chartjs-adapter-dayjs": "~1.0.0",
|
||||
"concurrently": "^7.1.0",
|
||||
"core-js": "~3.18.3",
|
||||
"cross-env": "~7.0.3",
|
||||
"dns2": "~2.0.1",
|
||||
"eslint": "~8.14.0",
|
||||
"eslint-plugin-vue": "~8.7.1",
|
||||
"favico.js": "^0.3.10",
|
||||
"jest": "~27.2.5",
|
||||
"jest-puppeteer": "~6.0.3",
|
||||
"postcss-html": "^1.3.1",
|
||||
"postcss-rtlcss": "~3.4.1",
|
||||
"postcss-scss": "~4.0.3",
|
||||
"prismjs": "^1.27.0",
|
||||
"puppeteer": "~13.1.3",
|
||||
"qrcode": "~1.5.0",
|
||||
"rollup-plugin-visualizer": "^5.6.0",
|
||||
"sass": "~1.42.1",
|
||||
"stylelint": "~14.7.1",
|
||||
"stylelint-config-standard": "~25.0.0",
|
||||
"timezones-list": "~3.0.1",
|
||||
"typescript": "~4.4.4",
|
||||
"v-pagination-3": "~0.1.7",
|
||||
"vite": "~2.9.9",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vue": "next",
|
||||
"vue-chart-3": "3.0.9",
|
||||
"vue-confirm-dialog": "~1.0.2",
|
||||
@ -130,38 +156,7 @@
|
||||
"vue-qrcode": "~1.0.0",
|
||||
"vue-router": "~4.0.14",
|
||||
"vue-toastification": "~2.0.0-rc.5",
|
||||
"vuedraggable": "~4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/github": "~5.0.1",
|
||||
"@babel/eslint-parser": "~7.17.0",
|
||||
"@babel/preset-env": "^7.15.8",
|
||||
"@types/bootstrap": "~5.1.9",
|
||||
"@vitejs/plugin-legacy": "~1.8.2",
|
||||
"@vitejs/plugin-vue": "~2.3.3",
|
||||
"@vue/compiler-sfc": "~3.2.36",
|
||||
"aedes": "^0.46.3",
|
||||
"babel-plugin-rewire": "~1.2.0",
|
||||
"concurrently": "^7.1.0",
|
||||
"core-js": "~3.18.3",
|
||||
"cross-env": "~7.0.3",
|
||||
"delay": "^5.0.0",
|
||||
"dns2": "~2.0.1",
|
||||
"eslint": "~8.14.0",
|
||||
"eslint-plugin-vue": "~8.7.1",
|
||||
"jest": "~27.2.5",
|
||||
"jest-puppeteer": "~6.0.3",
|
||||
"lru-cache": "^7.7.1",
|
||||
"npm-check-updates": "^12.5.9",
|
||||
"postcss-html": "^1.3.1",
|
||||
"puppeteer": "~13.1.3",
|
||||
"rollup-plugin-visualizer": "^5.6.0",
|
||||
"sass": "~1.42.1",
|
||||
"stylelint": "~14.7.1",
|
||||
"stylelint-config-standard": "~25.0.0",
|
||||
"typescript": "~4.4.4",
|
||||
"vite": "~2.9.9",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vuedraggable": "~4.1.0",
|
||||
"wait-on": "^6.0.1"
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 893 B |
@ -178,7 +178,13 @@ class Database {
|
||||
} else {
|
||||
log.info("db", "Database patch is needed");
|
||||
|
||||
this.backup(version);
|
||||
try {
|
||||
this.backup(version);
|
||||
} catch (e) {
|
||||
log.error("db", e);
|
||||
log.error("db", "Unable to create a backup before patching the database. Please make sure you have enough space and permission.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Try catch anything here, if gone wrong, restore the backup
|
||||
try {
|
||||
@ -446,6 +452,23 @@ class Database {
|
||||
this.backupWalPath = walPath + ".bak" + version;
|
||||
fs.copyFileSync(walPath, this.backupWalPath);
|
||||
}
|
||||
|
||||
// Double confirm if all files actually backup
|
||||
if (!fs.existsSync(this.backupPath)) {
|
||||
throw new Error("Backup failed! " + this.backupPath);
|
||||
}
|
||||
|
||||
if (fs.existsSync(shmPath)) {
|
||||
if (!fs.existsSync(this.backupShmPath)) {
|
||||
throw new Error("Backup failed! " + this.backupShmPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (fs.existsSync(walPath)) {
|
||||
if (!fs.existsSync(this.backupWalPath)) {
|
||||
throw new Error("Backup failed! " + this.backupWalPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,6 @@ const version = require("../../package.json").version;
|
||||
const apicache = require("../modules/apicache");
|
||||
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||
|
||||
const axiosCachedDnsResolve = require("esm-wallaby")(module)("axios-cached-dns-resolve");
|
||||
|
||||
// create an axios client instance with the cached DNS resolve interceptor
|
||||
const axiosClient = axios.create();
|
||||
axiosCachedDnsResolve.registerInterceptor(axiosClient);
|
||||
|
||||
/**
|
||||
* status:
|
||||
* 0 = DOWN
|
||||
@ -293,7 +287,7 @@ class Monitor extends BeanModel {
|
||||
});
|
||||
|
||||
} else {
|
||||
res = await axiosClient.request(options);
|
||||
res = await axios.request(options);
|
||||
}
|
||||
|
||||
bean.msg = `${res.status} - ${res.statusText}`;
|
||||
@ -440,7 +434,7 @@ class Monitor extends BeanModel {
|
||||
throw new Error("Steam API Key not found");
|
||||
}
|
||||
|
||||
let res = await axiosClient.get(steamApiUrl, {
|
||||
let res = await axios.get(steamApiUrl, {
|
||||
timeout: this.interval * 1000 * 0.8,
|
||||
headers: {
|
||||
"Accept": "*/*",
|
||||
|
@ -14,7 +14,7 @@ class LunaSea extends NotificationProvider {
|
||||
if (heartbeatJSON == null) {
|
||||
let testdata = {
|
||||
"title": "Uptime Kuma Alert",
|
||||
"body": "Testing Successful.",
|
||||
"body": msg,
|
||||
};
|
||||
await axios.post(lunaseadevice, testdata);
|
||||
return okMsg;
|
||||
|
@ -654,7 +654,7 @@ let needSetup = false;
|
||||
bean.retryInterval = monitor.retryInterval;
|
||||
bean.hostname = monitor.hostname;
|
||||
bean.maxretries = monitor.maxretries;
|
||||
bean.port = monitor.port;
|
||||
bean.port = parseInt(monitor.port);
|
||||
bean.keyword = monitor.keyword;
|
||||
bean.ignoreTls = monitor.ignoreTls;
|
||||
bean.expiryNotification = monitor.expiryNotification;
|
||||
|
165
server/settings.js
Normal file
165
server/settings.js
Normal file
@ -0,0 +1,165 @@
|
||||
const { R } = require("redbean-node");
|
||||
const { log } = require("../src/util");
|
||||
|
||||
class Settings {
|
||||
|
||||
/**
|
||||
* Example:
|
||||
* {
|
||||
* key1: {
|
||||
* value: "value2",
|
||||
* timestamp: 12345678
|
||||
* },
|
||||
* key2: {
|
||||
* value: 2,
|
||||
* timestamp: 12345678
|
||||
* },
|
||||
* }
|
||||
* @type {{}}
|
||||
*/
|
||||
static cacheList = {
|
||||
|
||||
};
|
||||
|
||||
static cacheCleaner = null;
|
||||
|
||||
/**
|
||||
* Retrieve value of setting based on key
|
||||
* @param {string} key Key of setting to retrieve
|
||||
* @returns {Promise<any>} Value
|
||||
*/
|
||||
static async get(key) {
|
||||
|
||||
// Start cache clear if not started yet
|
||||
if (!Settings.cacheCleaner) {
|
||||
Settings.cacheCleaner = setInterval(() => {
|
||||
log.debug("settings", "Cache Cleaner is just started.");
|
||||
for (key in Settings.cacheList) {
|
||||
if (Date.now() - Settings.cacheList[key].timestamp > 60 * 1000) {
|
||||
log.debug("settings", "Cache Cleaner deleted: " + key);
|
||||
delete Settings.cacheList[key];
|
||||
}
|
||||
}
|
||||
|
||||
}, 60 * 1000);
|
||||
}
|
||||
|
||||
// Query from cache
|
||||
if (key in Settings.cacheList) {
|
||||
const v = Settings.cacheList[key].value;
|
||||
log.debug("settings", `Get Setting (cache): ${key}: ${v}`);
|
||||
return v;
|
||||
}
|
||||
|
||||
let value = await R.getCell("SELECT `value` FROM setting WHERE `key` = ? ", [
|
||||
key,
|
||||
]);
|
||||
|
||||
try {
|
||||
const v = JSON.parse(value);
|
||||
log.debug("settings", `Get Setting: ${key}: ${v}`);
|
||||
|
||||
Settings.cacheList[key] = {
|
||||
value: v,
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
return v;
|
||||
} catch (e) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified setting to specified value
|
||||
* @param {string} key Key of setting to set
|
||||
* @param {any} value Value to set to
|
||||
* @param {?string} type Type of setting
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async set(key, value, type = null) {
|
||||
|
||||
let bean = await R.findOne("setting", " `key` = ? ", [
|
||||
key,
|
||||
]);
|
||||
if (!bean) {
|
||||
bean = R.dispense("setting");
|
||||
bean.key = key;
|
||||
}
|
||||
bean.type = type;
|
||||
bean.value = JSON.stringify(value);
|
||||
await R.store(bean);
|
||||
|
||||
Settings.deleteCache([ key ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings based on type
|
||||
* @param {string} type The type of setting
|
||||
* @returns {Promise<Bean>}
|
||||
*/
|
||||
static async getSettings(type) {
|
||||
let list = await R.getAll("SELECT `key`, `value` FROM setting WHERE `type` = ? ", [
|
||||
type,
|
||||
]);
|
||||
|
||||
let result = {};
|
||||
|
||||
for (let row of list) {
|
||||
try {
|
||||
result[row.key] = JSON.parse(row.value);
|
||||
} catch (e) {
|
||||
result[row.key] = row.value;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set settings based on type
|
||||
* @param {string} type Type of settings to set
|
||||
* @param {Object} data Values of settings
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static async setSettings(type, data) {
|
||||
let keyList = Object.keys(data);
|
||||
|
||||
let promiseList = [];
|
||||
|
||||
for (let key of keyList) {
|
||||
let bean = await R.findOne("setting", " `key` = ? ", [
|
||||
key
|
||||
]);
|
||||
|
||||
if (bean == null) {
|
||||
bean = R.dispense("setting");
|
||||
bean.type = type;
|
||||
bean.key = key;
|
||||
}
|
||||
|
||||
if (bean.type === type) {
|
||||
bean.value = JSON.stringify(data[key]);
|
||||
promiseList.push(R.store(bean));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(promiseList);
|
||||
|
||||
Settings.deleteCache(keyList);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string[]} keyList
|
||||
*/
|
||||
static deleteCache(keyList) {
|
||||
for (let key of keyList) {
|
||||
delete Settings.cacheList[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Settings,
|
||||
};
|
@ -12,6 +12,7 @@ const chroma = require("chroma-js");
|
||||
const { badgeConstants } = require("./config");
|
||||
const mssql = require("mssql");
|
||||
const { NtlmClient } = require("axios-ntlm");
|
||||
const { Settings } = require("./settings");
|
||||
|
||||
// From ping-lite
|
||||
exports.WIN = /^win/.test(process.platform);
|
||||
@ -260,17 +261,7 @@ exports.mssqlQuery = function (connectionString, query) {
|
||||
* @returns {Promise<any>} Value
|
||||
*/
|
||||
exports.setting = async function (key) {
|
||||
let value = await R.getCell("SELECT `value` FROM setting WHERE `key` = ? ", [
|
||||
key,
|
||||
]);
|
||||
|
||||
try {
|
||||
const v = JSON.parse(value);
|
||||
log.debug("util", `Get Setting: ${key}: ${v}`);
|
||||
return v;
|
||||
} catch (e) {
|
||||
return value;
|
||||
}
|
||||
return await Settings.get(key);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -281,70 +272,26 @@ exports.setting = async function (key) {
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
exports.setSetting = async function (key, value, type = null) {
|
||||
let bean = await R.findOne("setting", " `key` = ? ", [
|
||||
key,
|
||||
]);
|
||||
if (!bean) {
|
||||
bean = R.dispense("setting");
|
||||
bean.key = key;
|
||||
}
|
||||
bean.type = type;
|
||||
bean.value = JSON.stringify(value);
|
||||
await R.store(bean);
|
||||
await Settings.set(key, value, type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get settings based on type
|
||||
* @param {?string} type The type of setting
|
||||
* @param {string} type The type of setting
|
||||
* @returns {Promise<Bean>}
|
||||
*/
|
||||
exports.getSettings = async function (type) {
|
||||
let list = await R.getAll("SELECT `key`, `value` FROM setting WHERE `type` = ? ", [
|
||||
type,
|
||||
]);
|
||||
|
||||
let result = {};
|
||||
|
||||
for (let row of list) {
|
||||
try {
|
||||
result[row.key] = JSON.parse(row.value);
|
||||
} catch (e) {
|
||||
result[row.key] = row.value;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return await Settings.getSettings(type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set settings based on type
|
||||
* @param {?string} type Type of settings to set
|
||||
* @param {string} type Type of settings to set
|
||||
* @param {Object} data Values of settings
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
exports.setSettings = async function (type, data) {
|
||||
let keyList = Object.keys(data);
|
||||
|
||||
let promiseList = [];
|
||||
|
||||
for (let key of keyList) {
|
||||
let bean = await R.findOne("setting", " `key` = ? ", [
|
||||
key
|
||||
]);
|
||||
|
||||
if (bean == null) {
|
||||
bean = R.dispense("setting");
|
||||
bean.type = type;
|
||||
bean.key = key;
|
||||
}
|
||||
|
||||
if (bean.type === type) {
|
||||
bean.value = JSON.stringify(data[key]);
|
||||
promiseList.push(R.store(bean));
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(promiseList);
|
||||
await Settings.setSettings(type, data);
|
||||
};
|
||||
|
||||
// ssl-checker by @dyaa
|
||||
|
@ -4,6 +4,11 @@
|
||||
<object class="my-4" width="200" height="200" data="/icon.svg" />
|
||||
<div class="fs-4 fw-bold">Uptime Kuma</div>
|
||||
<div>{{ $t("Version") }}: {{ $root.info.version }}</div>
|
||||
<div class="frontend-version">{{ $t("Frontend Version") }}: {{ $root.frontendVersion }}</div>
|
||||
|
||||
<div v-if="!$root.isFrontendBackendVersionMatched" class="alert alert-warning mt-4" role="alert">
|
||||
⚠️ {{ $t("Frontend Version do not match backend version!") }}
|
||||
</div>
|
||||
|
||||
<div class="my-3 update-link"><a href="https://github.com/louislam/uptime-kuma/releases" target="_blank" rel="noopener">{{ $t("Check Update On GitHub") }}</a></div>
|
||||
|
||||
@ -46,6 +51,16 @@ export default {
|
||||
}
|
||||
|
||||
.update-link {
|
||||
font-size: 0.9em;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.frontend-version {
|
||||
font-size: 0.9em;
|
||||
color: #cccccc;
|
||||
|
||||
.dark & {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -23,6 +23,7 @@
|
||||
<div class="my-4 pt-4">
|
||||
<h5 class="my-4 settings-subheading">{{ $t("settingsCertificateExpiry") }}</h5>
|
||||
<p>{{ $t("certificationExpiryDescription") }}</p>
|
||||
<p>{{ $t("notificationDescription") }}</p>
|
||||
<div class="mt-1 mb-3 ps-2 cert-exp-days col-12 col-xl-6">
|
||||
<div v-for="day in settings.tlsExpiryNotifyDays" :key="day" class="d-flex align-items-center justify-content-between cert-exp-day-row py-2">
|
||||
<span>{{ day }} {{ $tc("day", day) }}</span>
|
||||
|
@ -9,6 +9,7 @@ const languageList = {
|
||||
"nl-NL": "Nederlands",
|
||||
"nb-NO": "Norsk",
|
||||
"es-ES": "Español",
|
||||
"eu": "Euskara",
|
||||
"fa": "Farsi",
|
||||
"pt-BR": "Português (Brasileiro)",
|
||||
"fr-FR": "Français (France)",
|
||||
|
@ -4,8 +4,7 @@
|
||||
2. Create a language file (e.g. `zh-TW.js`). The filename must be ISO language code: http://www.lingoes.net/en/translator/langcode.htm
|
||||
3. Run `npm run update-language-files`. You can also use this command to check if there are new strings to translate for your language.
|
||||
4. Your language file should be filled in. You can translate now.
|
||||
5. Translate `src/components/settings/Security.vue` (search for a `Confirm` component with `rel="confirmDisableAuth"`).
|
||||
6. Add it into `languageList` constant.
|
||||
7. Make a [pull request](https://github.com/louislam/uptime-kuma/pulls) when you have done.
|
||||
5. Add it into `languageList` constant.
|
||||
6. Make a [pull request](https://github.com/louislam/uptime-kuma/pulls) when you have done.
|
||||
|
||||
If you do not have programming skills, let me know in [the issues section](https://github.com/louislam/uptime-kuma/issues). I will assist you. 😏
|
||||
|
@ -532,4 +532,8 @@ export default {
|
||||
Query: "Заявка",
|
||||
settingsCertificateExpiry: "Изтичане валидността на TLS сертификата",
|
||||
certificationExpiryDescription: "HTTPS мониторите ще задействат известие, ако е наличен изтичащ TLS сертификат, през следващите:",
|
||||
"ntfy Topic": "ntfy Тема",
|
||||
Domain: "Домейн",
|
||||
Workstation: "Работна станция",
|
||||
disableCloudflaredNoAuthMsg: "Тъй като сте в режим \"No Auth mode\", парола не се изисква.",
|
||||
};
|
||||
|
539
src/languages/eu.js
Normal file
539
src/languages/eu.js
Normal file
@ -0,0 +1,539 @@
|
||||
export default {
|
||||
languageName: "Euskara",
|
||||
checkEverySecond: "Egiaztatu {0} segunduro",
|
||||
retryCheckEverySecond: "Errepikatu {0} segunduro",
|
||||
retriesDescription: "Zerbitzua erorita markatu eta jakinarazpena bidali aurretik egindako saiakera kopuru maximoa",
|
||||
ignoreTLSError: "Ezikusiarena egin TLS/SSL erroreei HTTPS webguneetan",
|
||||
upsideDownModeDescription: "Alderantzizkatu erortze egoera. Zerbitzua martxan badago, ERORITA markatuko du.",
|
||||
maxRedirectDescription: "Jarraitu beharreko berbideratze kopuru maximoa. Jarri 0 berbideratzeak desgaitzeko.",
|
||||
acceptedStatusCodesDescription: "Hautatu erantzun ona kontsideratzen diren egoera kodeak.",
|
||||
passwordNotMatchMsg: "Errepikatutako pasahitza ez dator bat.",
|
||||
notificationDescription: "Jakinarazpenak monitorizazio funtzio bati asignatu behar zaizkio.",
|
||||
keywordDescription: "Bilatu gako-hitza HTML edo JSON erantzunean. Bilaketan maiuskulak kontuan hartzen dira.",
|
||||
pauseDashboardHome: "Gelditu",
|
||||
deleteMonitorMsg: "Ziur zaude monitorizazio hau ezabatu nahi duzula?",
|
||||
deleteNotificationMsg: "Ziur zaude jakinarazpen hau monitorizazio guztientzat ezabatu nahi duzula?",
|
||||
dnsPortDescription: "DNS zerbitzari portua. Defektuz 53. Nahi duzunean aldatu dezakezu portua.",
|
||||
resolverserverDescription: "Cloudflare zerbitzari lehenetsia da. Edozein unetan alda dezakezu ebazteko zerbitzaria.",
|
||||
rrtypeDescription: "Hautatu kontrolatu nahi duzun RR mota",
|
||||
enableDefaultNotificationDescription: "Jakinarazpen hau monitore berrientzat gaituko da defektuz. Baina monitorizazio bakoitzarentzat jakinarazpena desgaitu dezakezu.",
|
||||
pauseMonitorMsg: "Ziur zaude gelditu egin nahi duzula?",
|
||||
clearEventsMsg: "Ziur zaude monitorizazio honen gertaera guztiak ezabatu nahi dituzula?",
|
||||
clearHeartbeatsMsg: "Ziur zaude monitorizazio honen pultsu guztiak ezabatu nahi dituzula?",
|
||||
confirmClearStatisticsMsg: "Ziur zaude estatistika GUZTIAK ezabatu nahi dituzula?",
|
||||
importHandleDescription: "Aukeratu 'existitzen bada', izen bereko monitore edo jakinarazpen bakoitza saltatu nahi baduzu. Lehendik dauden kontrol eta jakinarazpen guztiak ezabatuko ditu 'Gainidatzi' aukerak.",
|
||||
confirmImportMsg: "Ziur zaude segurtasun-kopia inportatu nahi duzula? Egiaztatu inportatzeko aukera zuzena hautatu duzula.",
|
||||
twoFAVerifyLabel: "Sartu zure tokena 2FA egiaztatzeko:",
|
||||
tokenValidSettingsMsg: "Tokenak balio du! Orain 2FA konfigurazioa gorde dezakezu.",
|
||||
confirmEnableTwoFAMsg: "Ziur zaude 2FA gaitu nahi duzula?",
|
||||
confirmDisableTwoFAMsg: "Ziur zaude 2FA desgaitu nahi duzula?",
|
||||
Settings: "Ezarpenak",
|
||||
Dashboard: "Arbela",
|
||||
"New Update": "Eguneraketa berria",
|
||||
Language: "Hizkuntza",
|
||||
Appearance: "Itxura",
|
||||
Theme: "Gaia",
|
||||
General: "Orokorra",
|
||||
"Primary Base URL": "Oinarrizkoa URL",
|
||||
Version: "Bertsioa",
|
||||
"Check Update On GitHub": "Egiaztatu eguneraketa GitHuben",
|
||||
List: "Zerrenda",
|
||||
Add: "Gehitu",
|
||||
"Add New Monitor": "Gehitu monitorizazio berria",
|
||||
"Quick Stats": "Estatistika azkarrak",
|
||||
Up: "Erabilgarri",
|
||||
Down: "Erorita",
|
||||
Pending: "Zain",
|
||||
Unknown: "Ezezaguna",
|
||||
Pause: "Gelditu",
|
||||
Name: "Izena",
|
||||
Status: "Egoera",
|
||||
DateTime: "Data eta ordua",
|
||||
Message: "Mezua",
|
||||
"No important events": "Gertaera garrantzitsurik ez",
|
||||
Resume: "Jarraitu",
|
||||
Edit: "Editatu",
|
||||
Delete: "Ezabatu",
|
||||
Current: "Unekoa",
|
||||
Uptime: "Martxan",
|
||||
"Cert Exp.": "Ziurtagiri iraun.",
|
||||
day: "egun | egun",
|
||||
"-day": "-egun",
|
||||
hour: "ordua",
|
||||
"-hour": "-ordu",
|
||||
Response: "Erantzuna",
|
||||
Ping: "Ping",
|
||||
"Monitor Type": "Monitorizazio mota",
|
||||
Keyword: "Gakohitza",
|
||||
"Friendly Name": "Izen xumea",
|
||||
URL: "URLa",
|
||||
Hostname: "Ostalari izena",
|
||||
Port: "Portua",
|
||||
"Heartbeat Interval": "Pultsu interbaloak",
|
||||
Retries: "Errepikapenak",
|
||||
"Heartbeat Retry Interval": "Pultsu errepikatze interbaloak",
|
||||
Advanced: "Aurreratua",
|
||||
"Upside Down Mode": "Alderantzizkako modua",
|
||||
"Max. Redirects": "Berbideratze max.",
|
||||
"Accepted Status Codes": "Onartutako egoera kodeak",
|
||||
"Push URL": "Push URLa",
|
||||
needPushEvery: "URL hau {0} segunduro deitu beharko zenuke.",
|
||||
pushOptionalParams: "Hautazko parametroak: {0}",
|
||||
Save: "Gorde",
|
||||
Notifications: "Jakinarazpenak",
|
||||
"Not available, please setup.": "Ez dago eskuragarri, ezarri mesedez.",
|
||||
"Setup Notification": "Ezarri jakinarazpenak",
|
||||
Light: "Argia",
|
||||
Dark: "Iluna",
|
||||
Auto: "Auto",
|
||||
"Theme - Heartbeat Bar": "Gaia - Pultsu barra",
|
||||
Normal: "Normala",
|
||||
Bottom: "Behean",
|
||||
None: "Bat ere ez",
|
||||
Timezone: "Timezone",
|
||||
"Search Engine Visibility": "Bilatzaile ikurgarritasuna",
|
||||
"Allow indexing": "Onartu indexatzea",
|
||||
"Discourage search engines from indexing site": "Discourage search engines from indexing site",
|
||||
"Change Password": "Aldatu pasahitza",
|
||||
"Current Password": "Uneko pasahitza",
|
||||
"New Password": "Pasahitz berria",
|
||||
"Repeat New Password": "Errepikatu pasahitz berria",
|
||||
"Update Password": "Eguneratu pasahitza",
|
||||
"Disable Auth": "Desgaitu Auth",
|
||||
"Enable Auth": "Gaitu Auth",
|
||||
"disableauth.message1": "Ziur zaude <strong>autentifikazioa desgaitu</strong> nahi duzula?",
|
||||
"disableauth.message2": "Egoera jakin batzuetarako diseinatuta dago, Uptime Kumaren <strong>aurrean hirugarrengo autentifikazio batzuek jartzeko</strong> (Cloudflare Access, Authelia edo beste autentifikazio-mekanismo batzuk).",
|
||||
"Please use this option carefully!": "Mesedez, kontuz erabili aukera hau!",
|
||||
Logout: "Saioa amaitu",
|
||||
Leave: "Utzi",
|
||||
"I understand, please disable": "Ulertzen dut, mesedez desgaitu",
|
||||
Confirm: "Baieztatu",
|
||||
Yes: "Bai",
|
||||
No: "Ez",
|
||||
Username: "Erabiltzailea",
|
||||
Password: "Pasahitza",
|
||||
"Remember me": "Gogora nazazu",
|
||||
Login: "Saioa hasi",
|
||||
"No Monitors, please": "Monitorizaziorik ez, mesedez",
|
||||
"add one": "gehitu bat",
|
||||
"Notification Type": "Jakinarazpen mota",
|
||||
Email: "Emaila",
|
||||
Test: "Testa",
|
||||
"Certificate Info": "Ziurtagiri informazioa",
|
||||
"Resolver Server": "Ebazpen-zerbitzaria",
|
||||
"Resource Record Type": "Baliabideen erregistro mota",
|
||||
"Last Result": "Azken emaitza",
|
||||
"Create your admin account": "Sortu zure admin kontua",
|
||||
"Repeat Password": "Errepikatu pasahitza",
|
||||
"Import Backup": "segurtasun-kopia inportatu",
|
||||
"Export Backup": "segurtasun-kopia esportatu",
|
||||
Export: "Esportatu",
|
||||
Import: "Inportatu",
|
||||
respTime: "Erantz. denbora (ms)",
|
||||
notAvailableShort: "N/A",
|
||||
"Default enabled": "Lehenetsia gaituta",
|
||||
"Apply on all existing monitors": "Aplikatu existitzen diren monitorizazio guztietan",
|
||||
Create: "Sortu",
|
||||
"Clear Data": "Garbitu datuak",
|
||||
Events: "Gertaerak",
|
||||
Heartbeats: "Pultsuak",
|
||||
"Auto Get": "Auto Get",
|
||||
backupDescription: "Monitore eta jakinarazpen guztien segurtasun-kopiak egin ditzakezu JSON fitxategi batean.",
|
||||
backupDescription2: "Oharra: ez dira historia eta gertaeren datuak sartzen.",
|
||||
backupDescription3: "Datu sentikorrak, hala nola jakinarazpen tokenak, esportazio-fitxategian sartzen dira; mesedez, gorde esportazioa modu seguruan.",
|
||||
alertNoFile: "Mesedez hautatu inportatzeko fitxategia.",
|
||||
alertWrongFileType: "Mesedez hautatu JSON fitxategia.",
|
||||
"Clear all statistics": "Garbitu estatistika guztiak",
|
||||
"Skip existing": "Saltatu existitzen bada",
|
||||
Overwrite: "Gainidatzi",
|
||||
Options: "Aukerak",
|
||||
"Keep both": "Biak mantendu",
|
||||
"Verify Token": "Egiaztatu Tokena",
|
||||
"Setup 2FA": "Ezarri 2FA",
|
||||
"Enable 2FA": "Gaitu 2FA",
|
||||
"Disable 2FA": "Desgaitu 2FA",
|
||||
"2FA Settings": "2FA ezarpenak",
|
||||
"Two Factor Authentication": "Bi aldetako autentifikazioa (2FA)",
|
||||
Active: "Aktibo",
|
||||
Inactive: "Inaktibo",
|
||||
Token: "Tokena",
|
||||
"Show URI": "Erakutsi URIa",
|
||||
Tags: "Etiketak",
|
||||
"Add New below or Select...": "Gehitu beste bat behean edo hautatu...",
|
||||
"Tag with this name already exist.": "Izen hau duen etiketa dagoeneko badago.",
|
||||
"Tag with this value already exist.": "Balio hau duen etiketa dagoeneko badago.",
|
||||
color: "kolorea",
|
||||
"value (optional)": "balioa (hautazkoa)",
|
||||
Gray: "Grisa",
|
||||
Red: "Gorria",
|
||||
Orange: "Naranja",
|
||||
Green: "Berdea",
|
||||
Blue: "Urdina",
|
||||
Indigo: "Indigo",
|
||||
Purple: "Morea",
|
||||
Pink: "Arrosa",
|
||||
"Search...": "Bilatu...",
|
||||
"Avg. Ping": "Batazbesteko Pinga",
|
||||
"Avg. Response": "Batazbesteko erantzuna",
|
||||
"Entry Page": "Sarrera orria",
|
||||
statusPageNothing: "Ezer ere ez hemen, mesedez gehitu taldea edo monitorizazioa.",
|
||||
"No Services": "Zerbitzurik ez",
|
||||
"All Systems Operational": "Sistema guztiak martxan",
|
||||
"Partially Degraded Service": "Zerbitzu partzialki degradatua",
|
||||
"Degraded Service": "Zerbitzu degradatua",
|
||||
"Add Group": "Gehitu taldea",
|
||||
"Add a monitor": "Gehitu monitorizazioa",
|
||||
"Edit Status Page": "Editatu egoera orria",
|
||||
"Go to Dashboard": "Joan arbelera",
|
||||
"Status Page": "Egoera orria",
|
||||
"Status Pages": "Egoera orriak",
|
||||
defaultNotificationName: "Nire {notification} Alerta ({number})",
|
||||
here: "Hemen",
|
||||
Required: "Beharrezkoa",
|
||||
telegram: "Telegram",
|
||||
"Bot Token": "Bot Tokena",
|
||||
wayToGetTelegramToken: "You can get a token from {0}.",
|
||||
"Chat ID": "Txat IDa",
|
||||
supportTelegramChatID: "Support Direct Chat / Group / Channel's Chat ID",
|
||||
wayToGetTelegramChatID: "You can get your chat ID by sending a message to the bot and going 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": "Bidalketa URLa",
|
||||
"Content Type": "Eduki mota",
|
||||
webhookJsonDesc: "{0} is good for any modern HTTP servers such as Express.js",
|
||||
webhookFormDataDesc: "{multipart} is good for PHP. The JSON will need to be parsed with {decodeFunction}",
|
||||
smtp: "Emaila (SMTP)",
|
||||
secureOptionNone: "Bat ere ez / STARTTLS (25, 587)",
|
||||
secureOptionTLS: "TLS (465)",
|
||||
"Ignore TLS Error": "Ignore TLS Error",
|
||||
"From Email": "Email honetatik",
|
||||
emailCustomSubject: "Pertsonalizatutako gaia",
|
||||
"To Email": "Email honetara",
|
||||
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: "Zenbakia",
|
||||
Recipients: "Recipients",
|
||||
needSignalAPI: "You need to have a signal client with REST API.",
|
||||
wayToCheckSignalURL: "You can check this URL to view how to set one up:",
|
||||
signalImportant: "IMPORTANT: You cannot mix groups and numbers in recipients!",
|
||||
gotify: "Gotify",
|
||||
"Application Token": "Aplikazio tokena",
|
||||
"Server URL": "Zerbitzari URLa",
|
||||
Priority: "Lehentasuna",
|
||||
slack: "Slack",
|
||||
"Icon Emoji": "Emoji ikonoa",
|
||||
"Channel Name": "Kanalaren izena",
|
||||
"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",
|
||||
PushByTechulus: "Push by Techulus",
|
||||
octopush: "Octopush",
|
||||
promosms: "PromoSMS",
|
||||
clicksendsms: "ClickSend SMS",
|
||||
lunasea: "LunaSea",
|
||||
apprise: "Apprise (Support 50+ Notification services)",
|
||||
GoogleChat: "Google Chat (Google Workspace only)",
|
||||
pushbullet: "Pushbullet",
|
||||
line: "Line Messenger",
|
||||
mattermost: "Mattermost",
|
||||
"User Key": "Erabiltzaile gakoa",
|
||||
Device: "Gailua",
|
||||
"Message Title": "Mezuaren izenburua",
|
||||
"Notification Sound": "Jakinarazpen soinua",
|
||||
"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 mota",
|
||||
octopushTypePremium: "Premium (Fast - recommended for alerting)",
|
||||
octopushTypeLowCost: "Low Cost (Slow - sometimes blocked by operator)",
|
||||
checkPrice: "Check {0} prices:",
|
||||
apiCredentials: "API credentials",
|
||||
octopushLegacyHint: "Do you use the legacy version of Octopush (2011-2020) or the new version?",
|
||||
"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:": "Adibidez: {0}",
|
||||
"Read more:": "Irakurri gehiago: {0}",
|
||||
"Status:": "Egoera: {0}",
|
||||
"Read more": "Irakurri gehiago",
|
||||
appriseInstalled: "Apprise instalatuta.",
|
||||
appriseNotInstalled: "Apprise ez dago instalatuta. {0}",
|
||||
"Access Token": "Access Token",
|
||||
"Channel access token": "Channel access token",
|
||||
"Line Developers Console": "Line Developers Console",
|
||||
lineDevConsoleTo: "Line Developers Console - {0}",
|
||||
"Basic Settings": "Oinarrizko ezarpenak",
|
||||
"User ID": "Erabiltzaile 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": "Ikono 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 the Webhook posts to by entering the channel name into \"Channel Name\" field. This needs to be enabled in the 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",
|
||||
matrixHomeserverURL: "Hasiera zerbitzari URL (with http(s):// and optionally port)",
|
||||
"Internal Room Id": "Internal Room ID",
|
||||
matrixDesc1: "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.",
|
||||
matrixDesc2: "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 {0}",
|
||||
Method: "Metodoa",
|
||||
Body: "Gorputza",
|
||||
Headers: "Goiburuak",
|
||||
PushUrl: "Push URL",
|
||||
HeadersInvalidFormat: "The request headers are not valid JSON: ",
|
||||
BodyInvalidFormat: "The request body is not valid JSON: ",
|
||||
"Monitor History": "Monitorizazio Historia",
|
||||
clearDataOlderThan: "Keep monitor history data for {0} days.",
|
||||
PasswordsDoNotMatch: "Pasahitzak ez datoz bat.",
|
||||
records: "records",
|
||||
"One record": "One record",
|
||||
steamApiKeyDescription: "For monitoring a Steam Game Server you need a Steam Web-API key. You can register your API key here: ",
|
||||
"Current User": "Uneko erabiltzailea",
|
||||
topic: "Topic",
|
||||
topicExplanation: "MQTT topic to monitor",
|
||||
successMessage: "Arrakasta mezua",
|
||||
successMessageExplanation: "MQTT message that will be considered as success",
|
||||
recent: "Duela gutxikoa",
|
||||
Done: "Egina",
|
||||
Info: "Info",
|
||||
Security: "Segurtasuna",
|
||||
"Steam API Key": "Steam API Giltza",
|
||||
"Shrink Database": "Shrink Datubasea",
|
||||
"Pick a RR-Type...": "Pick a RR-Type...",
|
||||
"Pick Accepted Status Codes...": "Hautatu onartutako egoera kodeak...",
|
||||
Default: "Lehenetsia",
|
||||
"HTTP Options": "HTTP Aukerak",
|
||||
"Create Incident": "Sortu inzidentzia",
|
||||
Title: "Titulua",
|
||||
Content: "Edukia",
|
||||
Style: "Estiloa",
|
||||
info: "info",
|
||||
warning: "kontuz",
|
||||
danger: "arriskua",
|
||||
error: "errorea",
|
||||
critical: "kritikoa",
|
||||
primary: "oinarrizkoa",
|
||||
light: "argia",
|
||||
dark: "iluna",
|
||||
Post: "Post",
|
||||
"Please input title and content": "Mesedez sartu titulua eta edukia",
|
||||
Created: "Sortuta",
|
||||
"Last Updated": "Azken eguneratzea",
|
||||
Unpin: "Unpin",
|
||||
"Switch to Light Theme": "Aldatu gai argira",
|
||||
"Switch to Dark Theme": "Aldatu gai ilunera",
|
||||
"Show Tags": "Erakutsi etiketak",
|
||||
"Hide Tags": "Ezkutatu etiketak",
|
||||
Description: "Deskribapena",
|
||||
"No monitors available.": "Monitorizaziorik eskuragarri ez.",
|
||||
"Add one": "Gehitu bat",
|
||||
"No Monitors": "Monitorizaziorik ez",
|
||||
"Untitled Group": "Titulurik gabeko taldea",
|
||||
Services: "Zerbitzuak",
|
||||
Discard: "Baztertu",
|
||||
Cancel: "Ezeztatu",
|
||||
"Powered by": "Honekin egina:",
|
||||
shrinkDatabaseDescription: "Trigger database VACUUM for SQLite. If your database is created after 1.10.0, AUTO_VACUUM is already enabled and this action is not needed.",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
serwersmsAPIUser: "API erabiltzailea (webapi_ aurre-hizkia barne)",
|
||||
serwersmsAPIPassword: "API pasahitza",
|
||||
serwersmsPhoneNumber: "Telefono zenbakia",
|
||||
serwersmsSenderName: "SMS bidaltzaile izena (registered via customer portal)",
|
||||
stackfield: "Stackfield",
|
||||
Customize: "Pertsonalizatu",
|
||||
"Custom Footer": "Oin pertsonalizatua",
|
||||
"Custom CSS": "CSS pertsonalizatua",
|
||||
smtpDkimSettings: "DKIM ezarpenak",
|
||||
smtpDkimDesc: "Please refer to the Nodemailer DKIM {0} for usage.",
|
||||
documentation: "dokumentazioa",
|
||||
smtpDkimDomain: "Domeinu izena",
|
||||
smtpDkimKeySelector: "Gako hautatzailea",
|
||||
smtpDkimPrivateKey: "Gako pribatua",
|
||||
smtpDkimHashAlgo: "Hash algoritmoa (hautazkoa)",
|
||||
smtpDkimheaderFieldNames: "Header Keys to sign (Optional)",
|
||||
smtpDkimskipFields: "Header Keys not to sign (Optional)",
|
||||
wayToGetPagerDutyKey: "You can get this by going to Service -> Service Directory -> (Select a service) -> Integrations -> Add integration. Here you can search for \"Events API V2\". More info {0}",
|
||||
"Integration Key": "Integration Key",
|
||||
"Integration URL": "Integrazio URLa",
|
||||
"Auto resolve or acknowledged": "Auto resolve or acknowledged",
|
||||
"do nothing": "ez egin ezer",
|
||||
"auto acknowledged": "auto acknowledged",
|
||||
"auto resolve": "auto resolve",
|
||||
gorush: "Gorush",
|
||||
alerta: "Alerta",
|
||||
alertaApiEndpoint: "API Endpoint",
|
||||
alertaEnvironment: "Ingurunea",
|
||||
alertaApiKey: "API Key",
|
||||
alertaAlertState: "Alerta egoera",
|
||||
alertaRecoverState: "Berreskuratze egoera",
|
||||
deleteStatusPageMsg: "Ziur zaude egoera orri hau ezabatu nahi duzula?",
|
||||
Proxies: "Proxiak",
|
||||
default: "Lehenetsia",
|
||||
enabled: "Gaituta",
|
||||
setAsDefault: "Ezarri lehenetsitzat",
|
||||
deleteProxyMsg: "Are you sure want to delete this proxy for all monitors?",
|
||||
proxyDescription: "Proxies must be assigned to a monitor to function.",
|
||||
enableProxyDescription: "This proxy will not effect on monitor requests until it is activated. You can control temporarily disable the proxy from all monitors by activation status.",
|
||||
setAsDefaultProxyDescription: "This proxy will be enabled by default for new monitors. You can still disable the proxy separately for each monitor.",
|
||||
"Certificate Chain": "Certificate Chain",
|
||||
Valid: "Baliozkoa",
|
||||
Invalid: "Baliogabea",
|
||||
AccessKeyId: "AccessKey ID",
|
||||
SecretAccessKey: "AccessKey Secret",
|
||||
PhoneNumbers: "TelefonoZenbakiak",
|
||||
TemplateCode: "TemplateCode",
|
||||
SignName: "SignName",
|
||||
"Sms template must contain parameters: ": "Sms txantiloiak parametroak eduki behar ditu: ",
|
||||
"Bark Endpoint": "Bark Endpoint",
|
||||
WebHookUrl: "WebHookUrl",
|
||||
SecretKey: "SecretKey",
|
||||
"For safety, must use secret key": "For safety, must use secret key",
|
||||
"Device Token": "Gailu tokena",
|
||||
Platform: "Plataforma",
|
||||
iOS: "iOS",
|
||||
Android: "Android",
|
||||
Huawei: "Huawei",
|
||||
High: "Altua",
|
||||
Retry: "Errepikatu",
|
||||
Topic: "Gaia",
|
||||
"WeCom Bot Key": "WeCom Bot Key",
|
||||
"Setup Proxy": "Ezarri Proxya",
|
||||
"Proxy Protocol": "Proxy protokoloa",
|
||||
"Proxy Server": "Proxy zerbitzaria",
|
||||
"Proxy server has authentication": "Proxy zerbitzariak autentifikazioa dauka",
|
||||
User: "Erabiltzailea",
|
||||
Installed: "Instalatuta",
|
||||
"Not installed": "Instalatu gabe",
|
||||
Running: "Martxan",
|
||||
"Not running": "Ez martxan",
|
||||
"Remove Token": "Ezabatu Tokena",
|
||||
Start: "Hasi",
|
||||
Stop: "Gelditu",
|
||||
"Uptime Kuma": "Uptime Kuma",
|
||||
"Add New Status Page": "Gehitu egoera orri berria",
|
||||
Slug: "Sluga",
|
||||
"Accept characters:": "Onartu karaktereak:",
|
||||
startOrEndWithOnly: "Start or end with {0} only",
|
||||
"No consecutive dashes": "No consecutive dashes",
|
||||
Next: "Hurrengoa",
|
||||
"The slug is already taken. Please choose another slug.": "Sluga dagoeneko hartuta dago. Mesedez beste bat hautatu.",
|
||||
"No Proxy": "Proxyrik ez",
|
||||
Authentication: "Authentication",
|
||||
"HTTP Basic Auth": "HTTP oinarrizko Auth",
|
||||
"New Status Page": "Egoera orri berria",
|
||||
"Page Not Found": "Orria ez da aurkitu",
|
||||
"Reverse Proxy": "Alderantzizkako Proxya",
|
||||
Backup: "Backup",
|
||||
About: "Honi buruz",
|
||||
wayToGetCloudflaredURL: "(Download cloudflared from {0})",
|
||||
cloudflareWebsite: "Cloudflare webgunea",
|
||||
"Message:": "Mezua:",
|
||||
"Don't know how to get the token? Please read the guide:": "Don't know how to get the token? Please read the guide:",
|
||||
"The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.": "The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.",
|
||||
"Other Software": "Beste softwarea",
|
||||
"For example: nginx, Apache and Traefik.": "Adibidez: nginx, Apache and Traefik.",
|
||||
"Please read": "Mesedez irakurri",
|
||||
"Subject:": "Gaia:",
|
||||
"Valid To:": "Balio-epea:",
|
||||
"Days Remaining:": "Egun faltan:",
|
||||
"Issuer:": "Issuer:",
|
||||
"Fingerprint:": "Hatzmarka:",
|
||||
"No status pages": "Egoera orririk ez",
|
||||
"Domain Name Expiry Notification": "Domeinu izen iraungitze jakinarazpena",
|
||||
Proxy: "Proxya",
|
||||
"Date Created": "Data sortuta",
|
||||
onebotHttpAddress: "OneBot HTTP helbidea",
|
||||
onebotMessageType: "OneBot mezu mota",
|
||||
onebotGroupMessage: "Taldea",
|
||||
onebotPrivateMessage: "Pribatua",
|
||||
onebotUserOrGroupId: "Talde/Erabiltzaile IDa",
|
||||
onebotSafetyTips: "For safety, must set access token",
|
||||
"PushDeer Key": "PushDeer Key",
|
||||
"Footer Text": "Oineko testua",
|
||||
"Show Powered By": "Erakutsi Honekin egina:",
|
||||
"Domain Names": "Domeinu izenak",
|
||||
signedInDisp: "Signed in as {0}",
|
||||
signedInDispDisabled: "Auth desgaituta.",
|
||||
"Certificate Expiry Notification": "Zertifikatu iraungitze jakinarazpena",
|
||||
"API Username": "API Erabiltzailea",
|
||||
"API Key": "API Gakoa",
|
||||
"Recipient Number": "Recipient Number",
|
||||
"From Name/Number": "From Name/Number",
|
||||
"Leave blank to use a shared sender number.": "Leave blank to use a shared sender number.",
|
||||
"Octopush API Version": "Octopush API Version",
|
||||
"Legacy Octopush-DM": "Legacy Octopush-DM",
|
||||
endpoint: "endpoint",
|
||||
octopushAPIKey: "\"API key\" from HTTP API credentials in control panel",
|
||||
octopushLogin: "\"Login\" from HTTP API credentials in control panel",
|
||||
promosmsLogin: "API Saio haste izena",
|
||||
promosmsPassword: "API Pasahitza",
|
||||
"pushoversounds pushover": "Pushover (defektuz)",
|
||||
"pushoversounds bike": "Bizikleta",
|
||||
"pushoversounds bugle": "Bugle",
|
||||
"pushoversounds cashregister": "Cash Register",
|
||||
"pushoversounds classical": "Klasikoa",
|
||||
"pushoversounds cosmic": "Kosmikoa",
|
||||
"pushoversounds falling": "Erortzen",
|
||||
"pushoversounds gamelan": "Gamelan",
|
||||
"pushoversounds incoming": "Incoming",
|
||||
"pushoversounds intermission": "Intermission",
|
||||
"pushoversounds magic": "Magia",
|
||||
"pushoversounds mechanical": "Mekanikoa",
|
||||
"pushoversounds pianobar": "Piano Bar",
|
||||
"pushoversounds siren": "Sirena",
|
||||
"pushoversounds spacealarm": "Espazio Alarma",
|
||||
"pushoversounds tugboat": "Tug Boat",
|
||||
"pushoversounds alien": "Alien Alarm (long)",
|
||||
"pushoversounds climb": "Climb (long)",
|
||||
"pushoversounds persistent": "Persistent (long)",
|
||||
"pushoversounds echo": "Pushover Echo (long)",
|
||||
"pushoversounds updown": "Up Down (long)",
|
||||
"pushoversounds vibrate": "Bibrazioa soilik",
|
||||
"pushoversounds none": "Bat ere ez (isilik)",
|
||||
pushyAPIKey: "Secret API giltza",
|
||||
pushyToken: "Gailu tokena",
|
||||
"Show update if available": "Erakutsi eguneratzea eskuragarri badago",
|
||||
"Also check beta release": "Beta bertsioak ere egiaztatu",
|
||||
"Using a Reverse Proxy?": "Proxy alderantzizkako zerbitzaria erabiltzen?",
|
||||
"Check how to config it for WebSocket": "Check how to config it for WebSocket",
|
||||
"Steam Game Server": "Steam joko zerbitzaria",
|
||||
"Most likely causes:": "Arrazoi probableenak:",
|
||||
"The resource is no longer available.": "Baliabidea ez dago erabilgarri.",
|
||||
"There might be a typing error in the address.": "Idazketa-akats bat egon daiteke helbidean.",
|
||||
"What you can try:": "Probatu dezakezuna:",
|
||||
"Retype the address.": "Berridatzi helbidea.",
|
||||
"Go back to the previous page.": "Itzuli aurreko orrialdera",
|
||||
"Coming Soon": "Laster",
|
||||
wayToGetClickSendSMSToken: "API erabiltzailea and API giltza hemendik lortu ditzakezu: {0} .",
|
||||
"Connection String": "Konexio katea",
|
||||
Query: "Kontsulta",
|
||||
settingsCertificateExpiry: "TLS irungitze zertifikatua",
|
||||
certificationExpiryDescription: "HTTPS Monitorizazio jakinarazpena martxan jarri TLS zertifikatua iraungitzeko hau falta denean:",
|
||||
"ntfy Topic": "ntfy Topic",
|
||||
Domain: "Domeinua",
|
||||
Workstation: "Lan gunea",
|
||||
disableCloudflaredNoAuthMsg: "Ez Auth moduan zaude, pasahitza ez da beharrezkoa.",
|
||||
};
|
@ -90,8 +90,11 @@ export default {
|
||||
"New Password": "Nieuw wachtwoord",
|
||||
"Repeat New Password": "Herhaal nieuw wachtwoord",
|
||||
"Update Password": "Vernieuw wachtwoord",
|
||||
"Disable Auth": "Autorisatie uitschakelen",
|
||||
"Enable Auth": "Autorisatie inschakelen",
|
||||
"Disable Auth": "Authenticatie uitschakelen",
|
||||
"Enable Auth": "Authenticatie inschakelen",
|
||||
"disableauth.message1": "Weet je zeker dat je <strong>authenticatie wilt uitschakelen</strong>?",
|
||||
"disableauth.message2": "Er zijn omstandigheden waarbij je <strong>authenticatie door derden wilt implementeren</strong> voor Uptime Kuma, zoals Cloudflare Access, Authelia of andere authenticatiemechanismen.",
|
||||
"Please use this option carefully!": "Gebruik deze optie zorgvuldig!",
|
||||
Logout: "Uitloggen",
|
||||
Leave: "Vertrekken",
|
||||
"I understand, please disable": "Ik begrijp het, schakel a.u.b. uit",
|
||||
@ -351,7 +354,7 @@ export default {
|
||||
Discard: "Weggooien",
|
||||
Cancel: "Annuleren",
|
||||
"Powered by": "Mogelijk gemaakt door",
|
||||
shrinkDatabaseDescription: "Trigger database VACUUM voor SQLite. Als de database na 1.10.0 gemaakt is, dan is AUTO_VACUUM al aangezet en deze actie niet nodig.",
|
||||
shrinkDatabaseDescription: "Activeer database VACUUM voor SQLite. Als de database na 1.10.0 aangemaakt is, dan staat AUTO_VACUUM al aan en is deze actie niet nodig.",
|
||||
serwersms: "SerwerSMS.pl",
|
||||
serwersmsAPIUser: "API Gebruikersnaam (incl. webapi_ prefix)",
|
||||
serwersmsAPIPassword: "API Wachtwoord",
|
||||
@ -386,7 +389,7 @@ export default {
|
||||
proxyDescription: "Proxies moeten worden toegewezen aan een monitor om te functioneren.",
|
||||
enableProxyDescription: "Deze proxy heeft geen effect op monitor verzoeken totdat het is geactiveerd. Je kunt tijdelijk de proxy uitschakelen voor alle monitors voor activatie status.",
|
||||
setAsDefaultProxyDescription: "Deze proxy wordt standaard aangezet voor alle nieuwe monitors. Je kunt nog steeds de proxy apart uitschakelen voor elke monitor.",
|
||||
"Certificate Chain": "Certificaat Chain",
|
||||
"Certificate Chain": "Certificaatketen",
|
||||
Valid: "Geldig",
|
||||
Invalid: "Ongeldig",
|
||||
AccessKeyId: "AccessKey ID",
|
||||
@ -407,7 +410,7 @@ export default {
|
||||
High: "Hoog",
|
||||
Retry: "Opnieuw",
|
||||
Topic: "Onderwerp",
|
||||
"WeCom Bot Key": "WeCom Bot Sleutel",
|
||||
"WeCom Bot Key": "WeCom Bot Key",
|
||||
"Setup Proxy": "Proxy instellen",
|
||||
"Proxy Protocol": "Proxy Protocol",
|
||||
"Proxy Server": "Proxy Server",
|
||||
@ -449,7 +452,6 @@ export default {
|
||||
"Issuer:": "Uitgever:",
|
||||
"Fingerprint:": "Vingerafruk:",
|
||||
"No status pages": "Geen status pagina's",
|
||||
"Domain Name Expiry Notification": "Domein Naam Verloop Notificatie",
|
||||
Proxy: "Proxy",
|
||||
"Date Created": "Datum Aangemaakt",
|
||||
onebotHttpAddress: "OneBot HTTP Adres",
|
||||
@ -460,6 +462,70 @@ export default {
|
||||
onebotSafetyTips: "Voor de veiligheid moet een toegangssleutel worden ingesteld",
|
||||
"PushDeer Key": "PushDeer Key",
|
||||
"Footer Text": "Footer Tekst",
|
||||
"Show Powered By": "Laat 'Mogeljik gemaakt door' zien",
|
||||
"Show Powered By": "Laat \"Mogeljik gemaakt door\" zien",
|
||||
"Domain Names": "Domein Namen",
|
||||
"pushoversounds pushover": "Pushover (default)",
|
||||
"pushoversounds bike": "Bike",
|
||||
"pushoversounds bugle": "Bugle",
|
||||
"pushoversounds cashregister": "Cash Register",
|
||||
"pushoversounds classical": "Classical",
|
||||
"pushoversounds cosmic": "Cosmic",
|
||||
"pushoversounds falling": "Falling",
|
||||
"pushoversounds gamelan": "Gamelan",
|
||||
"pushoversounds incoming": "Incoming",
|
||||
"pushoversounds intermission": "Intermission",
|
||||
"pushoversounds magic": "Magic",
|
||||
"pushoversounds mechanical": "Mechanical",
|
||||
"pushoversounds pianobar": "Piano Bar",
|
||||
"pushoversounds siren": "Siren",
|
||||
"pushoversounds spacealarm": "Space Alarm",
|
||||
"pushoversounds tugboat": "Tug Boat",
|
||||
"pushoversounds alien": "Alien Alarm (long)",
|
||||
"pushoversounds climb": "Climb (long)",
|
||||
"pushoversounds persistent": "Persistent (long)",
|
||||
"pushoversounds echo": "Pushover Echo (long)",
|
||||
"pushoversounds updown": "Up Down (long)",
|
||||
"pushoversounds vibrate": "Vibrate Only",
|
||||
"pushoversounds none": "None (silent)",
|
||||
dnsPortDescription: "DNS-serverpoort. Standaard ingesteld op 53. Je kunt de poort op elk moment wijzigen.",
|
||||
error: "fout",
|
||||
critical: "kritisch",
|
||||
wayToGetPagerDutyKey: "Je kunt dit krijgen door naar Service -> Service Directory -> (Selecteer een service) -> Integraties -> Integratie toevoegen te gaan. Hier kunt u zoeken naar \"Events API V2\". Meer informatie {0}",
|
||||
"Integration Key": "Integration Key",
|
||||
"Integration URL": "Integration URL",
|
||||
"Auto resolve or acknowledged": "Automatisch oplossen of bevestigen",
|
||||
"do nothing": "niets doen",
|
||||
"auto acknowledged": "automatisch bevestigen",
|
||||
"auto resolve": "automatisch oplossen",
|
||||
Authentication: "authenticatie",
|
||||
signedInDisp: "Aangemeld als {0}",
|
||||
signedInDispDisabled: "Authenticatie uitgeschakeld.",
|
||||
"Certificate Expiry Notification": "Melding over verlopen certificaat",
|
||||
"Recipient Number": "Nummer ontvanger",
|
||||
"From Name/Number": "Van naam/nummer",
|
||||
"Leave blank to use a shared sender number.": "Laat leeg om een gedeeld afzendernummer te gebruiken.",
|
||||
endpoint: "endpoint",
|
||||
pushyAPIKey: "Secret API Key",
|
||||
pushyToken: "Device token",
|
||||
"Show update if available": "Update weergeven indien beschikbaar",
|
||||
"Also check beta release": "Controleer ook de bètaversies",
|
||||
"Using a Reverse Proxy?": "Een reverse proxy gebruiken?",
|
||||
"Check how to config it for WebSocket": "Controleer hoe je het configureert voor een WebSocket",
|
||||
"Steam Game Server": "Steam gameserver",
|
||||
"Most likely causes:": "Meest waarschijnlijke oorzaken:",
|
||||
"The resource is no longer available.": "De paginabron is niet langer beschikbaar.",
|
||||
"There might be a typing error in the address.": "Er zit een typefout in het de URL.",
|
||||
"What you can try:": "Wat je kan proberen:",
|
||||
"Retype the address.": "De URL controleren en/of opnnieuw typen.",
|
||||
"Go back to the previous page.": "Terug naar de vorige pagina.",
|
||||
"Coming Soon": "Binnenkort beschikbaar",
|
||||
wayToGetClickSendSMSToken: "Je kan een API Username en API Key krijgen vanuit {0} .",
|
||||
"Connection String": "Connection String",
|
||||
Query: "Query",
|
||||
settingsCertificateExpiry: "TLS Certificate Expiry",
|
||||
certificationExpiryDescription: "HTTPS Monitors trigger notification when TLS certificate expires in:",
|
||||
"ntfy Topic": "ntfy Topic",
|
||||
Domain: "Domein",
|
||||
Workstation: "Werkstation",
|
||||
disableCloudflaredNoAuthMsg: "De \"Geen authenticatie\" modus staat aan, wachtwoord is niet vereist.",
|
||||
};
|
||||
|
@ -184,8 +184,8 @@ export default {
|
||||
"Add a monitor": "Dodaj monitor",
|
||||
"Edit Status Page": "Uredi statusno stran",
|
||||
"Go to Dashboard": "Pojdi na nadzorno ploščo",
|
||||
"Status Page": "Página de Status",
|
||||
"Status Pages": "Página de Status",
|
||||
"Status Page": "Statusna stran",
|
||||
"Status Pages": "Statusne strani",
|
||||
defaultNotificationName: "Moje {notification} Obvestilo ({number})",
|
||||
here: "tukaj",
|
||||
Required: "Obvezno",
|
||||
|
@ -601,6 +601,28 @@ export default {
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Frontend Version
|
||||
* It should be compiled to a static value while building the frontend.
|
||||
* Please see ./config/vite.config.js, it is defined via vite.js
|
||||
* @returns {string}
|
||||
*/
|
||||
frontendVersion() {
|
||||
// eslint-disable-next-line no-undef
|
||||
return FRONTEND_VERSION;
|
||||
},
|
||||
|
||||
/**
|
||||
* Are both frontend and backend in the same version?
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isFrontendBackendVersionMatched() {
|
||||
if (!this.info.version) {
|
||||
return true;
|
||||
}
|
||||
return this.info.version === this.frontendVersion;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
|
@ -535,7 +535,7 @@ export default {
|
||||
if (this.monitor.type === "dns") {
|
||||
this.monitor.port = "53";
|
||||
} else {
|
||||
this.monitor.port = "";
|
||||
this.monitor.port = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ export default {
|
||||
|
||||
.logo {
|
||||
width: $logo-width;
|
||||
height: $logo-width;
|
||||
|
||||
// Better when the image is loading
|
||||
min-height: 1px;
|
||||
|
Loading…
Reference in New Issue
Block a user