mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-04 09:27:15 +00:00
feat: apply inbound/outbound/routing changes live via Xray gRPC API
Add a hot-apply layer that computes a diff between the old and new generated config and applies only the changed parts through the Xray gRPC HandlerService and RoutingService, avoiding a full process restart whenever possible. A restart is still performed when sections that have no reload API (log, dns, policy, observatory, ...) actually change. Key additions: - internal/xray/hot_diff.go: ComputeHotDiff with canonical-JSON comparison (sorted keys, null=absent, full number precision) so UI reformatting never triggers a spurious restart - internal/xray/api.go: AddOutbound/DelOutbound, ApplyRoutingConfig, GetBalancerInfo, SetBalancerTarget, TestRoute gRPC wrappers - internal/web/service/xray.go: tryHotApply, ensureAPIServices, GetBalancersStatus, OverrideBalancer, TestRoute service methods - internal/web/controller/xray_setting.go: balancerStatus, balancerOverride, routeTest API endpoints - frontend: BalancersTab live-status/override columns, RouteTester component, Restart button removed (Save now hot-applies) - balancer-helpers.ts: syncObservatories never creates observatory sections for random/roundRobin balancers (no reload API → restart) - i18n: balancerLive/Override/routeTester keys added to all 13 locales
This commit is contained in:
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "موازنات التحميل",
|
||||
"balancerTagRequired": "الوسم مطلوب",
|
||||
"balancerSelectorRequired": "اختر صادراً واحداً على الأقل",
|
||||
"balancerLive": "الهدف الحالي",
|
||||
"balancerOverride": "تجاوز الاختيار",
|
||||
"balancerOverridePh": "تلقائي (الاستراتيجية)",
|
||||
"balancerLiveRefresh": "تحديث حالة موازن التحميل",
|
||||
"balancerNotRunning": "موازن التحميل ده مش نشط في Xray الشغال — احفظ التغييرات أو ابدأ Xray الأول",
|
||||
"routeTester": "اختبار المسار",
|
||||
"routeTesterDesc": "اسأل Xray الشغال أي صادر هيتعامل مع الاتصال ده. مفيش ترافيك بيتبعت — القرار بييجي مباشرة من محرك التوجيه الحي.",
|
||||
"routeTesterDest": "نطاق أو IP",
|
||||
"routeTesterPort": "المنفذ",
|
||||
"routeTesterInbound": "الوارد",
|
||||
"routeTesterProtocol": "البروتوكول المكتشف",
|
||||
"routeTesterTest": "اختبر المسار",
|
||||
"routeTesterMatchedOutbound": "الصادر المطابق",
|
||||
"routeTesterViaBalancer": "عبر موازن التحميل",
|
||||
"routeTesterDefaultOutbound": "ما في قاعدة توجيه اتطابقت — الترافيك رايح للصادر الافتراضي (الأول).",
|
||||
"OutboundsDesc": "حدد مسار الترافيك الصادر.",
|
||||
"Routings": "قواعد التوجيه",
|
||||
"RoutingsDesc": "أولوية كل قاعدة مهمة جداً!",
|
||||
|
||||
@@ -1186,6 +1186,21 @@
|
||||
"Balancers": "Balancers",
|
||||
"balancerTagRequired": "Tag is required",
|
||||
"balancerSelectorRequired": "Pick at least one outbound",
|
||||
"balancerLive": "Live Target",
|
||||
"balancerOverride": "Override",
|
||||
"balancerOverridePh": "Auto (strategy)",
|
||||
"balancerLiveRefresh": "Refresh live balancer state",
|
||||
"balancerNotRunning": "This balancer is not active in the running Xray — save your changes or start Xray first",
|
||||
"routeTester": "Route Tester",
|
||||
"routeTesterDesc": "Ask the running Xray which outbound would handle a connection. No traffic is sent — the decision comes straight from the live routing engine.",
|
||||
"routeTesterDest": "Domain or IP",
|
||||
"routeTesterPort": "Port",
|
||||
"routeTesterInbound": "Inbound",
|
||||
"routeTesterProtocol": "Sniffed protocol",
|
||||
"routeTesterTest": "Test Route",
|
||||
"routeTesterMatchedOutbound": "Matched outbound",
|
||||
"routeTesterViaBalancer": "via balancer",
|
||||
"routeTesterDefaultOutbound": "No routing rule matched — traffic goes to the default (first) outbound.",
|
||||
"OutboundsDesc": "Set the outgoing traffic pathway.",
|
||||
"Routings": "Routing Rules",
|
||||
"RoutingsDesc": "The priority of each rule is important!",
|
||||
|
||||
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "Equilibradores",
|
||||
"balancerTagRequired": "La etiqueta es obligatoria",
|
||||
"balancerSelectorRequired": "Elige al menos una salida",
|
||||
"balancerLive": "Destino actual",
|
||||
"balancerOverride": "Forzar destino",
|
||||
"balancerOverridePh": "Automático (estrategia)",
|
||||
"balancerLiveRefresh": "Actualizar estado del balanceador",
|
||||
"balancerNotRunning": "Este balanceador no está activo en el Xray en ejecución — guarda los cambios o inicia Xray primero",
|
||||
"routeTester": "Prueba de ruta",
|
||||
"routeTesterDesc": "Pregunta al Xray en ejecución qué salida gestionaría una conexión. No se envía tráfico real — la decisión viene directamente del motor de enrutamiento en vivo.",
|
||||
"routeTesterDest": "Dominio o IP",
|
||||
"routeTesterPort": "Puerto",
|
||||
"routeTesterInbound": "Entrante",
|
||||
"routeTesterProtocol": "Protocolo detectado",
|
||||
"routeTesterTest": "Probar ruta",
|
||||
"routeTesterMatchedOutbound": "Salida coincidente",
|
||||
"routeTesterViaBalancer": "vía balanceador",
|
||||
"routeTesterDefaultOutbound": "Ninguna regla de enrutamiento coincidió — el tráfico va a la salida predeterminada (primera).",
|
||||
"OutboundsDesc": "Cambia la plantilla de configuración para definir formas de salida para este servidor.",
|
||||
"Routings": "Reglas de enrutamiento",
|
||||
"RoutingsDesc": "¡La prioridad de cada regla es importante!",
|
||||
|
||||
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "بالانسرها",
|
||||
"balancerTagRequired": "تگ الزامی است",
|
||||
"balancerSelectorRequired": "حداقل یک خروجی انتخاب کنید",
|
||||
"balancerLive": "هدف زنده",
|
||||
"balancerOverride": "اجبار مسیر",
|
||||
"balancerOverridePh": "خودکار (استراتژی)",
|
||||
"balancerLiveRefresh": "بهروزرسانی وضعیت زنده بالانسر",
|
||||
"balancerNotRunning": "این بالانسر در Xray در حال اجرا فعال نیست — ابتدا تغییرات را ذخیره کنید یا Xray را روشن کنید",
|
||||
"routeTester": "آزمایش مسیر",
|
||||
"routeTesterDesc": "از Xray در حال اجرا بپرسید یک اتصال از کدام خروجی عبور میکند. هیچ ترافیکی ارسال نمیشود — پاسخ مستقیماً از موتور مسیریابی زنده میآید.",
|
||||
"routeTesterDest": "دامنه یا IP",
|
||||
"routeTesterPort": "پورت",
|
||||
"routeTesterInbound": "ورودی",
|
||||
"routeTesterProtocol": "پروتکل تشخیصی",
|
||||
"routeTesterTest": "آزمایش مسیر",
|
||||
"routeTesterMatchedOutbound": "خروجی منطبق",
|
||||
"routeTesterViaBalancer": "از طریق بالانسر",
|
||||
"routeTesterDefaultOutbound": "هیچ قانونی منطبق نشد — ترافیک به خروجی پیشفرض (اولین خروجی) میرود.",
|
||||
"OutboundsDesc": "مسیر ترافیک خروجی را تنظیم کنید",
|
||||
"Routings": "قوانین مسیریابی",
|
||||
"RoutingsDesc": "اولویت هر قانون مهم است",
|
||||
|
||||
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "Penyeimbang",
|
||||
"balancerTagRequired": "Tag wajib diisi",
|
||||
"balancerSelectorRequired": "Pilih setidaknya satu outbound",
|
||||
"balancerLive": "Target Saat Ini",
|
||||
"balancerOverride": "Paksa Tujuan",
|
||||
"balancerOverridePh": "Otomatis (strategi)",
|
||||
"balancerLiveRefresh": "Perbarui status penyeimbang beban",
|
||||
"balancerNotRunning": "Penyeimbang ini tidak aktif di Xray yang berjalan — simpan perubahan atau mulai Xray terlebih dahulu",
|
||||
"routeTester": "Uji Rute",
|
||||
"routeTesterDesc": "Tanyakan kepada Xray yang berjalan outbound mana yang akan menangani koneksi. Tidak ada lalu lintas yang dikirim — keputusan langsung datang dari mesin routing langsung.",
|
||||
"routeTesterDest": "Domain atau IP",
|
||||
"routeTesterPort": "Port",
|
||||
"routeTesterInbound": "Inbound",
|
||||
"routeTesterProtocol": "Protokol yang terdeteksi",
|
||||
"routeTesterTest": "Uji Rute",
|
||||
"routeTesterMatchedOutbound": "Outbound yang cocok",
|
||||
"routeTesterViaBalancer": "melalui penyeimbang",
|
||||
"routeTesterDefaultOutbound": "Tidak ada aturan routing yang cocok — lalu lintas menuju outbound default (pertama).",
|
||||
"OutboundsDesc": "Atur jalur lalu lintas keluar.",
|
||||
"Routings": "Aturan Pengalihan",
|
||||
"RoutingsDesc": "Prioritas setiap aturan penting!",
|
||||
|
||||
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "負荷分散",
|
||||
"balancerTagRequired": "タグは必須です",
|
||||
"balancerSelectorRequired": "アウトバウンドを少なくとも1つ選んでください",
|
||||
"balancerLive": "現在のターゲット",
|
||||
"balancerOverride": "ターゲット強制",
|
||||
"balancerOverridePh": "自動(ストラテジー)",
|
||||
"balancerLiveRefresh": "ロードバランサーのライブ状態を更新",
|
||||
"balancerNotRunning": "このバランサーは実行中の Xray でアクティブではありません — 変更を保存するか、先に Xray を起動してください",
|
||||
"routeTester": "ルートテスト",
|
||||
"routeTesterDesc": "実行中の Xray にどのアウトバウンドが接続を処理するか問い合わせます。実際のトラフィックは送信されません — 判断はライブルーティングエンジンから直接取得されます。",
|
||||
"routeTesterDest": "ドメインまたは IP",
|
||||
"routeTesterPort": "ポート",
|
||||
"routeTesterInbound": "インバウンド",
|
||||
"routeTesterProtocol": "検出されたプロトコル",
|
||||
"routeTesterTest": "ルートをテスト",
|
||||
"routeTesterMatchedOutbound": "マッチしたアウトバウンド",
|
||||
"routeTesterViaBalancer": "バランサー経由",
|
||||
"routeTesterDefaultOutbound": "ルーティングルールに一致しませんでした — トラフィックはデフォルト(最初の)アウトバウンドに送られます。",
|
||||
"OutboundsDesc": "アウトバウンドトラフィックの送信方法を設定する",
|
||||
"Routings": "ルーティングルール",
|
||||
"RoutingsDesc": "各ルールの優先順位が重要です",
|
||||
|
||||
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "Balanceadores",
|
||||
"balancerTagRequired": "A tag é obrigatória",
|
||||
"balancerSelectorRequired": "Selecione pelo menos uma saída",
|
||||
"balancerLive": "Destino atual",
|
||||
"balancerOverride": "Forçar destino",
|
||||
"balancerOverridePh": "Automático (estratégia)",
|
||||
"balancerLiveRefresh": "Atualizar estado do balanceador",
|
||||
"balancerNotRunning": "Este balanceador não está ativo no Xray em execução — salve as alterações ou inicie o Xray primeiro",
|
||||
"routeTester": "Teste de rota",
|
||||
"routeTesterDesc": "Pergunte ao Xray em execução qual saída trataria uma conexão. Nenhum tráfego é enviado — a decisão vem diretamente do motor de roteamento ao vivo.",
|
||||
"routeTesterDest": "Domínio ou IP",
|
||||
"routeTesterPort": "Porta",
|
||||
"routeTesterInbound": "Entrada",
|
||||
"routeTesterProtocol": "Protocolo detectado",
|
||||
"routeTesterTest": "Testar rota",
|
||||
"routeTesterMatchedOutbound": "Saída correspondente",
|
||||
"routeTesterViaBalancer": "via balanceador",
|
||||
"routeTesterDefaultOutbound": "Nenhuma regra de roteamento correspondeu — o tráfego vai para a saída padrão (primeira).",
|
||||
"OutboundsDesc": "Definir o caminho de saída do tráfego.",
|
||||
"Routings": "Regras de Roteamento",
|
||||
"RoutingsDesc": "A prioridade de cada regra é importante!",
|
||||
|
||||
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "Балансировщик",
|
||||
"balancerTagRequired": "Тег обязателен",
|
||||
"balancerSelectorRequired": "Выберите хотя бы одно исходящее",
|
||||
"balancerLive": "Текущая цель",
|
||||
"balancerOverride": "Переопределить",
|
||||
"balancerOverridePh": "Авто (стратегия)",
|
||||
"balancerLiveRefresh": "Обновить состояние балансировщика",
|
||||
"balancerNotRunning": "Этот балансировщик неактивен в запущенном Xray — сохраните изменения или запустите Xray",
|
||||
"routeTester": "Тест маршрута",
|
||||
"routeTesterDesc": "Спросите запущенный Xray, через какой исходящий будет обработано соединение. Трафик не отправляется — решение поступает напрямую от живого движка маршрутизации.",
|
||||
"routeTesterDest": "Домен или IP",
|
||||
"routeTesterPort": "Порт",
|
||||
"routeTesterInbound": "Входящий",
|
||||
"routeTesterProtocol": "Обнаруженный протокол",
|
||||
"routeTesterTest": "Тест маршрута",
|
||||
"routeTesterMatchedOutbound": "Совпавший исходящий",
|
||||
"routeTesterViaBalancer": "через балансировщик",
|
||||
"routeTesterDefaultOutbound": "Ни одно правило маршрутизации не совпало — трафик направляется в исходящий по умолчанию (первый).",
|
||||
"OutboundsDesc": "Изменение шаблона конфигурации, чтобы определить исходящие подключения для этого сервера",
|
||||
"Routings": "Маршрутизация",
|
||||
"RoutingsDesc": "Важен приоритет каждого правила!",
|
||||
|
||||
@@ -1184,6 +1184,21 @@
|
||||
"Balancers": "Dengeleyiciler",
|
||||
"balancerTagRequired": "Etiket zorunludur",
|
||||
"balancerSelectorRequired": "En az bir giden bağlantı seçin",
|
||||
"balancerLive": "Anlık Hedef",
|
||||
"balancerOverride": "Hedef Zorla",
|
||||
"balancerOverridePh": "Otomatik (strateji)",
|
||||
"balancerLiveRefresh": "Dengeleyici durumunu yenile",
|
||||
"balancerNotRunning": "Bu dengeleyici çalışan Xray'de etkin değil — değişikliklerinizi kaydedin veya önce Xray'i başlatın",
|
||||
"routeTester": "Rota Testi",
|
||||
"routeTesterDesc": "Çalışan Xray'e hangi giden bağlantının bir isteği işleyeceğini sorun. Gerçek trafik gönderilmez — karar doğrudan canlı yönlendirme motorundan gelir.",
|
||||
"routeTesterDest": "Alan adı veya IP",
|
||||
"routeTesterPort": "Port",
|
||||
"routeTesterInbound": "Gelen",
|
||||
"routeTesterProtocol": "Algılanan protokol",
|
||||
"routeTesterTest": "Rotayı Test Et",
|
||||
"routeTesterMatchedOutbound": "Eşleşen giden",
|
||||
"routeTesterViaBalancer": "dengeleyici aracılığıyla",
|
||||
"routeTesterDefaultOutbound": "Hiçbir yönlendirme kuralı eşleşmedi — trafik varsayılan (ilk) giden bağlantıya yönlendirilir.",
|
||||
"OutboundsDesc": "Giden trafiğin yolunu ayarlayın.",
|
||||
"Routings": "Yönlendirme Kuralları",
|
||||
"RoutingsDesc": "Her kuralın önceliği önemlidir!",
|
||||
|
||||
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "Балансери",
|
||||
"balancerTagRequired": "Тег обов'язковий",
|
||||
"balancerSelectorRequired": "Виберіть принаймні один вихідний",
|
||||
"balancerLive": "Поточна ціль",
|
||||
"balancerOverride": "Примусова ціль",
|
||||
"balancerOverridePh": "Авто (стратегія)",
|
||||
"balancerLiveRefresh": "Оновити стан балансувальника",
|
||||
"balancerNotRunning": "Цей балансувальник неактивний у запущеному Xray — збережіть зміни або спочатку запустіть Xray",
|
||||
"routeTester": "Тест маршруту",
|
||||
"routeTesterDesc": "Запитайте запущений Xray, через який вихідний буде оброблено з'єднання. Реальний трафік не надсилається — рішення надходить безпосередньо від живого рушія маршрутизації.",
|
||||
"routeTesterDest": "Домен або IP",
|
||||
"routeTesterPort": "Порт",
|
||||
"routeTesterInbound": "Вхідний",
|
||||
"routeTesterProtocol": "Виявлений протокол",
|
||||
"routeTesterTest": "Тест маршруту",
|
||||
"routeTesterMatchedOutbound": "Відповідний вихідний",
|
||||
"routeTesterViaBalancer": "через балансувальник",
|
||||
"routeTesterDefaultOutbound": "Жодне правило маршрутизації не збіглося — трафік надходить до вихідного за замовчуванням (першого).",
|
||||
"OutboundsDesc": "Встановити шлях вихідного трафіку.",
|
||||
"Routings": "Правила маршрутизації",
|
||||
"RoutingsDesc": "Пріоритет кожного правила важливий!",
|
||||
|
||||
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "Cân bằng",
|
||||
"balancerTagRequired": "Tag là bắt buộc",
|
||||
"balancerSelectorRequired": "Chọn ít nhất một outbound",
|
||||
"balancerLive": "Mục tiêu hiện tại",
|
||||
"balancerOverride": "Ghi đè đích",
|
||||
"balancerOverridePh": "Tự động (chiến lược)",
|
||||
"balancerLiveRefresh": "Làm mới trạng thái bộ cân bằng tải",
|
||||
"balancerNotRunning": "Bộ cân bằng này không hoạt động trong Xray đang chạy — hãy lưu thay đổi hoặc khởi động Xray trước",
|
||||
"routeTester": "Kiểm tra tuyến đường",
|
||||
"routeTesterDesc": "Hỏi Xray đang chạy outbound nào sẽ xử lý kết nối. Không có lưu lượng nào được gửi — quyết định đến thẳng từ công cụ định tuyến trực tiếp.",
|
||||
"routeTesterDest": "Tên miền hoặc IP",
|
||||
"routeTesterPort": "Cổng",
|
||||
"routeTesterInbound": "Inbound",
|
||||
"routeTesterProtocol": "Giao thức nhận diện",
|
||||
"routeTesterTest": "Kiểm tra tuyến",
|
||||
"routeTesterMatchedOutbound": "Outbound phù hợp",
|
||||
"routeTesterViaBalancer": "qua bộ cân bằng tải",
|
||||
"routeTesterDefaultOutbound": "Không có quy tắc định tuyến nào khớp — lưu lượng đến outbound mặc định (đầu tiên).",
|
||||
"OutboundsDesc": "Thay đổi mẫu cấu hình để xác định các cách ra đi cho máy chủ này.",
|
||||
"Routings": "Quy tắc định tuyến",
|
||||
"RoutingsDesc": "Mức độ ưu tiên của mỗi quy tắc đều quan trọng!",
|
||||
|
||||
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "负载均衡",
|
||||
"balancerTagRequired": "标签为必填项",
|
||||
"balancerSelectorRequired": "至少选择一个出站",
|
||||
"balancerLive": "当前目标",
|
||||
"balancerOverride": "强制指定",
|
||||
"balancerOverridePh": "自动(策略)",
|
||||
"balancerLiveRefresh": "刷新负载均衡器实时状态",
|
||||
"balancerNotRunning": "此负载均衡器在运行中的 Xray 未激活 — 请先保存更改或启动 Xray",
|
||||
"routeTester": "路由测试",
|
||||
"routeTesterDesc": "向运行中的 Xray 查询某个连接将使用哪个出站。不会发送真实流量 — 结果直接来自实时路由引擎。",
|
||||
"routeTesterDest": "域名或 IP",
|
||||
"routeTesterPort": "端口",
|
||||
"routeTesterInbound": "入站",
|
||||
"routeTesterProtocol": "嗅探协议",
|
||||
"routeTesterTest": "测试路由",
|
||||
"routeTesterMatchedOutbound": "匹配出站",
|
||||
"routeTesterViaBalancer": "经由负载均衡器",
|
||||
"routeTesterDefaultOutbound": "无路由规则匹配 — 流量将发往默认(第一个)出站。",
|
||||
"OutboundsDesc": "设置出站流量传出方式",
|
||||
"Routings": "路由规则",
|
||||
"RoutingsDesc": "每条规则的优先级都很重要",
|
||||
|
||||
@@ -1183,6 +1183,21 @@
|
||||
"Balancers": "負載均衡",
|
||||
"balancerTagRequired": "標籤為必填",
|
||||
"balancerSelectorRequired": "至少選擇一個出站",
|
||||
"balancerLive": "目前目標",
|
||||
"balancerOverride": "強制指定",
|
||||
"balancerOverridePh": "自動(策略)",
|
||||
"balancerLiveRefresh": "重新整理負載均衡器即時狀態",
|
||||
"balancerNotRunning": "此負載均衡器在執行中的 Xray 未啟用 — 請先儲存變更或啟動 Xray",
|
||||
"routeTester": "路由測試",
|
||||
"routeTesterDesc": "向執行中的 Xray 查詢某個連線將使用哪個出站。不會傳送真實流量 — 結果直接來自即時路由引擎。",
|
||||
"routeTesterDest": "網域或 IP",
|
||||
"routeTesterPort": "埠號",
|
||||
"routeTesterInbound": "入站",
|
||||
"routeTesterProtocol": "嗅探協議",
|
||||
"routeTesterTest": "測試路由",
|
||||
"routeTesterMatchedOutbound": "匹配出站",
|
||||
"routeTesterViaBalancer": "經由負載均衡器",
|
||||
"routeTesterDefaultOutbound": "無路由規則匹配 — 流量將導向預設(第一個)出站。",
|
||||
"OutboundsDesc": "設定出站流量傳出方式",
|
||||
"Routings": "路由規則",
|
||||
"RoutingsDesc": "每條規則的優先順序都很重要",
|
||||
|
||||
Reference in New Issue
Block a user