From 663d1c08363fdb8efdd3f5d1fea8946ebf319841 Mon Sep 17 00:00:00 2001 From: ali rahimi Date: Thu, 16 Jan 2025 21:09:41 +0100 Subject: [PATCH 01/13] conflict merge --- web/assets/js/util/utils.js | 35 + web/controller/inbound.go | 82 +- web/html/common/qrcode_modal.html | 19 +- web/html/xui/client_modal.html | 445 +++++++---- web/html/xui/form/client.html | 18 +- web/html/xui/inbound_client_table.html | 6 +- web/html/xui/inbound_modal.html | 4 + web/html/xui/inbounds.html | 218 ++++- web/translation/translate.en_US.toml | 3 + web/translation/translate.fa_IR.toml | 1021 ++++++++++++------------ web/translation/translate.ru_RU.toml | 3 + web/translation/translate.vi_VN.toml | 1 + 12 files changed, 1151 insertions(+), 704 deletions(-) diff --git a/web/assets/js/util/utils.js b/web/assets/js/util/utils.js index 1659890370..41512d732e 100644 --- a/web/assets/js/util/utils.js +++ b/web/assets/js/util/utils.js @@ -83,6 +83,41 @@ class HttpUtil { } return msg; } + + static async jsonPost(url, data) { + let msg; + try { + const requestOptions = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }; + const resp = await fetch(url, requestOptions); + const response = await resp.json(); + + msg = this._respToMsg({data : response}); + } catch (e) { + msg = new Msg(false, e.toString()); + } + this._handleMsg(msg); + return msg; + } + + static async postWithModalJson(url, data, modal) { + if (modal) { + modal.loading(true); + } + const msg = await this.jsonPost(url, data); + if (modal) { + modal.loading(false); + if (msg instanceof Msg && msg.success) { + modal.close(); + } + } + return msg; + } } class PromiseUtil { diff --git a/web/controller/inbound.go b/web/controller/inbound.go index bee886773b..6f2b312c26 100644 --- a/web/controller/inbound.go +++ b/web/controller/inbound.go @@ -1,10 +1,10 @@ package controller import ( + "errors" "encoding/json" "fmt" "strconv" - "x-ui/database/model" "x-ui/web/service" "x-ui/web/session" @@ -31,8 +31,10 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) { g.POST("/del/:id", a.delInbound) g.POST("/update/:id", a.updateInbound) g.POST("/addClient", a.addInboundClient) + g.POST("/addGroupClient", a.addGroupInboundClient) g.POST("/:id/delClient/:clientId", a.delInboundClient) g.POST("/updateClient/:clientId", a.updateInboundClient) + g.POST("/updateClients", a.updateGroupInboundClient) g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic) g.POST("/resetAllTraffics", a.resetAllTraffics) g.POST("/resetAllClientTraffics/:id", a.resetAllClientTraffics) @@ -164,6 +166,34 @@ func (a *InboundController) addInboundClient(c *gin.Context) { } } +func (a *InboundController) addGroupInboundClient(c *gin.Context) { + var requestData []model.Inbound + + err := c.ShouldBindJSON(&requestData) + + if err != nil { + jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) + return + } + + needRestart := true + + for _, data := range requestData { + + needRestart, err = a.inboundService.AddInboundClient(&data) + if err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } + } + + jsonMsg(c, "Client(s) added", nil) + if err == nil && needRestart { + a.xrayService.SetToNeedRestart() + } + +} + func (a *InboundController) delInboundClient(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { @@ -208,6 +238,56 @@ func (a *InboundController) updateInboundClient(c *gin.Context) { } } +func (a *InboundController) updateGroupInboundClient(c *gin.Context) { + var requestData []map[string]interface{} + + if err := c.ShouldBindJSON(&requestData); err != nil { + jsonMsg(c, I18nWeb(c, "pages.inbounds.update"), err) + return + } + + needRestart := false + + for _, item := range requestData { + + inboundMap, ok := item["inbound"].(map[string]interface{}) + if !ok { + jsonMsg(c, "Something went wrong!", errors.New("Failed to convert 'inbound' to map")) + return + } + + clientId, ok := item["clientId"].(string) + if !ok { + jsonMsg(c, "Something went wrong!", errors.New("Failed to convert 'clientId' to string")) + return + } + + inboundJSON, err := json.Marshal(inboundMap) + if err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } + + var inboundModel model.Inbound + if err := json.Unmarshal(inboundJSON, &inboundModel); err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } + + if restart, err := a.inboundService.UpdateInboundClient(&inboundModel, clientId); err != nil { + jsonMsg(c, "Something went wrong!", err) + return + } else { + needRestart = needRestart || restart + } + } + + jsonMsg(c, "Client updated", nil) + if needRestart { + a.xrayService.SetToNeedRestart() + } +} + func (a *InboundController) resetClientTraffic(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { diff --git a/web/html/common/qrcode_modal.html b/web/html/common/qrcode_modal.html index 28349ee85e..ce79a9b62b 100644 --- a/web/html/common/qrcode_modal.html +++ b/web/html/common/qrcode_modal.html @@ -16,12 +16,14 @@ style="width: 100%; height: 100%; display: flex; border-radius: 1rem;"> - {{ i18n "pages.inbounds.client" }} - [[ clientCount[dbInbound.id].online.length ]] - + + @@ -381,7 +385,7 @@

[[ clientEmail ]]

[[ clientCount[dbInbound.id].online.length ]] - + @@ -407,7 +411,7 @@ - + @@ -416,7 +420,7 @@ [[ DateUtil.formatMillis(dbInbound.expiryTime) ]] - + @@ -807,6 +811,9 @@ case "delDepletedClients": this.delDepletedClients(-1) break; + case "addGroupClient": + this.openGroupAddClient() + break; } }, clickAction(action, dbInbound) { @@ -949,6 +956,18 @@ await this.submit(`/xui/inbound/update/${dbInbound.id}`, data, inModal); }, + openGroupAddClient() { + clientModal.show({ + title: '{{ i18n "pages.client.groupAdd"}}', + okText: '{{ i18n "pages.client.submitAdd"}}', + dbInbounds: this.dbInbounds, + confirm: async (clients, dbInboundIds) => { + await this.addGroupClient(clients, dbInboundIds, clientModal); + await this.showQrcode(dbInboundIds[0],clients[0], true) + }, + isEdit: false + }); + }, openAddClient(dbInboundId) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); clientModal.show({ @@ -957,6 +976,7 @@ dbInbound: dbInbound, confirm: async (clients, dbInboundId) => { await this.addClient(clients, dbInboundId, clientModal); + await this.showQrcode(dbInboundId,clients) }, isEdit: false }); @@ -979,6 +999,7 @@ clientModal.show({ title: '{{ i18n "pages.client.edit"}}', okText: '{{ i18n "pages.client.submitEdit"}}', + dbInbounds: this.dbInbounds, dbInbound: dbInbound, index: index, confirm: async (client, dbInboundId, clientId) => { @@ -1004,12 +1025,36 @@ }; await this.submit(`/xui/inbound/addClient`, data, modal); }, + async addGroupClient(clients, dbInboundIds, modal) { + const data = [] + dbInboundIds.forEach((dbInboundId, index) => { + data.push({ + id: dbInboundId, + settings: '{"clients": [' + clients[index].toString() + ']}', + }) + }) + await this.submit(`/x-ui/inbound/addGroupClient`, data, modal, true) + }, async updateClient(client, dbInboundId, clientId) { - const data = { - id: dbInboundId, - settings: '{"clients": [' + client.toString() + ']}', - }; - await this.submit(`/xui/inbound/updateClient/${clientId}`, data, clientModal); + if (Array.isArray(client) && Array.isArray(dbInboundId) && Array.isArray(clientId)){ + const data = [] + client.forEach((client, index) => { + data.push({ + clientId: clientId[index], + inbound: { + id: dbInboundId[index], + settings: '{"clients": [' + client.toString() + ']}', + } + }) + }) + await this.submit(`/xui/inbound/updateClients`, data, clientModal, true); + }else{ + const data = { + id: dbInboundId, + settings: '{"clients": [' + client.toString() + ']}', + }; + await this.submit(`/x-ui/inbound/updateClient/${clientId}`, data, clientModal); + } }, resetTraffic(dbInboundId) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); @@ -1037,21 +1082,79 @@ onOk: () => this.submit('/xui/inbound/del/' + dbInboundId), }); }, - delClient(dbInboundId, client,confirmation = true) { - dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); - clientId = this.getClientId(dbInbound.protocol, client); + async delClientHandler(dbInboundId, currentClient, clients = []) { + if (clients.length > 0) { + for (const client of clients) { + const dbInbound = this.dbInbounds.find(inbound => inbound.id === client.inboundId); + if (dbInbound) { + const inbound = dbInbound.toInbound(); + if (inbound && inbound.clients && inbound.clients.length === 1) { + let newClient = Inbound.Settings.getSettings(inbound.protocol).toString(); + newClient = JSON.parse(newClient); + newClient = newClient && newClient.clients && newClient.clients.length > 0 ? JSON.stringify(newClient.clients[0], null, 2) : null; + if (newClient) { + const data = { + id: client.inboundId, + settings: '{"clients": [' + newClient + ']}', + }; + await this.submit(`/panel/inbound/addClient`, data, null); + } + } + } + await this.submit(`/panel/inbound/${client.inboundId}/delClient/${client.clientId}`); + } + } else { + const dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); + const clientId = this.getClientId(dbInbound.protocol, currentClient); + await this.submit(`/panel/inbound/${dbInboundId}/delClient/${clientId}`); + } + }, + delClient(dbInboundId, currentClient, confirmation = true) { + const subGroup = this.subSettings.enable ? this.getSubGroupClients(this.dbInbounds, currentClient) : []; + const clients = subGroup && subGroup.clients && subGroup.clients.length > 0 ? subGroup.clients : []; if (confirmation){ + const clientEmails = clients.length > 0 ? clients.map(item => item.email) : currentClient.email this.$confirm({ - title: '{{ i18n "pages.inbounds.deleteClient"}}' + ' ' + client.email, + title: '{{ i18n "pages.inbounds.deleteClient"}}' + ' ' + clientEmails, content: '{{ i18n "pages.inbounds.deleteClientContent"}}', class: themeSwitcher.currentTheme, okText: '{{ i18n "delete"}}', cancelText: '{{ i18n "cancel"}}', - onOk: () => this.submit(`/xui/inbound/${dbInboundId}/delClient/${clientId}`), + onOk: () => this.delClientHandler(dbInboundId, currentClient, clients), }); } else { - this.submit(`/xui/inbound/${dbInboundId}/delClient/${clientId}`); + this.delClientHandler(dbInboundId, currentClient, clients) + } + }, + getSubGroupClients(dbInbounds, currentClient) { + const response = { + inbounds: [], + clients: [], + editIds: [] + } + if (dbInbounds && dbInbounds.length > 0 && currentClient) { + dbInbounds.forEach((dbInboundItem) => { + const dbInbound = new DBInbound(dbInboundItem); + if (dbInbound) { + const inbound = dbInbound.toInbound(); + if (inbound) { + const clients = inbound.clients; + if (clients.length > 0) { + clients.forEach((client) => { + if (client['subId'] === currentClient['subId']) { + client['inboundId'] = dbInboundItem.id + client['clientId'] = this.getClientId(dbInbound.protocol, client) + response.inbounds.push(dbInboundItem.id) + response.clients.push(client) + response.editIds.push(client['clientId']) + } + }) + } + } + } + }) } + return response; }, getClientId(protocol, client) { switch (protocol) { @@ -1080,10 +1183,10 @@ } return newDbInbound; }, - showQrcode(dbInboundId, client) { + showQrcode(dbInboundId, client, isJustSub = false) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); newDbInbound = this.checkFallback(dbInbound); - qrModal.show('{{ i18n "qrCode"}}', newDbInbound, client); + qrModal.show('{{ i18n "qrCode"}}', newDbInbound, client, isJustSub); }, showInfo(dbInboundId, client) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); @@ -1103,17 +1206,25 @@ }, async switchEnableClient(dbInboundId, client) { this.loading() - dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); - inbound = dbInbound.toInbound(); - clients = inbound.clients; - index = this.findIndexOfClient(dbInbound.protocol, clients, client); - clients[index].enable = !clients[index].enable; - clientId = this.getClientId(dbInbound.protocol, clients[index]); - await this.updateClient(clients[index], dbInboundId, clientId); + const subGroup = this.subSettings.enable ? this.getSubGroupClients(this.dbInbounds, client) : []; + if (subGroup && subGroup.clients && subGroup.clients.length > 0){ + await this.updateClient(subGroup.clients.map(item => { + item.enable = !item.enable + return item + }), subGroup.inbounds, subGroup.editIds); + }else{ + dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); + inbound = dbInbound.toInbound(); + clients = inbound.clients; + index = this.findIndexOfClient(dbInbound.protocol, clients, client); + clients[index].enable = !clients[index].enable; + clientId = this.getClientId(dbInbound.protocol, clients[index]); + await this.updateClient(clients[index], dbInboundId, clientId); + } this.loading(false); }, - async submit(url, data, modal) { - const msg = await HttpUtil.postWithModal(url, data, modal); + async submit(url, data, model, isJson = false) { + const msg = isJson ? await HttpUtil.postWithModalJson(url, data, model) : await HttpUtil.postWithModal(url, data, model); if (msg.success) { await this.getDBInbounds(); } @@ -1121,18 +1232,33 @@ getInboundClients(dbInbound) { return dbInbound.toInbound().clients; }, + resetClientTrafficHandler(client, dbInboundId, clients = []) { + if (clients.length > 0){ + clients.forEach((client) => { + const inbound = this.dbInbounds.find(inbound => inbound.id === client.inboundId) + if(inbound && this.hasClientStats(inbound, client.email)) { + this.submit('/xui/inbound/' + client.inboundId + '/resetClientTraffic/' + client.email) + } + }) + }else { + this.submit('/xui/inbound/' + dbInboundId + '/resetClientTraffic/' + client.email); + } + }, resetClientTraffic(client, dbInboundId, confirmation = true) { + const subGroup = this.subSettings.enable ? this.getSubGroupClients(this.dbInbounds, client) : []; + const clients = subGroup && subGroup.clients && subGroup.clients.length > 0 ? subGroup.clients : []; if (confirmation){ + const clientEmails = clients.length > 0 ? clients.map(item => item.email) : client.email this.$confirm({ - title: '{{ i18n "pages.inbounds.resetTraffic"}}' + ' ' + client.email, + title: '{{ i18n "pages.inbounds.resetTraffic"}}' + ' ' + clientEmails, content: '{{ i18n "pages.inbounds.resetTrafficContent"}}', class: themeSwitcher.currentTheme, okText: '{{ i18n "reset"}}', cancelText: '{{ i18n "cancel"}}', - onOk: () => this.submit('/xui/inbound/' + dbInboundId + '/resetClientTraffic/' + client.email), + onOk: () => this.resetClientTrafficHandler(client, dbInboundId, clients), }) } else { - this.submit('/xui/inbound/' + dbInboundId + '/resetClientTraffic/' + client.email); + this.resetClientTrafficHandler(client, dbInboundId, clients); } }, resetAllTraffic() { @@ -1168,6 +1294,10 @@ isExpiry(dbInbound, index) { return dbInbound.toInbound().isExpiry(index); }, + hasClientStats(dbInbound, email) { + if (email.length == 0) return 0; + return !!dbInbound.clientStats.find(stats => stats.email === email); + }, getUpStats(dbInbound, email) { if (email.length == 0) return 0; clientStats = dbInbound.clientStats.find(stats => stats.email === email); @@ -1224,13 +1354,13 @@ expColor = usageColor(new Date().getTime(), this.expireDiff, clientStats.expiryTime); switch (true) { case statsColor == "red" || expColor == "red": - return "#E04141"; + return "#cf3c3c"; // Red case statsColor == "orange" || expColor == "orange": - return "#FFA031"; - case statsColor == "blue" || expColor == "blue": - return "#0e49b5"; + return "#f37b24"; // Orange + case statsColor == "green" || expColor == "green": + return "#008771"; // Green default: - return "#7a316f"; + return "#7a316f"; // purple } }, isClientEnabled(dbInbound, email) { @@ -1271,11 +1401,11 @@ value: '', okText: '{{ i18n "pages.inbounds.import" }}', confirm: async (dbInboundText) => { - await this.submit('/xui/inbound/import', {data: dbInboundText}, promptModal); + await this.submit('/panel/inbound/import', {data: dbInboundText}, promptModal); }, }); }, - exportAllSubs() { + exportAllSubs() { let subLinks = [] for (const dbInbound of this.dbInbounds) { const clients = this.getInboundClients(dbInbound); @@ -1305,12 +1435,12 @@ }, async startDataRefreshLoop() { while (this.isRefreshEnabled) { - try { - await this.getDBInbounds(); - } catch (e) { - console.error(e); - } - await PromiseUtil.sleep(this.refreshInterval); + try { + await this.getDBInbounds(); + } catch (e) { + console.error(e); + } + await PromiseUtil.sleep(this.refreshInterval); } }, toggleRefresh() { @@ -1338,7 +1468,7 @@ } // Add option to see all in one page sizeOptions.push(i.toString()); - + p = { showSizeChanger: true, size: 'small', diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index 8185cd2e7a..1d246bf361 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -187,6 +187,9 @@ [pages.client] "add" = "Add Client" +"groupAdd" = "Agregar usuario a la suscripción" +"isGroupEdit" = "Edición de grupo" +"isGroupEditDesc" = "Se editan todos los clientes con la misma suscripción" "edit" = "Edit Client" "submitAdd" = "Add Client" "submitEdit" = "Save Changes" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index 120d892672..6391766c9d 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -1,509 +1,512 @@ -"username" = "نام‌کاربری" -"password" = "رمزعبور" -"login" = "ورود" -"confirm" = "تایید" -"cancel" = "انصراف" -"close" = "بستن" -"copy" = "کپی" -"copied" = "کپی شد" -"download" = "دانلود" -"remark" = "نام" -"enable" = "فعال" -"protocol" = "پروتکل" -"search" = "جستجو" -"filter" = "فیلتر" -"loading" = "...در حال بارگذاری" -"second" = "ثانیه" -"minute" = "دقیقه" -"hour" = "ساعت" -"day" = "روز" -"check" = "چک کردن" -"indefinite" = "نامحدود" -"unlimited" = "نامحدود" -"none" = "هیچ" -"qrCode" = "QR کد" -"info" = "اطلاعات بیشتر" -"edit" = "ویرایش" -"delete" = "حذف" -"reset" = "ریست" -"copySuccess" = "باموفقیت کپی‌شد" -"sure" = "مطمئن" -"encryption" = "رمزگذاری" -"transmission" = "راه‌اتصال" -"host" = "آدرس" -"path" = "مسیر" -"camouflage" = "مبهم‌سازی" -"status" = "وضعیت" -"enabled" = "فعال" -"disabled" = "غیرفعال" -"depleted" = "منقضی" -"depletingSoon" = "در‌حال‌انقضا" -"offline" = "آفلاین" -"online" = "آنلاین" -"domainName" = "آدرس دامنه" -"monitor" = "آدرس آی‌پی" -"certificate" = "گواهی" -"fail" = "ناموفق" -"success" = " موفق" -"getVersion" = "دریافت نسخه" -"install" = "نصب" -"clients" = "کاربران" -"usage" = "استفاده" -"remained" = "باقی‌مانده" -"secAlertTitle" = "هشدار‌ امنیتی" -"secAlertSsl" = "این‌اتصال‌امن نیست. لطفا‌ تازمانی‌که تی‌ال‌اس برای محافظت از‌ داده‌ها فعال نشده‌است، از وارد کردن اطلاعات حساس خودداری کنید" -"secAlertConf" = "تنظیمات خاصی در برابر حملات آسیب پذیر هستند. توصیه می‌شود پروتکل‌های امنیتی را برای جلوگیری از نفوذ احتمالی تقویت کنید" -"secAlertSSL" = "پنل فاقد ارتباط امن است. لطفاً یک گواهینامه تی‌ال‌اس برای محافظت از داده‌ها نصب کنید" -"secAlertPanelPort" = "استفاده از پورت پیش‌فرض پنل ناامن است. لطفاً یک پورت تصادفی یا خاص تنظیم کنید" -"secAlertPanelURI" = "مسیر پیش‌فرض لینک پنل ناامن است. لطفاً یک مسیر پیچیده تنظیم کنید" -"secAlertSubURI" = "مسیر پیش‌فرض لینک سابسکریپشن ناامن است. لطفاً یک مسیر پیچیده تنظیم کنید" -"secAlertSubJsonURI" = "مسیر پیش‌فرض لینک سابسکریپشن جیسون ناامن است. لطفاً یک مسیر پیچیده تنظیم کنید" -"security" = "امنیت" - -[menu] -"dashboard" = "نمای کلی" -"inbounds" = "ورودی‌ها" -"settings" = "تنظیمات پنل" -"xray" = "پیکربندی ایکس‌ری" -"logout" = "خروج" -"link" = "مدیریت" - -[pages.login] -"title" = "خوش‌آمدید" -"loginAgain" = "مدت زمان استفاده به‌اتمام ‌رسیده، لطفا دوباره وارد شوید" - -[pages.login.toasts] -"invalidFormData" = "اطلاعات به‌درستی وارد نشده‌است" -"emptyUsername" = "لطفا یک نام‌کاربری وارد کنید‌" -"emptyPassword" = "لطفا یک رمزعبور وارد کنید" -"wrongUsernameOrPassword" = "نام‌کاربری یا رمزعبور‌اشتباه‌است" -"successLogin" = "ورود" - -[pages.index] -"title" = "نمای کلی" -"memory" = "RAM" -"hard" = "Disk" -"serverInfo" = "سرور" -"hostname" = "نام میزبان" -"xrayStatus" = "‌ایکس‌ری" -"stopXray" = "توقف" -"restartXray" = "ریستارت" -"xraySwitch" = "تغییر‌ نسخه ایکس‌ری" -"xraySwitchClick" = "نسخه‌ مورد نظر را انتخاب کنید" -"xraySwitchClickDesk" = "لطفا بادقت انتخاب کنید. درصورت انتخاب نسخه قدیمی‌تر، امکان ناهماهنگی با پیکربندی‌های فعلی وجود دارد" -"operationHours" = "مدت‌کارکرد" -"operationHoursDesc" = "مدت کارکرد سیستم‌عامل پس‌از شروع به‌کار" -"xrayoperationHoursDesc" = "مدت کارکرد ایکس‌ری پس‌از آخرین ریستارت" -"systemLoad" = "بارسیستم" -"systemLoadDesc" = "میانگین بار در 1، 5 و 15 دقیقه گذشته" -"connectionTcpCountDesc" = "TCP کل اتصالات" -"connectionUdpCountDesc" = "UDP کل اتصالات" -"upSpeed" = "سرعت کلی آپلود" -"downSpeed" = "‌سرعت کلی دانلود" -"totalSent" = "کل ترافیک ارسالی پس‌از شروع به‌کار سیستم‌عامل" -"totalReceive" = "کل ترافیک دریافتی پس‌از شروع به‌کار سیستم‌عامل" -"xraySwitchVersionDialog" = "تغییرنسخه‌ایکس‌ری" -"xraySwitchVersionDialogDesc" = "آیا از تغییر نسخه‌ مطمئن هستید؟" -"dontRefresh" = "در حال نصب، لطفا صفحه را رفرش نکنید" -"logs" = "گزارش‌ها" -"config" = "کانفیگ" -"backup" = "پشتیبان‌گیری و بازیابی" -"backupTitle" = "پشتیبان‌گیری و بازیابی دیتابیس" -"backupDescription" = "توصیه‌می‌شود قبل‌از بازیابی دیتابیس، یک نسخه پشتیبان تهیه ‌کنید" -"exportDatabase" = "دریافت پشتیبان" -"importDatabase" = "بازیابی" - -[pages.inbounds] -"title" = "کاربران" -"totalDownUp" = "دریافت/ارسال کل" -"totalUsage" = "‌‌‌مصرف کل" -"inboundCount" = "کل ورودی‌ها" -"operate" = "منو" -"enable" = "فعال" -"remark" = "نام" -"protocol" = "پروتکل" -"port" = "پورت" -"traffic" = "ترافیک" -"details" = "جزئیات" -"transportConfig" = "نحوه اتصال" -"expireDate" = "تاریخ انقضا" -"resetTraffic" = "ریست ترافیک" -"addInbound" = "افزودن ورودی" -"generalActions" = "عملیات کلی" -"create" = "افزودن" -"update" = "ویرایش" -"modifyInbound" = "ویرایش ورودی" -"deleteInbound" = "حذف ورودی" -"deleteInboundContent" = "آیا مطمئن به حذف ورودی هستید؟" -"deleteClient" = "حذف کاربر" -"deleteClientContent" = "آیا مطمئن به حذف کاربر هستید؟" -"resetTrafficContent" = "آیا مطمئن به ریست ترافیک هستید؟" -"copyLink" = "کپی لینک" -"address" = "آدرس" -"network" = "شبکه" -"destinationPort" = "پورت مقصد" -"targetAddress" = "آدرس مقصد" -"monitorDesc" = "برای گوش‌دادن به‌تمام آی‌پی‌ها خالی‌بگذارید" -"meansNoLimit" = "صفر یعنی نامحدود. واحد: گیگابایت" -"totalFlow" = "ترافیک کل" -"leaveBlankToNeverExpire" = "برای منقضی‌نشدن خالی‌بگذارید" -"noRecommendKeepDefault" = "توصیه‌می‌شود به‌طور پیش‌فرض حفظ‌شود" -"certificatePath" = "مسیر فایل" -"certificateContent" = "محتوای فایل" -"publicKeyPath" = "مسیر کلید عمومی" -"publicKeyContent" = "محتوای کلید عمومی" -"keyPath" = "مسیر کلید خصوصی" -"keyContent" = "محتوای کلید خصوصی" -"clickOnQRcode" = "برای کپی لینک بر روی کدتصویری کلیک کنید" -"client" = "کاربر" -"export" = "استخراج لینک‌ها" -"clone" = "شبیه‌سازی" -"cloneInbound" = "شبیه‌سازی ورودی" -"cloneInboundContent" = "همه موارد این ورودی بجز پورت، آی‌پی و کاربر‌ها شبیه‌سازی خواهند شد" -"resetAllTraffic" = "ریست ترافیک کل ورودی‌ها" -"resetAllTrafficTitle" = "ریست ترافیک کل ورودی‌ها" -"resetAllTrafficContent" = "آیا مطمئن به ریست ترافیک تمام ورودی‌ها هستید؟" -"resetInboundClientTraffics" = "ریست ترافیک کاربران" -"resetInboundClientTrafficTitle" = "ریست ترافیک کاربران" -"resetInboundClientTrafficContent" = "آیا مطمئن به ریست ترافیک تمام کاربران این‌ ورودی هستید؟" -"resetAllClientTraffics" = "ریست ترافیک کل کاربران" -"resetAllClientTrafficTitle" = "ریست ترافیک کل کاربران" -"resetAllClientTrafficContent" = "آیا مطمئن به ریست ترافیک تمام کاربران هستید؟" -"delDepletedClients" = "حذف کاربران منقضی" -"delDepletedClientsTitle" = "حذف کاربران منقضی" -"delDepletedClientsContent" = "آیا مطمئن به حذف تمام کاربران منقضی‌شده ‌هستید؟" -"email" = "ایمیل" -"emailDesc" = "باید یک ایمیل یکتا باشد" -"setDefaultCert" = "استفاده از گواهی پنل" -"telegramDesc" = "دریافت کنید‌ '/id'یا دستور @userinfobot آی‌دی‌(های) چت مدیر را بدون '@' واردکنید. از" -"subscriptionDesc" = "لینک سابسکربپشن خودرا در 'اطلاعات بیشتر' پیدا کنید، همچنین می‌توانید از همین نام برای چندین کاربر استفاده‌کنید" -"info" = "اطلاعات" -"same" = "همسان" -"inboundData" = "داده‌های ورودی" -"exportInbound" = "استخراج ورودی" -"import" = "افزودن" -"importInbound" = "افزودن یک ورودی" - -[pages.client] -"add" = "کاربر جدید" -"edit" = "ویرایش کاربر" -"submitAdd" = "اضافه کردن" -"submitEdit" = "ذخیره تغییرات" -"clientCount" = "تعداد کاربران" -"bulk" = "انبوه‌سازی" -"method" = "روش" -"first" = "از" -"last" = "تا" -"prefix" = "پیشوند" -"postfix" = "پسوند" -"delayedStart" = "شروع‌پس‌از‌اولین‌استفاده" -"expireDays" = "مدت زمان" -"days" = "(روز)" -"renew" = "تمدید خودکار" -"renewDesc" = "تمدید خودکار پس‌از ‌انقضا. 0 = غیرفعال - واحد: روز" - -[pages.inbounds.toasts] -"obtain" = "فراهم‌سازی" - -[pages.inbounds.stream.general] -"request" = "درخواست" -"response" = "پاسخ" -"name" = "نام" -"value" = "مقدار" - -[pages.inbounds.stream.tcp] -"version" = "نسخه" -"method" = "متد" -"path" = "مسیر" -"status" = "وضعیت" -"statusDescription" = "توضیحات وضعیت" -"requestHeader" = "سربرگ درخواست" -"responseHeader" = "سربرگ پاسخ" - -[pages.settings] -"title" = "تنظیمات پنل" -"save" = "ذخیره" -"infoDesc" = "برای اعمال تغییرات در این بخش باید پس از ذخیره کردن، پنل را ریستارت کنید" -"restartPanel" = "ریستارت پنل" -"restartPanelDesc" = "آیا مطمئن به ریستارت پنل هستید؟ اگر پس‌از ریستارت نتوانستید به پنل دسترسی پیدا کنید، گزارش‌های موجود در اسکریپت پنل را بررسی کنید" -"resetDefaultConfig" = "برگشت به پیش‌فرض" -"panelConfig" = "عمومی" -"userSettings" = "احرازهویت" -"TGBotSettings" = "ربات تلگرام" -"panelListeningIP" = "آدرس آی‌پی" -"panelListeningIPDesc" = "آدرس آی‌پی برای وب پنل. برای گوش‌دادن به‌تمام آی‌پی‌ها خالی‌بگذارید" -"panelListeningDomain" = "نام دامنه" -"panelListeningDomainDesc" = "آدرس دامنه برای وب پنل. برای گوش‌دادن به‌تمام دامنه‌ها و آی‌پی‌ها خالی‌بگذارید" -"panelPort" = "شماره پورت" -"panelPortDesc" = "شماره پورت برای وب پنل. باید پورت استفاده نشده‌باشد" -"publicKeyPath" = "مسیر کلید عمومی" -"publicKeyPathDesc" = "مسیر فایل کلیدعمومی برای وب پنل. با '/' شروع‌می‌شود" -"privateKeyPath" = "مسیر کلید خصوصی" -"privateKeyPathDesc" = "مسیر فایل کلیدخصوصی برای وب پنل. با '/' شروع‌می‌شود" -"panelUrlPath" = "URI مسیر" -"panelUrlPathDesc" = "مسیر لینک وب پنل. با '/' شروع‌ و با '/' خاتمه‌ می‌یابد" -"pageSize" = "اندازه صفحه بندی جدول" -"pageSizeDesc" = "اندازه صفحه برای جدول ورودی‌ها. 0 = غیرفعال" -"remarkModel" = "نام‌کانفیگ و جداکننده" -"sampleRemark" = "نمونه‌نام" -"oldUsername" = "نام‌کاربری فعلی" -"currentPassword" = "رمز‌عبور فعلی" -"newUsername" = "نام‌کاربری جدید" -"newPassword" = "رمزعبور جدید" -"telegramBotEnable" = "فعال‌سازی ربات تلگرام" -"telegramBotEnableDesc" = "ربات تلگرام را فعال می‌کند" -"telegramToken" = "توکن تلگرام" -"telegramTokenDesc" = "دریافت کنید @botfather توکن تلگرام، از" -"telegramChatId" = "آی‌دی چت مدیر" -"telegramChatIdDesc" = "دریافت کنید '/id'یا دستور @userinfobot آی‌دی(های) چت مدیر، از" -"telegramNotifyTime" = "زمان اطلاع‌رسانی" -"telegramNotifyTimeDesc" = "زمان‌اطلاع‌رسانی ربات تلگرام برای ارسال گزارش‌های دوره‌ای. از فرمت زمانی کرون‌تاب استفاده‌کنید‌" -"tgNotifyBackup" = "پشتیبان‌گیری دیتابیس" -"tgNotifyBackupDesc" = "فایل پشتیبان دیتابیس را به‌همراه گزارش‌ دریافت می‌کنید‌" -"tgNotifyLogin" = "اطلاع‌رسانی ورود" -"tgNotifyLoginDesc" = "هر زمان کسی سعی به ورود به وب پنل شما را داشت. درباره نام‌کاربری، آی‌پی و زمان، مطلع می‌شوید" -"sessionMaxAge" = "مدت جلسه" -"sessionMaxAgeDesc" = "بیشینه مدت زمانی‌که می‌توانید لاگین بمانید. واحد: دقیقه" -"expireTimeDiff" = "اطلاع‌رسانی زمان انقضا" -"expireTimeDiffDesc" = "وقتی زمان باقی‌مانده به‌آستانه تعیین‌شده رسید، مطلع می‌شوید. واحد: روز" -"trafficDiff" = "اطلاع‌رسانی ترافیک باقی‌مانده" -"trafficDiffDesc" = "وقتی‌ ترافیک باقی‌مانده به‌آستانه تعیین‌شده رسید، مطلع می‌شوید. واحد: گیگابایت" -"tgNotifyCpu" = "اطلاع‌رسانی بار پردازنده" -"tgNotifyCpuDesc" = "اگر بار پردازنده از آستانه تعیین‌شده فراتر رفت، مطلع می‌شوید. واحد: درصد" -"timeZone" = "منطقه زمانی" -"timeZoneDesc" = "وظایف برنامه ریزی شده بر اساس این منطقه‌زمانی اجرا می‌شود" -"subSettings" = "سابسکریپشن" -"subEnable" = "فعال‌سازی سرویس سابسکریپشن" -"subEnableDesc" = " سرویس سابسکریپشن‌ را فعال می‌کند" -"subListen" = "آدرس آی‌پی" -"subListenDesc" = "آدرس آی‌پی برای سابسکریپشن. برای گوش‌دادن به‌تمام آی‌پی‌ها خالی‌بگذارید" -"subPort" = "شماره پورت" -"subPortDesc" = "شماره پورت برای سابسکریپشن. باید پورت استفاده نشده‌باشد" -"subCertPath" = "مسیر کلید عمومی" -"subCertPathDesc" = "مسیر فایل کلیدعمومی برای سابیکریپشن. با '/' شروع‌می‌شود" -"subKeyPath" = "مسیر کلید خصوصی" -"subKeyPathDesc" = "مسیر فایل کلیدخصوصی برای سابسکریپشن. با '/' شروع‌می‌شود" -"subPath" = "URI مسیر" -"subPathDesc" = "مسیر لینک سابسکریپشن. با '/' شروع‌ و با '/' خاتمه‌ می‌یابد" -"subDomain" = "نام دامنه" -"subDomainDesc" = "آدرس دامنه برای سابسکریپشن. برای گوش‌دادن به‌تمام دامنه‌ها و آی‌پی‌ها خالی‌بگذارید‌" -"subUpdates" = "فاصله بروزرسانی‌" -"subUpdatesDesc" = "فاصله مابین بروزرسانی لینک سابسکریپشن در برنامه‌های کاربری. واحد: ساعت" -"subEncrypt" = "کدگذاری" -"subEncryptDesc" = " محتوای برگشتی سابسکریپشن برپایه بیس64 کدگذاری خواهدشد" -"subShowInfo" = "نمایش اطلاعات مصرف" -"subShowInfoDesc" = "ترافیک و زمان باقی‌مانده را در برنامه‌های کاربری نمایش می‌دهد" -"subURI" = "پراکسی معکوس URI" -"subURIDesc" = "سابسکریپشن از لینکی که در پشت پراکسی‌های معکوس تنظیم شده‌، استفاده خواهدکرد" -"fragment" = "تکه‌تکه شدن" -"fragmentDesc" = "فعال کردن تکه تکه شدن برای بسته نخست تی‌ال‌اس" -"fragmentSett" = "تنظیمات فرگمنت" -"noisesDesc" = "فعال کردن Noises." -"noisesSett" = "تنظیمات Noises" -"mux" = "ماکس" -"muxDesc" = "چندین جریان داده مستقل را در یک جریان داده ثابت منتقل می کند" -"muxSett" = "تنظیمات ماکس" -"direct" = "اتصال مستقیم" -"directDesc" = "به طور مستقیم با دامنه ها یا محدوده آی‌پی یک کشور خاص ارتباط برقرار می کند" - -[pages.settings.toasts] -"modifySettings" = "ویرایش تنظیمات" -"getSettings" = "دریافت تنظیمات" -"modifyUser" = "ویرایش مدیر" -"originalUserPassIncorrect" = "نام‌کاربری یا رمزعبور فعلی اشتباه‌است" -"userPassMustBeNotEmpty" = "نام‌کاربری یا رمزعبور جدید خالی‌است" - -[pages.xray] -"title" = "پیکربندی ایکس‌ری" -"save" = "ذخیره" -"restart" = "ریستارت ایکس‌ری" -"basicTemplate" = "پایه" -"advancedTemplate" = "پیشرفته" -"generalConfigs" = "استراتژی‌ کلی" -"generalConfigsDesc" = "این گزینه‌ها استراتژی کلی ترافیک را تعیین می‌کنند" -"logConfigs" = "تنظیمات گزار‌ش‌ها" -"logConfigsDesc" = "فعال کردن گزارش ممکن است بر عملکرد سرور شما تأثیر بگذارد. توصیه می‌شود فقط در صورت لزوم آن را با دقت فعال کنید" -"blockConfigs" = "سپر محافظ" -"blockConfigsDesc" = "این گزینه‌ها ترافیک را بر اساس پروتکل‌های درخواستی خاص، و وب سایت‌ها مسدود می‌کند" -"basicRouting" = "مسیریابی پایه" -"blockConnectionsConfigsDesc" = "این گزینه‌ها ترافیک را بر اساس کشور درخواست‌شده خاص مسدود می‌کنند." -"directConnectionsConfigsDesc" = "یک اتصال مستقیم تضمین می‌کند که ترافیک خاص از طریق سرور دیگری مسیریابی نشود." -"blockips" = "مسدود کردن آی‌پی‌ها" -"blockdomains" = "مسدود کردن دامنه‌ها" -"directips" = "آی‌پی‌های مستقیم" -"directdomains" = "دامنه‌های مستقیم" -"ipv4Routing" = "IPv4 مسیریابی" -"ipv4RoutingDesc" = "این گزینه‌ها ترافیک را از طریق آی‌پی نسخه4 سرور، به مقصد هدایت می‌کند" -"warpRouting" = "WARP مسیریابی" -"warpRoutingDesc" = "این گزینه‌ها ترافیک‌ را از طریق وارپ کلادفلر به مقصد هدایت می‌کند" -"Template" = "‌پیکربندی پیشرفته الگو ایکس‌ری" -"TemplateDesc" = "فایل پیکربندی نهایی ایکس‌ری بر اساس این الگو ایجاد می‌شود" -"FreedomStrategy" = "Freedom استراتژی پروتکل" -"FreedomStrategyDesc" = "تعیین می‌کند Freedom استراتژی خروجی شبکه را برای پروتکل" -"RoutingStrategy" = "استراتژی کلی مسیریابی" -"RoutingStrategyDesc" = "استراتژی کلی مسیریابی برای حل تمام درخواست‌ها را تعیین می‌کند" -"Torrent" = "مسدودسازی پروتکل بیت‌تورنت" -"TorrentDesc" = "پروتکل بیت تورنت را مسدود می‌کند" -"Family" = "محافظ خانواده" -"FamilyDesc" = "محتوای مخصوص بزرگسالان، و وبسایت‌های ناامن را مسدود می‌کند" -"Inbounds" = "ورودی‌ها" -"Outbounds" = "خروجی‌ها" -"Routings" = "قوانین مسیریابی" -"RoutingsDesc" = "اولویت هر قانون مهم است" -"Balancers" = "بالانسرها" -"logLevel" = "سطح گزارش" -"logLevelDesc" = "سطح گزارش، شدت مسائلی را که باید ثبت شوند، تعیین می‌کند" -"accessLog" = "گزارش دسترسی" -"accessLogDesc" = "مسیر فایل گزارش دسترسی" -"errorLog" = "گزارش خطا" -"errorLogDesc" = "مسیر فایل گزارش خطا" -"dnsLog" = "گزارش DNS" -"dnsLogDesc" = "آیا ثبت‌های درخواست DNS را فعال کنید" -"maskAddress" = "پنهان کردن آدرس" -"maskAddressDesc" = "پوشش آدرس IP، هنگامی که فعال می‌شود، به طور خودکار آدرس IP که در لاگ ظاهر می‌شود را جایگزین می‌کند." - -[pages.xray.rules] -"first" = "اولین" -"last" = "آخرین" -"up" = "بالا" -"down" = "پایین" -"source" = "مبدا" -"dest" = "مقصد" -"inbound" = "ورودی" -"outbound" = "خروجی" -"info" = "اطلاعات" -"add" = "افزودن قانون" -"edit" = "ویرایش قانون" -"useComma" = "موارد جداشده با کاما" -"balancer" = "بالانسر" - -[pages.xray.outbound] -"addOutbound" = "افزودن خروجی" -"addReverse" = "افزودن معکوس" -"editOutbound" = "ویرایش خروجی" -"editReverse" = "ویرایش معکوس" -"tag" = "برچسب" -"tagDesc" = "برچسب یگانه" -"address" = "آدرس" -"reverse" = "معکوس" -"domain" = "دامنه" -"type" = "نوع" -"bridge" = "پل" -"portal" = "پورتال" -"intercon" = "اتصال میانی" -"settings" = "تنظیمات" -"accountInfo" = "اطلاعات حساب" -"outboundStatus" = "وضعیت خروجی" -"sendThrough" = "ارسال با" - -[pages.xray.balancer] -"addBalancer" = "افزودن بالانسر" -"editBalancer" = "ویرایش بالانسر" -"balancerStrategy" = "استراتژی" -"balancerSelectors" = "انتخاب‌گرها" -"fallback" = "جایگزین" -"tag" = "برچسب" -"tagDesc" = "برچسب یگانه" -"balancerDesc" = "امکان استفاده همزمان برچسب خروجی و برچسب بالانسر باهم وجود ندارد. درصورت استفاده همزمان فقط برچسب خروجی عمل خواهد کرد" - -[pages.xray.wireguard] -"secretKey" = "کلید شخصی" -"publicKey" = "کلید عمومی" -"allowedIPs" = "آی‌پی‌های مجاز" -"endpoint" = "نقطه پایانی" -"psk" = "کلید مشترک" -"domainStrategy" = "استراتژی حل دامنه" - -[pages.xray.dns] -"enable" = "فعال کردن حل دامنه" -"enableDesc" = "سرور حل دامنه داخلی را فعال می‌کند" -"tag" = "برچسب" -"tagDesc" = "این برچسب در قوانین مسیریابی به عنوان یک برچسب ورودی قابل استفاده خواهد بود" -"strategy" = "استراتژی پرس‌وجو" -"strategyDesc" = "استراتژی کلی برای حل نام‌دامنه" -"add" = "افزودن سرور" -"edit" = "ویرایش سرور" -"domains" = "دامنه‌ها" -"expectIPs" = "آی‌پی‌های مورد انتظار" - -[pages.xray.fakedns] -"add" = "افزودن دی‌ان‌اس جعلی" -"edit" = "ویرایش دی‌ان‌اس جعلی" -"ipPool" = "زیرشبکه استخر آی‌پی" -"poolSize" = "اندازه استخر" - -[tgbot] -"noResult" = "❗نتیجه‌ای یافت نشد" -"wentWrong" = "❌ مشکلی رخ داده‌است" -"noInbounds" = " هیچ ورودی یافت نشد" -"unlimited" = "♾ نامحدود" -"day" = "روز" -"days" = "روزها" -"unknown" = "نامشخص" -"inbounds" = "ورودی‌ها" -"clients" = "کاربران" - -[tgbot.commands] -"unknown" = "❗ دستور ناشناخته" -"pleaseChoose" = "👇 لطفاًانتخاب کنید:\r\n" -"help" = "🤖 به این ربات خوش‌آمدید! این ربات برای ارائه داده‌های خاص از وب پنل طراحی شده‌است و به‌شما امکان تغییرات لازم را می‌دهد\r\n\r\n" -"start" = "👋 سلام {{ .Firstname }}.\r\n" -"welcome" = "🤖 به‌ربات مدیریت {{ .Hostname }} خوش‌آمدید\r\n" -"status" = "✅ ربات‌درحالت‌عادی‌است" -"usage" = "❗ لطفا یک متن برای جستجو واردکنید" -"getID" = "🆔 شناسه‌شما: {{ .ID }}" -"helpAdminCommands" = "برای جستجوی ایمیل کاربر:\r\n/usage [ایمیل]\r\n \r\nبرای جستجوی ورودی‌ها (با آمار کاربر):\r\n/inbound [توضیح]" -"helpClientCommands" = "برای جستجوی آمار، فقط از دستور زیر استفاده‌کنید:\r\n \r\n/usage [UUID|رمز عبور]\r\n \r\nاز رمزعبور استفاده کنید Trojan/Shadowsocks و برای UUID از VMess/VLESS برای" - -[tgbot.messages] -"cpuThreshold" = "🔴 بار ‌پردازنده {{ .Percent }}% بیشتر از آستانه است {{ .Threshold }}%" -"loginSuccess" = "✅ باموفقیت به پنل واردشدید \r\n" -"loginFailed" = "❗️ ورود به پنل ناموفق‌بود \r\n" -"report" = "🕰 گزارشات‌زمان‌بندی‌شده: {{ .RunTime }}\r\n" -"datetime" = "⏰ تاریخ‌وزمان: {{ .DateTime }}\r\n" -"hostname" = "💻 نام‌میزبان: {{ .Hostname }}\r\n" -"version" = "🚀 X-UI: {{ .Version }}\r\n" -"ipv6" = "🌐 IPv6: {{ .IPv6 }}\r\n" -"ipv4" = "🌐 IPv4: {{ .IPv4 }}\r\n" -"ip" = "🌐 IP: {{ .IP }}\r\n" -"serverUpTime" = "⏳ مدت‌کارکرد: {{ .UpTime }} {{ .Unit }}\r\n" -"serverLoad" = "📈 بارسیستم: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n" -"serverMemory" = "📋 RAM: {{ .Current }}/{{ .Total }}\r\n" -"tcpCount" = "🔹 TCP: {{ .Count }}\r\n" -"udpCount" = "🔸 UDP: {{ .Count }}\r\n" -"traffic" = "🚦 ترافیک: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n" -"xrayStatus" = "ℹ️ وضعیت‌: {{ .State }}\r\n" -"username" = "👤 نام‌کاربری: {{ .Username }}\r\n" -"time" = "⏰ زمان: {{ .Time }}\r\n" -"inbound" = "📍 نام‌ورودی: {{ .Remark }}\r\n" -"port" = "🔌 پورت: {{ .Port }}\r\n" -"expire" = "📅 تاریخ‌انقضا: {{ .DateTime }}\r\n \r\n" -"expireIn" = "📅 انقضا در: {{ .Time }}\r\n \r\n" -"active" = "💡 فعال: {{ .Enable }}\r\n" -"online" = "🌐 وضعیت‌اتصال: {{ .Status }}\r\n" -"email" = "📧 ایمیل: {{ .Email }}\r\n" -"upload" = "🔼 آپلود↑: {{ .Upload }}\r\n" -"download" = "🔽 دانلود↓: {{ .Download }}\r\n" -"total" = "🔄 کل: {{ .UpDown }} / {{ .Total }}\r\n" -"exhaustedMsg" = "🚨 {{ .Type }} به‌اتمام‌رسیده‌است:\r\n" -"exhaustedCount" = "🚨 تعداد {{ .Type }} به‌اتمام رسیده‌است:\r\n" -"onlinesCount" = "🌐 کاربران‌آنلاین: {{ .Count }}\r\n" -"disabled" = "🛑 غیرفعال: {{ .Disabled }}\r\n" -"depleteSoon" = "🔜 به‌زودی به‌پایان خواهدرسید: {{ .Deplete }}\r\n \r\n" -"backupTime" = "🗄 زمان‌پشتیبان‌گیری: {{ .Time }}\r\n" -"yes" = "✅ بله" -"no" = "❌ خیر" - -[tgbot.buttons] -"dbBackup" = "دریافت فایل پشتیبان" -"serverUsage" = "استفاده از سیستم" -"getInbounds" = "دریافت ورودی‌ها" -"depleteSoon" = "به‌زودی به‌پایان خواهدرسید" -"clientUsage" = "دریافت آمار کاربر" -"onlines" = "کاربران آنلاین" -"commands" = "دستورات" - -[tgbot.answers] -"getInboundsFailed" = "❌ دریافت ورودی‌ها باخطا مواجه شد" -"askToAddUser" = "پیکربندی شما پیدا نشد!\r\nشما باید نام‌کاربری تلگرام خود را تنظیم کنید و از مدیر سرویس خود بخواهید که آن را به پیکربندی(های) شما اضافه کند" -"askToAddUserName" = "پیکربندی شما یافت نشد!\r\nلطفاً از مدیر سرویس خود بخواهید اطلاعات تلگرام شما را به پیکربندی(های) شما اضافه کند \r\n\r\nنام‌کاربری شما: @{{ .TgUserName }}" +"username" = "نام‌کاربری" +"password" = "رمزعبور" +"login" = "ورود" +"confirm" = "تایید" +"cancel" = "انصراف" +"close" = "بستن" +"copy" = "کپی" +"copied" = "کپی شد" +"download" = "دانلود" +"remark" = "نام" +"enable" = "فعال" +"protocol" = "پروتکل" +"search" = "جستجو" +"filter" = "فیلتر" +"loading" = "...در حال بارگذاری" +"second" = "ثانیه" +"minute" = "دقیقه" +"hour" = "ساعت" +"day" = "روز" +"check" = "چک کردن" +"indefinite" = "نامحدود" +"unlimited" = "نامحدود" +"none" = "هیچ" +"qrCode" = "QR کد" +"info" = "اطلاعات بیشتر" +"edit" = "ویرایش" +"delete" = "حذف" +"reset" = "ریست" +"copySuccess" = "باموفقیت کپی‌شد" +"sure" = "مطمئن" +"encryption" = "رمزگذاری" +"transmission" = "راه‌اتصال" +"host" = "آدرس" +"path" = "مسیر" +"camouflage" = "مبهم‌سازی" +"status" = "وضعیت" +"enabled" = "فعال" +"disabled" = "غیرفعال" +"depleted" = "منقضی" +"depletingSoon" = "در‌حال‌انقضا" +"offline" = "آفلاین" +"online" = "آنلاین" +"domainName" = "آدرس دامنه" +"monitor" = "آدرس آی‌پی" +"certificate" = "گواهی" +"fail" = "ناموفق" +"success" = " موفق" +"getVersion" = "دریافت نسخه" +"install" = "نصب" +"clients" = "کاربران" +"usage" = "استفاده" +"remained" = "باقی‌مانده" +"secAlertTitle" = "هشدار‌ امنیتی" +"secAlertSsl" = "این‌اتصال‌امن نیست. لطفا‌ تازمانی‌که تی‌ال‌اس برای محافظت از‌ داده‌ها فعال نشده‌است، از وارد کردن اطلاعات حساس خودداری کنید" +"secAlertConf" = "تنظیمات خاصی در برابر حملات آسیب پذیر هستند. توصیه می‌شود پروتکل‌های امنیتی را برای جلوگیری از نفوذ احتمالی تقویت کنید" +"secAlertSSL" = "پنل فاقد ارتباط امن است. لطفاً یک گواهینامه تی‌ال‌اس برای محافظت از داده‌ها نصب کنید" +"secAlertPanelPort" = "استفاده از پورت پیش‌فرض پنل ناامن است. لطفاً یک پورت تصادفی یا خاص تنظیم کنید" +"secAlertPanelURI" = "مسیر پیش‌فرض لینک پنل ناامن است. لطفاً یک مسیر پیچیده تنظیم کنید" +"secAlertSubURI" = "مسیر پیش‌فرض لینک سابسکریپشن ناامن است. لطفاً یک مسیر پیچیده تنظیم کنید" +"secAlertSubJsonURI" = "مسیر پیش‌فرض لینک سابسکریپشن جیسون ناامن است. لطفاً یک مسیر پیچیده تنظیم کنید" +"security" = "امنیت" + +[menu] +"dashboard" = "نمای کلی" +"inbounds" = "ورودی‌ها" +"settings" = "تنظیمات پنل" +"xray" = "پیکربندی ایکس‌ری" +"logout" = "خروج" +"link" = "مدیریت" + +[pages.login] +"title" = "خوش‌آمدید" +"loginAgain" = "مدت زمان استفاده به‌اتمام ‌رسیده، لطفا دوباره وارد شوید" + +[pages.login.toasts] +"invalidFormData" = "اطلاعات به‌درستی وارد نشده‌است" +"emptyUsername" = "لطفا یک نام‌کاربری وارد کنید‌" +"emptyPassword" = "لطفا یک رمزعبور وارد کنید" +"wrongUsernameOrPassword" = "نام‌کاربری یا رمزعبور‌اشتباه‌است" +"successLogin" = "ورود" + +[pages.index] +"title" = "نمای کلی" +"memory" = "RAM" +"hard" = "Disk" +"serverInfo" = "سرور" +"hostname" = "نام میزبان" +"xrayStatus" = "‌ایکس‌ری" +"stopXray" = "توقف" +"restartXray" = "ریستارت" +"xraySwitch" = "تغییر‌ نسخه ایکس‌ری" +"xraySwitchClick" = "نسخه‌ مورد نظر را انتخاب کنید" +"xraySwitchClickDesk" = "لطفا بادقت انتخاب کنید. درصورت انتخاب نسخه قدیمی‌تر، امکان ناهماهنگی با پیکربندی‌های فعلی وجود دارد" +"operationHours" = "مدت‌کارکرد" +"operationHoursDesc" = "مدت کارکرد سیستم‌عامل پس‌از شروع به‌کار" +"xrayoperationHoursDesc" = "مدت کارکرد ایکس‌ری پس‌از آخرین ریستارت" +"systemLoad" = "بارسیستم" +"systemLoadDesc" = "میانگین بار در 1، 5 و 15 دقیقه گذشته" +"connectionTcpCountDesc" = "TCP کل اتصالات" +"connectionUdpCountDesc" = "UDP کل اتصالات" +"upSpeed" = "سرعت کلی آپلود" +"downSpeed" = "‌سرعت کلی دانلود" +"totalSent" = "کل ترافیک ارسالی پس‌از شروع به‌کار سیستم‌عامل" +"totalReceive" = "کل ترافیک دریافتی پس‌از شروع به‌کار سیستم‌عامل" +"xraySwitchVersionDialog" = "تغییرنسخه‌ایکس‌ری" +"xraySwitchVersionDialogDesc" = "آیا از تغییر نسخه‌ مطمئن هستید؟" +"dontRefresh" = "در حال نصب، لطفا صفحه را رفرش نکنید" +"logs" = "گزارش‌ها" +"config" = "کانفیگ" +"backup" = "پشتیبان‌گیری و بازیابی" +"backupTitle" = "پشتیبان‌گیری و بازیابی دیتابیس" +"backupDescription" = "توصیه‌می‌شود قبل‌از بازیابی دیتابیس، یک نسخه پشتیبان تهیه ‌کنید" +"exportDatabase" = "دریافت پشتیبان" +"importDatabase" = "بازیابی" + +[pages.inbounds] +"title" = "کاربران" +"totalDownUp" = "دریافت/ارسال کل" +"totalUsage" = "‌‌‌مصرف کل" +"inboundCount" = "کل ورودی‌ها" +"operate" = "منو" +"enable" = "فعال" +"remark" = "نام" +"protocol" = "پروتکل" +"port" = "پورت" +"traffic" = "ترافیک" +"details" = "جزئیات" +"transportConfig" = "نحوه اتصال" +"expireDate" = "تاریخ انقضا" +"resetTraffic" = "ریست ترافیک" +"addInbound" = "افزودن ورودی" +"generalActions" = "عملیات کلی" +"create" = "افزودن" +"update" = "ویرایش" +"modifyInbound" = "ویرایش ورودی" +"deleteInbound" = "حذف ورودی" +"deleteInboundContent" = "آیا مطمئن به حذف ورودی هستید؟" +"deleteClient" = "حذف کاربر" +"deleteClientContent" = "آیا مطمئن به حذف کاربر هستید؟" +"resetTrafficContent" = "آیا مطمئن به ریست ترافیک هستید؟" +"copyLink" = "کپی لینک" +"address" = "آدرس" +"network" = "شبکه" +"destinationPort" = "پورت مقصد" +"targetAddress" = "آدرس مقصد" +"monitorDesc" = "برای گوش‌دادن به‌تمام آی‌پی‌ها خالی‌بگذارید" +"meansNoLimit" = "صفر یعنی نامحدود. واحد: گیگابایت" +"totalFlow" = "ترافیک کل" +"leaveBlankToNeverExpire" = "برای منقضی‌نشدن خالی‌بگذارید" +"noRecommendKeepDefault" = "توصیه‌می‌شود به‌طور پیش‌فرض حفظ‌شود" +"certificatePath" = "مسیر فایل" +"certificateContent" = "محتوای فایل" +"publicKeyPath" = "مسیر کلید عمومی" +"publicKeyContent" = "محتوای کلید عمومی" +"keyPath" = "مسیر کلید خصوصی" +"keyContent" = "محتوای کلید خصوصی" +"clickOnQRcode" = "برای کپی لینک بر روی کدتصویری کلیک کنید" +"client" = "کاربر" +"export" = "استخراج لینک‌ها" +"clone" = "شبیه‌سازی" +"cloneInbound" = "شبیه‌سازی ورودی" +"cloneInboundContent" = "همه موارد این ورودی بجز پورت، آی‌پی و کاربر‌ها شبیه‌سازی خواهند شد" +"resetAllTraffic" = "ریست ترافیک کل ورودی‌ها" +"resetAllTrafficTitle" = "ریست ترافیک کل ورودی‌ها" +"resetAllTrafficContent" = "آیا مطمئن به ریست ترافیک تمام ورودی‌ها هستید؟" +"resetInboundClientTraffics" = "ریست ترافیک کاربران" +"resetInboundClientTrafficTitle" = "ریست ترافیک کاربران" +"resetInboundClientTrafficContent" = "آیا مطمئن به ریست ترافیک تمام کاربران این‌ ورودی هستید؟" +"resetAllClientTraffics" = "ریست ترافیک کل کاربران" +"resetAllClientTrafficTitle" = "ریست ترافیک کل کاربران" +"resetAllClientTrafficContent" = "آیا مطمئن به ریست ترافیک تمام کاربران هستید؟" +"delDepletedClients" = "حذف کاربران منقضی" +"delDepletedClientsTitle" = "حذف کاربران منقضی" +"delDepletedClientsContent" = "آیا مطمئن به حذف تمام کاربران منقضی‌شده ‌هستید؟" +"email" = "ایمیل" +"emailDesc" = "باید یک ایمیل یکتا باشد" +"setDefaultCert" = "استفاده از گواهی پنل" +"telegramDesc" = "دریافت کنید‌ '/id'یا دستور @userinfobot آی‌دی‌(های) چت مدیر را بدون '@' واردکنید. از" +"subscriptionDesc" = "لینک سابسکربپشن خودرا در 'اطلاعات بیشتر' پیدا کنید، همچنین می‌توانید از همین نام برای چندین کاربر استفاده‌کنید" +"info" = "اطلاعات" +"same" = "همسان" +"inboundData" = "داده‌های ورودی" +"exportInbound" = "استخراج ورودی" +"import" = "افزودن" +"importInbound" = "افزودن یک ورودی" + +[pages.client] +"add" = "کاربر جدید" +"groupAdd" = "افزودن کاربر سابسکریپشن" +"isGroupEdit" = "ویرایش گروهی" +"isGroupEditDesc" = "همه کاربران با سابسکریپشن یکسان ویرایش می شوند" +"edit" = "ویرایش کاربر" +"submitAdd" = "اضافه کردن" +"submitEdit" = "ذخیره تغییرات" +"clientCount" = "تعداد کاربران" +"bulk" = "انبوه‌سازی" +"method" = "روش" +"first" = "از" +"last" = "تا" +"prefix" = "پیشوند" +"postfix" = "پسوند" +"delayedStart" = "شروع‌پس‌از‌اولین‌استفاده" +"expireDays" = "مدت زمان" +"days" = "(روز)" +"renew" = "تمدید خودکار" +"renewDesc" = "تمدید خودکار پس‌از ‌انقضا. 0 = غیرفعال - واحد: روز" + +[pages.inbounds.toasts] +"obtain" = "فراهم‌سازی" + +[pages.inbounds.stream.general] +"request" = "درخواست" +"response" = "پاسخ" +"name" = "نام" +"value" = "مقدار" + +[pages.inbounds.stream.tcp] +"version" = "نسخه" +"method" = "متد" +"path" = "مسیر" +"status" = "وضعیت" +"statusDescription" = "توضیحات وضعیت" +"requestHeader" = "سربرگ درخواست" +"responseHeader" = "سربرگ پاسخ" + +[pages.settings] +"title" = "تنظیمات پنل" +"save" = "ذخیره" +"infoDesc" = "برای اعمال تغییرات در این بخش باید پس از ذخیره کردن، پنل را ریستارت کنید" +"restartPanel" = "ریستارت پنل" +"restartPanelDesc" = "آیا مطمئن به ریستارت پنل هستید؟ اگر پس‌از ریستارت نتوانستید به پنل دسترسی پیدا کنید، گزارش‌های موجود در اسکریپت پنل را بررسی کنید" +"resetDefaultConfig" = "برگشت به پیش‌فرض" +"panelConfig" = "عمومی" +"userSettings" = "احرازهویت" +"TGBotSettings" = "ربات تلگرام" +"panelListeningIP" = "آدرس آی‌پی" +"panelListeningIPDesc" = "آدرس آی‌پی برای وب پنل. برای گوش‌دادن به‌تمام آی‌پی‌ها خالی‌بگذارید" +"panelListeningDomain" = "نام دامنه" +"panelListeningDomainDesc" = "آدرس دامنه برای وب پنل. برای گوش‌دادن به‌تمام دامنه‌ها و آی‌پی‌ها خالی‌بگذارید" +"panelPort" = "شماره پورت" +"panelPortDesc" = "شماره پورت برای وب پنل. باید پورت استفاده نشده‌باشد" +"publicKeyPath" = "مسیر کلید عمومی" +"publicKeyPathDesc" = "مسیر فایل کلیدعمومی برای وب پنل. با '/' شروع‌می‌شود" +"privateKeyPath" = "مسیر کلید خصوصی" +"privateKeyPathDesc" = "مسیر فایل کلیدخصوصی برای وب پنل. با '/' شروع‌می‌شود" +"panelUrlPath" = "URI مسیر" +"panelUrlPathDesc" = "مسیر لینک وب پنل. با '/' شروع‌ و با '/' خاتمه‌ می‌یابد" +"pageSize" = "اندازه صفحه بندی جدول" +"pageSizeDesc" = "اندازه صفحه برای جدول ورودی‌ها. 0 = غیرفعال" +"remarkModel" = "نام‌کانفیگ و جداکننده" +"sampleRemark" = "نمونه‌نام" +"oldUsername" = "نام‌کاربری فعلی" +"currentPassword" = "رمز‌عبور فعلی" +"newUsername" = "نام‌کاربری جدید" +"newPassword" = "رمزعبور جدید" +"telegramBotEnable" = "فعال‌سازی ربات تلگرام" +"telegramBotEnableDesc" = "ربات تلگرام را فعال می‌کند" +"telegramToken" = "توکن تلگرام" +"telegramTokenDesc" = "دریافت کنید @botfather توکن تلگرام، از" +"telegramChatId" = "آی‌دی چت مدیر" +"telegramChatIdDesc" = "دریافت کنید '/id'یا دستور @userinfobot آی‌دی(های) چت مدیر، از" +"telegramNotifyTime" = "زمان اطلاع‌رسانی" +"telegramNotifyTimeDesc" = "زمان‌اطلاع‌رسانی ربات تلگرام برای ارسال گزارش‌های دوره‌ای. از فرمت زمانی کرون‌تاب استفاده‌کنید‌" +"tgNotifyBackup" = "پشتیبان‌گیری دیتابیس" +"tgNotifyBackupDesc" = "فایل پشتیبان دیتابیس را به‌همراه گزارش‌ دریافت می‌کنید‌" +"tgNotifyLogin" = "اطلاع‌رسانی ورود" +"tgNotifyLoginDesc" = "هر زمان کسی سعی به ورود به وب پنل شما را داشت. درباره نام‌کاربری، آی‌پی و زمان، مطلع می‌شوید" +"sessionMaxAge" = "مدت جلسه" +"sessionMaxAgeDesc" = "بیشینه مدت زمانی‌که می‌توانید لاگین بمانید. واحد: دقیقه" +"expireTimeDiff" = "اطلاع‌رسانی زمان انقضا" +"expireTimeDiffDesc" = "وقتی زمان باقی‌مانده به‌آستانه تعیین‌شده رسید، مطلع می‌شوید. واحد: روز" +"trafficDiff" = "اطلاع‌رسانی ترافیک باقی‌مانده" +"trafficDiffDesc" = "وقتی‌ ترافیک باقی‌مانده به‌آستانه تعیین‌شده رسید، مطلع می‌شوید. واحد: گیگابایت" +"tgNotifyCpu" = "اطلاع‌رسانی بار پردازنده" +"tgNotifyCpuDesc" = "اگر بار پردازنده از آستانه تعیین‌شده فراتر رفت، مطلع می‌شوید. واحد: درصد" +"timeZone" = "منطقه زمانی" +"timeZoneDesc" = "وظایف برنامه ریزی شده بر اساس این منطقه‌زمانی اجرا می‌شود" +"subSettings" = "سابسکریپشن" +"subEnable" = "فعال‌سازی سرویس سابسکریپشن" +"subEnableDesc" = " سرویس سابسکریپشن‌ را فعال می‌کند" +"subListen" = "آدرس آی‌پی" +"subListenDesc" = "آدرس آی‌پی برای سابسکریپشن. برای گوش‌دادن به‌تمام آی‌پی‌ها خالی‌بگذارید" +"subPort" = "شماره پورت" +"subPortDesc" = "شماره پورت برای سابسکریپشن. باید پورت استفاده نشده‌باشد" +"subCertPath" = "مسیر کلید عمومی" +"subCertPathDesc" = "مسیر فایل کلیدعمومی برای سابیکریپشن. با '/' شروع‌می‌شود" +"subKeyPath" = "مسیر کلید خصوصی" +"subKeyPathDesc" = "مسیر فایل کلیدخصوصی برای سابسکریپشن. با '/' شروع‌می‌شود" +"subPath" = "URI مسیر" +"subPathDesc" = "مسیر لینک سابسکریپشن. با '/' شروع‌ و با '/' خاتمه‌ می‌یابد" +"subDomain" = "نام دامنه" +"subDomainDesc" = "آدرس دامنه برای سابسکریپشن. برای گوش‌دادن به‌تمام دامنه‌ها و آی‌پی‌ها خالی‌بگذارید‌" +"subUpdates" = "فاصله بروزرسانی‌" +"subUpdatesDesc" = "فاصله مابین بروزرسانی لینک سابسکریپشن در برنامه‌های کاربری. واحد: ساعت" +"subEncrypt" = "کدگذاری" +"subEncryptDesc" = " محتوای برگشتی سابسکریپشن برپایه بیس64 کدگذاری خواهدشد" +"subShowInfo" = "نمایش اطلاعات مصرف" +"subShowInfoDesc" = "ترافیک و زمان باقی‌مانده را در برنامه‌های کاربری نمایش می‌دهد" +"subURI" = "پراکسی معکوس URI" +"subURIDesc" = "سابسکریپشن از لینکی که در پشت پراکسی‌های معکوس تنظیم شده‌، استفاده خواهدکرد" +"fragment" = "تکه‌تکه شدن" +"fragmentDesc" = "فعال کردن تکه تکه شدن برای بسته نخست تی‌ال‌اس" +"fragmentSett" = "تنظیمات فرگمنت" +"noisesDesc" = "فعال کردن Noises." +"noisesSett" = "تنظیمات Noises" +"mux" = "ماکس" +"muxDesc" = "چندین جریان داده مستقل را در یک جریان داده ثابت منتقل می کند" +"muxSett" = "تنظیمات ماکس" +"direct" = "اتصال مستقیم" +"directDesc" = "به طور مستقیم با دامنه ها یا محدوده آی‌پی یک کشور خاص ارتباط برقرار می کند" + +[pages.settings.toasts] +"modifySettings" = "ویرایش تنظیمات" +"getSettings" = "دریافت تنظیمات" +"modifyUser" = "ویرایش مدیر" +"originalUserPassIncorrect" = "نام‌کاربری یا رمزعبور فعلی اشتباه‌است" +"userPassMustBeNotEmpty" = "نام‌کاربری یا رمزعبور جدید خالی‌است" + +[pages.xray] +"title" = "پیکربندی ایکس‌ری" +"save" = "ذخیره" +"restart" = "ریستارت ایکس‌ری" +"basicTemplate" = "پایه" +"advancedTemplate" = "پیشرفته" +"generalConfigs" = "استراتژی‌ کلی" +"generalConfigsDesc" = "این گزینه‌ها استراتژی کلی ترافیک را تعیین می‌کنند" +"logConfigs" = "تنظیمات گزار‌ش‌ها" +"logConfigsDesc" = "فعال کردن گزارش ممکن است بر عملکرد سرور شما تأثیر بگذارد. توصیه می‌شود فقط در صورت لزوم آن را با دقت فعال کنید" +"blockConfigs" = "سپر محافظ" +"blockConfigsDesc" = "این گزینه‌ها ترافیک را بر اساس پروتکل‌های درخواستی خاص، و وب سایت‌ها مسدود می‌کند" +"basicRouting" = "مسیریابی پایه" +"blockConnectionsConfigsDesc" = "این گزینه‌ها ترافیک را بر اساس کشور درخواست‌شده خاص مسدود می‌کنند." +"directConnectionsConfigsDesc" = "یک اتصال مستقیم تضمین می‌کند که ترافیک خاص از طریق سرور دیگری مسیریابی نشود." +"blockips" = "مسدود کردن آی‌پی‌ها" +"blockdomains" = "مسدود کردن دامنه‌ها" +"directips" = "آی‌پی‌های مستقیم" +"directdomains" = "دامنه‌های مستقیم" +"ipv4Routing" = "IPv4 مسیریابی" +"ipv4RoutingDesc" = "این گزینه‌ها ترافیک را از طریق آی‌پی نسخه4 سرور، به مقصد هدایت می‌کند" +"warpRouting" = "WARP مسیریابی" +"warpRoutingDesc" = "این گزینه‌ها ترافیک‌ را از طریق وارپ کلادفلر به مقصد هدایت می‌کند" +"Template" = "‌پیکربندی پیشرفته الگو ایکس‌ری" +"TemplateDesc" = "فایل پیکربندی نهایی ایکس‌ری بر اساس این الگو ایجاد می‌شود" +"FreedomStrategy" = "Freedom استراتژی پروتکل" +"FreedomStrategyDesc" = "تعیین می‌کند Freedom استراتژی خروجی شبکه را برای پروتکل" +"RoutingStrategy" = "استراتژی کلی مسیریابی" +"RoutingStrategyDesc" = "استراتژی کلی مسیریابی برای حل تمام درخواست‌ها را تعیین می‌کند" +"Torrent" = "مسدودسازی پروتکل بیت‌تورنت" +"TorrentDesc" = "پروتکل بیت تورنت را مسدود می‌کند" +"Family" = "محافظ خانواده" +"FamilyDesc" = "محتوای مخصوص بزرگسالان، و وبسایت‌های ناامن را مسدود می‌کند" +"Inbounds" = "ورودی‌ها" +"Outbounds" = "خروجی‌ها" +"Routings" = "قوانین مسیریابی" +"RoutingsDesc" = "اولویت هر قانون مهم است" +"Balancers" = "بالانسرها" +"logLevel" = "سطح گزارش" +"logLevelDesc" = "سطح گزارش، شدت مسائلی را که باید ثبت شوند، تعیین می‌کند" +"accessLog" = "گزارش دسترسی" +"accessLogDesc" = "مسیر فایل گزارش دسترسی" +"errorLog" = "گزارش خطا" +"errorLogDesc" = "مسیر فایل گزارش خطا" +"dnsLog" = "گزارش DNS" +"dnsLogDesc" = "آیا ثبت‌های درخواست DNS را فعال کنید" +"maskAddress" = "پنهان کردن آدرس" +"maskAddressDesc" = "پوشش آدرس IP، هنگامی که فعال می‌شود، به طور خودکار آدرس IP که در لاگ ظاهر می‌شود را جایگزین می‌کند." + +[pages.xray.rules] +"first" = "اولین" +"last" = "آخرین" +"up" = "بالا" +"down" = "پایین" +"source" = "مبدا" +"dest" = "مقصد" +"inbound" = "ورودی" +"outbound" = "خروجی" +"info" = "اطلاعات" +"add" = "افزودن قانون" +"edit" = "ویرایش قانون" +"useComma" = "موارد جداشده با کاما" +"balancer" = "بالانسر" + +[pages.xray.outbound] +"addOutbound" = "افزودن خروجی" +"addReverse" = "افزودن معکوس" +"editOutbound" = "ویرایش خروجی" +"editReverse" = "ویرایش معکوس" +"tag" = "برچسب" +"tagDesc" = "برچسب یگانه" +"address" = "آدرس" +"reverse" = "معکوس" +"domain" = "دامنه" +"type" = "نوع" +"bridge" = "پل" +"portal" = "پورتال" +"intercon" = "اتصال میانی" +"settings" = "تنظیمات" +"accountInfo" = "اطلاعات حساب" +"outboundStatus" = "وضعیت خروجی" +"sendThrough" = "ارسال با" + +[pages.xray.balancer] +"addBalancer" = "افزودن بالانسر" +"editBalancer" = "ویرایش بالانسر" +"balancerStrategy" = "استراتژی" +"balancerSelectors" = "انتخاب‌گرها" +"fallback" = "جایگزین" +"tag" = "برچسب" +"tagDesc" = "برچسب یگانه" +"balancerDesc" = "امکان استفاده همزمان برچسب خروجی و برچسب بالانسر باهم وجود ندارد. درصورت استفاده همزمان فقط برچسب خروجی عمل خواهد کرد" + +[pages.xray.wireguard] +"secretKey" = "کلید شخصی" +"publicKey" = "کلید عمومی" +"allowedIPs" = "آی‌پی‌های مجاز" +"endpoint" = "نقطه پایانی" +"psk" = "کلید مشترک" +"domainStrategy" = "استراتژی حل دامنه" + +[pages.xray.dns] +"enable" = "فعال کردن حل دامنه" +"enableDesc" = "سرور حل دامنه داخلی را فعال می‌کند" +"tag" = "برچسب" +"tagDesc" = "این برچسب در قوانین مسیریابی به عنوان یک برچسب ورودی قابل استفاده خواهد بود" +"strategy" = "استراتژی پرس‌وجو" +"strategyDesc" = "استراتژی کلی برای حل نام‌دامنه" +"add" = "افزودن سرور" +"edit" = "ویرایش سرور" +"domains" = "دامنه‌ها" +"expectIPs" = "آی‌پی‌های مورد انتظار" + +[pages.xray.fakedns] +"add" = "افزودن دی‌ان‌اس جعلی" +"edit" = "ویرایش دی‌ان‌اس جعلی" +"ipPool" = "زیرشبکه استخر آی‌پی" +"poolSize" = "اندازه استخر" + +[tgbot] +"noResult" = "❗نتیجه‌ای یافت نشد" +"wentWrong" = "❌ مشکلی رخ داده‌است" +"noInbounds" = " هیچ ورودی یافت نشد" +"unlimited" = "♾ نامحدود" +"day" = "روز" +"days" = "روزها" +"unknown" = "نامشخص" +"inbounds" = "ورودی‌ها" +"clients" = "کاربران" + +[tgbot.commands] +"unknown" = "❗ دستور ناشناخته" +"pleaseChoose" = "👇 لطفاًانتخاب کنید:\r\n" +"help" = "🤖 به این ربات خوش‌آمدید! این ربات برای ارائه داده‌های خاص از وب پنل طراحی شده‌است و به‌شما امکان تغییرات لازم را می‌دهد\r\n\r\n" +"start" = "👋 سلام {{ .Firstname }}.\r\n" +"welcome" = "🤖 به‌ربات مدیریت {{ .Hostname }} خوش‌آمدید\r\n" +"status" = "✅ ربات‌درحالت‌عادی‌است" +"usage" = "❗ لطفا یک متن برای جستجو واردکنید" +"getID" = "🆔 شناسه‌شما: {{ .ID }}" +"helpAdminCommands" = "برای جستجوی ایمیل کاربر:\r\n/usage [ایمیل]\r\n \r\nبرای جستجوی ورودی‌ها (با آمار کاربر):\r\n/inbound [توضیح]" +"helpClientCommands" = "برای جستجوی آمار، فقط از دستور زیر استفاده‌کنید:\r\n \r\n/usage [UUID|رمز عبور]\r\n \r\nاز رمزعبور استفاده کنید Trojan/Shadowsocks و برای UUID از VMess/VLESS برای" + +[tgbot.messages] +"cpuThreshold" = "🔴 بار ‌پردازنده {{ .Percent }}% بیشتر از آستانه است {{ .Threshold }}%" +"loginSuccess" = "✅ باموفقیت به پنل واردشدید \r\n" +"loginFailed" = "❗️ ورود به پنل ناموفق‌بود \r\n" +"report" = "🕰 گزارشات‌زمان‌بندی‌شده: {{ .RunTime }}\r\n" +"datetime" = "⏰ تاریخ‌وزمان: {{ .DateTime }}\r\n" +"hostname" = "💻 نام‌میزبان: {{ .Hostname }}\r\n" +"version" = "🚀 X-UI: {{ .Version }}\r\n" +"ipv6" = "🌐 IPv6: {{ .IPv6 }}\r\n" +"ipv4" = "🌐 IPv4: {{ .IPv4 }}\r\n" +"ip" = "🌐 IP: {{ .IP }}\r\n" +"serverUpTime" = "⏳ مدت‌کارکرد: {{ .UpTime }} {{ .Unit }}\r\n" +"serverLoad" = "📈 بارسیستم: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n" +"serverMemory" = "📋 RAM: {{ .Current }}/{{ .Total }}\r\n" +"tcpCount" = "🔹 TCP: {{ .Count }}\r\n" +"udpCount" = "🔸 UDP: {{ .Count }}\r\n" +"traffic" = "🚦 ترافیک: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n" +"xrayStatus" = "ℹ️ وضعیت‌: {{ .State }}\r\n" +"username" = "👤 نام‌کاربری: {{ .Username }}\r\n" +"time" = "⏰ زمان: {{ .Time }}\r\n" +"inbound" = "📍 نام‌ورودی: {{ .Remark }}\r\n" +"port" = "🔌 پورت: {{ .Port }}\r\n" +"expire" = "📅 تاریخ‌انقضا: {{ .DateTime }}\r\n \r\n" +"expireIn" = "📅 انقضا در: {{ .Time }}\r\n \r\n" +"active" = "💡 فعال: {{ .Enable }}\r\n" +"online" = "🌐 وضعیت‌اتصال: {{ .Status }}\r\n" +"email" = "📧 ایمیل: {{ .Email }}\r\n" +"upload" = "🔼 آپلود↑: {{ .Upload }}\r\n" +"download" = "🔽 دانلود↓: {{ .Download }}\r\n" +"total" = "🔄 کل: {{ .UpDown }} / {{ .Total }}\r\n" +"exhaustedMsg" = "🚨 {{ .Type }} به‌اتمام‌رسیده‌است:\r\n" +"exhaustedCount" = "🚨 تعداد {{ .Type }} به‌اتمام رسیده‌است:\r\n" +"onlinesCount" = "🌐 کاربران‌آنلاین: {{ .Count }}\r\n" +"disabled" = "🛑 غیرفعال: {{ .Disabled }}\r\n" +"depleteSoon" = "🔜 به‌زودی به‌پایان خواهدرسید: {{ .Deplete }}\r\n \r\n" +"backupTime" = "🗄 زمان‌پشتیبان‌گیری: {{ .Time }}\r\n" +"yes" = "✅ بله" +"no" = "❌ خیر" + +[tgbot.buttons] +"dbBackup" = "دریافت فایل پشتیبان" +"serverUsage" = "استفاده از سیستم" +"getInbounds" = "دریافت ورودی‌ها" +"depleteSoon" = "به‌زودی به‌پایان خواهدرسید" +"clientUsage" = "دریافت آمار کاربر" +"onlines" = "کاربران آنلاین" +"commands" = "دستورات" + +[tgbot.answers] +"getInboundsFailed" = "❌ دریافت ورودی‌ها باخطا مواجه شد" +"askToAddUser" = "پیکربندی شما پیدا نشد!\r\nشما باید نام‌کاربری تلگرام خود را تنظیم کنید و از مدیر سرویس خود بخواهید که آن را به پیکربندی(های) شما اضافه کند" +"askToAddUserName" = "پیکربندی شما یافت نشد!\r\nلطفاً از مدیر سرویس خود بخواهید اطلاعات تلگرام شما را به پیکربندی(های) شما اضافه کند \r\n\r\nنام‌کاربری شما: @{{ .TgUserName }}" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index 8bcd41df8f..18ca440184 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -187,6 +187,9 @@ [pages.client] "add" = "Добавить клиента" +"groupAdd" = "Добавить пользователя подписки" +"isGroupEdit" = "Групповое редактирование" +"isGroupEditDesc" = "Все клиенты с одинаковой подпиской редактируются" "edit" = "Редактировать клиента" "submitAdd" = "Добавить клиента" "submitEdit" = "Сохранить изменения" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index 1a6a2f7b85..383dc8b451 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -187,6 +187,7 @@ [pages.client] "add" = "Thêm máy khách" +"groupAdd" = "Thêm người dùng đăng ký" "edit" = "Chỉnh sửa Máy khách" "submitAdd" = "Thêm máy khách" "submitEdit" = "Lưu thay đổi" From a16945803c016009e9db09ab441de23cab9f5c10 Mon Sep 17 00:00:00 2001 From: ali rahimi Date: Sun, 21 Jan 2024 15:26:19 +0100 Subject: [PATCH 02/13] conflict merge --- web/html/common/qrcode_modal.html | 1 + web/html/xui/client_modal.html | 7 ++- web/html/xui/inbound_client_table.html | 63 ++++++++++++-------------- 3 files changed, 34 insertions(+), 37 deletions(-) diff --git a/web/html/common/qrcode_modal.html b/web/html/common/qrcode_modal.html index ce79a9b62b..6054cf09ad 100644 --- a/web/html/common/qrcode_modal.html +++ b/web/html/common/qrcode_modal.html @@ -25,6 +25,7 @@ style="width: 100%; height: 100%; display: flex; border-radius: 1rem;"> +