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:
poduck
2025-12-03 21:40:54 -05:00
parent 902582f4ba
commit c7f241b30a
34 changed files with 1313 additions and 592 deletions

View File

@@ -2,6 +2,7 @@ import React from 'react';
import { useDraggable } from '@dnd-kit/core';
import { Clock, GripVertical } from 'lucide-react';
import { clsx } from 'clsx';
import { useTranslation } from 'react-i18next';
export interface PendingAppointment {
id: number;
@@ -15,6 +16,7 @@ interface PendingItemProps {
}
const PendingItem: React.FC<PendingItemProps> = ({ appointment }) => {
const { t } = useTranslation();
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
id: `pending-${appointment.id}`,
data: {
@@ -43,7 +45,7 @@ const PendingItem: React.FC<PendingItemProps> = ({ appointment }) => {
</div>
<div className="mt-2 flex items-center gap-1 text-xs text-gray-400">
<Clock size={10} />
<span>{appointment.durationMinutes} min</span>
<span>{appointment.durationMinutes} {t('scheduler.min')}</span>
</div>
</div>
);
@@ -54,16 +56,18 @@ interface PendingSidebarProps {
}
const PendingSidebar: React.FC<PendingSidebarProps> = ({ appointments }) => {
const { t } = useTranslation();
return (
<div className="w-64 bg-gray-50 border-r border-gray-200 flex flex-col h-full shrink-0">
<div className="p-4 border-b border-gray-200 bg-gray-100">
<h3 className="text-xs font-bold text-gray-500 uppercase tracking-wider flex items-center gap-2">
<Clock size={12} /> Pending Requests ({appointments.length})
<Clock size={12} /> {t('scheduler.pendingRequests')} ({appointments.length})
</h3>
</div>
<div className="p-4 overflow-y-auto flex-1">
{appointments.length === 0 ? (
<div className="text-xs text-gray-400 italic text-center py-4">No pending requests</div>
<div className="text-xs text-gray-400 italic text-center py-4">{t('scheduler.noPendingRequests')}</div>
) : (
appointments.map(apt => (
<PendingItem key={apt.id} appointment={apt} />