1
0
mirror of https://github.com/donaldzou/WGDashboard.git synced 2024-11-22 07:10:09 +01:00

Still working on localization

This commit is contained in:
Donald Zou 2024-09-12 15:21:42 +08:00
parent a3a312e3db
commit 02c2221970
7 changed files with 129 additions and 50 deletions

View File

@ -41,6 +41,7 @@ import PeerJobsAllModal from "@/components/configurationComponents/peerJobsAllMo
import PeerJobsLogsModal from "@/components/configurationComponents/peerJobsLogsModal.vue"; import PeerJobsLogsModal from "@/components/configurationComponents/peerJobsLogsModal.vue";
import {ref} from "vue"; import {ref} from "vue";
import PeerShareLinkModal from "@/components/configurationComponents/peerShareLinkModal.vue"; import PeerShareLinkModal from "@/components/configurationComponents/peerShareLinkModal.vue";
import LocaleText from "@/components/text/localeText.vue";
Chart.register( Chart.register(
ArcElement, ArcElement,
@ -71,6 +72,7 @@ Chart.register(
export default { export default {
name: "peerList", name: "peerList",
components: { components: {
LocaleText,
PeerShareLinkModal, PeerShareLinkModal,
PeerJobsLogsModal, PeerJobsLogsModal,
PeerJobsAllModal, PeerJobs, PeerCreate, PeerQRCode, PeerSettings, PeerSearch, Peer, Line, Bar}, PeerJobsAllModal, PeerJobs, PeerCreate, PeerQRCode, PeerSettings, PeerSearch, Peer, Line, Bar},
@ -410,7 +412,9 @@ export default {
<div v-if="!this.loading" class="container-md"> <div v-if="!this.loading" class="container-md">
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div> <div>
<small CLASS="text-muted">CONFIGURATION</small> <small CLASS="text-muted">
<LocaleText t="CONFIGURATION"></LocaleText>
</small>
<div class="d-flex align-items-center gap-3"> <div class="d-flex align-items-center gap-3">
<h1 class="mb-0"><samp>{{this.configurationInfo.Name}}</samp></h1> <h1 class="mb-0"><samp>{{this.configurationInfo.Name}}</samp></h1>
</div> </div>
@ -418,13 +422,15 @@ export default {
<div class="card rounded-3 bg-transparent shadow-sm ms-auto"> <div class="card rounded-3 bg-transparent shadow-sm ms-auto">
<div class="card-body py-2 d-flex align-items-center"> <div class="card-body py-2 d-flex align-items-center">
<div> <div>
<p class="mb-0 text-muted"><small>Status</small></p> <p class="mb-0 text-muted"><small>
<LocaleText t="Status"></LocaleText>
</small></p>
<div class="form-check form-switch ms-auto"> <div class="form-check form-switch ms-auto">
<label class="form-check-label" style="cursor: pointer" :for="'switch' + this.configurationInfo.id"> <label class="form-check-label" style="cursor: pointer" :for="'switch' + this.configurationInfo.id">
{{this.configurationToggling ? 'Turning ':''}} <LocaleText t="On" v-if="this.configurationInfo.Status"></LocaleText>
{{this.configurationInfo.Status ? "On":"Off"}} <LocaleText t="Off" v-else></LocaleText>
<span v-if="this.configurationToggling" <span v-if="this.configurationToggling"
class="spinner-border spinner-border-sm" aria-hidden="true"></span> class="spinner-border spinner-border-sm ms-2" aria-hidden="true"></span>
</label> </label>
<input class="form-check-input" <input class="form-check-input"
style="cursor: pointer" style="cursor: pointer"
@ -444,7 +450,9 @@ export default {
<div class="col-6 col-lg-3"> <div class="col-6 col-lg-3">
<div class="card rounded-3 bg-transparent shadow-sm"> <div class="card rounded-3 bg-transparent shadow-sm">
<div class="card-body py-2"> <div class="card-body py-2">
<p class="mb-0 text-muted"><small>Address</small></p> <p class="mb-0 text-muted"><small>
<LocaleText t="Address"></LocaleText>
</small></p>
{{this.configurationInfo.Address}} {{this.configurationInfo.Address}}
</div> </div>
</div> </div>
@ -452,7 +460,9 @@ export default {
<div class="col-6 col-lg-3"> <div class="col-6 col-lg-3">
<div class="card rounded-3 bg-transparent shadow-sm"> <div class="card rounded-3 bg-transparent shadow-sm">
<div class="card-body py-2"> <div class="card-body py-2">
<p class="mb-0 text-muted"><small>Listen Port</small></p> <p class="mb-0 text-muted"><small>
<LocaleText t="Listen Port"></LocaleText>
</small></p>
{{this.configurationInfo.ListenPort}} {{this.configurationInfo.ListenPort}}
</div> </div>
</div> </div>
@ -460,7 +470,9 @@ export default {
<div style="word-break: break-all" class="col-12 col-lg-6"> <div style="word-break: break-all" class="col-12 col-lg-6">
<div class="card rounded-3 bg-transparent shadow-sm"> <div class="card rounded-3 bg-transparent shadow-sm">
<div class="card-body py-2"> <div class="card-body py-2">
<p class="mb-0 text-muted"><small>Public Key</small></p> <p class="mb-0 text-muted"><small>
<LocaleText t="Public Key"></LocaleText>
</small></p>
<samp>{{this.configurationInfo.PublicKey}}</samp> <samp>{{this.configurationInfo.PublicKey}}</samp>
</div> </div>
</div> </div>
@ -471,7 +483,9 @@ export default {
<div class="card rounded-3 bg-transparent shadow-sm"> <div class="card rounded-3 bg-transparent shadow-sm">
<div class="card-body d-flex"> <div class="card-body d-flex">
<div> <div>
<p class="mb-0 text-muted"><small>Connected Peers</small></p> <p class="mb-0 text-muted"><small>
<LocaleText t="Connected Peers"></LocaleText>
</small></p>
<strong class="h4">{{configurationSummary.connectedPeers}}</strong> <strong class="h4">{{configurationSummary.connectedPeers}}</strong>
</div> </div>
<i class="bi bi-ethernet ms-auto h2 text-muted"></i> <i class="bi bi-ethernet ms-auto h2 text-muted"></i>
@ -482,7 +496,9 @@ export default {
<div class="card rounded-3 bg-transparent shadow-sm"> <div class="card rounded-3 bg-transparent shadow-sm">
<div class="card-body d-flex"> <div class="card-body d-flex">
<div> <div>
<p class="mb-0 text-muted"><small>Total Usage</small></p> <p class="mb-0 text-muted"><small>
<LocaleText t="Total Usage"></LocaleText>
</small></p>
<strong class="h4">{{configurationSummary.totalUsage}} GB</strong> <strong class="h4">{{configurationSummary.totalUsage}} GB</strong>
</div> </div>
<i class="bi bi-arrow-down-up ms-auto h2 text-muted"></i> <i class="bi bi-arrow-down-up ms-auto h2 text-muted"></i>
@ -493,7 +509,9 @@ export default {
<div class="card rounded-3 bg-transparent shadow-sm"> <div class="card rounded-3 bg-transparent shadow-sm">
<div class="card-body d-flex"> <div class="card-body d-flex">
<div> <div>
<p class="mb-0 text-muted"><small>Total Received</small></p> <p class="mb-0 text-muted"><small>
<LocaleText t="Total Received"></LocaleText>
</small></p>
<strong class="h4 text-primary">{{configurationSummary.totalReceive}} GB</strong> <strong class="h4 text-primary">{{configurationSummary.totalReceive}} GB</strong>
</div> </div>
<i class="bi bi-arrow-down ms-auto h2 text-muted"></i> <i class="bi bi-arrow-down ms-auto h2 text-muted"></i>
@ -504,7 +522,9 @@ export default {
<div class="card rounded-3 bg-transparent shadow-sm"> <div class="card rounded-3 bg-transparent shadow-sm">
<div class="card-body d-flex"> <div class="card-body d-flex">
<div> <div>
<p class="mb-0 text-muted"><small>Total Sent</small></p> <p class="mb-0 text-muted"><small>
<LocaleText t="Total Sent"></LocaleText>
</small></p>
<strong class="h4 text-success">{{configurationSummary.totalSent}} GB</strong> <strong class="h4 text-success">{{configurationSummary.totalSent}} GB</strong>
</div> </div>
<i class="bi bi-arrow-up ms-auto h2 text-muted"></i> <i class="bi bi-arrow-up ms-auto h2 text-muted"></i>
@ -516,7 +536,9 @@ export default {
<div class="col-12 col-lg-6"> <div class="col-12 col-lg-6">
<div class="card rounded-3 bg-transparent shadow-sm" style="height: 270px"> <div class="card rounded-3 bg-transparent shadow-sm" style="height: 270px">
<div class="card-header bg-transparent border-0"> <div class="card-header bg-transparent border-0">
<small class="text-muted">Peers Total Data Usage</small></div> <small class="text-muted">
<LocaleText t="Peers Data Usage"></LocaleText>
</small></div>
<div class="card-body pt-1"> <div class="card-body pt-1">
<Bar <Bar
:data="individualDataUsage" :data="individualDataUsage"
@ -527,7 +549,9 @@ export default {
</div> </div>
<div class="col-sm col-lg-3"> <div class="col-sm col-lg-3">
<div class="card rounded-3 bg-transparent shadow-sm" style="height: 270px"> <div class="card rounded-3 bg-transparent shadow-sm" style="height: 270px">
<div class="card-header bg-transparent border-0"><small class="text-muted">Real Time Received Data Usage</small></div> <div class="card-header bg-transparent border-0"><small class="text-muted">
<LocaleText t="Real Time Received Data Usage"></LocaleText>
</small></div>
<div class="card-body pt-1"> <div class="card-body pt-1">
<Line <Line
:options="chartOptions" :options="chartOptions"
@ -539,7 +563,9 @@ export default {
</div> </div>
<div class="col-sm col-lg-3"> <div class="col-sm col-lg-3">
<div class="card rounded-3 bg-transparent shadow-sm" style="height: 270px"> <div class="card rounded-3 bg-transparent shadow-sm" style="height: 270px">
<div class="card-header bg-transparent border-0"><small class="text-muted">Real Time Sent Data Usage</small></div> <div class="card-header bg-transparent border-0"><small class="text-muted">
<LocaleText t="Real Time Sent Data Usage"></LocaleText>
</small></div>
<div class="card-body pt-1"> <div class="card-body pt-1">
<Line <Line
:options="chartOptions" :options="chartOptions"

View File

@ -2,10 +2,13 @@
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js"; import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import {fetchGet, fetchPost} from "@/utilities/fetch.js"; import {fetchGet, fetchPost} from "@/utilities/fetch.js";
import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js"; import {WireguardConfigurationsStore} from "@/stores/WireguardConfigurationsStore.js";
import LocaleText from "@/components/text/localeText.vue";
import {GetLocale} from "@/utilities/locale.js";
export default { export default {
name: "peerSearch", name: "peerSearch",
components: {LocaleText},
setup(){ setup(){
const store = DashboardConfigurationStore(); const store = DashboardConfigurationStore();
const wireguardConfigurationStore = WireguardConfigurationsStore() const wireguardConfigurationStore = WireguardConfigurationsStore()
@ -18,16 +21,16 @@ export default {
data(){ data(){
return { return {
sort: { sort: {
status: "Status", status: GetLocale("Status"),
name: "Name", name: GetLocale("Name"),
allowed_ip: "Allowed IP", allowed_ip: GetLocale("Allowed IP"),
restricted: "Restricted" restricted: GetLocale("Restricted")
}, },
interval: { interval: {
'5000': '5 Seconds', '5000': GetLocale('5 Seconds'),
'10000': '10 Seconds', '10000': GetLocale('10 Seconds'),
'30000': '30 Seconds', '30000': GetLocale('30 Seconds'),
'60000': '1 Minutes' '60000': GetLocale('1 Minutes')
}, },
searchString: "", searchString: "",
searchStringTimeout: undefined, searchStringTimeout: undefined,
@ -77,8 +80,10 @@ export default {
}) })
} }
}, },
mounted() { computed: {
searchBarPlaceholder(){
return GetLocale("Search Peers...")
}
} }
} }
</script> </script>
@ -89,16 +94,18 @@ export default {
<RouterLink <RouterLink
to="create" to="create"
class="text-decoration-none btn text-primary-emphasis bg-primary-subtle rounded-3 border-1 border-primary-subtle shadow-sm"> class="text-decoration-none btn text-primary-emphasis bg-primary-subtle rounded-3 border-1 border-primary-subtle shadow-sm">
<i class="bi bi-plus-lg me-2"></i>Peer <i class="bi bi-plus-lg me-2"></i>
<LocaleText t="Peer"></LocaleText>
</RouterLink> </RouterLink>
<button class="btn text-primary-emphasis bg-primary-subtle rounded-3 border-1 border-primary-subtle shadow-sm" <button class="btn text-primary-emphasis bg-primary-subtle rounded-3 border-1 border-primary-subtle shadow-sm"
@click="this.downloadAllPeer()"> @click="this.downloadAllPeer()">
<i class="bi bi-download me-2"></i> Download All <i class="bi bi-download me-2"></i>
<LocaleText t="Download All"></LocaleText>
</button> </button>
<div class="mt-3 mt-md-0 flex-grow-1"> <div class="mt-3 mt-md-0 flex-grow-1">
<input class="form-control rounded-3 bg-secondary-subtle border-1 border-secondary-subtle shadow-sm w-100" <input class="form-control rounded-3 bg-secondary-subtle border-1 border-secondary-subtle shadow-sm w-100"
placeholder="Search Peers..." :placeholder="searchBarPlaceholder"
id="searchPeers" id="searchPeers"
@keyup="this.debounce()" @keyup="this.debounce()"
v-model="this.searchString"> v-model="this.searchString">
@ -108,7 +115,7 @@ export default {
class="btn text-secondary-emphasis bg-secondary-subtle rounded-3 border-1 border-secondary-subtle shadow-sm" class="btn text-secondary-emphasis bg-secondary-subtle rounded-3 border-1 border-secondary-subtle shadow-sm"
type="button" aria-expanded="false"> type="button" aria-expanded="false">
<i class="bi bi-filter-circle me-2"></i> <i class="bi bi-filter-circle me-2"></i>
Display <LocaleText t="Display"></LocaleText>
</button> </button>
<button class="btn text-secondary-emphasis bg-secondary-subtle rounded-3 border-1 border-secondary-subtle shadow-sm" <button class="btn text-secondary-emphasis bg-secondary-subtle rounded-3 border-1 border-secondary-subtle shadow-sm"
@click="this.showMoreSettings = true" @click="this.showMoreSettings = true"
@ -123,13 +130,15 @@ export default {
<div class="m-auto modal-dialog-centered dashboardModal"> <div class="m-auto modal-dialog-centered dashboardModal">
<div class="card rounded-3 shadow w-100"> <div class="card rounded-3 shadow w-100">
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"> <div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2">
<h4 class="mb-0 fw-normal">Display <h4 class="mb-0 fw-normal"><LocaleText t="Display"></LocaleText>
</h4> </h4>
<button type="button" class="btn-close ms-auto" @click="this.showDisplaySettings = false"></button> <button type="button" class="btn-close ms-auto" @click="this.showDisplaySettings = false"></button>
</div> </div>
<div class="card-body px-4 pb-4 d-flex gap-3 flex-column"> <div class="card-body px-4 pb-4 d-flex gap-3 flex-column">
<div> <div>
<p class="text-muted fw-bold mb-2"><small>Sort by</small></p> <p class="text-muted fw-bold mb-2"><small>
<LocaleText t="Sort by"></LocaleText>
</small></p>
<div class="list-group"> <div class="list-group">
<a v-for="(value, key) in this.sort" class="list-group-item list-group-item-action d-flex" role="button" @click="this.updateSort(key)"> <a v-for="(value, key) in this.sort" class="list-group-item list-group-item-action d-flex" role="button" @click="this.updateSort(key)">
<span class="me-auto">{{value}}</span> <span class="me-auto">{{value}}</span>
@ -139,7 +148,9 @@ export default {
</div> </div>
</div> </div>
<div> <div>
<p class="text-muted fw-bold mb-2"><small>Refresh interval</small></p> <p class="text-muted fw-bold mb-2"><small>
<LocaleText t="Refresh Interval"></LocaleText>
</small></p>
<div class="list-group"> <div class="list-group">
<a v-for="(value, key) in this.interval" <a v-for="(value, key) in this.interval"
class="list-group-item list-group-item-action d-flex" role="button" class="list-group-item list-group-item-action d-flex" role="button"
@ -164,21 +175,24 @@ export default {
<div class="m-auto modal-dialog-centered dashboardModal"> <div class="m-auto modal-dialog-centered dashboardModal">
<div class="card rounded-3 shadow w-100"> <div class="card rounded-3 shadow w-100">
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2"> <div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-2">
<h4 class="mb-0 fw-normal">Configuration Settings <h4 class="mb-0 fw-normal">
<LocaleText t="Configuration Settings"></LocaleText>
</h4> </h4>
<button type="button" class="btn-close ms-auto" @click="this.showMoreSettings = false"></button> <button type="button" class="btn-close ms-auto" @click="this.showMoreSettings = false"></button>
</div> </div>
<div class="card-body px-4 pb-4 d-flex gap-3 flex-column"> <div class="card-body px-4 pb-4 d-flex gap-3 flex-column">
<div> <div>
<p class="text-muted fw-bold mb-2"><small>Peer Jobs</small></p> <p class="text-muted fw-bold mb-2"><small>
<LocaleText t="Peer Jobs"></LocaleText>
</small></p>
<div class="list-group"> <div class="list-group">
<a class="list-group-item list-group-item-action d-flex" role="button" <a class="list-group-item list-group-item-action d-flex" role="button"
@click="this.$emit('jobsAll')"> @click="this.$emit('jobsAll')">
Active Jobs <LocaleText t="Active Jobs"></LocaleText>
</a> </a>
<a class="list-group-item list-group-item-action d-flex" role="button" <a class="list-group-item list-group-item-action d-flex" role="button"
@click="this.$emit('jobLogs')"> @click="this.$emit('jobLogs')">
Logs <LocaleText t="Logs"></LocaleText>
</a> </a>
</div> </div>
</div> </div>

View File

@ -48,7 +48,9 @@ export default {
<small class="text-muted"> <small class="text-muted">
<LocaleText t="Expire At"></LocaleText> <LocaleText t="Expire At"></LocaleText>
</small> </small>
{{this.apiKey.ExpiredAt ? this.apiKey.ExpiredAt : 'Never'}}
<LocaleText t="Never Expire" v-if="!this.apiKey.ExpiredAt"></LocaleText>
<span>{{ this.apiKey.ExpiredAt }}</span>
</div> </div>
<a role="button" class="btn btn-sm bg-danger-subtle text-danger-emphasis rounded-3" <a role="button" class="btn btn-sm bg-danger-subtle text-danger-emphasis rounded-3"
v-if="!this.store.getActiveCrossServer()" v-if="!this.store.getActiveCrossServer()"

View File

@ -3,10 +3,11 @@ import dayjs from "dayjs";
import {fetchPost} from "@/utilities/fetch.js"; import {fetchPost} from "@/utilities/fetch.js";
import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js"; import {DashboardConfigurationStore} from "@/stores/DashboardConfigurationStore.js";
import VueDatePicker from "@vuepic/vue-datepicker"; import VueDatePicker from "@vuepic/vue-datepicker";
import LocaleText from "@/components/text/localeText.vue";
export default { export default {
name: "newDashboardAPIKey", name: "newDashboardAPIKey",
components: {VueDatePicker}, components: {LocaleText, VueDatePicker},
data(){ data(){
return{ return{
newKeyData:{ newKeyData:{
@ -58,11 +59,15 @@ export default {
style="background-color: #00000060; backdrop-filter: blur(3px)"> style="background-color: #00000060; backdrop-filter: blur(3px)">
<div class="card m-auto rounded-3 mt-5"> <div class="card m-auto rounded-3 mt-5">
<div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0"> <div class="card-header bg-transparent d-flex align-items-center gap-2 border-0 p-4 pb-0">
<h6 class="mb-0">Create API Key</h6> <h6 class="mb-0">
<LocaleText t="Create API Key"></LocaleText>
</h6>
<button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button> <button type="button" class="btn-close ms-auto" @click="this.$emit('close')"></button>
</div> </div>
<div class="card-body d-flex gap-2 p-4 flex-column"> <div class="card-body d-flex gap-2 p-4 flex-column">
<small class="text-muted">When should this API Key expire?</small> <small class="text-muted">
<LocaleText t="When should this API Key expire?"></LocaleText>
</small>
<div class="d-flex align-items-center gap-2"> <div class="d-flex align-items-center gap-2">
<VueDatePicker <VueDatePicker
:is24="true" :is24="true"
@ -80,7 +85,8 @@ export default {
<input class="form-check-input" type="checkbox" <input class="form-check-input" type="checkbox"
v-model="this.newKeyData.neverExpire" id="neverExpire" :disabled="this.submitting"> v-model="this.newKeyData.neverExpire" id="neverExpire" :disabled="this.submitting">
<label class="form-check-label" for="neverExpire"> <label class="form-check-label" for="neverExpire">
Never Expire (<i class="bi bi-emoji-grimace-fill"></i> Don't think that's a good idea) <LocaleText t="Never Expire"></LocaleText> (<i class="bi bi-emoji-grimace-fill me-2"></i>
<LocaleText t="Don't think that's a good idea"></LocaleText>)
</label> </label>
</div> </div>
<button class="ms-auto btn bg-success-subtle text-success-emphasis border-1 border-success-subtle rounded-3 shadow-sm" <button class="ms-auto btn bg-success-subtle text-success-emphasis border-1 border-success-subtle rounded-3 shadow-sm"
@ -88,7 +94,8 @@ export default {
@click="this.submitNewAPIKey()" @click="this.submitNewAPIKey()"
> >
<i class="bi bi-check-lg me-2" v-if="!this.submitting"></i> <i class="bi bi-check-lg me-2" v-if="!this.submitting"></i>
{{this.submitting ? 'Creating...':'Done'}} <LocaleText t="Creating..." v-if="this.submitting"></LocaleText>
<LocaleText t="Create" v-else></LocaleText>
</button> </button>
</div> </div>
</div> </div>

View File

@ -72,7 +72,7 @@ export default {
<LocaleText :t="this.title"></LocaleText> <LocaleText :t="this.title"></LocaleText>
</small></strong> </small></strong>
</label> </label>
<div class="d-flex gap-2 align-items-start mb-2"> <div class="d-flex gap-2 align-items-start">
<div class="flex-grow-1"> <div class="flex-grow-1">
<input type="text" class="form-control rounded-3" <input type="text" class="form-control rounded-3"
:class="{'is-invalid': this.showInvalidFeedback, 'is-valid': this.isValid}" :class="{'is-invalid': this.showInvalidFeedback, 'is-valid': this.isValid}"

View File

@ -1,16 +1,12 @@
export const GetLocale = (key) => { export const GetLocale = (key) => {
console.log(key)
if (window.Locale === null) if (window.Locale === null)
return key return key
const reg = Object.keys(window.Locale) const reg = Object.keys(window.Locale)
const match = reg.filter(x => { const match = reg.filter(x => {
return key.match(new RegExp('^' + x + '$', 'g')) !== null return key.match(new RegExp('^' + x + '$', 'gi')) !== null
}) })
console.log(match)
if (match.length === 0 || match.length > 1){ if (match.length === 0 || match.length > 1){
return key return key
} }
return window.Locale[match[0]] return key.replace(new RegExp(match[0], 'gi'), window.Locale[match[0]])
} }

View File

@ -45,5 +45,39 @@
"Disabled": "已停用", "Disabled": "已停用",
"No WGDashboard API Key": "没有 WGDashboard API 秘钥", "No WGDashboard API Key": "没有 WGDashboard API 秘钥",
"Expire At": "过期于", "Expire At": "过期于",
"Are you sure to delete this API key\\?": "确定删除此 API 秘钥?" "Are you sure to delete this API key\\?": "确定删除此 API 秘钥?",
"Create API Key": "创建 API 秘钥",
"When should this API Key expire\\?": "这个 API 秘钥什么时候过期呢?",
"Never Expire": "从不过期",
"Don't think that's a good idea": "我不觉得这是一个好主意",
"Creating\\.\\.\\.": "创建中...",
"Create": "创建",
"Status": "状态",
"On": "已启用",
"Off": "已停用",
"Address": "网络地址",
"Listen Port": "监听端口",
"Public Key": "公钥",
"Connected Peers": "已连接端点",
"Total Usage": "总数据用量",
"Total Received": "总接收数据用量",
"Total Sent": "总发送数据用量",
"Peers Data Usage": "端点的数据用量",
"Real Time Received Data Usage": "实时接收数据量",
"Real Time Sent Data Usage": "实时发送数据量",
"Peer": "端点",
"Download All": "全部下载",
"Search Peers\\.\\.\\.": "搜索端点...",
"Display": "显示设置",
"Sort By": "排列方式",
"Refresh Interval": "刷新间隔",
"Name": "名字",
"Allowed IP": "允许 IP 地址",
"Restricted": "已限制端点",
"(.*) Seconds": "$1 秒",
"(.*) Minutes": "$1 分钟",
"Configuration Settings": "配置设定",
"Peer Jobs": "端点任务",
"Active Jobs": "未运行任务",
"Logs": "日志"
} }