translate to Traditional Chinese (Hong Kong)

This commit is contained in:
LouisLam 2021-08-24 18:26:44 +08:00
parent dd4c00eed3
commit 28a51d806b
15 changed files with 226 additions and 135 deletions

View file

@ -4,7 +4,7 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 id="exampleModalLabel" class="modal-title"> <h5 id="exampleModalLabel" class="modal-title">
Confirm {{ $t("Confirm") }}
</h5> </h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" /> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
</div> </div>
@ -35,7 +35,7 @@ export default {
}, },
yesText: { yesText: {
type: String, type: String,
default: "Yes", default: "Yes", // TODO: No idea what to translate this
}, },
noText: { noText: {
type: String, type: String,

View file

@ -6,12 +6,12 @@
<div class="form-floating"> <div class="form-floating">
<input id="floatingInput" v-model="username" type="text" class="form-control" placeholder="Username"> <input id="floatingInput" v-model="username" type="text" class="form-control" placeholder="Username">
<label for="floatingInput">Username</label> <label for="floatingInput">{{ $t("Username") }}</label>
</div> </div>
<div class="form-floating mt-3"> <div class="form-floating mt-3">
<input id="floatingPassword" v-model="password" type="password" class="form-control" placeholder="Password"> <input id="floatingPassword" v-model="password" type="password" class="form-control" placeholder="Password">
<label for="floatingPassword">Password</label> <label for="floatingPassword">{{ $t("Password") }}</label>
</div> </div>
<div class="form-check mb-3 mt-3 d-flex justify-content-center pe-4"> <div class="form-check mb-3 mt-3 d-flex justify-content-center pe-4">
@ -19,12 +19,12 @@
<input id="remember" v-model="$root.remember" type="checkbox" value="remember-me" class="form-check-input"> <input id="remember" v-model="$root.remember" type="checkbox" value="remember-me" class="form-check-input">
<label class="form-check-label" for="remember"> <label class="form-check-label" for="remember">
Remember me {{ $t("Remember me") }}
</label> </label>
</div> </div>
</div> </div>
<button class="w-100 btn btn-primary" type="submit" :disabled="processing"> <button class="w-100 btn btn-primary" type="submit" :disabled="processing">
Login {{ $t("Login") }}
</button> </button>
<div v-if="res && !res.ok" class="alert alert-danger mt-3" role="alert"> <div v-if="res && !res.ok" class="alert alert-danger mt-3" role="alert">

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="shadow-box list mb-4"> <div class="shadow-box list mb-4">
<div v-if="Object.keys($root.monitorList).length === 0" class="text-center mt-3"> <div v-if="Object.keys($root.monitorList).length === 0" class="text-center mt-3">
No Monitors, please <router-link to="/add">add one</router-link>. {{ $t("No Monitors, please") }} <router-link to="/add">{{ $t("add one") }}</router-link>
</div> </div>
<router-link v-for="(item, index) in sortedMonitorList" :key="index" :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }"> <router-link v-for="(item, index) in sortedMonitorList" :key="index" :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }">

View file

@ -5,17 +5,17 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 id="exampleModalLabel" class="modal-title"> <h5 id="exampleModalLabel" class="modal-title">
Setup Notification {{ $t("Setup Notification") }}
</h5> </h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" /> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" />
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="mb-3"> <div class="mb-3">
<label for="type" class="form-label">Notification Type</label> <label for="type" class="form-label">{{ $t("Notification Type") }}</label>
<select id="type" v-model="notification.type" class="form-select"> <select id="type" v-model="notification.type" class="form-select">
<option value="telegram">Telegram</option> <option value="telegram">Telegram</option>
<option value="webhook">Webhook</option> <option value="webhook">Webhook</option>
<option value="smtp">Email (SMTP)</option> <option value="smtp">{{ $t("Email") }} (SMTP)</option>
<option value="discord">Discord</option> <option value="discord">Discord</option>
<option value="signal">Signal</option> <option value="signal">Signal</option>
<option value="gotify">Gotify</option> <option value="gotify">Gotify</option>
@ -31,7 +31,7 @@
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="name" class="form-label">Friendly Name</label> <label for="name" class="form-label">{{ $t("Friendly Name") }}</label>
<input id="name" v-model="notification.name" type="text" class="form-control" required> <input id="name" v-model="notification.name" type="text" class="form-control" required>
</div> </div>
@ -407,13 +407,13 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button v-if="id" type="button" class="btn btn-danger" :disabled="processing" @click="deleteConfirm"> <button v-if="id" type="button" class="btn btn-danger" :disabled="processing" @click="deleteConfirm">
Delete {{ $t("Delete") }}
</button> </button>
<button type="button" class="btn btn-warning" :disabled="processing" @click="test"> <button type="button" class="btn btn-warning" :disabled="processing" @click="test">
Test {{ $t("Test") }}
</button> </button>
<button type="submit" class="btn btn-primary" :disabled="processing"> <button type="submit" class="btn btn-primary" :disabled="processing">
Save {{ $t("Save") }}
</button> </button>
</div> </div>
</div> </div>

View file

@ -27,18 +27,18 @@ export default {
text() { text() {
if (this.status === 0) { if (this.status === 0) {
return "Down" return this.$t("Down");
} }
if (this.status === 1) { if (this.status === 1) {
return "Up" return this.$t("Up");
} }
if (this.status === 2) { if (this.status === 2) {
return "Pending" return this.$t("Pending");
} }
return "Unknown" return this.$t("Unknown");
}, },
}, },
} }

View file

@ -1,3 +1,12 @@
export default { export default {
languageName: "English", languageName: "English",
checkEverySecond: "Check every {0} seconds.",
"Avg.": "Avg. ",
retriesDescription: "Maximum retries before the service is marked as down and a notification is sent",
ignoreTLSError: "Ignore TLS/SSL error for HTTPS websites",
upsideDownModeDescription: "Flip the status upside down. If the service is reachable, it is DOWN.",
maxRedirectDescription: "Maximum number of redirects to follow. Set to 0 to disable redirects.",
acceptedStatusCodesDescription: "Select status codes which are considered as a successful response.",
passwordNotMatchMsg: "The repeat password does not match.",
notificationDescription: "Please assign a notification to monitor(s) to get it to work.",
} }

97
src/languages/zh-HK.js Normal file
View file

@ -0,0 +1,97 @@
export default {
languageName: "繁體中文 (香港)",
Settings: "設定",
Dashboard: "錶板",
"New Update": "有更新",
Language: "語言",
Appearance: "外觀",
Theme: "主題",
General: "一般",
Version: "版本",
"Check Update On GitHub": "到 Github 查看更新",
List: "列表",
Add: "新增",
"Add New Monitor": "新增監測器",
"Quick Stats": "綜合數據",
Up: "上線",
Down: "離線",
Pending: "待定",
Unknown: "不明",
Pause: "暫停",
Name: "名稱",
Status: "狀態",
DateTime: "日期時間",
Message: "內容",
"No important events": "沒有重要事件",
Resume: "恢復",
Edit: "編輯",
Delete: "刪除",
Current: "目前",
Uptime: "上線率",
"Cert Exp.": "証書期限",
days: "日",
day: "日",
"-day": "日",
hour: "小時",
"-hour": "小時",
checkEverySecond: "每 {0} 秒檢查一次",
"Avg.": "平均",
Response: "反應時間",
Ping: "反應時間",
"Monitor Type": "監測器類型",
Keyword: "關鍵字",
"Friendly Name": "名稱",
URL: "網址 URL",
Hostname: "Hostname",
Port: "Port",
"Heartbeat Interval": "檢查間距",
Retries: "重試數次確定為離線",
retriesDescription: "重試多少次後才判定為離線及傳送通知。如數值為 0 會即判定為離線及傳送通知。",
Advanced: "進階",
ignoreTLSError: "忽略 TLS/SSL 錯誤",
"Upside Down Mode": "反轉模式",
upsideDownModeDescription: "反轉狀態,如網址是可正常瀏覽,會被判定為 '離線/DOWN'",
"Max. Redirects": "跟隨重新導向 (Redirect) 的次數",
maxRedirectDescription: "設為 0 即不跟蹤",
"Accepted Status Codes": "接受為上線的 HTTP 狀態碼",
acceptedStatusCodesDescription: "可多選",
Save: "儲存",
Notifications: "通知",
"Not available, please setup.": "無法使用,需要設定",
"Setup Notification": "設定通知",
Light: "明亮",
Dark: "暗黑",
Auto: "自動",
"Theme - Heartbeat Bar": "監測器列表 狀態條外觀",
Normal: "一般",
Bottom: "下方",
None: "沒有",
Timezone: "時區",
"Search Engine Visibility": "是否允許搜尋器索引",
"Allow indexing": "允許索引",
"Discourage search engines from indexing site": "不建議搜尋器索引",
"Change Password": "變更密碼",
"Current Password": "目前密碼",
"New Password": "新密碼",
"Repeat New Password": "確認新密碼",
passwordNotMatchMsg: "密碼不一致",
"Update Password": "更新密碼",
"Disable Auth": "取消登入認証",
"Enable Auth": "開啟登入認証",
Logout: "登出",
notificationDescription: "新增後,你需要在監測器裡啟用。",
Leave: "離開",
"I understand, please disable": "我明白,請取消登入認証",
Confirm: "確認",
Yes: "是",
No: "否",
Username: "帳號",
Password: "密碼",
"Remember me": "記住我",
Login: "登入",
"No Monitors, please": "沒有監測器,請",
"add one": "新增",
"Notification Type": "通知類型",
"Email": "電郵",
"Test": "測試",
}

View file

@ -1,10 +0,0 @@
export default {
languageName: "繁體中文 (香港)",
Settings: "設定",
Dashboard: "錶板",
"New Update": "有更新",
Language: "語言",
Appearance: "外觀",
Theme: "主題",
General: "一般",
}

View file

@ -48,8 +48,8 @@
<footer> <footer>
<div class="container-fluid"> <div class="container-fluid">
Uptime Kuma - Uptime Kuma -
Version: {{ $root.info.version }} - {{ $t("Version") }}: {{ $root.info.version }} -
<a href="https://github.com/louislam/uptime-kuma/releases" target="_blank" rel="noopener">Check Update On GitHub</a> <a href="https://github.com/louislam/uptime-kuma/releases" target="_blank" rel="noopener">{{ $t("Check Update On GitHub") }}</a>
</div> </div>
</footer> </footer>
@ -63,12 +63,12 @@
<router-link to="/list" class="nav-link"> <router-link to="/list" class="nav-link">
<div><font-awesome-icon icon="list" /></div> <div><font-awesome-icon icon="list" /></div>
List {{ $t("List") }}
</router-link> </router-link>
<router-link to="/add" class="nav-link"> <router-link to="/add" class="nav-link">
<div><font-awesome-icon icon="plus" /></div> <div><font-awesome-icon icon="plus" /></div>
Add {{ $t("Add") }}
</router-link> </router-link>
<router-link to="/settings" class="nav-link"> <router-link to="/settings" class="nav-link">

View file

@ -24,7 +24,7 @@ import List from "./pages/List.vue";
import { appName } from "./util.ts"; import { appName } from "./util.ts";
import en from "./languages/en"; import en from "./languages/en";
import zhHK from "./languages/zh-hk"; import zhHK from "./languages/zh-HK";
const routes = [ const routes = [
{ {
@ -89,7 +89,7 @@ const router = createRouter({
const languageList = { const languageList = {
en, en,
zhHK, "zh-HK": zhHK,
}; };
const i18n = createI18n({ const i18n = createI18n({

View file

@ -3,7 +3,7 @@
<div class="row"> <div class="row">
<div v-if="! $root.isMobile" class="col-12 col-md-5 col-xl-4"> <div v-if="! $root.isMobile" class="col-12 col-md-5 col-xl-4">
<div> <div>
<router-link to="/add" class="btn btn-primary mb-3"><font-awesome-icon icon="plus" /> Add New Monitor</router-link> <router-link to="/add" class="btn btn-primary mb-3"><font-awesome-icon icon="plus" /> {{ $t("Add New Monitor") }}</router-link>
</div> </div>
<MonitorList /> <MonitorList />
</div> </div>

View file

@ -2,50 +2,38 @@
<transition name="slide-fade" appear> <transition name="slide-fade" appear>
<div v-if="$route.name === 'DashboardHome'"> <div v-if="$route.name === 'DashboardHome'">
<h1 class="mb-3"> <h1 class="mb-3">
Quick Stats {{ $t("Quick Stats") }}
</h1> </h1>
<div class="shadow-box big-padding text-center"> <div class="shadow-box big-padding text-center">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<h3>Up</h3> <h3>{{ $t("Up") }}</h3>
<span class="num">{{ stats.up }}</span> <span class="num">{{ stats.up }}</span>
</div> </div>
<div class="col"> <div class="col">
<h3>Down</h3> <h3>{{ $t("Down") }}</h3>
<span class="num text-danger">{{ stats.down }}</span> <span class="num text-danger">{{ stats.down }}</span>
</div> </div>
<div class="col"> <div class="col">
<h3>Unknown</h3> <h3>{{ $t("Unknown") }}</h3>
<span class="num text-secondary">{{ stats.unknown }}</span> <span class="num text-secondary">{{ stats.unknown }}</span>
</div> </div>
<div class="col"> <div class="col">
<h3>Pause</h3> <h3>{{ $t("Pause") }}</h3>
<span class="num text-secondary">{{ stats.pause }}</span> <span class="num text-secondary">{{ stats.pause }}</span>
</div> </div>
</div> </div>
<div v-if="false" class="row">
<div class="col-3">
<h3>Uptime</h3>
<p>(24-hour)</p>
<span class="num" />
</div>
<div class="col-3">
<h3>Uptime</h3>
<p>(30-day)</p>
<span class="num" />
</div>
</div>
</div> </div>
<div class="shadow-box" style="margin-top: 25px;overflow-x: scroll"> <div class="shadow-box" style="margin-top: 25px;overflow-x: scroll">
<table class="table table-borderless table-hover"> <table class="table table-borderless table-hover">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>{{ $t("Name") }}</th>
<th>Status</th> <th>{{ $t("Status") }}</th>
<th>DateTime</th> <th>{{ $t("DateTime") }}</th>
<th>Message</th> <th>{{ $t("Message") }}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -58,7 +46,7 @@
<tr v-if="importantHeartBeatList.length === 0"> <tr v-if="importantHeartBeatList.length === 0">
<td colspan="4"> <td colspan="4">
No important events {{ $t("No important events") }}
</td> </td>
</tr> </tr>
</tbody> </tbody>

View file

@ -14,16 +14,16 @@
<div class="functions"> <div class="functions">
<button v-if="monitor.active" class="btn btn-light" @click="pauseDialog"> <button v-if="monitor.active" class="btn btn-light" @click="pauseDialog">
<font-awesome-icon icon="pause" /> Pause <font-awesome-icon icon="pause" /> {{ $t("Pause") }}
</button> </button>
<button v-if="! monitor.active" class="btn btn-primary" @click="resumeMonitor"> <button v-if="! monitor.active" class="btn btn-primary" @click="resumeMonitor">
<font-awesome-icon icon="play" /> Resume <font-awesome-icon icon="play" /> {{ $t("Resume") }}
</button> </button>
<router-link :to=" '/edit/' + monitor.id " class="btn btn-secondary"> <router-link :to=" '/edit/' + monitor.id " class="btn btn-secondary">
<font-awesome-icon icon="edit" /> Edit <font-awesome-icon icon="edit" /> {{ $t("Edit") }}
</router-link> </router-link>
<button class="btn btn-danger" @click="deleteDialog"> <button class="btn btn-danger" @click="deleteDialog">
<font-awesome-icon icon="trash" /> Delete <font-awesome-icon icon="trash" /> {{ $t("Delete") }}
</button> </button>
</div> </div>
@ -31,7 +31,7 @@
<div class="row"> <div class="row">
<div class="col-md-8"> <div class="col-md-8">
<HeartbeatBar :monitor-id="monitor.id" /> <HeartbeatBar :monitor-id="monitor.id" />
<span class="word">Check every {{ monitor.interval }} seconds.</span> <span class="word">{{ $t("checkEverySecond", [ monitor.interval ]) }}</span>
</div> </div>
<div class="col-md-4 text-center"> <div class="col-md-4 text-center">
<span class="badge rounded-pill" :class=" 'bg-' + status.color " style="font-size: 30px">{{ status.text }}</span> <span class="badge rounded-pill" :class=" 'bg-' + status.color " style="font-size: 30px">{{ status.text }}</span>
@ -43,7 +43,7 @@
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<h4>{{ pingTitle }}</h4> <h4>{{ pingTitle }}</h4>
<p>(Current)</p> <p>({{ $t("Current") }})</p>
<span class="num"> <span class="num">
<a href="#" @click.prevent="showPingChartBox = !showPingChartBox"> <a href="#" @click.prevent="showPingChartBox = !showPingChartBox">
<CountUp :value="ping" /> <CountUp :value="ping" />
@ -51,26 +51,26 @@
</span> </span>
</div> </div>
<div class="col"> <div class="col">
<h4>Avg. {{ pingTitle }}</h4> <h4>{{ $t("Avg.") }}{{ pingTitle }}</h4>
<p>(24-hour)</p> <p>(24{{ $t("-hour") }})</p>
<span class="num"><CountUp :value="avgPing" /></span> <span class="num"><CountUp :value="avgPing" /></span>
</div> </div>
<div class="col"> <div class="col">
<h4>Uptime</h4> <h4>{{ $t("Uptime") }}</h4>
<p>(24-hour)</p> <p>(24{{ $t("-hour") }})</p>
<span class="num"><Uptime :monitor="monitor" type="24" /></span> <span class="num"><Uptime :monitor="monitor" type="24" /></span>
</div> </div>
<div class="col"> <div class="col">
<h4>Uptime</h4> <h4>{{ $t("Uptime") }}</h4>
<p>(30-day)</p> <p>(30{{ $t("-day") }})</p>
<span class="num"><Uptime :monitor="monitor" type="720" /></span> <span class="num"><Uptime :monitor="monitor" type="720" /></span>
</div> </div>
<div v-if="certInfo" class="col"> <div v-if="certInfo" class="col">
<h4>Cert Exp.</h4> <h4>{{ $t("Cert Exp.") }}</h4>
<p>(<Datetime :value="certInfo.validTo" date-only />)</p> <p>(<Datetime :value="certInfo.validTo" date-only />)</p>
<span class="num"> <span class="num">
<a href="#" @click.prevent="toggleCertInfoBox = !toggleCertInfoBox">{{ certInfo.daysRemaining }} days</a> <a href="#" @click.prevent="toggleCertInfoBox = !toggleCertInfoBox">{{ certInfo.daysRemaining }} {{ $t("days") }}</a>
</span> </span>
</div> </div>
</div> </div>
@ -132,9 +132,9 @@
<table class="table table-borderless table-hover"> <table class="table table-borderless table-hover">
<thead> <thead>
<tr> <tr>
<th>Status</th> <th>{{ $t("Status") }}</th>
<th>DateTime</th> <th>{{ $t("DateTime") }}</th>
<th>Message</th> <th>{{ $t("Message") }}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -146,7 +146,7 @@
<tr v-if="importantHeartBeatList.length === 0"> <tr v-if="importantHeartBeatList.length === 0">
<td colspan="3"> <td colspan="3">
No important events {{ $t("No important events") }}
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -209,10 +209,9 @@ export default {
pingTitle() { pingTitle() {
if (this.monitor.type === "http") { if (this.monitor.type === "http") {
return "Response" return this.$t("Response");
} }
return this.$t("Ping");
return "Ping"
}, },
monitor() { monitor() {

View file

@ -6,10 +6,10 @@
<div class="shadow-box"> <div class="shadow-box">
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<h2 class="mb-2">General</h2> <h2 class="mb-2">{{ $t("General") }}</h2>
<div class="my-3"> <div class="my-3">
<label for="type" class="form-label">Monitor Type</label> <label for="type" class="form-label">{{ $t("Monitor Type") }}</label>
<select id="type" v-model="monitor.type" class="form-select" aria-label="Default select example"> <select id="type" v-model="monitor.type" class="form-select" aria-label="Default select example">
<option value="http"> <option value="http">
HTTP(s) HTTP(s)
@ -21,23 +21,23 @@
Ping Ping
</option> </option>
<option value="keyword"> <option value="keyword">
HTTP(s) - Keyword HTTP(s) - {{ $t("Keyword") }}
</option> </option>
</select> </select>
</div> </div>
<div class="my-3"> <div class="my-3">
<label for="name" class="form-label">Friendly Name</label> <label for="name" class="form-label">{{ $t("Friendly Name") }}</label>
<input id="name" v-model="monitor.name" type="text" class="form-control" required> <input id="name" v-model="monitor.name" type="text" class="form-control" required>
</div> </div>
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3"> <div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3">
<label for="url" class="form-label">URL</label> <label for="url" class="form-label">{{ $t("URL") }}</label>
<input id="url" v-model="monitor.url" type="url" class="form-control" pattern="https?://.+" required> <input id="url" v-model="monitor.url" type="url" class="form-control" pattern="https?://.+" required>
</div> </div>
<div v-if="monitor.type === 'keyword' " class="my-3"> <div v-if="monitor.type === 'keyword' " class="my-3">
<label for="keyword" class="form-label">Keyword</label> <label for="keyword" class="form-label">{{ $t("Keyword") }}</label>
<input id="keyword" v-model="monitor.keyword" type="text" class="form-control" required> <input id="keyword" v-model="monitor.keyword" type="text" class="form-control" required>
<div class="form-text"> <div class="form-text">
Search keyword in plain html or JSON response and it is case-sensitive Search keyword in plain html or JSON response and it is case-sensitive
@ -45,57 +45,57 @@
</div> </div>
<div v-if="monitor.type === 'port' || monitor.type === 'ping' " class="my-3"> <div v-if="monitor.type === 'port' || monitor.type === 'ping' " class="my-3">
<label for="hostname" class="form-label">Hostname</label> <label for="hostname" class="form-label">{{ $t("Hostname") }}</label>
<input id="hostname" v-model="monitor.hostname" type="text" class="form-control" required> <input id="hostname" v-model="monitor.hostname" type="text" class="form-control" required>
</div> </div>
<div v-if="monitor.type === 'port' " class="my-3"> <div v-if="monitor.type === 'port' " class="my-3">
<label for="port" class="form-label">Port</label> <label for="port" class="form-label">{{ $t("Port") }}</label>
<input id="port" v-model="monitor.port" type="number" class="form-control" required min="0" max="65535" step="1"> <input id="port" v-model="monitor.port" type="number" class="form-control" required min="0" max="65535" step="1">
</div> </div>
<div class="my-3"> <div class="my-3">
<label for="interval" class="form-label">Heartbeat Interval (Every {{ monitor.interval }} seconds)</label> <label for="interval" class="form-label">{{ $t("Heartbeat Interval") }} ({{ $t("checkEverySecond", [ monitor.interval ]) }})</label>
<input id="interval" v-model="monitor.interval" type="number" class="form-control" required min="20" step="1"> <input id="interval" v-model="monitor.interval" type="number" class="form-control" required min="20" step="1">
</div> </div>
<div class="my-3"> <div class="my-3">
<label for="maxRetries" class="form-label">Retries</label> <label for="maxRetries" class="form-label">{{ $t("Retries") }}</label>
<input id="maxRetries" v-model="monitor.maxretries" type="number" class="form-control" required min="0" step="1"> <input id="maxRetries" v-model="monitor.maxretries" type="number" class="form-control" required min="0" step="1">
<div class="form-text"> <div class="form-text">
Maximum retries before the service is marked as down and a notification is sent {{ $t("retriesDescription") }}
</div> </div>
</div> </div>
<h2 class="mt-5 mb-2">Advanced</h2> <h2 class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check"> <div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check">
<input id="ignore-tls" v-model="monitor.ignoreTls" class="form-check-input" type="checkbox" value=""> <input id="ignore-tls" v-model="monitor.ignoreTls" class="form-check-input" type="checkbox" value="">
<label class="form-check-label" for="ignore-tls"> <label class="form-check-label" for="ignore-tls">
Ignore TLS/SSL error for HTTPS websites {{ $t("ignoreTLSError") }}
</label> </label>
</div> </div>
<div class="my-3 form-check"> <div class="my-3 form-check">
<input id="upside-down" v-model="monitor.upsideDown" class="form-check-input" type="checkbox"> <input id="upside-down" v-model="monitor.upsideDown" class="form-check-input" type="checkbox">
<label class="form-check-label" for="upside-down"> <label class="form-check-label" for="upside-down">
Upside Down Mode {{ $t("Upside Down Mode") }}
</label> </label>
<div class="form-text"> <div class="form-text">
Flip the status upside down. If the service is reachable, it is DOWN. {{ $t("upsideDownModeDescription") }}
</div> </div>
</div> </div>
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3"> <div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3">
<label for="maxRedirects" class="form-label">Max. Redirects</label> <label for="maxRedirects" class="form-label">{{ $t("Max. Redirects") }}</label>
<input id="maxRedirects" v-model="monitor.maxredirects" type="number" class="form-control" required min="0" step="1"> <input id="maxRedirects" v-model="monitor.maxredirects" type="number" class="form-control" required min="0" step="1">
<div class="form-text"> <div class="form-text">
Maximum number of redirects to follow. Set to 0 to disable redirects. {{ $t("maxRedirectDescription") }}
</div> </div>
</div> </div>
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3"> <div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3">
<label for="acceptedStatusCodes" class="form-label">Accepted Status Codes</label> <label for="acceptedStatusCodes" class="form-label">{{ $t("Accepted Status Codes") }}</label>
<VueMultiselect <VueMultiselect
id="acceptedStatusCodes" id="acceptedStatusCodes"
@ -112,21 +112,21 @@
></VueMultiselect> ></VueMultiselect>
<div class="form-text"> <div class="form-text">
Select status codes which are considered as a successful response. {{ $t("acceptedStatusCodesDescription") }}
</div> </div>
</div> </div>
<div class="mt-5 mb-1"> <div class="mt-5 mb-1">
<button class="btn btn-primary" type="submit" :disabled="processing">Save</button> <button class="btn btn-primary" type="submit" :disabled="processing">{{ $t("Save") }}</button>
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div v-if="$root.isMobile" class="mt-3" /> <div v-if="$root.isMobile" class="mt-3" />
<h2 class="mb-2">Notifications</h2> <h2 class="mb-2">{{ $t("Notifications") }}</h2>
<p v-if="$root.notificationList.length === 0"> <p v-if="$root.notificationList.length === 0">
Not available, please setup. {{ $t("Not available, please setup.") }}
</p> </p>
<div v-for="notification in $root.notificationList" :key="notification.id" class="form-check form-switch my-3"> <div v-for="notification in $root.notificationList" :key="notification.id" class="form-check form-switch my-3">
@ -134,12 +134,12 @@
<label class="form-check-label" :for=" 'notification' + notification.id"> <label class="form-check-label" :for=" 'notification' + notification.id">
{{ notification.name }} {{ notification.name }}
<a href="#" @click="$refs.notificationDialog.show(notification.id)">Edit</a> <a href="#" @click="$refs.notificationDialog.show(notification.id)">{{ $t("Edit") }}</a>
</label> </label>
</div> </div>
<button class="btn btn-primary me-2" type="button" @click="$refs.notificationDialog.show()"> <button class="btn btn-primary me-2" type="button" @click="$refs.notificationDialog.show()">
Setup Notification {{ $t("Setup Notification") }}
</button> </button>
</div> </div>
</div> </div>
@ -175,7 +175,7 @@ export default {
computed: { computed: {
pageName() { pageName() {
return (this.isAdd) ? "Add New Monitor" : "Edit" return this.$t((this.isAdd) ? "Add New Monitor" : "Edit");
}, },
isAdd() { isAdd() {
return this.$route.path === "/add"; return this.$route.path === "/add";

View file

@ -25,29 +25,29 @@
<div> <div>
<div class="btn-group" role="group" aria-label="Basic checkbox toggle button group"> <div class="btn-group" role="group" aria-label="Basic checkbox toggle button group">
<input id="btncheck1" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="light"> <input id="btncheck1" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="light">
<label class="btn btn-outline-primary" for="btncheck1">Light</label> <label class="btn btn-outline-primary" for="btncheck1">{{ $t("Light") }}</label>
<input id="btncheck2" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="dark"> <input id="btncheck2" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="dark">
<label class="btn btn-outline-primary" for="btncheck2">Dark</label> <label class="btn btn-outline-primary" for="btncheck2">{{ $t("Dark") }}</label>
<input id="btncheck3" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="auto"> <input id="btncheck3" v-model="$root.userTheme" type="radio" class="btn-check" name="theme" autocomplete="off" value="auto">
<label class="btn btn-outline-primary" for="btncheck3">Auto</label> <label class="btn btn-outline-primary" for="btncheck3">{{ $t("Auto") }}</label>
</div> </div>
</div> </div>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label">Theme - Heartbeat Bar</label> <label class="form-label">{{ $t("Theme - Heartbeat Bar") }}</label>
<div> <div>
<div class="btn-group" role="group" aria-label="Basic checkbox toggle button group"> <div class="btn-group" role="group" aria-label="Basic checkbox toggle button group">
<input id="btncheck4" v-model="$root.userHeartbeatBar" type="radio" class="btn-check" name="heartbeatBarTheme" autocomplete="off" value="normal"> <input id="btncheck4" v-model="$root.userHeartbeatBar" type="radio" class="btn-check" name="heartbeatBarTheme" autocomplete="off" value="normal">
<label class="btn btn-outline-primary" for="btncheck4">Normal</label> <label class="btn btn-outline-primary" for="btncheck4">{{ $t("Normal") }}</label>
<input id="btncheck5" v-model="$root.userHeartbeatBar" type="radio" class="btn-check" name="heartbeatBarTheme" autocomplete="off" value="bottom"> <input id="btncheck5" v-model="$root.userHeartbeatBar" type="radio" class="btn-check" name="heartbeatBarTheme" autocomplete="off" value="bottom">
<label class="btn btn-outline-primary" for="btncheck5">Bottom</label> <label class="btn btn-outline-primary" for="btncheck5">{{ $t("Bottom") }}</label>
<input id="btncheck6" v-model="$root.userHeartbeatBar" type="radio" class="btn-check" name="heartbeatBarTheme" autocomplete="off" value="none"> <input id="btncheck6" v-model="$root.userHeartbeatBar" type="radio" class="btn-check" name="heartbeatBarTheme" autocomplete="off" value="none">
<label class="btn btn-outline-primary" for="btncheck6">None</label> <label class="btn btn-outline-primary" for="btncheck6">{{ $t("None") }}</label>
</div> </div>
</div> </div>
</div> </div>
@ -55,10 +55,10 @@
<h2 class="mt-5 mb-2">{{ $t("General") }}</h2> <h2 class="mt-5 mb-2">{{ $t("General") }}</h2>
<form class="mb-3" @submit.prevent="saveGeneral"> <form class="mb-3" @submit.prevent="saveGeneral">
<div class="mb-3"> <div class="mb-3">
<label for="timezone" class="form-label">Timezone</label> <label for="timezone" class="form-label">{{ $t("Timezone") }}</label>
<select id="timezone" v-model="$root.userTimezone" class="form-select"> <select id="timezone" v-model="$root.userTimezone" class="form-select">
<option value="auto"> <option value="auto">
Auto: {{ guessTimezone }} {{ $t("Auto") }}: {{ guessTimezone }}
</option> </option>
<option v-for="(timezone, index) in timezoneList" :key="index" :value="timezone.value"> <option v-for="(timezone, index) in timezoneList" :key="index" :value="timezone.value">
{{ timezone.name }} {{ timezone.name }}
@ -67,65 +67,65 @@
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label">Search Engine Visibility</label> <label class="form-label">{{ $t("Search Engine Visibility") }}</label>
<div class="form-check"> <div class="form-check">
<input id="searchEngineIndexYes" v-model="settings.searchEngineIndex" class="form-check-input" type="radio" name="flexRadioDefault" :value="true" required> <input id="searchEngineIndexYes" v-model="settings.searchEngineIndex" class="form-check-input" type="radio" name="flexRadioDefault" :value="true" required>
<label class="form-check-label" for="searchEngineIndexYes"> <label class="form-check-label" for="searchEngineIndexYes">
Allow indexing {{ $t("Allow indexing") }}
</label> </label>
</div> </div>
<div class="form-check"> <div class="form-check">
<input id="searchEngineIndexNo" v-model="settings.searchEngineIndex" class="form-check-input" type="radio" name="flexRadioDefault" :value="false" required> <input id="searchEngineIndexNo" v-model="settings.searchEngineIndex" class="form-check-input" type="radio" name="flexRadioDefault" :value="false" required>
<label class="form-check-label" for="searchEngineIndexNo"> <label class="form-check-label" for="searchEngineIndexNo">
Discourage search engines from indexing site {{ $t("Discourage search engines from indexing site") }}
</label> </label>
</div> </div>
</div> </div>
<div> <div>
<button class="btn btn-primary" type="submit"> <button class="btn btn-primary" type="submit">
Save {{ $t("Save") }}
</button> </button>
</div> </div>
</form> </form>
<template v-if="loaded"> <template v-if="loaded">
<template v-if="! settings.disableAuth"> <template v-if="! settings.disableAuth">
<h2 class="mt-5 mb-2">Change Password</h2> <h2 class="mt-5 mb-2">{{ $t("Change Password") }}</h2>
<form class="mb-3" @submit.prevent="savePassword"> <form class="mb-3" @submit.prevent="savePassword">
<div class="mb-3"> <div class="mb-3">
<label for="current-password" class="form-label">Current Password</label> <label for="current-password" class="form-label">{{ $t("Current Password") }}</label>
<input id="current-password" v-model="password.currentPassword" type="password" class="form-control" required> <input id="current-password" v-model="password.currentPassword" type="password" class="form-control" required>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="new-password" class="form-label">New Password</label> <label for="new-password" class="form-label">{{ $t("New Password") }}</label>
<input id="new-password" v-model="password.newPassword" type="password" class="form-control" required> <input id="new-password" v-model="password.newPassword" type="password" class="form-control" required>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="repeat-new-password" class="form-label">Repeat New Password</label> <label for="repeat-new-password" class="form-label">{{ $t("Repeat New Password") }}</label>
<input id="repeat-new-password" v-model="password.repeatNewPassword" type="password" class="form-control" :class="{ 'is-invalid' : invalidPassword }" required> <input id="repeat-new-password" v-model="password.repeatNewPassword" type="password" class="form-control" :class="{ 'is-invalid' : invalidPassword }" required>
<div class="invalid-feedback"> <div class="invalid-feedback">
The repeat password does not match. {{ $t("passwordNotMatchMsg") }}
</div> </div>
</div> </div>
<div> <div>
<button class="btn btn-primary" type="submit"> <button class="btn btn-primary" type="submit">
Update Password {{ $t("Update Password") }}
</button> </button>
</div> </div>
</form> </form>
</template> </template>
<h2 class="mt-5 mb-2">Advanced</h2> <h2 class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
<div class="mb-3"> <div class="mb-3">
<button v-if="settings.disableAuth" class="btn btn-outline-primary me-1" @click="enableAuth">Enable Auth</button> <button v-if="settings.disableAuth" class="btn btn-outline-primary me-1" @click="enableAuth">{{ $t("Enable Auth") }}</button>
<button v-if="! settings.disableAuth" class="btn btn-primary me-1" @click="confirmDisableAuth">Disable Auth</button> <button v-if="! settings.disableAuth" class="btn btn-primary me-1" @click="confirmDisableAuth">{{ $t("Disable Auth") }}</button>
<button v-if="! settings.disableAuth" class="btn btn-danger me-1" @click="$root.logout">Logout</button> <button v-if="! settings.disableAuth" class="btn btn-danger me-1" @click="$root.logout">{{ $t("Logout") }}</button>
</div> </div>
</template> </template>
</div> </div>
@ -133,23 +133,23 @@
<div class="notification-list col-md-6"> <div class="notification-list col-md-6">
<div v-if="$root.isMobile" class="mt-3" /> <div v-if="$root.isMobile" class="mt-3" />
<h2>Notifications</h2> <h2>{{ $t("Notifications") }}</h2>
<p v-if="$root.notificationList.length === 0"> <p v-if="$root.notificationList.length === 0">
Not available, please setup. {{ $t("Not available, please setup.") }}
</p> </p>
<p v-else> <p v-else>
Please assign a notification to monitor(s) to get it to work. {{ $t("notificationDescription") }}
</p> </p>
<ul class="list-group mb-3" style="border-radius: 1rem;"> <ul class="list-group mb-3" style="border-radius: 1rem;">
<li v-for="(notification, index) in $root.notificationList" :key="index" class="list-group-item"> <li v-for="(notification, index) in $root.notificationList" :key="index" class="list-group-item">
{{ notification.name }}<br> {{ notification.name }}<br>
<a href="#" @click="$refs.notificationDialog.show(notification.id)">Edit</a> <a href="#" @click="$refs.notificationDialog.show(notification.id)">{{ $t("Edit") }}</a>
</li> </li>
</ul> </ul>
<button class="btn btn-primary me-2" type="button" @click="$refs.notificationDialog.show()"> <button class="btn btn-primary me-2" type="button" @click="$refs.notificationDialog.show()">
Setup Notification {{ $t("Setup Notification") }}
</button> </button>
</div> </div>
</div> </div>
@ -157,10 +157,18 @@
<NotificationDialog ref="notificationDialog" /> <NotificationDialog ref="notificationDialog" />
<Confirm ref="confirmDisableAuth" btn-style="btn-danger" yes-text="I understand, please disable" no-text="Leave" @yes="disableAuth"> <Confirm ref="confirmDisableAuth" btn-style="btn-danger" :yes-text="$t('I understand, please disable')" :no-text="$t('Leave')" @yes="disableAuth">
<p>Are you sure want to <strong>disable auth</strong>?</p> <template v-if="$i18n.locale === 'en' ">
<p>It is for <strong>someone who have 3rd-party auth</strong> in front of Uptime Kuma such as Cloudflare Access.</p> <p>Are you sure want to <strong>disable auth</strong>?</p>
<p>Please use it carefully.</p> <p>It is for <strong>someone who have 3rd-party auth</strong> in front of Uptime Kuma such as Cloudflare Access.</p>
<p>Please use it carefully.</p>
</template>
<template v-if="$i18n.locale === 'zh-HK' ">
<p>你是否確認<strong>取消登入認証</strong></p>
<p>這個功能是設計給已有<strong>第三方認証</strong>的用家例如 Cloudflare Access</p>
<p>請小心使用</p>
</template>
</Confirm> </Confirm>
</div> </div>
</transition> </transition>