feat(i18n): Comprehensive internationalization of frontend components and pages
Translate all hardcoded English strings to use i18n translation keys: Components: - TransactionDetailModal: payment details, refunds, technical info - ConnectOnboarding/ConnectOnboardingEmbed: Stripe Connect setup - StripeApiKeysForm: API key management - DomainPurchase: domain registration flow - Sidebar: navigation labels - Schedule/Sidebar, PendingSidebar: scheduler UI - MasqueradeBanner: masquerade status - Dashboard widgets: metrics, capacity, customers, tickets - Marketing: PricingTable, PluginShowcase, BenefitsSection - ConfirmationModal, ServiceList: common UI Pages: - Staff: invitation flow, role management - Customers: form placeholders - Payments: transactions, payouts, billing - BookingSettings: URL and redirect configuration - TrialExpired: upgrade prompts and features - PlatformSettings, PlatformBusinesses: admin UI - HelpApiDocs: API documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
Wallet,
|
||||
Building2,
|
||||
} from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { createAccountSession, refreshConnectStatus, ConnectAccountInfo } from '../api/payments';
|
||||
|
||||
interface ConnectOnboardingEmbedProps {
|
||||
@@ -37,6 +38,7 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
onComplete,
|
||||
onError,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [stripeConnectInstance, setStripeConnectInstance] = useState<StripeConnectInstance | null>(null);
|
||||
const [loadingState, setLoadingState] = useState<LoadingState>('idle');
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||
@@ -78,12 +80,12 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
setLoadingState('ready');
|
||||
} catch (err: any) {
|
||||
console.error('Failed to initialize Stripe Connect:', err);
|
||||
const message = err.response?.data?.error || err.message || 'Failed to initialize payment setup';
|
||||
const message = err.response?.data?.error || err.message || t('payments.failedToInitializePayment');
|
||||
setErrorMessage(message);
|
||||
setLoadingState('error');
|
||||
onError?.(message);
|
||||
}
|
||||
}, [loadingState, onError]);
|
||||
}, [loadingState, onError, t]);
|
||||
|
||||
// Handle onboarding completion
|
||||
const handleOnboardingExit = useCallback(async () => {
|
||||
@@ -100,23 +102,23 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
// Handle errors from the Connect component
|
||||
const handleLoadError = useCallback((loadError: { error: { message?: string }; elementTagName: string }) => {
|
||||
console.error('Connect component load error:', loadError);
|
||||
const message = loadError.error.message || 'Failed to load payment component';
|
||||
const message = loadError.error.message || t('payments.failedToLoadPaymentComponent');
|
||||
setErrorMessage(message);
|
||||
setLoadingState('error');
|
||||
onError?.(message);
|
||||
}, [onError]);
|
||||
}, [onError, t]);
|
||||
|
||||
// Account type display
|
||||
const getAccountTypeLabel = () => {
|
||||
switch (connectAccount?.account_type) {
|
||||
case 'standard':
|
||||
return 'Standard Connect';
|
||||
return t('payments.standardConnect');
|
||||
case 'express':
|
||||
return 'Express Connect';
|
||||
return t('payments.expressConnect');
|
||||
case 'custom':
|
||||
return 'Custom Connect';
|
||||
return t('payments.customConnect');
|
||||
default:
|
||||
return 'Connect';
|
||||
return t('payments.connect');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -128,39 +130,39 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
<div className="flex items-start gap-3">
|
||||
<CheckCircle className="text-green-600 dark:text-green-400 shrink-0 mt-0.5" size={20} />
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-green-800 dark:text-green-300">Stripe Connected</h4>
|
||||
<h4 className="font-medium text-green-800 dark:text-green-300">{t('payments.stripeConnected')}</h4>
|
||||
<p className="text-sm text-green-700 dark:text-green-400 mt-1">
|
||||
Your Stripe account is connected and ready to accept payments.
|
||||
{t('payments.stripeConnectedDesc')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-4">
|
||||
<h4 className="font-medium text-gray-900 dark:text-white mb-3">Account Details</h4>
|
||||
<h4 className="font-medium text-gray-900 dark:text-white mb-3">{t('payments.accountDetails')}</h4>
|
||||
<div className="space-y-2 text-sm">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-600 dark:text-gray-400">Account Type:</span>
|
||||
<span className="text-gray-600 dark:text-gray-400">{t('payments.accountType')}:</span>
|
||||
<span className="text-gray-900 dark:text-white">{getAccountTypeLabel()}</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-gray-600 dark:text-gray-400">Status:</span>
|
||||
<span className="text-gray-600 dark:text-gray-400">{t('payments.status')}:</span>
|
||||
<span className="px-2 py-0.5 text-xs font-medium rounded-full bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-300">
|
||||
{connectAccount.status}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-gray-600 dark:text-gray-400">Charges:</span>
|
||||
<span className="text-gray-600 dark:text-gray-400">{t('payments.charges')}:</span>
|
||||
<span className="flex items-center gap-1 text-green-600 dark:text-green-400">
|
||||
<CreditCard size={14} />
|
||||
Enabled
|
||||
{t('payments.enabled')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-gray-600 dark:text-gray-400">Payouts:</span>
|
||||
<span className="text-gray-600 dark:text-gray-400">{t('payments.payouts')}:</span>
|
||||
<span className="flex items-center gap-1 text-green-600 dark:text-green-400">
|
||||
<Wallet size={14} />
|
||||
{connectAccount.payouts_enabled ? 'Enabled' : 'Pending'}
|
||||
{connectAccount.payouts_enabled ? t('payments.enabled') : t('payments.pending')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -174,9 +176,9 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
return (
|
||||
<div className="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-6 text-center">
|
||||
<CheckCircle className="mx-auto text-green-600 dark:text-green-400 mb-3" size={48} />
|
||||
<h4 className="font-medium text-green-800 dark:text-green-300 text-lg">Onboarding Complete!</h4>
|
||||
<h4 className="font-medium text-green-800 dark:text-green-300 text-lg">{t('payments.onboardingComplete')}</h4>
|
||||
<p className="text-sm text-green-700 dark:text-green-400 mt-2">
|
||||
Your Stripe account has been set up. You can now accept payments.
|
||||
{t('payments.stripeSetupComplete')}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
@@ -190,7 +192,7 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
<div className="flex items-start gap-3">
|
||||
<AlertCircle className="text-red-600 dark:text-red-400 shrink-0 mt-0.5" size={20} />
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-red-800 dark:text-red-300">Setup Failed</h4>
|
||||
<h4 className="font-medium text-red-800 dark:text-red-300">{t('payments.setupFailed')}</h4>
|
||||
<p className="text-sm text-red-700 dark:text-red-400 mt-1">{errorMessage}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -202,7 +204,7 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
}}
|
||||
className="w-full px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 bg-gray-100 dark:bg-gray-700 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600"
|
||||
>
|
||||
Try Again
|
||||
{t('payments.tryAgain')}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
@@ -216,23 +218,22 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
<div className="flex items-start gap-3">
|
||||
<Building2 className="text-blue-600 dark:text-blue-400 shrink-0 mt-0.5" size={20} />
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-blue-800 dark:text-blue-300">Set Up Payments</h4>
|
||||
<h4 className="font-medium text-blue-800 dark:text-blue-300">{t('payments.setUpPayments')}</h4>
|
||||
<p className="text-sm text-blue-700 dark:text-blue-400 mt-1">
|
||||
As a {tier} tier business, you'll use Stripe Connect to accept payments.
|
||||
Complete the onboarding process to start accepting payments from your customers.
|
||||
{t('payments.tierPaymentDescriptionWithOnboarding', { tier })}
|
||||
</p>
|
||||
<ul className="mt-3 space-y-1 text-sm text-blue-700 dark:text-blue-400">
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle size={14} />
|
||||
Secure payment processing
|
||||
{t('payments.securePaymentProcessing')}
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle size={14} />
|
||||
Automatic payouts to your bank account
|
||||
{t('payments.automaticPayouts')}
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckCircle size={14} />
|
||||
PCI compliance handled for you
|
||||
{t('payments.pciCompliance')}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -244,7 +245,7 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
className="w-full flex items-center justify-center gap-2 px-4 py-3 text-sm font-medium text-white bg-[#635BFF] rounded-lg hover:bg-[#5851ea] transition-colors"
|
||||
>
|
||||
<CreditCard size={18} />
|
||||
Start Payment Setup
|
||||
{t('payments.startPaymentSetup')}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
@@ -255,7 +256,7 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-12">
|
||||
<Loader2 className="animate-spin text-[#635BFF] mb-4" size={40} />
|
||||
<p className="text-gray-600 dark:text-gray-400">Initializing payment setup...</p>
|
||||
<p className="text-gray-600 dark:text-gray-400">{t('payments.initializingPaymentSetup')}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -265,10 +266,9 @@ const ConnectOnboardingEmbed: React.FC<ConnectOnboardingEmbedProps> = ({
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="bg-gray-50 dark:bg-gray-700/50 border border-gray-200 dark:border-gray-600 rounded-lg p-4">
|
||||
<h4 className="font-medium text-gray-900 dark:text-white mb-2">Complete Your Account Setup</h4>
|
||||
<h4 className="font-medium text-gray-900 dark:text-white mb-2">{t('payments.completeAccountSetup')}</h4>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||
Fill out the information below to finish setting up your payment account.
|
||||
Your information is securely handled by Stripe.
|
||||
{t('payments.fillOutInfoForPayment')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user