Update help/docs pages to use i18n translations

- Update locales/index.ts to import help namespace for all languages
- Convert DocumentationPage.tsx to use useTranslation('help')
  * All sections now use translation keys from help.json
  * Difficulty labels, categories, and articles fully internationalized
  * UI strings (titles, buttons, placeholders) use translations
- Convert HelpCenterPage.tsx to use useTranslation('help')
  * Categories loaded from translations
  * FAQs loaded dynamically from help.json array
  * All UI strings internationalized (search, titles, contact info)
- Both pages now support Spanish, English, and Basque languages
- Maintains full backward compatibility with existing Spanish content

Result: Complete i18n implementation for /help and /help/docs routes
This commit is contained in:
Claude
2025-11-18 12:07:37 +00:00
parent c41ba0030e
commit d98fed0cd0
3 changed files with 128 additions and 209 deletions

View File

@@ -39,129 +39,129 @@ interface DocArticle {
}
const DocumentationPage: React.FC = () => {
const { t } = useTranslation();
const { t } = useTranslation('help');
const [activeSection, setActiveSection] = useState<string>('getting-started');
const sections: DocSection[] = [
{
id: 'getting-started',
title: 'Primeros Pasos',
description: 'Todo lo que necesitas para comenzar',
title: t('categories.gettingStarted.title'),
description: t('categories.gettingStarted.description'),
icon: Rocket,
articles: [
{
id: 'quick-start',
title: 'Guía de Inicio Rápido',
description: 'Configura tu cuenta en 10 minutos',
readTime: '5 min',
title: t('articles.gettingStarted.quickStart.title'),
description: t('articles.gettingStarted.quickStart.description'),
readTime: `${t('articles.gettingStarted.quickStart.readTime')} ${t('docs.readTime')}`,
difficulty: 'beginner',
},
{
id: 'import-data',
title: 'Importar Datos Históricos',
description: 'Cómo subir tu historial de ventas desde Excel o TPV',
readTime: '8 min',
title: t('articles.gettingStarted.importData.title'),
description: t('articles.gettingStarted.importData.description'),
readTime: `${t('articles.gettingStarted.importData.readTime')} ${t('docs.readTime')}`,
difficulty: 'beginner',
},
{
id: 'products-catalog',
title: 'Configurar Catálogo de Productos',
description: 'Añade tus productos, recetas e ingredientes',
readTime: '6 min',
title: t('articles.gettingStarted.productsCatalog.title'),
description: t('articles.gettingStarted.productsCatalog.description'),
readTime: `${t('articles.gettingStarted.productsCatalog.readTime')} ${t('docs.readTime')}`,
difficulty: 'beginner',
},
{
id: 'first-prediction',
title: 'Tu Primera Predicción',
description: 'Interpreta y ajusta las predicciones de demanda',
readTime: '10 min',
title: t('articles.gettingStarted.firstPrediction.title'),
description: t('articles.gettingStarted.firstPrediction.description'),
readTime: `${t('articles.gettingStarted.firstPrediction.readTime')} ${t('docs.readTime')}`,
difficulty: 'beginner',
},
],
},
{
id: 'features',
title: 'Funcionalidades',
description: 'Guías detalladas de cada módulo',
title: t('categories.features.title'),
description: t('categories.features.description'),
icon: Package,
articles: [
{
id: 'demand-forecasting',
title: 'Predicción de Demanda con IA',
description: 'Cómo funciona el algoritmo y cómo sacarle el máximo partido',
readTime: '12 min',
title: t('articles.features.demandForecasting.title'),
description: t('articles.features.demandForecasting.description'),
readTime: `${t('articles.features.demandForecasting.readTime')} ${t('docs.readTime')}`,
difficulty: 'intermediate',
},
{
id: 'production-planning',
title: 'Planificación de Producción',
description: 'Optimiza tu horneado diario basándote en predicciones',
readTime: '10 min',
title: t('articles.features.productionPlanning.title'),
description: t('articles.features.productionPlanning.description'),
readTime: `${t('articles.features.productionPlanning.readTime')} ${t('docs.readTime')}`,
difficulty: 'intermediate',
},
{
id: 'inventory-management',
title: 'Gestión de Inventario',
description: 'Controla stock, proveedores y compras',
readTime: '9 min',
title: t('articles.features.inventoryManagement.title'),
description: t('articles.features.inventoryManagement.description'),
readTime: `${t('articles.features.inventoryManagement.readTime')} ${t('docs.readTime')}`,
difficulty: 'intermediate',
},
{
id: 'pos-integration',
title: 'Punto de Venta (TPV)',
description: 'Registra ventas y sincroniza con predicciones',
readTime: '8 min',
title: t('articles.features.posIntegration.title'),
description: t('articles.features.posIntegration.description'),
readTime: `${t('articles.features.posIntegration.readTime')} ${t('docs.readTime')}`,
difficulty: 'beginner',
},
{
id: 'waste-tracking',
title: 'Seguimiento de Desperdicios',
description: 'Mide, analiza y reduce el desperdicio alimentario',
readTime: '7 min',
title: t('articles.features.wasteTracking.title'),
description: t('articles.features.wasteTracking.description'),
readTime: `${t('articles.features.wasteTracking.readTime')} ${t('docs.readTime')}`,
difficulty: 'beginner',
},
],
},
{
id: 'analytics',
title: 'Análisis e Insights',
description: 'Interpreta tus datos y métricas',
title: t('categories.analytics.title'),
description: t('categories.analytics.description'),
icon: BarChart3,
articles: [
{
id: 'dashboard-overview',
title: 'Panel de Control',
description: 'Entiende todas las métricas clave de un vistazo',
readTime: '8 min',
title: t('articles.analytics.dashboardOverview.title'),
description: t('articles.analytics.dashboardOverview.description'),
readTime: `${t('articles.analytics.dashboardOverview.readTime')} ${t('docs.readTime')}`,
difficulty: 'beginner',
},
{
id: 'reports',
title: 'Informes y Reportes',
description: 'Genera y exporta informes personalizados',
readTime: '10 min',
title: t('articles.analytics.reports.title'),
description: t('articles.analytics.reports.description'),
readTime: `${t('articles.analytics.reports.readTime')} ${t('docs.readTime')}`,
difficulty: 'intermediate',
},
{
id: 'ai-insights',
title: 'Insights de IA',
description: 'Descubre patrones y oportunidades automáticamente',
readTime: '12 min',
title: t('articles.analytics.aiInsights.title'),
description: t('articles.analytics.aiInsights.description'),
readTime: `${t('articles.analytics.aiInsights.readTime')} ${t('docs.readTime')}`,
difficulty: 'advanced',
},
{
id: 'performance-metrics',
title: 'Métricas de Rendimiento',
description: 'KPIs clave: márgenes, rotación, precisión de predicciones',
readTime: '15 min',
title: t('articles.analytics.performanceMetrics.title'),
description: t('articles.analytics.performanceMetrics.description'),
readTime: `${t('articles.analytics.performanceMetrics.readTime')} ${t('docs.readTime')}`,
difficulty: 'intermediate',
},
],
},
{
id: 'account',
title: 'Gestión de Cuenta',
description: 'Administra tu perfil y equipo',
title: t('categories.account.title'),
description: t('categories.account.description'),
icon: Settings,
articles: [
{
@@ -196,8 +196,8 @@ const DocumentationPage: React.FC = () => {
},
{
id: 'billing',
title: 'Facturación y Planes',
description: 'Suscripciones, pagos y facturas',
title: t('categories.billing.title'),
description: t('categories.billing.description'),
icon: CreditCard,
articles: [
{
@@ -232,8 +232,8 @@ const DocumentationPage: React.FC = () => {
},
{
id: 'privacy',
title: 'Privacidad y Seguridad',
description: 'RGPD, datos y cumplimiento',
title: t('categories.privacy.title'),
description: t('categories.privacy.description'),
icon: Shield,
articles: [
{
@@ -284,16 +284,7 @@ const DocumentationPage: React.FC = () => {
};
const getDifficultyLabel = (difficulty: string) => {
switch (difficulty) {
case 'beginner':
return 'Principiante';
case 'intermediate':
return 'Intermedio';
case 'advanced':
return 'Avanzado';
default:
return difficulty;
}
return t(`difficulty.${difficulty}` as any) || difficulty;
};
return (
@@ -313,14 +304,13 @@ const DocumentationPage: React.FC = () => {
<div className="text-center max-w-4xl mx-auto">
<div className="inline-flex items-center gap-2 bg-[var(--color-primary)]/10 text-[var(--color-primary)] px-4 py-2 rounded-full text-sm font-medium mb-6">
<FileText className="w-4 h-4" />
<span>Documentación</span>
<span>{t('docs.subtitle')}</span>
</div>
<h1 className="text-4xl lg:text-6xl font-extrabold text-[var(--text-primary)] mb-6">
Guías Completas Para
<span className="block text-[var(--color-primary)]">Dominar Panadería IA</span>
{t('docs.title')}
</h1>
<p className="text-xl text-[var(--text-secondary)] leading-relaxed mb-8">
Tutoriales paso a paso, mejores prácticas y trucos para aprovechar al máximo la plataforma
{t('docs.description')}
</p>
{/* Quick Actions */}
@@ -331,14 +321,14 @@ const DocumentationPage: React.FC = () => {
className="inline-flex items-center gap-2 px-6 py-3 bg-[var(--color-primary)] text-white rounded-xl font-bold hover:shadow-xl transition-all hover:scale-105"
>
<Rocket className="w-5 h-5" />
<span>Comenzar</span>
<span>{t('docs.getStarted')}</span>
</a>
<Link
to="/help"
className="inline-flex items-center gap-2 px-6 py-3 border-2 border-[var(--border-primary)] text-[var(--text-primary)] rounded-xl font-medium hover:border-[var(--color-primary)] transition-all"
>
<HelpCircle className="w-5 h-5" />
<span>Centro de Ayuda</span>
<span>{t('docs.backToHelp')}</span>
</Link>
</div>
</div>
@@ -353,7 +343,7 @@ const DocumentationPage: React.FC = () => {
<div className="lg:col-span-1">
<div className="sticky top-8">
<h3 className="text-lg font-bold text-[var(--text-primary)] mb-4">
Secciones
{t('docs.sectionsTitle')}
</h3>
<nav className="space-y-2">
{sections.map((section) => (
@@ -374,7 +364,7 @@ const DocumentationPage: React.FC = () => {
activeSection === section.id ? 'text-white/80' : 'text-[var(--text-tertiary)]'
}`}
>
{section.articles.length} artículos
{section.articles.length} {t('docs.articlesCount')}
</div>
</div>
</button>
@@ -384,7 +374,7 @@ const DocumentationPage: React.FC = () => {
{/* Quick Links */}
<div className="mt-8 p-4 bg-[var(--bg-secondary)] rounded-xl border border-[var(--border-primary)]">
<h4 className="font-bold text-[var(--text-primary)] mb-3 text-sm">
Enlaces Rápidos
{t('docs.quickLinks')}
</h4>
<div className="space-y-2 text-sm">
<Link
@@ -392,21 +382,21 @@ const DocumentationPage: React.FC = () => {
className="flex items-center gap-2 text-[var(--text-secondary)] hover:text-[var(--color-primary)] transition-colors"
>
<HelpCircle className="w-4 h-4" />
<span>Centro de Ayuda</span>
<span>{t('docs.backToHelp')}</span>
</Link>
<Link
to="/help/support"
className="flex items-center gap-2 text-[var(--text-secondary)] hover:text-[var(--color-primary)] transition-colors"
>
<ExternalLink className="w-4 h-4" />
<span>Contactar Soporte</span>
<span>{t('docs.contactSupport')}</span>
</Link>
<a
href="#"
className="flex items-center gap-2 text-[var(--text-secondary)] hover:text-[var(--color-primary)] transition-colors"
>
<Download className="w-4 h-4" />
<span>Descargar PDF</span>
<span>{t('docs.downloadPdf')}</span>
</a>
</div>
</div>
@@ -473,10 +463,10 @@ const DocumentationPage: React.FC = () => {
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl lg:text-4xl font-extrabold text-[var(--text-primary)] mb-4">
Tutoriales en Vídeo
{t('docs.videoTutorialsTitle')}
</h2>
<p className="text-xl text-[var(--text-secondary)]">
Aprende viendo (próximamente)
{t('docs.videoTutorialsSubtitle')}
</p>
</div>
@@ -524,7 +514,7 @@ const DocumentationPage: React.FC = () => {
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl lg:text-4xl font-extrabold text-[var(--text-primary)] mb-4">
Recursos Adicionales
{t('docs.additionalResourcesTitle')}
</h2>
</div>
@@ -532,39 +522,39 @@ const DocumentationPage: React.FC = () => {
<div className="bg-blue-50 dark:bg-blue-900/20 rounded-2xl p-6 border-2 border-blue-200 dark:border-blue-800">
<Info className="w-8 h-8 text-blue-600 mb-4" />
<h3 className="text-lg font-bold text-[var(--text-primary)] mb-2">
Glosario de Términos
{t('resources.glossary.title')}
</h3>
<p className="text-sm text-[var(--text-secondary)] mb-4">
Definiciones de conceptos clave y terminología técnica
{t('resources.glossary.description')}
</p>
<a href="#glossary" className="text-blue-600 hover:underline font-medium text-sm">
Ver Glosario
{t('resources.glossary.action')}
</a>
</div>
<div className="bg-amber-50 dark:bg-amber-900/20 rounded-2xl p-6 border-2 border-amber-200 dark:border-amber-800">
<AlertCircle className="w-8 h-8 text-amber-600 mb-4" />
<h3 className="text-lg font-bold text-[var(--text-primary)] mb-2">
Solución de Problemas
{t('resources.troubleshooting.title')}
</h3>
<p className="text-sm text-[var(--text-secondary)] mb-4">
Errores comunes y cómo resolverlos rápidamente
{t('resources.troubleshooting.description')}
</p>
<Link to="/help" className="text-amber-600 hover:underline font-medium text-sm">
Ver Soluciones
{t('resources.troubleshooting.action')}
</Link>
</div>
<div className="bg-green-50 dark:bg-green-900/20 rounded-2xl p-6 border-2 border-green-200 dark:border-green-800">
<CheckCircle2 className="w-8 h-8 text-green-600 mb-4" />
<h3 className="text-lg font-bold text-[var(--text-primary)] mb-2">
Mejores Prácticas
{t('resources.bestPractices.title')}
</h3>
<p className="text-sm text-[var(--text-secondary)] mb-4">
Tips y consejos de expertos para optimizar tu uso
{t('resources.bestPractices.description')}
</p>
<a href="#best-practices" className="text-green-600 hover:underline font-medium text-sm">
Leer Tips
{t('resources.bestPractices.action')}
</a>
</div>
</div>
@@ -575,16 +565,16 @@ const DocumentationPage: React.FC = () => {
<section className="py-20 bg-gradient-to-r from-[var(--color-primary)] to-orange-600">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 className="text-3xl lg:text-4xl font-bold text-white mb-6">
¿Listo Para Empezar?
{t('docs.ctaTitle')}
</h2>
<p className="text-xl text-white/90 mb-8">
Regístrate en el programa piloto y obtén 3 meses gratis
{t('docs.ctaSubtitle')}
</p>
<Link
to="/register"
className="inline-flex items-center gap-2 px-8 py-4 bg-white text-[var(--color-primary)] rounded-xl font-bold hover:shadow-2xl transition-all hover:scale-105"
>
<span>Crear Cuenta Gratis</span>
<span>{t('docs.ctaButton')}</span>
<ChevronRight className="w-5 h-5" />
</Link>
</div>