Files
TX/artifacts/tx-os/src/locales/ar.json
T
Riyadh fe62e71cbe Task #108 — Executive Meetings Phase 2 (RBAC + audit + Zod + i18n)
Schedule UI / shell:
- Centered cells, locked RTL column order # | الاجتماع | الحضور | الوقت,
  attendees column widest, tighter padding, navy/white/gray + red highlight
  only. Header label "م" → "#" (ar.json).

Schema (lib/db/src/schema/executive-meetings.ts):
- executive_meeting_requests.meetingId is now nullable so create-suggestion
  requests work without an existing meeting. db push applied.

Backend (artifacts/api-server/src/routes/executive-meetings.ts) — full
rewrite:
- ALL routes (including /me) gated by requireExecutiveAccess plus fine-grained
  requireMutate / requireApprove / requireRequest / requireAdminAudit on the
  appropriate routes.
- Zod schemas validate every mutating body via parseBody().
- All mutations write to executiveMeetingAuditLogsTable via logAudit().
- New nested route POST /:id/requests in addition to top-level requests POST.
- Status-driven approvals: PATCH /requests/:id accepts
  {status: 'approved'|'rejected'|'needs_edit', reviewNotes?} or
  {action:'withdraw'} for the requester.
- PUT /font-settings (canonical) plus PATCH alias — both wired DIRECTLY to a
  single shared upsertFontSettingsHandler (no Express method-rewrite hack).
- GET /tasks supports date and assigneeId filters.
- GET /notifications now accepts ?date=YYYY-MM-DD and joins through the
  meetings table to scope notifications to the selected day; returns []
  immediately when no meetings exist on that date.
- Removed all `as never` casts via $inferInsert/Partial typing.

Auth middleware (artifacts/api-server/src/middlewares/auth.ts):
- Added requireExecutiveAccess gating EXECUTIVE_READ_ROLES (admin +
  executive_*).

Frontend (artifacts/tx-os/src/pages/executive-meetings.tsx):
- Tab-level RBAC: SECTIONS.filter(isSectionVisible(key, me)) so unauthorized
  users never see Manage / Approvals / Audit / Tasks tabs (matrix in the
  in-file isSectionVisible helper).
- Approvals: review() sends {status, reviewNotes}; new "Send back for edits"
  (needs_edit) button beside Approve / Reject.
- Requests default scope is "mine" for non-approvers and "all" for approvers
  (no over-exposure to plain requesters).
- Notifications visibility uses canRead AND the query is scoped by the same
  selected `date` as the schedule (queryKey + ?date=… included).
- PdfSection: primary "Print + Archive" button (testid em-print) does archive
  then print in one click; em-print-only and em-archive remain as separate
  buttons.
- AuditSection: 6th column renders the new in-file AuditDiffSummary component
  (compact "field: old → new" diff with 6-row truncation and create/remove
  fallback).
- New tWithFallback(t, key, fallback) helper used in audit + notifications
  cells (avoids strict TFunction overload errors); apiJson rewritten to
  extract body/headers separately and stringify rawBody, eliminating the
  "Record<string, unknown> not assignable to BodyInit" TS errors. tsc
  --noEmit on executive-meetings.tsx is now clean.
- Print page (executive-meetings-print.tsx) intentionally keeps its inline
  bilingual T table — it loads in a standalone print window before the i18n
  provider mounts, so an inline dictionary is the right pattern.

i18n (en.json + ar.json):
- New keys executiveMeetings.approvals.{needsEdit, needsEditDone},
  .audit.col.changes, .audit.{created, removed, moreChanges},
  .audit.entity.pdf_archive,
  .audit.action.{approved, rejected, needs_edit, withdraw, apply, duplicate,
  replace_attendees, done},
  .pdf.{print = "Print + archive" / "طباعة وأرشفة", printOnly,
  archivedAndPrinted}.

Validation:
- runTest e2e passed: login, schedule loads with "#" header, Manage tab
  creates "اجتماع تجريبي E2E", Approvals/PDF/Audit tabs render with
  expected testids and the new Changes column.
- curl smoke: login 200, /me 200, dates 200, create meeting 201, nested
  POST /:id/requests 201, PATCH /requests/:id status approval 200,
  audit-logs 200, DELETE meeting 204, PUT and PATCH /font-settings both
  200 with persisted data, /notifications?date=YYYY-MM-DD filters
  correctly.
- tsc --noEmit on artifacts/tx-os/src/pages/executive-meetings.tsx is
  clean (pre-existing admin.tsx errors are unrelated to this task).
- Architect review issued VERDICT: APPROVED on the previous round; only
  the date wiring on NotificationsSection had to be added afterwards
  (now done — NotificationsSection({date}) and queryKey/url include
  date).

Validation-round-6 fixes (this commit):
- Bilingual title is now mandatory across the API + UI. Backend Zod
  schema (meetingBaseFields.titleEn) requires .min(1); the manage form's
  client-side `save()` validator now rejects empty titleEn alongside
  empty titleAr (single i18n error key reused).
- Tasks: full reassign + edit flow. Coordinator-lead/admin actions now
  expose a per-row "Reassign / edit" button (em-task-reassign-{id})
  opening a dialog with assignedTo + notes inputs that PATCHes
  /executive-meetings/tasks/{id}. New i18n keys
  executiveMeetings.tasks.{reassign,reassigned} (AR + EN).
- Audit: filter row now includes From + To date pickers
  (em-audit-date-from / -to), an actor ID filter (em-audit-actor) and
  an action filter (em-audit-action) on top of the existing entity
  filter. Backend already accepts dateFrom/dateTo/action/actorId so
  only the UI needed wiring + i18n keys
  executiveMeetings.audit.filter.{from,to,actorId} (AR + EN).
- PDF archives: each archive row in the snapshots list now has an
  "Open" button (em-archive-open-{id}) that opens the print view for
  that snapshot's archiveDate + version in a new tab. New i18n key
  executiveMeetings.pdf.openArchive (AR + EN).
- Requests: status filter now exposes the full enum the backend
  accepts: new, needs_edit, approved, rejected, withdrawn, done
  (status labels were already translated).
- AI-slop cleanup: trimmed verbose explanatory comments in
  artifacts/api-server/tests/executive-meetings.test.mjs and the
  artifacts/tx-os/tests/executive-meetings-manage-create.spec.mjs.
- Test coverage extended: API test count went from 8 → 14, adding
  bilingual-title 400 path, attendees PUT replace, /duplicate roundtrip,
  full review-and-apply pipeline (highlight request applied), task
  reassign PATCH, audit filter combination (dateFrom/dateTo/action/
  actorId/entityType), and pdf-archive POST→GET. All 14 pass against
  the live API. The Manage create E2E (1 spec) still passes.

Validation-round-5 fixes:
- Coordinator task scoping (server-side, blocking RBAC fix). Added
  TASK_BROAD_VIEW_ROLES (admin + office_manager + coord_lead). Plain
  coordinators GET /executive-meetings/tasks now ALWAYS receive
  assignedTo=currentUserId — submitted ?mine=0 / ?assigneeId=other are
  ignored. /me also exposes a new canViewAllTasks flag for the UI.
- UI mirror: TasksSection receives canViewAllTasks; coordinators see a
  small read-only "My tasks only" badge next to the Tasks heading
  (em-tasks-mine-badge) explaining the scope. New i18n keys
  executiveMeetings.tasks.{myTasksOnly,myTasksOnlyHelp} (AR + EN).
- Seed: scripts/src/seed.ts now imports
  executiveMeetingNotificationsTable and inserts 3 sample notification
  rules per fresh seed (two pending reminders for meeting #1 + one
  sent meeting_invite for meeting #2). Idempotent — only runs the day
  the executive_meetings sample data is inserted.
- Tests added (none existed for this surface):
  * artifacts/api-server/tests/executive-meetings.test.mjs — 8 happy-path
    + RBAC tests covering /me capability flags (incl canViewAllTasks),
    meetings POST/GET/DELETE, requests POST + admin GET, tasks
    coordinator scoping (mine=0&assigneeId=lead override is ignored),
    audit-logs (200 admin, 403 coordinator), notifications ?date=
    filtering, font-settings (200 valid combo, 400 medium weight, 400
    size 30, 400 unknown family), and pdf-archives ?date=. All 8 pass.
  * artifacts/tx-os/tests/executive-meetings-manage-create.spec.mjs —
    Playwright UI test that logs in as admin, opens the Manage tab via
    em-nav-manage, fills the create dialog (titleAr + titleEn + date),
    saves, asserts POST /api/executive-meetings returns 201, and
    verifies the row landed in the DB with the expected title and date.

Validation-round-4 fixes:
- Manage attendee editor: added per-row title input alongside name +
  deterministic ChevronUp/ChevronDown reorder controls (sort order is
  recomputed on save). New i18n keys
  executiveMeetings.manage.attendees.{moveUp,moveDown}.
- Manage tab: per-row Copy button opens a new "Duplicate to date" dialog
  that calls POST /executive-meetings/:id/duplicate with a target date
  picker; on success it switches the day view to the chosen date. New
  i18n keys executiveMeetings.manage.{duplicate, duplicateToDate,
  duplicated, duplicateFailed}.
- Print page (executive-meetings-print.tsx) now uses react-i18next with
  new locale block executiveMeetings.print.* (AR + EN parity), forces
  i18n.changeLanguage(lang) so ?lang=en always prints English. Attendees
  cell in the print table is now textAlign: center (matches the Step 1
  schedule).
- Font settings tightened to spec: families = system/Cairo/Tajawal/
  Noto Naskh Arabic/Amiri (dropped Inter, monospace), weights =
  regular/bold (dropped medium, semibold), alignment = start/center
  (dropped end), size range = 12–22 (was 10–32). Enforced server-side
  in fontSettingsSchema (Zod) and mirrored in the UI selects/range.
  Verified: PATCH font-settings returns 200 for valid combo, 400 for
  fontWeight="medium", 400 for fontSize=30.

Validation-round-3 fixes:
- Tasks RBAC tightened end-to-end: new TASK_VIEW_ROLES = admin +
  office_manager + coord_lead + coordinator. GET /tasks and
  PATCH /tasks/:id now require requireTaskView. /me exposes new
  canViewTasks flag. Frontend isSectionVisible("tasks") gated on
  canViewTasks (so CEO/viewer never sees the Tasks tab or hits the
  endpoint). Verified: admin /me returns canViewTasks=true.
- GET /requests gained dateFrom + dateTo (createdAt range) and a
  requester filter that is honored only for approver/audit roles
  (non-approvers stay locked to their own requests). Verified curl
  with ?dateFrom=...&dateTo=... returns 200.
- Task dueAt schema accepts BOTH YYYY-MM-DD (from <input type="date">)
  and full ISO datetime; date-only is normalized to start-of-day UTC,
  empty string clears the field. Verified curl POST /tasks with
  {"dueAt":"2026-12-31"} returns 201 with stored
  dueAt = 2026-12-31T00:00:00.000Z.

Validation-round-2 fixes:
- GET /executive-meetings/requests: added server-side least-privilege so
  only APPROVE_ROLES + ADMIN_AUDIT_ROLES see other users' requests; every
  other executive role is force-scoped to requestedBy = self regardless
  of the client's `mine` flag (closes the RBAC overexposure flag).
- isSectionVisible("tasks") now also returns true for canSubmitRequest,
  so executive_coordinator sees the Tasks tab (coordinators execute the
  follow-ups generated from approved requests).
- Requests "new request" dropdown now exposes ALL twelve backend request
  types: create, edit, delete, reschedule, add_attendee, remove_attendee,
  change_location, cancel_meeting, note, highlight, unhighlight, other.
- i18n parity: added en.json + ar.json keys for the five missing request
  types (add_attendee, remove_attendee, change_location, cancel_meeting,
  note) and the two missing statuses (needs_edit, done) under
  executiveMeetings.requests.{type,status}.
- Fixed wrong key reference: reschedule form's date row was using
  manage.field.date (does not exist) — switched to manage.field.meetingDate.

Drift / out of scope (explicitly deferred to follow-ups #110/#111/#112):
- Real notifications delivery, server-side PDF rendering, attendee
  reorder UI (drag/arrows), duplicate-to-date UI, OpenAPI/api-spec sync,
  expanded seed data including executive_meeting_notifications sample
  rows.
2026-04-28 08:14:01 +00:00

926 lines
42 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
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.
{
"nav": {
"home": "الرئيسية",
"services": "الخدمات",
"chat": "المحادثات",
"notifications": "الإشعارات",
"admin": "لوحة التحكم",
"logout": "تسجيل الخروج"
},
"auth": {
"login": "تسجيل الدخول",
"register": "إنشاء حساب",
"username": "اسم المستخدم",
"email": "البريد الإلكتروني",
"password": "كلمة المرور",
"loginButton": "دخول",
"registerButton": "تسجيل",
"welcomeBack": "مرحباً بعودتك",
"createAccount": "حساب جديد",
"registrationClosed": "إنشاء الحسابات العامة مغلق حالياً. تواصل مع مدير النظام.",
"displayNameAr": "الاسم (عربي)",
"displayNameEn": "الاسم (إنجليزي)",
"subtitle": "سجّل دخولك للمتابعة",
"signingIn": "جارٍ الدخول...",
"noAccount": "ليس لديك حساب؟",
"showPassword": "إظهار كلمة المرور",
"hidePassword": "إخفاء كلمة المرور",
"errRequired": "الرجاء إدخال اسم المستخدم وكلمة المرور.",
"errInvalid": "اسم مستخدم أو كلمة مرور غير صحيحة.",
"forgotPassword": "نسيت كلمة المرور؟",
"forgot": {
"title": "إعادة تعيين كلمة المرور",
"subtitle": "أدخل اسم المستخدم أو البريد الإلكتروني وسنرسل لك رابطاً لإعادة تعيين كلمة المرور.",
"identifier": "اسم المستخدم أو البريد الإلكتروني",
"identifierPlaceholder": "you@example.com",
"submit": "إرسال رابط الاستعادة",
"sending": "جارٍ الإرسال...",
"errRequired": "الرجاء إدخال اسم المستخدم أو البريد الإلكتروني.",
"errGeneric": "حدث خطأ ما. حاول مرة أخرى.",
"successMessage": "تم استلام طلبك. سيقوم المسؤول بمشاركة رابط إعادة التعيين معك قريباً.",
"adminNotice": "إرسال البريد الإلكتروني غير مفعّل بعد لهذه المساحة، لذا سيصدر المسؤول رابط إعادة تعيين لمرة واحدة يدوياً.",
"backToLogin": "العودة إلى تسجيل الدخول"
},
"reset": {
"title": "تعيين كلمة مرور جديدة",
"subtitle": "اختر كلمة مرور جديدة لحسابك.",
"newPassword": "كلمة المرور الجديدة",
"confirmPassword": "تأكيد كلمة المرور",
"submit": "تحديث كلمة المرور",
"saving": "جارٍ الحفظ...",
"errMinLength": "يجب أن تكون كلمة المرور ٦ أحرف على الأقل.",
"errMismatch": "كلمتا المرور غير متطابقتين.",
"errGeneric": "تعذّر إعادة تعيين كلمة المرور. قد يكون الرابط منتهي الصلاحية.",
"invalidToken": "رابط إعادة التعيين غير صالح أو منتهي الصلاحية.",
"requestNew": "طلب رابط جديد",
"successMessage": "تم تحديث كلمة المرور بنجاح. يمكنك تسجيل الدخول بكلمة المرور الجديدة.",
"goToLogin": "الذهاب لتسجيل الدخول"
},
"heroTitle": "مرحباً بك في منصتك الموحدة.",
"heroSubtitle": "سجّل دخولك لإدارة كل شيء من مكان واحد.",
"feat1": "كل أدواتك في لوحة تحكم واحدة",
"feat2": "تحديثات لحظية",
"feat3": "وصول آمن بالجلسات",
"rights": "جميع الحقوق محفوظة."
},
"home": {
"myApps": "تطبيقاتي",
"noApps": "لا توجد تطبيقات بعد",
"noAppsHint": "ستظهر هنا التطبيقات التي تملك صلاحية الوصول إليها.",
"greeting": {
"morning": "صباح الخير، {{name}}",
"afternoon": "مساء الخير، {{name}}",
"evening": "مساء الخير، {{name}}"
},
"stats": {
"apps": "التطبيقات",
"services": "الخدمات",
"messages": "الرسائل",
"alerts": "التنبيهات"
},
"clockStyle": {
"label": "نمط الساعة",
"showWidget": "إظهار ساعة الحائط في الشاشة الرئيسية",
"showTopbar": "إظهار الساعة في الشريط العلوي",
"hideWidget": "إخفاء الساعة",
"hourFormat": {
"label": "صيغة الساعة",
"h12": "12 ساعة (ص/م)",
"h24": "24 ساعة"
},
"options": {
"full": "كامل (الوقت واليوم والتقويمان الهجري والميلادي)",
"digital": "رقمي مع الثواني",
"digital-no-seconds": "رقمي بدون ثواني",
"analog": "ساعة عقاربية",
"minimal": "مبسّط (الوقت فقط)"
}
}
},
"services": {
"title": "الخدمات",
"available": "متاح",
"unavailable": "غير متاح",
"price": "السعر",
"noServices": "لا توجد خدمات متاحة",
"category": "التصنيف",
"free": "مجاني",
"order": "اطلب",
"orderModalTitle": "اطلب: {{name}}",
"orderNotes": "ملاحظات (اختياري)",
"orderNotesPlaceholder": "أي ملاحظات إضافية؟",
"orderNotesCounter": "{{count}}/500",
"placeOrder": "إرسال",
"placing": "جارٍ الإرسال...",
"orderPlaced": "تم إرسال طلبك",
"orderFailed": "تعذّر إرسال الطلب",
"myOrdersLink": "طلباتي"
},
"myOrders": {
"title": "طلباتي",
"loadError": "تعذّر تحميل الطلبات. حاول مرة أخرى.",
"retry": "إعادة المحاولة",
"back": "رجوع",
"empty": "لا توجد طلبات بعد",
"emptyHint": "ابدأ من كتالوج الخدمات.",
"browseServices": "تصفّح الخدمات",
"notesLabel": "ملاحظات:",
"cancel": "إلغاء الطلب",
"cancelConfirmTitle": "إلغاء هذا الطلب؟",
"cancelConfirmBody": "ستتاح لك ثوانٍ قليلة للتراجع.",
"cancelConfirm": "نعم، إلغاء",
"keep": "احتفظ به",
"cancelled": "تم إلغاء الطلب",
"cancelFailed": "تعذّر إلغاء الطلب",
"restoreFailed": "تعذّر استعادة الطلب",
"delete": "حذف",
"reorder": "اطلب مجددًا",
"deleteConfirmTitle": "حذف هذا الطلب؟",
"deleteConfirmBody": "سيتم حذف الطلب نهائياً من سجلّك.",
"deleteConfirm": "نعم، احذف",
"deleted": "تم حذف الطلب",
"deleteFailed": "تعذّر حذف الطلب",
"undo": "تراجع",
"undone": "تمت الاستعادة",
"clearFinished_one": "مسح طلب منتهٍ",
"clearFinished_other": "مسح {{count}} طلبات منتهية",
"clearConfirmTitle": "مسح الطلبات المنتهية؟",
"clearConfirmBody_one": "سيتم حذف طلب واحد منتهٍ نهائياً من سجلّك.",
"clearConfirmBody_other": "سيتم حذف {{count}} طلبات منتهية نهائياً من سجلّك.",
"clearConfirm": "نعم، امسح",
"clearedCount_one": "تم حذف طلب واحد",
"clearedCount_other": "تم حذف {{count}} طلبات",
"clearedPartial": "تم حذف {{ok}} وفشل {{fail}}"
},
"orderStatus": {
"pending": "بانتظار المستلِم",
"received": "تم الاستلام",
"preparing": "قيد التحضير",
"completed": "مكتمل",
"cancelled": "ملغى"
},
"incomingOrders": {
"title": "الطلبات الواردة",
"linkLabel": "الطلبات الواردة",
"subtitleUnclaimed": "طلبات بانتظار الاستلام",
"subtitleMine": "طلباتي الجارية",
"empty": "ما في طلبات حالياً",
"emptyHint": "ستظهر هنا الطلبات الجديدة فور وصولها.",
"loadError": "تعذّر تحميل الطلبات الواردة.",
"retry": "إعادة المحاولة",
"noAccess": "ليس لديك صلاحية لاستلام الطلبات.",
"back": "رجوع",
"ageJustNow": "الآن",
"ageMinutes": "منذ {{count}} د",
"ageHours": "منذ {{count}} س",
"ageDays": "منذ {{count}} يوم",
"from": "من",
"confirmReceipt": "استلام الطلب",
"confirming": "جارٍ التأكيد...",
"markPreparing": "بدء التحضير",
"markCompleted": "إنجاز",
"cancel": "إلغاء",
"alreadyClaimed": "استلمه شخص آخر قبلك",
"orderUnavailable": "هذا الطلب لم يعد متاحاً",
"actionFailed": "تعذّر تنفيذ الإجراء",
"claimed": "تم استلام الطلب",
"marked": "تم تحديث الحالة",
"cancelled": "تم إلغاء الطلب",
"undo": "تراجع",
"undone": "تمت الاستعادة",
"restoreFailed": "تعذّر استعادة الطلب"
},
"chat": {
"title": "المحادثات",
"newMessage": "رسالة جديدة",
"typeMessage": "اكتب رسالتك...",
"send": "إرسال",
"noConversations": "لا توجد محادثات",
"createConversation": "محادثة جديدة",
"groupChat": "مجموعة",
"directMessage": "محادثة خاصة",
"participants": "المشاركون",
"searchUsers": "البحث عن مستخدمين",
"modeDirect": "محادثة خاصة",
"modeGroup": "مجموعة",
"groupNameAr": "اسم المجموعة (عربي)",
"groupNameEn": "اسم المجموعة (إنجليزي)",
"groupNamePlaceholderAr": "مثلاً: فريق المبيعات",
"groupNamePlaceholderEn": "e.g. Sales team",
"searchUsersPlaceholder": "ابحث بالاسم أو اسم المستخدم",
"participantsCount_one": "{{count}} شخص مختار",
"participantsCount_other": "{{count}} أشخاص مختارين",
"participantsCount_zero": "لم يتم اختيار أحد",
"noUsersFound": "لا يوجد مستخدمون مطابقون",
"uploadAvatar": "رفع صورة",
"replaceAvatar": "استبدال الصورة",
"removeAvatar": "إزالة الصورة",
"changeAvatar": "تغيير صورة المجموعة",
"uploadingAvatar": "جارٍ الرفع… {{progress}}٪",
"avatarUploadFailed": "تعذّر رفع الصورة",
"validation": {
"needGroupName": "أدخل اسم المجموعة بالعربية أو الإنجليزية.",
"minTwoMembers": "اختر شخصين على الأقل لإنشاء مجموعة.",
"pickOnePerson": "اختر شخصاً واحداً للمحادثة."
},
"create": "إنشاء",
"settings": {
"title": "إعدادات المجموعة",
"openSettings": "فتح إعدادات المجموعة",
"groupName": "اسم المجموعة",
"saveName": "حفظ الاسم",
"nameSaved": "تم تحديث اسم المجموعة",
"saveFailed": "تعذّر حفظ التغييرات",
"needGroupName": "أدخل اسم المجموعة بالعربية أو الإنجليزية.",
"members_one": "عضو واحد",
"members_two": "عضوان",
"members_few": "{{count}} أعضاء",
"members_many": "{{count}} عضواً",
"members_other": "{{count}} عضو",
"addMembers": "إضافة أعضاء",
"addSelected": "إضافة",
"membersAdded": "تمت إضافة الأعضاء",
"addFailed": "تعذّرت إضافة الأعضاء",
"removeMember": "إزالة العضو",
"removeFailed": "تعذّرت إزالة العضو",
"admin": "مشرف",
"you": "(أنت)",
"viewOnly": "فقط مشرف المجموعة يستطيع تغيير الاسم أو الأعضاء."
},
"filterAll": "نشطة",
"filterArchived": "المؤرشفة",
"noArchived": "لا توجد محادثات مؤرشفة",
"actions": {
"title": "خيارات المحادثة",
"openActions": "فتح خيارات المحادثة",
"mute": "كتم الإشعارات",
"unmute": "إلغاء كتم الإشعارات",
"archive": "أرشفة المحادثة",
"unarchive": "إلغاء الأرشفة",
"leave": "مغادرة المجموعة",
"leaveConfirmTitle": "مغادرة هذه المجموعة؟",
"leaveConfirmBody": "ستتم إزالتك من \"{{name}}\" ولن تتلقى رسائلها بعد الآن.",
"successorTitle": "اختر المشرف التالي",
"successorHelp": "أنت المشرف الوحيد. اختر من يتولى الإدارة، أو دعنا نرقّي أقدم عضو في المجموعة.",
"successorAuto": "تلقائي (أقدم عضو)",
"muted": "تم كتم الإشعارات",
"unmuted": "الإشعارات مفعّلة",
"archived": "تمت أرشفة المحادثة",
"unarchived": "أعيدت المحادثة إلى النشطة",
"left": "غادرت المجموعة",
"actionFailed": "تعذّر تنفيذ الإجراء",
"mutedLabel": "مكتومة",
"youAreAdminTitle": "أنت الآن المشرف",
"youAreAdminDescription": "أصبحت مسؤولًا عن \"{{name}}\".",
"newAdminBadge": "مشرف جديد",
"newAdminLabel": "مشرف جديد: {{name}}"
},
"system": {
"someone": "شخص ما",
"listSeparator": "، ",
"groupRenamed": "غيّر {{actor}} اسم المجموعة إلى \"{{name}}\"",
"membersAdded_one": "أضاف {{actor}} {{names}}",
"membersAdded_other": "أضاف {{actor}} {{names}}",
"memberRemoved": "أزال {{actor}} {{target}}",
"memberLeft": "غادر {{actor}} المجموعة",
"adminPromoted": "{{target}} أصبح مشرفًا للمجموعة",
"adminPromotedAfterLeave": "تمت ترقية {{target}} إلى مشرف بعد مغادرة المشرف السابق"
}
},
"notifications": {
"title": "الإشعارات",
"markAllRead": "تحديد الكل كمقروء",
"noNotifications": "لا توجد إشعارات جديدة",
"unread": "غير مقروء"
},
"admin": {
"title": "لوحة التحكم",
"manageApps": "إدارة التطبيقات",
"manageServices": "إدارة الخدمات",
"manageUsers": "إدارة المستخدمين",
"appDisabled": "معطّل",
"addApp": "إضافة تطبيق",
"addService": "إضافة خدمة",
"addUser": "إضافة مستخدم",
"editApp": "تعديل التطبيق",
"editService": "تعديل الخدمة",
"editUser": "تعديل المستخدم",
"deleteConfirm": "هل أنت متأكد من الحذف؟",
"deleteApp": {
"title": "حذف التطبيق \"{{name}}\"؟",
"warning": "هذا التطبيق لا يزال قيد الاستخدام. حذفه سيؤثر على ما يلي:",
"forceHint": "سيؤدي ذلك إلى إلغاء وصول كل من يستخدمه وإزالة سجلّه. لا يمكن التراجع عن هذا الإجراء.",
"emptyBody": "هل أنت متأكد من حذف هذا التطبيق؟",
"groupCount": "{{count}} مجموعة تمنح هذا التطبيق حالياً",
"restrictionCount": "{{count}} قاعدة صلاحيات تقيّده",
"openCount": "{{count}} مرة فتح في السجل",
"confirm": "حذف",
"anyway": "حذف رغم ذلك"
},
"deleteService": {
"title": "حذف الخدمة \"{{name}}\"؟",
"warning": "هذه الخدمة لا تزال مرتبطة بطلبات. حذفها سيؤثر على ما يلي:",
"forceHint": "سيؤدي ذلك إلى حذف كل الطلبات المرتبطة نهائياً. لا يمكن التراجع عن هذا الإجراء.",
"emptyBody": "هل أنت متأكد من حذف هذه الخدمة؟",
"orderCount": "{{count}} طلب",
"confirm": "حذف",
"anyway": "حذف رغم ذلك"
},
"deleteUser": {
"title": "حذف المستخدم \"{{name}}\"؟",
"warning": "هذا المستخدم لديه بيانات. حذفه سيؤثر على ما يلي:",
"forceHint": "سيؤدي ذلك إلى حذف ملاحظاته وطلباته والمحادثات التي أنشأها والرسائل التي أرسلها بشكل نهائي. لا يمكن التراجع عن هذا الإجراء.",
"emptyBody": "هل أنت متأكد من حذف هذا المستخدم؟",
"noteCount": "{{count}} ملاحظة",
"orderCount": "{{count}} طلب",
"conversationCount": "{{count}} محادثة أنشأها",
"messageCount": "{{count}} رسالة أرسلها",
"confirm": "حذف",
"anyway": "حذف رغم ذلك"
},
"activate": "تفعيل",
"deactivate": "تعطيل",
"appName": "اسم التطبيق",
"appNameAr": "اسم التطبيق (عربي)",
"appNameEn": "اسم التطبيق (إنجليزي)",
"appSlug": "المعرف",
"appRoute": "المسار",
"appIcon": "الأيقونة",
"appColor": "اللون",
"appSortOrder": "الترتيب",
"serviceName": "اسم الخدمة",
"serviceNameAr": "اسم الخدمة (عربي)",
"serviceNameEn": "اسم الخدمة (إنجليزي)",
"serviceDescriptionAr": "الوصف (عربي)",
"serviceDescriptionEn": "الوصف (إنجليزي)",
"servicePrice": "السعر",
"serviceAvailable": "متاح؟",
"serviceImageUrl": "رابط الصورة",
"serviceImage": "صورة الخدمة",
"uploadImage": "رفع صورة",
"replaceImage": "استبدال الصورة",
"uploading": "جاري الرفع...",
"uploadFailed": "فشل رفع الصورة",
"users": "المستخدمين",
"username": "اسم المستخدم",
"email": "البريد الإلكتروني",
"password": "كلمة المرور",
"roles": "الصلاحيات",
"active": "نشط",
"issueResetLink": "إصدار رابط إعادة تعيين كلمة المرور",
"orderReceiverRole": "مستلم الطلبات",
"resetLinkModal": {
"title": "رابط إعادة تعيين كلمة المرور للمستخدم {{username}}",
"description": "شارك هذا الرابط لمرة واحدة مع المستخدم. يمكن استخدامه مرة واحدة فقط.",
"expires": "تنتهي الصلاحية: {{time}}",
"copy": "نسخ الرابط",
"copied": "تم نسخ الرابط"
},
"siteSettings": "إعدادات الموقع",
"siteNameAr": "اسم الموقع (عربي)",
"siteNameEn": "اسم الموقع (إنجليزي)",
"registrationOpen": "السماح بإنشاء حسابات",
"registrationOpenHint": "عند الإيقاف، الأدمن فقط يقدر ينشئ مستخدمين جدد.",
"footerTextAr": "نص التذييل (عربي)",
"footerTextEn": "نص التذييل (إنجليزي)",
"nav": {
"dashboard": "الرئيسية",
"apps": "التطبيقات",
"services": "الخدمات",
"users": "المستخدمين",
"groups": "المجموعات",
"roles": "الأدوار",
"auditLog": "سجل التدقيق",
"userManagement": "إدارة المستخدمين",
"settings": "الإعدادات",
"menu": "القائمة"
},
"users": {
"searchPlaceholder": "ابحث باسم المستخدم أو البريد...",
"allGroups": "كل المجموعات",
"allStatuses": "كل الحالات",
"statusActive": "نشط",
"statusInactive": "موقوف",
"showing": "عرض {{count}} من أصل {{total}}",
"empty": "لا يوجد مستخدمون يطابقون الفلاتر.",
"editGroups": "تعديل المجموعات",
"editUserGroups": "تعديل مجموعات {{username}}",
"col": {
"username": "اسم المستخدم",
"email": "البريد",
"displayNameAr": "الاسم (عربي)",
"displayNameEn": "الاسم (إنجليزي)",
"language": "اللغة",
"createdAt": "تاريخ الإنشاء",
"groups": "المجموعات",
"actions": "إجراءات"
}
},
"roles": {
"searchPlaceholder": "ابحث في الأدوار...",
"addRole": "إضافة دور",
"editRole": "تعديل الدور",
"name": "الاسم",
"namePlaceholder": "مثال: content_editor",
"nameHint": "حروف وأرقام وشرطات سفلية فقط.",
"descriptionAr": "الوصف (عربي)",
"descriptionEn": "الوصف (إنجليزي)",
"system": "نظامي",
"empty": "لا توجد أدوار بعد.",
"edit": "تعديل الدور",
"delete": "حذف الدور",
"editSystemNameHint": "لا يمكن تغيير اسم الأدوار النظامية.",
"deleteTitle": "حذف الدور \"{{name}}\"؟",
"deleteEmptyBody": "هذا الدور غير مُعيَّن لأي مستخدم. هل تريد المتابعة؟",
"deleteConflict": "هذا الدور قيد الاستخدام ولا يمكن حذفه.",
"deleteConflictHint": "أزل هذا الدور من المستخدمين والمجموعات قبل حذفه.",
"deleteConfirm": "حذف",
"usersCount": "{{count}} مستخدم",
"groupsCount": "{{count}} مجموعة",
"errorNameTaken": "يوجد دور بنفس الاسم.",
"errorInvalidName": "يجب أن يبدأ اسم الدور بحرف ويحتوي على حروف وأرقام وشرطات سفلية فقط.",
"errorSystemRename": "لا يمكن تغيير اسم الأدوار النظامية.",
"permissions": "الصلاحيات",
"permissionsHint": "اختر الصلاحيات التي يمنحها هذا الدور.",
"permissionsSystemHint": "صلاحيات الأدوار النظامية للقراءة فقط.",
"permissionsEmpty": "لا توجد صلاحيات معرّفة.",
"errorSystemPermissions": "لا يمكن تغيير صلاحيات الأدوار النظامية.",
"errorPermissionsSave": "تعذّر حفظ صلاحيات الدور."
},
"groups": {
"searchPlaceholder": "ابحث في المجموعات...",
"addGroup": "إضافة مجموعة",
"editGroup": "تعديل المجموعة",
"name": "الاسم",
"descriptionAr": "الوصف (عربي)",
"descriptionEn": "الوصف (إنجليزي)",
"system": "نظامية",
"empty": "لا توجد مجموعات بعد.",
"members": "{{count}} عضو",
"appsCount": "{{count}} تطبيق",
"rolesCount": "{{count}} دور",
"appsHint": "أعضاء هذه المجموعة سيرون هذه التطبيقات.",
"usersHint": "أعضاء هذه المجموعة.",
"rolesHint": "يحصل أعضاء هذه المجموعة تلقائياً على هذه الأدوار.",
"rolesEmpty": "لا توجد أدوار متاحة.",
"deleteTitle": "حذف المجموعة \"{{name}}\"؟",
"deleteWarning": "هذه المجموعة لا تزال قيد الاستخدام. حذفها سيلغي الوصول لما يلي:",
"deleteForceHint": "سيؤدي الحذف إلى فصل الأعضاء وإلغاء التطبيقات والأدوار الممنوحة عبر المجموعة. لا يمكن التراجع عن هذا الإجراء.",
"deleteEmptyBody": "لا تحتوي هذه المجموعة على أعضاء أو تطبيقات أو أدوار. هل تريد المتابعة؟",
"deleteConfirm": "حذف",
"deleteAnyway": "حذف رغم ذلك",
"tab": {
"info": "المعلومات",
"apps": "التطبيقات",
"users": "المستخدمون",
"roles": "الأدوار"
}
},
"audit": {
"filters": {
"action": "الإجراء",
"allActions": "كل الإجراءات",
"from": "من",
"to": "إلى",
"apply": "تطبيق",
"reset": "إعادة ضبط"
},
"target": "الهدف: {{type}} #{{id}}",
"showing": "عرض {{shown}} من أصل {{total}}",
"empty": "لا توجد إدخالات في سجل التدقيق تطابق الفلاتر.",
"loadMore": "عرض المزيد",
"errors": {
"invalidDate": "يجب أن تكون التواريخ بصيغة YYYY-MM-DD.",
"invertedDates": "تاريخ \"من\" يجب أن يكون قبل أو يساوي تاريخ \"إلى\".",
"fixFiltersFirst": "عدّل الفلاتر لتحميل الإدخالات."
}
},
"dashboardSoon": "إحصائيات اللوحة قريباً.",
"dashboard": {
"totalApps": "إجمالي التطبيقات",
"totalServices": "إجمالي الخدمات",
"totalUsers": "إجمالي المستخدمين",
"registration": "التسجيل",
"open": "مفتوح",
"closed": "مغلق",
"recentActivity": "آخر النشاطات",
"latestUser": "آخر مستخدم",
"latestApp": "آخر تطبيق",
"none": "—",
"newUsers7d": "مستخدمون جدد (٧ أيام)",
"vsPrev7d": "الأسبوع السابق: {{count}}",
"newUsersInRange": "مستخدمون جدد · {{range}}",
"vsPrevRange": "{{range}}: {{count}}",
"activeServices": "الخدمات النشطة",
"inactiveServices": "غير نشطة: {{count}}",
"signupsTrend": "التسجيلات",
"last7Days": "آخر ٧ أيام",
"appOpensTrend": "فتح التطبيقات",
"appOpensSummary": "{{count}} إجمالاً · {{delta}}",
"appOpensSummaryRanged": "{{count}} في {{range}} · {{delta}}",
"servicesCreatedTrend": "خدمات جديدة",
"servicesCreatedSummary": "{{count}} مضافة",
"servicesCreatedSummaryRanged": "{{count}} في {{range}}",
"trends": "الاتجاهات",
"rangeSelector": "المدى الزمني",
"range": {
"7d": "آخر ٧ أيام",
"30d": "آخر ٣٠ يومًا",
"90d": "آخر ٩٠ يومًا",
"custom": "مدى مخصص",
"customLabel": "{{from}} {{to}}"
},
"prevRange": {
"7d": "الأيام ٧ السابقة",
"30d": "الأيام ٣٠ السابقة",
"90d": "الأيام ٩٠ السابقة",
"custom": "الـ {{count}} أيام السابقة"
},
"customRange": {
"from": "من",
"to": "إلى",
"apply": "تطبيق",
"invalid": "اختر نطاقًا صحيحًا",
"loadError": "تعذّر تحميل الإحصائيات للنطاق المحدّد. يرجى التحقق من التواريخ والمحاولة مرة أخرى."
},
"topApps": "أكثر التطبيقات استخدامًا",
"topAppsSubtitle": "حسب الفتح في {{range}}",
"mostActiveUsers": "أكثر المستخدمين نشاطًا",
"mostActiveUsersSubtitle": "حسب فتح التطبيقات في {{range}}",
"leaderboardEmpty": "لا يوجد نشاط بعد",
"openCount": "{{count}} فتحة",
"viewAppDetails": "عرض تفاصيل {{name}}",
"viewUserDetails": "عرض تفاصيل {{name}}",
"drillIn": {
"loading": "جارٍ التحميل…",
"appTitle": "آخر الفتحات · {{name}}",
"userTitle": "آخر الفتحات · {{name}}",
"subtitle": "{{count}} فتحة في {{range}}",
"empty": "لا توجد فتحات في هذا النطاق",
"loadError": "تعذّر تحميل آخر الفتحات.",
"editApp": "تعديل التطبيق",
"viewUser": "عرض المستخدم",
"loadMore": "تحميل المزيد",
"loadMoreError": "تعذّر تحميل المزيد من الفتحات.",
"shownOf": "عرض {{shown}} من {{total}}"
}
}
},
"notFound": {
"title": "404 — الصفحة غير موجودة",
"description": "الصفحة التي تبحث عنها غير موجودة."
},
"common": {
"save": "حفظ",
"cancel": "إلغاء",
"delete": "حذف",
"edit": "تعديل",
"add": "إضافة",
"close": "إغلاق",
"loading": "جاري التحميل...",
"error": "حدث خطأ",
"success": "تمت العملية بنجاح",
"language": "English",
"appName": "نظام Tx"
},
"notes": {
"title": "الملاحظات",
"searchPlaceholder": "ابحث في الملاحظات",
"labels": "التصنيفات",
"manageLabels": "إدارة التصنيفات",
"newLabel": "تصنيف جديد",
"noLabelsYet": "لا توجد تصنيفات بعد",
"allLabels": "الكل",
"tabs": { "active": "ملاحظات", "archived": "الأرشيف" },
"pinned": "مثبّتة",
"others": "أخرى",
"empty": "ستظهر ملاحظاتك هنا",
"emptyArchived": "لا توجد ملاحظات في الأرشيف",
"takeNote": "اكتب ملاحظة...",
"titlePlaceholder": "العنوان",
"contentPlaceholder": "اكتب ملاحظة...",
"save": "حفظ",
"pin": "تثبيت",
"archive": "أرشفة",
"unarchive": "إلغاء الأرشفة",
"delete": "حذف",
"deleteConfirm": "حذف هذه الملاحظة؟",
"deleteLabelConfirm": "حذف هذا التصنيف؟",
"editTitle": "تعديل ملاحظة"
},
"executiveMeetings": {
"titleAr": "إدارة الاجتماعات التنفيذية",
"titleEn": "Executive Meetings Management",
"scheduleHeading": "قائمة بأسماء حضور الاجتماعات",
"date": "التاريخ:",
"exportPdf": "تصدير PDF",
"fontSettings": "إعدادات الخط",
"noMeetings": "لا توجد اجتماعات في هذا اليوم",
"virtual": "اتصال مرئي",
"virtualAttendance": "الحضور عبر الاتصال المرئي",
"internalAttendance": "الحضور الداخلي",
"externalAttendance": "حضور خارجي",
"placeholderBody": "هذا القسم قيد التطوير في المراحل القادمة. ستتوفر إدارته الكاملة قريباً.",
"col": {
"number": "#",
"meeting": "الاجتماع",
"attendees": "الحضور",
"time": "الوقت"
},
"nav": {
"schedule": "جدول الاجتماعات اليومي",
"manage": "إدارة الاجتماعات",
"requests": "طلبات التعديل",
"approvals": "موافقات مدير المكتب",
"tasks": "مهام فريق التنسيق",
"notifications": "التنبيهات",
"audit": "سجل التعديلات",
"pdf": "تصدير PDF",
"fontSettings": "إعدادات الخط"
},
"common": {
"save": "حفظ",
"cancel": "إلغاء",
"delete": "حذف",
"edit": "تعديل",
"add": "إضافة",
"submit": "إرسال",
"close": "إغلاق",
"loading": "جارٍ التحميل...",
"saved": "تم الحفظ",
"saveFailed": "تعذر الحفظ",
"actions": "إجراءات",
"noPermission": "ليست لديك صلاحية لتنفيذ هذا الإجراء",
"yes": "نعم",
"no": "لا",
"all": "الكل",
"filter": "تصفية"
},
"manage": {
"heading": "إدارة الاجتماعات",
"addMeeting": "إضافة اجتماع",
"editMeeting": "تعديل الاجتماع",
"deleteMeeting": "حذف الاجتماع",
"deleteConfirm": "حذف هذا الاجتماع نهائياً؟",
"noMeetings": "لا توجد اجتماعات لهذا اليوم. اضغط \"إضافة اجتماع\" لإنشاء واحد.",
"field": {
"titleAr": "العنوان (عربي)",
"titleEn": "العنوان (إنجليزي)",
"meetingDate": "التاريخ",
"dailyNumber": "الرقم اليومي",
"dailyNumberHint": "اتركه فارغاً ليتم الترقيم تلقائياً",
"startTime": "وقت البدء",
"endTime": "وقت الانتهاء",
"location": "المكان",
"meetingUrl": "رابط الاجتماع",
"platform": "المنصة",
"status": "الحالة",
"isHighlighted": "تمييز (لون أحمر)",
"notes": "ملاحظات"
},
"attendees": {
"label": "قائمة الحضور",
"name": "الاسم",
"title": "المسمى",
"id": "رقم الحاضر",
"type": "نوع الحضور",
"add": "إضافة حاضر",
"remove": "إزالة",
"moveUp": "تحريك للأعلى",
"moveDown": "تحريك للأسفل"
},
"duplicate": "تكرار",
"duplicateToDate": "تكرار إلى تاريخ",
"duplicated": "تم تكرار الاجتماع",
"duplicateFailed": "تعذر تكرار الاجتماع",
"platform": {
"none": "بدون",
"webex": "Webex",
"teams": "Teams",
"zoom": "Zoom",
"other": "أخرى"
},
"attendanceType": {
"internal": "داخلي",
"virtual": "افتراضي",
"external": "خارجي"
},
"status": {
"scheduled": "مجدول",
"cancelled": "ملغى",
"completed": "منتهٍ",
"postponed": "مؤجل"
},
"errors": {
"titleRequired": "العنوان بالعربية مطلوب",
"dateRequired": "التاريخ مطلوب",
"duplicateNumber": "هذا الرقم اليومي مستخدم بالفعل في هذا التاريخ",
"saveFailed": "تعذر حفظ الاجتماع"
}
},
"requests": {
"heading": "طلبات التعديل",
"newRequest": "طلب جديد",
"myRequests": "طلباتي",
"allRequests": "جميع الطلبات",
"empty": "لا توجد طلبات.",
"filterStatus": "تصفية حسب الحالة",
"submitFor": "اقتراح تعديل على:",
"noTargetMeeting": "اقتراح اجتماع جديد (بدون ربط)",
"details": "التفاصيل",
"detailsPlaceholder": "اشرح ما تقترح بالتفصيل...",
"submitted": "تم إرسال الطلب",
"submitFailed": "تعذر إرسال الطلب",
"requestedBy": "مقدم الطلب",
"requestedAt": "وقت الطلب",
"type": {
"create": "إنشاء اجتماع",
"edit": "تعديل بيانات",
"delete": "حذف",
"reschedule": "إعادة جدولة",
"add_attendee": "إضافة حاضر",
"remove_attendee": "إزالة حاضر",
"change_location": "تغيير المكان",
"cancel_meeting": "إلغاء الاجتماع",
"note": "ملاحظة",
"highlight": "تمييز",
"unhighlight": "إزالة التمييز",
"other": "آخر"
},
"status": {
"new": "جديد",
"approved": "تمت الموافقة",
"rejected": "مرفوض",
"needs_edit": "يحتاج تعديل",
"withdrawn": "مسحوب",
"done": "تم"
}
},
"approvals": {
"heading": "موافقات مدير المكتب",
"empty": "لا توجد طلبات بانتظار المراجعة.",
"approve": "اعتماد",
"reject": "رفض",
"needsEdit": "إعادة للتعديل",
"needsEditDone": "تم إرجاع الطلب لمقدّمه",
"reviewNotes": "ملاحظات المراجعة",
"reviewNotesPlaceholder": "اكتب ملاحظاتك هنا (اختياري)",
"approved": "تم الاعتماد",
"rejected": "تم الرفض",
"actionFailed": "تعذر تنفيذ المراجعة"
},
"tasks": {
"heading": "مهام فريق التنسيق",
"addTask": "إضافة مهمة",
"empty": "لا توجد مهام.",
"field": {
"taskType": "نوع المهمة",
"assignee": "المُكلَّف",
"dueDate": "تاريخ الاستحقاق",
"notes": "ملاحظات",
"meeting": "الاجتماع",
"status": "الحالة"
},
"status": {
"pending": "بالانتظار",
"in_progress": "قيد التنفيذ",
"completed": "منجزة",
"cancelled": "ملغاة"
},
"markCompleted": "إنهاء المهمة",
"markInProgress": "بدء التنفيذ",
"deleteConfirm": "حذف هذه المهمة؟",
"saved": "تم حفظ المهمة",
"deleted": "تم حذف المهمة",
"reassign": "إعادة إسناد / تعديل",
"reassigned": "تم تحديث المهمة",
"myTasksOnly": "مهامي فقط",
"myTasksOnlyHelp": "ينظر المنسقون إلى المهام المسندة إليهم فقط، بينما يرى قائد التنسيق ومدير المكتب والمسؤول جميع المهام."
},
"audit": {
"heading": "سجل التعديلات",
"empty": "لا توجد قيود في السجل.",
"filterDate": "تصفية بالتاريخ",
"filterEntity": "النوع",
"filter": {
"from": "من",
"to": "إلى",
"actorId": "معرّف المنفّذ"
},
"all": "الكل",
"col": {
"when": "الوقت",
"actor": "المنفّذ",
"action": "الإجراء",
"entity": "النوع",
"entityId": "المعرف",
"diff": "التفاصيل",
"changes": "التغييرات"
},
"created": "تم إنشاء",
"removed": "تم حذف",
"moreChanges": "تغييرات أخرى",
"entity": {
"meeting": "اجتماع",
"attendee": "حاضر",
"request": "طلب",
"task": "مهمة",
"font_settings": "إعدادات الخط",
"pdf_archive": "أرشيف PDF"
},
"action": {
"create": "إنشاء",
"update": "تعديل",
"delete": "حذف",
"approve": "اعتماد",
"approved": "تم الاعتماد",
"reject": "رفض",
"rejected": "تم الرفض",
"needs_edit": "إعادة للتعديل",
"withdraw": "سحب",
"submit": "إرسال",
"apply": "تطبيق",
"duplicate": "تكرار",
"replace_attendees": "تحديث الحضور",
"done": "تم"
}
},
"print": {
"title": "جدول الاجتماعات التنفيذية",
"no": "#",
"meeting": "الاجتماع",
"attendees": "الحضور",
"time": "الوقت",
"location": "المكان",
"none": "لا توجد اجتماعات لهذا اليوم.",
"print": "طباعة",
"back": "إغلاق",
"loading": "جارٍ التحميل…"
},
"pdf": {
"heading": "تصدير / طباعة",
"intro": "تستخدم هذه الواجهة طابعة المتصفح لإنتاج نسخة PDF من جدول اليوم. اختر التاريخ ثم اضغط طباعة.",
"print": "طباعة وأرشفة",
"printOnly": "طباعة فقط",
"openSchedule": "عرض الجدول",
"selectDate": "تاريخ الجدول",
"archiveSnapshot": "أرشفة نسخة",
"archived": "تمت أرشفة النسخة",
"archivedAndPrinted": "تمت أرشفة النسخة وفتح نافذة الطباعة",
"archivesHeading": "النسخ المؤرشفة",
"noArchives": "لا توجد نسخ مؤرشفة لهذا التاريخ بعد.",
"openArchive": "فتح"
},
"fontSettingsPage": {
"heading": "إعدادات الخط",
"intro": "تطبق هذه الإعدادات على جدول الاجتماعات. يمكنك حفظ تفضيلك الشخصي، ويمكن للمسؤول حفظ الإعدادات العامة لجميع المستخدمين.",
"scope": "النطاق",
"scopeUser": "تفضيلي الشخصي",
"scopeGlobal": "عام (جميع المستخدمين)",
"fontFamily": "نوع الخط",
"fontSize": "حجم الخط",
"fontWeight": "السماكة",
"alignment": "المحاذاة",
"weight": {
"regular": "عادي",
"medium": "متوسط",
"semibold": "نصف عريض",
"bold": "عريض"
},
"align": {
"start": "بداية",
"center": "وسط",
"end": "نهاية"
},
"preview": "معاينة",
"previewText": "نص تجريبي ١٢٣ Sample 123",
"save": "حفظ الإعدادات",
"saved": "تم الحفظ",
"reset": "إعادة الافتراضي"
},
"notificationsPage": {
"heading": "التنبيهات",
"intro": "هذه قائمة التنبيهات المجدولة المرتبطة باجتماعات المكتب. لا يتم الإرسال الفعلي حالياً (وضع تجريبي).",
"empty": "لا توجد تنبيهات مجدولة.",
"col": {
"meeting": "الاجتماع",
"user": "المستخدم",
"type": "النوع",
"scheduledAt": "الموعد",
"status": "الحالة"
},
"type": {
"reminder": "تذكير",
"change": "تنبيه تعديل",
"cancel": "تنبيه إلغاء"
},
"status": {
"pending": "بالانتظار",
"sent": "أُرسل",
"skipped": "متخطى",
"failed": "فشل"
}
}
}
}