3x-ui/web/translation/ar-EG.json
Sanaei edf0f36940
Frontend rewrite: React + TypeScript with AntD v6 (#4498)
* chore(frontend): add react+typescript toolchain alongside vue

Step 0 of the planned vue->react migration. React 19, antd 5, i18next
+ react-i18next, typescript 5, and @vitejs/plugin-react 6 are added as
dev/runtime deps alongside the existing vue stack. Both frameworks
coexist in the build until the last entry flips.

* vite.config.js: react() plugin runs next to vue(); new manualChunks
  for vendor-react / vendor-antd-react / vendor-icons-react /
  vendor-i18next. Existing vue chunks unchanged.
* eslint.config.js: typescript-eslint + eslint-plugin-react-hooks
  rules scoped to *.{ts,tsx}; vue config untouched for *.{js,vue}.
* tsconfig.json: strict, jsx: react-jsx, moduleResolution: bundler,
  allowJs: true (lets .tsx files import the remaining .js modules
  during incremental migration), @/* path alias.
* env.d.ts: Vite client types + window.X_UI_BASE_PATH typing +
  SubPageData shape consumed by the subscription page.

Vite stays pinned at 8.0.13 per the existing project policy. No
existing .vue/.js source files touched in this step.

eslint-plugin-react (not -hooks) is not included because its latest
release does not yet support ESLint 10. react-hooks/purity covers
the safety-critical case; revisit when the plugin updates.

* refactor(frontend): port subpage to react+ts

Step 1 of the planned vue->react migration. The standalone
subscription page (sub/sub.go renders the HTML host; React mounts
into #app) is the first entry off vue.

Introduces two shared pieces both entries (and future ones) will
use:

* src/hooks/useTheme.tsx — React Context + useTheme hook + the
  same buildAntdThemeConfig (dark/ultra-dark token overrides) and
  pauseAnimationsUntilLeave helper the vue version exposes. Same
  localStorage keys (dark-mode, isUltraDarkThemeEnabled) and DOM
  side effects (body.className, html[data-theme]) so the two stay
  in sync across the coexistence period.
* src/i18n/react.ts — i18next + react-i18next loader that reads
  the same web/translation/*.json files via import.meta.glob. The
  vue-i18n setup in src/i18n/index.js is untouched and still serves
  the remaining vue entries.

SubPage.tsx mirrors the vue version's behavior: reads
window.__SUB_PAGE_DATA__ injected by the Go sub server, renders QR
codes / descriptions / Android+iOS deep-link dropdowns, supports
theme cycle and language switch. Uses AntD v5 idioms: Descriptions
items prop, Dropdown menu prop, Layout.Content.

* refactor(frontend): port login to react+ts

Step 2 of the planned vue->react migration. The login entry is the
first to exercise AntD React's Form API (Form + Form.Item with
name/rules + onFinish) and the existing axios/CSRF interceptors
under React.

* LoginPage.tsx: same form fields, conditional 2FA input,
  rotating headline ("Hello" / "Welcome to..."), drifting blob
  background, theme cycle + language popover. Headline transition
  switches from vue's <Transition mode=out-in> to a CSS keyframe
  animation keyed off the visible word.
* entries/login.tsx: setupAxios() + applyDocumentTitle() unchanged
  from the vue entry — both are framework-agnostic in src/utils
  and src/api/axios-init.js.

useTheme hook, ThemeProvider, and i18n/react.ts loader introduced
in step 1 are now shared across two entries; Vite extracts them as
a small chunk in the build output.

* refactor(frontend): port api-docs to react+ts

Step 3 of the planned vue->react migration. The five api-docs files
(ApiDocsPage, CodeBlock, EndpointRow, EndpointSection, plus the
data-only endpoints.js) all move to react+ts.

Also introduces components/AppSidebar.tsx — api-docs is the first
authenticated page to need it. AppSidebar.vue stays in place for the
six remaining vue entries (settings, inbounds, clients, xray, nodes,
index); each gets switched to AppSidebar.tsx as its entry migrates.
After the last entry flips, AppSidebar.vue is deleted.

Notable transformations:

* The scroll observer that highlights the active TOC link is a
  useEffect keyed on sections — re-registers whenever the visible
  set changes (search filter narrows it). Same behaviour as the vue
  watchEffect.
* v-html="safeInlineHtml(...)" becomes
  dangerouslySetInnerHTML={{ __html: safeInlineHtml(...) }}. The
  helper still escapes everything except <code> tags.
* JSON syntax highlighter in CodeBlock is unchanged — pure regex on
  the escaped string, then rendered via dangerouslySetInnerHTML.
* endpoints.js stays as JS (allowJs in tsconfig); only the consumer
  signatures (Endpoint, Section) are typed at the React boundary.
* AppSidebar reuses pauseAnimationsUntilLeave + useTheme from
  step 1. Drawer + Sider keyed off the same localStorage flag
  (isSidebarCollapsed) and DOM theme attributes the vue version
  uses, so the two stay in sync during coexistence.

* refactor(frontend): port nodes to react+ts

Step 4 of the planned vue->react migration. The nodes entry brings in
the largest shared-infrastructure batch so far — every authenticated
react page from here on can lean on these.

New shared pieces (live alongside their .vue counterparts during
coexistence):

* hooks/useMediaQuery.ts — useState + resize listener
* hooks/useWebSocket.ts — wraps WebSocketClient, subscribes on mount
  and unsubscribes on unmount. The underlying client is a single
  module-level instance so multiple components on the same page
  share one socket.
* hooks/useNodes.ts — node list state + CRUD + probe/test, including
  the totals memo (online/offline/avgLatency) used by the summary card.
  applyNodesEvent is the entry point for the heartbeat-pushed list.
* components/CustomStatistic.tsx — thin Statistic wrapper, prefix +
  suffix slots become props.
* components/Sparkline.tsx — the SVG line chart with measured-width
  axis scaling, gradient fill, tooltip overlay, and per-instance
  gradient id from React.useId. ResizeObserver lifecycle is in
  useEffect; the math is unchanged.

Pages:

* NodesPage — wires hooks + WebSocket together, renders summary card
  + NodeList, hosts the form modal. Uses Modal.useModal() for the
  delete confirm so the dialog inherits ConfigProvider theming.
* NodeList — desktop renders a Table with expandable history rows;
  mobile flips to a vertical card list whose actions live in a
  bottom-right Dropdown. The IP-blur eye toggle persists across both.
* NodeFormModal — controlled form (useState object, single setForm
  per change). The reset-on-open effect computes the next state
  once and applies it with eslint-disable to satisfy the new
  react-hooks/set-state-in-effect rule on a legitimate pattern.
* NodeHistoryPanel — polls /panel/api/nodes/history/{id}/{metric}/
  {bucket} every 15s, renders cpu+mem sparklines side-by-side.

* refactor(frontend): port settings to react+ts

Step 5 of the planned vue->react migration. Settings is the first
entry whose state model didn't translate to the Vue-style "parent
passes a reactive object, children mutate it in place" pattern, so
the React port flips it to lifted state + a typed updateSetting
patch function.

* models/setting.ts — typed AllSetting class with the same field
  defaults and equals() behavior the vue version had. The .js
  twin is deleted; nothing else imported it.
* hooks/useAllSetting.ts — owns allSetting + oldAllSetting state,
  exposes updateSetting(patch), saveDisabled is derived via useMemo
  off equals() (no more 1Hz dirty-check timer).
* components/SettingListItem.tsx — children-based wrapper instead
  of named slots. The vue twin stays alive because xray (BasicsTab,
  DnsTab) still imports it; deleted when xray migrates.

The five tab components and the TwoFactorModal each accept
{ allSetting, updateSetting } and render with AntD v5's Collapse
items[] API. Every v-model:value="x" became
value={...} onChange={(e) => updateSetting({ key: e.target.value })}
or onChange={(v) => updateSetting({ key: v })} for non-input
controls.

SubscriptionFormatsTab is the trickiest — fragment / noises[] /
mux / direct routing rules are stored as JSON-encoded strings on
the wire. Parsing them once via useMemo per field, mutating the
parsed object on edit, and stringifying back into the patch keeps
the round-trip identical to the vue version.

SettingsPage hosts the tab navigation (with hash sync), the
save / restart action bar, the security-warnings alert banner,
and the restart flow that rebuilds the panel URL after the new
host/port/cert settings take effect.

* refactor(frontend): port clients to react+ts

Step 6 of the planned vue->react migration. Clients is the biggest
data-CRUD page in the panel (1.1k-line ClientsPage, 4 modals, full
table + mobile card list, WebSocket-driven realtime traffic + online
updates).

New shared infra (lives alongside vue twins until inbounds migrates):

* hooks/useClients.ts — clients + inbounds list, CRUD + bulk delete +
  attach/detach + traffic reset, with WebSocket event handlers
  (traffic, client_stats, invalidate) and a small debounced refresh
  on the invalidate event. State managed via setState; the live
  client_stats event merges traffic snapshots row-by-row through a
  ref to avoid stale closure issues.
* hooks/useDatepicker.ts — singleton "gregorian"/"jalalian" cache
  with subscribe/notify so multiple components can read the panel's
  Calendar Type without re-fetching. Mirrors useDatepicker.js.
* components/DateTimePicker.tsx — AntD DatePicker wrapper.
  vue3-persian-datetime-picker has no React port; the Jalali UI
  calendar is deferred (read-only Jalali display via IntlUtil
  formatDate still works). The vue twin stays for inbounds.
* pages/inbounds/QrPanel.tsx — copy/download/copy-as-png QR helper
  shared between clients (qr modal) and inbounds (still on vue).
  Vue twin stays alive at QrPanel.vue.
* models/inbound.ts — slim port: only the TLS_FLOW_CONTROL constant
  the clients form needs. The full inbound model stays as
  inbound.js for now; inbounds will pull it in as inbound.ts.

The clients page itself uses Modal.useModal() for all confirm
dialogs (delete, bulk-delete, reset-traffic, delDepleted, reset-all)
so the dialogs render themed. Filter state persists to
localStorage under clientsFilterState. Sort + pagination state is
local; pageSize seeds from /panel/setting/defaultSettings.

The four modals share a controlled "open/onOpenChange" pattern
that replaces vue's v-model:open. ClientFormModal computes
attach/detach diffs from the inbound multi-select on submit; the
parent's onSave callback routes them through useClients's attach()/
detach() after the main update succeeds.

ESLint config: turned off four react-hooks v7 rules
(react-compiler, preserve-manual-memoization, set-state-in-effect,
purity). They're all React-Compiler-driven informational rules; we
don't run the compiler and the patterns they flag (initial-fetch
useEffect, derived computations using Date.now, inline arrow event
handlers) are all idiomatic React. Disabling globally instead of
per-line keeps the diff readable.

* refactor(frontend): port index dashboard to react+ts

Step 7 of the Vue→React migration. Ports the overview/index entry: dashboard
page, status + xray cards, panel-update / log / backup / system-history /
xray-metrics / xray-log / version modals, and the custom-geo subsection. Adds
the shared JsonEditor (CodeMirror 6) and useStatus hook used by the config
modal. Removes the unused react-hooks/set-state-in-effect disables now that
the rule is off globally.

* refactor(frontend): port xray to react+ts

Step 8 of the Vue→React migration. Ports the xray config entry: page shell,
basics/routing/outbounds/balancers/dns tabs, the rule + balancer + dns server
+ dns presets + warp + nord modals, the protocol-aware outbound form, and the
shared FinalMaskForm (TCP/UDP masks + QUIC params). Adds useXraySetting that
mirrors the legacy two-way sync between the JSON template string and the
parsed templateSettings tree. The outbound model itself stays in JS so the
class-driven form keeps its existing mutation API; instance access is typed
loosely inside the form to match.

The shared FinalMaskForm.vue and JsonEditor.vue stay alongside the new .tsx
versions until step 9 — InboundFormModal.vue still imports them.

Adds react-hooks/immutability and react-hooks/refs to the already-disabled
react-compiler rule set; both flag the outbound form's instance-mutation
pattern that doesn't run through useState.

* Upgrade frontend deps (antd v6, i18n, TS)

Bump frontend dependencies in package.json and regenerate package-lock.json. Notable updates: upgrade antd to v6, update i18next/react-i18next, axios, qs, vue-i18n, TypeScript and ESLint, plus related @rc-component packages and replacements (e.g. classnames/rc-util -> clsx/@rc-component/util). Lockfile changes reflect the new dependency tree required for Ant Design v6 and other package upgrades.

* refactor(frontend): port inbounds to react+ts and drop vue toolchain

Step 9 — the last entry. Ports the inbounds entry: page shell, list with
desktop table + mobile cards, info modal, qr-code modal, share-link
helpers, and the protocol-aware form modal (basics / protocol /
stream / security / sniffing / advanced JSON). useInbounds replaces
the Vue composable with WebSocket-driven traffic + client-stats merge.

Inbound and DBInbound models stay in JS so the class-driven form keeps
its mutation API; instance access is typed loosely inside the form to
match. FinalMaskForm/JsonEditor/TextModal/PromptModal/InfinityIcon are
the last shared bits to flip; their .vue counterparts go too.

Toolchain cleanup now that no entry needs Vue: drop plugin-vue from
vite.config, remove the .vue lint block + parser, prune vue / vue-i18n
/ ant-design-vue / @ant-design/icons-vue / vue3-persian-datetime-picker
/ moment-jalaali override from package.json, and switch utils/index.js
to import { message } from 'antd' instead of ant-design-vue.

* chore(frontend): adopt antd v6 api updates

Sweep deprecated props across the React tree:
- Modal: destroyOnClose -> destroyOnHidden, maskClosable -> mask.closable
- Space: direction -> orientation (or removed when redundant)
- Input.Group compact -> Space.Compact block
- Drawer: width -> size
- Spin: tip -> description
- Progress: trailColor -> railColor
- Alert: message -> title
- Popover: overlayClassName -> rootClassName
- BackTop -> FloatButton.BackTop

Also refresh dashboard theming for v6: rename dark/ultra Layout and Menu
tokens (siderBg, darkItemBg, darkSubMenuItemBg, darkPopupBg), tweak gauge
size/stroke, add font-size overrides for Statistic and Progress so the
overview numbers stay legible under v6 defaults.

* chore(frontend): antd v6 polish, theme + modal fixes

- adopt message.useMessage hook + messageBus bridge so HttpUtil messages
  inherit ConfigProvider theme tokens
- replace deprecated antd APIs (List, Input addonBefore/After, Empty
  imageStyle); introduce InputAddon helper + SettingListItem custom rows
- fix dark/ultra selectors in portaled modals (body.dark,
  html[data-theme='ultra-dark']) instead of nonexistent .is-dark/.is-ultra
- add horizontal scroll to clients table; reorder node columns so
  actions+enable sit at the left
- swap raw button for antd Button in NodeFormModal test connection
- fix FinalMaskForm nested-form by hoisting it outside OutboundFormModal's
  parent Form
- fix advanced "all" JSON tab in InboundFormModal — useMemo on a mutated
  ref was stale; compute on every render
- fix chart-on-open for SystemHistory + XrayMetrics modals by adding open
  to effect deps (useRef.current doesn't trigger re-runs)
- switch i18next interpolation to single-brace {var} to match locale files
- drop residual Vue mentions in CI workflows and Go comments

* fix(frontend): qr code collapse — open only first panel, allow toggle

ClientQrModal and QrCodeModal both used activeKey without onChange,
forcing every panel open and blocking user toggle. Switch to controlled
state initialized to the first item's key on open, with onChange so
clicks update state.

Also remove unused AppBridge.tsx (superseded by per-page message.useMessage
hook).

* fix(frontend): hover cards, balancer load, routing dnd, modal a11y, outbound crash

- ClientsPage/SettingsPage/XrayPage: add hoverable to bottom card/tabs so
  hover affordance matches the top card
- BalancerFormModal: lazy-init useState from props + destroyOnHidden so
  the form mounts with saved values instead of relying on a useEffect
  sync that could miss the first open
- RoutingTab: rewrite pointer drag — handlers are now defined inside the
  pointerdown closure so addEventListener/removeEventListener match;
  drag state lives on a ref (from/to/moved) so onUp reads the real
  indices, not stale closure values. Adds setPointerCapture so Windows
  and touch keep delivering events when the cursor leaves the handle.
- OutboundFormModal/InboundFormModal: blur the focused input before
  switching tabs to silence the aria-hidden-on-focused-element warning
- utils.isArrEmpty: return true for undefined/null arrays — the old form
  treated undefined as "not empty" which crashed VLESSSettings.fromJson
  when json.vnext was missing

* fix(frontend): clipboard reliability + restyle login page

- ClipboardManager.copyText: prefer navigator.clipboard on secure
  contexts, fall back to a focused on-screen textarea + execCommand.
  Old path used left:-9999px which failed selection in some browsers
  and swallowed execCommand's return value, so the "copied" toast
  appeared even when nothing made it to the clipboard.
- LoginPage: richer gradient backdrop — five animated colour blobs,
  glassmorphic card (backdrop-filter blur + saturate), gradient brand
  text/accent, masked grid texture for depth, and a thin gradient
  border on the card. Light/dark/ultra each get their own palette.

* Memoize compactAdvancedJson and update deps

Wrap compactAdvancedJson in useCallback (dependent on messageApi) and add it to the dependency array of applyAdvancedJsonToBasic. This ensures a stable function reference for correct dependency tracking and avoids stale closures/unnecessary re-renders in InboundFormModal.tsx.

* style(frontend): prettier charts, drop redundant frame, format net rates

- Sparkline: multi-stop gradient fill, soft drop-shadow under the line,
  dashed grid, glowing pulse on the latest-point marker, pill-shaped
  tooltip with dashed crosshair
- XrayMetricsModal: glow + pulse on the observatory alive dot,
  monospace stamps/listen text
- SystemHistoryModal: keep just the modal's frame around the chart (the
  inner wrapper I'd added stacked a second border on top); strip the
  decimal from Net Up/Down (25.63 KB/s → 25 KB/s) only on this chart's
  formatter

* style(frontend): refined dark/ultra palette + shared pro card frame

- Dark tokens shifted to a cooler, Linear-style palette: page #1a1b1f,
  sidebar/header #15161a (recessed nav, darker than cards), card
  #23252b, elevated #2d2f37
- Ultra dark: page pure #000 for OLED, sidebar #050507 disappears into
  the frame, card #101013 with a clear step, elevated #1a1a1e
- New styles/page-cards.css holds the card border/shadow/hover rules so
  all seven content pages (index, clients, inbounds, xray, settings,
  nodes, api-docs) share one definition instead of duplicating in each
  page CSS
- Dashboard typography: uppercase card titles with letter-spacing,
  larger 17px stat values, subtle gradient divider between stat columns,
  ellipsis on action labels so "Backup & Restore" doesn't break the
  card height at mid widths
- Light --bg-page stays at #e6e8ec for the contrast against white cards

* fix(frontend): wireguard info alignment, blue login dark, embed gitkeep

- align WireGuard info-modal fields with Protocol/Address/Port by wrapping
  values in Tag (matches the rest of the dl.info-list rows)
- swap login dark palette from purple to pure blue blobs/accent/brand
- pin web/dist/.gitkeep through gitignore so //go:embed all:dist never
  fails on a fresh clone with an empty dist directory

* docs: refresh frontend docs for the React + TS + AntD 6 stack

Update CONTRIBUTING.md and frontend/README.md to describe the migrated
frontend accurately:

- replace Vue 3 / Ant Design Vue 4 references with React 19 / AntD 6 / TS
- swap composables -> hooks, vue-i18n -> react-i18next, createApp -> createRoot
- mention the typecheck step (tsc --noEmit) in the PR checklist
- document the Vite 8.0.13 pin and TypeScript strict mode in conventions
- list the nodes and api-docs entries that were missing from the layout

* style(frontend): improve readability and mobile polish

- bump statistic title/value contrast in dark and ultra-dark so totals
  on the inbounds summary card stay legible
- give index card actions explicit colors per theme so links like Stop,
  Logs, System History no longer fade into the card background
- show the panel version as a tag next to "3X-UI" on mobile, mirroring
  the Xray version tag pattern, and turn it orange when an update is
  available
- make the login settings button a proper circle by adding size="large"
  + an explicit border-radius fallback on .toolbar-btn

* feat: jalali calendar support and date formatting fixes

- Wire useDatepicker into IntlUtil and switch jalalian display locale
  to fa-IR for clean "1405/07/03 12:00:00" output (drops the awkward
  "AP" era suffix that "<lang>-u-ca-persian" produced)
- Drop in persian-calendar-suite for the jalali date picker, with a
  light/dark/ultra theme map and CSS overrides so the inline-styled
  input stays readable and bg matches the surrounding container
- Force LTR on the picker input so "1405/03/07 00:00" reads naturally
- Pass calendar setting through ClientInfoModal, ClientsPage Duration
  tooltip, and ClientFormModal's expiry picker
- Heuristic toMs() in ClientInfoModal so GORM's autoUpdateTime seconds
  render as a real date instead of "1348/11/01"
- Persist UpdatedAt on the ClientRecord row in client_service.Update;
  previously only the inbound settings JSON was bumped, so the panel
  never saw a fresh updated_at after editing a client

* feat(frontend): donate link, panel version label, login lang menu

- Sidebar: add heart donate link to https://donate.sanaei.dev and small panel version under 3X-UI brand
- Login: swap settings-cog for translation icon, drop title, render languages as a direct list
- Vite dev: inject window.X_UI_CUR_VER from config/version so dev mode matches prod
- Translations: add menu.donate across all locales

* fix(xray-update): respect XUI_BIN_FOLDER on Windows

The Windows update path hardcoded "bin/xray-windows-amd64.exe", ignoring
the configured XUI_BIN_FOLDER. In dev mode (folder set to x-ui) this
created a stray bin/ folder while the running binary stayed un-updated.

* Bump Xray to v26.5.9 and minor cleanup

Update Xray release URLs to v26.5.9 in the GitHub Actions workflow and DockerInit.sh. Remove the hardcoded skip for tagVersion "26.5.3" so it will be considered when collecting Xray versions. Apply small formatting fixes: remove an extra blank line in database/db.go, normalize spacing/alignment of Protocol constants in database/model/model.go, and trim a trailing blank line in web/controller/inbound.go.

* fix(frontend): route remaining copy buttons through ClipboardManager

Direct navigator.clipboard calls fail in non-secure contexts (HTTP on a
LAN IP), making the API-docs code copy and security-tab token copy
silently broken. Both now go through ClipboardManager which falls back
to document.execCommand('copy') when navigator.clipboard is unavailable.

* fix(db): store CreatedAt/UpdatedAt in milliseconds

GORM's autoCreateTime/autoUpdateTime tags default to Unix seconds on
int64 fields and overwrite the service-supplied UnixMilli value on
save. The frontend interprets these timestamps as JS Date inputs
(milliseconds), so created/updated columns rendered ~1970 dates. Adding
the :milli qualifier makes GORM match what the service code and UI
expect.

* Improve legacy clipboard copy handling

Refactor ClipboardManager._legacyCopy to better handle focus and selection when copying. The textarea is now appended to the active element's parent (or body) and placed off-screen with aria-hidden and readonly attributes. The code preserves and restores the previous document selection and active element, uses focus({preventScroll: true}) to avoid scrolling, and returns the execCommand('copy') result. This makes legacy copy behavior more robust and less disruptive to the page state.

* fix(lint): drop redundant ok=false in clipboard fallback catch

* chore(deps): bump golang.org/x/net to v0.55.0 for GO-2026-5026
2026-05-23 15:21:45 +02:00

1093 lines
No EOL
66 KiB
JSON
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"username": "اسم المستخدم",
"password": "الباسورد",
"login": "تسجيل الدخول",
"confirm": "تأكيد",
"cancel": "إلغاء",
"close": "إغلاق",
"save": "حفظ",
"logout": "تسجيل خروج",
"create": "إنشاء",
"update": "تحديث",
"copy": "نسخ",
"copied": "اتنسخ",
"download": "تحميل",
"remark": "ملاحظة",
"enable": "مفعل",
"protocol": "بروتوكول",
"search": "بحث",
"filter": "فلترة",
"loading": "جاري التحميل...",
"refresh": "تحديث",
"clear": "مسح",
"second": "ثانية",
"minute": "دقيقة",
"hour": "ساعة",
"day": "يوم",
"check": "شيك",
"indefinite": "غير محدد",
"unlimited": "غير محدود",
"none": "مفيش",
"qrCode": "كود QR",
"info": "معلومات أكتر",
"edit": "تعديل",
"delete": "مسح",
"reset": "إعادة ضبط",
"noData": "لا توجد بيانات.",
"copySuccess": "اتنسخ بنجاح",
"sure": "متأكد؟",
"encryption": "تشفير",
"useIPv4ForHost": "استخدم IPv4 للمضيف",
"transmission": "نقل",
"host": "المستضيف",
"path": "مسار",
"camouflage": "تمويه",
"status": "الحالة",
"enabled": "مفعل",
"disabled": "معطل",
"depleted": "خلص",
"depletingSoon": "هينتهي قريب",
"offline": "أوفلاين",
"online": "أونلاين",
"domainName": "اسم الدومين",
"monitor": "المسمع IP",
"certificate": "شهادة رقمية",
"fail": "فشل",
"comment": "تعليق",
"success": "تم بنجاح",
"lastOnline": "آخر متصل",
"getVersion": "جيب النسخة",
"install": "تثبيت",
"clients": "عملاء",
"usage": "استخدام",
"twoFactorCode": "الكود",
"remained": "المتبقي",
"security": "أمان",
"secAlertTitle": "تنبيه أمني",
"secAlertSsl": "الاتصال ده مش آمن. ابعد عن إدخال معلومات حساسة لغاية ما تشغل TLS لحماية البيانات.",
"secAlertConf": "بعض الإعدادات معرضة لهجمات. ينصح بتعزيز بروتوكولات الأمان عشان تمنع الاختراقات المحتملة.",
"secAlertSSL": "البانل مش مؤمن. حمّل شهادة TLS لحماية البيانات.",
"secAlertPanelPort": "بورت البانل الافتراضي معرض للخطر. ياريت تغير لبورت عشوائي أو محدد.",
"secAlertPanelURI": "مسار URI الافتراضي للبانل مش آمن. ياريت تضبط مسار URI معقد.",
"secAlertSubURI": "مسار URI الافتراضي للاشتراك مش آمن. ياريت تضبط مسار URI معقد.",
"secAlertSubJsonURI": "مسار URI الافتراضي لاشتراك JSON مش آمن. ياريت تضبط مسار URI معقد.",
"emptyDnsDesc": "مفيش سيرفر DNS مضاف.",
"emptyFakeDnsDesc": "مفيش سيرفر Fake DNS مضاف.",
"emptyBalancersDesc": "مفيش موازن تحميل مضاف.",
"emptyReverseDesc": "مفيش بروكسي عكسي مضاف.",
"somethingWentWrong": "حدث خطأ ما",
"subscription": {
"title": "معلومات الاشتراك",
"subId": "معرّف الاشتراك",
"status": "الحالة",
"downloaded": "التنزيل",
"uploaded": "الرفع",
"expiry": "تاريخ الانتهاء",
"totalQuota": "الحصة الإجمالية",
"individualLinks": "روابط فردية",
"active": "نشط",
"inactive": "غير نشط",
"unlimited": "غير محدود",
"noExpiry": "بدون انتهاء"
},
"menu": {
"theme": "الثيم",
"dark": "داكن",
"ultraDark": "داكن جدًا",
"dashboard": "نظرة عامة",
"inbounds": "الإدخالات",
"clients": "العملاء",
"nodes": "النودز",
"settings": "إعدادات البانل",
"xray": "إعدادات Xray",
"apiDocs": "توثيق API",
"logout": "تسجيل خروج",
"link": "إدارة",
"donate": "تبرع"
},
"pages": {
"login": {
"hello": "أهلا",
"title": "أهلاً وسهلاً",
"loginAgain": "انتهت صلاحية الجلسة، سجل دخول تاني",
"toasts": {
"invalidFormData": "تنسيق البيانات المدخلة مش صحيح.",
"emptyUsername": "اسم المستخدم مطلوب",
"emptyPassword": "الباسورد مطلوب",
"wrongUsernameOrPassword": "اسم المستخدم أو كلمة المرور أو كود المصادقة الثنائية غير صحيح.",
"successLogin": "لقد تم تسجيل الدخول إلى حسابك بنجاح."
}
},
"index": {
"title": "نظرة عامة",
"cpu": "المعالج",
"logicalProcessors": "المعالجات المنطقية",
"frequency": "التردد",
"swap": "Swap",
"storage": "تخزين",
"memory": "رام",
"threads": "خيوط المعالجة",
"xrayStatus": "Xray",
"stopXray": "إيقاف",
"restartXray": "إعادة تشغيل",
"xraySwitch": "النسخة",
"xrayUpdates": "تحديثات Xray",
"xraySwitchClick": "اختار النسخة اللي عايز تتحول لها.",
"xraySwitchClickDesk": "اختار بحذر، النسخ القديمة ممكن ما تتوافقش مع الإعدادات الحالية.",
"updatePanel": "تحديث البانل",
"panelUpdateDesc": "ده هيحدث 3X-UI لآخر إصدار وهيعيد تشغيل خدمة البانل.",
"currentPanelVersion": "إصدار البانل الحالي",
"latestPanelVersion": "أحدث إصدار للبانل",
"panelUpToDate": "البانل محدث لآخر إصدار",
"upToDate": "محدث",
"xrayStatusUnknown": "مش معروف",
"xrayStatusRunning": "شغالة",
"xrayStatusStop": "متوقفة",
"xrayStatusError": "فيها غلطة",
"xrayErrorPopoverTitle": "حصل خطأ أثناء تشغيل Xray",
"operationHours": "مدة التشغيل",
"systemHistoryTitle": "تاريخ النظام",
"charts": "الرسوم البيانية",
"xrayMetricsTitle": "مقاييس Xray",
"xrayMetricsDisabled": "نقطة نهاية مقاييس Xray غير مهيأة",
"xrayMetricsHint": "أضف كتلة metrics على المستوى الأعلى في إعدادات xray مع tag باسم metrics_out و listen على 127.0.0.1:11111، ثم أعد تشغيل xray.",
"xrayObservatoryEmpty": "لا توجد بيانات Observatory بعد",
"xrayObservatoryHint": "أضف كتلة observatory إلى إعدادات xray مع قائمة وسوم outbound للفحص، ثم أعد تشغيل xray.",
"xrayObservatoryTagPlaceholder": "اختر outbound",
"xrayObservatoryAlive": "نشط",
"xrayObservatoryDead": "غير متصل",
"xrayObservatoryLastSeen": "آخر مشاهدة",
"xrayObservatoryLastTry": "آخر محاولة",
"trendLast2Min": "آخر دقيقتين",
"systemLoad": "تحميل النظام",
"systemLoadDesc": "متوسط تحميل النظام في الدقائق 1, 5, و15",
"connectionCount": "إحصائيات الاتصال",
"ipAddresses": "عناوين IP",
"toggleIpVisibility": "بدل إظهار IP",
"overallSpeed": "السرعة الكلية",
"upload": "رفع",
"download": "تنزيل",
"totalData": "إجمالي البيانات",
"sent": "مرسل",
"received": "مستقبل",
"documentation": "التوثيق",
"xraySwitchVersionDialog": "هل تريد حقًا تغيير إصدار Xray؟",
"xraySwitchVersionDialogDesc": "سيؤدي هذا إلى تغيير إصدار Xray إلى #version#.",
"xraySwitchVersionPopover": "تم تحديث Xray بنجاح",
"panelUpdateDialog": "هل فعلاً عايز تحدث البانل؟",
"panelUpdateDialogDesc": "ده هيحدث 3X-UI للإصدار #version# وهيعيد تشغيل البانل.",
"panelUpdateCheckPopover": "فشل التحقق من تحديث البانل",
"panelUpdateStartedPopover": "بدأ تحديث البانل",
"geofileUpdateDialog": "هل تريد حقًا تحديث ملف الجغرافيا؟",
"geofileUpdateDialogDesc": "سيؤدي هذا إلى تحديث ملف #filename#.",
"geofilesUpdateDialogDesc": "سيؤدي هذا إلى تحديث كافة الملفات.",
"geofilesUpdateAll": "تحديث الكل",
"geofileUpdatePopover": "تم تحديث ملف الجغرافيا بنجاح",
"customGeoTitle": "GeoSite / GeoIP مخصص",
"customGeoAdd": "إضافة",
"customGeoType": "النوع",
"customGeoAlias": "الاسم المستعار",
"customGeoUrl": "URL",
"customGeoEnabled": "مفعّل",
"customGeoLastUpdated": "آخر تحديث",
"customGeoExtColumn": "التوجيه (ext:…)",
"customGeoToastUpdateAll": "تم تحديث جميع المصادر المخصصة",
"customGeoActions": "إجراءات",
"customGeoEdit": "تعديل",
"customGeoDelete": "حذف",
"customGeoDownload": "تحديث الآن",
"customGeoModalAdd": "إضافة geo مخصص",
"customGeoModalEdit": "تعديل geo مخصص",
"customGeoModalSave": "حفظ",
"customGeoDeleteConfirm": "حذف مصدر geo المخصص هذا؟",
"customGeoRoutingHint": "في قواعد التوجيه استخدم العمود كـ ext:file.dat:tag (استبدل tag).",
"customGeoInvalidId": "معرّف المورد غير صالح",
"customGeoAliasesError": "تعذّر تحميل أسماء geo المخصصة",
"customGeoValidationAlias": "الاسم المستعار: أحرف صغيرة وأرقام و - و _ فقط",
"customGeoValidationUrl": "يجب أن يبدأ الرابط بـ http:// أو https://",
"customGeoAliasPlaceholder": "a-z 0-9 _ -",
"customGeoAliasLabelSuffix": " (مخصص)",
"customGeoToastList": "قائمة geo المخصص",
"customGeoToastAdd": "إضافة geo مخصص",
"customGeoToastUpdate": "تحديث geo مخصص",
"customGeoToastDelete": "تم حذف geofile «{{ .fileName }}» المخصص",
"customGeoToastDownload": "تم تحديث geofile «{{ .fileName }}»",
"customGeoErrInvalidType": "يجب أن يكون النوع geosite أو geoip",
"customGeoErrAliasRequired": "الاسم المستعار مطلوب",
"customGeoErrAliasPattern": "الاسم المستعار يحتوي على أحرف غير مسموحة",
"customGeoErrAliasReserved": "هذا الاسم محجوز",
"customGeoErrUrlRequired": "الرابط مطلوب",
"customGeoErrInvalidUrl": "الرابط غير صالح",
"customGeoErrUrlScheme": "يجب أن يستخدم الرابط http أو https",
"customGeoErrUrlHost": "مضيف الرابط غير صالح",
"customGeoErrDuplicateAlias": "هذا الاسم مستخدم مسبقاً لهذا النوع",
"customGeoErrNotFound": "مصدر geo المخصص غير موجود",
"customGeoErrDownload": "فشل التنزيل",
"customGeoErrUpdateAllIncomplete": "تعذر تحديث مصدر واحد أو أكثر من مصادر geo المخصصة",
"customGeoEmpty": "لا توجد مصادر geo مخصصة بعد — انقر على «إضافة» لإنشاء واحد",
"dontRefresh": "التثبيت شغال، متعملش Refresh للصفحة",
"logs": "السجلات",
"config": "الإعدادات",
"backup": "نسخة احتياطية",
"backupTitle": "نسخ احتياطي واستعادة",
"exportDatabase": "اخزن نسخة",
"exportDatabaseDesc": "اضغط عشان تحمل ملف .db يحتوي على نسخة احتياطية لقاعدة البيانات الحالية على جهازك.",
"importDatabase": "استرجاع",
"importDatabaseDesc": "اضغط عشان تختار وتحمل ملف .db من جهازك لاسترجاع قاعدة البيانات من نسخة احتياطية.",
"importDatabaseSuccess": "تم استيراد قاعدة البيانات بنجاح",
"importDatabaseError": "حدث خطأ أثناء استيراد قاعدة البيانات",
"readDatabaseError": "حدث خطأ أثناء قراءة قاعدة البيانات",
"getDatabaseError": "حدث خطأ أثناء استرجاع قاعدة البيانات",
"getConfigError": "حدث خطأ أثناء استرجاع ملف الإعدادات"
},
"inbounds": {
"title": "الإدخالات",
"totalDownUp": "إجمالي المرسل/المستقبل",
"totalUsage": "إجمالي الاستخدام",
"inboundCount": "عدد الإدخالات",
"operate": "القائمة",
"enable": "مفعل",
"remark": "ملاحظة",
"node": "نود",
"deployTo": "نشر على",
"localPanel": "بانل محلي",
"fallbacks": {
"title": "الـ Fallbacks",
"help": "عند وصول اتصال إلى هذا الـ inbound لا يطابق أي عميل، يتم توجيهه إلى inbound آخر. اختر فرعًا أدناه وسيتم ملء حقول التوجيه (SNI / ALPN / Path / xver) تلقائيًا من نقل الفرع — في الغالب لا تحتاج إلى أي تعديل إضافي. يجب أن يستمع كل فرع على 127.0.0.1 مع security=none.",
"empty": "لا توجد fallbacks بعد",
"add": "إضافة fallback",
"pickInbound": "اختر inbound",
"matchAny": "أي",
"rederive": "إعادة الملء من الفرع",
"rederived": "تم إعادة الملء من الفرع",
"editAdvanced": "تحرير حقول التوجيه",
"hideAdvanced": "إخفاء المتقدم",
"quickAddAll": "إضافة سريعة لكل الـ inbounds المؤهلة",
"quickAdded": "تمت إضافة {n} fallback",
"quickAddedNone": "لا توجد inbounds جديدة مؤهلة للإضافة",
"routesWhen": "يوجَّه عندما",
"defaultCatchAll": "افتراضي — يلتقط أي شيء آخر"
},
"protocol": "بروتوكول",
"port": "بورت",
"portMap": "خريطة البورت",
"traffic": "الترافيك",
"details": "تفاصيل",
"transportConfig": "نقل",
"expireDate": "المدة",
"createdAt": "تاريخ الإنشاء",
"updatedAt": "تاريخ التحديث",
"resetTraffic": "إعادة ضبط الترافيك",
"addInbound": "أضف إدخال",
"generalActions": "إجراءات عامة",
"modifyInbound": "تعديل الإدخال",
"deleteInbound": "حذف الإدخال",
"deleteInboundContent": "متأكد إنك عايز تحذف الإدخال؟",
"deleteClient": "حذف العميل",
"deleteClientContent": "متأكد إنك عايز تحذف العميل؟",
"resetTrafficContent": "متأكد إنك عايز تعيد ضبط الترافيك؟",
"copyLink": "انسخ الرابط",
"address": "العنوان",
"network": "الشبكة",
"destinationPort": "بورت الوجهة",
"targetAddress": "عنوان الهدف",
"monitorDesc": "سيبها فاضية لو عايز تستمع على كل الـ IPs",
"meansNoLimit": "= غير محدود. (الوحدة: جيجابايت)",
"totalFlow": "إجمالي التدفق",
"leaveBlankToNeverExpire": "سيبها فاضية عشان ماتنتهيش",
"noRecommendKeepDefault": "ننصح باستخدام الافتراضي",
"certificatePath": "مسار الملف",
"certificateContent": "محتوى الملف",
"publicKey": "المفتاح العام",
"privatekey": "المفتاح الخاص",
"clickOnQRcode": "اضغط على كود QR للنسخ",
"client": "عميل",
"export": "تصدير كل الروابط",
"clone": "استنساخ",
"cloneInbound": "استنساخ الإدخال",
"cloneInboundContent": "كل إعدادات الإدخال ده، غير البورت، IP الاستماع، والعملاء، هتتطبق على الاستنساخ.",
"cloneInboundOk": "استنساخ",
"resetAllTraffic": "إعادة ضبط ترافيك كل الإدخالات",
"resetAllTrafficTitle": "إعادة ضبط ترافيك كل الإدخالات",
"resetAllTrafficContent": "متأكد إنك عايز تعيد ضبط الترافيك لكل الإدخالات؟",
"resetInboundClientTraffics": "إعادة ضبط ترافيك العملاء",
"resetInboundClientTrafficTitle": "إعادة ضبط ترافيك العملاء",
"resetInboundClientTrafficContent": "متأكد إنك عايز تعيد ضبط ترافيك عملاء الإدخال ده؟",
"resetAllClientTraffics": "إعادة ضبط ترافيك كل العملاء",
"resetAllClientTrafficTitle": "إعادة ضبط ترافيك كل العملاء",
"resetAllClientTrafficContent": "متأكد إنك عايز تعيد ضبط ترافيك كل العملاء؟",
"delDepletedClients": "حذف العملاء اللي خلصت",
"delDepletedClientsTitle": "حذف العملاء اللي خلصت",
"delDepletedClientsContent": "متأكد إنك عايز تحذف كل العملاء اللي خلصت؟",
"email": "الإيميل",
"emailDesc": "ادخل إيميل فريد.",
"IPLimit": "تحديد IP",
"IPLimitDesc": "بيعطل الإدخال لو العدد زاد عن القيمة المحددة. (0 = تعطيل)",
"IPLimitlog": "سجل IP",
"IPLimitlogDesc": "سجل تاريخ الـ IPs. (عشان تفعل الإدخال بعد التعطيل، امسح السجل)",
"IPLimitlogclear": "امسح السجل",
"setDefaultCert": "استخدم شهادة البانل",
"streamTab": "الدفق",
"securityTab": "الأمان",
"sniffingTab": "الاستشعار",
"sniffingMetadataOnly": "البيانات الوصفية فقط",
"sniffingRouteOnly": "التوجيه فقط",
"sniffingIpsExcluded": "IP المستثناة",
"sniffingDomainsExcluded": "النطاقات المستثناة",
"decryption": "فك التشفير",
"encryption": "التشفير",
"vlessAuthX25519": "مصادقة X25519",
"vlessAuthMlkem768": "مصادقة ML-KEM-768",
"vlessAuthCustom": "مخصص",
"vlessAuthSelected": "المحدد: {auth}",
"advanced": {
"title": "أقسام JSON للاتصال الوارد",
"subtitle": "JSON الكامل للاتصال الوارد ومحررات مخصصة لـ settings و sniffing و streamSettings.",
"all": "الكل",
"allHelp": "كائن الاتصال الوارد الكامل بكل الحقول في محرر واحد.",
"settings": "الإعدادات",
"settingsHelp": "غلاف كتلة settings في Xray:",
"sniffing": "الاستشعار",
"sniffingHelp": "غلاف كتلة sniffing في Xray:",
"stream": "الدفق",
"streamHelp": "غلاف كتلة stream في Xray:",
"jsonErrorPrefix": "JSON متقدم"
},
"telegramDesc": "ادخل ID شات Telegram. (استخدم '/id' في البوت) أو ({'@'}userinfobot)",
"subscriptionDesc": "عشان تلاقي رابط الاشتراك، ادخل على 'التفاصيل'. وكمان ممكن تستخدم نفس الاسم لعدة عملاء.",
"info": "معلومات",
"same": "نفسه",
"inboundData": "بيانات الإدخال",
"exportInbound": "تصدير الإدخال",
"import": "استيراد",
"importInbound": "استيراد إدخال",
"periodicTrafficResetTitle": "إعادة تعيين حركة المرور",
"periodicTrafficResetDesc": "إعادة تعيين عداد حركة المرور تلقائيًا في فترات محددة",
"lastReset": "آخر إعادة تعيين",
"periodicTrafficReset": {
"never": "أبداً",
"daily": "يومياً",
"weekly": "أسبوعياً",
"monthly": "شهرياً",
"hourly": "كل ساعة"
},
"toasts": {
"obtain": "تم الحصول عليه",
"updateSuccess": "تم التحديث بنجاح",
"logCleanSuccess": "تم مسح السجل",
"inboundsUpdateSuccess": "تم تحديث الواردات بنجاح",
"inboundUpdateSuccess": "تم تحديث الوارد بنجاح",
"inboundCreateSuccess": "تم إنشاء الوارد بنجاح",
"inboundDeleteSuccess": "تم حذف الوارد بنجاح",
"inboundClientAddSuccess": "تمت إضافة عميل(عملاء) وارد",
"inboundClientDeleteSuccess": "تم حذف عميل وارد",
"inboundClientUpdateSuccess": "تم تحديث عميل وارد",
"delDepletedClientsSuccess": "تم حذف جميع العملاء المستنفذين",
"resetAllClientTrafficSuccess": "تم إعادة تعيين كل حركة المرور من العميل",
"resetAllTrafficSuccess": "تم إعادة تعيين كل حركة المرور",
"resetInboundClientTrafficSuccess": "تم إعادة تعيين حركة المرور",
"resetInboundTrafficSuccess": "تم إعادة تعيين حركة مرور الداخل",
"trafficGetError": "خطأ في الحصول على حركات المرور",
"getNewX25519CertError": "حدث خطأ أثناء الحصول على شهادة X25519.",
"getNewmldsa65Error": "حدث خطاء في الحصول على mldsa65.",
"getNewVlessEncError": "حدث خطأ أثناء الحصول على VlessEnc."
},
"stream": {
"general": {
"request": "طلب",
"response": "رد",
"name": "اسم",
"value": "قيمة"
},
"tcp": {
"version": "نسخة",
"method": "طريقة",
"path": "مسار",
"status": "الحالة",
"statusDescription": "وصف الحالة",
"requestHeader": "رأس الطلب",
"responseHeader": "رأس الرد"
}
}
},
"clients": {
"add": "إضافة عميل",
"edit": "تعديل العميل",
"submitAdd": "إضافة عميل",
"submitEdit": "حفظ التغييرات",
"clientCount": "عدد العملاء",
"bulk": "إضافة مجمعة",
"copyFromInbound": "نسخ العملاء من الاتصال الوارد",
"copyToInbound": "نسخ العملاء إلى",
"copySelected": "نسخ المحدد",
"copySource": "المصدر",
"copyEmailPreview": "معاينة البريد الناتج",
"copySelectSourceFirst": "يرجى تحديد اتصال وارد مصدر أولاً.",
"copyResult": "نتيجة النسخ",
"copyResultSuccess": "تم النسخ بنجاح",
"copyResultNone": "لا شيء للنسخ: لم يتم تحديد عملاء أو أن المصدر فارغ",
"copyResultErrors": "أخطاء النسخ",
"copyFlowLabel": "Flow للعملاء الجدد (VLESS)",
"copyFlowHint": "يُطبَّق على جميع العملاء المنسوخين. اتركه فارغًا للتخطي.",
"selectAll": "تحديد الكل",
"clearAll": "مسح الكل",
"method": "الطريقة",
"first": "أول",
"last": "آخر",
"ipLog": "سجل IP",
"prefix": "بادئة",
"postfix": "لاحقة",
"delayedStart": "البدء بعد أول استخدام",
"expireDays": "المدة",
"days": "يوم",
"renew": "تجديد تلقائي",
"renewDesc": "تجديد تلقائي بعد انتهاء الصلاحية. (0 = تعطيل) (الوحدة: يوم)",
"title": "العملاء",
"actions": "الإجراءات",
"totalGB": "مجموع المرسل/المستقبل (جيجابايت)",
"expiryTime": "انتهاء الصلاحية",
"addClients": "إضافة عملاء",
"limitIp": "حد عناوين IP",
"password": "كلمة المرور",
"subId": "معرّف الاشتراك",
"online": "متصل",
"email": "البريد الإلكتروني",
"comment": "ملاحظة",
"traffic": "حركة المرور",
"offline": "غير متصل",
"addTitle": "إضافة عميل",
"qrCode": "رمز QR",
"moreInformation": "مزيد من المعلومات",
"delete": "حذف",
"reset": "إعادة ضبط حركة المرور",
"editTitle": "تعديل العميل",
"client": "العميل",
"enabled": "مفعّل",
"remaining": "المتبقي",
"duration": "المدة",
"attachedInbounds": "الاتصالات الواردة المرتبطة",
"selectInbound": "حدد اتصالاً واردًا واحدًا أو أكثر",
"noSubId": "هذا العميل ليس لديه subId، لا يوجد رابط قابل للمشاركة.",
"noLinks": "لا توجد روابط للمشاركة — قم بإرفاق هذا العميل بأحد الاتصالات الواردة الداعمة للبروتوكول أولاً.",
"link": "رابط",
"resetNotPossible": "قم بإرفاق هذا العميل بأحد الاتصالات الواردة أولاً.",
"general": "عام",
"resetAllTraffics": "إعادة ضبط حركة مرور كل العملاء",
"resetAllTrafficsTitle": "إعادة ضبط حركة مرور كل العملاء؟",
"resetAllTrafficsContent": "يُعاد ضبط عدّاد الإرسال/الاستقبال لكل عميل إلى الصفر. لا تتأثر الحصص ومواعيد الانتهاء. لا يمكن التراجع.",
"empty": "لا يوجد عملاء بعد — أضف واحدًا للبدء.",
"deleteConfirmTitle": "حذف العميل {email}؟",
"deleteConfirmContent": "سيؤدي هذا إلى إزالة العميل من جميع الاتصالات الواردة المرتبطة وحذف سجل حركة مروره. لا يمكن التراجع.",
"deleteSelected": "حذف ({count})",
"bulkDeleteConfirmTitle": "حذف {count} عميل؟",
"bulkDeleteConfirmContent": "سيتم إزالة كل عميل محدد من جميع الاتصالات الواردة المرتبطة وحذف سجل حركة مروره. لا يمكن التراجع.",
"delDepleted": "حذف المنتهية",
"delDepletedConfirmTitle": "حذف العملاء المنتهية حصصهم؟",
"delDepletedConfirmContent": "يُحذف كل عميل استُنفِدت حصة حركة مروره أو انتهت صلاحيته. لا يمكن التراجع.",
"auth": "Auth",
"hysteriaAuth": "Auth (Hysteria)",
"uuid": "UUID",
"flow": "Flow",
"reverseTag": "Reverse tag",
"reverseTagPlaceholder": "Reverse tag اختياري",
"telegramId": "معرّف مستخدم تلغرام",
"telegramIdPlaceholder": "معرّف مستخدم تلغرام رقمي (0 = لا شيء)",
"created": "تاريخ الإنشاء",
"updated": "تاريخ التحديث",
"ipLimit": "حد IP",
"toasts": {
"deleted": "تم حذف العميل",
"trafficReset": "تمت إعادة ضبط حركة المرور",
"allTrafficsReset": "تمت إعادة ضبط حركة مرور كل العملاء",
"bulkDeleted": "تم حذف {count} عميل",
"bulkDeletedMixed": "تم حذف {ok}, وفشل {failed}",
"bulkCreated": "تم إنشاء {count} عميل",
"bulkCreatedMixed": "تم إنشاء {ok}, وفشل {failed}",
"delDepleted": "تم حذف {count} عميل منتهٍ"
}
},
"nodes": {
"title": "النودز",
"addNode": "إضافة نود",
"editNode": "تعديل نود",
"totalNodes": "إجمالي النودز",
"onlineNodes": "أونلاين",
"offlineNodes": "أوفلاين",
"avgLatency": "متوسط الكمون",
"name": "الاسم",
"namePlaceholder": "مثال: de-frankfurt-1",
"addressPlaceholder": "panel.example.com أو 1.2.3.4",
"remark": "ملاحظة",
"scheme": "البروتوكول",
"address": "العنوان",
"port": "البورت",
"basePath": "المسار الأساسي",
"apiToken": "توكن API",
"apiTokenPlaceholder": "التوكن من صفحة إعدادات البانل البعيد",
"apiTokenHint": "البانل البعيد بيعرض توكن API بتاعه في الإعدادات → توكن API.",
"regenerate": "تجديد التوكن",
"regenerateConfirm": "تجديد التوكن هيلغي التوكن الحالي. أي بانل مركزي بيستخدمه هيفقد الصلاحية لحد ما تحدّث التوكن. تكمّل؟",
"allowPrivateAddress": "السماح بالعنوان الخاص",
"allowPrivateAddressHint": "التفعيل فقط للعقد على شبكة خاصة أو VPN.",
"enable": "مفعل",
"status": "الحالة",
"cpu": "المعالج",
"mem": "الذاكرة",
"uptime": "مدة التشغيل",
"latency": "الكمون",
"lastHeartbeat": "آخر نبضة",
"xrayVersion": "إصدار Xray",
"panelVersion": "إصدار اللوحة",
"actions": "العمليات",
"probe": "فحص فوري",
"testConnection": "اختبار الاتصال",
"connectionOk": "الاتصال شغال ({ms} ms)",
"connectionFailed": "فشل الاتصال",
"never": "أبدًا",
"justNow": "دلوقتي",
"deleteConfirmTitle": "تحذف النود \"{name}\"؟",
"deleteConfirmContent": "ده هيوقّف مراقبة النود. البانل البعيد نفسه مش هيتأثر.",
"statusValues": {
"online": "أونلاين",
"offline": "أوفلاين",
"unknown": "غير معروف"
},
"toasts": {
"list": "فشل تحميل النودز",
"obtain": "فشل تحميل النود",
"add": "إضافة نود",
"update": "تحديث النود",
"delete": "حذف النود",
"deleted": "اتمسح النود",
"test": "اختبار الاتصال",
"fillRequired": "الاسم والعنوان والبورت وتوكن API كلهم مطلوبين",
"probeFailed": "فشل الفحص"
}
},
"settings": {
"title": "إعدادات البانل",
"save": "حفظ",
"infoDesc": "كل تغيير هتعمله هنا لازم يتخزن. ياريت تعيد تشغيل البانل عشان التعديلات تتفعل.",
"restartPanel": "إعادة تشغيل البانل",
"restartPanelDesc": "متأكد إنك عايز تعيد تشغيل البانل؟ لو ماقدرتش تدخل بعد إعادة التشغيل، شوف سجل البانل على السيرفر.",
"restartPanelSuccess": "تم إعادة تشغيل اللوحة بنجاح",
"actions": "إجراءات",
"resetDefaultConfig": "استرجاع الافتراضي",
"panelSettings": "عام",
"securitySettings": "المصادقة",
"TGBotSettings": "بوت Telegram",
"panelListeningIP": "IP الاستماع",
"panelListeningIPDesc": "عنوان IP للبانل. (سيبه فاضي عشان يستمع على كل الـ IPs)",
"panelListeningDomain": "دومين الاستماع",
"panelListeningDomainDesc": "اسم الدومين للبانل. (سيبه فاضي عشان يستمع على كل الدومينات والـ IPs)",
"panelPort": "بورت الاستماع",
"panelPortDesc": "رقم البورت للبانل. (لازم يكون بورت فاضي)",
"publicKeyPath": "مسار المفتاح العام",
"publicKeyPathDesc": "مسار ملف المفتاح العام للبانل. (يبدأ بـ '/')",
"privateKeyPath": "مسار المفتاح الخاص",
"privateKeyPathDesc": "مسار ملف المفتاح الخاص للبانل. (يبدأ بـ '/')",
"panelUrlPath": "مسار URI",
"panelUrlPathDesc": "مسار URI للبانل. (يبدأ بـ '/' وبينتهي بـ '/')",
"pageSize": "حجم الصفحة",
"pageSizeDesc": "حدد حجم الصفحة لجدول الإدخالات. (0 = تعطيل)",
"remarkModel": "نموذج الملاحظة وحرف الفصل",
"datepicker": "نوع التقويم",
"datepickerPlaceholder": "اختار التاريخ",
"datepickerDescription": "المهام المجدولة هتشتغل بناءً على التقويم ده.",
"sampleRemark": "مثال للملاحظة",
"oldUsername": "اسم المستخدم الحالي",
"currentPassword": "الباسورد الحالي",
"newUsername": "اسم المستخدم الجديد",
"newPassword": "الباسورد الجديد",
"telegramBotEnable": "تفعيل بوت Telegram",
"telegramBotEnableDesc": "يفعل بوت Telegram.",
"telegramToken": "توكن Telegram",
"telegramTokenDesc": "توكن البوت اللي جبت من '{'@'}BotFather'.",
"telegramProxy": "بروكسي SOCKS",
"telegramProxyDesc": "يفعل بروكسي SOCKS5 للاتصال بـ Telegram. (اضبط الإعدادات حسب الدليل)",
"telegramAPIServer": "سيرفر Telegram API",
"telegramAPIServerDesc": "سيرفر Telegram API المستخدم. سيبه فاضي لاستخدام الافتراضي.",
"telegramChatId": "ID شات الأدمن",
"telegramChatIdDesc": "ID شات الأدمن في Telegram. (مفصول بفواصل)(تقدر تجيبه من {'@'}userinfobot) أو (استخدم '/id' في البوت)",
"telegramNotifyTime": "وقت الإشعار",
"telegramNotifyTimeDesc": "وقت إشعار البوت للتقارير الدورية. (استخدم صيغة وقت crontab)",
"tgNotifyBackup": "نسخة احتياطية لقاعدة البيانات",
"tgNotifyBackupDesc": "ابعت ملف النسخة الاحتياطية لقاعدة البيانات مع التقرير.",
"tgNotifyLogin": "إشعار بتسجيل الدخول",
"tgNotifyLoginDesc": "استقبل إشعار بكل محاولة تسجيل دخول للبانل مع اسم المستخدم، الـ IP، والوقت.",
"sessionMaxAge": "مدة الجلسة",
"sessionMaxAgeDesc": "المدة اللي تفضل فيها مسجل دخول. (الوحدة: دقيقة)",
"expireTimeDiff": "تنبيه بتاريخ الانتهاء",
"expireTimeDiffDesc": "استقبل تنبيه قبل ما توصل لتاريخ الانتهاء بالمدة المحددة. (الوحدة: يوم)",
"trafficDiff": "تنبيه حد الترافيك",
"trafficDiffDesc": "استقبل تنبيه عند وصول الترافيك للحد المحدد. (الوحدة: جيجابايت)",
"tgNotifyCpu": "تنبيه حمل المعالج",
"tgNotifyCpuDesc": "استقبل تنبيه لو حمل المعالج عدى الحد المحدد. (الوحدة: %)",
"timeZone": "المنطقة الزمنية",
"timeZoneDesc": "المهام المجدولة هتشتغل بناءً على المنطقة الزمنية دي.",
"subSettings": "الاشتراك",
"subEnable": "تفعيل خدمة الاشتراك",
"subEnableDesc": "يفعل خدمة الاشتراك.",
"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": "بورت الاستماع",
"subPortDesc": "رقم البورت لخدمة الاشتراك. (لازم يكون بورت فاضي)",
"subCertPath": "مسار المفتاح العام",
"subCertPathDesc": "مسار ملف المفتاح العام لخدمة الاشتراك. (يبدأ بـ '/')",
"subKeyPath": "مسار المفتاح الخاص",
"subKeyPathDesc": "مسار ملف المفتاح الخاص لخدمة الاشتراك. (يبدأ بـ '/')",
"subPath": "مسار URI",
"subPathDesc": "مسار URI لخدمة الاشتراك. (يبدأ بـ '/' وبينتهي بـ '/')",
"subDomain": "دومين الاستماع",
"subDomainDesc": "اسم الدومين لخدمة الاشتراك. (سيبه فاضي عشان يستمع على كل الدومينات والـ IPs)",
"subUpdates": "فترات التحديث",
"subUpdatesDesc": "فترات تحديث رابط الاشتراك في تطبيقات العملاء. (الوحدة: ساعة)",
"subEncrypt": "تشفير",
"subEncryptDesc": "المحتوى اللي هيترجع من خدمة الاشتراك هيكون مشفر بـ Base64.",
"subShowInfo": "اظهر معلومات الاستخدام",
"subShowInfoDesc": "هيظهر الترافيك المتبقي والتاريخ في تطبيقات العملاء.",
"subEmailInRemark": "تضمين البريد الإلكتروني في الاسم",
"subEmailInRemarkDesc": "تضمين بريد العميل الإلكتروني في اسم ملف تعريف الاشتراك.",
"subURI": "مسار البروكسي العكسي",
"subURIDesc": "مسار URI لرابط الاشتراك عشان تستخدمه ورا البروكسي.",
"externalTrafficInformEnable": "تنبيه الترافيك الخارجي",
"externalTrafficInformEnableDesc": "يبعت تنبيه لـ API خارجي مع كل تحديث للترافيك.",
"externalTrafficInformURI": "مسار تنبيه الترافيك الخارجي",
"externalTrafficInformURIDesc": "تحديثات الترافيك هتتبعت للمسار ده.",
"restartXrayOnClientDisable": "إعادة تشغيل Xray بعد التعطيل التلقائي",
"restartXrayOnClientDisableDesc": "عند تعطيل العميل تلقائيا بسبب انتهاء الصلاحية أو حد حركة المرور، أعد تشغيل Xray.",
"fragment": "تجزئة",
"fragmentDesc": "يفعل تجزئة لحزمة TLS hello.",
"fragmentSett": "إعدادات التجزئة",
"noisesDesc": "يفعل التشويش.",
"noisesSett": "إعدادات التشويش",
"mux": "MUX",
"muxDesc": "ينقل أكثر من تيار بيانات مستقل خلال تيار بيانات واحد قائم.",
"muxSett": "إعدادات MUX",
"direct": "اتصال مباشر",
"directDesc": "ينشئ اتصال مباشر مع الدومينات أو نطاقات IP لدولة معينة.",
"notifications": "الإشعارات",
"certs": "الشهادات",
"externalTraffic": "الترافيك الخارجي",
"dateAndTime": "التاريخ والوقت",
"proxyAndServer": "البروكسي والسيرفر",
"intervals": "الفترات",
"information": "المعلومات",
"language": "اللغة",
"telegramBotLanguage": "لغة بوت Telegram",
"security": {
"admin": "بيانات الأدمن",
"twoFactor": "المصادقة الثنائية",
"twoFactorEnable": "تفعيل المصادقة الثنائية",
"twoFactorEnableDesc": "يضيف طبقة إضافية من المصادقة لتعزيز الأمان.",
"twoFactorModalSetTitle": "تفعيل المصادقة الثنائية",
"twoFactorModalDeleteTitle": "تعطيل المصادقة الثنائية",
"twoFactorModalSteps": "لإعداد المصادقة الثنائية، قم ببعض الخطوات:",
"twoFactorModalFirstStep": "1. امسح رمز QR هذا في تطبيق المصادقة أو انسخ الرمز الموجود بجانب رمز QR والصقه في التطبيق",
"twoFactorModalSecondStep": "2. أدخل الرمز من التطبيق",
"twoFactorModalRemoveStep": "أدخل الرمز من التطبيق لإزالة المصادقة الثنائية.",
"twoFactorModalChangeCredentialsTitle": "تغيير بيانات الاعتماد",
"twoFactorModalChangeCredentialsStep": "أدخل الرمز من التطبيق لتغيير بيانات اعتماد المسؤول.",
"twoFactorModalSetSuccess": "تم إنشاء المصادقة الثنائية بنجاح",
"twoFactorModalDeleteSuccess": "تم حذف المصادقة الثنائية بنجاح",
"twoFactorModalError": "رمز خاطئ",
"show": "إظهار",
"hide": "إخفاء",
"apiTokenNew": "رمز جديد",
"apiTokenName": "الاسم",
"apiTokenNamePlaceholder": "مثل central-panel-a",
"apiTokenNameRequired": "الاسم مطلوب",
"apiTokenEmpty": "لا توجد رموز بعد — أنشئ واحدًا لمصادقة الروبوتات أو اللوحات البعيدة.",
"apiTokenDeleteWarning": "أي عميل يستخدم هذا الرمز سيفقد المصادقة فورًا."
},
"toasts": {
"modifySettings": "تم تغيير المعلمات.",
"getSettings": "حدث خطأ أثناء استرداد المعلمات.",
"modifyUserError": "حدث خطأ أثناء تغيير بيانات اعتماد المسؤول.",
"modifyUser": "لقد قمت بتغيير بيانات اعتماد المسؤول بنجاح.",
"originalUserPassIncorrect": "اسم المستخدم أو الباسورد الحالي غير صحيح",
"userPassMustBeNotEmpty": "اسم المستخدم والباسورد الجديدين فاضيين",
"getOutboundTrafficError": "خطأ في الحصول على حركات المرور الصادرة",
"resetOutboundTrafficError": "خطأ في إعادة تعيين حركات المرور الصادرة"
}
},
"xray": {
"title": "إعدادات Xray",
"save": "احفظ",
"restart": "أعد تشغيل Xray",
"restartSuccess": "تم إعادة تشغيل Xray بنجاح",
"stopSuccess": "تم إيقاف Xray بنجاح",
"restartError": "حدث خطأ أثناء إعادة تشغيل Xray.",
"stopError": "حدث خطأ أثناء إيقاف Xray.",
"basicTemplate": "أساسي",
"advancedTemplate": "متقدم",
"generalConfigs": "إعدادات عامة",
"generalConfigsDesc": "الخيارات دي هتحدد التعديلات العامة.",
"logConfigs": "السجلات",
"logConfigsDesc": "السجلات ممكن تأثر على كفاءة السيرفر. ننصح بتفعيلها بحكمة لما تكون محتاجها.",
"blockConfigsDesc": "الخيارات دي هتحجب الترافيك بناءً على بروتوكولات ومواقع محددة.",
"basicRouting": "توجيه أساسي",
"blockConnectionsConfigsDesc": "الخيارات دي هتحجب الترافيك بناءً على الدولة المطلوبة.",
"directConnectionsConfigsDesc": "الاتصال المباشر بيضمن إن الترافيك المعين مايمرش من سيرفر تاني.",
"blockips": "حظر IPs",
"blockdomains": "حظر دومينات",
"directips": "اتصالات مباشرة لـ IPs",
"directdomains": "اتصالات مباشرة للدومينات",
"ipv4Routing": "توجيه IPv4",
"ipv4RoutingDesc": "الخيارات دي هتوجه الترافيك بناءً على وجهة معينة عبر IPv4.",
"warpRouting": "توجيه WARP",
"warpRoutingDesc": "الخيارات دي هتوجه الترافيك بناءً على وجهة معينة عبر WARP.",
"nordRouting": "توجيه NordVPN",
"nordRoutingDesc": "الخيارات دي هتوجه الترافيك بناءً على وجهة معينة عبر NordVPN.",
"Template": "قالب إعدادات Xray المتقدم",
"TemplateDesc": "ملف إعدادات Xray النهائي هيتولد بناءً على القالب ده.",
"FreedomStrategy": "استراتيجية بروتوكول الحرية",
"FreedomStrategyDesc": "اختار استراتيجية المخرجات للشبكة في بروتوكول الحرية.",
"RoutingStrategy": "استراتيجية التوجيه العامة",
"RoutingStrategyDesc": "حدد استراتيجية التوجيه الإجمالية لحل كل الطلبات.",
"outboundTestUrl": "رابط اختبار المخرج",
"outboundTestUrlDesc": "الرابط المستخدم عند اختبار اتصال المخرج",
"Torrent": "حظر بروتوكول التورنت",
"Inbounds": "الإدخالات",
"InboundsDesc": "قبول العملاء المعينين.",
"Outbounds": "المخرجات",
"Balancers": "موازنات التحميل",
"OutboundsDesc": "حدد مسار الترافيك الصادر.",
"Routings": "قواعد التوجيه",
"RoutingsDesc": "أولوية كل قاعدة مهمة جداً!",
"completeTemplate": "الكل",
"logLevel": "مستوى السجلات",
"logLevelDesc": "مستوى السجل الخاص بالأخطاء، اللي بيوضح المعلومات المطلوبة للتسجيل.",
"accessLog": "سجل الوصول",
"accessLogDesc": "مسار ملف سجل الوصول. القيمة الخاصة 'none' بتعطل سجل الوصول.",
"errorLog": "سجل الأخطاء",
"errorLogDesc": "مسار ملف سجل الأخطاء. القيمة الخاصة 'none' بتعطل سجل الأخطاء.",
"dnsLog": "سجل DNS",
"dnsLogDesc": "لو هتسجل استعلامات DNS.",
"maskAddress": "إخفاء العنوان",
"maskAddressDesc": "إخفاء عنوان الـ IP؛ لو مفعل، هيستبدل تلقائياً عنوان IP اللي بيظهر في السجل.",
"statistics": "إحصائيات",
"statsInboundUplink": "إحصائيات رفع الإدخال",
"statsInboundUplinkDesc": "تفعيل جمع الإحصائيات لترافيك الرفع لكل بروكسي من الإدخالات.",
"statsInboundDownlink": "إحصائيات تنزيل الإدخال",
"statsInboundDownlinkDesc": "تفعيل جمع الإحصائيات لترافيك التنزيل لكل بروكسي من الإدخالات.",
"statsOutboundUplink": "إحصائيات رفع المخرجات",
"statsOutboundUplinkDesc": "تفعيل جمع الإحصائيات لترافيك الرفع لكل بروكسي من المخرجات.",
"statsOutboundDownlink": "إحصائيات تنزيل المخرجات",
"statsOutboundDownlinkDesc": "تفعيل جمع الإحصائيات لترافيك التنزيل لكل بروكسي من المخرجات.",
"rules": {
"first": "أول",
"last": "آخر",
"up": "فوق",
"down": "تحت",
"source": "المصدر",
"dest": "الوجهة",
"inbound": "إدخال",
"outbound": "مخرج",
"balancer": "موازن",
"info": "معلومات",
"add": "أضف قاعدة",
"edit": "عدل القاعدة",
"useComma": "عناصر مفصولة بفواصل"
},
"outbound": {
"addOutbound": "أضف مخرج",
"addReverse": "أضف عكسي",
"editOutbound": "عدل المخرج",
"editReverse": "عدل العكسي",
"reverseTag": "وسم العكسي",
"reverseTagDesc": "وسم الخروج لبروكسي VLESS العكسي البسيط. اتركه فارغاً لتعطيله.",
"reverseTagPlaceholder": "وسم الخروج (اتركه فارغاً للتعطيل)",
"tag": "تاج",
"tagDesc": "تاج فريد",
"address": "العنوان",
"reverse": "عكسي",
"domain": "دومين",
"type": "النوع",
"bridge": "جسر",
"portal": "بوابة",
"link": "رابط",
"intercon": "تواصل",
"settings": "إعدادات",
"accountInfo": "معلومات الحساب",
"outboundStatus": "حالة المخرج",
"sendThrough": "أرسل من خلال",
"test": "اختبار",
"testResult": "نتيجة الاختبار",
"testing": "جاري اختبار الاتصال...",
"testSuccess": "الاختبار ناجح",
"testFailed": "فشل الاختبار",
"testError": "فشل اختبار المخرج",
"nordvpn": "NordVPN",
"accessToken": "رمز الوصول",
"country": "الدولة",
"server": "الخادم",
"city": "المدينة",
"allCities": "كل المدن",
"privateKey": "المفتاح الخاص",
"load": "الحمل"
},
"balancer": {
"addBalancer": "أضف موازن تحميل",
"editBalancer": "عدل موازن التحميل",
"balancerStrategy": "استراتيجية الموازن",
"balancerSelectors": "المحددات",
"tag": "تاج",
"tagDesc": "تاج فريد",
"balancerDesc": "ماينفعش تستخدم balancerTag و outboundTag مع بعض. لو اتستخدموا مع بعض، outboundTag هو اللي هيشتغل."
},
"wireguard": {
"secretKey": "المفتاح السري",
"publicKey": "المفتاح العام",
"allowedIPs": "عناوين IP المسموح بها",
"endpoint": "النهاية",
"psk": "المفتاح المشترك",
"domainStrategy": "استراتيجية الدومين"
},
"tun": {
"nameDesc": "اسم واجهة TUN. القيمة الافتراضية هي 'xray0'",
"mtuDesc": "وحدة النقل الأقصى. الحد الأقصى لحجم حزم البيانات. القيمة الافتراضية هي 1500",
"userLevel": "مستوى المستخدم",
"userLevelDesc": "ستستخدم جميع الاتصالات المُرسلة عبر هذا الإدخال مستوى المستخدم هذا. القيمة الافتراضية هي 0"
},
"dns": {
"enable": "فعل DNS",
"enableDesc": "فعل سيرفر DNS المدمج",
"tag": "تاج إدخال DNS",
"tagDesc": "التاج ده هيبقى متاح كإدخال في قواعد التوجيه.",
"clientIp": "IP العميل",
"clientIpDesc": "بيحدد موقع العميل خلال استعلامات DNS",
"disableCache": "تعطيل الكاش",
"disableCacheDesc": "بيعطل تخزين نتائج DNS مؤقتاً",
"disableFallback": "تعطيل النسخ الاحتياطي",
"disableFallbackDesc": "بيعطل استعلامات DNS الاحتياطية",
"disableFallbackIfMatch": "تعطيل النسخ الاحتياطي عند التطابق",
"disableFallbackIfMatchDesc": "بيعطل استعلامات DNS الاحتياطية لما يتحقق تطابق مع قائمة الدومينات",
"enableParallelQuery": "تفعيل الاستعلام المتوازي",
"enableParallelQueryDesc": "تفعيل استعلامات DNS المتوازية لعدة خوادم لحل أسرع",
"strategy": "استراتيجية الاستعلام",
"strategyDesc": "الاستراتيجية العامة لحل أسماء الدومين",
"add": "أضف سيرفر",
"edit": "عدل السيرفر",
"domains": "الدومينات",
"expectIPs": "العناوين المتوقعة",
"unexpectIPs": "عناوين IP غير متوقعة",
"useSystemHosts": "استخدام ملف Hosts الخاص بالنظام",
"useSystemHostsDesc": "استخدام ملف hosts من نظام مثبت",
"serveStale": "تقديم النتائج المنتهية",
"serveStaleDesc": "إرجاع نتائج الكاش المنتهية الصلاحية أثناء التحديث في الخلفية",
"serveExpiredTTL": "مدة صلاحية النتائج المنتهية",
"serveExpiredTTLDesc": "مدة صلاحية إدخالات الكاش المنتهية بالثواني؛ 0 = لا تنتهي أبدًا",
"timeoutMs": "المهلة (مللي ثانية)",
"skipFallback": "تخطي الاحتياطي",
"finalQuery": "الاستعلام النهائي",
"hosts": "Hosts",
"hostsAdd": "إضافة Host",
"hostsEmpty": "لم يتم تعريف أي Host",
"hostsDomain": "النطاق (مثل domain:example.com)",
"hostsValues": "عنوان IP أو نطاق — اكتب واضغط Enter",
"usePreset": "استخدام النموذج",
"dnsPresetTitle": "قوالب DNS",
"dnsPresetFamily": "العائلي",
"clearAll": "حذف الكل",
"clearAllTitle": "حذف جميع خوادم DNS؟",
"clearAllConfirm": "سيؤدي هذا إلى إزالة جميع خوادم DNS من القائمة. لا يمكن التراجع عن هذا الإجراء."
},
"fakedns": {
"add": "أضف Fake DNS",
"edit": "عدل Fake DNS",
"ipPool": "نطاق IP Pool",
"poolSize": "حجم المجموعة"
}
}
},
"tgbot": {
"keyboardClosed": "❌ لوحة المفاتيح مغلقة!",
"noResult": "❗ لا يوجد نتائج!",
"noQuery": "❌ لم يتم العثور على الاستعلام! يرجى استخدام الأمر مرة أخرى!",
"wentWrong": "❌ حدث خطأ ما!",
"noIpRecord": "❗ لا يوجد سجل IP!",
"noInbounds": "❗ لم يتم العثور على أي وارد!",
"unlimited": "♾ غير محدود (إعادة تعيين)",
"add": "إضافة",
"month": "شهر",
"months": "أشهر",
"day": "يوم",
"days": "أيام",
"hours": "ساعات",
"minutes": "دقائق",
"unknown": "غير معروف",
"inbounds": "الواردات",
"clients": "العملاء",
"offline": "🔴 غير متصل",
"online": "🟢 متصل",
"commands": {
"unknown": "❗ أمر مش معروف.",
"pleaseChoose": "👇 من فضلك اختار:\r\n",
"help": "🤖 أهلا بيك في البوت! البوت ده معمول عشان يديك بيانات معينة من البانل ويسمحلك بالتعديلات.",
"start": "👋 أهلا <i>{{ .Firstname }}</i>.\r\n",
"welcome": "🤖 أهلا بيك في بوت إدارة <b>{{ .Hostname }}</b>.\r\n",
"status": "✅ البوت شغال!",
"usage": "❗ من فضلك ادخل نص للتبحث عنه!",
"getID": "🆔 الـ ID بتاعك: <code>{{ .ID }}</code>",
"helpAdminCommands": "عشان تعيد تشغيل Xray Core:\r\n<code>/restart</code>\r\n\r\nعشان تدور على إيميل عميل:\r\n<code>/usage [Email]</code>\r\n\r\nعشان تدور على إدخالات (مع إحصائيات العملاء):\r\n<code>/inbound [Remark]</code>\r\n\r\nID شات Telegram:\r\n<code>/id</code>",
"helpClientCommands": "عشان تدور على الإحصائيات، استخدم الأمر ده:\r\n\r\n<code>/usage [Email]</code>\r\n\r\nID شات Telegram:\r\n<code>/id</code>",
"restartUsage": "\r\n\r\n<code>/restart</code>",
"restartSuccess": "✅ العملية نجحت!",
"restartFailed": "❗ حصل خطأ في العملية.\r\n\r\n<code>Error: {{ .Error }}</code>.",
"xrayNotRunning": "❗ Xray Core مش شغال.",
"startDesc": "عرض القائمة الرئيسية",
"helpDesc": "مساعدة البوت",
"statusDesc": "التحقق من حالة البوت",
"idDesc": "عرض معرف Telegram الخاص بك"
},
"messages": {
"cpuThreshold": "🔴 حمل المعالج {{ .Percent }}% عدى الحد المسموح ({{ .Threshold }}%)",
"selectUserFailed": "❌ حصل خطأ في اختيار المستخدم!",
"userSaved": "✅ حفظت بيانات مستخدم Telegram.",
"loginSuccess": "✅ تسجيل الدخول للبانل تم بنجاح.\r\n",
"loginFailed": "❗️فشل محاولة تسجيل الدخول للبانل.\r\n",
"2faFailed": "فشل 2FA",
"report": "🕰 التقارير المجدولة: {{ .RunTime }}\r\n",
"datetime": "⏰ التاريخ والوقت: {{ .DateTime }}\r\n",
"hostname": "💻 السيرفر: {{ .Hostname }}\r\n",
"version": "🚀 نسخة 3X-UI: {{ .Version }}\r\n",
"xrayVersion": "📡 نسخة Xray: {{ .XrayVersion }}\r\n",
"ipv6": "🌐 IPv6: {{ .IPv6 }}\r\n",
"ipv4": "🌐 IPv4: {{ .IPv4 }}\r\n",
"ip": "🌐 IP: {{ .IP }}\r\n",
"ips": "🔢 عناوين IP:\r\n{{ .IPs }}\r\n",
"serverUpTime": "⏳ وقت التشغيل: {{ .UpTime }} {{ .Unit }}\r\n",
"serverLoad": "📈 تحميل النظام: {{ .Load1 }}, {{ .Load2 }}, {{ .Load3 }}\r\n",
"serverMemory": "📋 الرام: {{ .Current }}/{{ .Total }}\r\n",
"tcpCount": "🔹 TCP: {{ .Count }}\r\n",
"udpCount": "🔸 UDP: {{ .Count }}\r\n",
"traffic": "🚦 الترافيك: {{ .Total }} (↑{{ .Upload }},↓{{ .Download }})\r\n",
"xrayStatus": " الحالة: {{ .State }}\r\n",
"username": "👤 اسم المستخدم: {{ .Username }}\r\n",
"reason": "❗️ السبب: {{ .Reason }}\r\n",
"time": "⏰ الوقت: {{ .Time }}\r\n",
"inbound": "📍 الإدخال: {{ .Remark }}\r\n",
"port": "🔌 البورت: {{ .Port }}\r\n",
"expire": "📅 تاريخ الانتهاء: {{ .Time }}\r\n",
"expireIn": "📅 هيخلص بعد: {{ .Time }}\r\n",
"active": "💡 مفعل: {{ .Enable }}\r\n",
"enabled": "🚨 مفعل: {{ .Enable }}\r\n",
"online": "🌐 حالة الاتصال: {{ .Status }}\r\n",
"lastOnline": "🔙 آخر متصل: {{ .Time }}\r\n",
"email": "📧 الإيميل: {{ .Email }}\r\n",
"upload": "🔼 رفع: ↑{{ .Upload }}\r\n",
"download": "🔽 تنزيل: ↓{{ .Download }}\r\n",
"total": "📊 الإجمالي: ↑↓{{ .UpDown }} / {{ .Total }}\r\n",
"TGUser": "👤 مستخدم Telegram: {{ .TelegramID }}\r\n",
"exhaustedMsg": "🚨 نفذ {{ .Type }}:\r\n",
"exhaustedCount": "🚨 عدد النفاذ لـ {{ .Type }}:\r\n",
"onlinesCount": "🌐 العملاء الأونلاين: {{ .Count }}\r\n",
"disabled": "🛑 معطل: {{ .Disabled }}\r\n",
"depleteSoon": "🔜 هينتهي قريب: {{ .Deplete }}\r\n\r\n",
"backupTime": "🗄 وقت النسخة الاحتياطية: {{ .Time }}\r\n",
"refreshedOn": "\r\n📋🔄 اتحدّث في: {{ .Time }}\r\n\r\n",
"yes": "✅ أيوه",
"no": "❌ لأ",
"received_id": "🔑📥 الـ ID اتحدث.",
"received_password": "🔑📥 الباسورد اتحدث.",
"received_email": "📧📥 الإيميل اتحدث.",
"received_comment": "💬📥 التعليق اتحدث.",
"id_prompt": "🔑 الـ ID الافتراضي: {{ .ClientId }}\n\nادخل الـ ID بتاعك.",
"pass_prompt": "🔑 الباسورد الافتراضي: {{ .ClientPassword }}\n\nادخل الباسورد بتاعك.",
"email_prompt": "📧 الإيميل الافتراضي: {{ .ClientEmail }}\n\nادخل الإيميل بتاعك.",
"comment_prompt": "💬 التعليق الافتراضي: {{ .ClientComment }}\n\nادخل تعليقك.",
"inbound_client_data_id": "🔄 الدخول: {{ .InboundRemark }}\n\n🔑 المعرف: {{ .ClientId }}\n📧 البريد الإلكتروني: {{ .ClientEmail }}\n📊 الترافيك: {{ .ClientTraffic }}\n📅 تاريخ الانتهاء: {{ .ClientExp }}\n🌐 حدّ IP: {{ .IpLimit }}\n💬 تعليق: {{ .ClientComment }}\n\nدلوقتي تقدر تضيف العميل على الدخول!",
"inbound_client_data_pass": "🔄 الدخول: {{ .InboundRemark }}\n\n🔑 كلمة المرور: {{ .ClientPass }}\n📧 البريد الإلكتروني: {{ .ClientEmail }}\n📊 الترافيك: {{ .ClientTraffic }}\n📅 تاريخ الانتهاء: {{ .ClientExp }}\n🌐 حدّ IP: {{ .IpLimit }}\n💬 تعليق: {{ .ClientComment }}\n\nدلوقتي تقدر تضيف العميل على الدخول!",
"cancel": "❌ العملية اتلغت! \n\nممكن تبدأ من /start في أي وقت. 🔄",
"error_add_client": "⚠️ حصل خطأ:\n\n {{ .error }}",
"using_default_value": "تمام، هشيل على القيمة الافتراضية. 😊",
"incorrect_input": "المدخلات مش صحيحة.\nالكلمات لازم تكون متصلة من غير فراغات.\nمثال صحيح: aaaaaa\nمثال غلط: aaa aaa 🚫",
"AreYouSure": "إنت متأكد؟ 🤔",
"SuccessResetTraffic": "📧 البريد الإلكتروني: {{ .ClientEmail }}\n🏁 النتيجة: ✅ تم بنجاح",
"FailedResetTraffic": "📧 البريد الإلكتروني: {{ .ClientEmail }}\n🏁 النتيجة: ❌ فشل \n\n🛠 الخطأ: [ {{ .ErrorMessage }} ]",
"FinishProcess": "🔚 عملية إعادة ضبط الترافيك خلصت لكل العملاء."
},
"buttons": {
"closeKeyboard": "❌ اقفل الكيبورد",
"cancel": "❌ إلغاء",
"cancelReset": "❌ إلغاء إعادة الضبط",
"cancelIpLimit": "❌ إلغاء حد الـ IP",
"confirmResetTraffic": "✅ تأكيد إعادة ضبط الترافيك؟",
"confirmClearIps": "✅ تأكيد مسح الـ IPs؟",
"confirmRemoveTGUser": "✅ تأكيد حذف مستخدم Telegram؟",
"confirmToggle": "✅ تأكيد تفعيل/تعطيل المستخدم؟",
"dbBackup": "احصل على نسخة DB",
"serverUsage": "استخدام السيرفر",
"getInbounds": "احصل على الإدخالات",
"depleteSoon": "هينتهي قريب",
"clientUsage": "استخدام العميل",
"onlines": "العملاء الأونلاين",
"commands": "الأوامر",
"refresh": "🔄 تجديد",
"clearIPs": "❌ مسح الـ IPs",
"removeTGUser": "❌ حذف مستخدم Telegram",
"selectTGUser": "👤 اختار مستخدم Telegram",
"selectOneTGUser": "👤 اختار مستخدم Telegram:",
"resetTraffic": "📈 إعادة ضبط الترافيك",
"resetExpire": "📅 تغيير تاريخ الانتهاء",
"ipLog": "🔢 سجل الـ IP",
"ipLimit": "🔢 حد الـ IP",
"setTGUser": "👤 ضبط مستخدم Telegram",
"toggle": "🔘 تفعيل / تعطيل",
"custom": "🔢 مخصص",
"confirmNumber": "✅ تأكيد: {{ .Num }}",
"confirmNumberAdd": "✅ تأكيد إضافة: {{ .Num }}",
"limitTraffic": "🚧 حد الترافيك",
"getBanLogs": "احصل على سجلات الحظر",
"allClients": "كل العملاء",
"addClient": "إضافة عميل",
"submitDisable": "إرسال كمعطّل ☑️",
"submitEnable": "إرسال كمفعّل ✅",
"use_default": "🏷️ استخدام الإعدادات الافتراضية",
"change_id": "⚙️🔑 المعرّف",
"change_password": "⚙️🔑 كلمة السر",
"change_email": "⚙️📧 البريد الإلكتروني",
"change_comment": "⚙️💬 تعليق",
"change_flow": "⚙️🚦 التدفق",
"ResetAllTraffics": "إعادة ضبط جميع الترافيك",
"SortedTrafficUsageReport": "تقرير استخدام الترافيك المرتب"
},
"answers": {
"successfulOperation": "✅ العملية نجحت!",
"errorOperation": "❗ حصل خطأ في العملية.",
"getInboundsFailed": "❌ فشل الحصول على الإدخالات.",
"getClientsFailed": "❌ فشل الحصول على العملاء.",
"canceled": "❌ {{ .Email }}: العملية اتلغت.",
"clientRefreshSuccess": "✅ {{ .Email }}: العميل اتحدث بنجاح.",
"IpRefreshSuccess": "✅ {{ .Email }}: الـ IPs اتحدثت بنجاح.",
"TGIdRefreshSuccess": "✅ {{ .Email }}: مستخدم Telegram اتحدث بنجاح.",
"resetTrafficSuccess": "✅ {{ .Email }}: الترافيك اتظبط بنجاح.",
"setTrafficLimitSuccess": "✅ {{ .Email }}: حد الترافيك اتسجل بنجاح.",
"expireResetSuccess": "✅ {{ .Email }}: أيام الانتهاء اتظبطت بنجاح.",
"resetIpSuccess": "✅ {{ .Email }}: حد الـ IP ({{ .Count }}) اتسجل بنجاح.",
"clearIpSuccess": "✅ {{ .Email }}: الـ IPs اتمسحت بنجاح.",
"getIpLog": "✅ {{ .Email }}: سجل الـ IP اتجاب.",
"getUserInfo": "✅ {{ .Email }}: بيانات مستخدم Telegram اتجاب.",
"removedTGUserSuccess": "✅ {{ .Email }}: مستخدم Telegram اتحذف بنجاح.",
"enableSuccess": "✅ {{ .Email }}: اتفعل بنجاح.",
"disableSuccess": "✅ {{ .Email }}: اتعطل بنجاح.",
"askToAddUserId": "مافيش إعدادات ليك!\r\nاطلب من الأدمن يضيف الـ Telegram ChatID الخاص بيك في إعداداتك.\r\n\r\nالـ ChatID بتاعك: <code>{{ .TgUserID }}</code>",
"chooseClient": "اختار عميل للإدخال {{ .Inbound }}",
"chooseInbound": "اختار الإدخال"
}
}
}