diff --git a/web/assets/js/model/inbound.js b/web/assets/js/model/inbound.js
index 2a5fb6d6..5228001c 100644
--- a/web/assets/js/model/inbound.js
+++ b/web/assets/js/model/inbound.js
@@ -2150,7 +2150,7 @@ Inbound.TrojanSettings.Fallback = class extends XrayCommonClass {
Inbound.ShadowsocksSettings = class extends Inbound.Settings {
constructor(protocol,
method = SSMethods.BLAKE3_AES_256_GCM,
- password = RandomUtil.randomShadowsocksPassword(),
+ password = '',
network = 'tcp,udp',
shadowsockses = [new Inbound.ShadowsocksSettings.Shadowsocks()],
ivCheck = false,
@@ -2188,7 +2188,7 @@ Inbound.ShadowsocksSettings = class extends Inbound.Settings {
Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass {
constructor(
method = '',
- password = RandomUtil.randomShadowsocksPassword(),
+ password = '',
email = RandomUtil.randomLowerAndNum(8),
limitIp = 0,
totalGB = 0,
diff --git a/web/assets/js/util/index.js b/web/assets/js/util/index.js
index 0d869af6..4bf760d7 100644
--- a/web/assets/js/util/index.js
+++ b/web/assets/js/util/index.js
@@ -138,8 +138,14 @@ class RandomUtil {
}
}
- static randomShadowsocksPassword() {
- const array = new Uint8Array(32);
+ static randomShadowsocksPassword(method = SSMethods.BLAKE3_AES_256_GCM) {
+ let length = 32;
+
+ if ([SSMethods.BLAKE3_AES_128_GCM].includes(method)) {
+ length = 16;
+ }
+
+ const array = new Uint8Array(length);
window.crypto.getRandomValues(array);
@@ -789,6 +795,25 @@ class LanguageManager {
if (window.navigator) {
lang = window.navigator.language || window.navigator.userLanguage;
+ const simularLangs = [
+ ["ar", this.supportedLanguages[0].value],
+ ["fa", this.supportedLanguages[2].value],
+ ["ja", this.supportedLanguages[5].value],
+ ["ru", this.supportedLanguages[6].value],
+ ["vi", this.supportedLanguages[7].value],
+ ["es", this.supportedLanguages[8].value],
+ ["id", this.supportedLanguages[9].value],
+ ["uk", this.supportedLanguages[10].value],
+ ["tr", this.supportedLanguages[11].value],
+ ["pt", this.supportedLanguages[12].value],
+ ]
+
+ simularLangs.forEach((pair) => {
+ if (lang === pair[0]) {
+ lang = pair[1];
+ }
+ });
+
if (LanguageManager.isSupportLanguage(lang)) {
CookieManager.setCookie("lang", lang, 150);
} else {
diff --git a/web/html/common/head.html b/web/html/common/head.html
deleted file mode 100644
index 35901769..00000000
--- a/web/html/common/head.html
+++ /dev/null
@@ -1,31 +0,0 @@
-{{define "head"}}
-
-
-
-
-
-
-
-
- {{ .host }} – {{ i18n .title}}
-
-
-{{end}}
\ No newline at end of file
diff --git a/web/html/common/js.html b/web/html/common/js.html
deleted file mode 100644
index 1c2d64b3..00000000
--- a/web/html/common/js.html
+++ /dev/null
@@ -1,14 +0,0 @@
-{{define "js"}}
-
-
-
-
-
-
-
-
-
-{{end}}
\ No newline at end of file
diff --git a/web/html/common/page.html b/web/html/common/page.html
new file mode 100644
index 00000000..f1c58fe1
--- /dev/null
+++ b/web/html/common/page.html
@@ -0,0 +1,58 @@
+{{ define "page/head_start" }}
+
+
+
+
+
+
+
+
+
+
+ {{ .host }} – {{ i18n .title}}
+{{ end }}
+
+{{ define "page/head_end" }}
+
+{{ end }}
+
+{{ define "page/body_start" }}
+
+
+{{ end }}
+
+{{ define "page/body_scripts" }}
+
+
+
+
+
+
+
+
+
+{{ end }}
+
+{{ define "page/body_end" }}
+
+
+{{ end }}
\ No newline at end of file
diff --git a/web/html/component/aClientTable.html b/web/html/component/aClientTable.html
index 868112d9..96bd502f 100644
--- a/web/html/component/aClientTable.html
+++ b/web/html/component/aClientTable.html
@@ -41,14 +41,28 @@
-
-
- {{ i18n "depleted" }}
- {{ i18n "disabled" }}
- {{ i18n "online" }}
-
-
- [[ client.email ]]
+
+
+
+ {{ i18n "depleted" }}
+ {{ i18n "disabled" }}
+ {{ i18n "online" }}
+
+
+
+
+ [[ client.email ]]
+
+
+
+ [[ client.comment ]]
+
+
+
+
+
+
+
diff --git a/web/html/form/client.html b/web/html/form/client.html
index c67f1470..846bbd13 100644
--- a/web/html/form/client.html
+++ b/web/html/form/client.html
@@ -22,7 +22,7 @@
{{ i18n "reset" }}
{{ i18n "password" }}
-
+
diff --git a/web/html/form/protocol/shadowsocks.html b/web/html/form/protocol/shadowsocks.html
index b9813afb..06e12075 100644
--- a/web/html/form/protocol/shadowsocks.html
+++ b/web/html/form/protocol/shadowsocks.html
@@ -31,7 +31,7 @@
{{ i18n "reset" }}
- Password
+ Password
diff --git a/web/html/inbounds.html b/web/html/inbounds.html
index 29e6b00f..e1267190 100644
--- a/web/html/inbounds.html
+++ b/web/html/inbounds.html
@@ -1,6 +1,4 @@
-
-
-{{template "head" .}}
+{{ template "page/head_start" .}}
+{{ template "page/head_end" .}}
-
+{{ template "page/body_start" .}}
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[[ total.clients ]]
-
-
- [[ clientEmail ]]
-
- [[ total.deactive.length ]]
-
-
-
- [[ clientEmail ]]
-
- [[ total.depleted.length ]]
-
-
-
- [[ clientEmail ]]
-
- [[ total.expiring.length ]]
-
-
-
- [[ clientEmail ]]
-
- [[ onlineClients.length ]]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.inbounds.addInbound" }}
-
-
-
- {{ i18n "pages.inbounds.generalActions" }}
-
- generalActions(a)" :theme="themeSwitcher.currentTheme">
-
-
- {{ i18n "pages.inbounds.importInbound" }}
-
-
-
- {{ i18n "pages.inbounds.export" }}
-
-
-
- {{ i18n "pages.inbounds.export" }} - {{ i18n "pages.settings.subSettings" }}
-
-
-
- {{ i18n "pages.inbounds.resetAllTraffic" }}
-
-
-
- {{ i18n "pages.inbounds.resetAllClientTraffics" }}
-
-
-
- {{ i18n "pages.inbounds.delDepletedClients" }}
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ i18n "pages.inbounds.autoRefresh" }}
-
-
-
-
- {{ i18n "pages.inbounds.autoRefreshInterval" }}
-
- [[ key ]]s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ i18n "none" }}
- {{ i18n "disabled" }}
- {{ i18n "depleted" }}
- {{ i18n "depletingSoon" }}
- {{ i18n "online" }}
-
-
-
-
-
- e.preventDefault()" type="more" :style="{ fontSize: '20px', textDecoration: 'solid' }">
- clickAction(a, dbInbound)" :theme="themeSwitcher.currentTheme">
-
-
- {{ i18n "edit" }}
-
-
-
- {{ i18n "qrCode" }}
-
-
-
-
- {{ i18n "pages.client.add"}}
-
-
-
- {{ i18n "pages.client.bulk"}}
-
-
-
- {{ i18n "pages.inbounds.resetInboundClientTraffics"}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[[ total.clients ]]
+
+
+ [[ clientEmail ]]
+
+ [[ total.deactive.length ]]
+
+
+
+ [[ clientEmail ]]
+
+ [[ total.depleted.length ]]
+
+
+
+ [[ clientEmail ]]
+
+ [[ total.expiring.length ]]
+
+
+
+ [[ clientEmail ]]
+
+ [[ onlineClients.length ]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ i18n "pages.inbounds.addInbound" }}
+
+
+
+ {{ i18n "pages.inbounds.generalActions" }}
+
+ generalActions(a)" :theme="themeSwitcher.currentTheme">
+
+
+ {{ i18n "pages.inbounds.importInbound" }}
- {{ i18n "pages.inbounds.export"}}
+ {{ i18n "pages.inbounds.export" }}
- {{ i18n "pages.inbounds.export"}} - {{ i18n "pages.settings.subSettings" }}
+ {{ i18n "pages.inbounds.export" }} - {{ i18n "pages.settings.subSettings" }}
+
+
+
+ {{ i18n "pages.inbounds.resetAllTraffic" }}
+
+
+
+ {{ i18n "pages.inbounds.resetAllClientTraffics" }}
{{ i18n "pages.inbounds.delDepletedClients" }}
-
-
-
-
- {{ i18n "info"}}
-
-
-
-
- {{ i18n "pages.inbounds.exportInbound" }}
-
-
- {{ i18n "pages.inbounds.resetTraffic" }}
-
-
- {{ i18n "pages.inbounds.clone"}}
-
-
-
- {{ i18n "delete"}}
-
-
-
-
- {{ i18n "pages.inbounds.enable" }}
-
-
-
+
+
+
-
- [[ dbInbound.protocol ]]
-
- [[ dbInbound.toInbound().stream.network ]]
- TLS
- Reality
-
+
+
+
+
+
+
+
+
{{ i18n "pages.inbounds.autoRefresh" }}
+
+
+
+
+ {{ i18n "pages.inbounds.autoRefreshInterval" }}
+
+ [[ key ]]s
+
+
+
+
+
+
-
-
- [[ clientCount[dbInbound.id].clients ]]
-
-
- [[ clientEmail ]]
-
- [[ clientCount[dbInbound.id].deactive.length ]]
-
-
-
- [[ clientEmail ]]
-
- [[ clientCount[dbInbound.id].depleted.length ]]
-
-
-
- [[ clientEmail ]]
-
- [[ clientCount[dbInbound.id].expiring.length ]]
-
-
-
- [[ clientEmail ]]
-
- [[ clientCount[dbInbound.id].online.length ]]
-
-
-
-
-
-
-
-
- ↑[[ SizeFormatter.sizeFormat(dbInbound.up) ]] |
- ↓[[ SizeFormatter.sizeFormat(dbInbound.down) ]] |
-
-
- {{ i18n "remained" }} |
- [[ SizeFormatter.sizeFormat(dbInbound.total - dbInbound.up - dbInbound.down) ]] |
-
-
+
+
+
+
+
+
+
+
+ {{ i18n "none" }}
+ {{ i18n "disabled" }}
+ {{ i18n "depleted" }}
+ {{ i18n "depletingSoon" }}
+ {{ i18n "online" }}
+
+
+
+
+
+ e.preventDefault()" type="more" :style="{ fontSize: '20px', textDecoration: 'solid' }">
+ clickAction(a, dbInbound)" :theme="themeSwitcher.currentTheme">
+
+
+ {{ i18n "edit" }}
+
+
+
+ {{ i18n "qrCode" }}
+
+
+
+
+ {{ i18n "pages.client.add"}}
+
+
+
+ {{ i18n "pages.client.bulk"}}
+
+
+
+ {{ i18n "pages.inbounds.resetInboundClientTraffics"}}
+
+
+
+ {{ i18n "pages.inbounds.export"}}
+
+
+
+ {{ i18n "pages.inbounds.export"}} - {{ i18n "pages.settings.subSettings" }}
+
+
+
+ {{ i18n "pages.inbounds.delDepletedClients" }}
+
+
+
+
+
+ {{ i18n "info"}}
+
+
+
+
+ {{ i18n "pages.inbounds.exportInbound" }}
+
+
+ {{ i18n "pages.inbounds.resetTraffic" }}
+
+
+ {{ i18n "pages.inbounds.clone"}}
+
+
+
+ {{ i18n "delete"}}
+
+
+
+
+ {{ i18n "pages.inbounds.enable" }}
+
+
+
-
- [[ SizeFormatter.sizeFormat(dbInbound.up + dbInbound.down) ]] /
-
- [[ SizeFormatter.sizeFormat(dbInbound.total) ]]
+
+ [[ dbInbound.protocol ]]
+
+ [[ dbInbound.toInbound().stream.network ]]
+ TLS
+ Reality
-
+
+
+
+ [[ clientCount[dbInbound.id].clients ]]
+
+
+
+
+ [[ clientCount[dbInbound.id].deactive.length ]]
+
+
+
+
+
+ [[ clientCount[dbInbound.id].depleted.length ]]
+
+
+
+
+
+ [[ clientCount[dbInbound.id].expiring.length ]]
+
+
+
+
+
+ [[ clientCount[dbInbound.id].online.length ]]
+
+
+
+
+
+
+
+
+ ↑[[ SizeFormatter.sizeFormat(dbInbound.up) ]] |
+ ↓[[ SizeFormatter.sizeFormat(dbInbound.down) ]] |
+
+
+ {{ i18n "remained" }} |
+ [[ SizeFormatter.sizeFormat(dbInbound.total - dbInbound.up - dbInbound.down) ]] |
+
+
+
+
+ [[ SizeFormatter.sizeFormat(dbInbound.up + dbInbound.down) ]] /
+
+ [[ SizeFormatter.sizeFormat(dbInbound.total) ]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[ DateUtil.formatMillis(dbInbound.expiryTime) ]]
+
+
+ [[ DateUtil.convertToJalalian(moment(dbInbound.expiryTime)) ]]
+
+
+ [[ remainedDays(dbInbound._expiryTime) ]]
+
+
+
-
-
-
-
-
-
-
-
-
-
- [[ DateUtil.formatMillis(dbInbound.expiryTime) ]]
+
-
- [[ DateUtil.convertToJalalian(moment(dbInbound.expiryTime)) ]]
-
-
- [[ remainedDays(dbInbound._expiryTime) ]]
-
-
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.inbounds.protocol" }} |
-
- [[ dbInbound.protocol ]]
-
- [[ dbInbound.toInbound().stream.network ]]
- tls
- reality
-
- |
-
-
- {{ i18n "pages.inbounds.port" }} |
- [[ dbInbound.port ]] |
-
-
- {{ i18n "clients" }} |
-
- [[ clientCount[dbInbound.id].clients ]]
-
-
- [[ clientEmail ]]
-
- [[ clientCount[dbInbound.id].deactive.length ]]
-
-
-
- [[ clientEmail ]]
-
- [[ clientCount[dbInbound.id].depleted.length ]]
-
-
-
- [[ clientEmail ]]
-
- [[ clientCount[dbInbound.id].expiring.length ]]
-
-
-
- [[ clientEmail ]]
-
- [[ clientCount[dbInbound.id].online.length ]]
-
- |
-
-
- {{ i18n "pages.inbounds.traffic" }} |
-
-
-
-
-
- ↑[[ SizeFormatter.sizeFormat(dbInbound.up) ]] |
- ↓[[ SizeFormatter.sizeFormat(dbInbound.down) ]] |
-
-
- {{ i18n "remained" }} |
- [[ SizeFormatter.sizeFormat(dbInbound.total - dbInbound.up - dbInbound.down) ]] |
-
-
-
-
- [[ SizeFormatter.sizeFormat(dbInbound.up + dbInbound.down) ]] /
-
- [[ SizeFormatter.sizeFormat(dbInbound.total) ]]
+
+
+
+
+
+ {{ i18n "pages.inbounds.protocol" }} |
+
+ [[ dbInbound.protocol ]]
+
+ [[ dbInbound.toInbound().stream.network ]]
+ tls
+ reality
+
+ |
+
+
+ {{ i18n "pages.inbounds.port" }} |
+ [[ dbInbound.port ]] |
+
+
+ {{ i18n "clients" }} |
+
+ [[ clientCount[dbInbound.id].clients ]]
+
+
+
-
+ [[ clientCount[dbInbound.id].deactive.length ]]
+
+
+
+
+
+ [[ clientCount[dbInbound.id].depleted.length ]]
+
+
+
+
+
+ [[ clientCount[dbInbound.id].expiring.length ]]
+
+
+
+
+
+ [[ clientCount[dbInbound.id].online.length ]]
+
+ |
+
+
+ {{ i18n "pages.inbounds.traffic" }} |
+
+
+
+
+
+ ↑[[ SizeFormatter.sizeFormat(dbInbound.up) ]] |
+ ↓[[ SizeFormatter.sizeFormat(dbInbound.down) ]] |
+
+
+ {{ i18n "remained" }} |
+ [[ SizeFormatter.sizeFormat(dbInbound.total - dbInbound.up - dbInbound.down) ]] |
+
+
+
+
+ [[ SizeFormatter.sizeFormat(dbInbound.up + dbInbound.down) ]] /
+
+ [[ SizeFormatter.sizeFormat(dbInbound.total) ]]
+
+
+
+
+
+
+ |
+
+
+ {{ i18n "pages.inbounds.expireDate" }} |
+
+
+
+ [[ DateUtil.formatMillis(dbInbound.expiryTime) ]]
+
+
+ [[ DateUtil.convertToJalalian(moment(dbInbound.expiryTime)) ]]
+
+
+
-
-
-
- |
-
-
- {{ i18n "pages.inbounds.expireDate" }} |
-
-
-
- [[ DateUtil.formatMillis(dbInbound.expiryTime) ]]
-
-
- [[ DateUtil.convertToJalalian(moment(dbInbound.expiryTime)) ]]
-
-
-
-
-
- |
-
-
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{template "component/aClientTable"}}
+
-
-
-
-
-
-
-
-
-
-
- {{template "component/aClientTable"}}
-
-
-
-
+
+
+
+
-{{template "js" .}}
+{{template "page/body_scripts" .}}
@@ -589,6 +674,13 @@
{{template "component/aThemeSwitch" .}}
{{template "component/aCustomStatistic" .}}
{{template "component/aPersianDatepicker" .}}
+{{template "modals/inboundModal"}}
+{{template "modals/promptModal"}}
+{{template "modals/qrcodeModal"}}
+{{template "modals/textModal"}}
+{{template "modals/inboundInfoModal"}}
+{{template "modals/clientsModal"}}
+{{template "modals/clientsBulkModal"}}
-
-{{template "modals/inboundModal"}}
-{{template "modals/promptModal"}}
-{{template "modals/qrcodeModal"}}
-{{template "modals/textModal"}}
-{{template "modals/inboundInfoModal"}}
-{{template "modals/clientsModal"}}
-{{template "modals/clientsBulkModal"}}
-
-
+{{ template "page/body_end" .}}
\ No newline at end of file
diff --git a/web/html/index.html b/web/html/index.html
index 2a6fb0ad..db678cd6 100644
--- a/web/html/index.html
+++ b/web/html/index.html
@@ -1,20 +1,9 @@
-
-
-{{template "head" .}}
+{{ template "page/head_start" .}}
+{{ template "page/head_end" .}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+{{ template "page/body_start" .}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ i18n "pages.index.cpu" }}: [[ CPUFormatter.cpuCoreFormat(status.cpuCores) ]]
+
+
+
+ {{ i18n "pages.index.logicalProcessors" }}: [[ (status.logicalPro) ]]
+ {{ i18n "pages.index.frequency" }}: [[ CPUFormatter.cpuSpeedFormat(status.cpuSpeedMhz) ]]
+
+
+
+
+
+
+
+ {{ i18n "pages.index.memory"}}: [[ SizeFormatter.sizeFormat(status.mem.current) ]] / [[ SizeFormatter.sizeFormat(status.mem.total) ]]
+
+
+
+
+
+
+
+
+
+ {{ i18n "pages.index.swap" }}: [[ SizeFormatter.sizeFormat(status.swap.current) ]] / [[ SizeFormatter.sizeFormat(status.swap.total) ]]
+
+
+
+
+
+ {{ i18n "pages.index.storage"}}: [[ SizeFormatter.sizeFormat(status.disk.current) ]] / [[ SizeFormatter.sizeFormat(status.disk.total) ]]
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
{{ i18n "pages.index.cpu" }}: [[ CPUFormatter.cpuCoreFormat(status.cpuCores) ]]
-
-
-
- {{ i18n "pages.index.logicalProcessors" }}: [[ (status.logicalPro) ]]
- {{ i18n "pages.index.frequency" }}: [[ CPUFormatter.cpuSpeedFormat(status.cpuSpeedMhz) ]]
-
-
-
-
-
-
-
- {{ i18n "pages.index.memory"}}: [[ SizeFormatter.sizeFormat(status.mem.current) ]] / [[ SizeFormatter.sizeFormat(status.mem.total) ]]
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.index.swap" }}: [[ SizeFormatter.sizeFormat(status.swap.current) ]] / [[ SizeFormatter.sizeFormat(status.swap.total) ]]
-
-
-
-
-
- {{ i18n "pages.index.storage"}}: [[ SizeFormatter.sizeFormat(status.disk.current) ]] / [[ SizeFormatter.sizeFormat(status.disk.total) ]]
-
-
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.index.xrayStatus" }}
-
- v[[ status.xray.version ]]
-
-
+
+
+
+
+
+ {{ i18n "pages.index.xrayStatus" }}
+
+ v[[ status.xray.version ]]
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.index.xrayErrorPopoverTitle" }}
-
-
-
-
-
-
-
- [[ line ]]
-
-
-
-
-
-
-
-
- {{ i18n "pages.index.stopXray" }}
-
-
-
- {{ i18n "pages.index.restartXray" }}
-
-
-
-
- [[ status.xray.version != 'Unknown' ? `v${status.xray.version}` : '{{ i18n "pages.index.xraySwitch" }}' ]]
+
+
+
+
+
+ {{ i18n "pages.index.xrayErrorPopoverTitle" }}
+
+
+
+
+
-
+
+ [[ line ]]
+
+
+
-
-
-
-
-
-
-
- {{ i18n "pages.index.logs" }}
-
-
-
- {{ i18n "pages.index.config" }}
-
-
-
- {{ i18n "pages.index.backup" }}
-
-
-
-
-
-
-
-
- v{{ .cur_ver }}
-
-
-
-
- @XrayUI
-
-
-
-
- {{ i18n "pages.index.documentation" }}
-
-
-
-
-
-
- Xray: [[ TimeFormatter.formatSecond(status.appStats.uptime) ]]
- OS: [[ TimeFormatter.formatSecond(status.uptime) ]]
-
-
-
-
+
+
+
+
+ {{ i18n "pages.index.stopXray" }}
+
+
+
+ {{ i18n "pages.index.restartXray" }}
+
+
+
+
+ [[ status.xray.version != 'Unknown' ? `v${status.xray.version}` : '{{ i18n "pages.index.xraySwitch" }}' ]]
+
+
+
+
+
+
+
+
+
+
+ {{ i18n "pages.index.logs" }}
+
+
+
+ {{ i18n "pages.index.config" }}
+
+
+
+ {{ i18n "pages.index.backup" }}
+
+
+
+
+
+
+
-
- [[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
-
- {{ i18n "pages.index.systemLoadDesc" }}
-
-
+ v{{ .cur_ver }}
-
-
-
-
- {{ i18n "pages.index.memory" }}: [[ SizeFormatter.sizeFormat(status.appStats.mem) ]]
- {{ i18n "pages.index.threads" }}: [[ status.appStats.threads ]]
-
-
-
-
-
-
-
-
-
-
-
- /s
-
-
-
-
-
-
-
-
-
- /s
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.index.toggleIpVisibility" }}
+
+
+
+ @XrayUI
+
+
+
+
+ {{ i18n "pages.index.documentation" }}
+
+
+
+
+
+
+ Xray: [[ TimeFormatter.formatSecond(status.appStats.uptime) ]]
+ OS: [[ TimeFormatter.formatSecond(status.uptime) ]]
+
+
+
+
+
+
+ [[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
+
+ {{ i18n "pages.index.systemLoadDesc" }}
+
+
+
+
+
+
+
+ {{ i18n "pages.index.memory" }}: [[ SizeFormatter.sizeFormat(status.appStats.mem) ]]
+ {{ i18n "pages.index.threads" }}: [[ status.appStats.threads ]]
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- versionModal.visible = false" :class="themeSwitcher.currentTheme" footer="">
-
-
-
-
-
- [[ version ]]
-
-
-
-
-
-
-
- [[ file ]]
-
-
-
-
-
-
- logModal.visible = false"
- :class="themeSwitcher.currentTheme"
- width="800px" footer="">
-
- {{ i18n "pages.index.logs" }}
-
-
-
-
-
-
-
- 10
- 20
- 50
- 100
- 500
-
-
- Debug
- Info
- Notice
- Warning
- Error
-
-
-
-
- SysLog
-
-
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.index.exportDatabase" }}
- {{ i18n "pages.index.exportDatabaseDesc" }}
-
-
-
-
-
- {{ i18n "pages.index.importDatabase" }}
- {{ i18n "pages.index.importDatabaseDesc" }}
-
-
-
-
-
+
+ /s
+
+
+
+
+
+
+
+
+
+ /s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ i18n "pages.index.toggleIpVisibility" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-{{template "js" .}}
+ versionModal.visible = false" :class="themeSwitcher.currentTheme" footer="">
+
+
+
+
+
+ [[ version ]]
+
+
+
+
+
+
+
+ [[ file ]]
+
+
+
+
+
+
+ logModal.visible = false"
+ :class="themeSwitcher.currentTheme"
+ width="800px" footer="">
+
+ {{ i18n "pages.index.logs" }}
+
+
+
+
+
+
+
+ 10
+ 20
+ 50
+ 100
+ 500
+
+
+ Debug
+ Info
+ Notice
+ Warning
+ Error
+
+
+
+
+ SysLog
+
+
+
+
+
+
+
+
+
+
+
+ {{ i18n "pages.index.exportDatabase" }}
+ {{ i18n "pages.index.exportDatabaseDesc" }}
+
+
+
+
+
+ {{ i18n "pages.index.importDatabase" }}
+ {{ i18n "pages.index.importDatabaseDesc" }}
+
+
+
+
+
+
+{{template "page/body_scripts" .}}
{{template "component/aSidebar" .}}
{{template "component/aThemeSwitch" .}}
{{template "component/aCustomStatistic" .}}
@@ -489,7 +479,7 @@
}
class Status {
- constructor(data, isLoaded = false) {
+ constructor(data) {
this.cpu = new CurTotal(0, 0);
this.cpuCores = 0;
this.logicalPro = 0;
@@ -513,7 +503,6 @@
return;
}
- this.isLoaded = isLoaded;
this.cpu = new CurTotal(data.cpu, 100);
this.cpuCores = data.cpuCores;
this.logicalPro = data.logicalPro;
@@ -633,32 +622,39 @@
mixins: [MediaQueryMixin],
data: {
themeSwitcher,
+ loadingStates: {
+ fetched: false,
+ spinning: false
+ },
status: new Status(),
versionModal,
logModal,
backupModal,
- spinning: false,
loadingTip: '{{ i18n "loading"}}',
showAlert: false,
showIp: false
},
methods: {
loading(spinning, tip = '{{ i18n "loading"}}') {
- this.spinning = spinning;
+ this.loadingStates.spinning = spinning;
this.loadingTip = tip;
},
async getStatus() {
try {
const msg = await HttpUtil.post('/server/status');
if (msg.success) {
+ if (!this.loadingStates.fetched) {
+ this.loadingStates.fetched = true;
+ }
+
this.setStatus(msg.obj, true);
}
} catch (e) {
console.error("Failed to get status:", e);
}
},
- setStatus(data, isLoaded = false) {
- this.status = new Status(data, isLoaded);
+ setStatus(data) {
+ this.status = new Status(data);
},
async openSelectV2rayVersion() {
this.loading(true);
@@ -788,5 +784,4 @@
},
});
-
-
+{{ template "page/body_end" .}}
\ No newline at end of file
diff --git a/web/html/login.html b/web/html/login.html
index 68e849f5..be6b9585 100644
--- a/web/html/login.html
+++ b/web/html/login.html
@@ -1,6 +1,4 @@
-
-
-{{template "head" .}}
+{{ template "page/head_start" .}}
+{{ template "page/head_end" .}}
-
-
-
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.settings.language" }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.login.hello" }}
- {{ i18n "pages.login.title" }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [[ loading ? '' : '{{ i18n "login" }}' ]]
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{template "js" .}}
- {{template "component/aThemeSwitch" .}}
-
-
-
+ function takeNext(word) {
+ return word.nextElementSibling ? word.nextElementSibling : word.parentElement.firstElementChild;
+ }
+
+ function switchWord(oldWord, newWord) {
+ oldWord.classList.remove('is-visible');
+ oldWord.classList.add('is-hidden');
+ newWord.classList.remove('is-hidden');
+ newWord.classList.add('is-visible');
+ }
+ });
+
+{{ template "page/body_end" .}}
\ No newline at end of file
diff --git a/web/html/settings.html b/web/html/settings.html
index dec40de7..1c55ea81 100644
--- a/web/html/settings.html
+++ b/web/html/settings.html
@@ -1,6 +1,4 @@
-
-
-{{template "head" .}}
+{{ template "page/head_start" .}}
-
-
-
-
-
-
-
-
-
- {{ i18n "secAlertConf" }}
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.settings.save" }}
- {{ i18n "pages.settings.restartPanel" }}
-
-
-
-
-
-
-
-
-
-
-
- {{ template "settings/panel/general" . }}
-
-
- {{ template "settings/panel/security" . }}
-
-
- {{ template "settings/panel/telegram" . }}
-
-
- {{ template "settings/panel/subscription/general" . }}
-
-
- {{ template "settings/panel/subscription/json" . }}
-
-
-
-
-
-
+{{ template "page/head_end" .}}
+
+{{ template "page/body_start" .}}
+
+
+
+
+
+
+
+
+ {{ i18n "secAlertConf" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ i18n "pages.settings.save" }}
+ {{ i18n "pages.settings.restartPanel" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ i18n "pages.settings.panelSettings" }}
+
+ {{ template "settings/panel/general" . }}
+
+
+
+
+ {{ i18n "pages.settings.securitySettings" }}
+
+ {{ template "settings/panel/security" . }}
+
+
+
+
+ {{ i18n "pages.settings.TGBotSettings" }}
+
+ {{ template "settings/panel/telegram" . }}
+
+
+
+
+ {{ i18n "pages.settings.subSettings" }}
+
+ {{ template "settings/panel/subscription/general" . }}
+
+
+
+
+ {{ i18n "pages.settings.subSettings" }} (JSON)
+
+ {{ template "settings/panel/subscription/json" . }}
+
+
+
+
+
+
+
+
-{{template "js" .}}
+
+{{template "page/body_scripts" .}}
@@ -132,10 +165,14 @@
-
-
\ No newline at end of file
+{{ template "page/body_end" .}}
\ No newline at end of file
diff --git a/web/html/settings/xray/advanced.html b/web/html/settings/xray/advanced.html
index b5f61b34..28e31871 100644
--- a/web/html/settings/xray/advanced.html
+++ b/web/html/settings/xray/advanced.html
@@ -1,5 +1,5 @@
{{define "settings/xray/advanced"}}
-
+
-
-{{template "head" .}}
+{{ template "page/head_start" .}}
+
+{{ template "page/head_end" .}}
+
+{{ template "page/body_start" .}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ i18n "pages.xray.save" }}
+
+
+ {{ i18n "pages.xray.restart" }}
+
+
+ {{ i18n "pages.index.xrayErrorPopoverTitle" }}
+
+ [[ line ]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { this.changePage(activeKey); }"
+ :class="themeSwitcher.currentTheme">
+
+
+
+ {{ i18n "pages.xray.basicTemplate"}}
+
+ {{ template "settings/xray/basics" . }}
+
+
+
+
+ {{ i18n "pages.xray.Routings"}}
+
+ {{ template "settings/xray/routing" . }}
+
+
+
+
+ {{ i18n "pages.xray.Outbounds"}}
+
+ {{ template "settings/xray/outbounds" . }}
+
+
+
+
+ {{ i18n "pages.xray.outbound.reverse"}}
+
+ {{ template "settings/xray/reverse" . }}
+
+
+
+
+ {{ i18n "pages.xray.Balancers"}}
+
+ {{ template "settings/xray/balancers" . }}
+
+
+
+
+ DNS
+
+ {{ template "settings/xray/dns" . }}
+
+
+
+
+ {{ i18n "pages.xray.advancedTemplate"}}
+
+ {{ template "settings/xray/advanced" . }}
+
+
+
+
+
+
+
+
+
+{{template "page/body_scripts" .}}
@@ -17,108 +164,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ i18n "pages.xray.save" }}
- {{ i18n "pages.xray.restart" }}
-
- {{ i18n "pages.index.xrayErrorPopoverTitle" }}
-
- [[ line ]]
-
-
-
-
-
-
-
-
-
-
-
-
- { this.changePage(activeKey); }"
- :class="themeSwitcher.currentTheme">
-
- {{ template "settings/xray/basics" . }}
-
-
- {{ template "settings/xray/routing" . }}
-
-
- {{ template "settings/xray/outbounds" . }}
-
-
- {{ template "settings/xray/reverse" . }}
-
-
- {{ template "settings/xray/balancers" . }}
-
-
- {{ template "settings/xray/dns" . }}
-
-
- {{ template "settings/xray/advanced" . }}
-
-
-
-
-
-
-
-{{template "js" .}}
{{template "component/aSidebar" .}}
{{template "component/aThemeSwitch" .}}
{{template "component/aTableSortable" .}}
@@ -132,1283 +177,1296 @@
{{template "modals/fakednsModal"}}
{{template "modals/warpModal"}}
-
-
+{{ template "page/body_end" .}}
\ No newline at end of file
diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml
index 1254087e..bf3fb43a 100644
--- a/web/translation/translate.ru_RU.toml
+++ b/web/translation/translate.ru_RU.toml
@@ -33,7 +33,7 @@
"sure" = "Да"
"encryption" = "Шифрование"
"useIPv4ForHost" = "Использовать IPv4 для хоста"
-"transmission" = "Протокол"
+"transmission" = "Транспорт"
"host" = "Хост"
"path" = "Путь"
"camouflage" = "Маскировка"
@@ -59,10 +59,10 @@
"security" = "Безопасность"
"secAlertTitle" = "Предупреждение системы безопасности"
"secAlertSsl" = "Это соединение не защищено. Пожалуйста, не вводите конфиденциальную информацию, пока не установите SSL сертификат для защиты соединения"
-"secAlertConf" = "Некоторые настройки уязвимы для атак. Рекомендуем усилить протоколы безопасности, чтобы предотвратить проблемы в будущем."
-"secAlertSSL" = "Ваше подключение к панели небезопасно. Пожалуйста, установите SSL сертификат для защиты данных."
-"secAlertPanelPort" = "Порт, на котором работает панель небезопасен. Пожалуйста, установите случайный или просто другой порт."
-"secAlertPanelURI" = "URI-адрес панели по умолчанию небезопасен. Пожалуйста, настройте сложный URI-адрес."
+"secAlertConf" = "Некоторые настройки уязвимы для атак. Чтобы в будущем не было проблем, нужно усилить защиту."
+"secAlertSSL" = "Ваше подключение к панели не защищено. Установите SSL сертификат для защиты данных."
+"secAlertPanelPort" = "Порт панели по умолчанию небезопасен. Установите случайный или просто другой порт."
+"secAlertPanelURI" = "Адрес панели по умолчанию небезопасен. Сделайте адрес сложным."
"secAlertSubURI" = "URI-адрес подписки по умолчанию небезопасен. Пожалуйста, настройте сложный URI-адрес."
"secAlertSubJsonURI" = "URI-адрес по умолчанию для JSON подписки небезопасен. Пожалуйста, настройте сложный URI-адрес."
"emptyDnsDesc" = "Нет добавленных DNS-серверов."
@@ -75,8 +75,8 @@
"theme" = "Тема"
"dark" = "Темная"
"ultraDark" = "Очень темная"
-"dashboard" = "Статус системы"
-"inbounds" = "Входящие подключения"
+"dashboard" = "Дашборд"
+"inbounds" = "Инбаунды"
"settings" = "Настройки"
"xray" = "Настройки Xray"
"logout" = "Выход"
@@ -91,15 +91,15 @@
"invalidFormData" = "Недопустимый формат данных"
"emptyUsername" = "Введите имя пользователя"
"emptyPassword" = "Введите пароль"
-"wrongUsernameOrPassword" = "Неверное имя пользователя, пароль или код двухфакторной аутентификации."
-"successLogin" = "Успешный вход"
+"wrongUsernameOrPassword" = "Неверные данные учетной записи."
+"successLogin" = "Вы успешно вошли в аккаунт"
[pages.index]
-"title" = "Статус системы"
+"title" = "Дашборд"
"cpu" = "ЦП"
"logicalProcessors" = "Логические процессоры"
"frequency" = "Частота"
-"swap" = "Swap"
+"swap" = "Файл подкачки"
"storage" = "Диск"
"memory" = "ОЗУ"
"threads" = "Потоки"
@@ -136,7 +136,7 @@
"geofileUpdateDialogDesc" = "Это обновит файл #filename#."
"geofileUpdatePopover" = "Геофайл успешно обновлён"
"dontRefresh" = "Установка в процессе. Не обновляйте страницу"
-"logs" = "Логи"
+"logs" = "Журнал"
"config" = "Конфигурация"
"backup" = "Резервная копия"
"backupTitle" = "Резервная копия базы данных"
@@ -151,10 +151,10 @@
"getConfigError" = "Произошла ошибка при получении конфигурационного файла"
[pages.inbounds]
-"title" = "Входящие подключения"
+"title" = "Инбаунды"
"totalDownUp" = "Объем отправленного/полученного трафика"
"totalUsage" = "Всего трафика"
-"inboundCount" = "Всего подключений"
+"inboundCount" = "Всего инбаундов"
"operate" = "Меню"
"enable" = "Включить"
"remark" = "Примечание"
@@ -165,18 +165,18 @@
"transportConfig" = "Транспорт"
"expireDate" = "Дата окончания"
"resetTraffic" = "Сброс трафика"
-"addInbound" = "Создать новое подключение"
+"addInbound" = "Создать инбаунд"
"generalActions" = "Общие действия"
"autoRefresh" = "Автообновление"
"autoRefreshInterval" = "Интервал"
-"modifyInbound" = "Изменить входящее подключение"
-"deleteInbound" = "Удалить входящее подключение"
-"deleteInboundContent" = "Вы уверены, что хотите удалить входящее подключение?"
+"modifyInbound" = "Изменить инбаунд"
+"deleteInbound" = "Удалить инбаунд"
+"deleteInboundContent" = "Вы уверены, что хотите удалить инбаунд?"
"deleteClient" = "Удалить клиента"
"deleteClientContent" = "Вы уверены, что хотите удалить клиента?"
"resetTrafficContent" = "Вы уверены, что хотите сбросить трафик?"
-"inboundUpdateSuccess" = "Входящее подключение успешно обновлено."
-"inboundCreateSuccess" = "Входящее подключение успешно создано."
+"inboundUpdateSuccess" = "Инбаунд успешно обновлен."
+"inboundCreateSuccess" = "Инбаунд успешно создан."
"copyLink" = "Копировать ссылку"
"address" = "Адрес"
"network" = "Сеть"
@@ -196,11 +196,11 @@
"export" = "Экспорт ссылок"
"clone" = "Клонировать"
"cloneInbound" = "Клонировать"
-"cloneInboundContent" = "Будут клонированы все настройки входящих подключений, кроме списка клиентов, порта и IP-адреса прослушивания"
+"cloneInboundContent" = "Будут клонированы все настройки инбаундов, кроме списка клиентов, порта и IP-адреса прослушивания"
"cloneInboundOk" = "Клонировано"
-"resetAllTraffic" = "Сброс трафика всех подключений"
-"resetAllTrafficTitle" = "Сброс трафика всех подключений"
-"resetAllTrafficContent" = "Вы уверены, что хотите сбросить трафик всех подключений?"
+"resetAllTraffic" = "Сброс трафика всех инбаундов"
+"resetAllTrafficTitle" = "Сброс трафика всех инбаундов"
+"resetAllTrafficContent" = "Вы уверены, что хотите сбросить трафик всех инбаундов?"
"resetInboundClientTraffics" = "Сброс трафика клиента"
"resetInboundClientTrafficTitle" = "Сброс трафика клиентов"
"resetInboundClientTrafficContent" = "Вы уверены, что хотите сбросить трафик для этих клиентов?"
@@ -222,10 +222,10 @@
"subscriptionDesc" = "Вы можете найти свою ссылку подписки в разделе 'Подробнее'"
"info" = "Информация"
"same" = "Тот же"
-"inboundData" = "Данные подключений"
-"exportInbound" = "Экспорт входящих подключений"
+"inboundData" = "Данные инбаундов"
+"exportInbound" = "Экспорт инбаундов"
"import" = "Импортировать"
-"importInbound" = "Импорт входящих подключений"
+"importInbound" = "Импорт инбаундов"
[pages.client]
"add" = "Создать клиента"
@@ -249,13 +249,13 @@
"obtain" = "Получить"
"updateSuccess" = "Обновление прошло успешно"
"logCleanSuccess" = "Лог был очищен"
-"inboundsUpdateSuccess" = "Входящие подключения успешно обновлены"
-"inboundUpdateSuccess" = "Входящее подключение успешно обновлено"
-"inboundCreateSuccess" = "Входящее подключение успешно создано"
-"inboundDeleteSuccess" = "Входящее подключение успешно удалено"
-"inboundClientAddSuccess" = "Клиент(ы) входящего подключения добавлен(ы)"
-"inboundClientDeleteSuccess" = "Клиент входящего подключения удалён"
-"inboundClientUpdateSuccess" = "Клиент входящего подключения обновлён"
+"inboundsUpdateSuccess" = "Инбаунды успешно обновлены"
+"inboundUpdateSuccess" = "Инбаунд успешно обновлено"
+"inboundCreateSuccess" = "Инбаунд успешно создано"
+"inboundDeleteSuccess" = "Инбаунд успешно удалено"
+"inboundClientAddSuccess" = "Клиент(ы) инбаунда добавлен(ы)"
+"inboundClientDeleteSuccess" = "Клиент инбаунда удалён"
+"inboundClientUpdateSuccess" = "Клиент инбаунда обновлён"
"delDepletedClientsSuccess" = "Все исчерпанные клиенты удалены"
"resetAllClientTrafficSuccess" = "Весь трафик клиента сброшен"
"resetAllTrafficSuccess" = "Весь трафик сброшен"
@@ -281,15 +281,15 @@
[pages.settings]
"title" = "Настройки"
"save" = "Сохранить"
-"infoDesc" = "Каждое выполненное изменение необходимо сохранить. Пожалуйста, перезапустите панель, чтобы изменения вступили в силу"
+"infoDesc" = "Каждое внесённое изменение должно быть сохранено. Пожалуйста, перезапустите панель, чтобы изменения вступили в силу."
"restartPanel" = "Перезапуск панели"
"restartPanelDesc" = "Вы уверены, что хотите перезапустить панель? Подтвердите, и перезапуск произойдёт через 3 секунды. Если панель будет недоступна, проверьте лог сервера"
"restartPanelSuccess" = "Панель успешно перезапущена"
"actions" = "Действия"
"resetDefaultConfig" = "Восстановить настройки по умолчанию"
-"panelSettings" = "Настройки панели"
-"securitySettings" = "Настройки безопасности"
-"TGBotSettings" = "Настройки Telegram бота"
+"panelSettings" = "Панель"
+"securitySettings" = "Учетная запись"
+"TGBotSettings" = "Telegram"
"panelListeningIP" = "IP-адрес для управления панелью"
"panelListeningIPDesc" = "Оставьте пустым для подключения с любого IP"
"panelListeningDomain" = "Домен панели"
@@ -303,7 +303,7 @@
"panelUrlPath" = "Корневой путь URL адреса панели"
"panelUrlPathDesc" = "Должен начинаться с '/' и заканчиваться '/'"
"pageSize" = "Размер нумерации страниц"
-"pageSizeDesc" = "Определить размер страницы для таблицы входящих подключений. Установите 0, чтобы отключить"
+"pageSizeDesc" = "Определить размер страницы для таблицы инбаундов. Установите 0, чтобы отключить"
"remarkModel" = "Модель примечания и символ разделения"
"datepicker" = "Выбор даты"
"datepickerPlaceholder" = "Выберите дату"
@@ -391,7 +391,7 @@
[pages.xray]
"title" = "Настройки Xray"
"save" = "Сохранить"
-"restart" = "Перезапустить Xray"
+"restart" = "Перезапуск Xray"
"restartSuccess" = "Xray успешно перезапущен"
"stopSuccess" = "Xray успешно остановлен"
"restartError" = "Произошла ошибка при перезапуске Xray."
@@ -402,7 +402,7 @@
"generalConfigsDesc" = "Эти параметры описывают общие настройки"
"logConfigs" = "Логи"
"logConfigsDesc" = "Логи могут замедлять работу сервера. Включайте только нужные вам виды логов при необходимости!"
-"blockConfigsDesc" = "Настройте, чтобы клиенты не имели доступа к определенным протоколам и веб-сайтами"
+"blockConfigsDesc" = "Настройте, чтобы клиенты не имели доступа к определенным протоколам"
"basicRouting" = "Базовые соединения"
"blockConnectionsConfigsDesc" = "Эти параметры будут блокировать трафик в зависимости от страны назначения."
"directConnectionsConfigsDesc" = "Прямое соединение означает, что определенный трафик не будет перенаправлен через другой сервер."
@@ -413,19 +413,19 @@
"ipv4Routing" = "Правила IPv4"
"ipv4RoutingDesc" = "Эти параметры позволят клиентам маршрутизироваться к целевым доменам только через IPv4"
"warpRouting" = "Правила WARP"
-"warpRoutingDesc" = "Внимание: перед использованием этих параметров установите WARP в режиме прокси-сервера socks5 на свой сервер, следуя инструкциям на GitHub панели. WARP будет направлять трафик на веб-сайты через серверы Cloudflare"
+"warpRoutingDesc" = " Эти опции будут направлять трафик в зависимости от конкретного пункта назначения через WARP."
"Template" = "Шаблон конфигурации Xray"
-"TemplateDesc" = "Создание файла конфигурации Xray на основе этого шаблона"
+"TemplateDesc" = "На основе шаблона создаётся конфигурационный файл Xray."
"FreedomStrategy" = "Настройка стратегии протокола Freedom"
"FreedomStrategyDesc" = "Установка стратегии вывода сети в протоколе Freedom"
"RoutingStrategy" = "Настройка маршрутизации доменов"
"RoutingStrategyDesc" = "Установка общей стратегии маршрутизации разрешения DNS"
"Torrent" = "Заблокировать BitTorrent"
-"Inbounds" = "Входящее соединение"
+"Inbounds" = "Инбаунды"
"InboundsDesc" = "Изменение шаблона конфигурации для подключения определенных клиентов"
-"Outbounds" = "Исходящее соединение"
+"Outbounds" = "Аутбаунды"
"Balancers" = "Балансировщик"
-"OutboundsDesc" = "Изменение шаблона конфигурации, чтобы определить исходящие соединения для этого сервера"
+"OutboundsDesc" = "Изменение шаблона конфигурации, чтобы определить аутбаунды для этого сервера"
"Routings" = "Маршрутизация"
"RoutingsDesc" = "Важен приоритет каждого правила!"
"completeTemplate" = "Все"
@@ -456,8 +456,8 @@
"down" = "Опустить вниз"
"source" = "Источник"
"dest" = "Пункт назначения"
-"inbound" = "Входящее соединение"
-"outbound" = "Исходящее соединение"
+"inbound" = "Инбаунд"
+"outbound" = "Аутбаунд"
"balancer" = "Балансировщик"
"info" = "Информация"
"add" = "Создать правило"
@@ -465,9 +465,9 @@
"useComma" = "Элементы, разделённые запятыми"
[pages.xray.outbound]
-"addOutbound" = "Создать исходящее соединение"
+"addOutbound" = "Создать аутбаунд"
"addReverse" = "Создать реверс-прокси"
-"editOutbound" = "Изменить исходящее соединение"
+"editOutbound" = "Изменить аутбаунд"
"editReverse" = "Редактировать реверс-прокси"
"tag" = "Тег"
"tagDesc" = "Уникальный тег"
@@ -481,7 +481,7 @@
"intercon" = "Соединение"
"settings" = "Настройки"
"accountInfo" = "Информация об учетной записи"
-"outboundStatus" = "Исходящий статус"
+"outboundStatus" = "Статус аутбаунда"
"sendThrough" = "Отправить через"
[pages.xray.balancer]
@@ -494,7 +494,7 @@
"balancerDesc" = "Невозможно одновременно использовать balancerTag и outboundTag. При одновременном использовании будет работать только outboundTag."
[pages.xray.wireguard]
-"secretKey" = "Приватный ключ"
+"secretKey" = "Секретный ключ"
"publicKey" = "Публичный ключ"
"allowedIPs" = "Разрешенные IP-адреса"
"endpoint" = "Конечная точка"
@@ -555,8 +555,8 @@
"modifyUser" = "Вы успешно изменили учетные данные администратора."
"originalUserPassIncorrect" = "Неверное имя пользователя или пароль"
"userPassMustBeNotEmpty" = "Новое имя пользователя и новый пароль должны быть заполнены"
-"getOutboundTrafficError" = "Ошибка получения исходящего трафика"
-"resetOutboundTrafficError" = "Ошибка сброса исходящего трафика"
+"getOutboundTrafficError" = "Ошибка получения трафика аутбаунда"
+"resetOutboundTrafficError" = "Ошибка сброса трафика аутбаунда"
[tgbot]
"keyboardClosed" = "❌ Клавиатура закрыта."
@@ -564,7 +564,7 @@
"noQuery" = "❌ Запрос не найден. Пожалуйста, повторите команду."
"wentWrong" = "❌ Что-то пошло не так..."
"noIpRecord" = "❗ Нет записей об IP-адресе."
-"noInbounds" = "❗ У вас не настроено ни одного подключения."
+"noInbounds" = "❗ У вас не настроено ни одного инбаунда."
"unlimited" = "♾ Безлимит"
"add" = "Добавить"
"month" = "Месяц"
@@ -573,7 +573,7 @@
"days" = "Дней"
"hours" = "Часов"
"unknown" = "Неизвестно"
-"inbounds" = "Подключения"
+"inbounds" = "Инбаунды"
"clients" = "Клиенты"
"offline" = "🔴 Офлайн"
"online" = "🟢 Онлайн"
@@ -587,7 +587,7 @@
"status" = "✅ Бот функционирует нормально."
"usage" = "❗ Пожалуйста, укажите email для поиска."
"getID" = "🆔 Ваш User ID: {{ .ID }}
"
-"helpAdminCommands" = "🔃 Для перезапуска Xray Core:\r\n/restart
\r\n\r\n🔎 Для поиска клиента по email:\r\n/usage [Email]
\r\n\r\n📊 Для поиска подключений (со статистикой клиентов):\r\n/inbound [имя подключения]
\r\n\r\n🆔 Ваш Telegram User ID:\r\n/id
"
+"helpAdminCommands" = "🔃 Для перезапуска Xray Core:\r\n/restart
\r\n\r\n🔎 Для поиска клиента по email:\r\n/usage [Email]
\r\n\r\n📊 Для поиска инбаундов (со статистикой клиентов):\r\n/inbound [имя подключения]
\r\n\r\n🆔 Ваш Telegram User ID:\r\n/id
"
"helpClientCommands" = "💲 Для просмотра информации о вашей подписке используйте команду:\r\n/usage [Email]
\r\n\r\n🆔 Ваш Telegram User ID:\r\n/id
"
"restartUsage" = "\r\n\r\n/restart
"
"restartSuccess" = "✅ Ядро Xray успешно перезапущено."
@@ -653,8 +653,8 @@
"pass_prompt" = "🔑 Стандартный пароль: {{ .ClientPassword }}\n\nВведите ваш пароль."
"email_prompt" = "📧 Стандартный email: {{ .ClientEmail }}\n\nВведите ваш email."
"comment_prompt" = "💬 Стандартный комментарий: {{ .ClientComment }}\n\nВведите ваш комментарий."
-"inbound_client_data_id" = "🔄 Подключения: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в подключение!"
-"inbound_client_data_pass" = "🔄 Подключения: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в подключение!"
+"inbound_client_data_id" = "🔄 Инбаунды: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в инбаунд!"
+"inbound_client_data_pass" = "🔄 Инбаунды: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в инбаунд!"
"cancel" = "❌ Процесс отменён! \n\nВы можете снова начать с /start в любое время. 🔄"
"error_add_client" = "⚠️ Ошибка:\n\n {{ .error }}"
"using_default_value" = "Используется значение по умолчанию👌"
@@ -676,7 +676,7 @@
"confirmToggle" = "✅ Подтвердить вкл/выкл пользователя?"
"dbBackup" = "📂 Бэкап БД"
"serverUsage" = "💻 Состояние сервера"
-"getInbounds" = "🔌 Подключения"
+"getInbounds" = "🔌 Инбаунды"
"depleteSoon" = "⚠️ Скоро конец"
"clientUsage" = "Статистика клиента"
"onlines" = "🟢 Онлайн"
@@ -714,7 +714,7 @@
[tgbot.answers]
"successfulOperation" = "✅ Успешно!"
"errorOperation" = "❗ Ошибка в операции."
-"getInboundsFailed" = "❌ Не удалось получить подключения."
+"getInboundsFailed" = "❌ Не удалось получить инбаунды."
"getClientsFailed" = "❌ Не удалось получить клиентов."
"canceled" = "❌ {{ .Email }}: Операция отменена."
"clientRefreshSuccess" = "✅ {{ .Email }}: Клиент успешно обновлен."
@@ -731,5 +731,5 @@
"enableSuccess" = "✅ {{ .Email }}: Включено успешно."
"disableSuccess" = "✅ {{ .Email }}: Отключено успешно."
"askToAddUserId" = "❌ Ваша конфигурация не найдена!\r\n💭 Пожалуйста, попросите администратора использовать ваш Telegram User ID в конфигурации.\r\n\r\n🆔 Ваш User ID: {{ .TgUserID }}
"
-"chooseClient" = "Выберите клиента для подключения {{ .Inbound }}"
-"chooseInbound" = "Выберите подключение"
+"chooseClient" = "Выберите клиента для инбаунда {{ .Inbound }}"
+"chooseInbound" = "Выберите инбаунд"