separate xray page #1286

This commit is contained in:
Alireza Ahmadi 2023-12-04 19:20:46 +01:00
parent a8b7063647
commit 2a8da2ba3c
12 changed files with 211 additions and 84 deletions

View file

@ -41,7 +41,7 @@ func (a *SettingController) initRouter(g *gin.RouterGroup) {
g.POST("/update", a.updateSetting)
g.POST("/updateUser", a.updateUser)
g.POST("/restartPanel", a.restartPanel)
g.GET("/getDefaultJsonConfig", a.getDefaultJsonConfig)
g.GET("/getDefaultJsonConfig", a.getDefaultXrayConfig)
g.POST("/updateUserSecret", a.updateSecret)
g.POST("/getUserSecret", a.getUserSecret)
}
@ -55,15 +55,6 @@ func (a *SettingController) getAllSetting(c *gin.Context) {
jsonObj(c, allSetting, nil)
}
func (a *SettingController) getDefaultJsonConfig(c *gin.Context) {
defaultJsonConfig, err := a.settingService.GetDefaultJsonConfig()
if err != nil {
jsonMsg(c, I18nWeb(c, "pages.settings.toasts.getSettings"), err)
return
}
jsonObj(c, defaultJsonConfig, nil)
}
func (a *SettingController) getDefaultSettings(c *gin.Context) {
type settingFunc func() (interface{}, error)
@ -169,3 +160,12 @@ func (a *SettingController) getUserSecret(c *gin.Context) {
jsonObj(c, user, nil)
}
}
func (a *SettingController) getDefaultXrayConfig(c *gin.Context) {
defaultJsonConfig, err := a.settingService.GetDefaultXrayConfig()
if err != nil {
jsonMsg(c, I18nWeb(c, "pages.settings.toasts.getSettings"), err)
return
}
jsonObj(c, defaultJsonConfig, nil)
}

View file

@ -0,0 +1,50 @@
package controller
import (
"x-ui/web/service"
"github.com/gin-gonic/gin"
)
type XraySettingController struct {
XraySettingService service.XraySettingService
SettingService service.SettingService
}
func NewXraySettingController(g *gin.RouterGroup) *XraySettingController {
a := &XraySettingController{}
a.initRouter(g)
return a
}
func (a *XraySettingController) initRouter(g *gin.RouterGroup) {
g = g.Group("/xray")
g.POST("/", a.getXraySetting)
g.POST("/update", a.updateSetting)
g.GET("/getDefaultJsonConfig", a.getDefaultXrayConfig)
}
func (a *XraySettingController) getXraySetting(c *gin.Context) {
xraySetting, err := a.SettingService.GetXrayConfigTemplate()
if err != nil {
jsonMsg(c, I18nWeb(c, "pages.settings.toasts.getSettings"), err)
return
}
jsonObj(c, xraySetting, nil)
}
func (a *XraySettingController) updateSetting(c *gin.Context) {
xraySetting := c.PostForm("xraySetting")
err := a.XraySettingService.SaveXraySetting(xraySetting)
jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err)
}
func (a *XraySettingController) getDefaultXrayConfig(c *gin.Context) {
defaultJsonConfig, err := a.SettingService.GetDefaultXrayConfig()
if err != nil {
jsonMsg(c, I18nWeb(c, "pages.settings.toasts.getSettings"), err)
return
}
jsonObj(c, defaultJsonConfig, nil)
}

View file

@ -7,8 +7,9 @@ import (
type XUIController struct {
BaseController
inboundController *InboundController
settingController *SettingController
inboundController *InboundController
settingController *SettingController
xraySettingController *XraySettingController
}
func NewXUIController(g *gin.RouterGroup) *XUIController {
@ -24,9 +25,11 @@ func (a *XUIController) initRouter(g *gin.RouterGroup) {
g.GET("/", a.index)
g.GET("/inbounds", a.inbounds)
g.GET("/settings", a.settings)
g.GET("/xray", a.xraySettings)
a.inboundController = NewInboundController(g)
a.settingController = NewSettingController(g)
a.xraySettingController = NewXraySettingController(g)
}
func (a *XUIController) index(c *gin.Context) {
@ -40,3 +43,7 @@ func (a *XUIController) inbounds(c *gin.Context) {
func (a *XUIController) settings(c *gin.Context) {
html(c, "settings.html", "pages.settings.title", nil)
}
func (a *XUIController) xraySettings(c *gin.Context) {
html(c, "xray.html", "pages.xray.title", nil)
}

View file

@ -2,12 +2,10 @@ package entity
import (
"crypto/tls"
"encoding/json"
"net"
"strings"
"time"
"x-ui/util/common"
"x-ui/xray"
)
type Msg struct {
@ -27,36 +25,35 @@ type Pager struct {
}
type AllSetting struct {
WebListen string `json:"webListen" form:"webListen"`
WebDomain string `json:"webDomain" form:"webDomain"`
WebPort int `json:"webPort" form:"webPort"`
WebCertFile string `json:"webCertFile" form:"webCertFile"`
WebKeyFile string `json:"webKeyFile" form:"webKeyFile"`
WebBasePath string `json:"webBasePath" form:"webBasePath"`
SessionMaxAge int `json:"sessionMaxAge" form:"sessionMaxAge"`
ExpireDiff int `json:"expireDiff" form:"expireDiff"`
TrafficDiff int `json:"trafficDiff" form:"trafficDiff"`
TgBotEnable bool `json:"tgBotEnable" form:"tgBotEnable"`
TgBotToken string `json:"tgBotToken" form:"tgBotToken"`
TgBotChatId string `json:"tgBotChatId" form:"tgBotChatId"`
TgRunTime string `json:"tgRunTime" form:"tgRunTime"`
TgBotBackup bool `json:"tgBotBackup" form:"tgBotBackup"`
TgBotLoginNotify bool `json:"tgBotLoginNotify" form:"tgBotLoginNotify"`
TgCpu int `json:"tgCpu" form:"tgCpu"`
TgLang string `json:"tgLang" form:"tgLang"`
XrayTemplateConfig string `json:"xrayTemplateConfig" form:"xrayTemplateConfig"`
TimeLocation string `json:"timeLocation" form:"timeLocation"`
SecretEnable bool `json:"secretEnable" form:"secretEnable"`
SubEnable bool `json:"subEnable" form:"subEnable"`
SubListen string `json:"subListen" form:"subListen"`
SubPort int `json:"subPort" form:"subPort"`
SubPath string `json:"subPath" form:"subPath"`
SubDomain string `json:"subDomain" form:"subDomain"`
SubCertFile string `json:"subCertFile" form:"subCertFile"`
SubKeyFile string `json:"subKeyFile" form:"subKeyFile"`
SubUpdates int `json:"subUpdates" form:"subUpdates"`
SubEncrypt bool `json:"subEncrypt" form:"subEncrypt"`
SubShowInfo bool `json:"subShowInfo" form:"subShowInfo"`
WebListen string `json:"webListen" form:"webListen"`
WebDomain string `json:"webDomain" form:"webDomain"`
WebPort int `json:"webPort" form:"webPort"`
WebCertFile string `json:"webCertFile" form:"webCertFile"`
WebKeyFile string `json:"webKeyFile" form:"webKeyFile"`
WebBasePath string `json:"webBasePath" form:"webBasePath"`
SessionMaxAge int `json:"sessionMaxAge" form:"sessionMaxAge"`
ExpireDiff int `json:"expireDiff" form:"expireDiff"`
TrafficDiff int `json:"trafficDiff" form:"trafficDiff"`
TgBotEnable bool `json:"tgBotEnable" form:"tgBotEnable"`
TgBotToken string `json:"tgBotToken" form:"tgBotToken"`
TgBotChatId string `json:"tgBotChatId" form:"tgBotChatId"`
TgRunTime string `json:"tgRunTime" form:"tgRunTime"`
TgBotBackup bool `json:"tgBotBackup" form:"tgBotBackup"`
TgBotLoginNotify bool `json:"tgBotLoginNotify" form:"tgBotLoginNotify"`
TgCpu int `json:"tgCpu" form:"tgCpu"`
TgLang string `json:"tgLang" form:"tgLang"`
TimeLocation string `json:"timeLocation" form:"timeLocation"`
SecretEnable bool `json:"secretEnable" form:"secretEnable"`
SubEnable bool `json:"subEnable" form:"subEnable"`
SubListen string `json:"subListen" form:"subListen"`
SubPort int `json:"subPort" form:"subPort"`
SubPath string `json:"subPath" form:"subPath"`
SubDomain string `json:"subDomain" form:"subDomain"`
SubCertFile string `json:"subCertFile" form:"subCertFile"`
SubKeyFile string `json:"subKeyFile" form:"subKeyFile"`
SubUpdates int `json:"subUpdates" form:"subUpdates"`
SubEncrypt bool `json:"subEncrypt" form:"subEncrypt"`
SubShowInfo bool `json:"subShowInfo" form:"subShowInfo"`
}
func (s *AllSetting) CheckValid() error {
@ -107,13 +104,7 @@ func (s *AllSetting) CheckValid() error {
s.WebBasePath += "/"
}
xrayConfig := &xray.Config{}
err := json.Unmarshal([]byte(s.XrayTemplateConfig), xrayConfig)
if err != nil {
return common.NewError("xray template config invalid:", err)
}
_, err = time.LoadLocation(s.TimeLocation)
_, err := time.LoadLocation(s.TimeLocation)
if err != nil {
return common.NewError("time location not exist:", s.TimeLocation)
}

View file

@ -70,7 +70,7 @@ func (s *SettingService) GetDefaultJsonConfig() (interface{}, error) {
func (s *SettingService) GetAllSetting() (*entity.AllSetting, error) {
db := database.GetDB()
settings := make([]*model.Setting, 0)
err := db.Model(model.Setting{}).Find(&settings).Error
err := db.Model(model.Setting{}).Not("key = ?", "xrayTemplateConfig").Find(&settings).Error
if err != nil {
return nil, err
}
@ -426,3 +426,12 @@ func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
}
return common.Combine(errs...)
}
func (s *SettingService) GetDefaultXrayConfig() (interface{}, error) {
var jsonData interface{}
err := json.Unmarshal([]byte(xrayTemplateConfig), &jsonData)
if err != nil {
return nil, err
}
return jsonData, nil
}

View file

@ -0,0 +1,28 @@
package service
import (
_ "embed"
"encoding/json"
"x-ui/util/common"
"x-ui/xray"
)
type XraySettingService struct {
SettingService
}
func (s *XraySettingService) SaveXraySetting(newXraySettings string) error {
if err := s.CheckXrayConfig(newXraySettings); err != nil {
return err
}
return s.SettingService.saveSetting("xrayTemplateConfig", newXraySettings)
}
func (s *XraySettingService) CheckXrayConfig(XrayTemplateConfig string) error {
xrayConfig := &xray.Config{}
err := json.Unmarshal([]byte(XrayTemplateConfig), xrayConfig)
if err != nil {
return common.NewError("xray template config invalid:", err)
}
return nil
}

View file

@ -12,7 +12,7 @@
"protocol" = "Protocol"
"search" = "Search"
"filter" = "Filter"
"loading" = "Loading"
"loading" = "Loading..."
"second" = "Second"
"minute" = "Minute"
"hour" = "Hour"
@ -37,7 +37,9 @@
"enabled" = "Enabled"
"disabled" = "Disabled"
"depleted" = "Depleted"
"depletingSoon" = "Depleting soon"
"depletingSoon" = "Depleting"
"offline" = "Offline"
"online" = "Online"
"domainName" = "Domain name"
"monitor" = "Listening IP"
"certificate" = "Certificate"
@ -54,6 +56,7 @@
"dashboard" = "System Status"
"inbounds" = "Inbounds"
"settings" = "Panel Settings"
"xray" = "Xray Settings"
"logout" = "Logout"
"link" = "Other"
@ -121,6 +124,8 @@
"modifyInbound" = "Modify Inbound"
"deleteInbound" = "Delete Inbound"
"deleteInboundContent" = "Confirm deletion of inbound?"
"deleteClient" = "Delete Client"
"deleteClientContent" = "Are you sure you want to delete client?"
"resetTrafficContent" = "Confirm traffic reset?"
"copyLink" = "Copy Link"
"address" = "Address"
@ -132,8 +137,8 @@
"totalFlow" = "Total Flow"
"leaveBlankToNeverExpire" = "Leave Blank to Never Expire"
"noRecommendKeepDefault" = "No special requirements to maintain default settings"
"certificatePath" = "Certificate File Path"
"certificateContent" = "Certificate File Content"
"certificatePath" = "File Path"
"certificateContent" = "File Content"
"publicKeyPath" = "Public Key Path"
"publicKeyContent" = "Public Key Content"
"keyPath" = "Private Key Path"
@ -169,6 +174,7 @@
"realityDesc" = "Xray core needs to be 1.8.0 or higher."
"telegramDesc" = "use Telegram ID without @ or chat IDs ( you can get it here @userinfobot or use '/id' command in bot )"
"subscriptionDesc" = "you can find your sub link on Details, also you can use the same name for several configurations"
"info" = "Info"
[pages.client]
"add" = "Add Client"
@ -185,6 +191,8 @@
"delayedStart" = "Start after first use"
"expireDays" = "Expire days"
"days" = "day(s)"
"renew" = "Auto renew"
"renewDesc" = "Auto renew days after expiration. 0 = disable"
[pages.inbounds.toasts]
"obtain" = "Obtain"
@ -216,7 +224,6 @@
"resetDefaultConfig" = "Reset to Default Configuration"
"panelSettings" = "Panel Settings"
"securitySettings" = "Security Settings"
"xrayConfiguration" = "Xray Configuration"
"TGBotSettings" = "Telegram Bot Settings"
"panelListeningIP" = "Panel Listening IP"
"panelListeningIPDesc" = "Leave blank by default to monitor all IPs."
@ -278,8 +285,8 @@
"subShowInfo" = "Show usage info"
"subShowInfoDesc" = "Show remianed traffic and date after config name"
[pages.settings.templates]
"title" = "Templates"
[pages.xray]
"title" = "Xray Settings"
"basicTemplate" = "Basic Template"
"advancedTemplate" = "Advanced Template"
"completeTemplate" = "Complete Template"

View file

@ -12,7 +12,7 @@
"protocol" = "Protocolo"
"search" = "Buscar"
"filter" = "Filtrar"
"loading" = "Cargando"
"loading" = "Cargando..."
"second" = "Segundo"
"minute" = "Minuto"
"hour" = "Hora"
@ -37,7 +37,9 @@
"enabled" = "Habilitado"
"disabled" = "Deshabilitado"
"depleted" = "Agotado"
"depletingSoon" = "Agotándose pronto"
"depletingSoon" = "Agotándose"
"offline" = "fuera de línea"
"online" = "en línea"
"domainName" = "Nombre de dominio"
"monitor" = "Listening IP"
"certificate" = "Certificado"
@ -54,6 +56,7 @@
"dashboard" = "Estado del Sistema"
"inbounds" = "Entradas"
"settings" = "Configuraciones"
"xray" = "Configuración Xray"
"logout" = "Cerrar Sesión"
"link" = "Otro"
@ -121,6 +124,8 @@
"modifyInbound" = "Modificar Entrada"
"deleteInbound" = "Eliminar Entrada"
"deleteInboundContent" = "¿Confirmar eliminación de entrada?"
"deleteClient" = "Eliminar cliente"
"deleteClientContent" = "¿Está seguro de que desea eliminar el cliente?"
"resetTrafficContent" = "¿Confirmar restablecimiento de tráfico?"
"copyLink" = "Copiar Enlace"
"address" = "Dirección"
@ -132,8 +137,8 @@
"totalFlow" = "Flujo Total"
"leaveBlankToNeverExpire" = "Dejar en Blanco para Nunca Expirar"
"noRecommendKeepDefault" = "No hay requisitos especiales para mantener la configuración predeterminada"
"certificatePath" = "Ruta del Archivo de Certificado"
"certificateContent" = "Contenido del Archivo de Certificado"
"certificatePath" = "Ruta del Archivo"
"certificateContent" = "Contenido del Archivo"
"publicKeyPath" = "Ruta de la Clave Pública"
"publicKeyContent" = "Contenido de la Clave Pública"
"keyPath" = "Ruta de la Clave Privada"
@ -169,6 +174,7 @@
"realityDesc" = "La versión del núcleo de Xray debe ser 1.8.0 o superior."
"telegramDesc" = "Utiliza el ID de Telegram sin @ o los IDs de chat (puedes obtenerlo aquí @userinfobot o usando el comando '/id' en el bot)."
"subscriptionDesc" = "Puedes encontrar tu enlace de suscripción en Detalles, también puedes usar el mismo nombre para varias configuraciones."
"info" = "Info"
[pages.client]
"add" = "Agregar Cliente"
@ -185,6 +191,8 @@
"delayedStart" = "Iniciar después del primer uso"
"expireDays" = "Días de Expiración"
"days" = "día(s)"
"renew" = "Renovación automática"
"renewDesc" = "Renovación automática días después del vencimiento. 0 = deshabilitar"
[pages.inbounds.toasts]
"obtain" = "Recibir"
@ -216,7 +224,6 @@
"resetDefaultConfig" = "Restablecer a Configuración Predeterminada"
"panelSettings" = "Configuraciones del Panel"
"securitySettings" = "Configuraciones de Seguridad"
"xrayConfiguration" = "Configuración de Xray"
"TGBotSettings" = "Configuraciones de Bot de Telegram"
"panelListeningIP" = "IP de Escucha del Panel"
"panelListeningIPDesc" = "Dejar en blanco por defecto para monitorear todas las IPs."
@ -278,8 +285,8 @@
"subShowInfo" = "Mostrar información de uso"
"subShowInfoDesc" = "Mostrar tráfico restante y fecha después del nombre de configuración."
[pages.settings.templates]
"title" = "Plantillas"
[pages.xray]
"title" = "Xray Configuración"
"basicTemplate" = "Plantilla Básica"
"advancedTemplate" = "Plantilla Avanzada"
"completeTemplate" = "Plantilla Completa"

View file

@ -38,6 +38,8 @@
"disabled" = "غیرفعال"
"depleted" = "منقضی"
"depletingSoon" = "در حال انقضا"
"offline" = "آفلاین"
"online" = "آنلاین"
"domainName" = "آدرس دامنه"
"monitor" = "آی پی اتصال"
"certificate" = "گواهی دیجیتال"
@ -54,6 +56,7 @@
"dashboard" = "وضعیت سیستم"
"inbounds" = "سرویس ها"
"settings" = "تنظیمات پنل"
"xray" = "الگوی ایکس‌ری"
"logout" = "خروج"
"link" = "دیگر"
@ -121,6 +124,8 @@
"modifyInbound" = "ویرایش سرویس"
"deleteInbound" = "حذف سرویس"
"deleteInboundContent" = "آیا مطمئن به حذف سرویس هستید ؟"
"deleteClient" = "حذف کاربر"
"deleteClientContent" = "آیا مطمئن به حذف کاربر هستید ؟"
"resetTrafficContent" = "آیا مطمئن به ریست ترافیک هستید ؟"
"copyLink" = "کپی لینک"
"address" = "آدرس"
@ -169,6 +174,7 @@
"realityDesc" = "هسته Xray باید 1.8.0 و بالاتر باشد"
"telegramDesc" = "از آیدی تلگرام بدون @ یا آیدی چت استفاده کنید (می توانید آن را از اینجا دریافت کنید @userinfobot یا در ربات دستور '/id' را وارد کنید)"
"subscriptionDesc" = "می توانید ساب لینک خود را در جزئیات پیدا کنید، همچنین می توانید از همین نام برای چندین کانفیگ استفاده کنید"
"info" = "اطلاعات"
[pages.client]
"add" = "کاربر جدید"
@ -185,6 +191,8 @@
"delayedStart" = "شروع بعد از اولین استفاده"
"expireDays" = "روزهای اعتبار"
"days" = "(روز)"
"renew" = "تمدید خودکار"
"renewDesc" = "روزهای تمدید خودکار پس از انقضا. 0 = غیرفعال"
[pages.inbounds.toasts]
"obtain" = "Obtain"
@ -216,7 +224,6 @@
"resetDefaultConfig" = "برگشت به تنظیمات پیشفرض"
"panelSettings" = "تنظیمات پنل"
"securitySettings" = "تنظیمات امنیتی"
"xrayConfiguration" = "تنظیمات Xray"
"TGBotSettings" = "تنظیمات ربات تلگرام"
"panelListeningIP" = "محدودیت آی پی پنل"
"panelListeningIPDesc" = "برای استفاده از تمام آی‌پیها به طور پیش فرض خالی بگذارید"

View file

@ -12,7 +12,7 @@
"protocol" = "Протокол"
"search" = "Поиск"
"filter" = "Фильтр"
"loading" = "Загрузка"
"loading" = "Загрузка..."
"second" = "Секунда"
"minute" = "Минута"
"hour" = "Час"
@ -38,6 +38,8 @@
"disabled" = "Отключено"
"depleted" = "Исчерпано"
"depletingSoon" = "Почти исчерпано"
"offline" = "Офлайн"
"online" = "Онлайн"
"domainName" = "Домен"
"monitor" = "Порт IP"
"certificate" = "Сертификат"
@ -54,6 +56,7 @@
"dashboard" = "Статус системы"
"inbounds" = "Подключения"
"settings" = "Настройки панели"
"xray" = "Xray Настройки"
"logout" = "Выход"
"link" = "Прочее"
@ -132,8 +135,8 @@
"totalFlow" = "Общий расход"
"leaveBlankToNeverExpire" = "Оставьте пустым, чтобы не истекало"
"noRecommendKeepDefault" = "Нет требований для сохранения настроек по умолчанию"
"certificatePath" = "Путь файла сертификата"
"certificateContent" = "Содержимое файла сертификата"
"certificatePath" = "Путь файла"
"certificateContent" = "Содержимое файла"
"publicKeyPath" = "Путь к публичному ключу"
"publicKeyContent" = "Содержимое публичного ключа"
"keyPath" = "Путь к приватному ключу"
@ -169,6 +172,7 @@
"realityDesc" = "Версия Xray должна быть не ниже 1.8.0"
"telegramDesc" = "Используйте идентификатор Telegram без символа @ или идентификатора чата (можно получить его здесь @userinfobot или использовать команду '/id' в боте)"
"subscriptionDesc" = "Вы можете найти свою ссылку подписки в разделе 'Подробнее', также вы можете использовать одно и то же имя для нескольких конфигураций"
"info" = "Информация"
[pages.client]
"add" = "Добавить пользователя"
@ -185,6 +189,8 @@
"delayedStart" = "Начать с момента первого подключения"
"expireDays" = "Срок действия"
"days" = "дней"
"renew" = "Автопродление"
"renewDesc" = "Автоматическое продление через несколько дней после истечения срока действия. 0 = отключить"
[pages.inbounds.toasts]
"obtain" = "Получить"
@ -278,8 +284,8 @@
"subShowInfo" = "Показать информацию об использовании"
"subShowInfoDesc" = "Показывать восстановленный трафик и дату после имени конфигурации"
[pages.settings.templates]
"title" = "Шаблоны"
[pages.xray]
"title" = "Xray Настройки"
"basicTemplate" = "Базовый шаблон"
"advancedTemplate" = "Расширенный шаблон"
"completeTemplate" = "Полный шаблон"

View file

@ -1,6 +1,6 @@
"username" = "Tên người dùng"
"password" = "Mật khẩu"
"login" = "Đăng nhập"
"login" = "Đăng nhập..."
"confirm" = "Xác nhận"
"cancel" = "Hủy bỏ"
"close" = "Đóng"
@ -37,7 +37,9 @@
"enabled" = "Đã kích hoạt"
"disabled" = "Đã tắt"
"depleted" = "Đã cạn kiệt"
"depletingSoon" = "Sắp cạn kiệt"
"depletingSoon" = "Đang cạn kiệt"
"offline" = "Ngoại tuyến"
"online" = "Ngoại tuyến"
"domainName" = "Tên miền"
"monitor" = "Listening IP"
"certificate" = "Chứng chỉ"
@ -55,6 +57,7 @@
"inbounds" = "Inbounds"
"settings" = "Cài đặt bảng điều khiển"
"logout" = "Đăng xuất"
"xray" = "Xray Cài đặt"
"link" = "Khác"
[pages.login]
@ -121,6 +124,8 @@
"modifyInbound" = "Chỉnh sửa điểm vào (Inbound)"
"deleteInbound" = "Xóa điểm vào (Inbound)"
"deleteInboundContent" = "Xác nhận xóa điểm vào? (Inbound)"
"deleteClient" = "Xóa khách hàng"
"deleteClientContent" = "Bạn có chắc chắn muốn xóa ứng dụng khách không?"
"resetTrafficContent" = "Xác nhận đặt lại lưu lượng?"
"copyLink" = "Sao chép liên kết"
"address" = "Địa chỉ"
@ -132,8 +137,8 @@
"totalFlow" = "Tổng lưu lượng"
"leaveBlankToNeverExpire" = "Để trống để không bao giờ hết hạn"
"noRecommendKeepDefault" = "Không yêu cầu đặc biệt để giữ nguyên cài đặt mặc định"
"certificatePath" = "Đường dẫn tập tin chứng chỉ"
"certificateContent" = "Nội dung tập tin chứng chỉ"
"certificatePath" = "Đường dẫn tập"
"certificateContent" = "Nội dung tập"
"publicKeyPath" = "Đường dẫn khóa công khai"
"publicKeyContent" = "Nội dung khóa công khai"
"keyPath" = "Đường dẫn khóa riêng tư"
@ -169,6 +174,7 @@
"realityDesc" = "Xray core cần phiên bản 1.8.0 hoặc cao hơn."
"telegramDesc" = "Sử dụng Telegram ID mà không cần ký hiệu @ hoặc chat IDs (bạn có thể nhận được nó ở đây @userinfobot hoặc sử dụng lệnh '/id' trong bot)"
"subscriptionDesc" = "Bạn có thể tìm liên kết đăng ký của mình trong Chi tiết, cũng như bạn có thể sử dụng cùng tên cho nhiều cấu hình khác nhau"
"info" = "Thông tin"
[pages.client]
"add" = "Thêm Client"
@ -185,6 +191,8 @@
"delayedStart" = "Bắt đầu sau khi sử dụng lần đầu"
"expireDays" = "Số ngày hết hạn"
"days" = "ngày"
"renew" = "Tự động gia hạn"
"renewDesc" = "Tự động gia hạn những ngày sau khi hết hạn. 0 = tắt"
[pages.inbounds.toasts]
"obtain" = "Nhận"
@ -278,8 +286,8 @@
"subShowInfo" = "Hiển thị thông tin sử dụng"
"subShowInfoDesc" = "Hiển thị lưu lượng truy cập còn lại và ngày sau tên cấu hình"
[pages.settings.templates]
"title" = "Mẫu"
[pages.xray]
"title" = "Xray Cài đặt"
"basicTemplate" = "Mẫu Cơ bản"
"advancedTemplate" = "Mẫu Nâng cao"
"completeTemplate" = "Mẫu Đầy đủ"

View file

@ -12,7 +12,7 @@
"protocol" = "协议"
"search" = "搜尋"
"filter" = "过滤器"
"loading" = "加载中"
"loading" = "加载中..."
"second" = "秒"
"minute" = "分钟"
"hour" = "小时"
@ -38,6 +38,8 @@
"disabled" = "关闭"
"depleted" = "耗尽"
"depletingSoon" = "即将耗尽"
"offline" = "离线"
"online" = "在线"
"domainName" = "域名"
"monitor" = "监听"
"certificate" = "证书"
@ -54,6 +56,7 @@
"dashboard" = "系统状态"
"inbounds" = "入站列表"
"settings" = "面板设置"
"xray" = "Xray 设置"
"logout" = "退出登录"
"link" = "其他"
@ -121,6 +124,8 @@
"modifyInbound" = "修改入站"
"deleteInbound" = "删除入站"
"deleteInboundContent" = "确定要删除入站吗?"
"deleteClient" = "删除客户端"
"deleteClientContent" = "您确定要删除客户端吗?"
"resetTrafficContent" = "确定要重置流量吗?"
"copyLink" = "复制链接"
"address" = "地址"
@ -132,8 +137,8 @@
"totalFlow" = "总流量"
"leaveBlankToNeverExpire" = "留空则永不到期"
"noRecommendKeepDefault" = "没有特殊需求保持默认即可"
"certificatePath" = "证书文件路径"
"certificateContent" = "证书文件内容"
"certificatePath" = "文件路径"
"certificateContent" = "文件内容"
"publicKeyPath" = "公钥文件路径"
"publicKeyContent" = "公钥内容"
"keyPath" = "密钥文件路径"
@ -169,6 +174,7 @@
"realityDesc" = "Xray核心需要1.8.0及以上版本"
"telegramDesc" = "使用 Telegram ID不包含 @ 符号或聊天 ID可以在 @userinfobot 处获取,或在机器人中使用'/id'命令)"
"subscriptionDesc" = "您可以在详细信息上找到您的子链接,也可以对多个配置使用相同的名称"
"info" = "信息"
[pages.client]
"add" = "添加客户端"
@ -185,6 +191,8 @@
"delayedStart" = "首次使用后开始"
"expireDays" = "过期天数"
"days" = "天"
"renew" = "自动续订"
"renewDesc" = "过期后自动续订。0 = 禁用"
[pages.inbounds.toasts]
"obtain" = "获取"
@ -216,7 +224,6 @@
"resetDefaultConfig" = "重置为默认配置"
"panelSettings" = "面板配置"
"securitySettings" = "安全设定"
"xrayConfiguration" = "xray 相关设置"
"TGBotSettings" = "TG提醒相关设置"
"panelListeningIP" = "面板监听 IP"
"panelListeningIPDesc" = "默认留空监听所有 IP"
@ -278,8 +285,8 @@
"subShowInfo" = "显示使用信息"
"subShowInfoDesc" = "在配置名称后显示剩余流量和日期"
[pages.settings.templates]
"title" = "模板"
[pages.xray]
"title" = "Xray 设置"
"basicTemplate" = "基本模板"
"advancedTemplate" = "高级模板部件"
"completeTemplate" = "Xray 配置的完整模板"