mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-30 18:52:12 +08:00
* feat(contract): export wire contract from backend and generate frontend types Adds a zero-dependency `frontend-contract` bin that serializes the real NoticeStatus variants and FrontendEvent payloads, scripts/gen-contract.mjs which emits the committed src/services/contract.ts, and a CI job that regenerates it and fails on a non-empty diff. events.ts now derives its event map from the generated contract instead of hand-typed shapes. * feat(events): route all backend events through a single event bus and store Adds src/services/bus (the only listen/emit site: one handler per contract event plus the frontend-internal test-all event) and the React context/reducer app store. Migrates the five scattered subscriptions (layout events, pending failures, proxy refresh, profile update/timer, test-all), deletes the old glue (events.ts, use-listen, use-layout-events, LoadingCacheProvider), moves run state into the store, and adds an architecture gate script wired into CI. Behavior is unchanged; the run-state query's poll/focus safety net is preserved by the store provider. * refactor(notice): make the notice table exhaustive and drop dead wire entries D5 cleanup, frontend and backend in one commit: removes the six config_validate::* statuses that never receive a backend send and the set_config::ok send (enum variants, golden list 41→34, send point in restart_clash_core), their frontend handlers, and the five i18n keys only those handlers used. The notice table is now typed as a Record over the generated NoticeStatus union, so a status without a frontend entry fails to compile. The info status (sent by the silent updater for breaking change notices, previously dropped with a console warning) now shows an info toast — the one deliberate behavior delta. * feat(mutate): single funnel for user-intent commands and invoke gate Adds src/services/mutate.ts: one path for optimistic apply, services-layer invoke, Busy handling, failure rollback, and the error toast, with busy bookkeeping mirrored into the app store. The patch hooks (verge, clash, profiles) now route through it. Moves the remaining direct invokes (unlock ×3, DNS ×4) into cmds.ts and turns on the invoke-only-in-services architecture gate in CI. * refactor(settings): route settings-domain commands through the mutate funnel Ports port saving, webdav/local backup operations, core change/restart/ upgrade, service install/uninstall/repair flows, the system-proxy toggle queue, the DNS override toggle, and app lifecycle commands onto the single funnel. Bespoke flows keep their own error handling via errorNotice:false; simple flows gain the funnel's default error toast and revalidation. * refactor(profiles): route profile operations through the mutate funnel Ports profile create/import/reorder/delete/update/patch/save-file and enhance calls onto the funnel; retry and editor flows keep their own error handling with errorNotice:false. Per-uid ids keep the update worker pool concurrent under the funnel's in-flight dedupe. * refactor(proxies): route proxy/home/misc commands through the mutate funnel Ports mode switching (page and home card), chain runtime updates, node selection with tray sync, selection recording, provider updates and syncs, and lightweight-mode entry onto the funnel; every site keeps its existing optimistic/revert and error-handling behavior. * docs: add frontend architecture guardrails for src Layering rules for the contract flow: generated contract as the only wire-typing source, event bus as the only listen/emit site, pure-reducer store for event-derived state, the mutate funnel for user intent, and invoke only in the services layer — each backed by the CI gates. * fix(events): close run-state race and restore single error toasts Self-review findings: the bus now re-reads the run-state snapshot in onSubscribed so an event racing the store's initial read cannot leave a stale snapshot (the ordering the old layout listener guaranteed), and the patch hooks pass errorNotice:false so GuardState/page handlers remain the only error toast, matching the pre-migration behavior. * fix(frontend): preserve queued intents and fresh runtime snapshots * refactor(frontend): trim unused mutation and busy state APIs * docs(frontend): focus guardrails on architecture ownership
140 lines
5.3 KiB
JSON
140 lines
5.3 KiB
JSON
{
|
|
"actions": {
|
|
"cancel": "لغو",
|
|
"close": "بستن",
|
|
"confirm": "تأیید",
|
|
"save": "ذخیره",
|
|
"delete": "حذف",
|
|
"edit": "ویرایش",
|
|
"new": "جدید",
|
|
"enable": "فعال کردن",
|
|
"upgrade": "ارتقاء",
|
|
"restart": "راهاندازی مجدد",
|
|
"resetToDefault": "بازنشانی به پیشفرض",
|
|
"refresh": "بازنشانی",
|
|
"retry": "Retry",
|
|
"refreshPage": "Refresh Page",
|
|
"showDetails": "Show Details",
|
|
"hideDetails": "Hide Details",
|
|
"listView": "نمای لیستی",
|
|
"tableView": "نمای جدولی",
|
|
"pause": "توقف",
|
|
"resume": "از سرگیری",
|
|
"closeAll": "بستن همه",
|
|
"clear": "پاک کردن",
|
|
"previous": "Previous",
|
|
"next": "Next",
|
|
"check": "بررسی"
|
|
},
|
|
"labels": {
|
|
"updateAt": "بهروزرسانی در",
|
|
"timeout": "Timeout",
|
|
"icon": "آیکون",
|
|
"name": "نام",
|
|
"readOnly": "فقط خواندنی",
|
|
"expireTime": "زمان انقضا",
|
|
"updateTime": "زمان بهروزرسانی",
|
|
"usedTotal": "استفادهشده / کل",
|
|
"from": "از",
|
|
"password": "رمز عبور",
|
|
"retryAttempts": "Retry attempts",
|
|
"downloaded": "دانلود شده",
|
|
"uploaded": "بارگذاری شده"
|
|
},
|
|
"statuses": {
|
|
"enabled": "توانایی فعال شد",
|
|
"disabled": "غیرفعال شد",
|
|
"saving": "Saving...",
|
|
"empty": "خالی خالی",
|
|
"loading": "در حال بارگذاری..."
|
|
},
|
|
"units": {
|
|
"milliseconds": "میلیثانیه",
|
|
"seconds": "ثانیهها",
|
|
"minutes": "دقیقه",
|
|
"hours": "ساعت",
|
|
"kilobytes": "KB",
|
|
"files": "Files"
|
|
},
|
|
"placeholders": {
|
|
"resetInput": "پاک کردن فیلد ورودی",
|
|
"filter": "شرایط فیلتر",
|
|
"matchCase": "تطبیق حروف کوچک و بزرگ",
|
|
"matchWholeWord": "تطبیق کل کلمه",
|
|
"useRegex": "استفاده از عبارت منظم"
|
|
},
|
|
"validation": {
|
|
"invalidRegex": "Invalid regular expression"
|
|
},
|
|
"window": {
|
|
"maximize": "بزرگنمایی",
|
|
"minimize": "کوچکنمایی"
|
|
},
|
|
"editorModes": {
|
|
"visualization": "تجسم",
|
|
"advanced": "پیشرفته"
|
|
},
|
|
"feedback": {
|
|
"errors": {
|
|
"unexpected": "مشکلی پیش آمد",
|
|
"label": "خطا",
|
|
"unknown": "خطای نامشخص",
|
|
"details": "جزئیات خطا",
|
|
"stack": "پشته خطا",
|
|
"componentStack": "پشته مؤلفه",
|
|
"trafficUnavailable": "دادههای ترافیک در دسترس نیست",
|
|
"operationFailed": "عملیات ناموفق بود",
|
|
"trafficStats": "Traffic Statistics Error",
|
|
"trafficStatsDescription": "The traffic statistics component encountered an error and has been disabled to prevent crashes."
|
|
},
|
|
"notices": {
|
|
"raw": "{{message}}",
|
|
"prefixedRaw": "{{prefix}} {{message}}"
|
|
},
|
|
"notifications": {
|
|
"importSuccess": "پروفایل با موفقیت وارد شد",
|
|
"importSubscriptionSuccess": "وارد کردن اشتراک با موفقیت انجام شد",
|
|
"importWithClashProxy": "Profile Imported with Clash proxy",
|
|
"updateAvailable": "Update Available",
|
|
"saved": "Saved successfully",
|
|
"common": {
|
|
"copySuccess": "کپی با موفقیت انجام شد",
|
|
"saveSuccess": "Configuration saved successfully",
|
|
"saveFailed": "Failed to save configuration",
|
|
"refreshFailed": "بهروزرسانی ناموفق بود"
|
|
}
|
|
},
|
|
"validation": {
|
|
"config": {
|
|
"failed": "اعتبارسنجی پیکربندی اشتراک ناموفق بود، فایل پیکربندی را بررسی کنید، تغییرات برگشت داده شد، جزئیات خطا:",
|
|
"bootFailed": "اعتبارسنجی پیکربندی هنگام راهاندازی ناموفق بود، پیکربندی پیشفرض استفاده شد، فایل پیکربندی را بررسی کنید، جزئیات خطا:",
|
|
"processTerminated": "فرآیند اعتبارسنجی متوقف شد. بررسی کنید که آیا نرمافزار امنیتی مانع اجرای هسته شده است یا پردازنده و محیط اجرای رایانه از برنامه هسته پشتیبانی میکنند."
|
|
},
|
|
"script": {
|
|
"syntaxError": "خطای نحوی اسکریپت، تغییرات برگشت داده شد",
|
|
"missingMain": "خطای اسکریپت، تغییرات برگشت داده شد",
|
|
"fileNotFound": "فایل یافت نشد، تغییرات برگشت داده شد",
|
|
"fileError": "خطای فایل اسکریپت، تغییرات برگشت داده شد"
|
|
},
|
|
"yaml": {
|
|
"syntaxError": "YAML syntax error, changes reverted",
|
|
"readError": "YAML read error, changes reverted",
|
|
"mappingError": "YAML mapping error, changes reverted"
|
|
},
|
|
"merge": {
|
|
"syntaxError": "Merge file syntax error, changes reverted",
|
|
"mappingError": "Merge file mapping error, changes reverted"
|
|
}
|
|
}
|
|
},
|
|
"filters": {
|
|
"logLevels": {
|
|
"all": "ALL",
|
|
"debug": "DEBUG",
|
|
"info": "INFO",
|
|
"warn": "WARN",
|
|
"error": "ERROR"
|
|
}
|
|
}
|
|
}
|