From fd5f5917378129d7a555a246d42a2a572476b948 Mon Sep 17 00:00:00 2001 From: "Danil S." <135337715+sh1shd@users.noreply.github.com> Date: Tue, 27 Jan 2026 05:06:01 +0700 Subject: [PATCH] feat: more subscription information fields (#3701) * feat: more subscription information fields * fix: incorrect translation * feat: implement field for Happ custom routing rules --- sub/sub.go | 28 +++++++- sub/subController.go | 66 ++++++++++++++----- web/assets/js/model/setting.js | 5 ++ web/entity/entity.go | 5 ++ .../settings/panel/subscription/general.html | 51 ++++++++++++-- web/service/setting.go | 25 +++++++ web/translation/translate.ar_EG.toml | 10 +++ web/translation/translate.en_US.toml | 10 +++ web/translation/translate.es_ES.toml | 10 +++ web/translation/translate.fa_IR.toml | 10 +++ web/translation/translate.id_ID.toml | 10 +++ web/translation/translate.ja_JP.toml | 10 +++ web/translation/translate.pt_BR.toml | 10 +++ web/translation/translate.ru_RU.toml | 12 +++- web/translation/translate.tr_TR.toml | 10 +++ web/translation/translate.uk_UA.toml | 10 +++ web/translation/translate.vi_VN.toml | 10 +++ web/translation/translate.zh_CN.toml | 10 +++ web/translation/translate.zh_TW.toml | 10 +++ 19 files changed, 285 insertions(+), 27 deletions(-) diff --git a/sub/sub.go b/sub/sub.go index 0605c8b9..1dcd9601 100644 --- a/sub/sub.go +++ b/sub/sub.go @@ -153,6 +153,31 @@ func (s *Server) initRouter() (*gin.Engine, error) { SubTitle = "" } + SubSupportUrl, err := s.settingService.GetSubSupportUrl() + if err != nil { + SubSupportUrl = "" + } + + SubProfileUrl, err := s.settingService.GetSubProfileUrl() + if err != nil { + SubProfileUrl = "" + } + + SubAnnounce, err := s.settingService.GetSubAnnounce() + if err != nil { + SubAnnounce = "" + } + + SubEnableRouting, err := s.settingService.GetSubEnableRouting() + if err != nil { + return nil, err + } + + SubRoutingRules, err := s.settingService.GetSubRoutingRules() + if err != nil { + SubRoutingRules = "" + } + // set per-request localizer from headers/cookies engine.Use(locale.LocalizerMiddleware()) @@ -231,7 +256,8 @@ func (s *Server) initRouter() (*gin.Engine, error) { s.sub = NewSUBController( g, LinksPath, JsonPath, subJsonEnable, Encrypt, ShowInfo, RemarkModel, SubUpdates, - SubJsonFragment, SubJsonNoises, SubJsonMux, SubJsonRules, SubTitle) + SubJsonFragment, SubJsonNoises, SubJsonMux, SubJsonRules, SubTitle, SubSupportUrl, + SubProfileUrl, SubAnnounce, SubEnableRouting, SubRoutingRules) return engine, nil } diff --git a/sub/subController.go b/sub/subController.go index ec574d6e..7653a4e1 100644 --- a/sub/subController.go +++ b/sub/subController.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "fmt" "strings" + "strconv" "github.com/mhsanaei/3x-ui/v2/config" @@ -12,12 +13,17 @@ import ( // SUBController handles HTTP requests for subscription links and JSON configurations. type SUBController struct { - subTitle string - subPath string - subJsonPath string - jsonEnabled bool - subEncrypt bool - updateInterval string + subTitle string + subSupportUrl string + subProfileUrl string + subAnnounce string + subEnableRouting bool + subRoutingRules string + subPath string + subJsonPath string + jsonEnabled bool + subEncrypt bool + updateInterval string subService *SubService subJsonService *SubJsonService @@ -38,18 +44,28 @@ func NewSUBController( jsonMux string, jsonRules string, subTitle string, + subSupportUrl string, + subProfileUrl string, + subAnnounce string, + subEnableRouting bool, + subRoutingRules string, ) *SUBController { sub := NewSubService(showInfo, rModel) a := &SUBController{ - subTitle: subTitle, - subPath: subPath, - subJsonPath: jsonPath, - jsonEnabled: jsonEnabled, - subEncrypt: encrypt, - updateInterval: update, + subTitle: subTitle, + subSupportUrl: subSupportUrl, + subProfileUrl: subProfileUrl, + subAnnounce: subAnnounce, + subEnableRouting: subEnableRouting, + subRoutingRules: subRoutingRules, + subPath: subPath, + subJsonPath: jsonPath, + jsonEnabled: jsonEnabled, + subEncrypt: encrypt, + updateInterval: update, - subService: sub, - subJsonService: NewSubJsonService(jsonFragment, jsonNoise, jsonMux, jsonRules, sub), + subService: sub, + subJsonService: NewSubJsonService(jsonFragment, jsonNoise, jsonMux, jsonRules, sub), } a.initRouter(g) return a @@ -127,7 +143,7 @@ func (a *SUBController) subs(c *gin.Context) { // Add headers header := fmt.Sprintf("upload=%d; download=%d; total=%d; expire=%d", traffic.Up, traffic.Down, traffic.Total, traffic.ExpiryTime/1000) - a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle) + a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle, a.subSupportUrl, a.subProfileUrl, a.subAnnounce, a.subEnableRouting, a.subRoutingRules) if a.subEncrypt { c.String(200, base64.StdEncoding.EncodeToString([]byte(result))) @@ -145,17 +161,31 @@ func (a *SUBController) subJsons(c *gin.Context) { if err != nil || len(jsonSub) == 0 { c.String(400, "Error!") } else { - // Add headers - a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle) + a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle, a.subSupportUrl, a.subProfileUrl, a.subAnnounce, a.subEnableRouting, a.subRoutingRules) c.String(200, jsonSub) } } // ApplyCommonHeaders sets common HTTP headers for subscription responses including user info, update interval, and profile title. -func (a *SUBController) ApplyCommonHeaders(c *gin.Context, header, updateInterval, profileTitle string) { +func (a *SUBController) ApplyCommonHeaders( + c *gin.Context, + header, + updateInterval, + profileTitle string, + profileSupportUrl string, + profileUrl string, + profileAnnounce string, + profileEnableRouting bool, + profileRoutingRules string, +) { c.Writer.Header().Set("Subscription-Userinfo", header) c.Writer.Header().Set("Profile-Update-Interval", updateInterval) c.Writer.Header().Set("Profile-Title", "base64:"+base64.StdEncoding.EncodeToString([]byte(profileTitle))) + c.Writer.Header().Set("Support-Url", profileSupportUrl) + c.Writer.Header().Set("Profile-Web-Page-Url", profileUrl) + c.Writer.Header().Set("Announce", "base64:"+base64.StdEncoding.EncodeToString([]byte(profileAnnounce))) + c.Writer.Header().Set("Routing-Enable", strconv.FormatBool(profileEnableRouting)) + c.Writer.Header().Set("Routing", profileRoutingRules) } diff --git a/web/assets/js/model/setting.js b/web/assets/js/model/setting.js index 53ffae1a..af80a63e 100644 --- a/web/assets/js/model/setting.js +++ b/web/assets/js/model/setting.js @@ -29,6 +29,11 @@ class AllSetting { this.subEnable = true; this.subJsonEnable = false; this.subTitle = ""; + this.subSupportUrl = ""; + this.subProfileUrl = ""; + this.subAnnounce = ""; + this.subEnableRouting = true; + this.subRoutingRules = ""; this.subListen = ""; this.subPort = 2096; this.subPath = "/sub/"; diff --git a/web/entity/entity.go b/web/entity/entity.go index 42e2df85..40294925 100644 --- a/web/entity/entity.go +++ b/web/entity/entity.go @@ -57,6 +57,11 @@ type AllSetting struct { SubEnable bool `json:"subEnable" form:"subEnable"` // Enable subscription server SubJsonEnable bool `json:"subJsonEnable" form:"subJsonEnable"` // Enable JSON subscription endpoint SubTitle string `json:"subTitle" form:"subTitle"` // Subscription title + SubSupportUrl string `json:"subSupportUrl" form:"subSupportUrl"` // Subscription support URL + SubProfileUrl string `json:"subProfileUrl" form:"subProfileUrl"` // Subscription profile URL + SubAnnounce string `json:"subAnnounce" form:"subAnnounce"` // Subscription announce + SubEnableRouting bool `json:"subEnableRouting" form:"subEnableRouting"` // Enable routing for subscription + SubRoutingRules string `json:"subRoutingRules" form:"subRoutingRules"` // Subscription global routing rules (Only for Happ) SubListen string `json:"subListen" form:"subListen"` // Subscription server listen IP SubPort int `json:"subPort" form:"subPort"` // Subscription server port SubPath string `json:"subPath" form:"subPath"` // Base path for subscription URLs diff --git a/web/html/settings/panel/subscription/general.html b/web/html/settings/panel/subscription/general.html index e65b2738..5d83aa37 100644 --- a/web/html/settings/panel/subscription/general.html +++ b/web/html/settings/panel/subscription/general.html @@ -15,13 +15,6 @@ - - - - - @@ -78,6 +71,50 @@ + {{ i18n "pages.xray.basicTemplate"}} + + + + + + + + + + + + + + + + + + + + + {{ i18n "pages.xray.advancedTemplate"}} (Happ) + + + + + + + + + + diff --git a/web/service/setting.go b/web/service/setting.go index 56db346d..3fa37f44 100644 --- a/web/service/setting.go +++ b/web/service/setting.go @@ -53,6 +53,11 @@ var defaultValueMap = map[string]string{ "subEnable": "true", "subJsonEnable": "false", "subTitle": "", + "subSupportUrl": "", + "subProfileUrl": "", + "subAnnounce": "", + "subEnableRouting": "true", + "subRoutingRules": "", "subListen": "", "subPort": "2096", "subPath": "/sub/", @@ -459,6 +464,26 @@ func (s *SettingService) GetSubTitle() (string, error) { return s.getString("subTitle") } +func (s *SettingService) GetSubSupportUrl() (string, error) { + return s.getString("subSupportUrl") +} + +func (s *SettingService) GetSubProfileUrl() (string, error) { + return s.getString("subProfileUrl") +} + +func (s *SettingService) GetSubAnnounce() (string, error) { + return s.getString("subAnnounce") +} + +func (s *SettingService) GetSubEnableRouting() (bool, error) { + return s.getBool("subEnableRouting") +} + +func (s *SettingService) GetSubRoutingRules() (string, error) { + return s.getString("subRoutingRules") +} + func (s *SettingService) GetSubListen() (string, error) { return s.getString("subListen") } diff --git a/web/translation/translate.ar_EG.toml b/web/translation/translate.ar_EG.toml index 06a3e937..6d75d196 100644 --- a/web/translation/translate.ar_EG.toml +++ b/web/translation/translate.ar_EG.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "تمكين/تعطيل نقطة نهاية اشتراك JSON بشكل مستقل." "subTitle" = "عنوان الاشتراك" "subTitleDesc" = "العنوان اللي هيظهر في عميل VPN" +"subSupportUrl" = "رابط الدعم" +"subSupportUrlDesc" = "رابط الدعم الفني المعروض في عميل VPN" +"subProfileUrl" = "رابط الملف الشخصي" +"subProfileUrlDesc" = "رابط لموقعك الإلكتروني يظهر في عميل VPN" +"subAnnounce" = "إعلان" +"subAnnounceDesc" = "نص الإعلان المعروض في عميل VPN" +"subEnableRouting" = "تفعيل التوجيه" +"subEnableRoutingDesc" = "إعداد عام لتمكين التوجيه (Routing) في عميل VPN. (فقط لـ Happ)" +"subRoutingRules" = "قواعد التوجيه" +"subRoutingRulesDesc" = "قواعد التوجيه العامة لعميل VPN. (فقط لـ Happ)" "subListen" = "IP الاستماع" "subListenDesc" = "عنوان IP لخدمة الاشتراك. (سيبه فاضي عشان يستمع على كل الـ IPs)" "subPort" = "بورت الاستماع" diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index 6da9185b..244e6f2c 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "Enable/Disable the JSON subscription endpoint independently." "subTitle" = "Subscription Title" "subTitleDesc" = "Title shown in VPN client" +"subSupportUrl" = "Support URL" +"subSupportUrlDesc" = "Technical support link shown in the VPN client" +"subProfileUrl" = "Profile URL" +"subProfileUrlDesc" = "A link to your website displayed in the VPN client" +"subAnnounce" = "Announce" +"subAnnounceDesc" = "The text of the announce displayed in the VPN client" +"subEnableRouting" = "Enable routing" +"subEnableRoutingDesc" = "Global setting to enable routing in the VPN client. (Only for Happ)" +"subRoutingRules" = "Routing rules" +"subRoutingRulesDesc" = "Global routing rules for the VPN client. (Only for Happ)" "subListen" = "Listen IP" "subListenDesc" = "The IP address for the subscription service. (leave blank to listen on all IPs)" "subPort" = "Listen Port" diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index ccd5beff..b0dde898 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "Habilitar/Deshabilitar el endpoint de suscripción JSON de forma independiente." "subTitle" = "Título de la Suscripción" "subTitleDesc" = "Título mostrado en el cliente de VPN" +"subSupportUrl" = "URL de soporte" +"subSupportUrlDesc" = "Enlace de soporte técnico mostrado en el cliente VPN" +"subProfileUrl" = "URL del perfil" +"subProfileUrlDesc" = "Un enlace a tu sitio web mostrado en el cliente VPN" +"subAnnounce" = "Anuncio" +"subAnnounceDesc" = "El texto del anuncio mostrado en el cliente VPN" +"subEnableRouting" = "Habilitar enrutamiento" +"subEnableRoutingDesc" = "Configuración global para habilitar el enrutamiento en el cliente VPN. (Solo para Happ)" +"subRoutingRules" = "Reglas de enrutamiento" +"subRoutingRulesDesc" = "Reglas de enrutamiento globales para el cliente VPN. (Solo para Happ)" "subListen" = "Listening IP" "subListenDesc" = "Dejar en blanco por defecto para monitorear todas las IPs." "subPort" = "Puerto de Suscripción" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index a25484d1..1eda5fb5 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "فعال/غیرفعال‌سازی مستقل نقطه دسترسی سابسکریپشن JSON." "subTitle" = "عنوان اشتراک" "subTitleDesc" = "عنوان نمایش داده شده در کلاینت VPN" +"subSupportUrl" = "آدرس پشتیبانی" +"subSupportUrlDesc" = "لینک پشتیبانی فنی که در کلاینت VPN نمایش داده می‌شود" +"subProfileUrl" = "آدرس پروفایل" +"subProfileUrlDesc" = "لینک وب‌سایت شما که در کلاینت VPN نمایش داده می‌شود" +"subAnnounce" = "اعلان" +"subAnnounceDesc" = "متن اعلانی که در کلاینت VPN نمایش داده می‌شود" +"subEnableRouting" = "فعال‌سازی مسیریابی" +"subEnableRoutingDesc" = "تنظیمات سراسری برای فعال‌سازی مسیریابی در کلاینت VPN. (فقط برای Happ)" +"subRoutingRules" = "قوانین مسیریابی" +"subRoutingRulesDesc" = "قوانین مسیریابی سراسری برای کلاینت VPN. (فقط برای Happ)" "subListen" = "آدرس آی‌پی" "subListenDesc" = "آدرس آی‌پی برای سرویس سابسکریپشن. برای گوش دادن به‌تمام آی‌پی‌ها خالی‌بگذارید" "subPort" = "پورت" diff --git a/web/translation/translate.id_ID.toml b/web/translation/translate.id_ID.toml index 7bd7aae0..8804ef04 100644 --- a/web/translation/translate.id_ID.toml +++ b/web/translation/translate.id_ID.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "Aktifkan/Nonaktifkan endpoint langganan JSON secara mandiri." "subTitle" = "Judul Langganan" "subTitleDesc" = "Judul yang ditampilkan di klien VPN" +"subSupportUrl" = "URL Dukungan" +"subSupportUrlDesc" = "Tautan dukungan teknis yang ditampilkan di klien VPN" +"subProfileUrl" = "URL Profil" +"subProfileUrlDesc" = "Tautan ke situs web Anda yang ditampilkan di klien VPN" +"subAnnounce" = "Pengumuman" +"subAnnounceDesc" = "Teks pengumuman yang ditampilkan di klien VPN" +"subEnableRouting" = "Aktifkan perutean" +"subEnableRoutingDesc" = "Pengaturan global untuk mengaktifkan perutean (routing) di klien VPN. (Hanya untuk Happ)" +"subRoutingRules" = "Aturan routing" +"subRoutingRulesDesc" = "Aturan routing global untuk klien VPN. (Hanya untuk Happ)" "subListen" = "IP Pendengar" "subListenDesc" = "Alamat IP untuk layanan langganan. (biarkan kosong untuk mendengarkan semua IP)" "subPort" = "Port Pendengar" diff --git a/web/translation/translate.ja_JP.toml b/web/translation/translate.ja_JP.toml index bc9c294a..8bba24c0 100644 --- a/web/translation/translate.ja_JP.toml +++ b/web/translation/translate.ja_JP.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "JSON サブスクリプションのエンドポイントを個別に有効/無効にする。" "subTitle" = "サブスクリプションタイトル" "subTitleDesc" = "VPNクライアントに表示されるタイトル" +"subSupportUrl" = "サポートURL" +"subSupportUrlDesc" = "VPNクライアントに表示されるテクニカルサポートへのリンク" +"subProfileUrl" = "プロフィールURL" +"subProfileUrlDesc" = "VPNクライアントに表示されるWebサイトへのリンク" +"subAnnounce" = "お知らせ" +"subAnnounceDesc" = "VPNクライアントに表示されるお知らせのテキスト" +"subEnableRouting" = "ルーティングを有効化" +"subEnableRoutingDesc" = "VPNクライアントでルーティングを有効にするためのグローバル設定。(Happのみ)" +"subRoutingRules" = "ルーティングルール" +"subRoutingRulesDesc" = "VPNクライアントのグローバルルーティングルール。(Happのみ)" "subListen" = "監視IP" "subListenDesc" = "サブスクリプションサービスが監視するIPアドレス(空白にするとすべてのIPを監視)" "subPort" = "監視ポート" diff --git a/web/translation/translate.pt_BR.toml b/web/translation/translate.pt_BR.toml index 86b3b97b..1b173e6e 100644 --- a/web/translation/translate.pt_BR.toml +++ b/web/translation/translate.pt_BR.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "Ativar/Desativar o endpoint de assinatura JSON de forma independente." "subTitle" = "Título da Assinatura" "subTitleDesc" = "Título exibido no cliente VPN" +"subSupportUrl" = "URL de Suporte" +"subSupportUrlDesc" = "Link de suporte técnico exibido no cliente VPN" +"subProfileUrl" = "URL de Perfil" +"subProfileUrlDesc" = "Um link para o seu site exibido no cliente VPN" +"subAnnounce" = "Anúncio" +"subAnnounceDesc" = "O texto do anúncio exibido no cliente VPN" +"subEnableRouting" = "Ativar roteamento" +"subEnableRoutingDesc" = "Configuração global para habilitar o roteamento no cliente VPN. (Apenas para Happ)" +"subRoutingRules" = "Regras de roteamento" +"subRoutingRulesDesc" = "Regras de roteamento globais para o cliente VPN. (Apenas para Happ)" "subListen" = "IP de Escuta" "subListenDesc" = "O endereço IP para o serviço de assinatura. (deixe em branco para escutar em todos os IPs)" "subPort" = "Porta de Escuta" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index 63fbbbb6..895734f5 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -373,7 +373,17 @@ "subEnableDesc" = "Функция подписки с отдельной конфигурацией" "subJsonEnable" = "Включить/отключить JSON-эндпоинт подписки независимо." "subTitle" = "Заголовок подписки" -"subTitleDesc" = "Название подписки, которое видит клиент в VPN клиенте" +"subTitleDesc" = "Название подписки, которое видит клиент в VPN-клиенте" +"subSupportUrl" = "URL поддержки" +"subSupportUrlDesc" = "Ссылка на техническую поддержку, отображаемая в VPN-клиенте" +"subProfileUrl" = "URL профиля" +"subProfileUrlDesc" = "Ссылка на ваш сайт, отображаемая в VPN-клиенте" +"subAnnounce" = "Объявление" +"subAnnounceDesc" = "Текст объявления, отображаемый в VPN-клиенте" +"subEnableRouting" = "Включить маршрутизацию" +"subEnableRoutingDesc" = "Глобальная настройка для включения маршрутизации в VPN-клиенте. (Только для Happ)" +"subRoutingRules" = "Правила маршрутизации" +"subRoutingRulesDesc" = "Глобальные правила маршрутизации для VPN-клиента. (Только для Happ)" "subListen" = "Прослушивание IP" "subListenDesc" = "Оставьте пустым по умолчанию, чтобы отслеживать все IP-адреса" "subPort" = "Порт подписки" diff --git a/web/translation/translate.tr_TR.toml b/web/translation/translate.tr_TR.toml index 25b8de9b..50639358 100644 --- a/web/translation/translate.tr_TR.toml +++ b/web/translation/translate.tr_TR.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "JSON abonelik uç noktasını bağımsız olarak Etkinleştir/Devre Dışı bırak." "subTitle" = "Abonelik Başlığı" "subTitleDesc" = "VPN istemcisinde gösterilen başlık" +"subSupportUrl" = "Destek URL'si" +"subSupportUrlDesc" = "VPN istemcisinde gösterilen teknik destek bağlantısı" +"subProfileUrl" = "Profil URL'si" +"subProfileUrlDesc" = "VPN istemcisinde görüntülenen web sitenize giden bağlantı" +"subAnnounce" = "Duyuru" +"subAnnounceDesc" = "VPN istemcisinde görüntülenen duyuru metni" +"subEnableRouting" = "Yönlendirmeyi etkinleştir" +"subEnableRoutingDesc" = "VPN istemcisinde yönlendirmeyi etkinleştirmek için genel ayar. (Yalnızca Happ için)" +"subRoutingRules" = "Yönlendirme kuralları" +"subRoutingRulesDesc" = "VPN istemcisi için genel yönlendirme kuralları. (Yalnızca Happ için)" "subListen" = "Dinleme IP" "subListenDesc" = "Abonelik hizmeti için IP adresi. (tüm IP'leri dinlemek için boş bırakın)" "subPort" = "Dinleme Portu" diff --git a/web/translation/translate.uk_UA.toml b/web/translation/translate.uk_UA.toml index c32854ae..54d45889 100644 --- a/web/translation/translate.uk_UA.toml +++ b/web/translation/translate.uk_UA.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "Увімкнути/вимкнути JSON-кінець підписки незалежно." "subTitle" = "Назва Підписки" "subTitleDesc" = "Назва, яка відображається у VPN-клієнті" +"subSupportUrl" = "URL підтримки" +"subSupportUrlDesc" = "Посилання на технічну підтримку, що відображається у VPN-клієнті" +"subProfileUrl" = "URL профілю" +"subProfileUrlDesc" = "Посилання на ваш вебсайт, що відображається у VPN-клієнті" +"subAnnounce" = "Оголошення" +"subAnnounceDesc" = "Текст оголошення, що відображається у VPN-клієнті" +"subEnableRouting" = "Увімкнути маршрутизацію" +"subEnableRoutingDesc" = "Глобальне налаштування для увімкнення маршрутизації у VPN-клієнті. (Тільки для Happ)" +"subRoutingRules" = "Правила маршрутизації" +"subRoutingRulesDesc" = "Глобальні правила маршрутизації для VPN-клієнта. (Тільки для Happ)" "subListen" = "Слухати IP" "subListenDesc" = "IP-адреса для служби підписки. (залиште порожнім, щоб слухати всі IP-адреси)" "subPort" = "Слухати порт" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index 1187548e..3fa63bb1 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "Bật/Tắt điểm cuối đăng ký JSON độc lập." "subTitle" = "Tiêu đề Đăng ký" "subTitleDesc" = "Tiêu đề hiển thị trong ứng dụng VPN" +"subSupportUrl" = "URL Hỗ trợ" +"subSupportUrlDesc" = "Liên kết hỗ trợ kỹ thuật hiển thị trong ứng dụng VPN" +"subProfileUrl" = "URL Hồ sơ" +"subProfileUrlDesc" = "Liên kết đến trang web của bạn hiển thị trong ứng dụng VPN" +"subAnnounce" = "Thông báo" +"subAnnounceDesc" = "Văn bản thông báo hiển thị trong ứng dụng VPN" +"subEnableRouting" = "Bật định tuyến" +"subEnableRoutingDesc" = "Cài đặt toàn cục để bật định tuyến trong ứng dụng khách VPN. (Chỉ dành cho Happ)" +"subRoutingRules" = "Quy tắc định tuyến" +"subRoutingRulesDesc" = "Quy tắc định tuyến toàn cầu cho client VPN. (Chỉ dành cho Happ)" "subListen" = "Listening IP" "subListenDesc" = "Mặc định để trống để nghe tất cả các IP" "subPort" = "Cổng gói đăng ký" diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml index 923cc21b..d6b82b93 100644 --- a/web/translation/translate.zh_CN.toml +++ b/web/translation/translate.zh_CN.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "单独启用/禁用 JSON 订阅端点。" "subTitle" = "订阅标题" "subTitleDesc" = "在VPN客户端中显示的标题" +"subSupportUrl" = "支持链接" +"subSupportUrlDesc" = "VPN 客户端中显示的技术支持链接" +"subProfileUrl" = "个人资料链接" +"subProfileUrlDesc" = "VPN 客户端中显示的网站链接" +"subAnnounce" = "公告" +"subAnnounceDesc" = "VPN 客户端中显示的公告文本" +"subEnableRouting" = "启用路由" +"subEnableRoutingDesc" = "在 VPN 客户端中启用路由的全局设置。(僅限 Happ)" +"subRoutingRules" = "路由規則" +"subRoutingRulesDesc" = "VPN 用戶端的全域路由規則。(僅限 Happ)" "subListen" = "监听 IP" "subListenDesc" = "订阅服务监听的 IP 地址(留空表示监听所有 IP)" "subPort" = "监听端口" diff --git a/web/translation/translate.zh_TW.toml b/web/translation/translate.zh_TW.toml index df32d742..616f2322 100644 --- a/web/translation/translate.zh_TW.toml +++ b/web/translation/translate.zh_TW.toml @@ -374,6 +374,16 @@ "subJsonEnable" = "獨立啟用/停用 JSON 訂閱端點。" "subTitle" = "訂閱標題" "subTitleDesc" = "在VPN客戶端中顯示的標題" +"subSupportUrl" = "支援連結" +"subSupportUrlDesc" = "VPN 用戶端中顯示的技術支援連結" +"subProfileUrl" = "個人資料連結" +"subProfileUrlDesc" = "VPN 用戶端中顯示的網站連結" +"subAnnounce" = "公告" +"subAnnounceDesc" = "VPN 用戶端中顯示的公告文字" +"subEnableRouting" = "啟用路由" +"subEnableRoutingDesc" = "在 VPN 用戶端中啟用路由的全域設定。(僅限 Happ)" +"subRoutingRules" = "路由規則" +"subRoutingRulesDesc" = "VPN 用戶端的全域路由規則。(僅限 Happ)" "subListen" = "監聽 IP" "subListenDesc" = "訂閱服務監聽的 IP 地址(留空表示監聽所有 IP)" "subPort" = "監聽埠"