Added internationalize, and fixed some small bugs.

This commit is contained in:
Hintay 2022-02-20 18:56:27 +08:00
parent 22da4ba879
commit 64f7de47dc
No known key found for this signature in database
GPG key ID: 120FC7FF121F2F2D
32 changed files with 1181 additions and 553 deletions

View file

@ -6,7 +6,11 @@ LOGNAME ?= $(shell logname)
# adding the name of the user's login name to the template file, so that # adding the name of the user's login name to the template file, so that
# on a multi-user system several users can run this without interference # on a multi-user system several users can run this without interference
ifeq ($(OS),Windows_NT)
TEMPLATE_POT ?= ./template-$(LOGNAME).pot
else
TEMPLATE_POT ?= /tmp/template-$(LOGNAME).pot TEMPLATE_POT ?= /tmp/template-$(LOGNAME).pot
endif
# Where to find input files (it can be multiple paths). # Where to find input files (it can be multiple paths).
INPUT_FILES = ./src INPUT_FILES = ./src

View file

@ -2,7 +2,7 @@
<a-breadcrumb class="breadcrumb"> <a-breadcrumb class="breadcrumb">
<a-breadcrumb-item v-for="(item, index) in breadList" :key="item.name"> <a-breadcrumb-item v-for="(item, index) in breadList" :key="item.name">
<router-link <router-link
v-if="item.name != name && index != 1" v-if="item.name !== name && index !== 1"
:to="{ path: item.path === '' ? '/' : item.path }" :to="{ path: item.path === '' ? '/' : item.path }"
>{{ item.name }} >{{ item.name }}
</router-link> </router-link>

View file

@ -50,6 +50,7 @@ import FooterLayout from './FooterLayout'
import PageHeader from '@/components/PageHeader/PageHeader' import PageHeader from '@/components/PageHeader/PageHeader'
import zh_CN from 'ant-design-vue/es/locale/zh_CN' import zh_CN from 'ant-design-vue/es/locale/zh_CN'
// TODO Change language for base layout.
export default { export default {
name: 'BaseLayout', name: 'BaseLayout',
data() { data() {

View file

@ -19,13 +19,14 @@
<script> <script>
import SetLanguage from '@/components/SetLanguage/SetLanguage' import SetLanguage from '@/components/SetLanguage/SetLanguage'
import $gettext from "@/lib/translate/gettext";
export default { export default {
name: 'HeaderComponent', name: 'HeaderComponent',
components: {SetLanguage}, components: {SetLanguage},
methods: { methods: {
logout() { logout() {
this.$api.auth.logout().then(() => { this.$api.auth.logout().then(() => {
this.$message.success('注销成功') this.$message.success($gettext('Logout successful'))
this.$router.push('/login') this.$router.push('/login')
}) })
} }

View file

@ -8,7 +8,7 @@
v-model="selectedKey" v-model="selectedKey"
> >
<template v-for="sidebar in visible(sidebars)"> <template v-for="sidebar in visible(sidebars)">
<a-menu-item v-if="!sidebar.children" :key="sidebar.name" <a-menu-item v-if="!sidebar.children || sidebar.meta.hideChildren === true" :key="sidebar.name"
@click="$router.push('/'+sidebar.path).catch(() => {})"> @click="$router.push('/'+sidebar.path).catch(() => {})">
<a-icon :type="sidebar.meta.icon"/> <a-icon :type="sidebar.meta.icon"/>
<span>{{ sidebar.name }}</span> <span>{{ sidebar.name }}</span>

View file

@ -2,14 +2,14 @@ import {translate} from 'vue-gettext'
import store from '@/lib/store' import store from '@/lib/store'
import {availableLanguages} from '@/lib/translate/index' import {availableLanguages} from '@/lib/translate/index'
let lang = window.navigator.language let lang = window.navigator.language.replace('-', '_')
if (!lang.includes('zh')) { if(availableLanguages[lang] === undefined) {
lang = lang.split('-')[0] lang = lang.split('_')[0]
} else { if(availableLanguages[lang] === undefined)
lang = lang.replace('-', '_') lang = 'en'
} }
store.getters.current_language || store.getters.current_language ||
store.commit('set_language', availableLanguages[lang] ? lang : 'en') store.commit('set_language', lang)
const config = { const config = {
language: store.getters.current_language, language: store.getters.current_language,
@ -19,8 +19,8 @@ const config = {
} }
// easygettext aliases // easygettext aliases
const { export const {
gettext: $gettext, gettext: $gettext, gettextInterpolate: $interpolate
} = translate } = translate
translate.initTranslations(store.state.settings.translations, config) translate.initTranslations(store.state.settings.translations, config)

View file

@ -10,110 +10,401 @@ msgstr ""
"Generated-By: easygettext\n" "Generated-By: easygettext\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/router/index.js:98 #: src/router/index.js:100
msgid "404 Not Found" msgid "404 Not Found"
msgstr "" msgstr ""
#: src/router/index.js:76 #: src/router/index.js:78
msgid "About" msgid "About"
msgstr "" msgstr ""
#: src/router/index.js:47 #: src/views/config/Config.vue:18 src/views/domain/DomainList.vue:29
msgid "Add Sites" #: src/views/user/User.vue:35
msgid "Action"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:94 #: src/router/index.js:47 src/views/domain/DomainAdd.vue:18
msgid "Cached:" #: src/views/domain/DomainEdit.vue:45
msgid "Add Site"
msgstr "" msgstr ""
#: src/router/index.js:60 #: src/views/domain/DomainAdd.vue:2
msgid "Config" msgid ""
"Add site here first, then you can configure TLS on the domain edit page."
msgstr ""
#: src/views/domain/DomainEdit.vue:194
msgid "Auto-renewal disabled for %{name}"
msgstr ""
#: src/views/domain/DomainEdit.vue:188
msgid "Auto-renewal enabled for %{name}"
msgstr ""
#: src/views/other/About.vue:11
msgid "Build with"
msgstr ""
#: src/views/config/ConfigEdit.vue:5 src/views/domain/DomainEdit.vue:23
msgid "Cancel"
msgstr ""
#: src/views/domain/columns.js:44
msgid "Certificate Auto-renewal"
msgstr ""
#: src/views/domain/CertInfo.vue:11 src/views/domain/CertInfo.vue:2
msgid "Certificate has expired"
msgstr ""
#: src/views/domain/CertInfo.vue:15 src/views/domain/CertInfo.vue:2
msgid "Certificate is valid"
msgstr ""
#: src/views/domain/columns.js:61
msgid "Certificate Path (ssl_certificate)"
msgstr ""
#: src/views/domain/CertInfo.vue:2
msgid "Certificate Status"
msgstr ""
#: src/views/domain/columns.js:4
msgid "Configuration Name"
msgstr ""
#: src/views/config/Config.vue:8
msgid "Configurations"
msgstr ""
#: src/views/dashboard/DashBoard.vue:52
msgid "CPU"
msgstr ""
#: src/views/user/User.vue:23
msgid "Created at"
msgstr "" msgstr ""
#: src/router/index.js:19 #: src/router/index.js:19
msgid "Dashboard" msgid "Dashboard"
msgstr "" msgstr ""
#: src/router/index.js:124 #: src/views/other/Install.vue:104
msgid "Detected version update, this page will automatically refresh." msgid "Database (Optional, default: database)"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:95 #: src/router/index.js:126
msgid "Free:" msgid "Detected version update, this page will refresh."
msgstr ""
#: src/views/other/About.vue:11
msgid "Development Mode"
msgstr ""
#: src/views/domain/DomainEdit.vue:196
msgid "Disable auto-renewal failed for %{name}"
msgstr ""
#: src/views/domain/DomainList.vue:7 src/views/domain/DomainList.vue:2
#: src/views/domain/DomainList.vue:17
msgid "Disabled"
msgstr ""
#: src/views/domain/DomainList.vue:55
msgid "Disabled successfully"
msgstr ""
#: src/views/domain/DomainEdit.vue:133
msgid "Do you want to change the template to support the TLS?"
msgstr ""
#: src/views/domain/DomainEdit.vue:45
msgid "Edit %{n}"
msgstr ""
#: src/router/index.js:68 src/views/config/ConfigEdit.vue:15
msgid "Edit Configuration"
msgstr ""
#: src/views/domain/DomainEdit.vue:91
msgid "Edit Configuration File"
msgstr ""
#: src/router/index.js:51
msgid "Edit Site"
msgstr ""
#: src/views/other/Install.vue:30
msgid "Email (*)"
msgstr ""
#: src/views/domain/DomainEdit.vue:190
msgid "Enable auto-renewal failed for %{name}"
msgstr ""
#: src/views/domain/DomainAdd.vue:33
msgid "Enable failed"
msgstr ""
#: src/views/domain/columns.js:35
msgid "Enable TLS"
msgstr ""
#: src/views/domain/DomainList.vue:8 src/views/domain/DomainList.vue:3
#: src/views/domain/DomainList.vue:16
msgid "Enabled"
msgstr ""
#: src/views/domain/DomainAdd.vue:27 src/views/domain/DomainList.vue:46
msgid "Enabled successfully"
msgstr ""
#: src/views/domain/CertInfo.vue:5
msgid "Expiration Date: %{date}"
msgstr ""
#: src/views/domain/DomainList.vue:59
msgid "Failed to disable %{msg}"
msgstr ""
#: src/views/domain/DomainList.vue:50
msgid "Failed to enable %{msg}"
msgstr ""
#: src/views/other/Error.vue:9
msgid "File Not Found"
msgstr ""
#: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainEdit.vue:3
msgid "Getting Certificate from Let's Encrypt"
msgstr ""
#: src/views/domain/DomainEdit.vue:156
msgid "Getting the certificate, please wait..."
msgstr "" msgstr ""
#: src/router/index.js:12 #: src/router/index.js:12
msgid "Home" msgid "Home"
msgstr "" msgstr ""
#: src/router/index.js:86 #: src/views/domain/columns.js:28
msgid "HTTP Listen Port"
msgstr ""
#: src/views/domain/columns.js:54
msgid "HTTPS Listen Port"
msgstr ""
#: src/views/domain/columns.js:22
msgid "Index (index)"
msgstr ""
#: src/router/index.js:88 src/views/other/Install.vue:50
msgid "Install" msgid "Install"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:13 #: src/views/domain/CertInfo.vue:3
msgid "Load averages" msgid "Intermediate Certification Authorities: %{issuer}"
msgstr "" msgstr ""
#: src/router/index.js:92 #: src/views/other/Install.vue:45
msgid "Invalid E-mail!"
msgstr ""
#: src/views/user/User.vue:19
msgid "Leave blank for no change"
msgstr ""
#: src/views/other/About.vue:16
msgctxt "Project"
msgid "License"
msgstr ""
#: src/views/dashboard/DashBoard.vue:13
msgid "Load Averages:"
msgstr ""
#: src/router/index.js:94 src/views/other/Login.vue:24
msgid "Login" msgid "Login"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:23 #: src/views/other/Login.vue:28
msgid "Login successful"
msgstr ""
#: src/layouts/HeaderLayout.vue:9
msgid "Logout successful"
msgstr ""
#: src/views/domain/DomainEdit.vue:12 src/views/domain/DomainEdit.vue:6
msgid ""
"Make sure you have configured a reverse proxy for <code>.well-known</code> "
"directory to <code>HTTPChallengePort</code> (default: 9180) before getting "
"the certificate."
msgstr ""
#: src/router/index.js:60
msgid "Manage Configs"
msgstr ""
#: src/router/index.js:35 src/views/domain/DomainList.vue:21
msgid "Manage Sites"
msgstr ""
#: src/router/index.js:27
msgid "Manage Users"
msgstr ""
#: src/views/dashboard/DashBoard.vue:24
msgid "Memory" msgid "Memory"
msgstr "" msgstr ""
#: src/router/index.js:68 #: src/views/config/Config.vue:5 src/views/domain/DomainList.vue:5
msgid "Modify Config" msgid "Name"
msgstr "" msgstr ""
#: src/router/index.js:51 #: src/router/index.js:106
msgid "Modify Sites"
msgstr ""
#: src/router/index.js:104
msgid "Not Found" msgid "Not Found"
msgstr "" msgstr ""
#: src/router/index.js:128 #: src/views/domain/CertInfo.vue:7
msgid "Not Valid Before: %{date}"
msgstr ""
#: src/views/domain/DomainEdit.vue:155
msgid ""
"Note: The server_name in the current configuration must be the domain name "
"you need to get the certificate."
msgstr ""
#: src/router/index.js:130
msgid "OK" msgid "OK"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:96 #: src/views/other/Login.vue:55 src/views/user/User.vue:13
msgid "Physical memory:" msgid "Password"
msgstr ""
#: src/views/other/Install.vue:82
msgid "Password (*)"
msgstr ""
#: src/views/other/Install.vue:49
msgid "Please input your E-mail!"
msgstr ""
#: src/views/other/Install.vue:95 src/views/other/Login.vue:68
msgid "Please input your password!"
msgstr ""
#: src/views/other/Install.vue:72 src/views/other/Login.vue:45
msgid "Please input your username!"
msgstr ""
#: src/views/domain/columns.js:67
msgid "Private Key Path (ssl_certificate_key)"
msgstr ""
#: src/views/other/About.vue:8
msgid "Project Team"
msgstr ""
#: src/views/domain/columns.js:16
msgid "Root Directory (root)"
msgstr ""
#: src/views/config/ConfigEdit.vue:6 src/views/domain/DomainAdd.vue:6
#: src/views/domain/DomainEdit.vue:24
msgid "Save"
msgstr ""
#: src/views/config/ConfigEdit.vue:47 src/views/domain/DomainAdd.vue:38
#: src/views/domain/DomainEdit.vue:151
msgid "Save error %{msg}"
msgstr ""
#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:24
#: src/views/domain/DomainEdit.vue:145
msgid "Saved successfully"
msgstr ""
#: src/views/config/ConfigEdit.vue:35 src/views/domain/DomainEdit.vue:71
#: src/views/other/Login.vue:33
msgid "Server error"
msgstr ""
#: src/views/domain/columns.js:10
msgid "Server Names (server_name)"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:38 #: src/views/dashboard/DashBoard.vue:38
msgid "Server status" msgid "Server Status"
msgstr ""
#: src/router/index.js:35
msgid "Sites"
msgstr "" msgstr ""
#: src/router/index.js:43 #: src/router/index.js:43
msgid "Sites List" msgid "Sites List"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:32 #: src/views/domain/DomainList.vue:11
msgid "Status"
msgstr ""
#: src/views/dashboard/DashBoard.vue:33
msgid "Storage" msgid "Storage"
msgstr "" msgstr ""
#: src/router/index.js:123 #: src/views/domain/CertInfo.vue:4
msgid "Subject Name: %{name}"
msgstr ""
#: src/router/index.js:125
msgid "System message" msgid "System message"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:124 #: src/views/domain/columns.js:50
msgid "Total:" msgid ""
"The certificate for the domain will be checked every hour, and will be "
"renewed if it has been more than 1 month since it was last issued.<br/>If "
"you do not have a certificate before, please click \"Getting Certificate "
"from Let's Encrypt\" first."
msgstr ""
#: src/views/other/Install.vue:119
msgid "The filename cannot contain the following characters: %{c}"
msgstr ""
#: src/views/domain/DomainEdit.vue:4
msgid ""
"The following values will only take effect if you have the corresponding "
"fields in your configuration file. The configuration filename cannot be "
"changed after it has been created."
msgstr ""
#: src/views/domain/DomainEdit.vue:134
msgid "This operation will lose the custom configuration."
msgstr ""
#: src/views/config/Config.vue:11 src/views/domain/DomainList.vue:22
#: src/views/user/User.vue:29
msgid "Updated at"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:12 #: src/views/dashboard/DashBoard.vue:12
msgid "Uptime" msgid "Uptime"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:94 src/views/dashboard/DashBoard.vue:123 #: src/views/dashboard/DashBoard.vue:95
msgid "Used:" msgid "Used: %{u}, Cached: %{c}, Free: %{f}, Physical Memory: %{p}"
msgstr "" msgstr ""
#: src/router/index.js:27 #: src/views/dashboard/DashBoard.vue:123
msgid "Users" msgid "Used: %{used} / Total: %{total}"
msgstr ""
#: src/views/other/Login.vue:32 src/views/user/User.vue:5
msgid "Username"
msgstr ""
#: src/views/other/Install.vue:59
msgid "Username (*)"
msgstr "" msgstr ""

View file

@ -1,123 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: easygettext\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: src/router/index.js:98
msgid "404 Not Found"
msgstr ""
#: src/router/index.js:76
msgid "About"
msgstr ""
#: src/router/index.js:47
msgid "Add Sites"
msgstr ""
#: src/views/dashboard/DashBoard.vue:94
msgid "Cached:"
msgstr ""
#: src/router/index.js:60
msgid "Config"
msgstr ""
#: src/router/index.js:19
msgid "Dashboard"
msgstr ""
#: src/router/index.js:124
msgid "Detected version update, this page will automatically refresh."
msgstr ""
#: src/views/dashboard/DashBoard.vue:95
msgid "Free:"
msgstr ""
#: src/router/index.js:12
msgid "Home"
msgstr ""
#: src/router/index.js:86
msgid "Install"
msgstr ""
#: src/views/dashboard/DashBoard.vue:13
msgid "Load averages"
msgstr ""
#: src/router/index.js:92
msgid "Login"
msgstr ""
#: src/views/dashboard/DashBoard.vue:23
msgid "Memory"
msgstr ""
#: src/router/index.js:68
msgid "Modify Config"
msgstr ""
#: src/router/index.js:51
msgid "Modify Sites"
msgstr ""
#: src/router/index.js:104
msgid "Not Found"
msgstr ""
#: src/router/index.js:128
msgid "OK"
msgstr ""
#: src/views/dashboard/DashBoard.vue:96
msgid "Physical memory:"
msgstr ""
#: src/views/dashboard/DashBoard.vue:38
msgid "Server status"
msgstr ""
#: src/router/index.js:35
msgid "Sites"
msgstr ""
#: src/router/index.js:43
msgid "Sites List"
msgstr ""
#: src/views/dashboard/DashBoard.vue:32
msgid "Storage"
msgstr ""
#: src/router/index.js:123
msgid "System message"
msgstr ""
#: src/views/dashboard/DashBoard.vue:124
msgid "Total: "
msgstr ""
#: src/views/dashboard/DashBoard.vue:12
msgid "Uptime"
msgstr ""
#: src/views/dashboard/DashBoard.vue:94
msgid "Used:"
msgstr ""
#: src/views/dashboard/DashBoard.vue:123
msgid "Used: "
msgstr ""
#: src/router/index.js:27
msgid "Users"
msgstr ""

View file

@ -10,112 +10,409 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: easygettext\n" "Generated-By: easygettext\n"
"X-Generator: Poedit 3.0.1\n" "X-Generator: Poedit 2.2\n"
#: src/router/index.js:98 #: src/router/index.js:100
msgid "404 Not Found" msgid "404 Not Found"
msgstr "404 找到页面" msgstr "404 找到页面"
#: src/router/index.js:76 #: src/router/index.js:78
msgid "About" msgid "About"
msgstr "关于" msgstr "关于"
#: src/router/index.js:47 #: src/views/config/Config.vue:18 src/views/domain/DomainList.vue:29
msgid "Add Sites" #: src/views/user/User.vue:35
msgid "Action"
msgstr "操作"
#: src/router/index.js:47 src/views/domain/DomainAdd.vue:18
#: src/views/domain/DomainEdit.vue:45
msgid "Add Site"
msgstr "添加站点" msgstr "添加站点"
#: src/views/dashboard/DashBoard.vue:94 #: src/views/domain/DomainAdd.vue:2
msgid "Cached:" msgid ""
msgstr "缓存:" "Add site here first, then you can configure TLS on the domain edit page."
msgstr "在这里添加站点,完成后可进入编辑页面配置 TLS。"
#: src/router/index.js:60 #: src/views/domain/DomainEdit.vue:194
msgid "Config" msgid "Auto-renewal disabled for %{name}"
msgstr "成功关闭 %{name} 自动续签"
#: src/views/domain/DomainEdit.vue:188
msgid "Auto-renewal enabled for %{name}"
msgstr "成功启用 %{name} 自动续签"
#: src/views/other/About.vue:11
msgid "Build with"
msgstr "构建基于"
#: src/views/config/ConfigEdit.vue:5 src/views/domain/DomainEdit.vue:23
msgid "Cancel"
msgstr "取消"
#: src/views/domain/columns.js:44
msgid "Certificate Auto-renewal"
msgstr "证书自动续签"
#: src/views/domain/CertInfo.vue:11 src/views/domain/CertInfo.vue:2
msgid "Certificate has expired"
msgstr "此证书已过期"
#: src/views/domain/CertInfo.vue:15 src/views/domain/CertInfo.vue:2
msgid "Certificate is valid"
msgstr "此证书有效"
#: src/views/domain/columns.js:61
msgid "Certificate Path (ssl_certificate)"
msgstr "TLS 证书路径 (ssl_certificate)"
#: src/views/domain/CertInfo.vue:2
msgid "Certificate Status"
msgstr "证书状态"
#: src/views/domain/columns.js:4
msgid "Configuration Name"
msgstr "配置名称"
#: src/views/config/Config.vue:8
msgid "Configurations"
msgstr "配置" msgstr "配置"
#: src/views/dashboard/DashBoard.vue:52
msgid "CPU"
msgstr "CPU"
#: src/views/user/User.vue:23
msgid "Created at"
msgstr "创建时间"
#: src/router/index.js:19 #: src/router/index.js:19
msgid "Dashboard" msgid "Dashboard"
msgstr "仪表盘" msgstr "仪表盘"
#: src/router/index.js:124 #: src/views/other/Install.vue:104
msgid "Detected version update, this page will automatically refresh." msgid "Database (Optional, default: database)"
msgstr "检测到版本更新,页面将会自动刷新。" msgstr "数据库 (可选,默认: database)"
#: src/views/dashboard/DashBoard.vue:95 #: src/router/index.js:126
msgid "Free:" msgid "Detected version update, this page will refresh."
msgstr "空闲:" msgstr "检测到版本更新,页面将会刷新。"
#: src/views/other/About.vue:11
msgid "Development Mode"
msgstr "开发模式"
#: src/views/domain/DomainEdit.vue:196
msgid "Disable auto-renewal failed for %{name}"
msgstr "关闭 %{name} 自动续签失败"
#: src/views/domain/DomainList.vue:7 src/views/domain/DomainList.vue:2
#: src/views/domain/DomainList.vue:17
msgid "Disabled"
msgstr "禁用"
#: src/views/domain/DomainList.vue:55
msgid "Disabled successfully"
msgstr "禁用成功"
#: src/views/domain/DomainEdit.vue:133
msgid "Do you want to change the template to support the TLS?"
msgstr "你想要改变模板以支持 TLS 吗?"
#: src/views/domain/DomainEdit.vue:45
msgid "Edit %{n}"
msgstr "编辑 %{n}"
#: src/router/index.js:68 src/views/config/ConfigEdit.vue:15
msgid "Edit Configuration"
msgstr "编辑配置"
#: src/views/domain/DomainEdit.vue:91
msgid "Edit Configuration File"
msgstr "编辑配置文件"
#: src/router/index.js:51
msgid "Edit Site"
msgstr "编辑站点"
#: src/views/other/Install.vue:30
msgid "Email (*)"
msgstr "邮箱 (*)"
#: src/views/domain/DomainEdit.vue:190
msgid "Enable auto-renewal failed for %{name}"
msgstr "启用 %{name} 自动续签失败"
#: src/views/domain/DomainAdd.vue:33
msgid "Enable failed"
msgstr "启用失败"
#: src/views/domain/columns.js:35
msgid "Enable TLS"
msgstr "启用 TLS"
#: src/views/domain/DomainList.vue:8 src/views/domain/DomainList.vue:3
#: src/views/domain/DomainList.vue:16
msgid "Enabled"
msgstr "启用"
#: src/views/domain/DomainAdd.vue:27 src/views/domain/DomainList.vue:46
msgid "Enabled successfully"
msgstr "启用成功"
#: src/views/domain/CertInfo.vue:5
msgid "Expiration Date: %{date}"
msgstr "过期时间: %{date}"
#: src/views/domain/DomainList.vue:59
msgid "Failed to disable %{msg}"
msgstr "禁用失败 %{msg}"
#: src/views/domain/DomainList.vue:50
msgid "Failed to enable %{msg}"
msgstr "启用失败 %{msg}"
#: src/views/other/Error.vue:9
msgid "File Not Found"
msgstr "未找到文件"
#: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainEdit.vue:3
msgid "Getting Certificate from Let's Encrypt"
msgstr "从 Let's Encrypt 获取证书"
#: src/views/domain/DomainEdit.vue:156
msgid "Getting the certificate, please wait..."
msgstr "正在获取证书,请稍等..."
#: src/router/index.js:12 #: src/router/index.js:12
msgid "Home" msgid "Home"
msgstr "首页" msgstr "首页"
#: src/router/index.js:86 #: src/views/domain/columns.js:28
msgid "HTTP Listen Port"
msgstr "HTTP 监听端口"
#: src/views/domain/columns.js:54
msgid "HTTPS Listen Port"
msgstr "HTTPS 监听端口"
#: src/views/domain/columns.js:22
msgid "Index (index)"
msgstr "网站首页 (index)"
#: src/router/index.js:88 src/views/other/Install.vue:50
msgid "Install" msgid "Install"
msgstr "安装" msgstr "安装"
#: src/views/dashboard/DashBoard.vue:13 #: src/views/domain/CertInfo.vue:3
msgid "Load averages" msgid "Intermediate Certification Authorities: %{issuer}"
msgstr "系统负载" msgstr "中级证书颁发机构: %{issuer}"
#: src/router/index.js:92 #: src/views/other/Install.vue:45
msgid "Invalid E-mail!"
msgstr "无效的邮箱!"
#: src/views/user/User.vue:19
msgid "Leave blank for no change"
msgstr "留空表示不修改"
#: src/views/other/About.vue:16
msgctxt "Project"
msgid "License"
msgstr "开源许可"
#: src/views/dashboard/DashBoard.vue:13
msgid "Load Averages:"
msgstr "系统负载:"
#: src/router/index.js:94 src/views/other/Login.vue:24
msgid "Login" msgid "Login"
msgstr "登录" msgstr "登录"
#: src/views/dashboard/DashBoard.vue:23 #: src/views/other/Login.vue:28
msgid "Login successful"
msgstr "登录成功"
#: src/layouts/HeaderLayout.vue:9
msgid "Logout successful"
msgstr "登出成功"
#: src/views/domain/DomainEdit.vue:12 src/views/domain/DomainEdit.vue:6
msgid ""
"Make sure you have configured a reverse proxy for <code>.well-known</code> "
"directory to <code>HTTPChallengePort</code> (default: 9180) before getting "
"the certificate."
msgstr ""
"在获取签发证书前,请确保配置文件中已将 <code>.well-known</code> 目录反向代"
"理到<code>HTTPChallengePort</code> (默认: 9180)"
#: src/router/index.js:60
msgid "Manage Configs"
msgstr "配置管理"
#: src/router/index.js:35 src/views/domain/DomainList.vue:21
msgid "Manage Sites"
msgstr "网站管理"
#: src/router/index.js:27
msgid "Manage Users"
msgstr "用户管理"
#: src/views/dashboard/DashBoard.vue:24
msgid "Memory" msgid "Memory"
msgstr "内存" msgstr "内存"
#: src/router/index.js:68 #: src/views/config/Config.vue:5 src/views/domain/DomainList.vue:5
msgid "Modify Config" msgid "Name"
msgstr "配置修改" msgstr "名称"
#: src/router/index.js:51 #: src/router/index.js:106
msgid "Modify Sites"
msgstr "站点修改"
#: src/router/index.js:104
msgid "Not Found" msgid "Not Found"
msgstr "找不到页面" msgstr "找不到页面"
#: src/router/index.js:128 #: src/views/domain/CertInfo.vue:7
msgid "OK" msgid "Not Valid Before: %{date}"
msgstr "好的" msgstr "此前无效: %{date}"
#: src/views/dashboard/DashBoard.vue:96 #: src/views/domain/DomainEdit.vue:155
msgid "Physical memory:" msgid ""
msgstr "物理内存:" "Note: The server_name in the current configuration must be the domain name "
"you need to get the certificate."
msgstr "注意:当前配置中的 server_name 必须为需要申请证书的域名。"
#: src/router/index.js:130
msgid "OK"
msgstr "确定"
#: src/views/other/Login.vue:55 src/views/user/User.vue:13
msgid "Password"
msgstr "密码"
#: src/views/other/Install.vue:82
msgid "Password (*)"
msgstr "密码 (*)"
#: src/views/other/Install.vue:49
msgid "Please input your E-mail!"
msgstr "请输入您的邮箱!"
#: src/views/other/Install.vue:95 src/views/other/Login.vue:68
msgid "Please input your password!"
msgstr "请输入您的密码!"
#: src/views/other/Install.vue:72 src/views/other/Login.vue:45
msgid "Please input your username!"
msgstr "请输入您的用户名!"
#: src/views/domain/columns.js:67
msgid "Private Key Path (ssl_certificate_key)"
msgstr "私钥路径 (ssl_certificate_key)"
#: src/views/other/About.vue:8
msgid "Project Team"
msgstr "项目团队"
#: src/views/domain/columns.js:16
msgid "Root Directory (root)"
msgstr "网站根目录 (root)"
#: src/views/config/ConfigEdit.vue:6 src/views/domain/DomainAdd.vue:6
#: src/views/domain/DomainEdit.vue:24
msgid "Save"
msgstr "保存"
#: src/views/config/ConfigEdit.vue:47 src/views/domain/DomainAdd.vue:38
#: src/views/domain/DomainEdit.vue:151
msgid "Save error %{msg}"
msgstr "保存错误 %{msg}"
#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:24
#: src/views/domain/DomainEdit.vue:145
msgid "Saved successfully"
msgstr "保存成功"
#: src/views/config/ConfigEdit.vue:35 src/views/domain/DomainEdit.vue:71
#: src/views/other/Login.vue:33
msgid "Server error"
msgstr "服务器错误"
#: src/views/domain/columns.js:10
msgid "Server Names (server_name)"
msgstr "网站域名 (server_name)"
#: src/views/dashboard/DashBoard.vue:38 #: src/views/dashboard/DashBoard.vue:38
msgid "Server status" msgid "Server Status"
msgstr "服务器状态" msgstr "服务器状态"
#: src/router/index.js:35
msgid "Sites"
msgstr "站点"
#: src/router/index.js:43 #: src/router/index.js:43
msgid "Sites List" msgid "Sites List"
msgstr "站点列表" msgstr "站点列表"
#: src/views/dashboard/DashBoard.vue:32 #: src/views/domain/DomainList.vue:11
msgid "Status"
msgstr "状态"
#: src/views/dashboard/DashBoard.vue:33
msgid "Storage" msgid "Storage"
msgstr "存储" msgstr "存储"
#: src/router/index.js:123 #: src/views/domain/CertInfo.vue:4
msgid "Subject Name: %{name}"
msgstr "主体名称: %{name}"
#: src/router/index.js:125
msgid "System message" msgid "System message"
msgstr "系统消息" msgstr "系统消息"
#: src/views/dashboard/DashBoard.vue:124 #: src/views/domain/columns.js:50
msgid "Total:" msgid ""
msgstr "总共:" "The certificate for the domain will be checked every hour, and will be "
"renewed if it has been more than 1 month since it was last issued.<br/>If "
"you do not have a certificate before, please click \"Getting Certificate "
"from Let's Encrypt\" first."
msgstr ""
"系统将会每小时检测一次该域名证书若距离上次签发已超过1个月则将自动续签。"
"<br/>如果您之前没有证书,请先点击 \"从 Let's Encrypt 获取证书\"。"
#: src/views/other/Install.vue:119
msgid "The filename cannot contain the following characters: %{c}"
msgstr "文件名不能包含以下字符: %{c}"
#: src/views/domain/DomainEdit.vue:4
msgid ""
"The following values will only take effect if you have the corresponding "
"fields in your configuration file. The configuration filename cannot be "
"changed after it has been created."
msgstr ""
"只有在您的配置文件中有相应字段时,下列的配置才能生效。配置文件名称创建后不"
"可修改。"
#: src/views/domain/DomainEdit.vue:134
msgid "This operation will lose the custom configuration."
msgstr "该操作将会丢失自定义配置。"
#: src/views/config/Config.vue:11 src/views/domain/DomainList.vue:22
#: src/views/user/User.vue:29
msgid "Updated at"
msgstr "修改时间"
#: src/views/dashboard/DashBoard.vue:12 #: src/views/dashboard/DashBoard.vue:12
msgid "Uptime" msgid "Uptime"
msgstr "运行时间" msgstr "运行时间"
#: src/views/dashboard/DashBoard.vue:94 src/views/dashboard/DashBoard.vue:123 #: src/views/dashboard/DashBoard.vue:95
msgid "Used:" msgid "Used: %{u}, Cached: %{c}, Free: %{f}, Physical Memory: %{p}"
msgstr "已使用:" msgstr "已使用: %{u}, 缓存: %{c}, 空闲: %{f}, 物理内存: %{p}"
#: src/router/index.js:27 #: src/views/dashboard/DashBoard.vue:123
msgid "Users" msgid "Used: %{used} / Total: %{total}"
msgstr "用户" msgstr "已使用: %{used} / 总共: %{total}"
#: src/views/other/Login.vue:32 src/views/user/User.vue:5
msgid "Username"
msgstr "用户名"
#: src/views/other/Install.vue:59
msgid "Username (*)"
msgstr "用户名 (*)"

View file

@ -9,110 +9,401 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: easygettext\n" "Generated-By: easygettext\n"
#: src/router/index.js:98 #: src/router/index.js:100
msgid "404 Not Found" msgid "404 Not Found"
msgstr "" msgstr ""
#: src/router/index.js:76 #: src/router/index.js:78
msgid "About" msgid "About"
msgstr "" msgstr ""
#: src/router/index.js:47 #: src/views/config/Config.vue:18 src/views/domain/DomainList.vue:29
msgid "Add Sites" #: src/views/user/User.vue:35
msgid "Action"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:94 #: src/router/index.js:47 src/views/domain/DomainAdd.vue:18
msgid "Cached:" #: src/views/domain/DomainEdit.vue:45
msgid "Add Site"
msgstr "" msgstr ""
#: src/router/index.js:60 #: src/views/domain/DomainAdd.vue:2
msgid "Config" msgid ""
"Add site here first, then you can configure TLS on the domain edit page."
msgstr ""
#: src/views/domain/DomainEdit.vue:194
msgid "Auto-renewal disabled for %{name}"
msgstr ""
#: src/views/domain/DomainEdit.vue:188
msgid "Auto-renewal enabled for %{name}"
msgstr ""
#: src/views/other/About.vue:11
msgid "Build with"
msgstr ""
#: src/views/config/ConfigEdit.vue:5 src/views/domain/DomainEdit.vue:23
msgid "Cancel"
msgstr ""
#: src/views/domain/columns.js:44
msgid "Certificate Auto-renewal"
msgstr ""
#: src/views/domain/CertInfo.vue:11 src/views/domain/CertInfo.vue:2
msgid "Certificate has expired"
msgstr ""
#: src/views/domain/CertInfo.vue:15 src/views/domain/CertInfo.vue:2
msgid "Certificate is valid"
msgstr ""
#: src/views/domain/columns.js:61
msgid "Certificate Path (ssl_certificate)"
msgstr ""
#: src/views/domain/CertInfo.vue:2
msgid "Certificate Status"
msgstr ""
#: src/views/domain/columns.js:4
msgid "Configuration Name"
msgstr ""
#: src/views/config/Config.vue:8
msgid "Configurations"
msgstr ""
#: src/views/dashboard/DashBoard.vue:52
msgid "CPU"
msgstr ""
#: src/views/user/User.vue:23
msgid "Created at"
msgstr "" msgstr ""
#: src/router/index.js:19 #: src/router/index.js:19
msgid "Dashboard" msgid "Dashboard"
msgstr "" msgstr ""
#: src/router/index.js:124 #: src/views/other/Install.vue:104
msgid "Detected version update, this page will automatically refresh." msgid "Database (Optional, default: database)"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:95 #: src/router/index.js:126
msgid "Free:" msgid "Detected version update, this page will refresh."
msgstr ""
#: src/views/other/About.vue:11
msgid "Development Mode"
msgstr ""
#: src/views/domain/DomainEdit.vue:196
msgid "Disable auto-renewal failed for %{name}"
msgstr ""
#: src/views/domain/DomainList.vue:7 src/views/domain/DomainList.vue:2
#: src/views/domain/DomainList.vue:17
msgid "Disabled"
msgstr ""
#: src/views/domain/DomainList.vue:55
msgid "Disabled successfully"
msgstr ""
#: src/views/domain/DomainEdit.vue:133
msgid "Do you want to change the template to support the TLS?"
msgstr ""
#: src/views/domain/DomainEdit.vue:45
msgid "Edit %{n}"
msgstr ""
#: src/router/index.js:68 src/views/config/ConfigEdit.vue:15
msgid "Edit Configuration"
msgstr ""
#: src/views/domain/DomainEdit.vue:91
msgid "Edit Configuration File"
msgstr ""
#: src/router/index.js:51
msgid "Edit Site"
msgstr ""
#: src/views/other/Install.vue:30
msgid "Email (*)"
msgstr ""
#: src/views/domain/DomainEdit.vue:190
msgid "Enable auto-renewal failed for %{name}"
msgstr ""
#: src/views/domain/DomainAdd.vue:33
msgid "Enable failed"
msgstr ""
#: src/views/domain/columns.js:35
msgid "Enable TLS"
msgstr ""
#: src/views/domain/DomainList.vue:8 src/views/domain/DomainList.vue:3
#: src/views/domain/DomainList.vue:16
msgid "Enabled"
msgstr ""
#: src/views/domain/DomainAdd.vue:27 src/views/domain/DomainList.vue:46
msgid "Enabled successfully"
msgstr ""
#: src/views/domain/CertInfo.vue:5
msgid "Expiration Date: %{date}"
msgstr ""
#: src/views/domain/DomainList.vue:59
msgid "Failed to disable %{msg}"
msgstr ""
#: src/views/domain/DomainList.vue:50
msgid "Failed to enable %{msg}"
msgstr ""
#: src/views/other/Error.vue:9
msgid "File Not Found"
msgstr ""
#: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainEdit.vue:3
msgid "Getting Certificate from Let's Encrypt"
msgstr ""
#: src/views/domain/DomainEdit.vue:156
msgid "Getting the certificate, please wait..."
msgstr "" msgstr ""
#: src/router/index.js:12 #: src/router/index.js:12
msgid "Home" msgid "Home"
msgstr "" msgstr ""
#: src/router/index.js:86 #: src/views/domain/columns.js:28
msgid "HTTP Listen Port"
msgstr ""
#: src/views/domain/columns.js:54
msgid "HTTPS Listen Port"
msgstr ""
#: src/views/domain/columns.js:22
msgid "Index (index)"
msgstr ""
#: src/router/index.js:88 src/views/other/Install.vue:50
msgid "Install" msgid "Install"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:13 #: src/views/domain/CertInfo.vue:3
msgid "Load averages" msgid "Intermediate Certification Authorities: %{issuer}"
msgstr "" msgstr ""
#: src/router/index.js:92 #: src/views/other/Install.vue:45
msgid "Invalid E-mail!"
msgstr ""
#: src/views/user/User.vue:19
msgid "Leave blank for no change"
msgstr ""
#: src/views/other/About.vue:16
msgctxt "Project"
msgid "License"
msgstr ""
#: src/views/dashboard/DashBoard.vue:13
msgid "Load Averages:"
msgstr ""
#: src/router/index.js:94 src/views/other/Login.vue:24
msgid "Login" msgid "Login"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:23 #: src/views/other/Login.vue:28
msgid "Login successful"
msgstr ""
#: src/layouts/HeaderLayout.vue:9
msgid "Logout successful"
msgstr ""
#: src/views/domain/DomainEdit.vue:12 src/views/domain/DomainEdit.vue:6
msgid ""
"Make sure you have configured a reverse proxy for <code>.well-known</code> "
"directory to <code>HTTPChallengePort</code> (default: 9180) before getting "
"the certificate."
msgstr ""
#: src/router/index.js:60
msgid "Manage Configs"
msgstr ""
#: src/router/index.js:35 src/views/domain/DomainList.vue:21
msgid "Manage Sites"
msgstr ""
#: src/router/index.js:27
msgid "Manage Users"
msgstr ""
#: src/views/dashboard/DashBoard.vue:24
msgid "Memory" msgid "Memory"
msgstr "" msgstr ""
#: src/router/index.js:68 #: src/views/config/Config.vue:5 src/views/domain/DomainList.vue:5
msgid "Modify Config" msgid "Name"
msgstr "" msgstr ""
#: src/router/index.js:51 #: src/router/index.js:106
msgid "Modify Sites"
msgstr ""
#: src/router/index.js:104
msgid "Not Found" msgid "Not Found"
msgstr "" msgstr ""
#: src/router/index.js:128 #: src/views/domain/CertInfo.vue:7
msgid "Not Valid Before: %{date}"
msgstr ""
#: src/views/domain/DomainEdit.vue:155
msgid ""
"Note: The server_name in the current configuration must be the domain name "
"you need to get the certificate."
msgstr ""
#: src/router/index.js:130
msgid "OK" msgid "OK"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:96 #: src/views/other/Login.vue:55 src/views/user/User.vue:13
msgid "Physical memory:" msgid "Password"
msgstr ""
#: src/views/other/Install.vue:82
msgid "Password (*)"
msgstr ""
#: src/views/other/Install.vue:49
msgid "Please input your E-mail!"
msgstr ""
#: src/views/other/Install.vue:95 src/views/other/Login.vue:68
msgid "Please input your password!"
msgstr ""
#: src/views/other/Install.vue:72 src/views/other/Login.vue:45
msgid "Please input your username!"
msgstr ""
#: src/views/domain/columns.js:67
msgid "Private Key Path (ssl_certificate_key)"
msgstr ""
#: src/views/other/About.vue:8
msgid "Project Team"
msgstr ""
#: src/views/domain/columns.js:16
msgid "Root Directory (root)"
msgstr ""
#: src/views/config/ConfigEdit.vue:6 src/views/domain/DomainAdd.vue:6
#: src/views/domain/DomainEdit.vue:24
msgid "Save"
msgstr ""
#: src/views/config/ConfigEdit.vue:47 src/views/domain/DomainAdd.vue:38
#: src/views/domain/DomainEdit.vue:151
msgid "Save error %{msg}"
msgstr ""
#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:24
#: src/views/domain/DomainEdit.vue:145
msgid "Saved successfully"
msgstr ""
#: src/views/config/ConfigEdit.vue:35 src/views/domain/DomainEdit.vue:71
#: src/views/other/Login.vue:33
msgid "Server error"
msgstr ""
#: src/views/domain/columns.js:10
msgid "Server Names (server_name)"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:38 #: src/views/dashboard/DashBoard.vue:38
msgid "Server status" msgid "Server Status"
msgstr ""
#: src/router/index.js:35
msgid "Sites"
msgstr "" msgstr ""
#: src/router/index.js:43 #: src/router/index.js:43
msgid "Sites List" msgid "Sites List"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:32 #: src/views/domain/DomainList.vue:11
msgid "Status"
msgstr ""
#: src/views/dashboard/DashBoard.vue:33
msgid "Storage" msgid "Storage"
msgstr "" msgstr ""
#: src/router/index.js:123 #: src/views/domain/CertInfo.vue:4
msgid "Subject Name: %{name}"
msgstr ""
#: src/router/index.js:125
msgid "System message" msgid "System message"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:124 #: src/views/domain/columns.js:50
msgid "Total:" msgid ""
"The certificate for the domain will be checked every hour, and will be "
"renewed if it has been more than 1 month since it was last issued.<br/>If "
"you do not have a certificate before, please click \"Getting Certificate "
"from Let's Encrypt\" first."
msgstr ""
#: src/views/other/Install.vue:119
msgid "The filename cannot contain the following characters: %{c}"
msgstr ""
#: src/views/domain/DomainEdit.vue:4
msgid ""
"The following values will only take effect if you have the corresponding "
"fields in your configuration file. The configuration filename cannot be "
"changed after it has been created."
msgstr ""
#: src/views/domain/DomainEdit.vue:134
msgid "This operation will lose the custom configuration."
msgstr ""
#: src/views/config/Config.vue:11 src/views/domain/DomainList.vue:22
#: src/views/user/User.vue:29
msgid "Updated at"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:12 #: src/views/dashboard/DashBoard.vue:12
msgid "Uptime" msgid "Uptime"
msgstr "" msgstr ""
#: src/views/dashboard/DashBoard.vue:94 src/views/dashboard/DashBoard.vue:123 #: src/views/dashboard/DashBoard.vue:95
msgid "Used:" msgid "Used: %{u}, Cached: %{c}, Free: %{f}, Physical Memory: %{p}"
msgstr "" msgstr ""
#: src/router/index.js:27 #: src/views/dashboard/DashBoard.vue:123
msgid "Users" msgid "Used: %{used} / Total: %{total}"
msgstr ""
#: src/views/other/Login.vue:32 src/views/user/User.vue:5
msgid "Username"
msgstr ""
#: src/views/other/Install.vue:59
msgid "Username (*)"
msgstr "" msgstr ""

View file

@ -1,122 +0,0 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: easygettext\n"
#: src/router/index.js:98
msgid "404 Not Found"
msgstr ""
#: src/router/index.js:76
msgid "About"
msgstr ""
#: src/router/index.js:47
msgid "Add Sites"
msgstr ""
#: src/views/dashboard/DashBoard.vue:94
msgid "Cached:"
msgstr ""
#: src/router/index.js:60
msgid "Config"
msgstr ""
#: src/router/index.js:19
msgid "Dashboard"
msgstr ""
#: src/router/index.js:124
msgid "Detected version update, this page will automatically refresh."
msgstr ""
#: src/views/dashboard/DashBoard.vue:95
msgid "Free:"
msgstr ""
#: src/router/index.js:12
msgid "Home"
msgstr ""
#: src/router/index.js:86
msgid "Install"
msgstr ""
#: src/views/dashboard/DashBoard.vue:13
msgid "Load averages"
msgstr ""
#: src/router/index.js:92
msgid "Login"
msgstr ""
#: src/views/dashboard/DashBoard.vue:23
msgid "Memory"
msgstr ""
#: src/router/index.js:68
msgid "Modify Config"
msgstr ""
#: src/router/index.js:51
msgid "Modify Sites"
msgstr ""
#: src/router/index.js:104
msgid "Not Found"
msgstr ""
#: src/router/index.js:128
msgid "OK"
msgstr ""
#: src/views/dashboard/DashBoard.vue:96
msgid "Physical memory:"
msgstr ""
#: src/views/dashboard/DashBoard.vue:38
msgid "Server status"
msgstr ""
#: src/router/index.js:35
msgid "Sites"
msgstr ""
#: src/router/index.js:43
msgid "Sites List"
msgstr ""
#: src/views/dashboard/DashBoard.vue:32
msgid "Storage"
msgstr ""
#: src/router/index.js:123
msgid "System message"
msgstr ""
#: src/views/dashboard/DashBoard.vue:124
msgid "Total: "
msgstr ""
#: src/views/dashboard/DashBoard.vue:12
msgid "Uptime"
msgstr ""
#: src/views/dashboard/DashBoard.vue:94
msgid "Used:"
msgstr ""
#: src/views/dashboard/DashBoard.vue:123
msgid "Used: "
msgstr ""
#: src/router/index.js:27
msgid "Users"
msgstr ""

View file

@ -28,7 +28,7 @@ Vue.use(GetTextPlugin, {
}) })
http.get('/translations.json').then(r => { http.get('/translations.json').then(r => {
store.commit('update_translations', r) if(r) store.commit('update_translations', r)
}) })
NProgress.configure({ NProgress.configure({

View file

@ -24,7 +24,7 @@ export const routes = [
}, },
{ {
path: 'user', path: 'user',
name: $gettext('Users'), name: $gettext('Manage Users'),
component: () => import('@/views/user/User.vue'), component: () => import('@/views/user/User.vue'),
meta: { meta: {
icon: 'user' icon: 'user'
@ -32,7 +32,7 @@ export const routes = [
}, },
{ {
path: 'domain', path: 'domain',
name: $gettext('Sites'), name: $gettext('Manage Sites'),
component: () => import('@/layouts/BaseRouterView'), component: () => import('@/layouts/BaseRouterView'),
meta: { meta: {
icon: 'cloud' icon: 'cloud'
@ -44,11 +44,11 @@ export const routes = [
component: () => import('@/views/domain/DomainList.vue'), component: () => import('@/views/domain/DomainList.vue'),
}, { }, {
path: 'add', path: 'add',
name: $gettext('Add Sites'), name: $gettext('Add Site'),
component: () => import('@/views/domain/DomainAdd.vue'), component: () => import('@/views/domain/DomainAdd.vue'),
}, { }, {
path: ':name', path: ':name',
name: $gettext('Modify Sites'), name: $gettext('Edit Site'),
component: () => import('@/views/domain/DomainEdit.vue'), component: () => import('@/views/domain/DomainEdit.vue'),
meta: { meta: {
hiddenInSidebar: true hiddenInSidebar: true
@ -57,20 +57,22 @@ export const routes = [
}, },
{ {
path: 'config', path: 'config',
name: $gettext('Config'), name: $gettext('Manage Configs'),
component: () => import('@/views/config/Config.vue'), component: () => import('@/views/config/Config.vue'),
meta: { meta: {
icon: 'file' icon: 'file',
}, hideChildren: true
},
{
path: 'config/:name',
name: $gettext('Modify Config'),
component: () => import('@/views/config/ConfigEdit.vue'),
meta: {
hiddenInSidebar: true
}, },
children: [{
path: 'config/:name',
name: $gettext('Edit Configuration'),
component: () => import('@/views/config/ConfigEdit.vue'),
meta: {
hiddenInSidebar: true
},
},]
}, },
{ {
path: 'about', path: 'about',
name: $gettext('About'), name: $gettext('About'),
@ -121,7 +123,7 @@ router.beforeEach((to, from, next) => {
&& Number(process.env.VUE_APP_BUILD_ID) === r.data.build_id)) { && Number(process.env.VUE_APP_BUILD_ID) === r.data.build_id)) {
Vue.prototype.$info({ Vue.prototype.$info({
title: $gettext('System message'), title: $gettext('System message'),
content: $gettext('Detected version update, this page will automatically refresh.'), content: $gettext('Detected version update, this page will refresh.'),
onOk() { onOk() {
location.reload() location.reload()
}, },

View file

@ -1,5 +1,5 @@
<template> <template>
<a-card title="配置文件"> <a-card :title="$gettext('Configurations')">
<std-table <std-table
:api="api" :api="api"
:columns="columns" :columns="columns"
@ -18,22 +18,23 @@
<script> <script>
import StdTable from '@/components/StdDataDisplay/StdTable' import StdTable from '@/components/StdDataDisplay/StdTable'
import $gettext from "@/lib/translate/gettext";
const columns = [{ const columns = [{
title: '名称', title: $gettext('Name'),
dataIndex: 'name', dataIndex: 'name',
scopedSlots: {customRender: '名称'}, scopedSlots: {customRender: 'name'},
sorter: true, sorter: true,
pithy: true pithy: true
}, { }, {
title: '修改时间', title: $gettext('Updated at'),
dataIndex: 'modify', dataIndex: 'modify',
datetime: true, datetime: true,
scopedSlots: {customRender: 'modify'}, scopedSlots: {customRender: 'modify'},
sorter: true, sorter: true,
pithy: true pithy: true
}, { }, {
title: '操作', title: $gettext('Action'),
dataIndex: 'action', dataIndex: 'action',
scopedSlots: {customRender: 'action'} scopedSlots: {customRender: 'action'}
}] }]

View file

@ -1,10 +1,10 @@
<template> <template>
<a-card title="配置文件编辑"> <a-card :title="$gettext('Edit Configuration')">
<vue-itextarea v-model="configText"/> <vue-itextarea v-model="configText"/>
<footer-tool-bar> <footer-tool-bar>
<a-space> <a-space>
<a-button @click="$router.go(-1)">返回</a-button> <a-button @click="$router.go(-1)" v-translate>Cancel</a-button>
<a-button type="primary" @click="save">保存</a-button> <a-button type="primary" @click="save" v-translate>Save</a-button>
</a-space> </a-space>
</footer-tool-bar> </footer-tool-bar>
</a-card> </a-card>
@ -13,6 +13,7 @@
<script> <script>
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar' import FooterToolBar from '@/components/FooterToolbar/FooterToolBar'
import VueItextarea from '@/components/VueItextarea/VueItextarea' import VueItextarea from '@/components/VueItextarea/VueItextarea'
import $gettext, {$interpolate} from "@/lib/translate/gettext";
export default { export default {
name: 'DomainEdit', name: 'DomainEdit',
@ -44,7 +45,7 @@ export default {
this.configText = r.config this.configText = r.config
}).catch(r => { }).catch(r => {
console.log(r) console.log(r)
this.$message.error('服务器错误') this.$message.error($gettext('Server error'))
}) })
} else { } else {
this.configText = '' this.configText = ''
@ -53,10 +54,10 @@ export default {
save() { save() {
this.$api.config.save(this.name ? this.name : this.config.name, {content: this.configText}).then(r => { this.$api.config.save(this.name ? this.name : this.config.name, {content: this.configText}).then(r => {
this.configText = r.config this.configText = r.config
this.$message.success('保存成功') this.$message.success($gettext('Saved successfully'))
}).catch(r => { }).catch(r => {
console.log(r) console.log(r)
this.$message.error('保存错误') this.$message.error($interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ""}))
}) })
} }
} }

View file

@ -2,7 +2,7 @@
<div> <div>
<a-row class="row-two"> <a-row class="row-two">
<a-col :lg="24" :sm="24"> <a-col :lg="24" :sm="24">
<a-card style="min-height: 400px" :title="$gettext('Server status')"> <a-card style="min-height: 400px" :title="$gettext('Server Status')">
<a-row> <a-row>
<a-col :lg="12" :sm="24" class="chart"> <a-col :lg="12" :sm="24" class="chart">
<a-statistic :value="cpu" style="margin: 0 50px 10px 0" title="CPU"> <a-statistic :value="cpu" style="margin: 0 50px 10px 0" title="CPU">
@ -11,17 +11,17 @@
</template> </template>
</a-statistic> </a-statistic>
<p><translate>Uptime</translate> {{ uptime }}</p> <p><translate>Uptime</translate> {{ uptime }}</p>
<p><translate>Load averages</translate> 1min:{{ loadavg?.load1?.toFixed(2) }} <p><translate>Load Averages: </translate> 1min:{{ loadavg?.load1?.toFixed(2) }} |
5min:{{ loadavg?.load5?.toFixed(2) }} 5min:{{ loadavg?.load5?.toFixed(2) }} |
15min:{{ loadavg?.load15?.toFixed(2) }}</p> 15min:{{ loadavg?.load15?.toFixed(2) }}</p>
<line-chart :chart-data="cpu_analytic" :options="cpu_analytic.options" :height="150"/> <line-chart :chart-data="cpu_analytic" :options="cpu_analytic.options" :height="150"/>
</a-col> </a-col>
<a-col :lg="6" :sm="8" :xs="12" class="chart_dashboard"> <a-col :lg="6" :sm="8" :xs="12" class="chart_dashboard">
<div> <div>
<a-tooltip <a-tooltip
:title="$gettext('Used:') + memory_used + $gettext('Cached:') + :title="$gettextInterpolate(
memory_cached + $gettext('Free:') + memory_free + $gettext('Used: %{u}, Cached: %{c}, Free: %{f}, Physical Memory: %{p}'),
$gettext('Physical memory:') + memory_total"> {u: memory_used, c: memory_cached, f:memory_free, p: memory_total})">
<a-progress :percent="memory_pressure" strokeColor="rgb(135, 208, 104)" <a-progress :percent="memory_pressure" strokeColor="rgb(135, 208, 104)"
type="dashboard"/> type="dashboard"/>
<p class="description" v-translate>Memory</p> <p class="description" v-translate>Memory</p>
@ -31,8 +31,8 @@
<a-col :lg="6" :sm="8" :xs="12" class="chart_dashboard"> <a-col :lg="6" :sm="8" :xs="12" class="chart_dashboard">
<div> <div>
<a-tooltip <a-tooltip
:title="$gettext('Used:')+ disk_used + :title="$gettextInterpolate($gettext('Used: %{used} / Total: %{total}'),
' / '+ $gettext('Total:') + disk_total"> {used: disk_used, total: disk_total})">
<a-progress :percent="disk_percentage" type="dashboard"/> <a-progress :percent="disk_percentage" type="dashboard"/>
<p class="description" v-translate>Storage</p> <p class="description" v-translate>Storage</p>
</a-tooltip> </a-tooltip>
@ -81,10 +81,10 @@ export default {
options: { options: {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
responsiveAnimationDuration: 0, // responsiveAnimationDuration: 0, // Duration of the animation after resizing
elements: { elements: {
line: { line: {
tension: 0 // 线 tension: 0 // Disable Bessel curves 线
} }
}, },
scales: { scales: {

View file

@ -1,17 +1,19 @@
<template> <template>
<div v-if="ok"> <div v-if="ok">
<h3>证书状态</h3> <h3 v-translate>Certificate Status</h3>
<p>中级证书颁发机构{{ cert.issuer_name }}</p> <p v-translate :translate-params="{issuer: cert.issuer_name}">Intermediate Certification Authorities: %{issuer}</p>
<p>证书名称{{ cert.subject_name }}</p> <p v-translate :translate-params="{name: cert.subject_name}">Subject Name: %{name}</p>
<p>过期时间{{ moment(cert.not_after).format('YYYY-MM-DD HH:mm:ss') }}</p> <p v-translate :translate-params="{date: moment(cert.not_after).format('YYYY-MM-DD HH:mm:ss')}">
<p>在此之前无效{{ moment(cert.not_before).format('YYYY-MM-DD HH:mm:ss') }}</p> Expiration Date: %{date}</p>
<p v-translate :translate-params="{date: moment(cert.not_before).format('YYYY-MM-DD HH:mm:ss')}">
Not Valid Before: %{date}</p>
<template v-if="new Date().toISOString() < cert.not_before || new Date().toISOString() > cert.not_after"> <template v-if="new Date().toISOString() < cert.not_before || new Date().toISOString() > cert.not_after">
<a-icon :style="{ color: 'red' }" type="close-circle"/> <a-icon :style="{ color: 'red' }" type="close-circle"/>
此证书已过期 <translate>Certificate has expired</translate>
</template> </template>
<template v-else> <template v-else>
<a-icon :style="{ color: 'green' }" type="check-circle"/> <a-icon :style="{ color: 'green' }" type="check-circle"/>
证书处在有效期内 <translate>Certificate is valid</translate>
</template> </template>
</div> </div>
</template> </template>

View file

@ -1,13 +1,13 @@
<template> <template>
<a-card title="添加站点"> <a-card :title="$gettext('Add Site')">
<p>在这里添加站点添加完成后进入域名配置编辑页面即可配置 SSL</p> <p v-translate>Add site here first, then you can configure TLS on the domain edit page.</p>
<std-data-entry :data-list="columns" :data-source="config"/> <std-data-entry :data-list="columns" :data-source="config"/>
<footer-tool-bar> <footer-tool-bar>
<a-button <a-button
type="primary" type="primary"
@click="save" @click="save"
> >
完成 <translate>Save</translate>
</a-button> </a-button>
</footer-tool-bar> </footer-tool-bar>
</a-card> </a-card>
@ -18,6 +18,7 @@ import FooterToolBar from '@/components/FooterToolbar/FooterToolBar'
import StdDataEntry from '@/components/StdDataEntry/StdDataEntry' import StdDataEntry from '@/components/StdDataEntry/StdDataEntry'
import {columns} from '@/views/domain/columns' import {columns} from '@/views/domain/columns'
import {unparse} from '@/views/domain/methods' import {unparse} from '@/views/domain/methods'
import $gettext, {$interpolate} from "@/lib/translate/gettext";
export default { export default {
name: 'DomainAdd', name: 'DomainAdd',
@ -36,21 +37,21 @@ export default {
this.$api.domain.get_template('http-conf').then(r => { this.$api.domain.get_template('http-conf').then(r => {
let text = unparse(r.template, this.config) let text = unparse(r.template, this.config)
this.$api.domain.save(this.config.name, {content: text, enabled: true}).then(() => { this.$api.domain.save(this.config.name, {content: text, enabled: true}).then(() => {
this.$message.success('保存成功') this.$message.success($gettext('Saved successfully'))
this.$api.domain.enable(this.config.name).then(() => { this.$api.domain.enable(this.config.name).then(() => {
this.$message.success('启用成功') this.$message.success($gettext('Enabled successfully'))
this.$router.push('/domain/' + this.config.name) this.$router.push('/domain/' + this.config.name)
}).catch(r => { }).catch(r => {
console.log(r) console.log(r)
this.$message.error(r.message ?? '启用失败', 10) this.$message.error(r.message ?? $gettext('Enable failed'), 10)
}) })
}).catch(r => { }).catch(r => {
console.log(r) console.log(r)
this.$message.error(r.message ?? '保存错误', 10) this.$message.error($interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ""}), 10)
}) })
}) })
} }

View file

@ -1,31 +1,28 @@
<template> <template>
<div> <div>
<a-collapse :bordered="false" default-active-key="1"> <a-collapse :bordered="false" default-active-key="1">
<a-collapse-panel key="1" :header="name ? '编辑站点:' + name : '添加站点'"> <a-collapse-panel key="1" :header="name ? $gettextInterpolate($gettext('Edit %{n}'), {n: name}) : $gettext('Add Site')">
<p>您的配置文件中应当有对应的字段时下列表单中的设置才能生效配置文件名称创建后不可修改</p> <p v-translate>The following values will only take effect if you have the corresponding fields in your configuration file. The configuration filename cannot be changed after it has been created.</p>
<std-data-entry :data-list="columns" v-model="config"/> <std-data-entry :data-list="columns" v-model="config"/>
<template v-if="config.support_ssl"> <template v-if="config.support_ssl">
<cert-info :domain="name" ref="cert-info" v-if="name"/> <cert-info :domain="name" ref="cert-info" v-if="name"/>
<br/> <br/>
<a-button @click="issue_cert" type="primary" ghost> <a-button @click="issue_cert" type="primary" ghost v-translate>
自动申请 Let's Encrypt 证书 Getting Certificate from Let's Encrypt
</a-button> </a-button><br/>
<p><br/>点击自动申请证书将会从 Let's Encrypt 获得签发证书 <p v-translate>Make sure you have configured a reverse proxy for <code>.well-known</code> directory to <code>HTTPChallengePort</code> (default: 9180) before getting the certificate.</p>
在获取签发证书前请确保配置文件中已为
<code>/.well-known</code> 目录反向代理到后端的
<code>HTTPChallengePort (default:9180)</code></p>
</template> </template>
</a-collapse-panel> </a-collapse-panel>
</a-collapse> </a-collapse>
<a-card title="配置文件编辑"> <a-card :title="$gettext('Edit Configuration File')">
<vue-itextarea v-model="configText"/> <vue-itextarea v-model="configText"/>
</a-card> </a-card>
<footer-tool-bar> <footer-tool-bar>
<a-space> <a-space>
<a-button @click="$router.push('/domain/list')">返回</a-button> <a-button @click="$router.push('/domain/list')" v-translate>Cancel</a-button>
<a-button type="primary" @click="save">保存</a-button> <a-button type="primary" @click="save" v-translate>Save</a-button>
</a-space> </a-space>
</footer-tool-bar> </footer-tool-bar>
</div> </div>
@ -39,6 +36,7 @@ import VueItextarea from '@/components/VueItextarea/VueItextarea'
import {columns, columnsSSL} from '@/views/domain/columns' import {columns, columnsSSL} from '@/views/domain/columns'
import {unparse} from '@/views/domain/methods' import {unparse} from '@/views/domain/methods'
import CertInfo from '@/views/domain/CertInfo' import CertInfo from '@/views/domain/CertInfo'
import $gettext, {$interpolate} from "@/lib/translate/gettext";
export default { export default {
name: 'DomainEdit', name: 'DomainEdit',
@ -102,7 +100,7 @@ export default {
}) })
}).catch(r => { }).catch(r => {
console.log(r) console.log(r)
this.$message.error('服务器错误') this.$message.error($gettext('Server error'))
}) })
} else { } else {
this.config = { this.config = {
@ -164,8 +162,8 @@ export default {
change_support_ssl() { change_support_ssl() {
const that = this const that = this
this.$confirm({ this.$confirm({
title: '您已修改 SSL 支持状态,是否需要更换配置文件模板?', title: $gettext('Do you want to change the template to support the TLS?'),
content: '更换配置文件模板将会丢失自定义配置', content: $gettext('This operation will lose the custom configuration.'),
onOk() { onOk() {
that.get_template() that.get_template()
}, },
@ -176,18 +174,18 @@ export default {
save() { save() {
this.$api.domain.save(this.name, {content: this.configText}).then(r => { this.$api.domain.save(this.name, {content: this.configText}).then(r => {
this.parse(r) this.parse(r)
this.$message.success('保存成功') this.$message.success($gettext('Saved successfully'))
if (this.name) { if (this.name) {
if (this.$refs['cert-info']) this.$refs['cert-info'].get() if (this.$refs['cert-info']) this.$refs['cert-info'].get()
} }
}).catch(r => { }).catch(r => {
console.log(r) console.log(r)
this.$message.error('保存错误' + r.message !== undefined ? ' ' + r.message : null, 10) this.$message.error($interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ""}), 10)
}) })
}, },
issue_cert() { issue_cert() {
this.$message.info('请注意,当前配置中 server_name 必须为需要申请证书的域名,否则无法申请', 15) this.$message.info($gettext('Note: The server_name in the current configuration must be the domain name you need to get the certificate.'), 15)
this.$message.info('正在申请,请稍后', 15) this.$message.info($gettext('Getting the certificate, please wait...'), 15)
this.ws = new WebSocket(this.getWebSocketRoot() + '/cert/issue/' + this.config.server_name this.ws = new WebSocket(this.getWebSocketRoot() + '/cert/issue/' + this.config.server_name
+ '?token=' + btoa(this.$store.state.user.token)) + '?token=' + btoa(this.$store.state.user.token))
@ -219,15 +217,15 @@ export default {
change_auto_cert() { change_auto_cert() {
if (this.config.auto_cert) { if (this.config.auto_cert) {
this.$api.domain.add_auto_cert(this.name).then(() => { this.$api.domain.add_auto_cert(this.name).then(() => {
this.$message.success(this.name + ' 加入自动续签列表成功') this.$message.success($interpolate($gettext('Auto-renewal enabled for %{name}', {name: this.name})))
}).catch(e => { }).catch(e => {
this.$message.error(e.message ?? this.name + ' 加入自动续签列表失败') this.$message.error(e.message ?? $interpolate($gettext('Enable auto-renewal failed for %{name}', {name: this.name})))
}) })
} else { } else {
this.$api.domain.remove_auto_cert(this.name).then(() => { this.$api.domain.remove_auto_cert(this.name).then(() => {
this.$message.success('从自动续签列表中删除 ' + this.name + ' 成功') this.$message.success($interpolate($gettext('Auto-renewal disabled for %{name}', {name: this.name})))
}).catch(e => { }).catch(e => {
this.$message.error(e.message ?? '从自动续签列表中删除 ' + this.name + ' 失败') this.$message.error(e.message ?? $interpolate($gettext('Disable auto-renewal failed for %{name}', {name: this.name})))
}) })
} }
} }

View file

@ -1,5 +1,5 @@
<template> <template>
<a-card title="网站管理"> <a-card :title="$gettext('Manage Sites')">
<std-table <std-table
:api="api" :api="api"
:columns="columns" :columns="columns"
@ -13,8 +13,8 @@
> >
<template #actions="{record}"> <template #actions="{record}">
<a-divider type="vertical"/> <a-divider type="vertical"/>
<a v-if="record.enabled" @click="disable(record.name)">禁用</a> <a v-if="record.enabled" @click="disable(record.name)" v-translate>Disabled</a>
<a v-else @click="enable(record.name)">启用</a> <a v-else @click="enable(record.name)" v-translate>Enabled</a>
</template> </template>
</std-table> </std-table>
</a-card> </a-card>
@ -22,33 +22,34 @@
<script> <script>
import StdTable from '@/components/StdDataDisplay/StdTable' import StdTable from '@/components/StdDataDisplay/StdTable'
import $gettext, {$interpolate} from "@/lib/translate/gettext";
const columns = [{ const columns = [{
title: '配置名称', title: $gettext('Name'),
dataIndex: 'name', dataIndex: 'name',
scopedSlots: {customRender: '名称'}, scopedSlots: {customRender: 'name'},
sorter: true, sorter: true,
pithy: true pithy: true
}, { }, {
title: '状态', title: $gettext('Status'),
dataIndex: 'enabled', dataIndex: 'enabled',
badge: true, badge: true,
scopedSlots: {customRender: 'enabled'}, scopedSlots: {customRender: 'enabled'},
mask: { mask: {
true: '启用', true: $gettext('Enabled'),
false: '未启用' false: $gettext('Disabled')
}, },
sorter: true, sorter: true,
pithy: true pithy: true
}, { }, {
title: '修改时间', title: $gettext('Updated at'),
dataIndex: 'modify', dataIndex: 'modify',
datetime: true, datetime: true,
scopedSlots: {customRender: 'modify'}, scopedSlots: {customRender: 'modify'},
sorter: true, sorter: true,
pithy: true pithy: true
}, { }, {
title: '操作', title: $gettext('Action'),
dataIndex: 'action', dataIndex: 'action',
scopedSlots: {customRender: 'action'} scopedSlots: {customRender: 'action'}
}] }]
@ -65,20 +66,20 @@ export default {
methods: { methods: {
enable(name) { enable(name) {
this.$api.domain.enable(name).then(() => { this.$api.domain.enable(name).then(() => {
this.$message.success('启用成功') this.$message.success($gettext('Enabled successfully'))
this.$refs.table.get_list() this.$refs.table.get_list()
}).catch(r => { }).catch(r => {
console.log(r) console.log(r)
this.$message.error('启用失败 ' + (r.message ?? ''), 10) this.$message.error($interpolate($gettext('Failed to enable %{msg}'), {msg: r.message ?? ''}), 10)
}) })
}, },
disable(name) { disable(name) {
this.$api.domain.disable(name).then(() => { this.$api.domain.disable(name).then(() => {
this.$message.success('禁用成功') this.$message.success($gettext('Disabled successfully'))
this.$refs.table.get_list() this.$refs.table.get_list()
}).catch(r => { }).catch(r => {
console.log(r) console.log(r)
this.$message.error('禁用失败') this.$message.error($interpolate($gettext('Failed to disable %{msg}'), {msg: r.message ?? ''}))
}) })
} }
} }

View file

@ -1,36 +1,38 @@
import $gettext from "@/lib/translate/gettext";
const columns = [{ const columns = [{
title: '配置文件名称', title: $gettext('Configuration Name'),
dataIndex: 'name', dataIndex: 'name',
edit: { edit: {
type: 'input' type: 'input'
} }
}, { }, {
title: '网站域名 (server_name)', title: $gettext('Server Names (server_name)'),
dataIndex: 'server_name', dataIndex: 'server_name',
edit: { edit: {
type: 'input' type: 'input'
} }
}, { }, {
title: '网站根目录 (root)', title: $gettext('Root Directory (root)'),
dataIndex: 'root', dataIndex: 'root',
edit: { edit: {
type: 'input' type: 'input'
} }
}, { }, {
title: '网站首页 (index)', title: $gettext('Index (index)'),
dataIndex: 'index', dataIndex: 'index',
edit: { edit: {
type: 'input' type: 'input'
} }
}, { }, {
title: 'http 监听端口', title: $gettext('HTTP Listen Port'),
dataIndex: 'http_listen_port', dataIndex: 'http_listen_port',
edit: { edit: {
type: 'number', type: 'number',
min: 80 min: 80
} }
}, { }, {
title: '支持 SSL', title: $gettext('Enable TLS'),
dataIndex: 'support_ssl', dataIndex: 'support_ssl',
edit: { edit: {
type: 'switch', type: 'switch',
@ -39,30 +41,30 @@ const columns = [{
}] }]
const columnsSSL = [{ const columnsSSL = [{
title: '自动续签', title: $gettext('Certificate Auto-renewal'),
dataIndex: 'auto_cert', dataIndex: 'auto_cert',
edit: { edit: {
type: 'switch', type: 'switch',
event: 'change_auto_cert' event: 'change_auto_cert'
}, },
description: '启用自动续签后,系统将会每小时检测一次该域名证书的信息,' + description: $gettext('The certificate for the domain will be checked every hour, ' +
'如果距离上次签发已超过1个月则将执行自动续签。' + 'and will be renewed if it has been more than 1 month since it was last issued.' +
'<br/>启用前先点击下方「自动申请 Let\'s Encrypt 证书」即可获得证书路径。' '<br/>If you do not have a certificate before, please click "Getting Certificate from Let\'s Encrypt" first.')
}, { }, {
title: 'https 监听端口', title: $gettext('HTTPS Listen Port'),
dataIndex: 'https_listen_port', dataIndex: 'https_listen_port',
edit: { edit: {
type: 'number', type: 'number',
min: 443 min: 443
} }
}, { }, {
title: 'SSL 证书路径 (ssl_certificate)', title: $gettext('Certificate Path (ssl_certificate)'),
dataIndex: 'ssl_certificate', dataIndex: 'ssl_certificate',
edit: { edit: {
type: 'input' type: 'input'
} }
}, { }, {
title: 'SSL 证书私钥路径 (ssl_certificate_key)', title: $gettext('Private Key Path (ssl_certificate_key)'),
dataIndex: 'ssl_certificate_key', dataIndex: 'ssl_certificate_key',
edit: { edit: {
type: 'input' type: 'input'

View file

@ -6,21 +6,23 @@
<h2>Nginx UI</h2> <h2>Nginx UI</h2>
<p>Yet another WebUI for Nginx</p> <p>Yet another WebUI for Nginx</p>
<p>Version: {{ version }} ({{ build_id }})</p> <p>Version: {{ version }} ({{ build_id }})</p>
<h3>项目组</h3> <h3 v-translate>Project Team</h3>
<p><a href="https://jackyu.cn/">@0xJacky</a></p> <p><a href="https://jackyu.cn/">@0xJacky</a></p>
<p><a href="https://blog.kugeek.com/">@Hintay</a></p> <p><a href="https://blog.kugeek.com/">@Hintay</a></p>
<h3>技术栈</h3> <h3 v-translate>Build with</h3>
<p>Go</p> <p>Go</p>
<p>Gin</p> <p>Gin</p>
<p>Vue</p> <p>Vue</p>
<p>Websocket</p> <p>Websocket</p>
<h3>开源协议</h3> <h3 v-translate translate-context="Project">License</h3>
<p>GNU General Public License v2.0</p> <p>GNU General Public License v2.0</p>
<p>Copyright © 2020 - {{ this_year }} Nginx UI </p> <p>Copyright © 2020 - {{ this_year }} Nginx UI </p>
</a-card> </a-card>
</template> </template>
<script> <script>
import $gettext from "@/lib/translate/gettext";
export default { export default {
name: 'About', name: 'About',
data() { data() {
@ -29,16 +31,9 @@ export default {
logo: require('@/assets/img/logo.png'), logo: require('@/assets/img/logo.png'),
this_year: date.getFullYear(), this_year: date.getFullYear(),
version: process.env.VUE_APP_VERSION, version: process.env.VUE_APP_VERSION,
build_id: process.env.VUE_APP_TOTAL_BUILD ?? '开发模式', build_id: process.env.VUE_APP_TOTAL_BUILD ?? $gettext('Development Mode'),
api_root: process.env.VUE_APP_API_ROOT api_root: process.env.VUE_APP_API_ROOT
} }
},
methods: {
async changeUserPower(power) {
await this.$store.dispatch('update_mock_user', {power: power})
await this.$api.user.info()
await this.$message.success('修改成功')
}
} }
} }
</script> </script>

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="wrapper"> <div class="wrapper">
<h1 class="title">{{ $route.meta.status_code ? $route.meta.status_code : 404 }}</h1> <h1 class="title">{{ $route.meta.status_code ? $route.meta.status_code : 404 }}</h1>
<p>{{ $route.meta.error ? $route.meta.error : '找不到文件' }}</p> <p>{{ $route.meta.error ? $route.meta.error : $gettext('File Not Found') }}</p>
</div> </div>
</template> </template>

View file

@ -1,18 +0,0 @@
<template>
<div class="home">
<img alt="Vue logo" src="../assets/img/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'Home',
components: {
HelloWorld
}
}
</script>

View file

@ -4,7 +4,7 @@
<h1>Nginx UI</h1> <h1>Nginx UI</h1>
</div> </div>
<a-form <a-form
id="components-form-demo-normal-login" id="components-form-install"
:form="form" :form="form"
class="login-form" class="login-form"
@submit="handleSubmit" @submit="handleSubmit"
@ -15,14 +15,14 @@
'email', 'email',
{ rules: [{ { rules: [{
type: 'email', type: 'email',
message: 'The input is not valid E-mail!', message: $gettext('Invalid E-mail!'),
}, },
{ {
required: true, required: true,
message: 'Please input your E-mail!', message: $gettext('Please input your E-mail!'),
},] }, },] },
]" ]"
placeholder="Email (*)" :placeholder="$gettext('Email (*)')"
> >
<a-icon slot="prefix" type="mail" style="color: rgba(0,0,0,.25)"/> <a-icon slot="prefix" type="mail" style="color: rgba(0,0,0,.25)"/>
</a-input> </a-input>
@ -31,9 +31,9 @@
<a-input <a-input
v-decorator="[ v-decorator="[
'username', 'username',
{ rules: [{ required: true, message: 'Please input your username!' }] }, { rules: [{ required: true, message: $gettext('Please input your username!') }] },
]" ]"
placeholder="Username (*)" :placeholder="$gettext('Username (*)')"
> >
<a-icon slot="prefix" type="user" style="color: rgba(0,0,0,.25)"/> <a-icon slot="prefix" type="user" style="color: rgba(0,0,0,.25)"/>
</a-input> </a-input>
@ -42,10 +42,10 @@
<a-input <a-input
v-decorator="[ v-decorator="[
'password', 'password',
{ rules: [{ required: true, message: 'Please input your Password!' }] }, { rules: [{ required: true, message: $gettext('Please input your password!') }] },
]" ]"
type="password" type="password"
placeholder="Password (*)" :placeholder="$gettext('Password (*)')"
> >
<a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)"/> <a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)"/>
</a-input> </a-input>
@ -54,16 +54,20 @@
<a-input <a-input
v-decorator="[ v-decorator="[
'database', 'database',
{ rules: [{ pattern: /^[^\\/:*?\x22<>|]{1,120}$/, message: 'Please input a legal file name!'}] }, { rules: [{ pattern: /^[^\\/:*?\x22<>|]{1,120}$/,
message: $gettextInterpolate(
$gettext('The filename cannot contain the following characters: %{c}'),
{c: '& &quot; ? < > # {} % ~ / \\'}
)}] },
]" ]"
placeholder="Database (Optional, default: database)" :placeholder="$gettext('Database (Optional, default: database)')"
> >
<a-icon slot="prefix" type="database" style="color: rgba(0,0,0,.25)"/> <a-icon slot="prefix" type="database" style="color: rgba(0,0,0,.25)"/>
</a-input> </a-input>
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<a-button type="primary" :block="true" html-type="submit" :loading="loading"> <a-button type="primary" :block="true" html-type="submit" :loading="loading" v-translate>
安装 Install
</a-button> </a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>

View file

@ -13,9 +13,9 @@
<a-input <a-input
v-decorator="[ v-decorator="[
'name', 'name',
{ rules: [{ required: true, message: '请输入用户名' }] }, { rules: [{ required: true, message: $gettext('Please input your username!') }] },
]" ]"
placeholder="Username" :placeholder="$gettext('Username')"
> >
<a-icon slot="prefix" type="user" style="color: rgba(0,0,0,.25)"/> <a-icon slot="prefix" type="user" style="color: rgba(0,0,0,.25)"/>
</a-input> </a-input>
@ -24,17 +24,17 @@
<a-input <a-input
v-decorator="[ v-decorator="[
'password', 'password',
{ rules: [{ required: true, message: '请输入密码' }] }, { rules: [{ required: true, message: $gettext('Please input your password!') }] },
]" ]"
type="password" type="password"
placeholder="Password" :placeholder="$gettext('Password')"
> >
<a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)"/> <a-icon slot="prefix" type="lock" style="color: rgba(0,0,0,.25)"/>
</a-input> </a-input>
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<a-button type="primary" :block="true" html-type="submit" :loading="loading"> <a-button type="primary" :block="true" html-type="submit" :loading="loading" v-translate>
登录 Login
</a-button> </a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>
@ -46,6 +46,8 @@
</template> </template>
<script> <script>
import $gettext from "@/lib/translate/gettext";
export default { export default {
name: 'Login', name: 'Login',
data() { data() {
@ -71,12 +73,12 @@ export default {
methods: { methods: {
login(values) { login(values) {
return this.$api.auth.login(values.name, values.password).then(async () => { return this.$api.auth.login(values.name, values.password).then(async () => {
await this.$message.success('登录成功', 1) await this.$message.success($gettext('Login successful'), 1)
const next = this.$route.query.next ? this.$route.query.next : '/' const next = this.$route.query.next ? this.$route.query.next : '/'
await this.$router.push(next) await this.$router.push(next)
}).catch(r => { }).catch(r => {
console.log(r) console.log(r)
this.$message.error(r.message ?? '服务器错误') this.$message.error(r.message ?? $gettext('Server error'))
}) })
}, },
handleSubmit: async function (e) { handleSubmit: async function (e) {

View file

@ -5,9 +5,10 @@
<script> <script>
import StdCurd from '@/components/StdDataDisplay/StdCurd' import StdCurd from '@/components/StdDataDisplay/StdCurd'
import $gettext from "@/lib/translate/gettext";
const columns = [{ const columns = [{
title: '用户名', title: $gettext('Username'),
dataIndex: 'name', dataIndex: 'name',
sorter: true, sorter: true,
pithy: true, pithy: true,
@ -15,29 +16,29 @@ const columns = [{
type: 'input' type: 'input'
} }
}, { }, {
title: '密码', title: $gettext('Password'),
dataIndex: 'password', dataIndex: 'password',
sorter: true, sorter: true,
pithy: true, pithy: true,
edit: { edit: {
type: 'input', type: 'input',
placeholder: '留空不修改' placeholder: $gettext('Leave blank for no change')
}, },
display: false display: false
}, { }, {
title: '创建时间', title: $gettext('Created at'),
dataIndex: 'created_at', dataIndex: 'created_at',
datetime: true, datetime: true,
sorter: true, sorter: true,
pithy: true pithy: true
}, { }, {
title: '修改时间', title: $gettext('Updated at'),
dataIndex: 'updated_at', dataIndex: 'updated_at',
datetime: true, datetime: true,
sorter: true, sorter: true,
pithy: true pithy: true
}, { }, {
title: '操作', title: $gettext('Action'),
dataIndex: 'action' dataIndex: 'action'
}] }]

View file

@ -1 +1 @@
{"version":"1.1.0","build_id":9,"total_build":26} {"version":"1.1.0","build_id":22,"total_build":39}

2
go.mod
View file

@ -3,6 +3,7 @@ module github.com/0xJacky/Nginx-UI
go 1.17 go 1.17
require ( require (
github.com/0xJacky/pofile v0.0.1
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/dustin/go-humanize v1.0.0 github.com/dustin/go-humanize v1.0.0
github.com/gin-contrib/static v0.0.1 github.com/gin-contrib/static v0.0.1
@ -23,7 +24,6 @@ require (
) )
require ( require (
github.com/0xJacky/pofile v0.0.1 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect github.com/StackExchange/wmi v1.2.1 // indirect
github.com/cenkalti/backoff/v4 v4.1.0 // indirect github.com/cenkalti/backoff/v4 v4.1.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect

4
go.sum
View file

@ -23,10 +23,6 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/0xJacky/pofile v0.0.0-20220216140954-bc565a3feb80 h1:qKPxkbGoP/vVxN1Vgd964oJBlhGwhrCAKiheoieOPhc=
github.com/0xJacky/pofile v0.0.0-20220216140954-bc565a3feb80/go.mod h1:gSDWobvodMtvwh7FE/F999AQoCwBoXgzyGffYFX9nKA=
github.com/0xJacky/pofile v0.0.0-20220219022008-df96416310e5 h1:NEsbh2Wez8+0Y72hbVQPPhyIkmc1RAgWOWbcISRUxEs=
github.com/0xJacky/pofile v0.0.0-20220219022008-df96416310e5/go.mod h1:gSDWobvodMtvwh7FE/F999AQoCwBoXgzyGffYFX9nKA=
github.com/0xJacky/pofile v0.0.0-20220219101524-60ce48e4de23 h1:nqaxj4ZYzLZzhFQeX1ZrXEBz0haUu7PypGFhQbQfDX0= github.com/0xJacky/pofile v0.0.0-20220219101524-60ce48e4de23 h1:nqaxj4ZYzLZzhFQeX1ZrXEBz0haUu7PypGFhQbQfDX0=
github.com/0xJacky/pofile v0.0.0-20220219101524-60ce48e4de23/go.mod h1:gSDWobvodMtvwh7FE/F999AQoCwBoXgzyGffYFX9nKA= github.com/0xJacky/pofile v0.0.0-20220219101524-60ce48e4de23/go.mod h1:gSDWobvodMtvwh7FE/F999AQoCwBoXgzyGffYFX9nKA=
github.com/0xJacky/pofile v0.0.1 h1:hVRaw6ZHkajSMAuP58WMDTvGF8+OF297jpAchFK/4rQ= github.com/0xJacky/pofile v0.0.1 h1:hVRaw6ZHkajSMAuP58WMDTvGF8+OF297jpAchFK/4rQ=

View file

@ -33,9 +33,9 @@ func main() {
log.Printf("nginx config dir path: %s", tool2.GetNginxConfPath("")) log.Printf("nginx config dir path: %s", tool2.GetNginxConfPath(""))
if "" != settings.ServerSettings.JwtSecret { if "" != settings.ServerSettings.JwtSecret {
model.Init() model.Init()
frontend.InitTranslations()
go tool2.AutoCert() go tool2.AutoCert()
} }
frontend.InitTranslations()
srv := &http.Server{ srv := &http.Server{
Addr: ":" + settings.ServerSettings.HttpPort, Addr: ":" + settings.ServerSettings.HttpPort,