Skip to content

Commit 9e2ce2d

Browse files
committed
feat(core-editor): enhance validation, localization, and WireGuard configuration
- Add validation error and warning localization strings across all supported languages - Implement port list validation supporting ranges (e.g., 443, 1000-2000, 444) for inbound and routing rules - Add pre-shared key generation UI and localization for WireGuard interface configuration - Enhance WireGuard form with field labels for interface name, keys, port, and address - Update port validation messages to reflect support for port lists and ranges - Add discard confirmation dialogs for inbound and outbound edits with localized messages - Implement routing rule validation for outbound and balancer tag requirements - Add loading state localization for core editor initialization - Improve validation summary component with error and warning categorization - Update inbound dialog schema and routing rule validation logic to support new port formats
1 parent 674eeca commit 9e2ce2d

13 files changed

Lines changed: 356 additions & 65 deletions

File tree

dashboard/public/statics/locales/en.json

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,8 +1943,14 @@
19431943
"coreEditor": {
19441944
"nameRequired": "Name is required",
19451945
"fixValidation": "Fix validation errors before saving",
1946+
"validationErrors": "Validation errors",
1947+
"validationWarnings": "Warnings",
19461948
"importWarnings": "Import notes",
19471949
"loadFailed": "Could not load this core.",
1950+
"loading": {
1951+
"title": "Loading core editor",
1952+
"description": "Preparing the editor layout."
1953+
},
19481954
"backToList": "Back to cores",
19491955
"invalidId": "Invalid core id.",
19501956
"discardTitle": "Discard changes?",
@@ -1999,7 +2005,18 @@
19992005
"interfaceBlurb": "WireGuard interface settings and key material for this core.",
20002006
"keysRegenerated": "New keypair generated",
20012007
"keysFailed": "Could not generate keys",
2002-
"regenerateKeys": "Regenerate keypair"
2008+
"regenerateKeys": "Regenerate keypair",
2009+
"generatePreSharedKey": "Generate pre-shared key",
2010+
"preSharedKeyGenerated": "Pre-shared key generated",
2011+
"preSharedKeyFailed": "Could not generate pre-shared key",
2012+
"fields": {
2013+
"interfaceName": "Interface name",
2014+
"privateKey": "Private key",
2015+
"publicKey": "Public key",
2016+
"preSharedKey": "Pre-shared key",
2017+
"listenPort": "Listen port",
2018+
"address": "Address"
2019+
}
20032020
},
20042021
"field": {
20052022
"tag": "Tag",
@@ -2103,6 +2120,7 @@
21032120
"domain": "Domain",
21042121
"domains": "Domains",
21052122
"ip": "IP",
2123+
"port": "Port",
21062124
"network": "Network",
21072125
"sourceip": "Source IP",
21082126
"source": "Source",
@@ -2299,7 +2317,7 @@
22992317
},
23002318
"validation": {
23012319
"protocolInvalid": "Select a valid protocol.",
2302-
"portRange": "Port must be a whole number between 1 and 65535.",
2320+
"portRange": "Port must be a port number or list like 443, 1000-2000,444.",
23032321
"destinationPortRange": "Destination port must be a whole number from 0 to 65535.",
23042322
"realityServerNamesRequired": "REALITY requires at least one server name.",
23052323
"realityServerNamesFormat": "REALITY server names must be a list of non-empty strings.",
@@ -2308,6 +2326,8 @@
23082326
"discardDraftTitle": "Discard new inbound?",
23092327
"discardDraftDescription": "This inbound is not in the list yet. Close without adding it will discard your changes.",
23102328
"discardDraftAction": "Discard",
2329+
"discardEditTitle": "Discard changes?",
2330+
"discardEditDescription": "Your modifications to this inbound will be lost if you close now.",
23112331
"finishCurrentTitle": "Finish the current inbound first",
23122332
"finishCurrentDescription": "Add it to the list, or close the dialog and discard the draft, before starting another inbound."
23132333
},
@@ -2325,6 +2345,8 @@
23252345
"discardDraftTitle": "Discard new outbound?",
23262346
"discardDraftDescription": "This outbound is not in the list yet. Closing without adding will discard your changes.",
23272347
"discardDraftAction": "Discard",
2348+
"discardEditTitle": "Discard changes?",
2349+
"discardEditDescription": "Your modifications to this outbound will be lost if you close now.",
23282350
"finishCurrentTitle": "Finish the current outbound first",
23292351
"finishCurrentDescription": "Add it to the list, or close the dialog and discard the draft, before starting another outbound.",
23302352
"tabForm": "Form",
@@ -2417,6 +2439,12 @@
24172439
"discardDraftAction": "Discard",
24182440
"finishCurrentTitle": "Finish the current rule first",
24192441
"finishCurrentDescription": "Add it to the list, or close the dialog and discard the draft, before starting another rule.",
2442+
"validation": {
2443+
"requiresOutboundOrBalancer": "Set an outbound tag or a balancer tag so the rule knows where to send traffic.",
2444+
"unknownOutboundTag": "Outbound tag \"{{tag}}\" is not defined on this profile.",
2445+
"unknownBalancerTag": "Balancer tag \"{{tag}}\" is not defined under routing.balancers.",
2446+
"portRange": "Port must be a port number or list like 443, 1000-2000,444."
2447+
},
24202448
"sectionRoutingAction": "Routing Action",
24212449
"routingActionHint": "Choose one target for matched traffic. When both are set, outboundTag takes precedence over balancerTag.",
24222450
"sectionMatchConditions": "Match Conditions",

dashboard/public/statics/locales/fa.json

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,8 +1858,14 @@
18581858
"coreEditor": {
18591859
"nameRequired": "نام الزامی است",
18601860
"fixValidation": "قبل از ذخیره خطاهای اعتبارسنجی را برطرف کنید",
1861+
"validationErrors": "خطاهای اعتبارسنجی",
1862+
"validationWarnings": "هشدارها",
18611863
"importWarnings": "یادداشت‌های واردات",
18621864
"loadFailed": "بارگیری این هسته ناموفق بود.",
1865+
"loading": {
1866+
"title": "در حال بارگیری ویرایشگر هسته",
1867+
"description": "در حال آماده‌سازی چیدمان ویرایشگر."
1868+
},
18631869
"backToList": "بازگشت به فهرست هسته‌ها",
18641870
"invalidId": "شناسهٔ هسته نامعتبر است.",
18651871
"discardTitle": "لغو تغییرات؟",
@@ -1913,7 +1919,18 @@
19131919
"interfaceBlurb": "تنظیمات رابط وایرگارد و مواد کلیدی این هسته.",
19141920
"keysRegenerated": "جفت کلید جدید تولید شد",
19151921
"keysFailed": "تولید کلیدهای ناموفق بود",
1916-
"regenerateKeys": "تولید مجدد جفت کلید"
1922+
"regenerateKeys": "تولید مجدد جفت کلید",
1923+
"generatePreSharedKey": "تولید کلید ازپیش‌اشتراک‌گذاری‌شده",
1924+
"preSharedKeyGenerated": "کلید ازپیش‌اشتراک‌گذاری‌شده تولید شد",
1925+
"preSharedKeyFailed": "تولید کلید ازپیش‌اشتراک‌گذاری‌شده ناموفق بود",
1926+
"fields": {
1927+
"interfaceName": "نام رابط",
1928+
"privateKey": "کلید خصوصی",
1929+
"publicKey": "کلید عمومی",
1930+
"preSharedKey": "کلید ازپیش‌اشتراک‌گذاری‌شده",
1931+
"listenPort": "پورت شنود",
1932+
"address": "آدرس"
1933+
}
19171934
},
19181935
"field": {
19191936
"tag": "برچسب",
@@ -2017,6 +2034,7 @@
20172034
"domain": "دامنه",
20182035
"domains": "دامنه‌ها",
20192036
"ip": "IP",
2037+
"port": "پورت",
20202038
"network": "شبکه",
20212039
"sourceip": "IP مبدأ",
20222040
"source": "مبدأ",
@@ -2212,7 +2230,7 @@
22122230
},
22132231
"validation": {
22142232
"protocolInvalid": "یک پروتکل معتبر انتخاب کنید.",
2215-
"portRange": "پورت باید عدد صحیح بین ۱ و ۶۵۵۳۵ باشد.",
2233+
"portRange": "پورت باید عدد یا فهرست پورت مانند 443, 1000-2000,444 باشد.",
22162234
"destinationPortRange": "پورت مقصد باید عدد صحیح از ۰ تا ۶۵۵۳۵ باشد.",
22172235
"realityServerNamesRequired": "REALITY حداقل به یک نام سرور نیاز دارد.",
22182236
"realityServerNamesFormat": "نام‌های سرور REALITY باید فهرستی از رشته‌های غیرخالی باشد.",
@@ -2221,6 +2239,8 @@
22212239
"discardDraftTitle": "ورودی جدید را دور بیندازید؟",
22222240
"discardDraftDescription": "این ورودی هنوز در فهرست نیست. بستن بدون افزودن، تغییرات را دور می‌اندازد.",
22232241
"discardDraftAction": "صرف‌نظر",
2242+
"discardEditTitle": "لغو تغییرات؟",
2243+
"discardEditDescription": "اگر اکنون ببندید، تغییرات شما روی این ورودی از بین می‌رود.",
22242244
"finishCurrentTitle": "ابتدا ورودی فعلی را تمام کنید",
22252245
"finishCurrentDescription": "آن را به فهرست اضافه کنید، یا دیالوگ را ببندید و پیش‌نویس را دور بیندازید، قبل از شروع ورودی دیگر."
22262246
},
@@ -2237,6 +2257,8 @@
22372257
"discardDraftTitle": "خروجی جدید را دور بیندازید؟",
22382258
"discardDraftDescription": "این خروجی هنوز در فهرست نیست. بستن بدون افزودن، تغییرات را دور می‌اندازد.",
22392259
"discardDraftAction": "صرف‌نظر",
2260+
"discardEditTitle": "لغو تغییرات؟",
2261+
"discardEditDescription": "اگر اکنون ببندید، تغییرات شما روی این خروجی از بین می‌رود.",
22402262
"finishCurrentTitle": "ابتدا خروجی فعلی را تمام کنید",
22412263
"finishCurrentDescription": "آن را به فهرست اضافه کنید، یا دیالوگ را ببندید و پیش‌نویس را دور بیندازید، قبل از شروع خروجی دیگر.",
22422264
"freedom": {
@@ -2312,6 +2334,12 @@
23122334
"discardDraftAction": "صرف‌نظر",
23132335
"finishCurrentTitle": "ابتدا قانون فعلی را تمام کنید",
23142336
"finishCurrentDescription": "آن را به فهرست اضافه کنید، یا دیالوگ را ببندید و پیش‌نویس را دور بیندازید، قبل از شروع قانون دیگر.",
2337+
"validation": {
2338+
"requiresOutboundOrBalancer": "یک برچسب خروجی یا برچسب متعادل‌کننده تنظیم کنید تا قانون بداند ترافیک را کجا بفرستد.",
2339+
"unknownOutboundTag": "برچسب خروجی «{{tag}}» در این پروفایل تعریف نشده است.",
2340+
"unknownBalancerTag": "برچسب متعادل‌کننده «{{tag}}» در routing.balancers تعریف نشده است.",
2341+
"portRange": "پورت باید عدد یا فهرست پورت مانند 443, 1000-2000,444 باشد."
2342+
},
23152343
"sectionRoutingAction": "اقدام مسیریابی",
23162344
"routingActionHint": "برای ترافیک منطبق یک مقصد انتخاب کنید. وقتی هر دو تنظیم شوند، outboundTag بر balancerTag اولویت دارد.",
23172345
"sectionMatchConditions": "شرایط تطبیق",

dashboard/public/statics/locales/ru.json

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,8 +1832,14 @@
18321832
"coreEditor": {
18331833
"nameRequired": "Укажите имя",
18341834
"fixValidation": "Исправьте ошибки проверки перед сохранением",
1835+
"validationErrors": "Ошибки проверки",
1836+
"validationWarnings": "Предупреждения",
18351837
"importWarnings": "Замечания импорта",
18361838
"loadFailed": "Не удалось загрузить это ядро.",
1839+
"loading": {
1840+
"title": "Загрузка редактора ядра",
1841+
"description": "Подготовка интерфейса редактора."
1842+
},
18371843
"backToList": "Назад к списку ядер",
18381844
"invalidId": "Неверный идентификатор ядра.",
18391845
"discardTitle": "Отменить изменения?",
@@ -1887,7 +1893,18 @@
18871893
"interfaceBlurb": "Настройки интерфейса WireGuard и ключи для этого ядра.",
18881894
"keysRegenerated": "Создана новая пара ключей",
18891895
"keysFailed": "Не удалось сгенерировать ключи",
1890-
"regenerateKeys": "Пересоздать пару ключей"
1896+
"regenerateKeys": "Пересоздать пару ключей",
1897+
"generatePreSharedKey": "Сгенерировать предварительный общий ключ",
1898+
"preSharedKeyGenerated": "Предварительный общий ключ сгенерирован",
1899+
"preSharedKeyFailed": "Не удалось сгенерировать предварительный общий ключ",
1900+
"fields": {
1901+
"interfaceName": "Имя интерфейса",
1902+
"privateKey": "Приватный ключ",
1903+
"publicKey": "Публичный ключ",
1904+
"preSharedKey": "Предварительный общий ключ",
1905+
"listenPort": "Порт прослушивания",
1906+
"address": "Адрес"
1907+
}
18911908
},
18921909
"field": {
18931910
"tag": "Тег",
@@ -1991,6 +2008,7 @@
19912008
"domain": "Домен",
19922009
"domains": "Домены",
19932010
"ip": "IP",
2011+
"port": "Порт",
19942012
"network": "Сеть",
19952013
"sourceip": "IP источника",
19962014
"source": "Источник",
@@ -2186,7 +2204,7 @@
21862204
},
21872205
"validation": {
21882206
"protocolInvalid": "Выберите допустимый протокол.",
2189-
"portRange": "Порт должен быть целым числом от 1 до 65535.",
2207+
"portRange": "Порт должен быть номером или списком портов, например 443, 1000-2000,444.",
21902208
"destinationPortRange": "Порт назначения должен быть целым числом от 0 до 65535.",
21912209
"realityServerNamesRequired": "Для REALITY нужно хотя бы одно имя сервера (server name).",
21922210
"realityServerNamesFormat": "Имена серверов REALITY должны быть списком непустых строк.",
@@ -2195,6 +2213,8 @@
21952213
"discardDraftTitle": "Отменить новый входящий?",
21962214
"discardDraftDescription": "Этот входящий ещё не в списке. Закрытие без добавления отменит изменения.",
21972215
"discardDraftAction": "Отменить",
2216+
"discardEditTitle": "Отменить изменения?",
2217+
"discardEditDescription": "Ваши изменения этого входящего будут потеряны, если закрыть окно сейчас.",
21982218
"finishCurrentTitle": "Сначала завершите текущий входящий",
21992219
"finishCurrentDescription": "Добавьте его в список или закройте диалог и отмените черновик перед созданием другого входящего."
22002220
},
@@ -2211,6 +2231,8 @@
22112231
"discardDraftTitle": "Отменить новый исходящий?",
22122232
"discardDraftDescription": "Этот исходящий ещё не в списке. Закрытие без добавления отменит изменения.",
22132233
"discardDraftAction": "Отменить",
2234+
"discardEditTitle": "Отменить изменения?",
2235+
"discardEditDescription": "Ваши изменения этого исходящего будут потеряны, если закрыть окно сейчас.",
22142236
"finishCurrentTitle": "Сначала завершите текущий исходящий",
22152237
"finishCurrentDescription": "Добавьте его в список или закройте диалог и отмените черновик перед созданием другого исходящего.",
22162238
"freedom": {
@@ -2286,6 +2308,12 @@
22862308
"discardDraftAction": "Отменить",
22872309
"finishCurrentTitle": "Сначала завершите текущее правило",
22882310
"finishCurrentDescription": "Добавьте его в список или закройте диалог и отмените черновик перед созданием другого правила.",
2311+
"validation": {
2312+
"requiresOutboundOrBalancer": "Укажите тег исходящего или тег балансировщика, чтобы правило знало, куда отправлять трафик.",
2313+
"unknownOutboundTag": "Тег исходящего \"{{tag}}\" не определён в этом профиле.",
2314+
"unknownBalancerTag": "Тег балансировщика \"{{tag}}\" не определён в routing.balancers.",
2315+
"portRange": "Порт должен быть номером или списком портов, например 443, 1000-2000,444."
2316+
},
22892317
"sectionRoutingAction": "Действие маршрутизации",
22902318
"routingActionHint": "Выберите одну цель для совпадающего трафика. Если заданы оба, outboundTag имеет приоритет над balancerTag.",
22912319
"sectionMatchConditions": "Условия совпадения",

dashboard/public/statics/locales/zh.json

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,8 +1905,14 @@
19051905
"coreEditor": {
19061906
"nameRequired": "名称为必填项",
19071907
"fixValidation": "保存前请修复校验错误",
1908+
"validationErrors": "校验错误",
1909+
"validationWarnings": "警告",
19081910
"importWarnings": "导入提示",
19091911
"loadFailed": "无法加载此核心。",
1912+
"loading": {
1913+
"title": "正在加载核心编辑器",
1914+
"description": "正在准备编辑器布局。"
1915+
},
19101916
"backToList": "返回核心列表",
19111917
"invalidId": "核心 ID 无效。",
19121918
"discardTitle": "放弃更改?",
@@ -1960,7 +1966,18 @@
19601966
"interfaceBlurb": "此核心的 WireGuard 接口与密钥设置。",
19611967
"keysRegenerated": "已生成新密钥对",
19621968
"keysFailed": "无法生成密钥",
1963-
"regenerateKeys": "重新生成密钥对"
1969+
"regenerateKeys": "重新生成密钥对",
1970+
"generatePreSharedKey": "生成预共享密钥",
1971+
"preSharedKeyGenerated": "已生成预共享密钥",
1972+
"preSharedKeyFailed": "无法生成预共享密钥",
1973+
"fields": {
1974+
"interfaceName": "接口名称",
1975+
"privateKey": "私钥",
1976+
"publicKey": "公钥",
1977+
"preSharedKey": "预共享密钥",
1978+
"listenPort": "监听端口",
1979+
"address": "地址"
1980+
}
19641981
},
19651982
"field": {
19661983
"tag": "标签",
@@ -2064,6 +2081,7 @@
20642081
"domain": "域名",
20652082
"domains": "域名列表",
20662083
"ip": "IP",
2084+
"port": "端口",
20672085
"network": "网络",
20682086
"sourceip": "源 IP",
20692087
"source": "",
@@ -2259,7 +2277,7 @@
22592277
},
22602278
"validation": {
22612279
"protocolInvalid": "请选择有效协议。",
2262-
"portRange": "端口必须为 1 至 65535 之间的整数",
2280+
"portRange": "端口必须是端口号或端口列表,例如 443, 1000-2000,444",
22632281
"destinationPortRange": "目标端口必须为 0 至 65535 之间的整数。",
22642282
"realityServerNamesRequired": "REALITY 至少需要填写一个 server name。",
22652283
"realityServerNamesFormat": "REALITY 的 server names 必须为非空字符串的列表。",
@@ -2268,6 +2286,8 @@
22682286
"discardDraftTitle": "放弃新入站?",
22692287
"discardDraftDescription": "此入站尚未加入列表。关闭而不添加将丢弃更改。",
22702288
"discardDraftAction": "放弃",
2289+
"discardEditTitle": "放弃更改?",
2290+
"discardEditDescription": "如果现在关闭,对此入站的修改将会丢失。",
22712291
"finishCurrentTitle": "请先完成当前入站",
22722292
"finishCurrentDescription": "请先加入列表,或关闭对话框并丢弃草稿,再开始另一个入站。"
22732293
},
@@ -2284,6 +2304,8 @@
22842304
"discardDraftTitle": "放弃新出站?",
22852305
"discardDraftDescription": "此出站尚未加入列表。关闭而不添加将丢弃更改。",
22862306
"discardDraftAction": "放弃",
2307+
"discardEditTitle": "放弃更改?",
2308+
"discardEditDescription": "如果现在关闭,对此出站的修改将会丢失。",
22872309
"finishCurrentTitle": "请先完成当前出站",
22882310
"finishCurrentDescription": "请先加入列表,或关闭对话框并丢弃草稿,再开始另一个出站。",
22892311
"freedom": {
@@ -2359,6 +2381,12 @@
23592381
"discardDraftAction": "放弃",
23602382
"finishCurrentTitle": "请先完成当前规则",
23612383
"finishCurrentDescription": "请先加入列表,或关闭对话框并丢弃草稿,再开始另一条规则。",
2384+
"validation": {
2385+
"requiresOutboundOrBalancer": "请设置出站标签或负载均衡器标签,让规则知道流量应发送到哪里。",
2386+
"unknownOutboundTag": "此配置中未定义出站标签“{{tag}}”。",
2387+
"unknownBalancerTag": "routing.balancers 中未定义负载均衡器标签“{{tag}}”。",
2388+
"portRange": "端口必须是端口号或端口列表,例如 443, 1000-2000,444。"
2389+
},
23622390
"sectionRoutingAction": "路由动作",
23632391
"routingActionHint": "为匹配的流量选择一个目标。当两者都设置时,outboundTag 优先于 balancerTag。",
23642392
"sectionMatchConditions": "匹配条件",

0 commit comments

Comments
 (0)