Localize shared modals/overlays, logs, users and cluster-pool pages.

Add a components dictionary (delete/deleting overlays, confirm-modal
defaults, build-progress phases, deployment bar, resource-upgrade modal)
and move the logs, admin users, and admin cluster-pools pages onto the
dictionaries — filters, tables, forms, statuses, toasts and confirm
dialogs — with locale-aware dates and RTL-aware layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
keyhan
2026-06-11 15:36:30 +03:30
parent e99ab789ba
commit 6c1133f534
6 changed files with 488 additions and 196 deletions
+140
View File
@@ -441,6 +441,146 @@ const en: Dictionary = {
statusUpdateFailed: 'Failed to update invoice status',
reasonRequired: 'Reason is required for manual status changes',
},
logs: {
title: 'Logs',
subtitle: 'Application, Redis, RabbitMQ, and database logs in one place',
levels: { all: 'All levels', error: 'Error', warn: 'Warning', info: 'Info', debug: 'Debug' },
sources: { all: 'All sources', app: 'Application', redis: 'Redis', rabbitmq: 'RabbitMQ', database: 'Database' },
ranges: { '1h': 'Last hour', '6h': 'Last 6 hours', '24h': 'Last 24 hours', '7d': 'Last 7 days' },
resource: 'Resource',
allResources: 'All resources',
applicationsGroup: 'Applications',
servicesGroup: 'Databases & services',
source: 'Source',
level: 'Level',
timeRange: 'Time range',
search: 'Search',
searchPlaceholder: 'Search message...',
loading: 'Loading',
refresh: 'Refresh',
autoRefresh: 'Auto-refresh (5s)',
totalPeriod: 'Total ({period})',
errors: 'Errors',
warnings: 'Warnings',
sourcesStat: 'Sources',
loadFailed: 'Failed to load logs. Ensure logging is enabled on your application and Elasticsearch is running.',
logEntries: 'Log entries',
totalPage: '{total} total · page {page}/{pages}',
loadingLogs: 'Loading logs...',
noLogs: 'No logs found for the selected filters.',
noLogsHint: 'Deploy an app with logging enabled to start collecting logs.',
colTime: 'Time',
colLevel: 'Level',
colApp: 'App',
colSource: 'Source',
colMessage: 'Message',
prev: 'Previous',
next: 'Next',
reconnecting: 'Reconnecting to logging…',
notAvailable: 'Logging not available',
notAvailableMessage: 'Central Elasticsearch is not deployed on the cluster. Enable the logging addon when deploying an app, and ask an administrator to deploy the logging stack.',
checkingConnection: 'Checking connection…',
retryingAuto: 'Retrying automatically every few seconds.',
},
users: {
title: 'User Management',
count: '{n} user(s) registered',
addUser: 'Add User',
createNewUser: 'Create New User',
firstName: 'First Name',
lastName: 'Last Name',
email: 'Email',
password: 'Password',
firstNamePlaceholder: 'John',
lastNamePlaceholder: 'Doe',
emailPlaceholder: 'john@example.com',
passwordMin: 'Min 8 characters',
role: 'Role',
roles: { user: 'User', admin: 'Admin', technical: 'Technical', sales: 'Sales' },
creating: 'Creating...',
createUser: 'Create User',
searchPlaceholder: 'Search by name or email...',
noUsersSearch: 'No users found matching your search.',
noUsers: 'No users yet.',
colUser: 'User',
colEmail: 'Email',
colRole: 'Role',
colStatus: 'Status',
colApps: 'Apps',
colCreated: 'Created',
colActions: 'Actions',
active: 'Active',
inactive: 'Inactive',
appsCount: '{n} apps',
passwordBtn: 'Password',
deactivate: 'Deactivate',
activate: 'Activate',
setPassword: 'Set password',
newPasswordFor: 'New password for',
savePassword: 'Save password',
saving: 'Saving...',
createdSuccess: 'User created successfully',
createFailed: 'Failed to create user',
userUpdated: 'User updated',
roleUpdated: 'Role updated',
passwordUpdated: 'Password updated',
passwordFailed: 'Failed to update password',
},
pools: {
title: 'Cluster Pools',
subtitle: 'Load-balanced groups of clusters for automatic app distribution',
createPool: 'Create Pool',
editTitle: 'Edit “{name}”',
createNewPool: 'Create New Cluster Pool',
poolName: 'Pool Name',
strategy: 'Strategy',
strategyOptions: {
'weighted-resource': 'Weighted Resource — prefer healthy capacity and higher weights',
'least-loaded': 'Least Loaded — prefer lowest CPU, memory, and pod pressure',
'weighted-round-robin': 'Weighted Round Robin — rotate proportionally by weight',
'region-based': 'Region Based — prefer matching region, then weight and load',
'least-apps': 'Least Apps — deploy to cluster with fewest apps',
'round-robin': 'Round Robin — rotate across clusters evenly',
},
strategyShort: {
'weighted-resource': 'Weighted Resource',
'least-loaded': 'Least Loaded',
'weighted-round-robin': 'Weighted RR',
'region-based': 'Region Based',
'least-apps': 'Least Apps',
'round-robin': 'Round Robin',
},
priority: 'Priority',
description: 'Description',
descriptionPlaceholder: 'Load-balanced pool for production workloads',
useAsDefault: 'Use as default allocator pool',
selectClusters: 'Select Clusters ({n} selected)',
noClustersRegistered: 'No clusters registered. Add clusters first.',
defaultBadge: 'Default',
na: 'N/A',
weight: 'weight',
saving: 'Saving...',
updatePool: 'Update Pool',
poolCreated: 'Cluster pool created!',
createFailed: 'Failed to create pool',
poolUpdated: 'Cluster pool updated!',
updateFailed: 'Failed to update pool',
poolDeleted: 'Cluster pool deleted',
noPools: 'No cluster pools created yet',
noPoolsHint: 'Create a pool to enable load-balanced deployment across multiple clusters',
active: 'Active',
inactive: 'Inactive',
defaultPool: 'Default Pool',
priorityBadge: 'Priority {n}',
noClustersInPool: 'No clusters in this pool (they may have been deleted)',
clustersActive: '{active}/{total} clusters active · Created {date}',
edit: 'Edit',
remove: 'Remove',
deletePoolTitle: 'Delete Pool “{name}”',
deletePoolMessage: 'Apps already assigned to this pool will keep their current cluster.',
clusterStatus: { active: 'active', inactive: 'inactive', error: 'error' },
clusterHealth: { healthy: 'healthy', degraded: 'degraded', unhealthy: 'unhealthy', unknown: 'unknown' },
},
},
};
+140
View File
@@ -440,6 +440,146 @@ const fa = {
statusUpdateFailed: 'به‌روزرسانی وضعیت فاکتور ناموفق بود',
reasonRequired: 'برای تغییر دستی وضعیت، ذکر دلیل الزامی است',
},
logs: {
title: 'لاگ‌ها',
subtitle: 'لاگ اپلیکیشن، Redis، RabbitMQ و دیتابیس در یک‌جا',
levels: { all: 'همهٔ سطوح', error: 'خطا', warn: 'هشدار', info: 'اطلاع', debug: 'دیباگ' },
sources: { all: 'همهٔ منابع', app: 'اپلیکیشن', redis: 'Redis', rabbitmq: 'RabbitMQ', database: 'دیتابیس' },
ranges: { '1h': 'یک ساعت اخیر', '6h': '۶ ساعت اخیر', '24h': '۲۴ ساعت اخیر', '7d': '۷ روز اخیر' },
resource: 'منبع',
allResources: 'همهٔ منابع',
applicationsGroup: 'اپلیکیشن‌ها',
servicesGroup: 'دیتابیس‌ها و سرویس‌ها',
source: 'منبع',
level: 'سطح',
timeRange: 'بازهٔ زمانی',
search: 'جستجو',
searchPlaceholder: 'جستجوی پیام…',
loading: 'در حال بارگذاری',
refresh: 'تازه‌سازی',
autoRefresh: 'تازه‌سازی خودکار (۵ث)',
totalPeriod: 'مجموع ({period})',
errors: 'خطاها',
warnings: 'هشدارها',
sourcesStat: 'منابع',
loadFailed: 'بارگذاری لاگ‌ها ناموفق بود. مطمئن شو لاگینگ روی اپت فعال است و Elasticsearch در حال اجراست.',
logEntries: 'ورودی‌های لاگ',
totalPage: '{total} مورد · صفحهٔ {page}/{pages}',
loadingLogs: 'در حال بارگذاری لاگ‌ها…',
noLogs: 'برای فیلترهای انتخاب‌شده لاگی پیدا نشد.',
noLogsHint: 'برای شروع جمع‌آوری لاگ، اپی با لاگینگ فعال منتشر کن.',
colTime: 'زمان',
colLevel: 'سطح',
colApp: 'اپ',
colSource: 'منبع',
colMessage: 'پیام',
prev: 'قبلی',
next: 'بعدی',
reconnecting: 'در حال اتصال مجدد به لاگینگ…',
notAvailable: 'لاگینگ در دسترس نیست',
notAvailableMessage: 'Elasticsearch مرکزی روی کلاستر مستقر نشده است. هنگام انتشار اپ، افزونهٔ لاگینگ را فعال کن و از مدیر بخواه استک لاگینگ را مستقر کند.',
checkingConnection: 'در حال بررسی اتصال…',
retryingAuto: 'هر چند ثانیه به‌صورت خودکار تلاش می‌شود.',
},
users: {
title: 'مدیریت کاربران',
count: '{n} کاربر ثبت‌شده',
addUser: 'افزودن کاربر',
createNewUser: 'ساخت کاربر جدید',
firstName: 'نام',
lastName: 'نام خانوادگی',
email: 'ایمیل',
password: 'رمز عبور',
firstNamePlaceholder: 'مثلاً علی',
lastNamePlaceholder: 'مثلاً رضایی',
emailPlaceholder: 'name@example.com',
passwordMin: 'حداقل ۸ کاراکتر',
role: 'نقش',
roles: { user: 'کاربر', admin: 'مدیر', technical: 'فنی', sales: 'فروش' },
creating: 'در حال ساخت…',
createUser: 'ساخت کاربر',
searchPlaceholder: 'جستجو بر اساس نام یا ایمیل…',
noUsersSearch: 'کاربری مطابق جستجو پیدا نشد.',
noUsers: 'هنوز کاربری نیست.',
colUser: 'کاربر',
colEmail: 'ایمیل',
colRole: 'نقش',
colStatus: 'وضعیت',
colApps: 'اپ‌ها',
colCreated: 'تاریخ ایجاد',
colActions: 'عملیات',
active: 'فعال',
inactive: 'غیرفعال',
appsCount: '{n} اپ',
passwordBtn: 'رمز عبور',
deactivate: 'غیرفعال‌سازی',
activate: 'فعال‌سازی',
setPassword: 'تنظیم رمز عبور',
newPasswordFor: 'رمز عبور جدید برای',
savePassword: 'ذخیرهٔ رمز',
saving: 'در حال ذخیره…',
createdSuccess: 'کاربر با موفقیت ساخته شد',
createFailed: 'ساخت کاربر ناموفق بود',
userUpdated: 'کاربر به‌روزرسانی شد',
roleUpdated: 'نقش به‌روزرسانی شد',
passwordUpdated: 'رمز عبور به‌روزرسانی شد',
passwordFailed: 'به‌روزرسانی رمز ناموفق بود',
},
pools: {
title: 'پول‌های کلاستر',
subtitle: 'گروه‌های متوازن‌شدهٔ کلاستر برای توزیع خودکار اپ‌ها',
createPool: 'ساخت پول',
editTitle: 'ویرایش «{name}»',
createNewPool: 'ساخت پول کلاستر جدید',
poolName: 'نام پول',
strategy: 'استراتژی',
strategyOptions: {
'weighted-resource': 'منابع وزن‌دار — اولویت با ظرفیت سالم و وزن بالاتر',
'least-loaded': 'کم‌بارترین — اولویت با کمترین CPU، حافظه و فشار پاد',
'weighted-round-robin': 'چرخشی وزن‌دار — چرخش متناسب با وزن',
'region-based': 'بر اساس منطقه — اولویت با منطقهٔ منطبق، سپس وزن و بار',
'least-apps': 'کمترین اپ — انتشار روی کلاستر با کمترین اپ',
'round-robin': 'چرخشی — چرخش یکنواخت بین کلاسترها',
},
strategyShort: {
'weighted-resource': 'منابع وزن‌دار',
'least-loaded': 'کم‌بارترین',
'weighted-round-robin': 'چرخشی وزن‌دار',
'region-based': 'بر اساس منطقه',
'least-apps': 'کمترین اپ',
'round-robin': 'چرخشی',
},
priority: 'اولویت',
description: 'توضیحات',
descriptionPlaceholder: 'پول متوازن‌شده برای بارهای کاری پروداکشن',
useAsDefault: 'استفاده به‌عنوان پول تخصیص پیش‌فرض',
selectClusters: 'انتخاب کلاسترها ({n} انتخاب‌شده)',
noClustersRegistered: 'هیچ کلاستری ثبت نشده. اول کلاستر اضافه کن.',
defaultBadge: 'پیش‌فرض',
na: 'نامشخص',
weight: 'وزن',
saving: 'در حال ذخیره…',
updatePool: 'به‌روزرسانی پول',
poolCreated: 'پول کلاستر ساخته شد!',
createFailed: 'ساخت پول ناموفق بود',
poolUpdated: 'پول کلاستر به‌روزرسانی شد!',
updateFailed: 'به‌روزرسانی پول ناموفق بود',
poolDeleted: 'پول کلاستر حذف شد',
noPools: 'هنوز پول کلاستری ساخته نشده',
noPoolsHint: 'برای فعال‌سازی انتشار متوازن روی چند کلاستر، یک پول بساز',
active: 'فعال',
inactive: 'غیرفعال',
defaultPool: 'پول پیش‌فرض',
priorityBadge: 'اولویت {n}',
noClustersInPool: 'کلاستری در این پول نیست (شاید حذف شده‌اند)',
clustersActive: '{active}/{total} کلاستر فعال · ایجاد {date}',
edit: 'ویرایش',
remove: 'حذف',
deletePoolTitle: 'حذف پول «{name}»',
deletePoolMessage: 'اپ‌هایی که از قبل به این پول اختصاص یافته‌اند، کلاستر فعلی‌شان را حفظ می‌کنند.',
clusterStatus: { active: 'فعال', inactive: 'غیرفعال', error: 'خطا' },
clusterHealth: { healthy: 'سالم', degraded: 'نزول‌یافته', unhealthy: 'ناسالم', unknown: 'نامشخص' },
},
},
};