8d1855b89c
Reject zip uploads when the selected runtime does not match archive contents, and re-validate before Kaniko builds to fail fast instead of producing the wrong Dockerfile. Co-authored-by: Cursor <cursoragent@cursor.com>
1697 lines
79 KiB
TypeScript
1697 lines
79 KiB
TypeScript
import type { Dictionary } from './fa';
|
||
|
||
// English (en-US) dictionary. Must mirror the shape of fa.ts (the source of truth).
|
||
const en: Dictionary = {
|
||
common: {
|
||
appName: 'Abrban',
|
||
login: 'Sign in',
|
||
register: 'Sign up',
|
||
logout: 'Sign out',
|
||
signOut: 'Sign out',
|
||
dashboard: 'Dashboard',
|
||
backHome: 'Back to home',
|
||
loading: 'Loading…',
|
||
save: 'Save',
|
||
cancel: 'Cancel',
|
||
delete: 'Delete',
|
||
edit: 'Edit',
|
||
create: 'Create',
|
||
back: 'Back',
|
||
search: 'Search',
|
||
confirm: 'Confirm',
|
||
close: 'Close',
|
||
yes: 'Yes',
|
||
no: 'No',
|
||
currency: 'Toman',
|
||
currencyShort: 'T',
|
||
},
|
||
|
||
errors: {
|
||
generic: 'Something went wrong. Please try again.',
|
||
network: 'Could not reach the server. Check your internet connection.',
|
||
timeout: 'The server took too long to respond. Please try again.',
|
||
unauthorized: 'Your session has expired. Please sign in again.',
|
||
forbidden: 'You do not have permission to do this.',
|
||
notFound: 'The requested item was not found.',
|
||
conflict: 'This action conflicts with the current state. Refresh and try again.',
|
||
validation: 'The information you entered is invalid. Please check your input.',
|
||
rateLimit: 'Too many requests. Please wait a moment and try again.',
|
||
server: 'A server error occurred. Please try again shortly.',
|
||
runtimeMismatch: 'The selected project type ({configured}) does not match the uploaded archive ({detected}).',
|
||
},
|
||
|
||
language: {
|
||
label: 'Language',
|
||
},
|
||
|
||
meta: {
|
||
title: 'Abrban | Cloud infrastructure, in your control',
|
||
description:
|
||
'Abrban — a self-service cloud platform on Kubernetes. Ship your app in seconds: managed databases, custom domains, automatic SSL and live logs.',
|
||
},
|
||
|
||
roles: {
|
||
admin: 'Admin',
|
||
technical: 'Technical',
|
||
sales: 'Sales',
|
||
},
|
||
|
||
landing: {
|
||
badge: 'Self-service cloud platform',
|
||
nav: {
|
||
services: 'Services',
|
||
pricing: 'Pricing',
|
||
estimator: 'Estimate',
|
||
learn: 'Learn',
|
||
blog: 'Blog',
|
||
menu: 'Menu',
|
||
},
|
||
hero: {
|
||
title: 'Abrban',
|
||
tagline: 'Cloud infrastructure, in your control',
|
||
subtitle:
|
||
'Ship your app to Kubernetes in seconds — no server hassle, no DevOps complexity.',
|
||
ctaPrimary: 'Start for free',
|
||
ctaSecondary: 'Sign in',
|
||
scrollHint: 'Dive into the clouds',
|
||
},
|
||
services: {
|
||
title: 'Platform services',
|
||
subtitle: 'Everything you need to build and run your product, in one place.',
|
||
comingSoon: 'Coming soon',
|
||
explore: 'Click to explore',
|
||
paas: {
|
||
label: 'PaaS',
|
||
name: 'Platform as a Service',
|
||
desc: 'Ship your app straight from code to Kubernetes — automatic build and release.',
|
||
},
|
||
dbaas: {
|
||
label: 'DBaaS',
|
||
name: 'Database as a Service',
|
||
desc: 'Managed, reliable databases ready in seconds.',
|
||
},
|
||
kaas: {
|
||
label: 'KaaS',
|
||
name: 'Kubernetes as a Service',
|
||
desc: 'A dedicated, managed Kubernetes cluster for your team.',
|
||
},
|
||
laas: {
|
||
label: 'LaaS',
|
||
name: 'Logging as a Service',
|
||
desc: 'Centralized log collection, retention and analysis.',
|
||
},
|
||
},
|
||
value: {
|
||
lead: 'A ',
|
||
highlight: 'self-service PaaS',
|
||
tail: ' on Kubernetes — all the power of cloud infrastructure, without the storm of complexity.',
|
||
body: 'Abrban handles the hard DevOps layers for you, so you can focus only on your product.',
|
||
},
|
||
how: {
|
||
title: 'As simple as three steps',
|
||
steps: [
|
||
{ n: '1', title: 'Hand us your code', desc: 'Connect your repository or app.' },
|
||
{ n: '2', title: 'We build it', desc: 'Abrban automatically builds and deploys to Kubernetes.' },
|
||
{ n: '3', title: 'Go live', desc: 'Domain and SSL are ready; your app goes live.' },
|
||
],
|
||
},
|
||
features: {
|
||
title: 'Everything you need to build',
|
||
subtitle: 'A complete toolkit to ship and maintain your app.',
|
||
items: [
|
||
{ title: 'Lightning deploys', desc: 'Ship Node.js, Laravel and WordPress with one click; automatic build and release.' },
|
||
{ title: 'Managed databases', desc: 'PostgreSQL, MySQL, Redis, RabbitMQ and Elasticsearch — ready and reliable.' },
|
||
{ title: 'Automatic SSL', desc: 'Connect a custom domain; SSL certificates are issued and renewed automatically.' },
|
||
{ title: 'Preview links', desc: 'Get a stable TLS Preview URL for every deploy and test fast.' },
|
||
{ title: 'Live logs', desc: 'Follow build and runtime logs live, the moment they happen.' },
|
||
{ title: 'Snapshots & backups', desc: 'Snapshot your app state and restore it whenever you want.' },
|
||
{ title: 'Transparent billing', desc: 'Prepaid wallet, precise invoices and real-time usage — no surprises.' },
|
||
{ title: 'Persian support', desc: 'A support team and ticketing system, in Persian and always by your side.' },
|
||
],
|
||
},
|
||
trust: {
|
||
title: 'Why teams trust Abrban',
|
||
items: [
|
||
{ kpi: '< 60 sec', label: 'Average deploy time' },
|
||
{ kpi: '99.9%', label: 'Infrastructure uptime' },
|
||
{ kpi: 'Auto TLS', label: 'Security by default' },
|
||
{ kpi: 'Iran-native', label: 'Optimized for Iranian users' },
|
||
],
|
||
},
|
||
pricing: {
|
||
title: 'Transparent pricing',
|
||
subtitle: 'Pay only for the resources you use. These rates are read straight from the platform’s active plans.',
|
||
runtimeLabel: 'Application type',
|
||
cycle: { hourly: 'Hourly', monthly: 'Monthly', yearly: 'Yearly' },
|
||
perCycle: { hourly: 'per hour', monthly: 'per month', yearly: 'per year' },
|
||
discountBadge: '{p}% off',
|
||
free: 'Free',
|
||
resources: {
|
||
base_fee: 'Base fee',
|
||
cpu_per_core: 'CPU (per core)',
|
||
memory_per_gb: 'Memory (per GB)',
|
||
storage_per_gb: 'Storage (per GB)',
|
||
database_addon: 'Managed database',
|
||
custom_domain_addon: 'Custom domain + SSL',
|
||
},
|
||
currency: 'Toman',
|
||
note: 'Your final bill is based on actual usage; these are the per-unit rates for each resource.',
|
||
loadError: 'Could not load pricing.',
|
||
},
|
||
estimator: {
|
||
title: 'Estimate your package',
|
||
subtitle: 'Pick the resources you need and see an instant cost estimate.',
|
||
runtime: 'Application type',
|
||
cpu: 'CPU',
|
||
memory: 'Memory (RAM)',
|
||
storage: 'Storage',
|
||
replicas: 'Replicas',
|
||
database: 'Database',
|
||
databaseType: 'Database type',
|
||
options: 'Add-on services',
|
||
redis: 'Redis',
|
||
rabbitmq: 'RabbitMQ',
|
||
elasticsearch: 'Elasticsearch (logging)',
|
||
customDomain: 'Custom domain + SSL',
|
||
cores: '{n} cores',
|
||
gb: '{n} GB',
|
||
none: 'None',
|
||
estimatedTitle: 'Estimated cost',
|
||
perCycle: { hourly: 'per hour', monthly: 'per month', yearly: 'per year' },
|
||
cycle: { hourly: 'Hourly', monthly: 'Monthly', yearly: 'Yearly' },
|
||
youSave: '{p}% discount applied',
|
||
calculating: 'Calculating…',
|
||
cta: 'Build this package',
|
||
currency: 'Toman',
|
||
error: 'Could not calculate cost.',
|
||
},
|
||
blog: {
|
||
title: 'Blog & guides',
|
||
subtitle: 'Guides and the latest writing to help you build faster on Abrban.',
|
||
comingSoon: 'Coming soon',
|
||
cta: 'View all articles',
|
||
readMore: 'Read more',
|
||
minRead: '{n} min read',
|
||
notFound: 'This article was not found.',
|
||
backToBlog: 'Back to the blog',
|
||
posts: [
|
||
{ tag: 'Getting started', title: 'Ship your first app in minutes', desc: 'From connecting a repo to a domain and automatic SSL — step by step.' },
|
||
{ tag: 'Cost optimization', title: 'Pick the right resources and pay less', desc: 'Tune CPU, memory, replicas and add-on services wisely.' },
|
||
{ tag: 'Security', title: 'Custom domains with automatic SSL', desc: 'Connect your domain and let Abrban issue and renew the certificate.' },
|
||
],
|
||
},
|
||
finalCta: {
|
||
titleLead: 'The sky is clear; it’s time to ',
|
||
titleHighlight: 'go live',
|
||
titleTail: ' with your app.',
|
||
body: 'Create your account now and experience your first deploy.',
|
||
ctaPrimary: 'Get started now',
|
||
ctaSecondary: 'Dashboard',
|
||
},
|
||
footer: {
|
||
copyright: 'All rights to this website belong to Abrban',
|
||
contactTitle: 'Contact us',
|
||
phone: '021-91092762',
|
||
email: 'info@abrban.com',
|
||
},
|
||
},
|
||
|
||
auth: {
|
||
backHome: 'Back to home',
|
||
login: {
|
||
title: 'Welcome back',
|
||
subtitle: 'Sign in to your Abrban account with your mobile',
|
||
altPrompt: 'Don’t have an account yet?',
|
||
altLabel: 'Sign up',
|
||
tabPassword: 'With password',
|
||
tabOtp: 'With one-time code',
|
||
phone: 'Mobile number',
|
||
password: 'Password',
|
||
otpHint: 'A verification code will be texted to your mobile.',
|
||
sendCode: 'Send code',
|
||
sending: 'Sending…',
|
||
codeSent: 'Verification code sent',
|
||
verifyNeeded: 'Verify your mobile number to continue.',
|
||
otpTitle: 'Verify mobile number',
|
||
otpSubtitle: 'Enter the 6-digit code we texted you',
|
||
submit: 'Sign in',
|
||
submitting: 'Signing in…',
|
||
success: 'Signed in successfully!',
|
||
error: 'Sign in failed',
|
||
},
|
||
register: {
|
||
title: 'Create account',
|
||
subtitle: 'Ship your first app in a few minutes',
|
||
altPrompt: 'Already have an account?',
|
||
altLabel: 'Sign in',
|
||
firstName: 'First name',
|
||
firstNamePlaceholder: 'e.g. Ali',
|
||
lastName: 'Last name',
|
||
lastNamePlaceholder: 'e.g. Rezaei',
|
||
phone: 'Mobile number',
|
||
emailOptional: 'Email (optional)',
|
||
password: 'Password',
|
||
passwordPlaceholder: 'At least 8 characters',
|
||
submit: 'Create account',
|
||
submitting: 'Creating account…',
|
||
codeSent: 'A verification code was texted to your mobile',
|
||
success: 'Account created and verified!',
|
||
error: 'Sign up failed',
|
||
verifyError: 'Code verification failed',
|
||
},
|
||
otp: {
|
||
sentTo: 'A verification code was texted to:',
|
||
codeLabel: 'Verification code',
|
||
verify: 'Verify and continue',
|
||
verifying: 'Verifying…',
|
||
back: 'Back',
|
||
resend: 'Resend code',
|
||
resendIn: 'Resend in {s}s',
|
||
},
|
||
},
|
||
|
||
components: {
|
||
deleting: 'Deleting…',
|
||
deletingNamed: 'Deleting “{name}”…',
|
||
deletingService: 'Deleting service…',
|
||
deletingApplication: 'Deleting application…',
|
||
deletingModalBeingRemoved: '“{name}” is being permanently removed.',
|
||
deletingModalDetailApp: 'Removing this application, deployments, and data from the cluster. This may take a minute.',
|
||
deletingModalDetailService: 'Removing this service and its data from the cluster. This may take a minute.',
|
||
deletingModalWait: 'Please wait — do not close this page.',
|
||
buildPhases: {
|
||
uploading: 'Uploading source to cluster',
|
||
building: 'Building Docker image',
|
||
deploying: 'Deploying to Kubernetes',
|
||
done: 'Deployment complete',
|
||
failed: 'Deployment failed',
|
||
cancelled: 'Deployment cancelled',
|
||
},
|
||
startingDeployment: 'Starting deployment…',
|
||
deploymentCancelled: 'Deployment cancelled',
|
||
cancelDeploymentFailed: 'Failed to cancel deployment',
|
||
minimizeHint: 'Use minimize to keep working while deployment continues. Close (×) cancels the deployment.',
|
||
buildLogTitle: 'Build log',
|
||
buildLogWaiting: 'Starting build…',
|
||
buildLogLive: 'live',
|
||
continueInBackground: 'Continue in background',
|
||
minimizeAria: 'Minimize and continue in background',
|
||
cancelDeploymentAria: 'Cancel deployment',
|
||
viewProgressFor: 'View deployment progress for {name}',
|
||
prevDeployment: 'Previous deployment',
|
||
nextDeployment: 'Next deployment',
|
||
upgradeTitle: 'Confirm Resource Upgrade',
|
||
upgradeNeedsPay: 'This upgrade requires payment for the remaining billing period.',
|
||
upgradeNoCost: 'No additional cost for this change.',
|
||
currentHourlyCost: 'Current hourly cost',
|
||
newHourlyCost: 'New hourly cost',
|
||
remainingHoursInPeriod: 'Remaining hours in period',
|
||
proratedAmountToPay: 'Prorated amount to pay',
|
||
walletBalance: 'Wallet Balance',
|
||
tomanPerHour: '{n} Toman/hour',
|
||
hoursUnit: '{n} hours',
|
||
tomanUnit: '{n} Toman',
|
||
walletShortBy: 'Wallet is short by {n} Toman. You can pay the delta by gateway on the invoice page.',
|
||
applying: 'Applying…',
|
||
createInvoicePay: 'Create Invoice & Pay',
|
||
applyChanges: 'Apply Changes',
|
||
res: {
|
||
databaseResources: 'Database resources',
|
||
cpuRequest: 'CPU request',
|
||
cpuLimit: 'CPU limit',
|
||
memoryRequest: 'Memory request',
|
||
memoryLimit: 'Memory limit',
|
||
oneCore: '1 core',
|
||
twoCores: '2 cores',
|
||
storageGb: 'Storage (GB)',
|
||
},
|
||
deployStatus: {
|
||
running: 'running',
|
||
pending: 'pending',
|
||
building: 'building',
|
||
deploying: 'deploying',
|
||
failed: 'failed',
|
||
build_failed: 'build_failed',
|
||
cancelled: 'cancelled',
|
||
stopped: 'stopped',
|
||
active: 'active',
|
||
suspended: 'suspended',
|
||
pending_deletion: 'pending_deletion',
|
||
},
|
||
workloadLogs: {
|
||
logs: 'Logs',
|
||
liveEvery3s: 'Live (every 3s)',
|
||
autoEvery5s: 'Auto-refresh (every 5s)',
|
||
hideLogs: 'Hide logs',
|
||
showLogs: 'Show logs',
|
||
podLogs: 'Pod logs',
|
||
buildLogs: 'Build logs',
|
||
noBuildNote: 'Workload pod output (no image build for this service).',
|
||
loadingLogs: 'Loading logs...',
|
||
serviceStopped: 'Service is stopped. Start it to see logs.',
|
||
waitingPods: 'Waiting for workload pods to be ready...',
|
||
buildInProgress: 'Build in progress... Logs will appear when complete.',
|
||
buildPending: 'Build is pending...',
|
||
noDeployments: 'No deployments yet. Deploy your app to see build logs.',
|
||
noBuildLogs: 'No build logs available for this deployment.',
|
||
buildDone: 'Done',
|
||
},
|
||
externalAccess: {
|
||
title: 'External access',
|
||
warning: 'Opens a NodePort on the cluster node IP. Anyone who can reach that IP may connect until the session ends or you revoke it. Use short durations for temporary access; permanent keeps the port open until revoked.',
|
||
deployFirst: 'Deploy the service first to enable external access.',
|
||
service: 'Service',
|
||
accessMode: 'Access mode',
|
||
temporary: 'Temporary',
|
||
alwaysOpen: 'Always open',
|
||
duration: 'Duration',
|
||
persistentNote: 'The port stays exposed until you click Revoke. Only use this when you need a stable external endpoint.',
|
||
opening: 'Opening…',
|
||
openPermanently: 'Open port permanently',
|
||
enableAccess: 'Enable access',
|
||
noSessions: 'No active external access sessions.',
|
||
revoke: 'Revoke',
|
||
endpoint: 'Endpoint',
|
||
url: 'URL',
|
||
permanentUntilRevoked: 'Permanent (until revoked)',
|
||
expired: 'Expired',
|
||
targets: {
|
||
database: 'Database',
|
||
redis: 'Redis',
|
||
rabbitmq_amqp: 'RabbitMQ (AMQP)',
|
||
rabbitmq_management: 'RabbitMQ Management UI',
|
||
},
|
||
permanentEnabled: 'Permanent external access enabled',
|
||
temporaryEnabled: 'Temporary external access enabled',
|
||
enableFailed: 'Failed to enable access',
|
||
revoked: 'Access revoked',
|
||
revokeFailed: 'Failed to revoke access',
|
||
hShort: 'h',
|
||
mShort: 'm',
|
||
sShort: 's',
|
||
},
|
||
dbConfig: {
|
||
engine: 'Database engine',
|
||
version: 'Version',
|
||
credentials: 'Database credentials',
|
||
credentialsOptional: '(optional — auto-generated if empty)',
|
||
username: 'Username',
|
||
usernamePlaceholder: 'appuser',
|
||
password: 'Password',
|
||
passwordPlaceholder: 'Auto-generated',
|
||
generatePassword: 'Generate random password',
|
||
credentialsNote: 'Used for internal cluster access. Use temporary or permanent external access below after deploy.',
|
||
uploadDumpLabel: 'Optional: upload DB dump to restore at creation',
|
||
remove: 'Remove',
|
||
uploadHint: 'Upload a SQL dump to be restored after the database is created',
|
||
uploadConstraints: 'Optional • Max 500MB • .sql, .gz, .dump',
|
||
allowedFormats: 'Allowed: .sql, .gz, .dump',
|
||
maxSize: 'Max 500MB',
|
||
storageSize: 'Database storage size',
|
||
suggestedFromDump: 'Suggested from dump ({gi} GiB min fit)',
|
||
minimumGb: 'Minimum {n} GB',
|
||
mustFitDump: ' (must fit the uploaded dump)',
|
||
expansionOnly: ' • Only expansion allowed after creation',
|
||
storageTooSmallTitle: 'Storage too small',
|
||
ok: 'OK',
|
||
storageTooSmallDetail: 'Your database dump is about {dumpGi} GiB. Database storage must be at least {need} GiB (you selected {selected} GiB). Increase database storage, then try again.',
|
||
},
|
||
snapshots: {
|
||
title: 'Snapshots',
|
||
newSnapshot: 'New Snapshot',
|
||
creating: 'Creating…',
|
||
hide: 'Hide',
|
||
show: 'Show',
|
||
deployFirst: 'Deploy the service first',
|
||
waitCurrent: 'Wait for the current backup to finish',
|
||
infoNote: 'Database snapshots store a SQL dump you can download later. When progress reaches 100%, use the download button. Up to 10 snapshots are kept; oldest are removed automatically.',
|
||
loadingBackups: 'Loading backups…',
|
||
noBackups: 'No backups yet',
|
||
noBackupsHint: 'Click New backup to create your first database dump.',
|
||
defaultLabel: 'Database backup',
|
||
auto: 'Auto',
|
||
manual: 'Manual',
|
||
dumping: 'Dumping…',
|
||
preparing: 'Preparing dump…',
|
||
exporting: 'Exporting database…',
|
||
finalizing: 'Finalizing…',
|
||
creatingDump: 'Creating database dump…',
|
||
dump: 'Dump',
|
||
downloadTitle: 'Download database dump',
|
||
deleteTitle: 'Delete backup',
|
||
removeFailedTitle: 'Remove failed backup',
|
||
maxKept: 'Maximum 10 backups are kept.',
|
||
backupReady: 'Backup ready — you can download the dump now',
|
||
backupFailed: 'Backup failed',
|
||
backupStarted: 'Backup started — dump in progress',
|
||
createFailed: 'Failed to create backup',
|
||
backupDeleted: 'Backup deleted',
|
||
deleteFailed: 'Failed to delete backup',
|
||
downloadStarted: 'Download started',
|
||
downloadFailed: 'Failed to download database dump',
|
||
deleteConfirmTitle: 'Delete backup?',
|
||
deleteConfirmMessage: 'Delete “{label}”? The dump file will be permanently removed.',
|
||
snapStatus: { completed: 'completed', failed: 'failed' },
|
||
},
|
||
serviceResources: {
|
||
title: 'Resources & Scaling',
|
||
hide: 'Hide',
|
||
monitor: 'Monitor',
|
||
deployToView: 'Deploy the service to view metrics and adjust resources.',
|
||
loadingMetrics: 'Loading metrics…',
|
||
replicas: 'Replicas',
|
||
pods: 'Pods',
|
||
metrics: 'Metrics',
|
||
serviceStopped: 'Service is stopped.',
|
||
noMetrics: 'No resource metrics yet.',
|
||
storage: 'Storage',
|
||
loadingStorage: 'Loading storage…',
|
||
used: 'Used',
|
||
allocated: 'Allocated',
|
||
expansionNote: 'Only expansion is allowed. Use Apply changes below.',
|
||
storageChargedNote: ' Additional storage is charged for the remaining billing period.',
|
||
storageUnavailable: 'Storage metrics unavailable.',
|
||
adjustCpuMem: 'Adjust CPU / memory',
|
||
redisResources: 'Redis resources',
|
||
rabbitmqResources: 'RabbitMQ resources',
|
||
upgradeChargeNote: 'Upgrades that increase cost are charged for the remaining billing period (wallet or invoice), same as applications.',
|
||
applying: 'Applying…',
|
||
applyChanges: 'Apply changes',
|
||
restoreDump: 'Restore database dump',
|
||
restoring: 'Restoring database…',
|
||
uploadToRestore: 'Upload SQL dump to restore',
|
||
uploadFormats: '.sql, .gz, or .dump — max 500MB',
|
||
workloads: { database: 'Database', redis: 'Redis', rabbitmq: 'RabbitMQ' },
|
||
resourcesUpdated: 'Resources updated',
|
||
updateFailed: 'Failed to update resources',
|
||
upgradedPaid: 'Resources upgraded! Paid {amount} Toman',
|
||
updatedSuccess: 'Resources updated successfully',
|
||
upgradeFailed: 'Failed to upgrade resources',
|
||
calcFailed: 'Failed to calculate upgrade cost',
|
||
invoiceCreated: 'Invoice created. Choose how you want to pay.',
|
||
invoiceFailed: 'Failed to create upgrade invoice',
|
||
restoredSuccess: 'Database restored successfully',
|
||
restoreFailed: 'Database restore failed',
|
||
uploadFailed: 'Failed to upload database dump',
|
||
invalidFile: 'Please upload a .sql, .dump, or .gz file',
|
||
fileTooLarge: 'File size must be less than 500MB',
|
||
renewFirst: 'Renew the service before changing resources',
|
||
},
|
||
},
|
||
|
||
nav: {
|
||
sectionAdmin: 'Admin',
|
||
sectionTechnical: 'Technical',
|
||
sectionSales: 'Sales',
|
||
walletBalanceTitle: 'Wallet balance',
|
||
dashboard: 'Dashboard',
|
||
applications: 'Applications',
|
||
services: 'Databases & Services',
|
||
logs: 'Logs',
|
||
newDeploy: 'New Deploy',
|
||
wallet: 'Wallet',
|
||
invoices: 'Invoices',
|
||
tickets: 'Tickets',
|
||
account: 'My Account',
|
||
users: 'Users',
|
||
allApplications: 'All Applications',
|
||
billingPlans: 'Billing Plans',
|
||
clusters: 'Clusters',
|
||
clusterPools: 'Cluster Pools',
|
||
allTickets: 'All Tickets',
|
||
technicalTickets: 'Technical Tickets',
|
||
salesTickets: 'Sales Tickets',
|
||
},
|
||
|
||
dashboard: {
|
||
account: {
|
||
title: 'My Account',
|
||
subtitle: 'Manage your account details, mobile number and password.',
|
||
personalInfo: 'Personal information',
|
||
firstName: 'First name',
|
||
lastName: 'Last name',
|
||
emailOptional: 'Email (optional)',
|
||
emailHint: 'Email is for contact only and is not used to sign in.',
|
||
save: 'Save',
|
||
saving: 'Saving…',
|
||
savedName: 'Profile saved successfully',
|
||
verified: 'Verified',
|
||
unverified: 'Unverified',
|
||
notSet: 'Not set',
|
||
verifyNow: 'Verify',
|
||
currentPassword: 'Current password',
|
||
passwordReason: 'Your current password is required to change your mobile number.',
|
||
sendCode: 'Send code',
|
||
sending: 'Sending…',
|
||
codeSent: 'Verification code sent',
|
||
codeSentTo: 'A verification code was texted to:',
|
||
enterCode: 'Verification code',
|
||
confirm: 'Confirm',
|
||
verifying: 'Verifying…',
|
||
resend: 'Resend code',
|
||
cancel: 'Cancel',
|
||
phoneUpdated: 'Mobile number updated successfully',
|
||
changePassword: 'Change password',
|
||
newPassword: 'New password',
|
||
confirmPassword: 'Confirm new password',
|
||
passwordMismatch: 'New password and confirmation do not match',
|
||
passwordChanged: 'Password changed successfully',
|
||
passwordHint: 'At least 8 characters',
|
||
errorGeneric: 'Operation failed',
|
||
phone: {
|
||
label: 'Mobile number',
|
||
empty: 'No number set',
|
||
add: 'Add number',
|
||
change: 'Change number',
|
||
newLabel: 'New mobile number',
|
||
},
|
||
},
|
||
status: {
|
||
running: 'Running',
|
||
pending: 'Pending',
|
||
building: 'Building',
|
||
deploying: 'Deploying',
|
||
failed: 'Failed',
|
||
build_failed: 'Build failed',
|
||
cancelled: 'Cancelled',
|
||
stopped: 'Stopped',
|
||
},
|
||
home: {
|
||
welcome: 'Welcome back, {name}!',
|
||
overview: 'Overview of your applications and managed services.',
|
||
creditsTitle: 'Prepaid resource credits',
|
||
creditsBody:
|
||
'If you delete an app before your plan ends, you can deploy a new app with the same resources at no extra charge until the credit expires.',
|
||
fromApp: 'From app “{name}”',
|
||
resourceCredit: 'Resource credit',
|
||
remaining: '{label} remaining',
|
||
expires: 'Expires {date}',
|
||
cpu: 'CPU',
|
||
ram: 'RAM',
|
||
replicas: 'Replicas',
|
||
db: 'DB',
|
||
dbDisk: 'DB disk',
|
||
appDisk: 'App disk',
|
||
useOnNewApp: 'Use on new app →',
|
||
statApplications: 'Applications',
|
||
statAppsRunning: 'Apps running',
|
||
statManagedServices: 'Managed services',
|
||
statServicesRunning: 'Services running',
|
||
appsFailed: '{n} application(s) failed',
|
||
servicesFailed: '{n} service(s) failed',
|
||
recentApplications: 'Recent applications',
|
||
newApplication: 'New application',
|
||
noApplications: 'No applications yet',
|
||
deployFirst: 'Deploy your first app',
|
||
viewAllApplications: 'View all {n} applications →',
|
||
recentServices: 'Recent databases & services',
|
||
newService: 'New service',
|
||
noServices: 'No managed services yet',
|
||
createServiceCta: 'Create database or service',
|
||
viewAllServices: 'View all {n} services →',
|
||
replica: 'replica',
|
||
replicaPlural: 'replicas',
|
||
},
|
||
apps: {
|
||
title: 'My Applications',
|
||
count: '{n} application(s)',
|
||
newApplication: 'New Application',
|
||
noApplications: 'No applications yet',
|
||
emptyDesc: 'Deploy your first application to get started.',
|
||
deployFirst: 'Deploy your first app',
|
||
colApplication: 'Application',
|
||
colRuntime: 'Runtime',
|
||
colStatus: 'Status',
|
||
colServiceStatus: 'Service Status',
|
||
colExpiry: 'Expiry',
|
||
colActions: 'Actions',
|
||
view: 'View',
|
||
lifecycle: {
|
||
active: 'Active',
|
||
suspended: 'Suspended — Unpaid',
|
||
pending_deletion: 'Pending Deletion',
|
||
deleted: 'Deleted',
|
||
},
|
||
expired: 'Expired',
|
||
daysHours: '{d}d {h}h remaining',
|
||
hours: '{h}h remaining',
|
||
mins: '{m}m remaining',
|
||
noPlan: 'No plan',
|
||
deleteTitle: 'Delete Application',
|
||
deleteMessage:
|
||
'Permanently delete “{name}” and all its data?\n\nIf your plan still has time left, the prepaid resources will appear on your dashboard for use on a new app at no extra charge.',
|
||
deleted: 'Application deleted',
|
||
deletedWithCredit: 'Application deleted. Your prepaid resources are shown on the dashboard.',
|
||
},
|
||
services: {
|
||
title: 'Databases & Services',
|
||
subtitle: 'Standalone databases, Redis, and RabbitMQ — {n} service(s)',
|
||
newService: 'New Service',
|
||
noServices: 'No managed services yet',
|
||
emptyDesc: 'Provision a database, Redis, or RabbitMQ without deploying a full application.',
|
||
createFirst: 'Create your first service',
|
||
deleteTitle: 'Delete service?',
|
||
deleteMessage: 'Permanently delete “{name}”? This cannot be undone.',
|
||
deleted: 'Service deleted',
|
||
deletedWithCredit: 'Service deleted. Prepaid resources are on your dashboard.',
|
||
},
|
||
wallet: {
|
||
title: 'Wallet',
|
||
subtitle: 'Manage your balance and transactions',
|
||
currentBalance: 'Current Balance',
|
||
toman: 'Toman',
|
||
topUp: 'Top Up',
|
||
amountPlaceholder: 'Amount (Toman) — min 1,000',
|
||
payNow: 'Pay Now',
|
||
transactionHistory: 'Transaction History',
|
||
noTransactions: 'No transactions yet',
|
||
balanceAfter: 'Balance: {amount} {unit}',
|
||
invoice: 'Invoice {number}',
|
||
minChargeError: 'Minimum charge amount is 1,000 Toman',
|
||
chargedSuccess: 'Wallet charged successfully',
|
||
chargeFailed: 'Failed to charge wallet',
|
||
paymentSuccess: 'Payment successful — wallet charged',
|
||
paymentFailed: 'Payment failed',
|
||
topUpDesc: 'Wallet top-up',
|
||
topUpGatewayDesc: 'Wallet top-up via gateway',
|
||
txTypes: {
|
||
charge: 'Deposit',
|
||
deduction: 'Payment',
|
||
refund: 'Refund',
|
||
gateway_payment: 'Gateway payment',
|
||
},
|
||
},
|
||
tickets: {
|
||
status: { open: 'Open', waiting: 'Waiting', answered: 'Answered', closed: 'Closed' },
|
||
priority: { low: 'Low', medium: 'Medium', high: 'High' },
|
||
department: { technical: 'Technical', sales: 'Sales' },
|
||
departmentFull: { technical: 'Technical Support', sales: 'Sales' },
|
||
role: { admin: 'Admin', technical: 'Technical', sales: 'Sales' },
|
||
myTickets: 'My Tickets',
|
||
myTicketsSubtitle: 'Support tickets and their status',
|
||
newTicket: 'New Ticket',
|
||
createNewTicket: 'Create New Ticket',
|
||
subject: 'Subject',
|
||
subjectPlaceholder: 'Brief description of your issue',
|
||
departmentField: 'Department',
|
||
priorityField: 'Priority',
|
||
messageField: 'Message',
|
||
messagePlaceholder: 'Describe your issue in detail...',
|
||
submitTicket: 'Submit Ticket',
|
||
creating: 'Creating...',
|
||
noTickets: 'No tickets yet',
|
||
noTicketsHint: 'Create a ticket if you need help',
|
||
createdSuccess: 'Ticket created successfully',
|
||
createFailed: 'Failed to create ticket',
|
||
messages: '{n} message(s)',
|
||
msg: '{n} msg',
|
||
back: 'Back',
|
||
notFound: 'Ticket not found',
|
||
by: 'by',
|
||
closeTicket: 'Close Ticket',
|
||
closedNotice: 'This ticket is closed. Create a new ticket if you need further assistance.',
|
||
replyPlaceholder: 'Type your reply...',
|
||
send: 'Send',
|
||
replySent: 'Reply sent',
|
||
replyFailed: 'Failed to send reply',
|
||
ticketClosed: 'Ticket closed',
|
||
unknown: 'Unknown',
|
||
ticketsTitle: '{dept} Tickets',
|
||
totalTickets: '{n} total tickets',
|
||
unanswered: 'Unanswered',
|
||
needResponse: 'Need response',
|
||
answered: 'Answered',
|
||
waitingForUser: 'Waiting for user',
|
||
totalOpen: 'Total Open',
|
||
excludingClosed: 'Excluding closed',
|
||
all: 'All',
|
||
noTicketsStaff: 'No tickets',
|
||
noStatusTickets: 'No {status} tickets',
|
||
noDeptTickets: 'No tickets in this department',
|
||
allTickets: 'All Tickets',
|
||
allTicketsSubtitle: 'Overview of all support tickets across departments',
|
||
totalTicketsStat: 'Total Tickets',
|
||
needStaffResponse: 'Need staff response',
|
||
avgResponseTime: 'Avg Response Time',
|
||
byDepartment: 'By Department',
|
||
departmentLabel: 'Department:',
|
||
statusLabel: 'Status:',
|
||
noTicketsFound: 'No tickets found',
|
||
minutes: '{n} min',
|
||
hours: '{n} hours',
|
||
days: '{n} days',
|
||
},
|
||
invoices: {
|
||
status: {
|
||
draft: 'Draft',
|
||
issued: 'Unpaid',
|
||
partially_paid: 'Partially paid',
|
||
paid: 'Paid',
|
||
void: 'Void',
|
||
failed: 'Failed',
|
||
},
|
||
title: 'Invoices',
|
||
subtitle: 'Review what each payment was for and pay open invoices.',
|
||
subtotal: 'Subtotal',
|
||
walletBalance: 'Wallet balance',
|
||
toman: 'Toman',
|
||
filterAll: 'All',
|
||
filterUnpaid: 'Unpaid',
|
||
loadingInvoices: 'Loading invoices...',
|
||
noInvoices: 'No invoices found',
|
||
total: 'Total',
|
||
due: 'Due',
|
||
paidLabel: 'Paid',
|
||
method: 'Method',
|
||
selectInvoice: 'Select an invoice to view details',
|
||
downloadPdf: 'Download PDF',
|
||
lineItems: 'Line items',
|
||
payment: 'Payment',
|
||
walletCoversNote: 'Wallet balance covers {wallet} Toman. The remaining {rest} Toman will be paid through the gateway.',
|
||
processing: 'Processing...',
|
||
pay: 'Pay',
|
||
paidOn: 'Paid on {date}',
|
||
paymentFailed: 'Payment failed',
|
||
waitingRemaining: 'Waiting for the remaining payment.',
|
||
paymentComplete: 'Payment complete',
|
||
paymentCompleteUpdated: 'Payment complete and service updated',
|
||
gatewayFailed: 'Gateway payment failed',
|
||
invoicePaid: 'Invoice paid',
|
||
invoicePaidUpdated: 'Invoice paid and service updated',
|
||
downloadFailed: 'Failed to download invoice PDF',
|
||
adminTitle: 'Invoice Management',
|
||
adminSubtitle: 'Track all user invoices, payments, gateway refs, and wallet transactions.',
|
||
searchPlaceholder: 'Search invoice, email, or application',
|
||
allStatuses: 'All statuses',
|
||
allMethods: 'All methods',
|
||
methodWallet: 'Wallet',
|
||
methodGateway: 'Gateway',
|
||
methodMixed: 'Mixed',
|
||
colInvoice: 'Invoice',
|
||
colUser: 'User',
|
||
colStatus: 'Status',
|
||
colMethod: 'Method',
|
||
colDue: 'Due',
|
||
selectInvoiceShort: 'Select an invoice',
|
||
tracking: 'Tracking',
|
||
transactions: 'Transactions',
|
||
noTransactions: 'No linked transactions yet',
|
||
manualStatusChange: 'Manual status change',
|
||
reasonPlaceholder: 'Reason is required for audit visibility',
|
||
failedBtn: 'Failed',
|
||
voidBtn: 'Void',
|
||
statusUpdated: 'Invoice status updated',
|
||
statusUpdateFailed: 'Failed to update invoice status',
|
||
reasonRequired: 'Reason is required for manual status changes',
|
||
pdf: {
|
||
documentTitle: 'Invoice',
|
||
tagline: 'Cloud infrastructure, in your control',
|
||
invoiceNumberLabel: 'Invoice number',
|
||
colIndex: '#',
|
||
colDesc: 'Description',
|
||
colAmount: 'Amount',
|
||
customer: 'Customer',
|
||
phone: 'Phone',
|
||
application: 'Application',
|
||
createdAt: 'Issued on',
|
||
paidAt: 'Paid on',
|
||
subtotal: 'Subtotal',
|
||
generatedAt: 'This document was generated automatically on {date}.',
|
||
footer: 'Abrban — abrban.com',
|
||
},
|
||
},
|
||
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.',
|
||
elasticDisabledTitle: 'Elasticsearch logging is off',
|
||
elasticDisabledMessage: 'You did not enable Elasticsearch for this application when creating it, so centralized logs are unavailable. Enable the Elasticsearch addon when deploying a new app to see its logs here.',
|
||
elasticDisabledMessageAll: 'None of your applications have Elasticsearch enabled, so centralized logs are unavailable. Enable the Elasticsearch addon when deploying a new app to see its logs here.',
|
||
},
|
||
users: {
|
||
title: 'User Management',
|
||
count: '{n} user(s) registered',
|
||
addUser: 'Add User',
|
||
createNewUser: 'Create New User',
|
||
firstName: 'First Name',
|
||
lastName: 'Last Name',
|
||
phone: 'Mobile number',
|
||
email: 'Email',
|
||
emailOptional: 'Email (optional)',
|
||
password: 'Password',
|
||
firstNamePlaceholder: 'John',
|
||
lastNamePlaceholder: 'Doe',
|
||
phonePlaceholder: '09123456789',
|
||
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, mobile or email...',
|
||
noUsersSearch: 'No users found matching your search.',
|
||
noUsers: 'No users yet.',
|
||
colUser: 'User',
|
||
colPhone: 'Mobile',
|
||
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',
|
||
detail: {
|
||
back: 'Back',
|
||
notFound: 'User not found',
|
||
loading: 'Loading…',
|
||
viewDetails: 'View details',
|
||
tabOverview: 'Overview',
|
||
tabApplications: 'Applications',
|
||
tabActivity: 'Activity',
|
||
tabErrors: 'Errors',
|
||
tabTickets: 'Tickets',
|
||
accountStatus: 'Account status',
|
||
basicInfo: 'Basic info',
|
||
walletBalance: 'Wallet balance',
|
||
revenue: 'Revenue generated',
|
||
totalCharged: 'Total charged',
|
||
totalRefunded: 'Total refunded',
|
||
joinedAt: 'Joined',
|
||
namespace: 'Namespace',
|
||
recentTransactions: 'Recent transactions',
|
||
noTransactions: 'No transactions yet.',
|
||
countsTitle: 'Summary',
|
||
appsTotal: 'Total applications',
|
||
appsActive: 'Active apps',
|
||
appsDeleted: 'Deleted / archived apps',
|
||
managedServices: 'Managed services',
|
||
optionalServices: 'Add-on services',
|
||
deploymentsCount: 'Deployments',
|
||
ticketsOpenCount: 'Open tickets',
|
||
txType: 'Type',
|
||
txAmount: 'Amount',
|
||
txBalance: 'Balance after',
|
||
txDesc: 'Description',
|
||
txDate: 'Date',
|
||
txTypes: { charge: 'Charge', deduction: 'Deduction', refund: 'Refund', gateway_payment: 'Gateway payment' },
|
||
appName: 'Name',
|
||
appType: 'Type',
|
||
appStatus: 'Status',
|
||
appExpires: 'Service expiry',
|
||
appCreated: 'Created',
|
||
appResources: 'Resources',
|
||
activeApps: 'Active apps',
|
||
deletedApps: 'Deleted / archived apps',
|
||
noApps: 'No applications.',
|
||
expired: 'Expired',
|
||
remainingDays: '{n} days left',
|
||
remainingHours: '{n} hours left',
|
||
lifecycle: { active: 'Active', suspended: 'Suspended', pending_deletion: 'Pending deletion', docked: 'Archived', deleted: 'Deleted' },
|
||
restore: { restorable: 'Restorable', recoverable: 'Recoverable with payment', none: 'Not restorable' },
|
||
errorApp: 'Application',
|
||
errorReason: 'Error reason',
|
||
errorTime: 'Time',
|
||
errorState: 'State',
|
||
errorResolved: 'Resolved',
|
||
errorOpen: 'Open',
|
||
noErrors: 'No build/deploy errors.',
|
||
noErrorMessage: 'No error message recorded.',
|
||
viewLogs: 'View logs',
|
||
hideLogs: 'Hide logs',
|
||
buildLog: 'Build log',
|
||
deployLog: 'Deploy log',
|
||
noLog: 'No log available.',
|
||
noActivity: 'No activity recorded.',
|
||
activityTypes: { app_created: 'Application created', app_docked: 'Application archived', app_deleted: 'Application deleted', deployment: 'Deployment', transaction: 'Wallet transaction', ticket: 'Support ticket' },
|
||
ticketSubject: 'Subject',
|
||
ticketStatus: 'Status',
|
||
ticketDept: 'Department',
|
||
ticketPriority: 'Priority',
|
||
ticketMessages: '{n} messages',
|
||
noTickets: 'No tickets.',
|
||
viewConversation: 'View conversation',
|
||
hideConversation: 'Hide conversation',
|
||
ticketStatuses: { open: 'Open', answered: 'Answered', waiting: 'Waiting', closed: 'Closed' },
|
||
ticketDepts: { technical: 'Technical', sales: 'Sales' },
|
||
ticketPriorities: { low: 'Low', medium: 'Medium', high: 'High' },
|
||
senderRoles: { user: 'User', admin: 'Admin', technical: 'Technical support', sales: 'Sales' },
|
||
loginAsUser: 'Login as user',
|
||
impersonateFailed: 'Failed to start impersonation',
|
||
impersonatingBanner: 'You are viewing the panel as "{name}"',
|
||
exitImpersonation: 'Exit user mode',
|
||
tabAudit: 'Admin access log',
|
||
auditAction: 'Event',
|
||
auditAdmin: 'Admin',
|
||
auditTime: 'Time',
|
||
auditIp: 'IP',
|
||
noAudit: 'No admin access recorded.',
|
||
auditActions: { impersonation_start: 'Logged in as user', impersonation_stop: 'Exited user mode' },
|
||
},
|
||
},
|
||
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' },
|
||
},
|
||
clusters: {
|
||
title: 'Cluster Management',
|
||
count: '{n} cluster(s) registered',
|
||
addCluster: 'Add Cluster',
|
||
registerNew: 'Register New Cluster',
|
||
verifyNote: 'The system will verify the Kubernetes connection before registering.',
|
||
name: 'Name',
|
||
apiServer: 'API Server URL',
|
||
region: 'Region',
|
||
provider: 'Provider',
|
||
selectProvider: 'Select provider',
|
||
weight: 'Weight',
|
||
tags: 'Tags',
|
||
tagsPlaceholder: 'ssd, production, iran',
|
||
description: 'Description',
|
||
kubeconfig: 'Kubeconfig (YAML)',
|
||
kubeconfigPlaceholder: 'Paste your kubeconfig here...',
|
||
setDefault: 'Set as default cluster',
|
||
verifying: 'Verifying connection & adding...',
|
||
added: 'Cluster added & connection verified ✓',
|
||
addFailed: 'Failed to add cluster',
|
||
connectionOk: 'Connection OK — Kubernetes {version}',
|
||
connectionFailed: 'Connection failed: {error}',
|
||
testFailed: 'Failed to test connection',
|
||
removed: 'Cluster removed',
|
||
noClusters: 'No clusters registered yet.',
|
||
noClustersHint: 'Add a Kubernetes cluster to start deploying applications.',
|
||
defaultBadge: 'Default',
|
||
healthBadge: 'health: {status}',
|
||
weightBadge: 'weight {n}',
|
||
resources: 'Resources',
|
||
testing: 'Testing...',
|
||
test: 'Test',
|
||
remove: 'Remove',
|
||
removeTitle: 'Remove Cluster',
|
||
removeMessage: 'Are you sure you want to remove “{name}”?',
|
||
loadingResources: 'Loading resources...',
|
||
resourcesFailed: 'Failed to load resources',
|
||
nodes: 'Nodes',
|
||
pods: 'Pods',
|
||
apps: 'Apps',
|
||
totalCpu: 'Total CPU',
|
||
cpuReserved: 'CPU Reserved',
|
||
memReserved: 'Memory Reserved',
|
||
memory: 'Memory',
|
||
capacity: 'capacity',
|
||
allocatable: 'allocatable',
|
||
colName: 'Name',
|
||
colStatus: 'Status',
|
||
colRoles: 'Roles',
|
||
colCpu: 'CPU (Cap / Alloc)',
|
||
colMemory: 'Memory (Cap / Alloc)',
|
||
toolsTitle: 'Tools Management',
|
||
toolsSubtitle: 'Install and manage infrastructure tools per cluster. Nothing is installed automatically — add only what each cluster needs.',
|
||
defaultSuffix: ' (default)',
|
||
loadingTools: 'Loading tools…',
|
||
toolsFailed: 'Failed to load tools for this cluster.',
|
||
toolStatus: {
|
||
installed: 'Installed',
|
||
installing: 'Installing…',
|
||
failed: 'Failed',
|
||
not_installed: 'Not installed',
|
||
unknown: 'Unknown',
|
||
},
|
||
requires: 'Requires:',
|
||
uninstall: 'Uninstall',
|
||
uninstalling: 'Removing…',
|
||
install: 'Install',
|
||
installing: 'Installing…',
|
||
repair: 'Repair',
|
||
confirmInstall: 'Confirm install',
|
||
installRequiredFirst: 'Install required tools first',
|
||
removeToolTitle: 'Remove {name}',
|
||
removeToolMessage: 'Uninstall “{name}” from this cluster?',
|
||
uninstallConfirm: 'Uninstall',
|
||
installStarted: '{name} install started',
|
||
installToolFailed: 'Failed to install {name}',
|
||
toolRemoved: '{name} removed',
|
||
removeToolFailed: 'Failed to remove {name}',
|
||
fieldRequired: '{field} is required',
|
||
clusterStatus: { active: 'active', maintenance: 'maintenance', inactive: 'inactive', error: 'error' },
|
||
clusterHealth: { healthy: 'healthy', degraded: 'degraded', unhealthy: 'unhealthy', unknown: 'unknown' },
|
||
na: 'N/A',
|
||
},
|
||
billing: {
|
||
cycles: { hourly: 'Hourly', monthly: 'Monthly', yearly: 'Yearly' },
|
||
resources: {
|
||
base_fee: 'Base fee',
|
||
cpu_per_core: 'CPU (per core)',
|
||
memory_per_gb: 'Memory (per GB)',
|
||
storage_per_gb: 'Storage (per GB)',
|
||
database_addon: 'Database addon',
|
||
redis_addon: 'Redis',
|
||
rabbitmq_addon: 'RabbitMQ',
|
||
elasticsearch_addon: 'Elasticsearch',
|
||
custom_domain_addon: 'Custom domain + SSL',
|
||
},
|
||
resourceCol: 'Resource',
|
||
title: 'Billing Plans',
|
||
subtitle: 'Set unit prices per resource. Users choose CPU, memory, and storage when deploying; cost = their usage × these rates.',
|
||
editPlans: 'Edit plans',
|
||
saving: 'Saving...',
|
||
save: 'Save',
|
||
saved: 'Billing plans saved',
|
||
saveFailed: 'Failed to save billing plans',
|
||
howTitle: 'How billing works',
|
||
howApps: 'Applications — user picks runtime resources in deploy; you set price per core, GB, base fee, and database addon. CPU and RAM in estimates bill proportionally (for example half the per-GB rate at half a gigabyte of memory).',
|
||
howOptional: 'Optional services (Redis, RabbitMQ) — same unit matrix per service as runtimes; deploy wizard defaults are edited separately. CPU/RAM in the cost calculator bill in proportion to actual limits (e.g. 500Mi counts as 0.5× the per-GB memory rate).',
|
||
howDefaults: 'Deploy defaults — optional prefill only; changing them does not change what existing apps pay unless the user chose those values at deploy.',
|
||
noPricing: 'No pricing data',
|
||
appRuntimes: 'Application runtimes',
|
||
appRuntimesSub: 'Unit pricing per runtime (hourly / monthly / yearly)',
|
||
unitPricesSuffix: '— unit prices',
|
||
fillYearly: 'Fill yearly from monthly ×12',
|
||
optionalServices: 'Optional services',
|
||
optionalServicesSub: 'Unit pricing per service (hourly / monthly / yearly)',
|
||
deployDefaults: 'Optional services — deploy defaults',
|
||
deployDefaultsSub: 'Prefill CPU, memory, and storage when a user enables each service in the deploy wizard',
|
||
addons: 'Add-ons',
|
||
addonsSub: 'Flat fees not tied to a runtime',
|
||
customDomainTitle: 'Custom domain + SSL',
|
||
customDomainSub: 'Flat fee per billing cycle (not resource-based)',
|
||
loggingNote: 'Prefilled limits for Fluent Bit log shippers (billed per enabled workload when logging is on).',
|
||
logShipperCpuLimit: 'Log shipper CPU limit',
|
||
logShipperMemoryLimit: 'Log shipper memory limit',
|
||
defaultsNote: 'Shown when a user enables this service in deploy. They can change CPU, memory, and storage in Resources & Configuration; actual billing uses their choices × unit prices below.',
|
||
cpuRequest: 'CPU request',
|
||
cpuLimit: 'CPU limit',
|
||
memoryRequest: 'Memory request',
|
||
memoryLimit: 'Memory limit',
|
||
storageGi: 'Storage (Gi)',
|
||
oneCore: '1 core',
|
||
twoCores: '2 cores',
|
||
retentionTitle: 'Data Retention & Deletion Policy',
|
||
edit: 'Edit',
|
||
retentionSub: 'Configure how long user data is retained after plan expiration before permanent deletion.',
|
||
hourlyPlans: 'Hourly Plans',
|
||
monthlyPlans: 'Monthly Plans',
|
||
yearlyPlans: 'Yearly Plans',
|
||
deleteAfterHours: 'Delete after (hours):',
|
||
deleteAfterDays: 'Delete after (days):',
|
||
saveSettings: 'Save Settings',
|
||
lifecycleSaved: 'Lifecycle settings updated',
|
||
saveFailedShort: 'Failed to save',
|
||
hours: 'hours',
|
||
days: 'days',
|
||
globalDiscount: {
|
||
title: 'Platform-wide discount',
|
||
subtitle: 'A single percentage applied to every price and real invoice. 0 means no discount.',
|
||
label: 'Global discount %',
|
||
hint: 'A number between 0 and 100',
|
||
save: 'Save discount',
|
||
saving: 'Saving…',
|
||
saved: 'Global discount saved',
|
||
edit: 'Edit',
|
||
cancel: 'Cancel',
|
||
none: 'No platform-wide discount is currently active.',
|
||
active: 'A {p}% discount is active on all services.',
|
||
},
|
||
discounts: {
|
||
title: 'Discount codes',
|
||
subtitle: 'Percentage discounts on different services — public or for specific users.',
|
||
add: 'New discount',
|
||
empty: 'No discount codes yet',
|
||
edit: 'Edit',
|
||
delete: 'Delete',
|
||
deleteConfirm: 'Delete this discount code?',
|
||
code: 'Code',
|
||
codePlaceholder: 'NOWRUZ1403',
|
||
name: 'Label',
|
||
namePlaceholder: 'Nowruz discount',
|
||
description: 'Description',
|
||
percentOff: 'Percent off',
|
||
scope: 'Eligible services',
|
||
allServices: 'All services',
|
||
selectServices: 'Select specific services',
|
||
audience: 'Eligible users',
|
||
public: 'Public (all users)',
|
||
restricted: 'Specific users',
|
||
searchUsers: 'Search users by name or email…',
|
||
noUsersSelected: 'No users selected yet',
|
||
limits: 'Limits',
|
||
maxUses: 'Total usage cap',
|
||
maxUsesPerUser: 'Per-user cap',
|
||
unlimited: 'Unlimited',
|
||
startsAt: 'Start date',
|
||
endsAt: 'End date',
|
||
active: 'Active',
|
||
inactive: 'Inactive',
|
||
used: 'Used',
|
||
save: 'Save',
|
||
saving: 'Saving…',
|
||
cancel: 'Cancel',
|
||
saved: 'Discount code saved',
|
||
deleted: 'Discount code deleted',
|
||
saveFailed: 'Failed to save discount code',
|
||
groups: {
|
||
runtime: 'App runtimes',
|
||
optional: 'Optional services',
|
||
managed: 'Managed services',
|
||
addon: 'Add-ons',
|
||
},
|
||
coupon: {
|
||
label: 'Discount code',
|
||
placeholder: 'Enter discount code',
|
||
apply: 'Apply',
|
||
checking: 'Checking…',
|
||
applied: 'Discount applied',
|
||
remove: 'Remove',
|
||
discountLine: 'Discount',
|
||
},
|
||
reasons: {
|
||
not_found: 'Invalid discount code',
|
||
inactive: 'This discount code is inactive',
|
||
not_started: 'This code is not active yet',
|
||
expired: 'This code has expired',
|
||
max_uses_reached: 'This code has reached its usage limit',
|
||
max_uses_per_user_reached: 'You have reached your usage limit for this code',
|
||
not_eligible_user: 'This code is not available for your account',
|
||
no_eligible_services: 'This code does not discount your selected services',
|
||
},
|
||
},
|
||
},
|
||
servicesNew: {
|
||
steps: ['Service type', 'Configuration', 'Review & pay'],
|
||
title: 'New managed service',
|
||
subtitle: 'Database, Redis, or RabbitMQ — billed like applications',
|
||
typeDatabase: 'Database',
|
||
typeDatabaseDesc: 'PostgreSQL, MySQL, MariaDB, MongoDB',
|
||
typeRedis: 'Redis',
|
||
typeRedisDesc: 'In-memory cache & store',
|
||
typeRabbitmq: 'RabbitMQ',
|
||
typeRabbitmqDesc: 'Message broker',
|
||
serviceName: 'Service name',
|
||
serviceNamePlaceholder: 'my-database',
|
||
nameHint: 'Lowercase letters, numbers, and hyphens only',
|
||
redisVersion: 'Redis version',
|
||
rabbitmqVersion: 'RabbitMQ version',
|
||
redisResources: 'Redis resources',
|
||
rabbitmqResources: 'RabbitMQ resources',
|
||
billingCycle: 'Billing cycle',
|
||
cycles: { hourly: 'Hourly', monthly: 'Monthly', yearly: 'Yearly' },
|
||
paymentMethod: 'Payment method',
|
||
wallet: 'Wallet',
|
||
insufficient: 'Insufficient',
|
||
payNow: 'Pay now',
|
||
pricingUnavailable: 'Pricing unavailable',
|
||
back: 'Back',
|
||
next: 'Next',
|
||
payProvision: 'Pay & provision',
|
||
provisioning: 'Provisioning service',
|
||
creatingService: 'Creating service',
|
||
uploadingDump: 'Uploading database dump',
|
||
payment: 'Payment',
|
||
deploying: 'Deploying',
|
||
provisionedSuccess: 'Service provisioned successfully',
|
||
deployFailed: 'Deploy failed',
|
||
paySucceededDeployFailed: 'Payment succeeded but deployment failed',
|
||
payProvisionFailed: 'Payment or provisioning failed',
|
||
payFailed: 'Payment failed',
|
||
insufficientBalance: 'Insufficient wallet balance',
|
||
serviceDesc: 'Service: {name} ({cycle})',
|
||
},
|
||
serviceDetail: {
|
||
productTypes: {
|
||
managed_database: 'Managed Database',
|
||
managed_redis: 'Managed Redis',
|
||
managed_rabbitmq: 'Managed RabbitMQ',
|
||
},
|
||
deploy: 'Deploy',
|
||
redeploy: 'Redeploy',
|
||
redeployTitle: 'Re-run Helm install for this service',
|
||
restart: 'Restart',
|
||
deleteServiceTitle: 'Delete service?',
|
||
deleteServiceMessage: 'Delete “{name}” permanently?',
|
||
provisioningStarted: 'Provisioning started',
|
||
provisioningFailed: 'Failed to start provisioning',
|
||
reprovisioningStarted: 'Re-provisioning started',
|
||
reprovisionFailed: 'Failed to re-provision service',
|
||
serviceRestarted: 'Service restarted',
|
||
restartFailed: 'Failed to restart service',
|
||
serviceRenewed: 'Service renewed',
|
||
renewalFailed: 'Renewal failed',
|
||
deletedWithCredit: 'Service deleted. Prepaid resources are on your dashboard.',
|
||
deleted: 'Service deleted',
|
||
deleteFailed: 'Failed to delete',
|
||
paymentRequired: 'Payment required',
|
||
renewToRestore: 'Renew to restore this service.',
|
||
renew: 'Renew',
|
||
planExpires: 'Plan expires: {date}',
|
||
configuration: 'Configuration',
|
||
serviceType: 'Service type',
|
||
databaseEngine: 'Database engine',
|
||
storage: 'Storage',
|
||
redisVersion: 'Redis version',
|
||
rabbitmqVersion: 'RabbitMQ version',
|
||
cpu: 'CPU',
|
||
memory: 'Memory',
|
||
billing: 'Billing',
|
||
deployMarker: 'Deploy marker',
|
||
deploymentHistory: 'Deployment History',
|
||
noDeployments: 'No deployments yet',
|
||
noDeploymentsHint: 'Click Deploy to provision this service',
|
||
provision: 'Provision',
|
||
connection: 'Connection',
|
||
internalCluster: 'Internal cluster',
|
||
host: 'Host',
|
||
port: 'Port',
|
||
database: 'Database',
|
||
username: 'Username',
|
||
password: 'Password',
|
||
useExternalNote: 'Use external access below for internet-facing connections.',
|
||
hideSecrets: 'Hide secrets',
|
||
showSecrets: 'Show secrets',
|
||
redisInternal: 'Redis (internal)',
|
||
rabbitmqInternal: 'RabbitMQ (internal)',
|
||
url: 'URL',
|
||
amqpPort: 'AMQP Port',
|
||
managementPort: 'Management Port',
|
||
amqpUrl: 'AMQP URL',
|
||
managementUrl: 'Management URL',
|
||
deployToLoadCreds: 'Deploy the service to load live credentials.',
|
||
loadingLogs: 'Loading logs...',
|
||
serviceStopped: 'Service is stopped.',
|
||
deployToSeeLogs: 'Deploy or re-provision the service to see workload logs.',
|
||
renewService: 'Renew service',
|
||
wallet: 'Wallet',
|
||
payFromWallet: 'Pay from wallet',
|
||
insufficientRenew: 'Insufficient wallet balance. Top up your wallet or pay via invoice.',
|
||
cycles: { hourly: 'Hourly', monthly: 'Monthly', yearly: 'Yearly' },
|
||
},
|
||
adminApps: {
|
||
title: 'All Applications',
|
||
count: '{n} application(s)',
|
||
matching: ' matching "{q}"',
|
||
lifecycle: { active: 'Active', suspended: 'Suspended — Unpaid', pending_deletion: 'Pending Deletion', deleted: 'Deleted' },
|
||
cycles: { hourly: 'Hourly', monthly: 'Monthly', yearly: 'Yearly' },
|
||
expired: 'Expired', dayShort: 'd', hourShort: 'h', minShort: 'm',
|
||
countRunning: 'Running', countDeploying: 'Deploying', countPending: 'Pending',
|
||
countStopped: 'Stopped', countFailed: 'Failed', countSuspended: 'Suspended', countPendingDel: 'Pending Del.',
|
||
searchPlaceholder: 'Search by app name, user name, email, or user ID…',
|
||
noAppsFound: 'No applications found', noResultsFor: 'No results for "{q}". Try a different search.',
|
||
noAppsYet: 'No applications yet', noAppsByUser: 'No applications have been created by any user.',
|
||
colApplication: 'Application', colOwner: 'Owner', colStatus: 'Status', colService: 'Service', colCluster: 'Cluster',
|
||
colMigration: 'Migration', colPlanExpiry: 'Plan / Expiry', colActions: 'Actions',
|
||
unknownCluster: 'Unknown cluster', notAssigned: 'Not assigned', noPlan: 'No plan', deletePrefix: 'Delete: {date}',
|
||
cluster: 'Cluster', plan: 'Plan', unknown: 'Unknown', na: 'N/A',
|
||
view: 'View', migrate: 'Migrate', notAssignedTooltip: 'Application is not assigned to a cluster',
|
||
deleteAppTitle: 'Delete Application', deleteAppConfirm: 'Are you sure you want to delete "{name}"?',
|
||
replicas: '{n} replica(s)',
|
||
migrateApplication: 'Migrate Application',
|
||
moveTo: 'Move {name} to a healthy target cluster with logs, retry, and rollback.',
|
||
targetCluster: 'Target Cluster', currentCluster: 'Current cluster',
|
||
unknownClusterShort: 'Unknown cluster ({id})',
|
||
selectHealthyCluster: 'Select healthy cluster',
|
||
currentExcludedNote: 'The current cluster is excluded. Migration is blocked for unhealthy, inactive, or maintenance clusters.',
|
||
noOtherCluster: 'No other cluster is available as a migration target.',
|
||
latestMigration: 'Latest migration', queued: 'queued', attempts: 'attempts',
|
||
noEvents: 'No events yet.', retryMigration: 'Retry migration',
|
||
startMigration: 'Start Migration', queueing: 'Queueing...',
|
||
appDeleted: 'Application deleted', migrationQueued: 'Migration job queued', migrationQueueFailed: 'Failed to queue migration',
|
||
migrationRetryQueued: 'Migration retry queued', migrationRetryFailed: 'Failed to retry migration',
|
||
migrationStatus: { completed: 'completed', failed: 'failed', rolled_back: 'rolled back', running: 'running', rolling_back: 'rolling back', queued: 'queued' },
|
||
},
|
||
appDetail: {
|
||
productTypeApp: 'Application',
|
||
cycles: { hourly: 'Hourly', monthly: 'Monthly', yearly: 'Yearly' },
|
||
deploy: 'Deploy', redeploy: 'Redeploy', start: 'Start', stop: 'Stop', restart: 'Restart',
|
||
preview: 'Preview', delete: 'Delete', renewNow: 'Renew Now', renewApplication: 'Renew Application',
|
||
rebuildTitle: 'Rebuild from latest source code', instantRollback: 'Instant rollback',
|
||
deploymentTriggered: 'Deployment triggered!', deployFailed: 'Failed to trigger deployment',
|
||
redeployStarted: 'Redeploy started', redeployFailed: 'Failed to trigger redeploy',
|
||
appStarted: 'Application started', startFailed: 'Failed to start application',
|
||
appStopped: 'Application stopped', stopFailed: 'Failed to stop application',
|
||
appRestarting: 'Application restarting...', restartFailed: 'Failed to restart application',
|
||
sourceUploaded: 'Source code uploaded successfully!', uploadFailed: 'Failed to upload source code',
|
||
uploadSourceFirst: 'Upload source code and click Deploy to get started',
|
||
sourceCodeUploaded: 'Source code uploaded',
|
||
fileMax10: 'File size must be at most 10 GB', fileZipOnly: 'Please upload a .zip or .tar.gz file',
|
||
previewHttps: 'Preview opened on HTTPS preview domain.', previewPort: 'Preview opened on port {port}',
|
||
previewFailed: 'Failed to get preview URL. Make sure the app is deployed.',
|
||
domainSet: 'Domain set. Please configure your DNS records.',
|
||
domainVerified: 'Domain verified successfully!',
|
||
customDomainRemoved: 'Custom domain removed',
|
||
removeDomainTitle: 'Remove Custom Domain',
|
||
removeDomainConfirm: 'Are you sure you want to remove "{domain}"? The website will only be accessible via the platform domain.',
|
||
remove: 'Remove',
|
||
copied: 'Copied!', copy: 'Copy',
|
||
resourcesUpdated: 'Resources updated', updateResourcesFailed: 'Failed to update resources',
|
||
resourcesUpdatedSuccess: 'Resources updated successfully!', noChanges: 'No changes to apply',
|
||
renewFirst: 'Renew the application before changing resources',
|
||
upgradedPaid: 'Resources upgraded! Paid {amount} Toman',
|
||
upgradeFailed: 'Failed to upgrade resources', calcFailed: 'Failed to calculate upgrade cost',
|
||
invoiceCreated: 'Invoice created. Choose how you want to pay.', invoiceFailed: 'Failed to create upgrade invoice',
|
||
dbRestored: 'Database restored successfully!', dbRestoreFailed: 'Database restore failed.', dbInvalidFile: 'Please upload a .sql, .dump, or .gz file',
|
||
fileMax500: 'File size must be less than 500MB', dbUploadFailed: 'Failed to upload database dump',
|
||
snapshotStarted: 'Snapshot creation started', snapshotCreateFailed: 'Failed to create snapshot',
|
||
snapshotDeleted: 'Snapshot deleted', snapshotDeleteFailed: 'Failed to delete snapshot',
|
||
deleteSnapshotTitle: 'Delete snapshot?', deleteSnapshotMessage: 'Delete "{label}"? The archived files will be permanently removed.',
|
||
deleteSnapshot: 'Delete snapshot',
|
||
rollbackFailed: 'Rollback failed', rollbackCompleted: 'Rollback completed:\n',
|
||
rollbackSnapTitle: 'Rollback to "{label}"?',
|
||
rollbackSnapMessage: 'This will restore:\n• App deployment via K8s revision (instant)\n• wp-content files (WordPress)\n• Database dump\n\nThe current state will be overwritten.',
|
||
rollbackRevTitle: 'Rollback to Revision {n}?',
|
||
rollbackRevMessage: 'This will rollback the Helm release to revision {n}.{cause}\n\nNo rebuild needed — takes effect in seconds.',
|
||
description: 'Description',
|
||
deleteAppTitle: 'Delete "{name}"?',
|
||
deleteAppMessage: 'This will permanently remove all Kubernetes resources, data, and deployment records.\n\n',
|
||
deleteAppCredit: 'Your remaining paid resources will appear on the dashboard for use on a new app at no extra charge.',
|
||
appDeleted: 'Application deleted', appDeletedCredit: 'Application deleted. Prepaid resources are on your dashboard.',
|
||
deleteAppFailed: 'Failed to delete application',
|
||
downloadInProgress: 'A download is already in progress. Please wait.',
|
||
downloading: 'Downloading {name}... This may take up to 15 minutes for large files.',
|
||
downloadedSuccess: '{name} downloaded successfully!',
|
||
downloadTimeout: 'Download timed out after 15 minutes. Try again or check server logs.',
|
||
downloadFailed: 'Failed to download {name}', downloadCurrentFailed: 'Failed to download current {name}',
|
||
configuration: 'Configuration', runtime: 'Runtime', image: 'Image', status: 'Status',
|
||
cpu: 'CPU', memory: 'Memory', replicas: 'Replicas', cluster: 'Cluster', pool: 'Pool', workload: 'Workload', port: 'Port',
|
||
cpuRequest: 'CPU Request', cpuLimit: 'CPU Limit', memoryRequest: 'Memory Request', memoryLimit: 'Memory Limit',
|
||
database: 'Database', databaseVolume: 'Database volume', gitConnected: 'Git repository connected',
|
||
deployMarker: 'Deploy marker', billing: 'Billing', name: 'Name', domain: 'Domain',
|
||
deploymentHistory: 'Deployment History', noDeployments: 'No deployments yet',
|
||
uploadToStart: 'Upload source code and click Deploy to get started',
|
||
sourceCode: 'Source Code', replace: 'Replace', uploadSourceClick: 'Upload source code and click Deploy to get started',
|
||
customDomain: 'Custom Domain', addCustomDomain: 'Add Custom Domain', setUpCustomDomain: 'Set Up Custom Domain',
|
||
appDomain: 'Application Domain', copyDomainHint: 'Click to copy',
|
||
platformDomain: 'Platform Domain', domainPlaceholder: 'example.com or www.example.com', dnsSetupGuide: 'DNS Setup Guide',
|
||
removeCustomDomain: 'Remove Custom Domain',
|
||
resourcesScaling: 'Resources & Scaling', monitor: 'Monitor', hide: 'Hide', show: 'Show',
|
||
liveUsage: 'Live usage', loadingMetrics: 'Loading metrics...', metrics: 'Metrics', pods: 'Pods', ready: 'Ready', restarts: 'Restarts',
|
||
noMetrics: 'No metrics yet', storageUsage: 'Storage Usage', loadingStorageMetrics: 'Loading storage metrics...',
|
||
noStorageData: 'No storage data available', storageMetricsUnavailable: 'Storage metrics unavailable',
|
||
used: 'Used', applyChanges: 'Apply Changes', applying: 'Applying...', processing: 'Processing...',
|
||
newSnapshot: 'New Snapshot', creating: 'Creating...',
|
||
k8sRevisions: 'K8s Revisions', fileSnapshots: 'File Snapshots', fullSnapshots: 'Full snapshots',
|
||
loadingRevisions: 'Loading revisions...', noRevisions: 'No revisions available',
|
||
revisionsAfterDeploy: 'Revisions appear after the first deployment.',
|
||
loadingSnapshots: 'Loading snapshots...', noSnapshots: 'No snapshots yet',
|
||
maxSnapshots: 'Maximum 10 snapshots are kept. Older snapshots are automatically deleted.',
|
||
rollback: 'Rollback', instant: 'Instant', current: 'Current', full: 'Full',
|
||
instantRollbackTitle: 'Instant rollback to this revision',
|
||
rollbackSnapTitleBtn: 'Rollback to this snapshot (uses K8s revision + restores DB/wp-content)',
|
||
downloadCurrentState: 'Download Current State',
|
||
downloadCurrentNote: 'Download a copy of the current live files without creating a snapshot. Large files may take up to 15 minutes.',
|
||
downloadSource: 'Download source code', downloadWpContent: 'Download wp-content', downloadDatabaseDump: 'Download database dump',
|
||
sourceCodeArtifact: 'Source code', databaseDump: 'Database Dump', downloading2: 'Downloading...',
|
||
restoreDatabaseDump: 'Restore Database Dump', uploadSqlToRestore: 'Upload SQL dump to restore',
|
||
restoringDatabase: 'Restoring database...', restoreOutput: 'Restore Output',
|
||
dbOnlyInternal: 'Database is only accessible within the cluster. Not exposed externally.',
|
||
serviceCredentials: 'Service Credentials', serviceCredsAfterDeploy: 'Service passwords are available after the application is deployed.',
|
||
password: 'Password',
|
||
logs: 'Logs',
|
||
planExpiringSoon: 'Plan Expiring Soon', planExpires: 'Plan expires: {date}', extendPlan: 'Extend Plan',
|
||
renewService: 'Renew Application', wallet: 'Wallet', walletBalance: 'Wallet Balance', payFromWallet: 'Pay from wallet',
|
||
insufficientRenew: 'Insufficient wallet balance. Top up your wallet or pay via invoice.',
|
||
bestForMost: 'Best for most users', saveUpTo20: 'Save up to 20%',
|
||
confirmResourceUpgrade: 'Confirm Resource Upgrade', currentHourlyCost: 'Current hourly cost', newHourlyCost: 'New hourly cost',
|
||
remainingHours: 'Remaining hours in period', proratedAmount: 'Prorated amount to pay',
|
||
feeIncludedNote: 'This fee is included in the total cost calculation.', thisMayTake: 'This may take a few minutes',
|
||
cancel: 'Cancel',
|
||
private: 'Private', active: 'Active',
|
||
deployingBtn: 'Deploying...',
|
||
adjustCpuMemStorage: 'Adjust CPU / memory & storage',
|
||
calculating: 'Calculating…',
|
||
connectionInfoInternal: 'Connection Info (Internal Cluster)',
|
||
createInvoicePay: 'Create Invoice & Pay',
|
||
customDomainPending: 'Custom Domain — Pending DNS Verification',
|
||
customDomainFee: 'Custom domain fee:',
|
||
dragDrop: 'Drag & drop a',
|
||
fileHereBrowse: 'file here, or click to browse',
|
||
expandDiskNote: 'Expand disk in Adjust CPU / memory & storage below.',
|
||
maxSize10gb: 'Max size: 10 GB',
|
||
maxSize500mb: 'Max size: 500MB',
|
||
payAsYouGo: 'Pay as you go, auto-renews',
|
||
pickComponentNote: 'Pick which component to update. CPU and memory apply per workload; storage can only grow (expand). The main application may use billing for paid upgrades; database and optional services apply directly in the cluster.',
|
||
rabbitmqVolume: 'RabbitMQ (optional) volume',
|
||
redisVolume: 'Redis (optional) volume',
|
||
rollbackSnapshots: 'Rollback & Snapshots',
|
||
snapshotsAutoNote: 'Snapshots are created automatically before each deploy, or you can create one manually.',
|
||
snapshotsIncludeNote: 'include source code, database dump, and wp-content. Use these to restore data or download backups. Auto-created before each deploy.',
|
||
revisionsHelmNote: 'using Helm release revisions. Switches to a previous configuration in seconds — no rebuild needed. Up to 10 revisions are kept.',
|
||
record: 'record:',
|
||
cpuColon: 'CPU:', memoryColon: 'Memory:', sidecars: 'Sidecars:',
|
||
typeColon: 'Type:', valueColon: 'Value:', nameHost: 'Name/Host:', cnameTarget: 'CNAME Target:',
|
||
orText: 'or',
|
||
verifyDns: 'Verify DNS', checking: 'Checking...',
|
||
dnsStep1: '1. Log in to your domain registrar (e.g. Cloudflare, Namecheap, GoDaddy)',
|
||
dnsStep2: '2. Go to DNS management for your domain',
|
||
dnsStep3a: '3. Add a ', dnsStep3b: ' record:',
|
||
dnsStep4a: '4. If using a root domain (without www), use a registrar that supports CNAME flattening (e.g. Cloudflare), or use ',
|
||
dnsStep4b: ' instead.',
|
||
dnsStep5: '5. Wait 5–30 minutes for DNS propagation (up to 48 hours in some cases)',
|
||
dnsStep6a: '6. Click the ', dnsStep6b: ' button above',
|
||
scheduledForDeletion: 'Application Scheduled for Deletion!',
|
||
suspendedPayment: 'Application Suspended — Payment Required',
|
||
willBeDeletedOn: 'This application will be permanently deleted on {date}. Renew now to prevent data loss.',
|
||
soon: 'soon',
|
||
planExpiredRestore: 'Your plan has expired. Renew to restore service access.',
|
||
planExpiresEarly: 'Your plan expires on {date}. Renew early to avoid service interruption.',
|
||
selectBillingCycle: 'Select a billing cycle to renew "{name}"',
|
||
toman: 'Toman', tomanPerHour: 'Toman/hour',
|
||
walletShortBy: 'Wallet is short by {n} Toman. You can pay the delta by gateway on the invoice page.',
|
||
revision: 'Revision', hoursUnit: '{n} hours',
|
||
payFromWalletBtn: 'Pay from wallet', applyDirectly: 'Apply directly',
|
||
},
|
||
deployWizard: {
|
||
cycles: { hourly: 'Hourly', monthly: 'Monthly', yearly: 'Yearly' },
|
||
deployNewApp: 'Deploy New Application',
|
||
followSteps: 'Follow the steps to deploy your app to the cloud.',
|
||
basicInfo: 'Basic Information',
|
||
appType: 'Application Type',
|
||
appName: 'Application Name',
|
||
descriptionOptional: 'Description (optional)',
|
||
whatDoesApp: 'What does this app do?',
|
||
nameHint: 'Lowercase letters, numbers, and hyphens only',
|
||
source: 'Source',
|
||
sourceCode: 'Source Code',
|
||
gitRepository: 'Git Repository',
|
||
uploadZip: 'Upload ZIP',
|
||
uploadAZip: 'Upload a ZIP',
|
||
repositoryUrl: 'Repository URL',
|
||
branch: 'Branch',
|
||
accessToken: 'Access Token',
|
||
auth: 'Auth',
|
||
tokenProvided: 'Token provided',
|
||
versionsDatabase: 'Versions & Database',
|
||
runtime: 'Runtime',
|
||
nodeVersion: 'Node.js Version', phpVersion: 'PHP Version', pythonVersion: 'Python Version',
|
||
goVersion: 'Go Version', wordpressVersion: 'WordPress Version',
|
||
database: 'Database',
|
||
databaseCredentials: 'Database Credentials',
|
||
dbUsername: 'DB Username', dbPassword: 'DB Password', dbStorage: 'DB Storage', dbDump: 'DB Dump',
|
||
databaseStorageSize: 'Database Storage Size',
|
||
databaseResources: 'Database resources',
|
||
databaseResourcesHint: 'Configure the database CPU, RAM and disk on the Resources step.',
|
||
username: 'Username', password: 'Password', autoGenerated: 'Auto-generated',
|
||
generatePassword: 'Generate random password',
|
||
dbCredsNote: 'These credentials are used for internal cluster communication only. The database is not exposed externally.',
|
||
optionalDbDump: 'Optional: Upload DB dump to restore at creation',
|
||
uploadSqlNote: 'Upload a SQL dump to be restored after the database is created',
|
||
uploadDbDumpHint: 'You can also upload a SQL database dump in the next step to restore your data.',
|
||
optionalServices: 'Optional Services',
|
||
configurePerService: 'Configure resources for each enabled service separately from your application.',
|
||
redisResources: 'Redis resources', rabbitmqResources: 'RabbitMQ resources',
|
||
centralizedLogging: 'Centralized logging', logsViaFluentBit: 'Logs collected via Fluent Bit sidecar',
|
||
logFilePaths: 'Log File Paths',
|
||
specifyLogFiles: 'Specify which log files to collect. Leave empty for default paths based on runtime.',
|
||
defaultPathsByRuntime: 'Default paths by runtime:',
|
||
resourcesConfig: 'Resources & Configuration',
|
||
applicationWorkload: 'Application workload',
|
||
cpu: 'CPU', memory: 'Memory', storage: 'Storage', replicas: 'Replicas', port: 'Port',
|
||
cpuRequest: 'CPU Request', cpuLimit: 'CPU Limit', memoryRequest: 'Memory Request', memoryLimit: 'Memory Limit',
|
||
clusterAssignment: 'Cluster Assignment',
|
||
useDefaultCluster: 'Use default cluster', defaultClusterUsed: 'Default cluster will be used',
|
||
pickSpecificCluster: 'Pick a specific cluster', pickClusterPool: 'Pick a cluster pool',
|
||
loadBalanced: 'Load Balanced', cluster: 'Cluster',
|
||
noClustersAvailable: 'No clusters available', noClusterPools: 'No cluster pools configured',
|
||
askAdminPool: 'Ask your admin to create a cluster pool', defaultClusterWillBeUsed: 'Default cluster will be used',
|
||
customDomain: 'Custom Domain', domainAddress: 'Domain Address',
|
||
dnsSetupRequired: 'DNS Setup Required', dnsNotVerified: 'DNS Not Verified', verifyDnsRecords: 'Verify DNS Records',
|
||
checkingDns: 'Checking DNS...', dnsVerified: 'DNS verified!', dnsVerifiedProceed: 'DNS verified! You can proceed.',
|
||
mustVerifyDns: 'You must verify DNS before proceeding. SSL will be provisioned automatically after deployment.',
|
||
requiredCnameRecord: 'Required CNAME record:',
|
||
record: 'record:', typeColon: 'Type:', nameHost: 'Name/Host:', valueColon: 'Value:', cnameTarget: 'CNAME Target:', versionColon: 'Version:',
|
||
yourPlatformDomain: 'your app Platform Domain (after creation)',
|
||
environmentVariables: 'Environment Variables', envVars: 'Env Vars',
|
||
uploadEnvFile: 'Upload .env file', add: 'Add', clear: 'Clear', remove: 'Remove',
|
||
reviewDeploy: 'Review & Deploy',
|
||
costEstimate: 'Cost Estimate', calculating: 'Calculating...', breakdown: 'Breakdown',
|
||
additionalCharges: 'Additional charges (you pay)', coveredByCredit: 'Covered by prepaid credit',
|
||
customDomainFee: 'Custom domain fee:', feeIncludedNote: 'This fee is included in the total cost calculation.',
|
||
prepaidCreditApplied: 'Prepaid credit applied', prepaidCreditPricing: 'Prepaid credit pricing',
|
||
deployWithCredit: 'Deploy with prepaid credit',
|
||
noChargeCovered: 'No additional charges — fully covered.',
|
||
noPaymentCredit: 'No payment required — your prepaid resource credit covers this deployment.',
|
||
noPricingPlans: 'No pricing plans defined yet',
|
||
paymentMethod: 'Payment Method', payFromWallet: 'Pay from Wallet', payNow: 'Pay Now', onlineGateway: 'Online payment gateway',
|
||
insufficientBalance: 'Insufficient balance', toman: 'Toman',
|
||
payDeploy: 'Pay & Deploy', deployApplication: 'Deploy Application',
|
||
processingPayment: 'Processing payment', creatingApplication: 'Creating application', startingDeployment: 'Starting deployment',
|
||
stageCreating: 'Creating application...', stageUploadingSource: 'Uploading source code...',
|
||
stageUploadingDb: 'Uploading database dump...', stagePaying: 'Processing payment...',
|
||
stageDeploying: 'Starting deployment...', stageRedirecting: 'Redirecting...', stageError: 'An error occurred',
|
||
deploymentFailed: 'Deployment Failed', success: 'Success!', deployingApplication: 'Deploying Application',
|
||
appTypeApplication: 'Application', appTypeDatabase: 'Database',
|
||
inMemoryCache: 'In-memory cache & store', messageBroker: 'Message broker',
|
||
wordpressOfficial: 'WordPress (Official Image)',
|
||
freshInstall: 'Fresh Install', migrateExisting: 'Migrate Existing Site',
|
||
freshInstallNote: 'Start with a clean WordPress. Install themes & plugins via the admin panel.',
|
||
migrateNote: 'Upload your WordPress files (wp-content, themes, plugins) and optionally a DB dump.',
|
||
dragWpZip: 'Drag & drop your WordPress ZIP here',
|
||
dragProjectZip: 'Drag & drop your project ZIP here',
|
||
stratLeastApps: 'Least Apps', stratLeastLoaded: 'Least Loaded', stratRoundRobin: 'Round Robin',
|
||
stratWeightedRR: 'Weighted RR', stratWeightedResource: 'Weighted Resource', stratRegionBased: 'Region Based',
|
||
default: 'Default', manual: 'Manual', none: 'None',
|
||
appCreatedDeploying: 'Application created! Triggering deployment...',
|
||
paymentSuccessDeploying: 'Payment successful! Deploying...',
|
||
insufficientWallet: 'Insufficient wallet balance. Please top up or use payment gateway.',
|
||
archiveMax10: 'Archive must be at most 10 GB', fileMax10: 'File size must be at most 10 GB',
|
||
onlyZipAllowed: 'Only .zip or .tar.gz files are allowed', envReadFailed: 'Failed to read environment file',
|
||
dnsCheckFailed: 'Failed to check DNS. Please try again.',
|
||
allowedDumpFormats: 'Allowed: .sql, .gz, .dump', maxSize500: 'Max 500MB',
|
||
storageTooSmall: 'Storage too small',
|
||
anyCustom: 'Any custom',
|
||
ofYourEntire: 'of your entire',
|
||
uploadAZipContaining: 'Upload a ZIP containing your WordPress files. Supported structures:',
|
||
zipWithFullRoot: 'ZIP with full WordPress root (',
|
||
filesAtRoot: 'files at root level',
|
||
directoryFullRoot: 'directory (the full WordPress root):',
|
||
zipWith: 'ZIP with',
|
||
containingWpFiles: ' containing your WordPress files. Supported structures:',
|
||
wpContentDesc: ' — themes, plugins, uploads',
|
||
wpConfigDesc: ' — custom configuration (optional)',
|
||
anyCustomA: 'Any custom ', anyCustomB: ' files at root level',
|
||
folderMax10: ' folder • Max 10 GB',
|
||
fullRootSuffix: ', ...) • Max 10 GB',
|
||
invalidDomainFormat: 'Invalid domain format. Use a format like example.com or www.example.com',
|
||
dnsNotConfigured: 'DNS records are not configured correctly. Please set up the CNAME record and wait for propagation before proceeding.',
|
||
dnsVerifyFailed: 'Failed to verify DNS. Please check your domain settings and try again.',
|
||
platformDomainArrow: 'your app Platform Domain (after creation)',
|
||
runtimeDescs: {
|
||
nodejs: 'Express, NestJS, Fastify',
|
||
laravel: 'PHP, Composer, Artisan',
|
||
wordpress: 'Official image',
|
||
go: 'Gin, Echo, Fiber',
|
||
python: 'Flask, FastAPI',
|
||
django: 'Python web framework',
|
||
php: 'Plain PHP apps',
|
||
dotnet: 'ASP.NET Core',
|
||
},
|
||
noValidEnvVars: 'No valid environment variables found in file',
|
||
appDataStorage: 'Application data storage',
|
||
wordpressFreshInstall: 'WordPress (Fresh Install)',
|
||
automaticAllocator: 'Automatic allocator',
|
||
back: 'Back', next: 'Next',
|
||
},
|
||
},
|
||
};
|
||
|
||
export default en;
|