From 6d5c6fb9b3905d8a0c22f39317fd5f77743d3505 Mon Sep 17 00:00:00 2001 From: Fringg Date: Sat, 7 Mar 2026 04:04:39 +0300 Subject: [PATCH] fix: mobile layout and period label translations for quick purchase landing - Add i18n period labels (ru/en/zh/fa) instead of backend English-only labels - Period tabs wrap on mobile instead of horizontal scroll - Prevent horizontal overflow shifting the layout --- src/locales/en.json | 20 +++++++++++++++++++- src/locales/fa.json | 18 +++++++++++++++++- src/locales/ru.json | 22 +++++++++++++++++++++- src/locales/zh.json | 18 +++++++++++++++++- src/pages/QuickPurchase.tsx | 30 +++++++++++++++++++++++++----- 5 files changed, 99 insertions(+), 9 deletions(-) diff --git a/src/locales/en.json b/src/locales/en.json index 1efc1e3..ea0c06b 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -3995,6 +3995,24 @@ "giftSentSuccess": "Gift sent!", "giftSentDesc": "Recipient will be notified by email", "autoLoginFailed": "Auto-login failed", - "autoLoginProcessing": "Signing in..." + "autoLoginProcessing": "Signing in...", + "periodLabels": { + "d1": "1 day", + "d2": "2 days", + "d3": "3 days", + "d5": "5 days", + "d7": "1 week", + "d14": "2 weeks", + "d30": "1 month", + "d60": "2 months", + "d90": "3 months", + "d180": "6 months", + "d365": "1 year", + "d456": "1 year + 3 mo.", + "nDays_one": "{{count}} day", + "nDays_other": "{{count}} days", + "nMonths_one": "{{count}} month", + "nMonths_other": "{{count}} months" + } } } diff --git a/src/locales/fa.json b/src/locales/fa.json index 4c6526e..1a64896 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -3546,6 +3546,22 @@ "giftSentSuccess": "هدیه ارسال شد!", "giftSentDesc": "گیرنده از طریق ایمیل مطلع خواهد شد", "autoLoginFailed": "ورود خودکار ناموفق بود", - "autoLoginProcessing": "در حال ورود..." + "autoLoginProcessing": "در حال ورود...", + "periodLabels": { + "d1": "۱ روز", + "d2": "۲ روز", + "d3": "۳ روز", + "d5": "۵ روز", + "d7": "۱ هفته", + "d14": "۲ هفته", + "d30": "۱ ماه", + "d60": "۲ ماه", + "d90": "۳ ماه", + "d180": "۶ ماه", + "d365": "۱ سال", + "d456": "۱ سال و ۳ ماه", + "nDays": "{{count}} روز", + "nMonths": "{{count}} ماه" + } } } diff --git a/src/locales/ru.json b/src/locales/ru.json index 6dc8b0d..2c672ed 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -4554,6 +4554,26 @@ "giftSentSuccess": "Подарок отправлен!", "giftSentDesc": "Получатель получит уведомление на email", "autoLoginFailed": "Не удалось выполнить автоматический вход", - "autoLoginProcessing": "Выполняется вход..." + "autoLoginProcessing": "Выполняется вход...", + "periodLabels": { + "d1": "1 день", + "d2": "2 дня", + "d3": "3 дня", + "d5": "5 дней", + "d7": "1 неделя", + "d14": "2 недели", + "d30": "1 месяц", + "d60": "2 месяца", + "d90": "3 месяца", + "d180": "6 месяцев", + "d365": "1 год", + "d456": "1 год + 3 мес.", + "nDays_one": "{{count}} день", + "nDays_few": "{{count}} дня", + "nDays_many": "{{count}} дней", + "nMonths_one": "{{count}} месяц", + "nMonths_few": "{{count}} месяца", + "nMonths_many": "{{count}} месяцев" + } } } diff --git a/src/locales/zh.json b/src/locales/zh.json index 1d346da..7d9a881 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -3545,6 +3545,22 @@ "giftSentSuccess": "礼物已发送!", "giftSentDesc": "收件人将通过邮件收到通知", "autoLoginFailed": "自动登录失败", - "autoLoginProcessing": "正在登录..." + "autoLoginProcessing": "正在登录...", + "periodLabels": { + "d1": "1天", + "d2": "2天", + "d3": "3天", + "d5": "5天", + "d7": "1周", + "d14": "2周", + "d30": "1个月", + "d60": "2个月", + "d90": "3个月", + "d180": "6个月", + "d365": "1年", + "d456": "1年3个月", + "nDays": "{{count}}天", + "nMonths": "{{count}}个月" + } } } diff --git a/src/pages/QuickPurchase.tsx b/src/pages/QuickPurchase.tsx index b494be4..8c95659 100644 --- a/src/pages/QuickPurchase.tsx +++ b/src/pages/QuickPurchase.tsx @@ -31,6 +31,22 @@ function isValidContact(value: string): boolean { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmed); } +function formatPeriodLabel( + days: number, + t: (key: string, options?: Record) => string, +): string { + const key = `landing.periodLabels.d${days}`; + const result = t(key); + if (result !== key) return result; + + const months = Math.floor(days / 30); + const remainder = days % 30; + if (months > 0 && remainder === 0) { + return t('landing.periodLabels.nMonths', { count: months }); + } + return t('landing.periodLabels.nDays', { count: days }); +} + // ============================================================ // Sub-components // ============================================================ @@ -82,21 +98,23 @@ function PeriodTabs({ selectedDays: number; onSelect: (days: number) => void; }) { + const { t } = useTranslation(); + return ( -
+
{periods.map((period) => ( ))}
@@ -469,7 +487,9 @@ function SummaryCard({

{t('landing.period', 'Period')}

-

{selectedPeriod.label}

+

+ {formatPeriodLabel(selectedPeriod.days, t)} +

)}
@@ -788,7 +808,7 @@ export default function QuickPurchase() { const showTariffCards = visibleTariffs.length > 1; return ( -
+
{/* Language switcher */}