mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-05-08 14:36:13 +00:00
feat: add configurable auto-restart on client auto-disable
Add a configurable option to restart Xray when clients are auto-disabled and persist disable actions. Changes include: - New setting restartXrayOnClientDisable (default true), getters/setters in SettingService, UI toggle in general settings, and translations for multiple locales. - AddTraffic signature updated to return a third bool (clientsDisabled). disableInvalidClients now calls Xray API to remove users, marks client_traffics.enable=false, updates inbound.Settings JSON so clients appear disabled in stored settings, and returns appropriate counts/errors. - XrayTrafficJob now checks the clientsDisabled flag and restarts Xray when the setting is enabled (with fallback to mark Xray as needing restart on failure). - XrayService.GetXrayConfig call adjusted to ignore AddTraffic returns. - Subscription generation (subService/subJson/subClash) no longer filters clients by their enable flag when matching subId. - Minor fixes: check_client_ip_job now checks scanner.Err and improved API error handling/logging. These changes ensure auto-disabled clients are propagated to Xray and the stored inbound settings, and provide an option to restart Xray automatically after auto-disable events.
This commit is contained in:
@@ -55,7 +55,7 @@ func (s *SubClashService) GetClash(subId string, host string) (string, string, e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
if client.Enable && client.SubID == subId {
|
if client.SubID == subId {
|
||||||
clientTraffics = append(clientTraffics, s.SubService.getClientTraffics(inbound.ClientStats, client.Email))
|
clientTraffics = append(clientTraffics, s.SubService.getClientTraffics(inbound.ClientStats, client.Email))
|
||||||
proxies = append(proxies, s.getProxies(inbound, client, host)...)
|
proxies = append(proxies, s.getProxies(inbound, client, host)...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ func (s *SubJsonService) GetJson(subId string, host string) (string, string, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
if client.Enable && client.SubID == subId {
|
if client.SubID == subId {
|
||||||
clientTraffics = append(clientTraffics, s.SubService.getClientTraffics(inbound.ClientStats, client.Email))
|
clientTraffics = append(clientTraffics, s.SubService.getClientTraffics(inbound.ClientStats, client.Email))
|
||||||
newConfigs := s.getConfig(inbound, client, host)
|
newConfigs := s.getConfig(inbound, client, host)
|
||||||
configArray = append(configArray, newConfigs...)
|
configArray = append(configArray, newConfigs...)
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ func (s *SubService) GetSubs(subId string, host string) ([]string, int64, xray.C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
if client.Enable && client.SubID == subId {
|
if client.SubID == subId {
|
||||||
link := s.getLink(inbound, client.Email)
|
link := s.getLink(inbound, client.Email)
|
||||||
result = append(result, link)
|
result = append(result, link)
|
||||||
ct := s.getClientTraffics(inbound.ClientStats, client.Email)
|
ct := s.getClientTraffics(inbound.ClientStats, client.Email)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ class AllSetting {
|
|||||||
this.subDomain = "";
|
this.subDomain = "";
|
||||||
this.externalTrafficInformEnable = false;
|
this.externalTrafficInformEnable = false;
|
||||||
this.externalTrafficInformURI = "";
|
this.externalTrafficInformURI = "";
|
||||||
|
this.restartXrayOnClientDisable = true;
|
||||||
this.subCertFile = "";
|
this.subCertFile = "";
|
||||||
this.subKeyFile = "";
|
this.subKeyFile = "";
|
||||||
this.subUpdates = 12;
|
this.subUpdates = 12;
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ type AllSetting struct {
|
|||||||
SubUpdates int `json:"subUpdates" form:"subUpdates"` // Subscription update interval in minutes
|
SubUpdates int `json:"subUpdates" form:"subUpdates"` // Subscription update interval in minutes
|
||||||
ExternalTrafficInformEnable bool `json:"externalTrafficInformEnable" form:"externalTrafficInformEnable"` // Enable external traffic reporting
|
ExternalTrafficInformEnable bool `json:"externalTrafficInformEnable" form:"externalTrafficInformEnable"` // Enable external traffic reporting
|
||||||
ExternalTrafficInformURI string `json:"externalTrafficInformURI" form:"externalTrafficInformURI"` // URI for external traffic reporting
|
ExternalTrafficInformURI string `json:"externalTrafficInformURI" form:"externalTrafficInformURI"` // URI for external traffic reporting
|
||||||
|
RestartXrayOnClientDisable bool `json:"restartXrayOnClientDisable" form:"restartXrayOnClientDisable"` // Restart Xray when clients are auto-disabled by expiry/traffic limit
|
||||||
SubEncrypt bool `json:"subEncrypt" form:"subEncrypt"` // Encrypt subscription responses
|
SubEncrypt bool `json:"subEncrypt" form:"subEncrypt"` // Encrypt subscription responses
|
||||||
SubShowInfo bool `json:"subShowInfo" form:"subShowInfo"` // Show client information in subscriptions
|
SubShowInfo bool `json:"subShowInfo" form:"subShowInfo"` // Show client information in subscriptions
|
||||||
SubURI string `json:"subURI" form:"subURI"` // Subscription server URI
|
SubURI string `json:"subURI" form:"subURI"` // Subscription server URI
|
||||||
|
|||||||
@@ -124,6 +124,13 @@
|
|||||||
v-model="allSetting.externalTrafficInformURI"></a-input>
|
v-model="allSetting.externalTrafficInformURI"></a-input>
|
||||||
</template>
|
</template>
|
||||||
</a-setting-list-item>
|
</a-setting-list-item>
|
||||||
|
<a-setting-list-item paddings="small">
|
||||||
|
<template #title>{{ i18n "pages.settings.restartXrayOnClientDisable"}}</template>
|
||||||
|
<template #description>{{ i18n "pages.settings.restartXrayOnClientDisableDesc"}}</template>
|
||||||
|
<template #control>
|
||||||
|
<a-switch v-model="allSetting.restartXrayOnClientDisable"></a-switch>
|
||||||
|
</template>
|
||||||
|
</a-setting-list-item>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
<a-collapse-panel key="5" header='{{ i18n "pages.settings.dateAndTime" }}'>
|
<a-collapse-panel key="5" header='{{ i18n "pages.settings.dateAndTime" }}'>
|
||||||
<a-setting-list-item paddings="small">
|
<a-setting-list-item paddings="small">
|
||||||
|
|||||||
@@ -199,6 +199,9 @@ func (j *CheckClientIpJob) processLogFile() bool {
|
|||||||
inboundClientIps[email][ip] = timestamp
|
inboundClientIps[email][ip] = timestamp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
j.checkError(err)
|
||||||
|
}
|
||||||
|
|
||||||
shouldCleanLog := false
|
shouldCleanLog := false
|
||||||
for email, ipTimestamps := range inboundClientIps {
|
for email, ipTimestamps := range inboundClientIps {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func (j *XrayTrafficJob) Run() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err, needRestart0 := j.inboundService.AddTraffic(traffics, clientTraffics)
|
err, needRestart0, clientsDisabled := j.inboundService.AddTraffic(traffics, clientTraffics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("add inbound traffic failed:", err)
|
logger.Warning("add inbound traffic failed:", err)
|
||||||
}
|
}
|
||||||
@@ -41,6 +41,18 @@ func (j *XrayTrafficJob) Run() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("add outbound traffic failed:", err)
|
logger.Warning("add outbound traffic failed:", err)
|
||||||
}
|
}
|
||||||
|
if clientsDisabled {
|
||||||
|
restartOnDisable, settingErr := j.settingService.GetRestartXrayOnClientDisable()
|
||||||
|
if settingErr != nil {
|
||||||
|
logger.Warning("get RestartXrayOnClientDisable failed:", settingErr)
|
||||||
|
}
|
||||||
|
if restartOnDisable {
|
||||||
|
if err := j.xrayService.RestartXray(true); err != nil {
|
||||||
|
logger.Warning("restart xray after disabling clients failed:", err)
|
||||||
|
j.xrayService.SetToNeedRestart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if ExternalTrafficInformEnable, err := j.settingService.GetExternalTrafficInformEnable(); ExternalTrafficInformEnable {
|
if ExternalTrafficInformEnable, err := j.settingService.GetExternalTrafficInformEnable(); ExternalTrafficInformEnable {
|
||||||
j.informTrafficToExternalAPI(traffics, clientTraffics)
|
j.informTrafficToExternalAPI(traffics, clientTraffics)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
|||||||
@@ -1228,7 +1228,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
|
|||||||
return needRestart, tx.Save(oldInbound).Error
|
return needRestart, tx.Save(oldInbound).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraffics []*xray.ClientTraffic) (error, bool) {
|
func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraffics []*xray.ClientTraffic) (error, bool, bool) {
|
||||||
var err error
|
var err error
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
tx := db.Begin()
|
tx := db.Begin()
|
||||||
@@ -1242,11 +1242,11 @@ func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraff
|
|||||||
}()
|
}()
|
||||||
err = s.addInboundTraffic(tx, inboundTraffics)
|
err = s.addInboundTraffic(tx, inboundTraffics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, false
|
return err, false, false
|
||||||
}
|
}
|
||||||
err = s.addClientTraffic(tx, clientTraffics)
|
err = s.addClientTraffic(tx, clientTraffics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, false
|
return err, false, false
|
||||||
}
|
}
|
||||||
|
|
||||||
needRestart0, count, err := s.autoRenewClients(tx)
|
needRestart0, count, err := s.autoRenewClients(tx)
|
||||||
@@ -1256,11 +1256,13 @@ func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraff
|
|||||||
logger.Debugf("%v clients renewed", count)
|
logger.Debugf("%v clients renewed", count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disabledClientsCount := int64(0)
|
||||||
needRestart1, count, err := s.disableInvalidClients(tx)
|
needRestart1, count, err := s.disableInvalidClients(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("Error in disabling invalid clients:", err)
|
logger.Warning("Error in disabling invalid clients:", err)
|
||||||
} else if count > 0 {
|
} else if count > 0 {
|
||||||
logger.Debugf("%v clients disabled", count)
|
logger.Debugf("%v clients disabled", count)
|
||||||
|
disabledClientsCount = count
|
||||||
}
|
}
|
||||||
|
|
||||||
needRestart2, count, err := s.disableInvalidInbounds(tx)
|
needRestart2, count, err := s.disableInvalidInbounds(tx)
|
||||||
@@ -1269,7 +1271,7 @@ func (s *InboundService) AddTraffic(inboundTraffics []*xray.Traffic, clientTraff
|
|||||||
} else if count > 0 {
|
} else if count > 0 {
|
||||||
logger.Debugf("%v inbounds disabled", count)
|
logger.Debugf("%v inbounds disabled", count)
|
||||||
}
|
}
|
||||||
return nil, (needRestart0 || needRestart1 || needRestart2)
|
return nil, (needRestart0 || needRestart1 || needRestart2), disabledClientsCount > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) addInboundTraffic(tx *gorm.DB, traffics []*xray.Traffic) error {
|
func (s *InboundService) addInboundTraffic(tx *gorm.DB, traffics []*xray.Traffic) error {
|
||||||
@@ -1546,46 +1548,105 @@ func (s *InboundService) disableInvalidClients(tx *gorm.DB) (bool, int64, error)
|
|||||||
now := time.Now().Unix() * 1000
|
now := time.Now().Unix() * 1000
|
||||||
needRestart := false
|
needRestart := false
|
||||||
|
|
||||||
if p != nil {
|
var clientsToDisable []struct {
|
||||||
var results []struct {
|
InboundId int
|
||||||
Tag string
|
Tag string
|
||||||
Email string
|
Email string
|
||||||
}
|
}
|
||||||
|
|
||||||
err := tx.Table("inbounds").
|
err := tx.Table("inbounds").
|
||||||
Select("inbounds.tag, client_traffics.email").
|
Select("inbounds.id as inbound_id, inbounds.tag, client_traffics.email").
|
||||||
Joins("JOIN client_traffics ON inbounds.id = client_traffics.inbound_id").
|
Joins("JOIN client_traffics ON inbounds.id = client_traffics.inbound_id").
|
||||||
Where("((client_traffics.total > 0 AND client_traffics.up + client_traffics.down >= client_traffics.total) OR (client_traffics.expiry_time > 0 AND client_traffics.expiry_time <= ?)) AND client_traffics.enable = ?", now, true).
|
Where("((client_traffics.total > 0 AND client_traffics.up + client_traffics.down >= client_traffics.total) OR (client_traffics.expiry_time > 0 AND client_traffics.expiry_time <= ?)) AND client_traffics.enable = ?", now, true).
|
||||||
Scan(&results).Error
|
Scan(&clientsToDisable).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, 0, err
|
return false, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p != nil {
|
||||||
s.xrayApi.Init(p.GetAPIPort())
|
s.xrayApi.Init(p.GetAPIPort())
|
||||||
for _, result := range results {
|
for _, client := range clientsToDisable {
|
||||||
err1 := s.xrayApi.RemoveUser(result.Tag, result.Email)
|
err1 := s.xrayApi.RemoveUser(client.Tag, client.Email)
|
||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
logger.Debug("Client disabled by api:", result.Email)
|
logger.Debug("Client disabled by api:", client.Email)
|
||||||
} else {
|
} else {
|
||||||
if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", result.Email)) {
|
if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", client.Email)) {
|
||||||
logger.Debug("User is already disabled. Nothing to do more...")
|
logger.Debug("User is already disabled. Nothing to do more...")
|
||||||
} else {
|
} else {
|
||||||
if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", result.Email)) {
|
logger.Debug("Error in disabling client by api:", err1)
|
||||||
logger.Debug("User is already disabled. Nothing to do more...")
|
needRestart = true
|
||||||
} else {
|
|
||||||
logger.Debug("Error in disabling client by api:", err1)
|
|
||||||
needRestart = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.xrayApi.Close()
|
s.xrayApi.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
result := tx.Model(xray.ClientTraffic{}).
|
result := tx.Model(xray.ClientTraffic{}).
|
||||||
Where("((total > 0 and up + down >= total) or (expiry_time > 0 and expiry_time <= ?)) and enable = ?", now, true).
|
Where("((total > 0 and up + down >= total) or (expiry_time > 0 and expiry_time <= ?)) and enable = ?", now, true).
|
||||||
Update("enable", false)
|
Update("enable", false)
|
||||||
err := result.Error
|
err = result.Error
|
||||||
count := result.RowsAffected
|
count := result.RowsAffected
|
||||||
return needRestart, count, err
|
if err != nil {
|
||||||
|
return needRestart, count, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also set enable=false in inbounds.settings JSON so clients are visibly disabled
|
||||||
|
if len(clientsToDisable) > 0 {
|
||||||
|
inboundEmailMap := make(map[int]map[string]struct{})
|
||||||
|
for _, c := range clientsToDisable {
|
||||||
|
if inboundEmailMap[c.InboundId] == nil {
|
||||||
|
inboundEmailMap[c.InboundId] = make(map[string]struct{})
|
||||||
|
}
|
||||||
|
inboundEmailMap[c.InboundId][c.Email] = struct{}{}
|
||||||
|
}
|
||||||
|
inboundIds := make([]int, 0, len(inboundEmailMap))
|
||||||
|
for id := range inboundEmailMap {
|
||||||
|
inboundIds = append(inboundIds, id)
|
||||||
|
}
|
||||||
|
var inbounds []*model.Inbound
|
||||||
|
if err = tx.Model(model.Inbound{}).Where("id IN ?", inboundIds).Find(&inbounds).Error; err != nil {
|
||||||
|
logger.Warning("disableInvalidClients fetch inbounds:", err)
|
||||||
|
return needRestart, count, nil
|
||||||
|
}
|
||||||
|
for _, inbound := range inbounds {
|
||||||
|
settings := map[string]any{}
|
||||||
|
if jsonErr := json.Unmarshal([]byte(inbound.Settings), &settings); jsonErr != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
clients, ok := settings["clients"].([]any)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
emailSet := inboundEmailMap[inbound.Id]
|
||||||
|
changed := false
|
||||||
|
for i := range clients {
|
||||||
|
c, ok := clients[i].(map[string]any)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
email, _ := c["email"].(string)
|
||||||
|
if _, shouldDisable := emailSet[email]; shouldDisable {
|
||||||
|
c["enable"] = false
|
||||||
|
c["updated_at"] = time.Now().Unix() * 1000
|
||||||
|
clients[i] = c
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if changed {
|
||||||
|
settings["clients"] = clients
|
||||||
|
modifiedSettings, jsonErr := json.MarshalIndent(settings, "", " ")
|
||||||
|
if jsonErr != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
inbound.Settings = string(modifiedSettings)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = tx.Save(inbounds).Error; err != nil {
|
||||||
|
logger.Warning("disableInvalidClients update inbound settings:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return needRestart, count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) GetInboundTags() (string, error) {
|
func (s *InboundService) GetInboundTags() (string, error) {
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ var defaultValueMap = map[string]string{
|
|||||||
"nord": "",
|
"nord": "",
|
||||||
"externalTrafficInformEnable": "false",
|
"externalTrafficInformEnable": "false",
|
||||||
"externalTrafficInformURI": "",
|
"externalTrafficInformURI": "",
|
||||||
|
"restartXrayOnClientDisable": "true",
|
||||||
"xrayOutboundTestUrl": "https://www.google.com/generate_204",
|
"xrayOutboundTestUrl": "https://www.google.com/generate_204",
|
||||||
|
|
||||||
// LDAP defaults
|
// LDAP defaults
|
||||||
@@ -628,6 +629,14 @@ func (s *SettingService) SetExternalTrafficInformURI(InformURI string) error {
|
|||||||
return s.setString("externalTrafficInformURI", InformURI)
|
return s.setString("externalTrafficInformURI", InformURI)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SettingService) GetRestartXrayOnClientDisable() (bool, error) {
|
||||||
|
return s.getBool("restartXrayOnClientDisable")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SettingService) SetRestartXrayOnClientDisable(value bool) error {
|
||||||
|
return s.setBool("restartXrayOnClientDisable", value)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SettingService) GetIpLimitEnable() (bool, error) {
|
func (s *SettingService) GetIpLimitEnable() (bool, error) {
|
||||||
accessLogPath, err := xray.GetAccessLogPath()
|
accessLogPath, err := xray.GetAccessLogPath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.inboundService.AddTraffic(nil, nil)
|
_, _, _ = s.inboundService.AddTraffic(nil, nil)
|
||||||
|
|
||||||
inbounds, err := s.inboundService.GetAllInbounds()
|
inbounds, err := s.inboundService.GetAllInbounds()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "يبعت تنبيه لـ API خارجي مع كل تحديث للترافيك."
|
"externalTrafficInformEnableDesc" = "يبعت تنبيه لـ API خارجي مع كل تحديث للترافيك."
|
||||||
"externalTrafficInformURI" = "مسار تنبيه الترافيك الخارجي"
|
"externalTrafficInformURI" = "مسار تنبيه الترافيك الخارجي"
|
||||||
"externalTrafficInformURIDesc" = "تحديثات الترافيك هتتبعت للمسار ده."
|
"externalTrafficInformURIDesc" = "تحديثات الترافيك هتتبعت للمسار ده."
|
||||||
|
"restartXrayOnClientDisable" = "إعادة تشغيل Xray بعد التعطيل التلقائي"
|
||||||
|
"restartXrayOnClientDisableDesc" = "عند تعطيل العميل تلقائيا بسبب انتهاء الصلاحية أو حد حركة المرور، أعد تشغيل Xray."
|
||||||
"fragment" = "تجزئة"
|
"fragment" = "تجزئة"
|
||||||
"fragmentDesc" = "يفعل تجزئة لحزمة TLS hello."
|
"fragmentDesc" = "يفعل تجزئة لحزمة TLS hello."
|
||||||
"fragmentSett" = "إعدادات التجزئة"
|
"fragmentSett" = "إعدادات التجزئة"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "Inform external API on every traffic update."
|
"externalTrafficInformEnableDesc" = "Inform external API on every traffic update."
|
||||||
"externalTrafficInformURI" = "External Traffic Inform URI"
|
"externalTrafficInformURI" = "External Traffic Inform URI"
|
||||||
"externalTrafficInformURIDesc" = "Traffic updates are sent to this URI."
|
"externalTrafficInformURIDesc" = "Traffic updates are sent to this URI."
|
||||||
|
"restartXrayOnClientDisable" = "Restart Xray After Auto Disable"
|
||||||
|
"restartXrayOnClientDisableDesc" = "When a client is automatically disabled due to expiration or traffic limit, restart Xray."
|
||||||
"fragment" = "Fragmentation"
|
"fragment" = "Fragmentation"
|
||||||
"fragmentDesc" = "Enable fragmentation for TLS hello packet."
|
"fragmentDesc" = "Enable fragmentation for TLS hello packet."
|
||||||
"fragmentSett" = "Fragmentation Settings"
|
"fragmentSett" = "Fragmentation Settings"
|
||||||
|
|||||||
@@ -476,6 +476,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "Informar a la API externa sobre cada actualización de tráfico."
|
"externalTrafficInformEnableDesc" = "Informar a la API externa sobre cada actualización de tráfico."
|
||||||
"externalTrafficInformURI" = "URI de información de tráfico externo"
|
"externalTrafficInformURI" = "URI de información de tráfico externo"
|
||||||
"externalTrafficInformURIDesc" = "Las actualizaciones de tráfico se envían a este URI."
|
"externalTrafficInformURIDesc" = "Las actualizaciones de tráfico se envían a este URI."
|
||||||
|
"restartXrayOnClientDisable" = "Reiniciar Xray tras desactivación automática"
|
||||||
|
"restartXrayOnClientDisableDesc" = "Cuando un cliente se desactive automáticamente por vencimiento o límite de tráfico, reiniciar Xray."
|
||||||
"subURIDesc" = "Cambiar el URI base de la URL de suscripción para usar detrás de los servidores proxy"
|
"subURIDesc" = "Cambiar el URI base de la URL de suscripción para usar detrás de los servidores proxy"
|
||||||
"fragment" = "Fragmentación"
|
"fragment" = "Fragmentación"
|
||||||
"fragmentDesc" = "Habilitar la fragmentación para el paquete de saludo de TLS"
|
"fragmentDesc" = "Habilitar la fragmentación para el paquete de saludo de TLS"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "مصرف ترافیک به سرویس خارجی ارسال می شود"
|
"externalTrafficInformEnableDesc" = "مصرف ترافیک به سرویس خارجی ارسال می شود"
|
||||||
"externalTrafficInformURI" = "لینک اطلاع رسانی خارجی مصرف ترافیک"
|
"externalTrafficInformURI" = "لینک اطلاع رسانی خارجی مصرف ترافیک"
|
||||||
"externalTrafficInformURIDesc" = "ترافیک های مصرفی به این لینک هم ارسال می شود"
|
"externalTrafficInformURIDesc" = "ترافیک های مصرفی به این لینک هم ارسال می شود"
|
||||||
|
"restartXrayOnClientDisable" = "ریاستارت Xray بعد از غیرفعالسازی خودکار"
|
||||||
|
"restartXrayOnClientDisableDesc" = "وقتی کاربر بهصورت خودکار بهدلیل اتمام زمان یا ترافیک غیرفعال میشود، Xray ریاستارت شود."
|
||||||
"fragment" = "فرگمنت"
|
"fragment" = "فرگمنت"
|
||||||
"fragmentDesc" = "فعال کردن فرگمنت برای بستهی نخست تیالاس"
|
"fragmentDesc" = "فعال کردن فرگمنت برای بستهی نخست تیالاس"
|
||||||
"fragmentSett" = "تنظیمات فرگمنت"
|
"fragmentSett" = "تنظیمات فرگمنت"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "Inform external API on every traffic update."
|
"externalTrafficInformEnableDesc" = "Inform external API on every traffic update."
|
||||||
"externalTrafficInformURI" = "Lalu Lintas Eksternal Menginformasikan URI"
|
"externalTrafficInformURI" = "Lalu Lintas Eksternal Menginformasikan URI"
|
||||||
"externalTrafficInformURIDesc" = "Pembaruan lalu lintas dikirim ke URI ini."
|
"externalTrafficInformURIDesc" = "Pembaruan lalu lintas dikirim ke URI ini."
|
||||||
|
"restartXrayOnClientDisable" = "Nyalakan Ulang Xray Setelah Nonaktif Otomatis"
|
||||||
|
"restartXrayOnClientDisableDesc" = "Saat klien otomatis dinonaktifkan karena kedaluwarsa atau batas trafik, mulai ulang Xray."
|
||||||
"fragment" = "Fragmentasi"
|
"fragment" = "Fragmentasi"
|
||||||
"fragmentDesc" = "Aktifkan fragmentasi untuk paket hello TLS"
|
"fragmentDesc" = "Aktifkan fragmentasi untuk paket hello TLS"
|
||||||
"fragmentSett" = "Pengaturan Fragmentasi"
|
"fragmentSett" = "Pengaturan Fragmentasi"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "トラフィックの更新ごとに外部 API に通知します。"
|
"externalTrafficInformEnableDesc" = "トラフィックの更新ごとに外部 API に通知します。"
|
||||||
"externalTrafficInformURI" = "外部トラフィック通知 URI"
|
"externalTrafficInformURI" = "外部トラフィック通知 URI"
|
||||||
"externalTrafficInformURIDesc" = "トラフィックの更新ごとに外部 API に通知します。"
|
"externalTrafficInformURIDesc" = "トラフィックの更新ごとに外部 API に通知します。"
|
||||||
|
"restartXrayOnClientDisable" = "自動無効化後に Xray を再起動"
|
||||||
|
"restartXrayOnClientDisableDesc" = "有効期限切れまたはトラフィック上限でクライアントが自動的に無効化されたとき、Xray を再起動します。"
|
||||||
"fragment" = "フラグメント"
|
"fragment" = "フラグメント"
|
||||||
"fragmentDesc" = "TLS helloパケットのフラグメントを有効にする"
|
"fragmentDesc" = "TLS helloパケットのフラグメントを有効にする"
|
||||||
"fragmentSett" = "設定"
|
"fragmentSett" = "設定"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "Informar a API externa sobre cada atualização de tráfego."
|
"externalTrafficInformEnableDesc" = "Informar a API externa sobre cada atualização de tráfego."
|
||||||
"externalTrafficInformURI" = "URI de informação de tráfego externo"
|
"externalTrafficInformURI" = "URI de informação de tráfego externo"
|
||||||
"externalTrafficInformURIDesc" = "As atualizações de tráfego são enviadas para este URI."
|
"externalTrafficInformURIDesc" = "As atualizações de tráfego são enviadas para este URI."
|
||||||
|
"restartXrayOnClientDisable" = "Reiniciar Xray Após Desativação Automática"
|
||||||
|
"restartXrayOnClientDisableDesc" = "Quando um cliente for desativado automaticamente por expiração ou limite de tráfego, reinicie o Xray."
|
||||||
"fragment" = "Fragmentação"
|
"fragment" = "Fragmentação"
|
||||||
"fragmentDesc" = "Ativa a fragmentação para o pacote TLS hello."
|
"fragmentDesc" = "Ativa a fragmentação para o pacote TLS hello."
|
||||||
"fragmentSett" = "Configurações de Fragmentação"
|
"fragmentSett" = "Configurações de Fragmentação"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "Информировать внешний API о каждом обновлении трафика"
|
"externalTrafficInformEnableDesc" = "Информировать внешний API о каждом обновлении трафика"
|
||||||
"externalTrafficInformURI" = "URI информации о внешнем трафике"
|
"externalTrafficInformURI" = "URI информации о внешнем трафике"
|
||||||
"externalTrafficInformURIDesc" = "Обновления трафика отправляются на этот URI"
|
"externalTrafficInformURIDesc" = "Обновления трафика отправляются на этот URI"
|
||||||
|
"restartXrayOnClientDisable" = "Перезапускать Xray после автоотключения"
|
||||||
|
"restartXrayOnClientDisableDesc" = "Когда клиент автоматически отключается из-за окончания срока действия или лимита трафика, перезапускать Xray."
|
||||||
"fragment" = "Фрагментация"
|
"fragment" = "Фрагментация"
|
||||||
"fragmentDesc" = "Включить фрагментацию TLS-хэндшейка"
|
"fragmentDesc" = "Включить фрагментацию TLS-хэндшейка"
|
||||||
"fragmentSett" = "Настройки фрагментации"
|
"fragmentSett" = "Настройки фрагментации"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "Her trafik güncellemesinde harici API'yi bilgilendirin."
|
"externalTrafficInformEnableDesc" = "Her trafik güncellemesinde harici API'yi bilgilendirin."
|
||||||
"externalTrafficInformURI" = "Harici Trafik Bilgisi URI'si"
|
"externalTrafficInformURI" = "Harici Trafik Bilgisi URI'si"
|
||||||
"externalTrafficInformURIDesc" = "Trafik güncellemeleri bu URI'ye gönderildi."
|
"externalTrafficInformURIDesc" = "Trafik güncellemeleri bu URI'ye gönderildi."
|
||||||
|
"restartXrayOnClientDisable" = "Otomatik Devre Dışı Sonrası Xray'i Yeniden Başlat"
|
||||||
|
"restartXrayOnClientDisableDesc" = "Bir istemci süre dolumu veya trafik limiti nedeniyle otomatik devre dışı bırakıldığında Xray'i yeniden başlat."
|
||||||
"fragment" = "Parçalama"
|
"fragment" = "Parçalama"
|
||||||
"fragmentDesc" = "TLS merhaba paketinin parçalanmasını etkinleştir."
|
"fragmentDesc" = "TLS merhaba paketinin parçalanmasını etkinleştir."
|
||||||
"fragmentSett" = "Parçalama Ayarları"
|
"fragmentSett" = "Parçalama Ayarları"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "Інформувати зовнішній API про кожне оновлення трафіку."
|
"externalTrafficInformEnableDesc" = "Інформувати зовнішній API про кожне оновлення трафіку."
|
||||||
"externalTrafficInformURI" = "Інформаційний URI зовнішнього трафіку"
|
"externalTrafficInformURI" = "Інформаційний URI зовнішнього трафіку"
|
||||||
"externalTrafficInformURIDesc" = "Оновлення трафіку надсилаються на цей URI."
|
"externalTrafficInformURIDesc" = "Оновлення трафіку надсилаються на цей URI."
|
||||||
|
"restartXrayOnClientDisable" = "Перезапускати Xray після авто-вимкнення"
|
||||||
|
"restartXrayOnClientDisableDesc" = "Коли клієнт автоматично вимикається через закінчення терміну дії або ліміт трафіку, перезапускати Xray."
|
||||||
"fragment" = "Фрагментація"
|
"fragment" = "Фрагментація"
|
||||||
"fragmentDesc" = "Увімкнути фрагментацію для пакету привітання TLS"
|
"fragmentDesc" = "Увімкнути фрагментацію для пакету привітання TLS"
|
||||||
"fragmentSett" = "Параметри фрагментації"
|
"fragmentSett" = "Параметри фрагментації"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "Thông báo cho API bên ngoài về mọi cập nhật lưu lượng truy cập."
|
"externalTrafficInformEnableDesc" = "Thông báo cho API bên ngoài về mọi cập nhật lưu lượng truy cập."
|
||||||
"externalTrafficInformURI" = "URI thông báo lưu lượng truy cập bên ngoài"
|
"externalTrafficInformURI" = "URI thông báo lưu lượng truy cập bên ngoài"
|
||||||
"externalTrafficInformURIDesc" = "Cập nhật lưu lượng truy cập được gửi tới URI này."
|
"externalTrafficInformURIDesc" = "Cập nhật lưu lượng truy cập được gửi tới URI này."
|
||||||
|
"restartXrayOnClientDisable" = "Khởi Động Lại Xray Sau Khi Tự Động Vô Hiệu Hóa"
|
||||||
|
"restartXrayOnClientDisableDesc" = "Khi người dùng bị vô hiệu hóa tự động do hết hạn hoặc chạm giới hạn lưu lượng, hãy khởi động lại Xray."
|
||||||
"fragment" = "Sự phân mảnh"
|
"fragment" = "Sự phân mảnh"
|
||||||
"fragmentDesc" = "Kích hoạt phân mảnh cho gói TLS hello"
|
"fragmentDesc" = "Kích hoạt phân mảnh cho gói TLS hello"
|
||||||
"fragmentSett" = "Cài đặt phân mảnh"
|
"fragmentSett" = "Cài đặt phân mảnh"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "每次流量更新时通知外部 API"
|
"externalTrafficInformEnableDesc" = "每次流量更新时通知外部 API"
|
||||||
"externalTrafficInformURI" = "外部流量通知 URI"
|
"externalTrafficInformURI" = "外部流量通知 URI"
|
||||||
"externalTrafficInformURIDesc" = "流量更新将发送到此 URI"
|
"externalTrafficInformURIDesc" = "流量更新将发送到此 URI"
|
||||||
|
"restartXrayOnClientDisable" = "客户端自动禁用后重启 Xray"
|
||||||
|
"restartXrayOnClientDisableDesc" = "当客户端因到期或流量超限被自动禁用时,重启 Xray。"
|
||||||
"fragment" = "分片"
|
"fragment" = "分片"
|
||||||
"fragmentDesc" = "启用 TLS hello 数据包分片"
|
"fragmentDesc" = "启用 TLS hello 数据包分片"
|
||||||
"fragmentSett" = "设置"
|
"fragmentSett" = "设置"
|
||||||
|
|||||||
@@ -477,6 +477,8 @@
|
|||||||
"externalTrafficInformEnableDesc" = "每次流量更新時通知外部 API"
|
"externalTrafficInformEnableDesc" = "每次流量更新時通知外部 API"
|
||||||
"externalTrafficInformURI" = "外部流量通知 URI"
|
"externalTrafficInformURI" = "外部流量通知 URI"
|
||||||
"externalTrafficInformURIDesc" = "流量更新將會傳送到此 URI"
|
"externalTrafficInformURIDesc" = "流量更新將會傳送到此 URI"
|
||||||
|
"restartXrayOnClientDisable" = "用戶自動停用後重新啟動 Xray"
|
||||||
|
"restartXrayOnClientDisableDesc" = "當用戶因到期或流量上限而被自動停用時,重新啟動 Xray。"
|
||||||
"fragment" = "分片"
|
"fragment" = "分片"
|
||||||
"fragmentDesc" = "啟用 TLS hello 資料包分片"
|
"fragmentDesc" = "啟用 TLS hello 資料包分片"
|
||||||
"fragmentSett" = "設定"
|
"fragmentSett" = "設定"
|
||||||
|
|||||||
Reference in New Issue
Block a user