2 Commits
ad4b770334
...
bcedc4ea04
25 changed files with 3376 additions and 1374 deletions
-
1package.json
-
135scripts/check-translations.js
-
856scripts/generate-locales.js
-
126src/components/layout/ServerStatusDialog.tsx
-
26src/components/shared/DeleteConfirmDialog.tsx
-
26src/features/auth/LoginPage.tsx
-
14src/features/dashboard/DashboardHome.tsx
-
20src/features/global-search/GlobalSearchDialog.tsx
-
4src/features/services/ServicesPage.tsx
-
13src/features/services/components/CategoriesServiceView.tsx
-
203src/features/services/components/CitiesServiceView.tsx
-
430src/features/services/components/CreateLocationDialog.tsx
-
870src/features/services/components/DuasServiceView.tsx
-
122src/features/services/components/LocationDetailSheet.tsx
-
397src/features/services/components/ZayerGuideServiceView.tsx
-
120src/features/services/services/trip-etiquette-api.ts
-
424src/features/services/services/zayer-guide-api.ts
-
34src/features/services/types/trip-etiquette.ts
-
33src/features/services/types/zayer-guide.ts
-
44src/features/tours/components/TourStatusBadge.tsx
-
12src/i18n/index.ts
-
12src/locales/__tests__/locales.test.ts
-
220src/locales/ar.json
-
144src/locales/en.json
-
202src/locales/fa.json
@ -0,0 +1,135 @@ |
|||||
|
#!/usr/bin/env node
|
||||
|
|
||||
|
/** |
||||
|
* Translation Synchronization Checker for aqila_panel. |
||||
|
* Validates that fa.json, en.json, and ar.json: |
||||
|
* 1. Exist and have valid JSON syntax. |
||||
|
* 2. Contain identical keys (nested dot-notation paths). |
||||
|
* 3. Have no null, undefined, or empty/whitespace values. |
||||
|
*/ |
||||
|
|
||||
|
import fs from 'node:fs' |
||||
|
import path from 'node:path' |
||||
|
import { fileURLToPath } from 'node:url' |
||||
|
|
||||
|
const __filename = fileURLToPath(import.meta.url) |
||||
|
const __dirname = path.dirname(__filename) |
||||
|
|
||||
|
const LOCALES_DIR = path.resolve(__dirname, '../src/locales') |
||||
|
const TARGET_LANGS = ['fa', 'en', 'ar'] |
||||
|
|
||||
|
function loadJson(filePath) { |
||||
|
try { |
||||
|
const raw = fs.readFileSync(filePath, 'utf-8') |
||||
|
return JSON.parse(raw) |
||||
|
} catch (err) { |
||||
|
console.error(`❌ Failed to read or parse JSON file: ${filePath}`) |
||||
|
console.error(err.message) |
||||
|
process.exit(1) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Recursively flattens an object to dot-notation paths and validates values. |
||||
|
* Returns { keys: Map<string, string>, emptyKeys: string[] } |
||||
|
*/ |
||||
|
function extractKeysAndValidate(obj, prefix = '') { |
||||
|
const keys = new Map() |
||||
|
const emptyKeys = [] |
||||
|
|
||||
|
for (const [key, value] of Object.entries(obj)) { |
||||
|
const fullPath = prefix ? `${prefix}.${key}` : key |
||||
|
|
||||
|
if (value === null || value === undefined) { |
||||
|
emptyKeys.push(fullPath) |
||||
|
keys.set(fullPath, '') |
||||
|
} else if (typeof value === 'object' && !Array.isArray(value)) { |
||||
|
const child = extractKeysAndValidate(value, fullPath) |
||||
|
for (const [childKey, childVal] of child.keys.entries()) { |
||||
|
keys.set(childKey, childVal) |
||||
|
} |
||||
|
emptyKeys.push(...child.emptyKeys) |
||||
|
} else if (typeof value === 'string') { |
||||
|
if (value.trim() === '') { |
||||
|
emptyKeys.push(fullPath) |
||||
|
} |
||||
|
keys.set(fullPath, value) |
||||
|
} else { |
||||
|
keys.set(fullPath, String(value)) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return { keys, emptyKeys } |
||||
|
} |
||||
|
|
||||
|
export function validateTranslations() { |
||||
|
console.log('🔍 Checking translation synchronization for aqila_panel locales...') |
||||
|
console.log(`📁 Directory: ${LOCALES_DIR}\n`) |
||||
|
|
||||
|
const data = {} |
||||
|
const extracted = {} |
||||
|
|
||||
|
for (const lang of TARGET_LANGS) { |
||||
|
const filePath = path.join(LOCALES_DIR, `${lang}.json`) |
||||
|
if (!fs.existsSync(filePath)) { |
||||
|
console.error(`❌ Missing locale file: ${filePath}`) |
||||
|
return { success: false, errors: [`Missing locale file: ${filePath}`] } |
||||
|
} |
||||
|
data[lang] = loadJson(filePath) |
||||
|
extracted[lang] = extractKeysAndValidate(data[lang]) |
||||
|
} |
||||
|
|
||||
|
const allKeyPaths = new Set() |
||||
|
for (const lang of TARGET_LANGS) { |
||||
|
for (const key of extracted[lang].keys.keys()) { |
||||
|
allKeyPaths.add(key) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const errors = [] |
||||
|
|
||||
|
// Check 1: Empty values
|
||||
|
for (const lang of TARGET_LANGS) { |
||||
|
if (extracted[lang].emptyKeys.length > 0) { |
||||
|
errors.push( |
||||
|
`[${lang}.json] Contains ${extracted[lang].emptyKeys.length} empty value(s):\n - ` + |
||||
|
extracted[lang].emptyKeys.join('\n - ') |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Check 2: Missing keys across languages
|
||||
|
for (const key of allKeyPaths) { |
||||
|
const missingIn = TARGET_LANGS.filter((lang) => !extracted[lang].keys.has(key)) |
||||
|
if (missingIn.length > 0) { |
||||
|
errors.push( |
||||
|
`Key "${key}" is missing in: [${missingIn.map((l) => `${l}.json`).join(', ')}]` |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Check 3: Key counts
|
||||
|
const counts = TARGET_LANGS.map((lang) => `${lang}.json: ${extracted[lang].keys.size} keys`).join(' | ') |
||||
|
|
||||
|
if (errors.length > 0) { |
||||
|
console.error('❌ Translation synchronization check FAILED!\n') |
||||
|
console.error(`📊 Key counts: ${counts}\n`) |
||||
|
console.error('🚨 Details:') |
||||
|
errors.forEach((err, idx) => console.error(`${idx + 1}. ${err}`)) |
||||
|
console.error('\n⚠️ Please ensure all keys exist and have non-empty values in fa.json, en.json, and ar.json.\n') |
||||
|
return { success: false, errors } |
||||
|
} |
||||
|
|
||||
|
console.log('✅ Translation synchronization check PASSED!') |
||||
|
console.log(`📊 Total keys verified: ${allKeyPaths.size} keys`) |
||||
|
console.log(` ${counts}\n`) |
||||
|
return { success: true, count: allKeyPaths.size } |
||||
|
} |
||||
|
|
||||
|
// Run if called directly from CLI
|
||||
|
if (process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) { |
||||
|
const result = validateTranslations() |
||||
|
if (!result.success) { |
||||
|
process.exit(1) |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,856 @@ |
|||||
|
import fs from 'node:fs' |
||||
|
import path from 'node:path' |
||||
|
import { fileURLToPath } from 'node:url' |
||||
|
|
||||
|
const __filename = fileURLToPath(import.meta.url) |
||||
|
const __dirname = path.dirname(__filename) |
||||
|
|
||||
|
const LOCALES_DIR = path.resolve(__dirname, '../src/locales') |
||||
|
|
||||
|
export const enLocale = { |
||||
|
navigation: { |
||||
|
brand: 'Aqila Admin Panel', |
||||
|
brandShort: 'Aqila', |
||||
|
dashboard: 'Dashboard', |
||||
|
dashboardTitle: 'Admin Dashboard', |
||||
|
tours: 'Tours', |
||||
|
allTours: 'All Tours', |
||||
|
ongoingTours: 'Ongoing Tours', |
||||
|
tourOrders: 'Orders & Bookings', |
||||
|
services: 'Services Center', |
||||
|
simcard: 'SIM Card', |
||||
|
zayerGuide: 'Zayer Guide', |
||||
|
exchange: 'Online Exchange', |
||||
|
duas: 'Duas & Ziyarat', |
||||
|
duasList: 'Duas & Ziyarat', |
||||
|
categories: 'Categories', |
||||
|
cities: 'Holy Cities', |
||||
|
store: 'Massoumah Store', |
||||
|
storeProducts: 'Products', |
||||
|
storeCategories: 'Categories', |
||||
|
costEstimate: 'Cost Estimate', |
||||
|
support: 'Support Center', |
||||
|
supporters: 'Support Staff', |
||||
|
faq: 'FAQ', |
||||
|
faqCategories: 'Subject Categories', |
||||
|
faqQuestions: 'Questions & Answers', |
||||
|
consultant: 'Support', |
||||
|
billing: 'Billing & Finance', |
||||
|
settings: 'Settings', |
||||
|
logout: 'Logout', |
||||
|
soon: 'Soon', |
||||
|
adminRole: 'System Administrator', |
||||
|
}, |
||||
|
topbar: { |
||||
|
serverOnline: 'Server is Online', |
||||
|
serverOffline: 'Server Disconnected', |
||||
|
theme: 'Theme', |
||||
|
language: 'Language', |
||||
|
selectLanguage: 'Select System Language', |
||||
|
search: 'Search...', |
||||
|
}, |
||||
|
auth: { |
||||
|
loginTitle: 'Login to Admin Dashboard', |
||||
|
loginDescription: 'Enter your credentials to access the management portal', |
||||
|
demoBoxTitle: 'Demo Ready Account:', |
||||
|
autoFill: 'Auto Fill', |
||||
|
emailLabel: 'Account Email', |
||||
|
emailPlaceholder: '[email protected]', |
||||
|
passwordLabel: 'Password', |
||||
|
passwordPlaceholder: '••••••••', |
||||
|
showPassword: 'Show password', |
||||
|
hidePassword: 'Hide password', |
||||
|
submitLogin: 'Login to Account', |
||||
|
loggingIn: 'Logging in...', |
||||
|
loginFailed: 'Login failed. Please try again.', |
||||
|
footerNote: 'Supports custom templates and direct API connection', |
||||
|
}, |
||||
|
dashboard: { |
||||
|
welcome: 'Welcome, {name}', |
||||
|
readyBadge: 'Ready for Development', |
||||
|
welcomeSubtitle: 'Aqila admin panel is ready for your new widgets, tables, and modules.', |
||||
|
cleanBoardTitle: 'Clean Dashboard Ready for Development', |
||||
|
cleanBoardDescription: |
||||
|
'All mock data and dummy UIs have been cleaned up. You can build your new modules using UI components and connect directly to Aqila database and backend.', |
||||
|
}, |
||||
|
serverStatus: { |
||||
|
title: 'System & Server Status', |
||||
|
description: 'Server connection summary, API configuration, and account details', |
||||
|
backendStatus: 'Django Server Status (Backend)', |
||||
|
connected: 'Online & Connected', |
||||
|
checking: 'Checking...', |
||||
|
disconnected: 'Disconnected', |
||||
|
recheck: 'Re-check', |
||||
|
rechecking: 'Testing...', |
||||
|
recheckFull: 'Re-check Server', |
||||
|
apiConfigTitle: 'API & Server Configuration', |
||||
|
targetServer: 'Target Server', |
||||
|
apiPrefix: 'API Prefix', |
||||
|
authHeader: 'Auth Header', |
||||
|
currentUserTitle: 'Current User Account', |
||||
|
roleSuperuser: 'Super Administrator (Superuser)', |
||||
|
roleStaff: 'System Administrator (Staff)', |
||||
|
roleUser: 'User', |
||||
|
fullName: 'Full Name:', |
||||
|
email: 'Email:', |
||||
|
userId: 'User ID:', |
||||
|
connectionStable: 'Connection to server is stable', |
||||
|
connectionTesting: 'Testing connection...', |
||||
|
connectionUnreachable: 'Server is unreachable', |
||||
|
}, |
||||
|
globalSearch: { |
||||
|
placeholder: 'Search pages, actions, or commands... (Ctrl+K)', |
||||
|
empty: 'No results found.', |
||||
|
systemSections: 'System Sections', |
||||
|
toggleTheme: 'Toggle Theme', |
||||
|
toggleThemeDesc: 'Switch theme between dark and light mode', |
||||
|
logoutAccount: 'Logout from account', |
||||
|
}, |
||||
|
common: { |
||||
|
save: 'Save Changes', |
||||
|
cancel: 'Cancel', |
||||
|
confirm: 'Confirm', |
||||
|
delete: 'Delete', |
||||
|
edit: 'Edit', |
||||
|
close: 'Close', |
||||
|
back: 'Back', |
||||
|
refresh: 'Refresh', |
||||
|
loading: 'Loading...', |
||||
|
status: 'Status', |
||||
|
actions: 'Actions', |
||||
|
all: 'All', |
||||
|
active: 'Active', |
||||
|
inactive: 'Inactive', |
||||
|
noData: 'No records found.', |
||||
|
pageOf: 'Page {current} of {total}', |
||||
|
success: 'Operation completed successfully.', |
||||
|
error: 'Server connection error.', |
||||
|
retry: 'Retry', |
||||
|
previous: 'Previous', |
||||
|
next: 'Next', |
||||
|
showing: 'Showing', |
||||
|
to: 'to', |
||||
|
of: 'of', |
||||
|
testSyncNotice: 'This is a test message for language synchronization verification.', |
||||
|
deleteConfirmTitle: 'Are you sure you want to delete this item?', |
||||
|
deleteConfirmDesc: 'This action cannot be undone and the record will be permanently deleted.', |
||||
|
yesDelete: 'Yes, Delete', |
||||
|
deleting: 'Deleting...', |
||||
|
filter: 'Filter', |
||||
|
search: 'Search...', |
||||
|
export: 'Export', |
||||
|
import: 'Import', |
||||
|
create: 'Create', |
||||
|
add: 'Add', |
||||
|
view: 'View', |
||||
|
details: 'Details', |
||||
|
operations: 'Operations', |
||||
|
enabled: 'Enabled', |
||||
|
disabled: 'Disabled', |
||||
|
unknown: 'Unknown', |
||||
|
days: '{count} Days', |
||||
|
dayOne: '1 Day', |
||||
|
}, |
||||
|
tours: { |
||||
|
title: 'Tour Management', |
||||
|
subtitle: 'Live monitoring of sales, travel itineraries, passengers, pricing, and multi-language translations', |
||||
|
totalRegistered: '{count} Tours Registered', |
||||
|
ongoingTitle: 'Ongoing Tours', |
||||
|
ongoingSubtitle: 'Live tracking of ongoing trips, daily itinerary schedules, current stage position, and passengers', |
||||
|
totalOngoing: '{count} Active Ongoing Tours', |
||||
|
ordersTitle: 'Tour Orders & Bookings', |
||||
|
ordersSubtitle: 'Order tracking, payment monitoring, document validation, and traveler deposit receipts', |
||||
|
totalOrders: 'Total Registered Orders', |
||||
|
approvedBookings: 'Approved Bookings', |
||||
|
pendingReviewOrders: 'Pending Receipt Review', |
||||
|
searchOrdersPlaceholder: 'Search orders (Passenger name, phone, order ID)...', |
||||
|
filterSaleStatus: 'Sale Status', |
||||
|
filterTripStatus: 'Trip Status', |
||||
|
filterOrderStatus: 'Order Status', |
||||
|
createTour: 'Create New Tour', |
||||
|
tourDetails: 'Tour Details', |
||||
|
manageTranslations: 'Manage Translations (5 Languages)', |
||||
|
tabOverview: 'Specifications', |
||||
|
tabItinerary: 'Itinerary', |
||||
|
tabPassengers: 'Passengers', |
||||
|
tabFeatures: 'Amenities', |
||||
|
saleAvailable: 'Available', |
||||
|
saleSoldOut: 'Sold Out', |
||||
|
saleNoShow: 'Hidden', |
||||
|
saleUnknown: 'Unknown', |
||||
|
tripPending: 'Upcoming', |
||||
|
tripTraveling: 'Ongoing', |
||||
|
tripFinished: 'Completed', |
||||
|
orderApproved: 'Approved', |
||||
|
orderAwaitingPayment: 'Awaiting Payment', |
||||
|
orderPending: 'Pending Receipt Review', |
||||
|
orderRejected: 'Rejected', |
||||
|
orderExpired: 'Expired', |
||||
|
countryIraq: 'Iraq', |
||||
|
countryIran: 'Iran', |
||||
|
countrySaudi: 'Saudi Arabia', |
||||
|
countrySyria: 'Syria', |
||||
|
countryOman: 'Oman', |
||||
|
}, |
||||
|
services: { |
||||
|
title: 'Services Center', |
||||
|
subtitle: 'Management of pilgrimage services, SIM cards, Zayer guide, exchange, store, and religious rituals', |
||||
|
allServices: 'All Services', |
||||
|
searchPlaceholder: 'Search services...', |
||||
|
simcardTitle: 'SIM Card', |
||||
|
simcardDesc: 'Internet packages, international SIM cards, and traveler orders (Zain, Asiacell, Korek, STC)', |
||||
|
zayerGuideTitle: 'Zayer Guide', |
||||
|
zayerGuideDesc: 'Holy shrines, historical sites, hospitals, mawakib, and city locations', |
||||
|
exchangeTitle: 'Online Exchange', |
||||
|
exchangeDesc: 'Exchange rates, currency requests, cash reserves, and traveler transfers (USD, IQD, IRR)', |
||||
|
duasTitle: 'Duas & Ziyarat', |
||||
|
duasDesc: 'Mafatih al-Jinan bank, audios, translations, and authentic ziyarats', |
||||
|
categoriesTitle: 'Categories', |
||||
|
categoriesDesc: 'Management of religious, shrine, store, and app content categories', |
||||
|
citiesTitle: 'Holy Cities', |
||||
|
citiesDesc: 'Pilgrimage cities (Najaf, Karbala, Kadhimiya, Samarra, Mashhad, Qom, Mecca, Medina)', |
||||
|
storeTitle: 'Massoumah Store', |
||||
|
storeDesc: 'Massoumah online store products, souvenirs, inventory, and order fulfillment', |
||||
|
costEstimateTitle: 'Cost Estimate', |
||||
|
costEstimateDesc: 'Estimation of total pilgrimage trip costs according to season, services, and hotel class', |
||||
|
supportTitle: 'Support', |
||||
|
supportDesc: 'Direct ticketing system, user requests, and operator responses', |
||||
|
faqTitle: 'FAQ', |
||||
|
faqDesc: 'Frequently asked questions bank, travel guides, and religious rules', |
||||
|
}, |
||||
|
billing: { |
||||
|
title: 'Invoices & Billing Management', |
||||
|
description: 'Review bank receipts, approve or reject payments, and track invoices across Aqila services', |
||||
|
totalInvoices: 'Total Invoices', |
||||
|
pendingReview: 'Pending Receipt Review', |
||||
|
awaitingPayment: 'Awaiting Customer Payment', |
||||
|
approvedPayments: 'Approved Payments', |
||||
|
rejectedOrExpired: 'Rejected / Expired', |
||||
|
searchPlaceholder: 'Search invoices (Customer name, email, card number, invoice ID)...', |
||||
|
statusFilter: 'Invoice Status', |
||||
|
serviceFilter: 'Service Type', |
||||
|
clearFilters: 'Clear Filters', |
||||
|
invoiceList: 'Invoice List', |
||||
|
customer: 'Customer', |
||||
|
amount: 'Amount', |
||||
|
service: 'Service', |
||||
|
date: 'Issue Date', |
||||
|
receipt: 'Payment Receipt', |
||||
|
hasReceipt: 'View Receipt', |
||||
|
noReceipt: 'None', |
||||
|
approve: 'Approve Payment', |
||||
|
reject: 'Reject Invoice', |
||||
|
rejectTitle: 'Reject Invoice', |
||||
|
rejectReason: 'Rejection Reason / Bank Receipt:', |
||||
|
rejectReasonPlaceholder: 'e.g., Unreadable receipt, amount mismatch, invalid transaction reference...', |
||||
|
rejectNotice: 'This explanation will be displayed to the traveler in their invoice details.', |
||||
|
submitReject: 'Submit & Reject Invoice', |
||||
|
submitting: 'Submitting...', |
||||
|
statusPending: 'Pending Receipt Review', |
||||
|
statusAwaiting: 'Awaiting Payment', |
||||
|
statusApproved: 'Payment Approved', |
||||
|
statusRejected: 'Rejected', |
||||
|
statusExpired: 'Expired', |
||||
|
invoice: 'Invoice', |
||||
|
invoices: 'Invoices', |
||||
|
id: 'ID', |
||||
|
viewDetails: 'View Details', |
||||
|
viewReceipt: 'View Receipt', |
||||
|
noReceiptUploaded: 'No receipt uploaded', |
||||
|
serviceTour: 'Pilgrimage Tours', |
||||
|
serviceSimcard: 'SIM Card', |
||||
|
serviceShop: 'Massoumah Store', |
||||
|
serviceExchange: 'Exchange (Tasreef)', |
||||
|
serviceCustomTrip: 'Custom Trip', |
||||
|
allStatuses: 'All Statuses', |
||||
|
allServices: 'All Services', |
||||
|
noFactorsFound: 'No invoices found.', |
||||
|
noFactorsFilter: 'No records match current filters. You can clear filters.', |
||||
|
noFactorsEmpty: 'No invoices have been issued in the system yet.', |
||||
|
confirmClearReceipt: 'Are you sure you want to remove the uploaded receipt image?', |
||||
|
receiptClearedSuccess: 'Payment receipt cleared successfully.', |
||||
|
tabAll: 'All Transactions', |
||||
|
tabTour: 'Tour Orders & Bookings', |
||||
|
tabSimcard: 'SIM Cards', |
||||
|
tabExchange: 'Currency & Exchange', |
||||
|
tabShop: 'Souvenir Store', |
||||
|
tabCustomTrip: 'Custom Trips', |
||||
|
coreTourBadge: 'Primary Core', |
||||
|
liveStatus: 'Live Status', |
||||
|
quickFilter: 'Status Filter', |
||||
|
}, |
||||
|
languages: { |
||||
|
fa: 'فارسی', |
||||
|
ar: 'العربية', |
||||
|
en: 'English', |
||||
|
}, |
||||
|
} |
||||
|
|
||||
|
export const faLocale = { |
||||
|
navigation: { |
||||
|
brand: 'پنل مدیریت عقیله', |
||||
|
brandShort: 'عقیله', |
||||
|
dashboard: 'داشبورد', |
||||
|
dashboardTitle: 'داشبورد مدیریت', |
||||
|
tours: 'تورها', |
||||
|
allTours: 'فهرست همه تورها', |
||||
|
ongoingTours: 'تورهای در حال برگزاری', |
||||
|
tourOrders: 'سفارشات و رزروها', |
||||
|
services: 'مرکز خدمات (همه)', |
||||
|
simcard: 'سیمکارت (Simcard)', |
||||
|
zayerGuide: 'راهنمای زائر (Zayer Guide)', |
||||
|
exchange: 'صرافی آنلاین (Exchange)', |
||||
|
duas: 'ادعیه و زیارات (Duas)', |
||||
|
duasList: 'ادعیه و زیارات', |
||||
|
categories: 'دستهبندیها', |
||||
|
cities: 'شهرهای زیارتی', |
||||
|
store: 'فروشگاه معصومه (Store)', |
||||
|
storeProducts: 'محصولات', |
||||
|
storeCategories: 'دستهبندیها', |
||||
|
costEstimate: 'تخمین هزینه (Cost Estimate)', |
||||
|
support: 'پشتیبانی (Support)', |
||||
|
supporters: 'پشتیبانها (Supporters)', |
||||
|
faq: 'سوالات متداول (FAQ)', |
||||
|
faqCategories: 'دستهبندیهای موضوعی', |
||||
|
faqQuestions: 'پرسش و پاسخها', |
||||
|
consultant: 'پشتیبانی (Support)', |
||||
|
billing: 'صورتحسابها و مالی', |
||||
|
settings: 'تنظیمات', |
||||
|
logout: 'خروج از سیستم', |
||||
|
soon: 'بهزودی', |
||||
|
adminRole: 'مدیر کل سیستم', |
||||
|
}, |
||||
|
topbar: { |
||||
|
serverOnline: 'سرور متصل است', |
||||
|
serverOffline: 'قطع ارتباط با سرور', |
||||
|
theme: 'تغییر تم', |
||||
|
language: 'تغییر زبان', |
||||
|
selectLanguage: 'انتخاب زبان سامانه', |
||||
|
search: 'جستجو...', |
||||
|
}, |
||||
|
auth: { |
||||
|
loginTitle: 'ورود به پنل مدیریت و داشبورد', |
||||
|
loginDescription: 'برای دسترسی به پرتال مدیریت، اطلاعات ورود خود را وارد نمایید', |
||||
|
demoBoxTitle: 'حساب آزمایشی آماده:', |
||||
|
autoFill: 'پر کردن خودکار', |
||||
|
emailLabel: 'ایمیل حساب کاربری', |
||||
|
emailPlaceholder: '[email protected]', |
||||
|
passwordLabel: 'رمز عبور', |
||||
|
passwordPlaceholder: '••••••••', |
||||
|
showPassword: 'نمایش رمز', |
||||
|
hidePassword: 'مخفیکردن رمز', |
||||
|
submitLogin: 'ورود به حساب کاربری', |
||||
|
loggingIn: 'در حال ورود...', |
||||
|
loginFailed: 'ورود ناموفق بود. دوباره تلاش کنید.', |
||||
|
footerNote: 'پشتیبانی از قالبهای سفارشی و اتصال مستقیم به API', |
||||
|
}, |
||||
|
dashboard: { |
||||
|
welcome: 'خوش آمدید، {name}', |
||||
|
readyBadge: 'آماده توسعه', |
||||
|
welcomeSubtitle: 'پنل مدیریت عقیله آماده اضافه کردن ویجتها، جداول و ماژولهای جدید شماست.', |
||||
|
cleanBoardTitle: 'داشبورد تمیز و آماده توسعه', |
||||
|
cleanBoardDescription: |
||||
|
'تمام اطلاعات و یوآیهای ساختگی حذف شدند. میتوانید ماژولهای جدید خود را با کامپوننتهای آماده UI پیادهسازی و مستقیماً به دیتابیس و بکاند عقیله متصل نمایید.', |
||||
|
}, |
||||
|
serverStatus: { |
||||
|
title: 'وضعیت سیستم و سرور', |
||||
|
description: 'خلاصه ارتباط سرور، پیکربندی API و اطلاعات حساب', |
||||
|
backendStatus: 'وضعیت سرور جنگو (Backend)', |
||||
|
connected: 'آنلاین و متصل', |
||||
|
checking: 'در حال بررسی...', |
||||
|
disconnected: 'قطع ارتباط', |
||||
|
recheck: 'بررسی مجدد', |
||||
|
rechecking: 'در حال تست...', |
||||
|
recheckFull: 'بررسی مجدد سرور', |
||||
|
apiConfigTitle: 'پیکربندی API و سرور', |
||||
|
targetServer: 'سرور هدف', |
||||
|
apiPrefix: 'پیشوند API', |
||||
|
authHeader: 'هدر احراز هویت', |
||||
|
currentUserTitle: 'اطلاعات حساب کاربری جاری', |
||||
|
roleSuperuser: 'مدیر ارشد (Superuser)', |
||||
|
roleStaff: 'مدیر سیستم (Staff)', |
||||
|
roleUser: 'کاربر', |
||||
|
fullName: 'نام و نام خانوادگی:', |
||||
|
email: 'ایمیل:', |
||||
|
userId: 'شناسه کاربری (ID):', |
||||
|
connectionStable: 'ارتباط با سرور پایدار است', |
||||
|
connectionTesting: 'در حال آزمایش اتصال...', |
||||
|
connectionUnreachable: 'سرور در دسترس نیست', |
||||
|
}, |
||||
|
globalSearch: { |
||||
|
placeholder: 'جستجوی صفحات، عملیاتها یا فرمانها... (Ctrl+K)', |
||||
|
empty: 'هیچ نتیجهای یافت نشد.', |
||||
|
systemSections: 'بخشهای سیستم', |
||||
|
toggleTheme: 'تغییر پوسته (Theme)', |
||||
|
toggleThemeDesc: 'تغییر تم به حالت تیره یا روشن', |
||||
|
logoutAccount: 'خروج از حساب کاربری', |
||||
|
}, |
||||
|
common: { |
||||
|
save: 'ذخیره تغییرات', |
||||
|
cancel: 'انصراف', |
||||
|
confirm: 'تایید', |
||||
|
delete: 'حذف', |
||||
|
edit: 'ویرایش', |
||||
|
close: 'بستن', |
||||
|
back: 'بازگشت', |
||||
|
refresh: 'بهروزرسانی', |
||||
|
loading: 'در حال بارگذاری...', |
||||
|
status: 'وضعیت', |
||||
|
actions: 'عملیات', |
||||
|
all: 'همه', |
||||
|
active: 'فعال', |
||||
|
inactive: 'غیرفعال', |
||||
|
noData: 'موردی برای نمایش یافت نشد.', |
||||
|
pageOf: 'صفحه {current} از {total}', |
||||
|
success: 'عملیات با موفقیت انجام شد.', |
||||
|
error: 'خطا در برقراری ارتباط با سرور.', |
||||
|
retry: 'تلاش مجدد', |
||||
|
previous: 'قبلی', |
||||
|
next: 'بعدی', |
||||
|
showing: 'نمایش', |
||||
|
to: 'تا', |
||||
|
of: 'از', |
||||
|
testSyncNotice: 'این یک پیام آزمایشی برای تست هماهنگی زبانهاست', |
||||
|
deleteConfirmTitle: 'آیا از حذف این مورد اطمینان دارید؟', |
||||
|
deleteConfirmDesc: 'این عملیات غیرقابل بازگشت است و رکورد مورد نظر به طور کامل حذف خواهد شد.', |
||||
|
yesDelete: 'بله، حذف شود', |
||||
|
deleting: 'در حال حذف...', |
||||
|
filter: 'فیلتر', |
||||
|
search: 'جستجو...', |
||||
|
export: 'خروجی اکسل', |
||||
|
import: 'ورود اطلاعات', |
||||
|
create: 'ایجاد جدید', |
||||
|
add: 'افزودن', |
||||
|
view: 'مشاهده', |
||||
|
details: 'جزئیات', |
||||
|
operations: 'عملیات', |
||||
|
enabled: 'فعال', |
||||
|
disabled: 'غیرفعال', |
||||
|
unknown: 'نامشخص', |
||||
|
days: '{count} روز', |
||||
|
dayOne: '۱ روز', |
||||
|
}, |
||||
|
tours: { |
||||
|
title: 'مدیریت تورها', |
||||
|
subtitle: 'پایش وضعیت زنده فروش، برنامههای سفر، مسافران، اطلاعات قیمتی و ترجمههای چندزبانه', |
||||
|
totalRegistered: '{count} تور ثبتشده', |
||||
|
ongoingTitle: 'تورهای در حال برگزاری', |
||||
|
ongoingSubtitle: 'پایش زنده وضعیت سفرهای جاری، زمانبندی روزانه (Itinerary)، موقعیت مرحله فعلی و وضعیت مسافران', |
||||
|
totalOngoing: '{count} تور فعال و در جریان', |
||||
|
ordersTitle: 'سفارشات و رزروهای تور', |
||||
|
ordersSubtitle: 'پیگیری سفارشات، نظارت بر پرداختها و اعتبارسنجی مدارک و فیشهای واریزی مسافران', |
||||
|
totalOrders: 'کل سفارشات ثبتشده', |
||||
|
approvedBookings: 'رزروهای تأییدشده', |
||||
|
pendingReviewOrders: 'در انتظار بررسی فیش', |
||||
|
searchOrdersPlaceholder: 'جستجوی سفارشات (نام مسافر، شماره تماس، کد سفارش)...', |
||||
|
filterSaleStatus: 'وضعیت فروش', |
||||
|
filterTripStatus: 'وضعیت سفر', |
||||
|
filterOrderStatus: 'وضعیت سفارش', |
||||
|
createTour: 'ایجاد تور جدید', |
||||
|
tourDetails: 'جزئیات تور', |
||||
|
manageTranslations: 'مدیریت ترجمهها (۵ زبان)', |
||||
|
tabOverview: 'مشخصات', |
||||
|
tabItinerary: 'برنامه سفر', |
||||
|
tabPassengers: 'مسافران', |
||||
|
tabFeatures: 'امکانات', |
||||
|
saleAvailable: 'در دسترس', |
||||
|
saleSoldOut: 'تکمیل ظرفیت', |
||||
|
saleNoShow: 'عدم نمایش', |
||||
|
saleUnknown: 'نامشخص', |
||||
|
tripPending: 'در انتظار اجرا', |
||||
|
tripTraveling: 'در حال برگزاری', |
||||
|
tripFinished: 'پایانیافته', |
||||
|
orderApproved: 'تایید شده', |
||||
|
orderAwaitingPayment: 'در انتظار پرداخت', |
||||
|
orderPending: 'در انتظار بررسی فیش', |
||||
|
orderRejected: 'رد شده', |
||||
|
orderExpired: 'منقضی شده', |
||||
|
countryIraq: 'عراق', |
||||
|
countryIran: 'ایران', |
||||
|
countrySaudi: 'عربستان', |
||||
|
countrySyria: 'سوریه', |
||||
|
countryOman: 'عمان', |
||||
|
}, |
||||
|
services: { |
||||
|
title: 'مرکز خدمات', |
||||
|
subtitle: 'مدیریت جامع خدمات زیارتی، سیمکارت، راهنمای زائر، صرافی، فروشگاه و مناسک', |
||||
|
allServices: 'همه خدمات', |
||||
|
searchPlaceholder: 'جستجوی خدمات...', |
||||
|
simcardTitle: 'سیمکارت', |
||||
|
simcardDesc: 'مدیریت بستههای اینترنت، سیمکارتهای بینالمللی و سفارشهای زائرین (زین، آسیاسل، کورک، STC)', |
||||
|
zayerGuideTitle: 'راهنمای زائر', |
||||
|
zayerGuideDesc: 'بانک جامع اماکن متبرکه، راهنمای اماکن تاریخی، بیمارستانها، مواکب و موقعیت مکانی شهرها', |
||||
|
exchangeTitle: 'صرافی آنلاین', |
||||
|
exchangeDesc: 'نرخ لحظهای ارزها، درخواستهای ارزی، مدیریت موجودی نقدی و حوالههای زائران (دلار، دینار، تومان)', |
||||
|
duasTitle: 'ادعیه و زیارات', |
||||
|
duasDesc: 'بانک مفاتیحالجنان، ادعیه صوتی، ترجمه و شرح متون ادعیه و زیارات معتبر', |
||||
|
categoriesTitle: 'دستهبندیها', |
||||
|
categoriesDesc: 'مدیریت دستهبندیهای موضوعی خدمات، اماکن، فروشگاه و محتواهای اپلیکیشن', |
||||
|
citiesTitle: 'شهرهای زیارتی', |
||||
|
citiesDesc: 'شهرهای زیارتی (نجف، کربلا، کاظمین، سامرا، مشهد، قم، مکه، مدینه)', |
||||
|
storeTitle: 'فروشگاه معصومه', |
||||
|
storeDesc: 'محصولات فروشگاه آنلاین معصومه، سوغات زیارتی، مدیریت انبار و سفارشات خرید', |
||||
|
costEstimateTitle: 'تخمین هزینه', |
||||
|
costEstimateDesc: 'محاسبه آنلاین هزینههای سفر انفرادی و خانوادگی به تفکیک فصل، خدمات و سطح هتل', |
||||
|
supportTitle: 'پشتیبانی', |
||||
|
supportDesc: 'سیستم تیکتینگ مستقیم، پشتیبانی از زائران و مدیریت پاسخگویی اپراتورها', |
||||
|
faqTitle: 'سوالات متداول', |
||||
|
faqDesc: 'بانک پرسش و پاسخهای پرتکرار زائرین، راهنمای سفر و احکام شرعی', |
||||
|
}, |
||||
|
billing: { |
||||
|
title: 'مدیریت صورتحسابها و فاکتورها', |
||||
|
description: 'بررسی فیشهای بانکی، تایید یا رد پرداختها و پیگیری ریز فاکتورهای ۵ سرویس سامانه عقیله', |
||||
|
totalInvoices: 'کل صورتحسابها', |
||||
|
pendingReview: 'در انتظار بررسی فیش', |
||||
|
awaitingPayment: 'در انتظار پرداخت مشتری', |
||||
|
approvedPayments: 'پرداختهای تایید شده', |
||||
|
rejectedOrExpired: 'رد شده / منقضی', |
||||
|
searchPlaceholder: 'جستجو در صورتحسابها (نام مشتری، ایمیل، شماره کارت، شماره فاکتور)...', |
||||
|
statusFilter: 'وضعیت صورتحساب', |
||||
|
serviceFilter: 'نوع سرویس', |
||||
|
clearFilters: 'پاک کردن فیلترها', |
||||
|
invoiceList: 'فهرست صورتحسابها', |
||||
|
customer: 'مشتری', |
||||
|
amount: 'مبلغ', |
||||
|
service: 'سرویس', |
||||
|
date: 'تاریخ صدور', |
||||
|
receipt: 'فیش پرداخت', |
||||
|
hasReceipt: 'مشاهده فیش', |
||||
|
noReceipt: 'ندارد', |
||||
|
approve: 'تایید پرداخت', |
||||
|
reject: 'رد فاکتور', |
||||
|
rejectTitle: 'رد صورتحساب', |
||||
|
rejectReason: 'علت رد فاکتور / فیش بانکی:', |
||||
|
rejectReasonPlaceholder: 'مثال: تصویر فیش ناخواناست، مبلغ فیش با فاکتور همخوانی ندارد، کد رهگیری نامعتبر است...', |
||||
|
rejectNotice: 'این توضیح به مسافر در بخش وضعیت فاکتور نمایش داده خواهد شد.', |
||||
|
submitReject: 'ثبت و رد فاکتور', |
||||
|
submitting: 'در حال ثبت...', |
||||
|
statusPending: 'در انتظار بررسی فیش', |
||||
|
statusAwaiting: 'در انتظار پرداخت', |
||||
|
statusApproved: 'پرداخت تایید شده', |
||||
|
statusRejected: 'رد شده', |
||||
|
statusExpired: 'منقضی شده', |
||||
|
invoice: 'صورتحساب', |
||||
|
invoices: 'صورتحسابها', |
||||
|
id: 'شناسه', |
||||
|
viewDetails: 'مشاهده جزئیات', |
||||
|
viewReceipt: 'مشاهده فیش', |
||||
|
noReceiptUploaded: 'فیشی بارگذاری نشده است', |
||||
|
serviceTour: 'تور زیارتی', |
||||
|
serviceSimcard: 'سیمکارت', |
||||
|
serviceShop: 'فروشگاه معصومه', |
||||
|
serviceExchange: 'صرافی (تصریف)', |
||||
|
serviceCustomTrip: 'سفر اختصاصی', |
||||
|
allStatuses: 'همه وضعیتها', |
||||
|
allServices: 'همه سرویسها', |
||||
|
noFactorsFound: 'هیچ صورتحسابی یافت نشد.', |
||||
|
noFactorsFilter: 'رکوردی با فیلترهای فعلی همخوانی ندارد. میتوانید فیلترها را پاک کنید.', |
||||
|
noFactorsEmpty: 'تاکنون هیچ صورتحسابی در سیستم صادر نشده است.', |
||||
|
confirmClearReceipt: 'آیا از حذف تصویر فیش بارگذاری شده اطمینان دارید؟', |
||||
|
receiptClearedSuccess: 'تصویر فیش پرداخت با موفقیت حذف شد.', |
||||
|
tabAll: 'کل تراکنشها', |
||||
|
tabTour: 'سفارشات و رزرو تور', |
||||
|
tabSimcard: 'سیمکارت', |
||||
|
tabExchange: 'ارز و صرافی', |
||||
|
tabShop: 'فروشگاه سوغات', |
||||
|
tabCustomTrip: 'سفرهای اختصاصی', |
||||
|
coreTourBadge: 'هسته اصلی', |
||||
|
liveStatus: 'وضعیت زنده', |
||||
|
quickFilter: 'فیلتر وضعیت', |
||||
|
}, |
||||
|
languages: { |
||||
|
fa: 'فارسی', |
||||
|
ar: 'العربية', |
||||
|
en: 'English', |
||||
|
}, |
||||
|
} |
||||
|
|
||||
|
export const arLocale = { |
||||
|
navigation: { |
||||
|
brand: 'لوحة تحكم عقيلة', |
||||
|
brandShort: 'عقيلة', |
||||
|
dashboard: 'الرئيسية', |
||||
|
dashboardTitle: 'لوحة التحكم', |
||||
|
tours: 'الرحلات', |
||||
|
allTours: 'جميع الرحلات', |
||||
|
ongoingTours: 'الرحلات الجارية', |
||||
|
tourOrders: 'الطلبات والحجوزات', |
||||
|
services: 'مركز الخدمات (الكل)', |
||||
|
simcard: 'شريحة الاتصال (Simcard)', |
||||
|
zayerGuide: 'دليل الزائر (Zayer Guide)', |
||||
|
exchange: 'الصرافة الإلكترونية (Exchange)', |
||||
|
duas: 'الأدعية والزيارات (Duas)', |
||||
|
duasList: 'الأدعية والزيارات', |
||||
|
categories: 'التصنيفات', |
||||
|
cities: 'المدن المقدسة', |
||||
|
store: 'متجر معصومة (Store)', |
||||
|
storeProducts: 'المنتجات', |
||||
|
storeCategories: 'التصنيفات', |
||||
|
costEstimate: 'تقدير التكلفة (Cost Estimate)', |
||||
|
support: 'الدعم الفني (Support)', |
||||
|
supporters: 'فريق الدعم (Supporters)', |
||||
|
faq: 'الأسئلة الشائعة (FAQ)', |
||||
|
faqCategories: 'التصنيفات الموضوعية', |
||||
|
faqQuestions: 'الأسئلة والأجوبة', |
||||
|
consultant: 'الدعم الفني (Support)', |
||||
|
billing: 'الفواتير والمالية', |
||||
|
settings: 'الإعدادات', |
||||
|
logout: 'تسجيل الخروج', |
||||
|
soon: 'قريباً', |
||||
|
adminRole: 'مدير النظام العام', |
||||
|
}, |
||||
|
topbar: { |
||||
|
serverOnline: 'الخادم متصل', |
||||
|
serverOffline: 'انقطع الاتصال بالخادم', |
||||
|
theme: 'المظهر', |
||||
|
language: 'اللغة', |
||||
|
selectLanguage: 'اختر لغة النظام', |
||||
|
search: 'بحث...', |
||||
|
}, |
||||
|
auth: { |
||||
|
loginTitle: 'تسجيل الدخول إلى لوحة الإدارة', |
||||
|
loginDescription: 'أدخل بيانات الاعتماد الخاصة بك للوصول إلى بوابة الإدارة', |
||||
|
demoBoxTitle: 'حساب تجريبي جاهز:', |
||||
|
autoFill: 'تعبئة تلقائية', |
||||
|
emailLabel: 'البريد الإلكتروني للحساب', |
||||
|
emailPlaceholder: '[email protected]', |
||||
|
passwordLabel: 'كلمة المرور', |
||||
|
passwordPlaceholder: '••••••••', |
||||
|
showPassword: 'عرض كلمة المرور', |
||||
|
hidePassword: 'إخفاء كلمة المرور', |
||||
|
submitLogin: 'تسجيل الدخول إلى الحساب', |
||||
|
loggingIn: 'جاري تسجيل الدخول...', |
||||
|
loginFailed: 'فشل تسجيل الدخول. يرجى المحاولة مرة أخرى.', |
||||
|
footerNote: 'يدعم القوالب المخصصة والاتصال المباشر بواجهة برمجة التطبيقات (API)', |
||||
|
}, |
||||
|
dashboard: { |
||||
|
welcome: 'مرحباً، {name}', |
||||
|
readyBadge: 'جاهز للتطوير', |
||||
|
welcomeSubtitle: 'لوحة تحكم عقيلة جاهزة لإضافة أدواتك وجداولك ووحداتك الجديدة.', |
||||
|
cleanBoardTitle: 'لوحة تحكم نظيفة وجاهزة للتطوير', |
||||
|
cleanBoardDescription: |
||||
|
'تم مسح جميع البيانات والواجهات الوهمية. يمكنك بناء وحداتك الجديدة باستخدام مكونات واجهة المستخدم الجاهزة والاتصال مباشرة بقاعدة البيانات وخادم عقيلة.', |
||||
|
}, |
||||
|
serverStatus: { |
||||
|
title: 'حالة النظام والخادم', |
||||
|
description: 'ملخص اتصال الخادم، وتكوين واجهة برمجة التطبيقات وبيانات الحساب', |
||||
|
backendStatus: 'حالة خادم جانغو (Backend)', |
||||
|
connected: 'متصل ونشط', |
||||
|
checking: 'جاري الفحص...', |
||||
|
disconnected: 'انقطع الاتصال', |
||||
|
recheck: 'إعادة الفحص', |
||||
|
rechecking: 'جاري الاختبار...', |
||||
|
recheckFull: 'إعادة فحص الخادم', |
||||
|
apiConfigTitle: 'تكوين واجهة برمجة التطبيقات والخادم', |
||||
|
targetServer: 'الخادم الهدف', |
||||
|
apiPrefix: 'بادئة API', |
||||
|
authHeader: 'ترويسة المصادقة', |
||||
|
currentUserTitle: 'بيانات الحساب الحالي', |
||||
|
roleSuperuser: 'المدير العام (Superuser)', |
||||
|
roleStaff: 'مدير النظام (Staff)', |
||||
|
roleUser: 'مستخدم', |
||||
|
fullName: 'الاسم الكامل:', |
||||
|
email: 'البريد الإلكتروني:', |
||||
|
userId: 'معرف المستخدم (ID):', |
||||
|
connectionStable: 'الاتصال بالخادم مستقر', |
||||
|
connectionTesting: 'جاري اختبار الاتصال...', |
||||
|
connectionUnreachable: 'الخادم غير متاح', |
||||
|
}, |
||||
|
globalSearch: { |
||||
|
placeholder: 'البحث في الصفحات والعمليات والأوامر... (Ctrl+K)', |
||||
|
empty: 'لم يتم العثور على أي نتائج.', |
||||
|
systemSections: 'أقسام النظام', |
||||
|
toggleTheme: 'تغيير السمة (Theme)', |
||||
|
toggleThemeDesc: 'تبديل المظهر بين الوضع الداكن والفاتح', |
||||
|
logoutAccount: 'تسجيل الخروج من الحساب', |
||||
|
}, |
||||
|
common: { |
||||
|
save: 'حفظ التغييرات', |
||||
|
cancel: 'إلغاء', |
||||
|
confirm: 'تأكيد', |
||||
|
delete: 'حذف', |
||||
|
edit: 'تعديل', |
||||
|
close: 'إغلاق', |
||||
|
back: 'رجوع', |
||||
|
refresh: 'تحديث', |
||||
|
loading: 'جاري التحميل...', |
||||
|
status: 'الحالة', |
||||
|
actions: 'الإجراءات', |
||||
|
all: 'الكل', |
||||
|
active: 'نشط', |
||||
|
inactive: 'غير نشط', |
||||
|
noData: 'لا توجد بيانات للعرض.', |
||||
|
pageOf: 'صفحة {current} من {total}', |
||||
|
success: 'تمت العملية بنجاح.', |
||||
|
error: 'حدث خطأ في الاتصال بالخادم.', |
||||
|
retry: 'إعادة المحاولة', |
||||
|
previous: 'السابق', |
||||
|
next: 'التالي', |
||||
|
showing: 'عرض', |
||||
|
to: 'إلى', |
||||
|
of: 'من', |
||||
|
testSyncNotice: 'هذه رسالة تجريبية لاختبار مزامنة اللغات.', |
||||
|
deleteConfirmTitle: 'هل أنت متأكد من حذف هذا العنصر؟', |
||||
|
deleteConfirmDesc: 'هذا الإجراء لا يمكن التراجع عنه وسيتم حذف السجل نهائياً.', |
||||
|
yesDelete: 'نعم، احذف', |
||||
|
deleting: 'جاري الحذف...', |
||||
|
filter: 'تصفية', |
||||
|
search: 'بحث...', |
||||
|
export: 'تصدير إكسل', |
||||
|
import: 'استيراد بيانات', |
||||
|
create: 'إنشاء جديد', |
||||
|
add: 'إضافة', |
||||
|
view: 'عرض', |
||||
|
details: 'تفاصيل', |
||||
|
operations: 'العمليات', |
||||
|
enabled: 'مفعل', |
||||
|
disabled: 'معطل', |
||||
|
unknown: 'غير محدد', |
||||
|
days: '{count} أيام', |
||||
|
dayOne: 'يوم واحد', |
||||
|
}, |
||||
|
tours: { |
||||
|
title: 'إدارة الرحلات', |
||||
|
subtitle: 'متابعة مباشرة لحالة المبيعات وجداول الرحلات والمسافرين وبيانات الأسعار والترجمات متعددة اللغات', |
||||
|
totalRegistered: '{count} رحلة مسجلة', |
||||
|
ongoingTitle: 'الرحلات الجارية', |
||||
|
ongoingSubtitle: 'متابعة مباشرة للرحلات الحالية والجدول اليومي والموقع الحالي وحالة المسافرين', |
||||
|
totalOngoing: '{count} رحلة نشطة وجارية', |
||||
|
ordersTitle: 'طلبات وحجوزات الرحلات', |
||||
|
ordersSubtitle: 'متابعة الطلبات ومراقبة المدفوعات والتحقق من وثائق وإيصالات التحويل للمسافرين', |
||||
|
totalOrders: 'إجمالي الطلبات المسجلة', |
||||
|
approvedBookings: 'الحجوزات المؤكدة', |
||||
|
pendingReviewOrders: 'بانتظار مراجعة الإيصال', |
||||
|
searchOrdersPlaceholder: 'البحث في الطلبات (اسم المسافر، الهاتف، معرف الطلب)...', |
||||
|
filterSaleStatus: 'حالة البيع', |
||||
|
filterTripStatus: 'حالة السفر', |
||||
|
filterOrderStatus: 'حالة الطلب', |
||||
|
createTour: 'إنشاء رحلة جديدة', |
||||
|
tourDetails: 'تفاصيل الرحلة', |
||||
|
manageTranslations: 'إدارة الترجمات (٥ لغات)', |
||||
|
tabOverview: 'المواصفات', |
||||
|
tabItinerary: 'برنامج الرحلة', |
||||
|
tabPassengers: 'المسافرون', |
||||
|
tabFeatures: 'المميزات', |
||||
|
saleAvailable: 'متاح', |
||||
|
saleSoldOut: 'اكتمل العدد', |
||||
|
saleNoShow: 'مخفي', |
||||
|
saleUnknown: 'غير محدد', |
||||
|
tripPending: 'بانتظار الانطلاق', |
||||
|
tripTraveling: 'جارية حالياً', |
||||
|
tripFinished: 'منتهية', |
||||
|
orderApproved: 'تمت الموافقة', |
||||
|
orderAwaitingPayment: 'بانتظار الدفع', |
||||
|
orderPending: 'بانتظار مراجعة الإيصال', |
||||
|
orderRejected: 'مرفوض', |
||||
|
orderExpired: 'منتهي الصلاحية', |
||||
|
countryIraq: 'العراق', |
||||
|
countryIran: 'إيران', |
||||
|
countrySaudi: 'السعودية', |
||||
|
countrySyria: 'سوريا', |
||||
|
countryOman: 'عمان', |
||||
|
}, |
||||
|
services: { |
||||
|
title: 'مركز الخدمات', |
||||
|
subtitle: 'إدارة شاملة لخدمات الزوار والشرائح ودليل الزائر والصرافة والمتجر والمناسك', |
||||
|
allServices: 'جميع الخدمات', |
||||
|
searchPlaceholder: 'البحث في الخدمات...', |
||||
|
simcardTitle: 'شريحة الاتصال', |
||||
|
simcardDesc: 'إدارة باقات الإنترنت والشرائح الدولية وطلبات الزوار (زين، آسیاسیل، كورك، STC)', |
||||
|
zayerGuideTitle: 'دليل الزائر', |
||||
|
zayerGuideDesc: 'دليل شامل للعتبات المقدسة والمعالم التاريخية والمستشفيات والمواكب ومواقع المدن', |
||||
|
exchangeTitle: 'الصرافة الإلكترونية', |
||||
|
exchangeDesc: 'أسعار الصرف المباشرة وطلبات العملات وإدارة السيولة النقدية وحوالات الزوار (دولار، دينار، تومان)', |
||||
|
duasTitle: 'الأدعية والزيارات', |
||||
|
duasDesc: 'بنك مفاتيح الجنان والتسجيلات الصوتية والترجمات وشروح الأدعية والزيارات المعتبرة', |
||||
|
categoriesTitle: 'التصنيفات', |
||||
|
categoriesDesc: 'إدارة التصنيفات الموضوعية للخدمات والأماكن والمتجر ومحتويات التطبيق', |
||||
|
citiesTitle: 'المدن المقدسة', |
||||
|
citiesDesc: 'المدن المقدسة (النجف، كربلاء، الكاظمية، سامراء، مشهد، قم، مكة، المدينة)', |
||||
|
storeTitle: 'متجر معصومة', |
||||
|
storeDesc: 'منتجات متجر معصومة الإلكتروني وهدايا الزيارة وإدارة المخزون وطلبات الشراء', |
||||
|
costEstimateTitle: 'تقدير التكلفة', |
||||
|
costEstimateDesc: 'حساب تكاليف الرحلات الفردية والعائلية حسب الموسم والخدمات ومستوى الفندق', |
||||
|
supportTitle: 'الدعم الفني', |
||||
|
supportDesc: 'نظام التذاكر المباشر ودعم الزوار وإدارة استجابات فريق العمل', |
||||
|
faqTitle: 'الأسئلة الشائعة', |
||||
|
faqDesc: 'بنك الأسئلة المتكررة للزوار وإرشادات السفر والأحكام الشرعية', |
||||
|
}, |
||||
|
billing: { |
||||
|
title: 'إدارة الفواتير والمدفوعات', |
||||
|
description: 'مراجعة إيصالات التحويل البنكي، واعتماد أو رفض المدفوعات ومتابعة تفاصيل فواتير خدمات عقيلة', |
||||
|
totalInvoices: 'إجمالي الفواتير', |
||||
|
pendingReview: 'بانتظار مراجعة الإيصال', |
||||
|
awaitingPayment: 'بانتظار دفع العميل', |
||||
|
approvedPayments: 'المدفوعات المعتمدة', |
||||
|
rejectedOrExpired: 'مرفوض / منتهي الصلاحية', |
||||
|
searchPlaceholder: 'البحث في الفواتير (اسم العميل، البريد، رقم البطاقة، رقم الفاتورة)...', |
||||
|
statusFilter: 'حالة الفاتورة', |
||||
|
serviceFilter: 'نوع الخدمة', |
||||
|
clearFilters: 'إعادة ضبط التصفية', |
||||
|
invoiceList: 'قائمة الفواتير', |
||||
|
customer: 'العميل', |
||||
|
amount: 'المبلغ', |
||||
|
service: 'الخدمة', |
||||
|
date: 'تاريخ الإصدار', |
||||
|
receipt: 'إيصال الدفع', |
||||
|
hasReceipt: 'عرض الإيصال', |
||||
|
noReceipt: 'لا يوجد', |
||||
|
approve: 'اعتماد الدفع', |
||||
|
reject: 'رفض الفاتورة', |
||||
|
rejectTitle: 'رفض الفاتورة', |
||||
|
rejectReason: 'سبب رفض الفاتورة / الإيصال البنكي:', |
||||
|
rejectReasonPlaceholder: 'مثال: صورة الإيصال غير واضحة، المبلغ غير متطابق، الرقم المرجعي غير صالح...', |
||||
|
rejectNotice: 'سيظهر هذا الشرح للمسافر في تفاصيل الفاتورة.', |
||||
|
submitReject: 'تأكيد ورفض الفاتورة', |
||||
|
submitting: 'جاري الإرسال...', |
||||
|
statusPending: 'بانتظار مراجعة الإيصال', |
||||
|
statusAwaiting: 'بانتظار الدفع', |
||||
|
statusApproved: 'تم اعتماد الدفع', |
||||
|
statusRejected: 'مرفوض', |
||||
|
statusExpired: 'منتهي الصلاحية', |
||||
|
invoice: 'فاتورة', |
||||
|
invoices: 'الفواتير', |
||||
|
id: 'المعرف', |
||||
|
viewDetails: 'عرض التفاصيل', |
||||
|
viewReceipt: 'عرض الإيصال', |
||||
|
noReceiptUploaded: 'لم يتم رفع إيصال', |
||||
|
serviceTour: 'رحلة زيارة', |
||||
|
serviceSimcard: 'شريحة اتصال', |
||||
|
serviceShop: 'متجر معصومة', |
||||
|
serviceExchange: 'صرافة (تصريف)', |
||||
|
serviceCustomTrip: 'رحلة مخصصة', |
||||
|
allStatuses: 'جميع الحالات', |
||||
|
allServices: 'جميع الخدمات', |
||||
|
noFactorsFound: 'لم يتم العثور على فواتير.', |
||||
|
noFactorsFilter: 'لا توجد نتائج تطابق معايير التصفية الحالية.', |
||||
|
noFactorsEmpty: 'لم يتم إصدار أي فواتير في النظام بعد.', |
||||
|
confirmClearReceipt: 'هل أنت متأكد من حذف صورة الإيصال المرفوعة؟', |
||||
|
receiptClearedSuccess: 'تم حذف صورة الإيصال بنجاح.', |
||||
|
tabAll: 'جميع المعاملات', |
||||
|
tabTour: 'طلبات وحجوزات الرحلات', |
||||
|
tabSimcard: 'شرائح الاتصال', |
||||
|
tabExchange: 'العملات والصرافة', |
||||
|
tabShop: 'متجر الهدايا', |
||||
|
tabCustomTrip: 'الرحلات الخاصة', |
||||
|
coreTourBadge: 'الخدمة الأساسية', |
||||
|
liveStatus: 'الحالة المباشرة', |
||||
|
quickFilter: 'تصفية الحالة', |
||||
|
}, |
||||
|
languages: { |
||||
|
fa: 'فارسی', |
||||
|
ar: 'العربية', |
||||
|
en: 'English', |
||||
|
}, |
||||
|
} |
||||
|
|
||||
|
function writeJson(filePath, data) { |
||||
|
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf8') |
||||
|
console.log(`✓ Generated: ${filePath}`) |
||||
|
} |
||||
|
|
||||
|
writeJson(path.join(LOCALES_DIR, 'en.json'), enLocale) |
||||
|
writeJson(path.join(LOCALES_DIR, 'fa.json'), faLocale) |
||||
|
writeJson(path.join(LOCALES_DIR, 'ar.json'), arLocale) |
||||
|
|
||||
|
console.log('\n🎉 Successfully synchronized all 3 locale files with en.json as Source of Truth!') |
||||
@ -8,6 +8,7 @@ import { useAuth, useLoginMutation } from '@/features/auth/use-auth' |
|||||
import { ApiError } from '@/services/http' |
import { ApiError } from '@/services/http' |
||||
import { siteConfig } from '@/config/site' |
import { siteConfig } from '@/config/site' |
||||
import { AqilaLogo } from '@/components/AqilaLogo' |
import { AqilaLogo } from '@/components/AqilaLogo' |
||||
|
import { useTranslation } from '@/i18n' |
||||
|
|
||||
function Field({ label, children }: { label: string; children: React.ReactNode }) { |
function Field({ label, children }: { label: string; children: React.ReactNode }) { |
||||
return ( |
return ( |
||||
@ -22,6 +23,7 @@ export default function LoginPage() { |
|||||
const location = useLocation() |
const location = useLocation() |
||||
const { isAuthenticated } = useAuth() |
const { isAuthenticated } = useAuth() |
||||
const loginMutation = useLoginMutation() |
const loginMutation = useLoginMutation() |
||||
|
const { t } = useTranslation() |
||||
|
|
||||
const [email, setEmail] = useState('') |
const [email, setEmail] = useState('') |
||||
const [password, setPassword] = useState('') |
const [password, setPassword] = useState('') |
||||
@ -50,7 +52,7 @@ export default function LoginPage() { |
|||||
loginMutation.error instanceof ApiError |
loginMutation.error instanceof ApiError |
||||
? loginMutation.error.message |
? loginMutation.error.message |
||||
: loginMutation.error |
: loginMutation.error |
||||
? 'ورود ناموفق بود. دوباره تلاش کنید.' |
|
||||
|
? t('auth.loginFailed') |
||||
: null |
: null |
||||
|
|
||||
return ( |
return ( |
||||
@ -67,7 +69,7 @@ export default function LoginPage() { |
|||||
</div> |
</div> |
||||
<div> |
<div> |
||||
<h1 className="text-xl font-black text-foreground">{siteConfig.name}</h1> |
<h1 className="text-xl font-black text-foreground">{siteConfig.name}</h1> |
||||
<p className="text-xs text-grey-3 mt-1">ورود به پنل مدیریت و داشبورد</p> |
|
||||
|
<p className="text-xs text-grey-3 mt-1">{t('auth.loginDescription')}</p> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|
||||
@ -79,7 +81,7 @@ export default function LoginPage() { |
|||||
{/* راهنمای لاگین دمو */} |
{/* راهنمای لاگین دمو */} |
||||
<div className="flex items-center justify-between rounded-xl border border-primary/20 bg-primary/10 p-3 text-xs"> |
<div className="flex items-center justify-between rounded-xl border border-primary/20 bg-primary/10 p-3 text-xs"> |
||||
<div> |
<div> |
||||
<span className="font-bold text-primary block">حساب آزمایشی آماده:</span> |
|
||||
|
<span className="font-bold text-primary block">{t('auth.demoBoxTitle')}</span> |
||||
<span dir="ltr" className="text-[11px] text-grey-2 font-mono">admin@gmail.com / admin</span> |
<span dir="ltr" className="text-[11px] text-grey-2 font-mono">admin@gmail.com / admin</span> |
||||
</div> |
</div> |
||||
<Button |
<Button |
||||
@ -89,31 +91,31 @@ export default function LoginPage() { |
|||||
onClick={fillDemo} |
onClick={fillDemo} |
||||
className="h-7 text-[11px]" |
className="h-7 text-[11px]" |
||||
> |
> |
||||
پر کردن خودکار |
|
||||
|
{t('auth.autoFill')} |
||||
</Button> |
</Button> |
||||
</div> |
</div> |
||||
|
|
||||
<Field label="ایمیل حساب کاربری"> |
|
||||
|
<Field label={t('auth.emailLabel')}> |
||||
<Input |
<Input |
||||
type="email" |
type="email" |
||||
dir="ltr" |
dir="ltr" |
||||
className="text-left" |
className="text-left" |
||||
autoComplete="username" |
autoComplete="username" |
||||
placeholder="[email protected]" |
|
||||
|
placeholder={t('auth.emailPlaceholder')} |
||||
value={email} |
value={email} |
||||
onChange={(e) => setEmail(e.target.value)} |
onChange={(e) => setEmail(e.target.value)} |
||||
autoFocus |
autoFocus |
||||
/> |
/> |
||||
</Field> |
</Field> |
||||
|
|
||||
<Field label="رمز عبور"> |
|
||||
|
<Field label={t('auth.passwordLabel')}> |
||||
<div className="relative"> |
<div className="relative"> |
||||
<Input |
<Input |
||||
type={showPassword ? 'text' : 'password'} |
type={showPassword ? 'text' : 'password'} |
||||
dir="ltr" |
dir="ltr" |
||||
className="text-left pe-11" |
className="text-left pe-11" |
||||
autoComplete="current-password" |
autoComplete="current-password" |
||||
placeholder="••••••••" |
|
||||
|
placeholder={t('auth.passwordPlaceholder')} |
||||
value={password} |
value={password} |
||||
onChange={(e) => setPassword(e.target.value)} |
onChange={(e) => setPassword(e.target.value)} |
||||
/> |
/> |
||||
@ -121,7 +123,7 @@ export default function LoginPage() { |
|||||
type="button" |
type="button" |
||||
onClick={() => setShowPassword((v) => !v)} |
onClick={() => setShowPassword((v) => !v)} |
||||
className="absolute inset-y-0 start-0 flex w-11 items-center justify-center text-grey-3 transition-colors hover:text-grey-1 [&_svg]:size-4" |
className="absolute inset-y-0 start-0 flex w-11 items-center justify-center text-grey-3 transition-colors hover:text-grey-1 [&_svg]:size-4" |
||||
aria-label={showPassword ? 'مخفیکردن رمز' : 'نمایش رمز'} |
|
||||
|
aria-label={showPassword ? t('auth.hidePassword') : t('auth.showPassword')} |
||||
tabIndex={-1} |
tabIndex={-1} |
||||
> |
> |
||||
<Ic name={showPassword ? 'eyeOff' : 'eye'} /> |
<Ic name={showPassword ? 'eyeOff' : 'eye'} /> |
||||
@ -142,14 +144,14 @@ export default function LoginPage() { |
|||||
className="w-full font-bold" |
className="w-full font-bold" |
||||
disabled={!valid} |
disabled={!valid} |
||||
isLoading={loginMutation.isPending} |
isLoading={loginMutation.isPending} |
||||
loadingText="در حال ورود…" |
|
||||
|
loadingText={t('auth.loggingIn')} |
||||
> |
> |
||||
ورود به حساب کاربری |
|
||||
|
{t('auth.submitLogin')} |
||||
</Button> |
</Button> |
||||
</form> |
</form> |
||||
|
|
||||
<p className="mt-4 text-center text-xs text-grey-4"> |
<p className="mt-4 text-center text-xs text-grey-4"> |
||||
پشتیبانی از قالبهای سفارشی و اتصال مستقیم به API |
|
||||
|
{t('auth.footerNote')} |
||||
</p> |
</p> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|||||
870
src/features/services/components/DuasServiceView.tsx
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,12 @@ |
|||||
|
import { describe, it, expect } from 'vitest' |
||||
|
import { validateTranslations } from '../../../scripts/check-translations.js' |
||||
|
|
||||
|
describe('Locale Translations Synchronization', () => { |
||||
|
it('should ensure fa.json, en.json, and ar.json have identical keys and no empty values', () => { |
||||
|
const result = validateTranslations() |
||||
|
expect(result.success).toBe(true) |
||||
|
if (!result.success) { |
||||
|
expect(result.errors).toEqual([]) |
||||
|
} |
||||
|
}) |
||||
|
}) |
||||
@ -1,15 +1,15 @@ |
|||||
{ |
{ |
||||
"navigation": { |
"navigation": { |
||||
"brand": "لوحة إدارة عقيلة", |
|
||||
|
"brand": "لوحة تحكم عقيلة", |
||||
"brandShort": "عقيلة", |
"brandShort": "عقيلة", |
||||
"dashboard": "لوحة القيادة", |
|
||||
"dashboardTitle": "لوحة إدارة النظام", |
|
||||
"tours": "الجولات", |
|
||||
"allTours": "جميع الجولات", |
|
||||
"ongoingTours": "الجولات الجارية", |
|
||||
|
"dashboard": "الرئيسية", |
||||
|
"dashboardTitle": "لوحة التحكم", |
||||
|
"tours": "الرحلات", |
||||
|
"allTours": "جميع الرحلات", |
||||
|
"ongoingTours": "الرحلات الجارية", |
||||
"tourOrders": "الطلبات والحجوزات", |
"tourOrders": "الطلبات والحجوزات", |
||||
"services": "مركز الخدمات (الكل)", |
"services": "مركز الخدمات (الكل)", |
||||
"simcard": "شرائح الاتصال (Simcard)", |
|
||||
|
"simcard": "شريحة الاتصال (Simcard)", |
||||
"zayerGuide": "دليل الزائر (Zayer Guide)", |
"zayerGuide": "دليل الزائر (Zayer Guide)", |
||||
"exchange": "الصرافة الإلكترونية (Exchange)", |
"exchange": "الصرافة الإلكترونية (Exchange)", |
||||
"duas": "الأدعية والزيارات (Duas)", |
"duas": "الأدعية والزيارات (Duas)", |
||||
@ -18,28 +18,84 @@ |
|||||
"cities": "المدن المقدسة", |
"cities": "المدن المقدسة", |
||||
"store": "متجر معصومة (Store)", |
"store": "متجر معصومة (Store)", |
||||
"storeProducts": "المنتجات", |
"storeProducts": "المنتجات", |
||||
"storeCategories": "الفئات", |
|
||||
"costEstimate": "تقدير التكاليف (Cost Estimate)", |
|
||||
"support": "الدعم والاستشارات (Support)", |
|
||||
|
"storeCategories": "التصنيفات", |
||||
|
"costEstimate": "تقدير التكلفة (Cost Estimate)", |
||||
|
"support": "الدعم الفني (Support)", |
||||
"supporters": "فريق الدعم (Supporters)", |
"supporters": "فريق الدعم (Supporters)", |
||||
"faq": "الأسئلة الشائعة (FAQ)", |
"faq": "الأسئلة الشائعة (FAQ)", |
||||
"faqCategories": "التصنيفات الموضوعية", |
"faqCategories": "التصنيفات الموضوعية", |
||||
"faqQuestions": "الأسئلة والأجوبة", |
"faqQuestions": "الأسئلة والأجوبة", |
||||
"consultant": "الدعم والاستشارات (Support)", |
|
||||
|
"consultant": "الدعم الفني (Support)", |
||||
"billing": "الفواتير والمالية", |
"billing": "الفواتير والمالية", |
||||
"settings": "الإعدادات", |
"settings": "الإعدادات", |
||||
"logout": "تسجيل الخروج", |
"logout": "تسجيل الخروج", |
||||
"soon": "قريباً", |
"soon": "قريباً", |
||||
"adminRole": "المدير العام للنظام" |
|
||||
|
"adminRole": "مدير النظام العام" |
||||
}, |
}, |
||||
"topbar": { |
"topbar": { |
||||
"serverOnline": "الخادم متصل", |
"serverOnline": "الخادم متصل", |
||||
"serverOffline": "انقطع الاتصال بالخادم", |
"serverOffline": "انقطع الاتصال بالخادم", |
||||
"theme": "المظهر", |
"theme": "المظهر", |
||||
"language": "تغيير اللغة", |
|
||||
|
"language": "اللغة", |
||||
"selectLanguage": "اختر لغة النظام", |
"selectLanguage": "اختر لغة النظام", |
||||
"search": "بحث..." |
"search": "بحث..." |
||||
}, |
}, |
||||
|
"auth": { |
||||
|
"loginTitle": "تسجيل الدخول إلى لوحة الإدارة", |
||||
|
"loginDescription": "أدخل بيانات الاعتماد الخاصة بك للوصول إلى بوابة الإدارة", |
||||
|
"demoBoxTitle": "حساب تجريبي جاهز:", |
||||
|
"autoFill": "تعبئة تلقائية", |
||||
|
"emailLabel": "البريد الإلكتروني للحساب", |
||||
|
"emailPlaceholder": "[email protected]", |
||||
|
"passwordLabel": "كلمة المرور", |
||||
|
"passwordPlaceholder": "••••••••", |
||||
|
"showPassword": "عرض كلمة المرور", |
||||
|
"hidePassword": "إخفاء كلمة المرور", |
||||
|
"submitLogin": "تسجيل الدخول إلى الحساب", |
||||
|
"loggingIn": "جاري تسجيل الدخول...", |
||||
|
"loginFailed": "فشل تسجيل الدخول. يرجى المحاولة مرة أخرى.", |
||||
|
"footerNote": "يدعم القوالب المخصصة والاتصال المباشر بواجهة برمجة التطبيقات (API)" |
||||
|
}, |
||||
|
"dashboard": { |
||||
|
"welcome": "مرحباً، {name}", |
||||
|
"readyBadge": "جاهز للتطوير", |
||||
|
"welcomeSubtitle": "لوحة تحكم عقيلة جاهزة لإضافة أدواتك وجداولك ووحداتك الجديدة.", |
||||
|
"cleanBoardTitle": "لوحة تحكم نظيفة وجاهزة للتطوير", |
||||
|
"cleanBoardDescription": "تم مسح جميع البيانات والواجهات الوهمية. يمكنك بناء وحداتك الجديدة باستخدام مكونات واجهة المستخدم الجاهزة والاتصال مباشرة بقاعدة البيانات وخادم عقيلة." |
||||
|
}, |
||||
|
"serverStatus": { |
||||
|
"title": "حالة النظام والخادم", |
||||
|
"description": "ملخص اتصال الخادم، وتكوين واجهة برمجة التطبيقات وبيانات الحساب", |
||||
|
"backendStatus": "حالة خادم جانغو (Backend)", |
||||
|
"connected": "متصل ونشط", |
||||
|
"checking": "جاري الفحص...", |
||||
|
"disconnected": "انقطع الاتصال", |
||||
|
"recheck": "إعادة الفحص", |
||||
|
"rechecking": "جاري الاختبار...", |
||||
|
"recheckFull": "إعادة فحص الخادم", |
||||
|
"apiConfigTitle": "تكوين واجهة برمجة التطبيقات والخادم", |
||||
|
"targetServer": "الخادم الهدف", |
||||
|
"apiPrefix": "بادئة API", |
||||
|
"authHeader": "ترويسة المصادقة", |
||||
|
"currentUserTitle": "بيانات الحساب الحالي", |
||||
|
"roleSuperuser": "المدير العام (Superuser)", |
||||
|
"roleStaff": "مدير النظام (Staff)", |
||||
|
"roleUser": "مستخدم", |
||||
|
"fullName": "الاسم الكامل:", |
||||
|
"email": "البريد الإلكتروني:", |
||||
|
"userId": "معرف المستخدم (ID):", |
||||
|
"connectionStable": "الاتصال بالخادم مستقر", |
||||
|
"connectionTesting": "جاري اختبار الاتصال...", |
||||
|
"connectionUnreachable": "الخادم غير متاح" |
||||
|
}, |
||||
|
"globalSearch": { |
||||
|
"placeholder": "البحث في الصفحات والعمليات والأوامر... (Ctrl+K)", |
||||
|
"empty": "لم يتم العثور على أي نتائج.", |
||||
|
"systemSections": "أقسام النظام", |
||||
|
"toggleTheme": "تغيير السمة (Theme)", |
||||
|
"toggleThemeDesc": "تبديل المظهر بين الوضع الداكن والفاتح", |
||||
|
"logoutAccount": "تسجيل الخروج من الحساب" |
||||
|
}, |
||||
"common": { |
"common": { |
||||
"save": "حفظ التغييرات", |
"save": "حفظ التغييرات", |
||||
"cancel": "إلغاء", |
"cancel": "إلغاء", |
||||
@ -64,7 +120,93 @@ |
|||||
"next": "التالي", |
"next": "التالي", |
||||
"showing": "عرض", |
"showing": "عرض", |
||||
"to": "إلى", |
"to": "إلى", |
||||
"of": "من" |
|
||||
|
"of": "من", |
||||
|
"testSyncNotice": "هذه رسالة تجريبية لاختبار مزامنة اللغات.", |
||||
|
"deleteConfirmTitle": "هل أنت متأكد من حذف هذا العنصر؟", |
||||
|
"deleteConfirmDesc": "هذا الإجراء لا يمكن التراجع عنه وسيتم حذف السجل نهائياً.", |
||||
|
"yesDelete": "نعم، احذف", |
||||
|
"deleting": "جاري الحذف...", |
||||
|
"filter": "تصفية", |
||||
|
"search": "بحث...", |
||||
|
"export": "تصدير إكسل", |
||||
|
"import": "استيراد بيانات", |
||||
|
"create": "إنشاء جديد", |
||||
|
"add": "إضافة", |
||||
|
"view": "عرض", |
||||
|
"details": "تفاصيل", |
||||
|
"operations": "العمليات", |
||||
|
"enabled": "مفعل", |
||||
|
"disabled": "معطل", |
||||
|
"unknown": "غير محدد", |
||||
|
"days": "{count} أيام", |
||||
|
"dayOne": "يوم واحد" |
||||
|
}, |
||||
|
"tours": { |
||||
|
"title": "إدارة الرحلات", |
||||
|
"subtitle": "متابعة مباشرة لحالة المبيعات وجداول الرحلات والمسافرين وبيانات الأسعار والترجمات متعددة اللغات", |
||||
|
"totalRegistered": "{count} رحلة مسجلة", |
||||
|
"ongoingTitle": "الرحلات الجارية", |
||||
|
"ongoingSubtitle": "متابعة مباشرة للرحلات الحالية والجدول اليومي والموقع الحالي وحالة المسافرين", |
||||
|
"totalOngoing": "{count} رحلة نشطة وجارية", |
||||
|
"ordersTitle": "طلبات وحجوزات الرحلات", |
||||
|
"ordersSubtitle": "متابعة الطلبات ومراقبة المدفوعات والتحقق من وثائق وإيصالات التحويل للمسافرين", |
||||
|
"totalOrders": "إجمالي الطلبات المسجلة", |
||||
|
"approvedBookings": "الحجوزات المؤكدة", |
||||
|
"pendingReviewOrders": "بانتظار مراجعة الإيصال", |
||||
|
"searchOrdersPlaceholder": "البحث في الطلبات (اسم المسافر، الهاتف، معرف الطلب)...", |
||||
|
"filterSaleStatus": "حالة البيع", |
||||
|
"filterTripStatus": "حالة السفر", |
||||
|
"filterOrderStatus": "حالة الطلب", |
||||
|
"createTour": "إنشاء رحلة جديدة", |
||||
|
"tourDetails": "تفاصيل الرحلة", |
||||
|
"manageTranslations": "إدارة الترجمات (٥ لغات)", |
||||
|
"tabOverview": "المواصفات", |
||||
|
"tabItinerary": "برنامج الرحلة", |
||||
|
"tabPassengers": "المسافرون", |
||||
|
"tabFeatures": "المميزات", |
||||
|
"saleAvailable": "متاح", |
||||
|
"saleSoldOut": "اكتمل العدد", |
||||
|
"saleNoShow": "مخفي", |
||||
|
"saleUnknown": "غير محدد", |
||||
|
"tripPending": "بانتظار الانطلاق", |
||||
|
"tripTraveling": "جارية حالياً", |
||||
|
"tripFinished": "منتهية", |
||||
|
"orderApproved": "تمت الموافقة", |
||||
|
"orderAwaitingPayment": "بانتظار الدفع", |
||||
|
"orderPending": "بانتظار مراجعة الإيصال", |
||||
|
"orderRejected": "مرفوض", |
||||
|
"orderExpired": "منتهي الصلاحية", |
||||
|
"countryIraq": "العراق", |
||||
|
"countryIran": "إيران", |
||||
|
"countrySaudi": "السعودية", |
||||
|
"countrySyria": "سوريا", |
||||
|
"countryOman": "عمان" |
||||
|
}, |
||||
|
"services": { |
||||
|
"title": "مركز الخدمات", |
||||
|
"subtitle": "إدارة شاملة لخدمات الزوار والشرائح ودليل الزائر والصرافة والمتجر والمناسك", |
||||
|
"allServices": "جميع الخدمات", |
||||
|
"searchPlaceholder": "البحث في الخدمات...", |
||||
|
"simcardTitle": "شريحة الاتصال", |
||||
|
"simcardDesc": "إدارة باقات الإنترنت والشرائح الدولية وطلبات الزوار (زين، آسیاسیل، كورك، STC)", |
||||
|
"zayerGuideTitle": "دليل الزائر", |
||||
|
"zayerGuideDesc": "دليل شامل للعتبات المقدسة والمعالم التاريخية والمستشفيات والمواكب ومواقع المدن", |
||||
|
"exchangeTitle": "الصرافة الإلكترونية", |
||||
|
"exchangeDesc": "أسعار الصرف المباشرة وطلبات العملات وإدارة السيولة النقدية وحوالات الزوار (دولار، دينار، تومان)", |
||||
|
"duasTitle": "الأدعية والزيارات", |
||||
|
"duasDesc": "بنك مفاتيح الجنان والتسجيلات الصوتية والترجمات وشروح الأدعية والزيارات المعتبرة", |
||||
|
"categoriesTitle": "التصنيفات", |
||||
|
"categoriesDesc": "إدارة التصنيفات الموضوعية للخدمات والأماكن والمتجر ومحتويات التطبيق", |
||||
|
"citiesTitle": "المدن المقدسة", |
||||
|
"citiesDesc": "المدن المقدسة (النجف، كربلاء، الكاظمية، سامراء، مشهد، قم، مكة، المدينة)", |
||||
|
"storeTitle": "متجر معصومة", |
||||
|
"storeDesc": "منتجات متجر معصومة الإلكتروني وهدايا الزيارة وإدارة المخزون وطلبات الشراء", |
||||
|
"costEstimateTitle": "تقدير التكلفة", |
||||
|
"costEstimateDesc": "حساب تكاليف الرحلات الفردية والعائلية حسب الموسم والخدمات ومستوى الفندق", |
||||
|
"supportTitle": "الدعم الفني", |
||||
|
"supportDesc": "نظام التذاكر المباشر ودعم الزوار وإدارة استجابات فريق العمل", |
||||
|
"faqTitle": "الأسئلة الشائعة", |
||||
|
"faqDesc": "بنك الأسئلة المتكررة للزوار وإرشادات السفر والأحكام الشرعية" |
||||
}, |
}, |
||||
"billing": { |
"billing": { |
||||
"title": "إدارة الفواتير والمدفوعات", |
"title": "إدارة الفواتير والمدفوعات", |
||||
@ -73,11 +215,11 @@ |
|||||
"pendingReview": "بانتظار مراجعة الإيصال", |
"pendingReview": "بانتظار مراجعة الإيصال", |
||||
"awaitingPayment": "بانتظار دفع العميل", |
"awaitingPayment": "بانتظار دفع العميل", |
||||
"approvedPayments": "المدفوعات المعتمدة", |
"approvedPayments": "المدفوعات المعتمدة", |
||||
"rejectedOrExpired": "مرفوض / منتهي", |
|
||||
"searchPlaceholder": "البحث في الفواتير (اسم المستخدم، البريد، رقم البطاقة، رقم الفاتورة)...", |
|
||||
|
"rejectedOrExpired": "مرفوض / منتهي الصلاحية", |
||||
|
"searchPlaceholder": "البحث في الفواتير (اسم العميل، البريد، رقم البطاقة، رقم الفاتورة)...", |
||||
"statusFilter": "حالة الفاتورة", |
"statusFilter": "حالة الفاتورة", |
||||
"serviceFilter": "نوع الخدمة", |
"serviceFilter": "نوع الخدمة", |
||||
"clearFilters": "مسح الفلاتر", |
|
||||
|
"clearFilters": "إعادة ضبط التصفية", |
||||
"invoiceList": "قائمة الفواتير", |
"invoiceList": "قائمة الفواتير", |
||||
"customer": "العميل", |
"customer": "العميل", |
||||
"amount": "المبلغ", |
"amount": "المبلغ", |
||||
@ -90,42 +232,42 @@ |
|||||
"reject": "رفض الفاتورة", |
"reject": "رفض الفاتورة", |
||||
"rejectTitle": "رفض الفاتورة", |
"rejectTitle": "رفض الفاتورة", |
||||
"rejectReason": "سبب رفض الفاتورة / الإيصال البنكي:", |
"rejectReason": "سبب رفض الفاتورة / الإيصال البنكي:", |
||||
"rejectReasonPlaceholder": "مثال: الإيصال غير واضح، المبلغ غير مطابق، رقم المعاملة غير صحيح...", |
|
||||
"rejectNotice": "سيتم عرض هذا التوضيح في تطبيق المسافر ضمن تفاصيل الفاتورة.", |
|
||||
"submitReject": "تسجيل ورفض الفاتورة", |
|
||||
"submitting": "جاري التسجيل...", |
|
||||
"statusPending": "قيد مراجعة الإيصال", |
|
||||
|
"rejectReasonPlaceholder": "مثال: صورة الإيصال غير واضحة، المبلغ غير متطابق، الرقم المرجعي غير صالح...", |
||||
|
"rejectNotice": "سيظهر هذا الشرح للمسافر في تفاصيل الفاتورة.", |
||||
|
"submitReject": "تأكيد ورفض الفاتورة", |
||||
|
"submitting": "جاري الإرسال...", |
||||
|
"statusPending": "بانتظار مراجعة الإيصال", |
||||
"statusAwaiting": "بانتظار الدفع", |
"statusAwaiting": "بانتظار الدفع", |
||||
"statusApproved": "تم الدفع والاعتماد", |
|
||||
|
"statusApproved": "تم اعتماد الدفع", |
||||
"statusRejected": "مرفوض", |
"statusRejected": "مرفوض", |
||||
"statusExpired": "منتهي الصلاحية", |
"statusExpired": "منتهي الصلاحية", |
||||
"invoice": "فاتورة", |
"invoice": "فاتورة", |
||||
"invoices": "فواتير", |
|
||||
|
"invoices": "الفواتير", |
||||
"id": "المعرف", |
"id": "المعرف", |
||||
"viewDetails": "عرض التفاصيل", |
"viewDetails": "عرض التفاصيل", |
||||
"viewReceipt": "عرض إيصال الدفع", |
|
||||
|
"viewReceipt": "عرض الإيصال", |
||||
"noReceiptUploaded": "لم يتم رفع إيصال", |
"noReceiptUploaded": "لم يتم رفع إيصال", |
||||
"serviceTour": "جولات الزيارة", |
|
||||
"serviceSimcard": "شرائح الاتصال", |
|
||||
"serviceShop": "متجر الهدايا", |
|
||||
"serviceExchange": "الصرافة (تصريف)", |
|
||||
"serviceCustomTrip": "رحلة خاصة", |
|
||||
|
"serviceTour": "رحلة زيارة", |
||||
|
"serviceSimcard": "شريحة اتصال", |
||||
|
"serviceShop": "متجر معصومة", |
||||
|
"serviceExchange": "صرافة (تصريف)", |
||||
|
"serviceCustomTrip": "رحلة مخصصة", |
||||
"allStatuses": "جميع الحالات", |
"allStatuses": "جميع الحالات", |
||||
"allServices": "جميع الخدمات", |
"allServices": "جميع الخدمات", |
||||
"noFactorsFound": "لم يتم العثور على فواتير.", |
"noFactorsFound": "لم يتم العثور على فواتير.", |
||||
"noFactorsFilter": "لم يتم العثور على نتائج مطابقة للفلاتر الحالية. يمكنك مسح الفلاتر.", |
|
||||
"noFactorsEmpty": "لم تصدر أي فواتير في النظام بعد.", |
|
||||
"confirmClearReceipt": "هل أنت متأكد من حذف صورة الإيصال المرفوعة لهذا الفاتورة؟", |
|
||||
"receiptClearedSuccess": "تم مسح إيصال الدفع بنجاح.", |
|
||||
|
"noFactorsFilter": "لا توجد نتائج تطابق معايير التصفية الحالية.", |
||||
|
"noFactorsEmpty": "لم يتم إصدار أي فواتير في النظام بعد.", |
||||
|
"confirmClearReceipt": "هل أنت متأكد من حذف صورة الإيصال المرفوعة؟", |
||||
|
"receiptClearedSuccess": "تم حذف صورة الإيصال بنجاح.", |
||||
"tabAll": "جميع المعاملات", |
"tabAll": "جميع المعاملات", |
||||
"tabTour": "طلبات وحجوزات الجولات", |
|
||||
|
"tabTour": "طلبات وحجوزات الرحلات", |
||||
"tabSimcard": "شرائح الاتصال", |
"tabSimcard": "شرائح الاتصال", |
||||
"tabExchange": "الصرافة والعملات", |
|
||||
|
"tabExchange": "العملات والصرافة", |
||||
"tabShop": "متجر الهدايا", |
"tabShop": "متجر الهدايا", |
||||
"tabCustomTrip": "الرحلات الخاصة", |
"tabCustomTrip": "الرحلات الخاصة", |
||||
"coreTourBadge": "المحور الأساسي", |
|
||||
"liveStatus": "الحالة اللحظية", |
|
||||
"quickFilter": "فلترة الحالة" |
|
||||
|
"coreTourBadge": "الخدمة الأساسية", |
||||
|
"liveStatus": "الحالة المباشرة", |
||||
|
"quickFilter": "تصفية الحالة" |
||||
}, |
}, |
||||
"languages": { |
"languages": { |
||||
"fa": "فارسی", |
"fa": "فارسی", |
||||
|
|||||
@ -40,6 +40,62 @@ |
|||||
"selectLanguage": "Select System Language", |
"selectLanguage": "Select System Language", |
||||
"search": "Search..." |
"search": "Search..." |
||||
}, |
}, |
||||
|
"auth": { |
||||
|
"loginTitle": "Login to Admin Dashboard", |
||||
|
"loginDescription": "Enter your credentials to access the management portal", |
||||
|
"demoBoxTitle": "Demo Ready Account:", |
||||
|
"autoFill": "Auto Fill", |
||||
|
"emailLabel": "Account Email", |
||||
|
"emailPlaceholder": "[email protected]", |
||||
|
"passwordLabel": "Password", |
||||
|
"passwordPlaceholder": "••••••••", |
||||
|
"showPassword": "Show password", |
||||
|
"hidePassword": "Hide password", |
||||
|
"submitLogin": "Login to Account", |
||||
|
"loggingIn": "Logging in...", |
||||
|
"loginFailed": "Login failed. Please try again.", |
||||
|
"footerNote": "Supports custom templates and direct API connection" |
||||
|
}, |
||||
|
"dashboard": { |
||||
|
"welcome": "Welcome, {name}", |
||||
|
"readyBadge": "Ready for Development", |
||||
|
"welcomeSubtitle": "Aqila admin panel is ready for your new widgets, tables, and modules.", |
||||
|
"cleanBoardTitle": "Clean Dashboard Ready for Development", |
||||
|
"cleanBoardDescription": "All mock data and dummy UIs have been cleaned up. You can build your new modules using UI components and connect directly to Aqila database and backend." |
||||
|
}, |
||||
|
"serverStatus": { |
||||
|
"title": "System & Server Status", |
||||
|
"description": "Server connection summary, API configuration, and account details", |
||||
|
"backendStatus": "Django Server Status (Backend)", |
||||
|
"connected": "Online & Connected", |
||||
|
"checking": "Checking...", |
||||
|
"disconnected": "Disconnected", |
||||
|
"recheck": "Re-check", |
||||
|
"rechecking": "Testing...", |
||||
|
"recheckFull": "Re-check Server", |
||||
|
"apiConfigTitle": "API & Server Configuration", |
||||
|
"targetServer": "Target Server", |
||||
|
"apiPrefix": "API Prefix", |
||||
|
"authHeader": "Auth Header", |
||||
|
"currentUserTitle": "Current User Account", |
||||
|
"roleSuperuser": "Super Administrator (Superuser)", |
||||
|
"roleStaff": "System Administrator (Staff)", |
||||
|
"roleUser": "User", |
||||
|
"fullName": "Full Name:", |
||||
|
"email": "Email:", |
||||
|
"userId": "User ID:", |
||||
|
"connectionStable": "Connection to server is stable", |
||||
|
"connectionTesting": "Testing connection...", |
||||
|
"connectionUnreachable": "Server is unreachable" |
||||
|
}, |
||||
|
"globalSearch": { |
||||
|
"placeholder": "Search pages, actions, or commands... (Ctrl+K)", |
||||
|
"empty": "No results found.", |
||||
|
"systemSections": "System Sections", |
||||
|
"toggleTheme": "Toggle Theme", |
||||
|
"toggleThemeDesc": "Switch theme between dark and light mode", |
||||
|
"logoutAccount": "Logout from account" |
||||
|
}, |
||||
"common": { |
"common": { |
||||
"save": "Save Changes", |
"save": "Save Changes", |
||||
"cancel": "Cancel", |
"cancel": "Cancel", |
||||
@ -64,7 +120,93 @@ |
|||||
"next": "Next", |
"next": "Next", |
||||
"showing": "Showing", |
"showing": "Showing", |
||||
"to": "to", |
"to": "to", |
||||
"of": "of" |
|
||||
|
"of": "of", |
||||
|
"testSyncNotice": "This is a test message for language synchronization verification.", |
||||
|
"deleteConfirmTitle": "Are you sure you want to delete this item?", |
||||
|
"deleteConfirmDesc": "This action cannot be undone and the record will be permanently deleted.", |
||||
|
"yesDelete": "Yes, Delete", |
||||
|
"deleting": "Deleting...", |
||||
|
"filter": "Filter", |
||||
|
"search": "Search...", |
||||
|
"export": "Export", |
||||
|
"import": "Import", |
||||
|
"create": "Create", |
||||
|
"add": "Add", |
||||
|
"view": "View", |
||||
|
"details": "Details", |
||||
|
"operations": "Operations", |
||||
|
"enabled": "Enabled", |
||||
|
"disabled": "Disabled", |
||||
|
"unknown": "Unknown", |
||||
|
"days": "{count} Days", |
||||
|
"dayOne": "1 Day" |
||||
|
}, |
||||
|
"tours": { |
||||
|
"title": "Tour Management", |
||||
|
"subtitle": "Live monitoring of sales, travel itineraries, passengers, pricing, and multi-language translations", |
||||
|
"totalRegistered": "{count} Tours Registered", |
||||
|
"ongoingTitle": "Ongoing Tours", |
||||
|
"ongoingSubtitle": "Live tracking of ongoing trips, daily itinerary schedules, current stage position, and passengers", |
||||
|
"totalOngoing": "{count} Active Ongoing Tours", |
||||
|
"ordersTitle": "Tour Orders & Bookings", |
||||
|
"ordersSubtitle": "Order tracking, payment monitoring, document validation, and traveler deposit receipts", |
||||
|
"totalOrders": "Total Registered Orders", |
||||
|
"approvedBookings": "Approved Bookings", |
||||
|
"pendingReviewOrders": "Pending Receipt Review", |
||||
|
"searchOrdersPlaceholder": "Search orders (Passenger name, phone, order ID)...", |
||||
|
"filterSaleStatus": "Sale Status", |
||||
|
"filterTripStatus": "Trip Status", |
||||
|
"filterOrderStatus": "Order Status", |
||||
|
"createTour": "Create New Tour", |
||||
|
"tourDetails": "Tour Details", |
||||
|
"manageTranslations": "Manage Translations (5 Languages)", |
||||
|
"tabOverview": "Specifications", |
||||
|
"tabItinerary": "Itinerary", |
||||
|
"tabPassengers": "Passengers", |
||||
|
"tabFeatures": "Amenities", |
||||
|
"saleAvailable": "Available", |
||||
|
"saleSoldOut": "Sold Out", |
||||
|
"saleNoShow": "Hidden", |
||||
|
"saleUnknown": "Unknown", |
||||
|
"tripPending": "Upcoming", |
||||
|
"tripTraveling": "Ongoing", |
||||
|
"tripFinished": "Completed", |
||||
|
"orderApproved": "Approved", |
||||
|
"orderAwaitingPayment": "Awaiting Payment", |
||||
|
"orderPending": "Pending Receipt Review", |
||||
|
"orderRejected": "Rejected", |
||||
|
"orderExpired": "Expired", |
||||
|
"countryIraq": "Iraq", |
||||
|
"countryIran": "Iran", |
||||
|
"countrySaudi": "Saudi Arabia", |
||||
|
"countrySyria": "Syria", |
||||
|
"countryOman": "Oman" |
||||
|
}, |
||||
|
"services": { |
||||
|
"title": "Services Center", |
||||
|
"subtitle": "Management of pilgrimage services, SIM cards, Zayer guide, exchange, store, and religious rituals", |
||||
|
"allServices": "All Services", |
||||
|
"searchPlaceholder": "Search services...", |
||||
|
"simcardTitle": "SIM Card", |
||||
|
"simcardDesc": "Internet packages, international SIM cards, and traveler orders (Zain, Asiacell, Korek, STC)", |
||||
|
"zayerGuideTitle": "Zayer Guide", |
||||
|
"zayerGuideDesc": "Holy shrines, historical sites, hospitals, mawakib, and city locations", |
||||
|
"exchangeTitle": "Online Exchange", |
||||
|
"exchangeDesc": "Exchange rates, currency requests, cash reserves, and traveler transfers (USD, IQD, IRR)", |
||||
|
"duasTitle": "Duas & Ziyarat", |
||||
|
"duasDesc": "Mafatih al-Jinan bank, audios, translations, and authentic ziyarats", |
||||
|
"categoriesTitle": "Categories", |
||||
|
"categoriesDesc": "Management of religious, shrine, store, and app content categories", |
||||
|
"citiesTitle": "Holy Cities", |
||||
|
"citiesDesc": "Pilgrimage cities (Najaf, Karbala, Kadhimiya, Samarra, Mashhad, Qom, Mecca, Medina)", |
||||
|
"storeTitle": "Massoumah Store", |
||||
|
"storeDesc": "Massoumah online store products, souvenirs, inventory, and order fulfillment", |
||||
|
"costEstimateTitle": "Cost Estimate", |
||||
|
"costEstimateDesc": "Estimation of total pilgrimage trip costs according to season, services, and hotel class", |
||||
|
"supportTitle": "Support", |
||||
|
"supportDesc": "Direct ticketing system, user requests, and operator responses", |
||||
|
"faqTitle": "FAQ", |
||||
|
"faqDesc": "Frequently asked questions bank, travel guides, and religious rules" |
||||
}, |
}, |
||||
"billing": { |
"billing": { |
||||
"title": "Invoices & Billing Management", |
"title": "Invoices & Billing Management", |
||||
|
|||||
@ -40,6 +40,62 @@ |
|||||
"selectLanguage": "انتخاب زبان سامانه", |
"selectLanguage": "انتخاب زبان سامانه", |
||||
"search": "جستجو..." |
"search": "جستجو..." |
||||
}, |
}, |
||||
|
"auth": { |
||||
|
"loginTitle": "ورود به پنل مدیریت و داشبورد", |
||||
|
"loginDescription": "برای دسترسی به پرتال مدیریت، اطلاعات ورود خود را وارد نمایید", |
||||
|
"demoBoxTitle": "حساب آزمایشی آماده:", |
||||
|
"autoFill": "پر کردن خودکار", |
||||
|
"emailLabel": "ایمیل حساب کاربری", |
||||
|
"emailPlaceholder": "[email protected]", |
||||
|
"passwordLabel": "رمز عبور", |
||||
|
"passwordPlaceholder": "••••••••", |
||||
|
"showPassword": "نمایش رمز", |
||||
|
"hidePassword": "مخفیکردن رمز", |
||||
|
"submitLogin": "ورود به حساب کاربری", |
||||
|
"loggingIn": "در حال ورود...", |
||||
|
"loginFailed": "ورود ناموفق بود. دوباره تلاش کنید.", |
||||
|
"footerNote": "پشتیبانی از قالبهای سفارشی و اتصال مستقیم به API" |
||||
|
}, |
||||
|
"dashboard": { |
||||
|
"welcome": "خوش آمدید، {name}", |
||||
|
"readyBadge": "آماده توسعه", |
||||
|
"welcomeSubtitle": "پنل مدیریت عقیله آماده اضافه کردن ویجتها، جداول و ماژولهای جدید شماست.", |
||||
|
"cleanBoardTitle": "داشبورد تمیز و آماده توسعه", |
||||
|
"cleanBoardDescription": "تمام اطلاعات و یوآیهای ساختگی حذف شدند. میتوانید ماژولهای جدید خود را با کامپوننتهای آماده UI پیادهسازی و مستقیماً به دیتابیس و بکاند عقیله متصل نمایید." |
||||
|
}, |
||||
|
"serverStatus": { |
||||
|
"title": "وضعیت سیستم و سرور", |
||||
|
"description": "خلاصه ارتباط سرور، پیکربندی API و اطلاعات حساب", |
||||
|
"backendStatus": "وضعیت سرور جنگو (Backend)", |
||||
|
"connected": "آنلاین و متصل", |
||||
|
"checking": "در حال بررسی...", |
||||
|
"disconnected": "قطع ارتباط", |
||||
|
"recheck": "بررسی مجدد", |
||||
|
"rechecking": "در حال تست...", |
||||
|
"recheckFull": "بررسی مجدد سرور", |
||||
|
"apiConfigTitle": "پیکربندی API و سرور", |
||||
|
"targetServer": "سرور هدف", |
||||
|
"apiPrefix": "پیشوند API", |
||||
|
"authHeader": "هدر احراز هویت", |
||||
|
"currentUserTitle": "اطلاعات حساب کاربری جاری", |
||||
|
"roleSuperuser": "مدیر ارشد (Superuser)", |
||||
|
"roleStaff": "مدیر سیستم (Staff)", |
||||
|
"roleUser": "کاربر", |
||||
|
"fullName": "نام و نام خانوادگی:", |
||||
|
"email": "ایمیل:", |
||||
|
"userId": "شناسه کاربری (ID):", |
||||
|
"connectionStable": "ارتباط با سرور پایدار است", |
||||
|
"connectionTesting": "در حال آزمایش اتصال...", |
||||
|
"connectionUnreachable": "سرور در دسترس نیست" |
||||
|
}, |
||||
|
"globalSearch": { |
||||
|
"placeholder": "جستجوی صفحات، عملیاتها یا فرمانها... (Ctrl+K)", |
||||
|
"empty": "هیچ نتیجهای یافت نشد.", |
||||
|
"systemSections": "بخشهای سیستم", |
||||
|
"toggleTheme": "تغییر پوسته (Theme)", |
||||
|
"toggleThemeDesc": "تغییر تم به حالت تیره یا روشن", |
||||
|
"logoutAccount": "خروج از حساب کاربری" |
||||
|
}, |
||||
"common": { |
"common": { |
||||
"save": "ذخیره تغییرات", |
"save": "ذخیره تغییرات", |
||||
"cancel": "انصراف", |
"cancel": "انصراف", |
||||
@ -64,7 +120,93 @@ |
|||||
"next": "بعدی", |
"next": "بعدی", |
||||
"showing": "نمایش", |
"showing": "نمایش", |
||||
"to": "تا", |
"to": "تا", |
||||
"of": "از" |
|
||||
|
"of": "از", |
||||
|
"testSyncNotice": "این یک پیام آزمایشی برای تست هماهنگی زبانهاست", |
||||
|
"deleteConfirmTitle": "آیا از حذف این مورد اطمینان دارید؟", |
||||
|
"deleteConfirmDesc": "این عملیات غیرقابل بازگشت است و رکورد مورد نظر به طور کامل حذف خواهد شد.", |
||||
|
"yesDelete": "بله، حذف شود", |
||||
|
"deleting": "در حال حذف...", |
||||
|
"filter": "فیلتر", |
||||
|
"search": "جستجو...", |
||||
|
"export": "خروجی اکسل", |
||||
|
"import": "ورود اطلاعات", |
||||
|
"create": "ایجاد جدید", |
||||
|
"add": "افزودن", |
||||
|
"view": "مشاهده", |
||||
|
"details": "جزئیات", |
||||
|
"operations": "عملیات", |
||||
|
"enabled": "فعال", |
||||
|
"disabled": "غیرفعال", |
||||
|
"unknown": "نامشخص", |
||||
|
"days": "{count} روز", |
||||
|
"dayOne": "۱ روز" |
||||
|
}, |
||||
|
"tours": { |
||||
|
"title": "مدیریت تورها", |
||||
|
"subtitle": "پایش وضعیت زنده فروش، برنامههای سفر، مسافران، اطلاعات قیمتی و ترجمههای چندزبانه", |
||||
|
"totalRegistered": "{count} تور ثبتشده", |
||||
|
"ongoingTitle": "تورهای در حال برگزاری", |
||||
|
"ongoingSubtitle": "پایش زنده وضعیت سفرهای جاری، زمانبندی روزانه (Itinerary)، موقعیت مرحله فعلی و وضعیت مسافران", |
||||
|
"totalOngoing": "{count} تور فعال و در جریان", |
||||
|
"ordersTitle": "سفارشات و رزروهای تور", |
||||
|
"ordersSubtitle": "پیگیری سفارشات، نظارت بر پرداختها و اعتبارسنجی مدارک و فیشهای واریزی مسافران", |
||||
|
"totalOrders": "کل سفارشات ثبتشده", |
||||
|
"approvedBookings": "رزروهای تأییدشده", |
||||
|
"pendingReviewOrders": "در انتظار بررسی فیش", |
||||
|
"searchOrdersPlaceholder": "جستجوی سفارشات (نام مسافر، شماره تماس، کد سفارش)...", |
||||
|
"filterSaleStatus": "وضعیت فروش", |
||||
|
"filterTripStatus": "وضعیت سفر", |
||||
|
"filterOrderStatus": "وضعیت سفارش", |
||||
|
"createTour": "ایجاد تور جدید", |
||||
|
"tourDetails": "جزئیات تور", |
||||
|
"manageTranslations": "مدیریت ترجمهها (۵ زبان)", |
||||
|
"tabOverview": "مشخصات", |
||||
|
"tabItinerary": "برنامه سفر", |
||||
|
"tabPassengers": "مسافران", |
||||
|
"tabFeatures": "امکانات", |
||||
|
"saleAvailable": "در دسترس", |
||||
|
"saleSoldOut": "تکمیل ظرفیت", |
||||
|
"saleNoShow": "عدم نمایش", |
||||
|
"saleUnknown": "نامشخص", |
||||
|
"tripPending": "در انتظار اجرا", |
||||
|
"tripTraveling": "در حال برگزاری", |
||||
|
"tripFinished": "پایانیافته", |
||||
|
"orderApproved": "تایید شده", |
||||
|
"orderAwaitingPayment": "در انتظار پرداخت", |
||||
|
"orderPending": "در انتظار بررسی فیش", |
||||
|
"orderRejected": "رد شده", |
||||
|
"orderExpired": "منقضی شده", |
||||
|
"countryIraq": "عراق", |
||||
|
"countryIran": "ایران", |
||||
|
"countrySaudi": "عربستان", |
||||
|
"countrySyria": "سوریه", |
||||
|
"countryOman": "عمان" |
||||
|
}, |
||||
|
"services": { |
||||
|
"title": "مرکز خدمات", |
||||
|
"subtitle": "مدیریت جامع خدمات زیارتی، سیمکارت، راهنمای زائر، صرافی، فروشگاه و مناسک", |
||||
|
"allServices": "همه خدمات", |
||||
|
"searchPlaceholder": "جستجوی خدمات...", |
||||
|
"simcardTitle": "سیمکارت", |
||||
|
"simcardDesc": "مدیریت بستههای اینترنت، سیمکارتهای بینالمللی و سفارشهای زائرین (زین، آسیاسل، کورک، STC)", |
||||
|
"zayerGuideTitle": "راهنمای زائر", |
||||
|
"zayerGuideDesc": "بانک جامع اماکن متبرکه، راهنمای اماکن تاریخی، بیمارستانها، مواکب و موقعیت مکانی شهرها", |
||||
|
"exchangeTitle": "صرافی آنلاین", |
||||
|
"exchangeDesc": "نرخ لحظهای ارزها، درخواستهای ارزی، مدیریت موجودی نقدی و حوالههای زائران (دلار، دینار، تومان)", |
||||
|
"duasTitle": "ادعیه و زیارات", |
||||
|
"duasDesc": "بانک مفاتیحالجنان، ادعیه صوتی، ترجمه و شرح متون ادعیه و زیارات معتبر", |
||||
|
"categoriesTitle": "دستهبندیها", |
||||
|
"categoriesDesc": "مدیریت دستهبندیهای موضوعی خدمات، اماکن، فروشگاه و محتواهای اپلیکیشن", |
||||
|
"citiesTitle": "شهرهای زیارتی", |
||||
|
"citiesDesc": "شهرهای زیارتی (نجف، کربلا، کاظمین، سامرا، مشهد، قم، مکه، مدینه)", |
||||
|
"storeTitle": "فروشگاه معصومه", |
||||
|
"storeDesc": "محصولات فروشگاه آنلاین معصومه، سوغات زیارتی، مدیریت انبار و سفارشات خرید", |
||||
|
"costEstimateTitle": "تخمین هزینه", |
||||
|
"costEstimateDesc": "محاسبه آنلاین هزینههای سفر انفرادی و خانوادگی به تفکیک فصل، خدمات و سطح هتل", |
||||
|
"supportTitle": "پشتیبانی", |
||||
|
"supportDesc": "سیستم تیکتینگ مستقیم، پشتیبانی از زائران و مدیریت پاسخگویی اپراتورها", |
||||
|
"faqTitle": "سوالات متداول", |
||||
|
"faqDesc": "بانک پرسش و پاسخهای پرتکرار زائرین، راهنمای سفر و احکام شرعی" |
||||
}, |
}, |
||||
"billing": { |
"billing": { |
||||
"title": "مدیریت صورتحسابها و فاکتورها", |
"title": "مدیریت صورتحسابها و فاکتورها", |
||||
@ -74,24 +216,24 @@ |
|||||
"awaitingPayment": "در انتظار پرداخت مشتری", |
"awaitingPayment": "در انتظار پرداخت مشتری", |
||||
"approvedPayments": "پرداختهای تایید شده", |
"approvedPayments": "پرداختهای تایید شده", |
||||
"rejectedOrExpired": "رد شده / منقضی", |
"rejectedOrExpired": "رد شده / منقضی", |
||||
"searchPlaceholder": "جستجو در فاکتورها (نام کاربر، ایمیل، شماره کارت، شماره فاکتور)...", |
|
||||
"statusFilter": "وضعیت فاکتور", |
|
||||
|
"searchPlaceholder": "جستجو در صورتحسابها (نام مشتری، ایمیل، شماره کارت، شماره فاکتور)...", |
||||
|
"statusFilter": "وضعیت صورتحساب", |
||||
"serviceFilter": "نوع سرویس", |
"serviceFilter": "نوع سرویس", |
||||
"clearFilters": "پاکسازی فیلترها", |
|
||||
"invoiceList": "فهرست فاکتورها", |
|
||||
|
"clearFilters": "پاک کردن فیلترها", |
||||
|
"invoiceList": "فهرست صورتحسابها", |
||||
"customer": "مشتری", |
"customer": "مشتری", |
||||
"amount": "مبلغ", |
"amount": "مبلغ", |
||||
"service": "سرویس", |
"service": "سرویس", |
||||
"date": "تاریخ صدور", |
"date": "تاریخ صدور", |
||||
"receipt": "فیش پرداختی", |
|
||||
|
"receipt": "فیش پرداخت", |
||||
"hasReceipt": "مشاهده فیش", |
"hasReceipt": "مشاهده فیش", |
||||
"noReceipt": "فاقد فیش", |
|
||||
|
"noReceipt": "ندارد", |
||||
"approve": "تایید پرداخت", |
"approve": "تایید پرداخت", |
||||
"reject": "رد صورتحساب", |
|
||||
|
"reject": "رد فاکتور", |
||||
"rejectTitle": "رد صورتحساب", |
"rejectTitle": "رد صورتحساب", |
||||
"rejectReason": "دلیل رد صورتحساب / فیش پرداختی:", |
|
||||
"rejectReasonPlaceholder": "مثال: فیش ناخوانا است، مبلغ واریزی مغایرت دارد، شماره رهگیری نامعتبر است...", |
|
||||
"rejectNotice": "این توضیحات در اپلیکیشن مسافر / کلاینت در بخش جزئیات صورتحساب نمایش داده میشود.", |
|
||||
|
"rejectReason": "علت رد فاکتور / فیش بانکی:", |
||||
|
"rejectReasonPlaceholder": "مثال: تصویر فیش ناخواناست، مبلغ فیش با فاکتور همخوانی ندارد، کد رهگیری نامعتبر است...", |
||||
|
"rejectNotice": "این توضیح به مسافر در بخش وضعیت فاکتور نمایش داده خواهد شد.", |
||||
"submitReject": "ثبت و رد فاکتور", |
"submitReject": "ثبت و رد فاکتور", |
||||
"submitting": "در حال ثبت...", |
"submitting": "در حال ثبت...", |
||||
"statusPending": "در انتظار بررسی فیش", |
"statusPending": "در انتظار بررسی فیش", |
||||
@ -99,32 +241,32 @@ |
|||||
"statusApproved": "پرداخت تایید شده", |
"statusApproved": "پرداخت تایید شده", |
||||
"statusRejected": "رد شده", |
"statusRejected": "رد شده", |
||||
"statusExpired": "منقضی شده", |
"statusExpired": "منقضی شده", |
||||
"invoice": "فاکتور", |
|
||||
"invoices": "فاکتور", |
|
||||
|
"invoice": "صورتحساب", |
||||
|
"invoices": "صورتحسابها", |
||||
"id": "شناسه", |
"id": "شناسه", |
||||
"viewDetails": "مشاهده جزئیات", |
"viewDetails": "مشاهده جزئیات", |
||||
"viewReceipt": "مشاهده فیش واریزی", |
|
||||
"noReceiptUploaded": "فیش واریزی بارگذاری نشده", |
|
||||
"serviceTour": "تورهای زیارتی", |
|
||||
|
"viewReceipt": "مشاهده فیش", |
||||
|
"noReceiptUploaded": "فیشی بارگذاری نشده است", |
||||
|
"serviceTour": "تور زیارتی", |
||||
"serviceSimcard": "سیمکارت", |
"serviceSimcard": "سیمکارت", |
||||
"serviceShop": "فروشگاه سوغات", |
|
||||
"serviceExchange": "صرافی (تسریف)", |
|
||||
|
"serviceShop": "فروشگاه معصومه", |
||||
|
"serviceExchange": "صرافی (تصریف)", |
||||
"serviceCustomTrip": "سفر اختصاصی", |
"serviceCustomTrip": "سفر اختصاصی", |
||||
"allStatuses": "همه وضعیتها", |
"allStatuses": "همه وضعیتها", |
||||
"allServices": "همه سرویسها", |
"allServices": "همه سرویسها", |
||||
"noFactorsFound": "صورتحسابی یافت نشد.", |
|
||||
"noFactorsFilter": "با فیلترهای جستجوی فعلی موردی پیدا نشد. میتوانید فیلترها را پاکسازی نمایید.", |
|
||||
"noFactorsEmpty": "هنوز هیچ صورتحسابی در سیستم صادر نشده است.", |
|
||||
"confirmClearReceipt": "آیا از حذف تصویر فیش بارگذاریشده برای این صورتحساب اطمینان دارید؟", |
|
||||
"receiptClearedSuccess": "فیش واریزی با موفقیت پاک شد.", |
|
||||
"tabAll": "همه تراکنشها", |
|
||||
"tabTour": "سفارشات و رزروهای تور", |
|
||||
"tabSimcard": "خرید سیمکارت", |
|
||||
"tabExchange": "صرافی و ارز", |
|
||||
|
"noFactorsFound": "هیچ صورتحسابی یافت نشد.", |
||||
|
"noFactorsFilter": "رکوردی با فیلترهای فعلی همخوانی ندارد. میتوانید فیلترها را پاک کنید.", |
||||
|
"noFactorsEmpty": "تاکنون هیچ صورتحسابی در سیستم صادر نشده است.", |
||||
|
"confirmClearReceipt": "آیا از حذف تصویر فیش بارگذاری شده اطمینان دارید؟", |
||||
|
"receiptClearedSuccess": "تصویر فیش پرداخت با موفقیت حذف شد.", |
||||
|
"tabAll": "کل تراکنشها", |
||||
|
"tabTour": "سفارشات و رزرو تور", |
||||
|
"tabSimcard": "سیمکارت", |
||||
|
"tabExchange": "ارز و صرافی", |
||||
"tabShop": "فروشگاه سوغات", |
"tabShop": "فروشگاه سوغات", |
||||
"tabCustomTrip": "سفر اختصاصی", |
|
||||
"coreTourBadge": "محور اصلی", |
|
||||
"liveStatus": "وضعیت لحظهای", |
|
||||
|
"tabCustomTrip": "سفرهای اختصاصی", |
||||
|
"coreTourBadge": "هسته اصلی", |
||||
|
"liveStatus": "وضعیت زنده", |
||||
"quickFilter": "فیلتر وضعیت" |
"quickFilter": "فیلتر وضعیت" |
||||
}, |
}, |
||||
"languages": { |
"languages": { |
||||
|
|||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue