mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-29 18:13:47 +00:00
fix(i18n): backfill 120 missing keys + close 2 typo regressions from purchase refactor
Surface: users (and especially Серёжа в bugs topic) were seeing raw i18n keys
like `subscription.promoGroup.title` rendered as literal text on the renewal
screen. Audit found 118 keys referenced in code that were absent from all 4
locale files, plus 140 keys missing only in zh/fa (silently falling back to
Russian for those users).
Root causes:
- cf52999 (extract TariffPickerGrid) introduced `subscription.promoGroup.title`
that never existed — should have been `subscription.promoGroup.yourGroup`.
- Subscription.tsx used `subscription.autopay.title` (object path) while
SubscriptionListCard.tsx used `subscription.autopay` (leaf) — i18next can't
hold both shapes for the same key.
- Many user-flow keys (subscription.notFound, subscriptions.empty, common.ok,
successNotification.*, etc.) were never added when their components landed.
- Historical drift had ~140 keys in ru/en that never got zh/fa translations.
Fix:
- Rename TariffPickerGrid usage `promoGroup.title` → `promoGroup.yourGroup`.
- Rename Subscription.tsx usage `autopay.title` → `autopay`.
- Add 116 brand-new keys across ru/en/zh/fa (464 entries).
- Add 8 partially-missing keys (en+ru gaps) for landing periods, dashboard
campaign/referrer stats, and promo offer failure counts.
- Translate 280 entries to close the zh/fa drift.
Final state: 0 keys missing in any of the 4 locale files for any code-referenced
translation key. Build + tsc green.
This commit is contained in:
@@ -26,11 +26,19 @@
|
||||
"all": "All",
|
||||
"units": {
|
||||
"gb": "GB",
|
||||
"perGb": "/GB"
|
||||
"perGb": "/GB",
|
||||
"days": "days",
|
||||
"mo": "mo"
|
||||
},
|
||||
"retry": "Retry",
|
||||
"saving": "Saving...",
|
||||
"understand": "Got it"
|
||||
"understand": "Got it",
|
||||
"balance": "Balance",
|
||||
"copied": "Copied",
|
||||
"no_results": "No results",
|
||||
"ok": "OK",
|
||||
"processing": "Processing…",
|
||||
"rangeTo": "to"
|
||||
},
|
||||
"nav": {
|
||||
"dashboard": "Dashboard",
|
||||
@@ -45,7 +53,8 @@
|
||||
"info": "Info",
|
||||
"wheel": "Fortune Wheel",
|
||||
"menu": "Menu",
|
||||
"gift": "Gift"
|
||||
"gift": "Gift",
|
||||
"navigation": "Navigation"
|
||||
},
|
||||
"notifications": {
|
||||
"ticketNotifications": "Ticket Notifications",
|
||||
@@ -148,7 +157,17 @@
|
||||
"tariff": "Tariff",
|
||||
"validUntil": "Valid until",
|
||||
"goToSubscription": "Go to Subscription",
|
||||
"goToBalance": "Go to Balance"
|
||||
"goToBalance": "Go to Balance",
|
||||
"devicesAdded": "+{{count}} devices",
|
||||
"devicesPurchased": {
|
||||
"title": "Devices added"
|
||||
},
|
||||
"totalDevices": "Total devices: {{count}}",
|
||||
"totalTraffic": "Total traffic: {{value}}",
|
||||
"trafficAdded": "+{{value}} traffic",
|
||||
"trafficPurchased": {
|
||||
"title": "Traffic added"
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"login": "Login",
|
||||
@@ -290,7 +309,10 @@
|
||||
"subscription": "Subscription",
|
||||
"referrals": "Referrals",
|
||||
"earnings": "Earnings"
|
||||
}
|
||||
},
|
||||
"manageAll": "Manage all",
|
||||
"showAll": "Show all",
|
||||
"subscriptions": "Subscriptions"
|
||||
},
|
||||
"subscription": {
|
||||
"title": "Subscription",
|
||||
@@ -346,7 +368,8 @@
|
||||
"cta": {
|
||||
"expiredHint": "Choose a plan and pay",
|
||||
"trialHint": "More traffic and devices",
|
||||
"activeHint": "Renewal and plan change"
|
||||
"activeHint": "Renewal and plan change",
|
||||
"renewHint": "Subscription expired — renew to continue using"
|
||||
},
|
||||
"connectionInfo": "Connection Info",
|
||||
"copyLink": "Copy Link",
|
||||
@@ -458,7 +481,8 @@
|
||||
"goToApps": "Go to Apps settings",
|
||||
"qrTitle": "Subscription QR Code",
|
||||
"qrScanHint": "Scan to connect",
|
||||
"qrButton": "QR Code"
|
||||
"qrButton": "QR Code",
|
||||
"openQr": "Open QR code"
|
||||
},
|
||||
"myDevices": "My Devices",
|
||||
"noDevices": "No connected devices",
|
||||
@@ -561,7 +585,14 @@
|
||||
"buyTrafficGb": "Buy {{gb}} GB",
|
||||
"buyUnlimited": "Buy Unlimited",
|
||||
"manageServers": "Squad management",
|
||||
"manageServersTitle": "Squad management"
|
||||
"manageServersTitle": "Squad management",
|
||||
"connectedDevices": "Connected devices",
|
||||
"currentDeviceLimit": "Current device limit",
|
||||
"decrementDevices": "Decrease devices",
|
||||
"disconnectDevicesFirst": "Disconnect extra devices first",
|
||||
"incrementDevices": "Add devices",
|
||||
"minDeviceLimit": "Minimum device limit",
|
||||
"newDeviceLimit": "New device limit"
|
||||
},
|
||||
"serverManagement": {
|
||||
"statusLegend": "✅ — connected • ➕ — will be added (paid) • ➖ — will be disconnected",
|
||||
@@ -620,7 +651,27 @@
|
||||
"stopScan": "Close camera",
|
||||
"noCamera": "Camera access denied",
|
||||
"codeFound": "Code found"
|
||||
}
|
||||
},
|
||||
"allTariffsPurchased": "All tariffs already purchased",
|
||||
"autopay": "Auto-renew",
|
||||
"backToList": "Back to subscriptions",
|
||||
"confirmDelete": "Delete subscription?",
|
||||
"dailyAutoCharge": "Daily auto-charge",
|
||||
"defaultName": "Subscription",
|
||||
"delete": "Delete",
|
||||
"deleteTitle": "Delete subscription",
|
||||
"get_config": "Get config",
|
||||
"loadError": "Failed to load subscription",
|
||||
"newTariff": "New tariff",
|
||||
"noOptionsAvailable": "No options available",
|
||||
"noRenewalOptions": "No renewal options",
|
||||
"notFound": "Subscription not found",
|
||||
"notFoundDesc": "It may have been deleted or not yet activated",
|
||||
"servers": "Servers",
|
||||
"statusActive": "Active",
|
||||
"statusExpired": "Expired",
|
||||
"statusLimited": "Limited",
|
||||
"statusTrial": "Trial"
|
||||
},
|
||||
"balance": {
|
||||
"title": "Balance",
|
||||
@@ -738,7 +789,9 @@
|
||||
"already_used_by_user": "You have already used this promo code",
|
||||
"user_not_found": "User not found",
|
||||
"server_error": "Server error"
|
||||
}
|
||||
},
|
||||
"daysLeft": "Days left: {{count}}",
|
||||
"selectSubscription": "Select a subscription"
|
||||
},
|
||||
"minAmountError": "Minimum amount: {{amount}} ₽",
|
||||
"maxAmountError": "Maximum amount: {{amount}} ₽",
|
||||
@@ -798,7 +851,8 @@
|
||||
"timeoutDesc": "Payment processing is taking longer than usual. You can try checking the status again.",
|
||||
"goToBalance": "Go to Balance",
|
||||
"tryAgain": "Try Again"
|
||||
}
|
||||
},
|
||||
"top_up": "Top up balance"
|
||||
},
|
||||
"referral": {
|
||||
"title": "Referral Program",
|
||||
@@ -984,7 +1038,8 @@
|
||||
"useExternalLink": "Please use the external link to get support",
|
||||
"openSupport": "Open Support",
|
||||
"contactSupport": "Please contact {{username}} for support",
|
||||
"contactUs": "Contact Support"
|
||||
"contactUs": "Contact Support",
|
||||
"create_ticket": "Create ticket"
|
||||
},
|
||||
"wheel": {
|
||||
"title": "Fortune Wheel",
|
||||
@@ -1017,7 +1072,8 @@
|
||||
"insufficientBalance": "Insufficient balance",
|
||||
"topUpRequired": "Top up your balance to pay for spin",
|
||||
"starsNotAvailable": "Stars payment not available. Open the app via Telegram.",
|
||||
"noSubscription": "An active subscription is required to spin the wheel. Activate your subscription first."
|
||||
"noSubscription": "An active subscription is required to spin the wheel. Activate your subscription first.",
|
||||
"selectSubscription": "Select a subscription first"
|
||||
},
|
||||
"payWithStars": "Pay with Stars",
|
||||
"payWithDays": "Pay with days",
|
||||
@@ -1036,7 +1092,8 @@
|
||||
"title": "Try your luck!",
|
||||
"description": "Spin the wheel and win prizes: subscription days, balance, traffic and more!",
|
||||
"button": "Go to wheel"
|
||||
}
|
||||
},
|
||||
"selectSubscription": "Select subscription"
|
||||
},
|
||||
"admin": {
|
||||
"backgrounds": {
|
||||
@@ -1544,7 +1601,8 @@
|
||||
"promoGroupsShort": "groups",
|
||||
"noPromoGroups": "No promo groups",
|
||||
"cancelButton": "Cancel",
|
||||
"saveButton": "Save"
|
||||
"saveButton": "Save",
|
||||
"notFound": "Payment method not found"
|
||||
},
|
||||
"remnawave": {
|
||||
"title": "RemnaWave",
|
||||
@@ -1611,7 +1669,8 @@
|
||||
"offline": "Offline",
|
||||
"disabled": "Disabled",
|
||||
"users": "Users"
|
||||
}
|
||||
},
|
||||
"usersOnlineCount": "{{count}} online"
|
||||
},
|
||||
"squads": {
|
||||
"synced": "Synced",
|
||||
@@ -1642,7 +1701,9 @@
|
||||
"localSettings": "Local Settings",
|
||||
"trialEligible": "Trial Eligible",
|
||||
"price": "Price",
|
||||
"users": "Users"
|
||||
"users": "Users",
|
||||
"inboundsCount": "{{count}} inbounds",
|
||||
"membersCount": "{{count}} members"
|
||||
},
|
||||
"sync": {
|
||||
"autoSync": "Auto Sync",
|
||||
@@ -1820,7 +1881,12 @@
|
||||
"btnConnect": "Connect",
|
||||
"btnSubscription": "Subscription",
|
||||
"btnSupport": "Support",
|
||||
"btnHome": "Home"
|
||||
"btnHome": "Home",
|
||||
"category": "Category",
|
||||
"categoryNews": "News",
|
||||
"categoryPromo": "Promo",
|
||||
"categorySystem": "System",
|
||||
"stopping": "Stopping…"
|
||||
},
|
||||
"pinnedMessages": {
|
||||
"title": "Pinned Messages",
|
||||
@@ -2310,7 +2376,10 @@
|
||||
"remnaWaveSettings": "RemnaWave Settings",
|
||||
"remnaWaveConfigUuid": "Config UUID",
|
||||
"remnaWaveConfigUuidHint": "UUID of subscription page config from RemnaWave panel",
|
||||
"availableConfigs": "Available configs"
|
||||
"availableConfigs": "Available configs",
|
||||
"noConfigs": "No configs",
|
||||
"remnaWaveConnected": "RemnaWave connected",
|
||||
"remnaWaveDisconnected": "RemnaWave disconnected"
|
||||
},
|
||||
"tickets": {
|
||||
"title": "Ticket Management",
|
||||
@@ -2361,7 +2430,13 @@
|
||||
"userNotificationsEnabled": "User Notifications",
|
||||
"userNotificationsEnabledDesc": "Send notifications to users about admin replies",
|
||||
"adminNotificationsEnabled": "Admin Notifications",
|
||||
"adminNotificationsEnabledDesc": "Send notifications to admins about new tickets and replies"
|
||||
"adminNotificationsEnabledDesc": "Send notifications to admins about new tickets and replies",
|
||||
"replyFailed": "Failed to send reply",
|
||||
"validation": {
|
||||
"checkIntervalRange": "Check interval must be between 1 and 1440 minutes",
|
||||
"reminderCooldownRange": "Reminder cooldown must be between 0 and 1440 minutes",
|
||||
"slaMinutesRange": "SLA must be between 1 and 10080 minutes"
|
||||
}
|
||||
},
|
||||
"tariffs": {
|
||||
"title": "Tariff Management",
|
||||
@@ -2588,7 +2663,8 @@
|
||||
"deactivate": "Deactivate",
|
||||
"activate": "Activate",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete"
|
||||
"delete": "Delete",
|
||||
"registrations": "Registrations"
|
||||
},
|
||||
"modal": {
|
||||
"editTitle": "Edit Campaign",
|
||||
@@ -2658,7 +2734,9 @@
|
||||
"totalSpending": "Subscription Spending",
|
||||
"periodComparison": "Period comparison",
|
||||
"vsLastWeek": "vs last week",
|
||||
"topRegistrations": "Top registrations"
|
||||
"topRegistrations": "Top registrations",
|
||||
"subscriptionsIssued": "Subscriptions issued",
|
||||
"tariffsIssued": "Tariffs issued"
|
||||
},
|
||||
"users": {
|
||||
"title": "Campaign Users",
|
||||
@@ -2682,7 +2760,10 @@
|
||||
"delete": "Delete"
|
||||
},
|
||||
"loadError": "Failed to load campaign",
|
||||
"updateError": "Failed to save changes"
|
||||
"updateError": "Failed to save changes",
|
||||
"validation": {
|
||||
"nameRequired": "Name is required"
|
||||
}
|
||||
},
|
||||
"withdrawals": {
|
||||
"title": "Withdrawals",
|
||||
@@ -2853,7 +2934,10 @@
|
||||
"createTitle": "Create Campaign",
|
||||
"createSubtitle": "Campaign will be auto-assigned to the partner",
|
||||
"autoAssignNote": "Campaign will be automatically assigned to partner {{name}}",
|
||||
"createAndAssign": "Create & Assign"
|
||||
"createAndAssign": "Create & Assign",
|
||||
"earnings": "Earnings",
|
||||
"referrals": "Referrals",
|
||||
"registrations": "Registrations"
|
||||
},
|
||||
"dangerZone": {
|
||||
"title": "Danger Zone",
|
||||
@@ -2928,7 +3012,10 @@
|
||||
"firstPurchaseOnly": "First purchase only",
|
||||
"cancel": "Cancel",
|
||||
"saving": "Saving...",
|
||||
"save": "Save"
|
||||
"save": "Save",
|
||||
"defaultTrialTariff": "Default trial tariff",
|
||||
"selectTariff": "Select tariff",
|
||||
"tariff": "Tariff"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Promo code statistics",
|
||||
@@ -2958,7 +3045,8 @@
|
||||
"totalPromocodes": "Total promo codes",
|
||||
"activeCount": "Active",
|
||||
"usagesCount": "Uses",
|
||||
"exhausted": "Exhausted"
|
||||
"exhausted": "Exhausted",
|
||||
"hoursValue": "{{count}}h"
|
||||
},
|
||||
"actions": {
|
||||
"stats": "Statistics",
|
||||
@@ -3249,7 +3337,9 @@
|
||||
"expired": "expired",
|
||||
"daysLeft": "d left",
|
||||
"deviceLimitUpdated": "Device limit updated",
|
||||
"invalidDays": "Please enter a valid number of days (greater than 0)"
|
||||
"invalidDays": "Please enter a valid number of days (greater than 0)",
|
||||
"backToList": "Back to subscriptions",
|
||||
"createNew": "Create new"
|
||||
},
|
||||
"balance": {
|
||||
"current": "Current balance",
|
||||
@@ -3333,7 +3423,9 @@
|
||||
"alreadyReferred": "already has referrer",
|
||||
"noUsersFound": "No users found"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notFound": "User not found",
|
||||
"purchaseCount": "Purchases: {{count}}"
|
||||
},
|
||||
"promoOffers": {
|
||||
"title": "Promo Offers",
|
||||
@@ -3342,7 +3434,8 @@
|
||||
"tabs": {
|
||||
"templates_one": "Templates ({{count}} template)",
|
||||
"templates_other": "Templates ({{count}} templates)",
|
||||
"logs": "Logs"
|
||||
"logs": "Logs",
|
||||
"templates": "Templates"
|
||||
},
|
||||
"noData": {
|
||||
"templates": "No templates",
|
||||
@@ -3372,7 +3465,9 @@
|
||||
"activeDiscountHours": "Discount validity (hours)",
|
||||
"discountDurationHint": "How long the discount lasts after activation",
|
||||
"templateActive": "Template active",
|
||||
"saving": "Saving..."
|
||||
"saving": "Saving...",
|
||||
"noServers": "No servers",
|
||||
"testSquads": "Test squads"
|
||||
},
|
||||
"send": {
|
||||
"title": "Send promo offer",
|
||||
@@ -3398,7 +3493,10 @@
|
||||
"notificationsSent_other": "Notifications sent: {{count}}",
|
||||
"notificationsFailed_one": "(failed: {{count}})",
|
||||
"notificationsFailed_other": "(failed: {{count}})",
|
||||
"sendError": "Failed to send offer"
|
||||
"sendError": "Failed to send offer",
|
||||
"notificationsSent": "Notifications sent",
|
||||
"offersCreated": "Offers created",
|
||||
"notificationsFailed": "(failed: {{count}})"
|
||||
},
|
||||
"notFound": "Template not found",
|
||||
"noActiveTemplates": "No active templates",
|
||||
@@ -3535,7 +3633,8 @@
|
||||
"selectedPermissions_other": "{{count}} permissions selected",
|
||||
"cancel": "Cancel",
|
||||
"saving": "Saving...",
|
||||
"save": "Save"
|
||||
"save": "Save",
|
||||
"selectedPermissions": "Selected permissions"
|
||||
},
|
||||
"presets": {
|
||||
"moderator": "Moderator",
|
||||
@@ -3555,7 +3654,9 @@
|
||||
"updateFailed": "Failed to update role",
|
||||
"nameRequired": "Role name is required",
|
||||
"deleteFailed": "Failed to delete role"
|
||||
}
|
||||
},
|
||||
"permissionsCount": "{{count}} permissions",
|
||||
"usersCount": "{{count}} users"
|
||||
},
|
||||
"roleAssign": {
|
||||
"title": "Role Assignment",
|
||||
@@ -3608,7 +3709,8 @@
|
||||
"roleRequired": "Please select a role",
|
||||
"assignFailed": "Failed to assign role",
|
||||
"revokeFailed": "Failed to revoke role"
|
||||
}
|
||||
},
|
||||
"totalAssignments": "Total assignments: {{count}}"
|
||||
},
|
||||
"policies": {
|
||||
"title": "Access Policies",
|
||||
@@ -3676,7 +3778,8 @@
|
||||
"day3": "Wed",
|
||||
"day4": "Thu",
|
||||
"day5": "Fri",
|
||||
"day6": "Sat"
|
||||
"day6": "Sat",
|
||||
"ipCount": "IP count"
|
||||
},
|
||||
"confirm": {
|
||||
"title": "Delete policy?",
|
||||
@@ -3762,7 +3865,10 @@
|
||||
"hoursAgo_one": "{{count}} hr ago",
|
||||
"hoursAgo_other": "{{count}} hrs ago",
|
||||
"daysAgo_one": "{{count}} day ago",
|
||||
"daysAgo_other": "{{count}} days ago"
|
||||
"daysAgo_other": "{{count}} days ago",
|
||||
"daysAgo": "{{count}}d ago",
|
||||
"hoursAgo": "{{count}}h ago",
|
||||
"minutesAgo": "{{count}}m ago"
|
||||
},
|
||||
"pagination": {
|
||||
"pageSize": "Per page:",
|
||||
@@ -3775,7 +3881,8 @@
|
||||
"errors": {
|
||||
"loadFailed": "Failed to load audit log",
|
||||
"retry": "Try again"
|
||||
}
|
||||
},
|
||||
"totalEntries": "Total entries: {{count}}"
|
||||
},
|
||||
"landings": {
|
||||
"title": "Landing Pages",
|
||||
@@ -3869,7 +3976,8 @@
|
||||
"funnel": "Funnel",
|
||||
"loadError": "Failed to load statistics",
|
||||
"noPurchases": "No purchases",
|
||||
"paid": "paid"
|
||||
"paid": "paid",
|
||||
"dailyPurchases": "Purchases per day"
|
||||
},
|
||||
"purchases": {
|
||||
"title": "Purchases",
|
||||
@@ -3895,7 +4003,16 @@
|
||||
"page": "Page {{current}} of {{total}}",
|
||||
"prev": "Previous",
|
||||
"next": "Next"
|
||||
}
|
||||
},
|
||||
"methodCurrency": "Currency",
|
||||
"methodDescPlaceholder": "Short description shown to the user",
|
||||
"methodDescription": "Method description",
|
||||
"methodDisplayName": "Display name",
|
||||
"methodIconUrl": "Icon URL",
|
||||
"methodMaxAmount": "Maximum amount",
|
||||
"methodMinAmount": "Minimum amount",
|
||||
"methodReturnUrl": "Return URL",
|
||||
"stickyPayButton": "Sticky pay button"
|
||||
},
|
||||
"infoPages": {
|
||||
"title": "Information Pages",
|
||||
@@ -4007,7 +4124,8 @@
|
||||
"disable": "Disable",
|
||||
"hide": "Hide ({{count}})",
|
||||
"showMore_one": "Show {{count}} more node",
|
||||
"showMore_other": "Show {{count}} more nodes"
|
||||
"showMore_other": "Show {{count}} more nodes",
|
||||
"showMore": "Show more"
|
||||
},
|
||||
"topReferrers": {
|
||||
"title": "Top referrers",
|
||||
@@ -4457,7 +4575,8 @@
|
||||
"yandex": "Yandex",
|
||||
"discord": "Discord",
|
||||
"vk": "VK"
|
||||
}
|
||||
},
|
||||
"backToAccounts": "Back to accounts"
|
||||
}
|
||||
},
|
||||
"theme": {
|
||||
@@ -4611,7 +4730,8 @@
|
||||
"warning": "A cancelled promo code cannot be reused. The discount will stop working immediately.",
|
||||
"confirm": "Cancel discount",
|
||||
"deactivating": "Cancelling...",
|
||||
"error": "Failed to cancel promo code. Please try again later."
|
||||
"error": "Failed to cancel promo code. Please try again later.",
|
||||
"success": "Offer deactivated"
|
||||
}
|
||||
},
|
||||
"telegramRedirect": {
|
||||
@@ -4788,7 +4908,9 @@
|
||||
"nDays_one": "{{count}} day",
|
||||
"nDays_other": "{{count}} days",
|
||||
"nMonths_one": "{{count}} month",
|
||||
"nMonths_other": "{{count}} months"
|
||||
"nMonths_other": "{{count}} months",
|
||||
"nDays": "{{count}} days",
|
||||
"nMonths": "{{count}} months"
|
||||
}
|
||||
},
|
||||
"gift": {
|
||||
@@ -4966,5 +5088,12 @@
|
||||
"linkUrlPrompt": "URL:"
|
||||
}
|
||||
}
|
||||
},
|
||||
"subscriptions": {
|
||||
"buy": "Buy subscription",
|
||||
"buyAnother": "Buy another subscription",
|
||||
"empty": "You have no subscriptions yet",
|
||||
"emptyDesc": "Choose a tariff to get started",
|
||||
"title": "My subscriptions"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user