feat: translate AgenticReadinessTab and add translation infrastructure

Translate AgenticReadinessTab from Spanish to English with i18next support:
- Replaced ~150 hardcoded Spanish strings with translation keys
- Added comprehensive translation keys to en.json and es.json
- Organized translations under agenticReadiness.* namespace
- Includes: methodology, tier explanations, factor descriptions, UI labels

Translation structure:
- agenticReadiness.methodology: Index definition and categories
- agenticReadiness.tiers: AUTOMATE, ASSIST, AUGMENT, HUMAN-ONLY
- agenticReadiness.factors: Predictability, simplicity, volume, ROI
- agenticReadiness.redFlags: CV, transfer, volume, data quality
- agenticReadiness.table: Headers, filters, sorting
- agenticReadiness.summary: Volume metrics and interpretations

All UI strings now support EN/ES language switching.
Frontend compiles successfully with no errors.

https://claude.ai/code/session_01GNbnkFoESkRcnPr3bLCYDg
This commit is contained in:
Claude
2026-02-07 17:31:40 +00:00
parent a3a645008c
commit 76ed597e47
3 changed files with 654 additions and 40 deletions

View File

@@ -20,6 +20,7 @@ import {
formatNumber,
formatPercent,
} from '../../config/designSystem';
import { useTranslation } from 'react-i18next';
// ============================================
// RED FLAGS CONFIGURATION AND DETECTION
@@ -38,50 +39,51 @@ interface RedFlagConfig {
description: string;
}
const RED_FLAG_CONFIGS: RedFlagConfig[] = [
// Note: These configs will be translated in the component using t() function
const getRedFlagConfigs = (t: any): RedFlagConfig[] => [
{
id: 'cv_high',
label: 'Critical AHT CV',
shortLabel: 'CV',
label: t('agenticReadiness.redFlags.cvCritical'),
shortLabel: t('agenticReadiness.redFlags.cvCriticalShort'),
threshold: 120,
operator: '>',
getValue: (q) => q.cv_aht,
format: (v) => `${v.toFixed(0)}%`,
color: 'red',
description: 'Extreme variability - unpredictable processes'
description: t('agenticReadiness.redFlags.cvCriticalDesc')
},
{
id: 'transfer_high',
label: 'Excessive Transfer',
shortLabel: 'Transfer',
label: t('agenticReadiness.redFlags.transferExcessive'),
shortLabel: t('agenticReadiness.redFlags.transferExcessiveShort'),
threshold: 50,
operator: '>',
getValue: (q) => q.transfer_rate,
format: (v) => `${v.toFixed(0)}%`,
color: 'orange',
description: 'High complexity - requires frequent escalation'
description: t('agenticReadiness.redFlags.transferExcessiveDesc')
},
{
id: 'volume_low',
label: 'Insufficient Volume',
shortLabel: 'Vol',
label: t('agenticReadiness.redFlags.volumeInsufficient'),
shortLabel: t('agenticReadiness.redFlags.volumeInsufficientShort'),
threshold: 50,
operator: '<',
getValue: (q) => q.volume,
format: (v) => v.toLocaleString(),
color: 'slate',
description: 'Negative ROI - volume doesn\'t justify investment'
description: t('agenticReadiness.redFlags.volumeInsufficientDesc')
},
{
id: 'valid_low',
label: 'Low Data Quality',
shortLabel: 'Valid',
label: t('agenticReadiness.redFlags.dataQualityLow'),
shortLabel: t('agenticReadiness.redFlags.dataQualityLowShort'),
threshold: 30,
operator: '<',
getValue: (q) => q.volume > 0 ? (q.volumeValid / q.volume) * 100 : 0,
format: (v) => `${v.toFixed(0)}%`,
color: 'amber',
description: 'Unreliable data - distorted metrics'
description: t('agenticReadiness.redFlags.dataQualityLowDesc')
}
];
@@ -91,10 +93,10 @@ interface DetectedRedFlag {
value: number;
}
function detectRedFlags(queue: OriginalQueueMetrics): DetectedRedFlag[] {
function detectRedFlags(queue: OriginalQueueMetrics, configs: RedFlagConfig[]): DetectedRedFlag[] {
const flags: DetectedRedFlag[] = [];
for (const config of RED_FLAG_CONFIGS) {
for (const config of configs) {
const value = config.getValue(queue);
const hasFlag = config.operator === '>'
? value > config.threshold
@@ -109,13 +111,13 @@ function detectRedFlags(queue: OriginalQueueMetrics): DetectedRedFlag[] {
}
// v3.5: Individual Red Flag badge component
function RedFlagBadge({ flag, size = 'sm' }: { flag: DetectedRedFlag; size?: 'sm' | 'md' }) {
function RedFlagBadge({ flag, size = 'sm', t }: { flag: DetectedRedFlag; size?: 'sm' | 'md'; t: any }) {
const sizeClasses = size === 'md' ? 'px-2 py-1 text-xs' : 'px-1.5 py-0.5 text-[10px]';
return (
<span
className={`inline-flex items-center gap-1 ${sizeClasses} rounded bg-red-100 text-red-700 font-medium`}
title={`${flag.config.label}: ${flag.config.format(flag.value)} (umbral: ${flag.config.operator}${flag.config.threshold})`}
title={`${flag.config.label}: ${flag.config.format(flag.value)} ${t('agenticReadiness.redFlags.threshold', { operator: flag.config.operator, value: flag.config.threshold })}`}
>
<XCircle className="w-3 h-3" />
{flag.config.shortLabel}: {flag.config.format(flag.value)}
@@ -124,8 +126,8 @@ function RedFlagBadge({ flag, size = 'sm' }: { flag: DetectedRedFlag; size?: 'sm
}
// v3.5: Componente de lista de Red Flags de una cola
function RedFlagsList({ queue, compact = false }: { queue: OriginalQueueMetrics; compact?: boolean }) {
const flags = detectRedFlags(queue);
function RedFlagsList({ queue, compact = false, configs, t }: { queue: OriginalQueueMetrics; compact?: boolean; configs: RedFlagConfig[]; t: any }) {
const flags = detectRedFlags(queue, configs);
if (flags.length === 0) return null;
@@ -133,7 +135,7 @@ function RedFlagsList({ queue, compact = false }: { queue: OriginalQueueMetrics;
return (
<div className="flex flex-wrap gap-1">
{flags.map(flag => (
<RedFlagBadge key={flag.config.id} flag={flag} size="sm" />
<RedFlagBadge key={flag.config.id} flag={flag} size="sm" t={t} />
))}
</div>
);
@@ -146,7 +148,7 @@ function RedFlagsList({ queue, compact = false }: { queue: OriginalQueueMetrics;
<XCircle className="w-3 h-3 text-red-500 flex-shrink-0" />
<span className="text-red-700 font-medium">{flag.config.label}:</span>
<span className="text-red-600">{flag.config.format(flag.value)}</span>
<span className="text-gray-400">(umbral: {flag.config.operator}{flag.config.threshold})</span>
<span className="text-gray-400">({t('agenticReadiness.redFlags.threshold', { operator: flag.config.operator, value: flag.config.threshold })})</span>
</div>
))}
</div>
@@ -173,46 +175,46 @@ interface TierExplanation {
recommendation: string;
}
const TIER_EXPLANATIONS: TierExplanation[] = [
const getTierExplanations = (t: any): TierExplanation[] => [
{
tier: 'AUTOMATE',
label: 'Automatizable',
label: t('agenticReadiness.automatable'),
emoji: '🤖',
color: '#10b981',
bgColor: '#d1fae5',
description: 'Procesos maduros listos para automatización completa con agente virtual.',
criteria: 'Score ≥7.5: CV AHT <75%, Transfer <15%, Volumen >500/mes',
recommendation: 'Desplegar agente virtual con resolución autónoma'
description: t('agenticReadiness.automatableDesc'),
criteria: t('agenticReadiness.automatableCriteria'),
recommendation: t('agenticReadiness.automatableAction')
},
{
tier: 'ASSIST',
label: 'Asistible',
label: t('agenticReadiness.assistable'),
emoji: '🤝',
color: '#3b82f6',
bgColor: '#dbeafe',
description: 'Candidatos a Copilot: IA asiste al agente humano en tiempo real.',
criteria: 'Score 5.5-7.5: Procesos semiestructurados con variabilidad moderada',
recommendation: 'Implementar Copilot con sugerencias y búsqueda inteligente'
description: t('agenticReadiness.assistableDesc'),
criteria: t('agenticReadiness.assistableCriteria'),
recommendation: t('agenticReadiness.assistableAction')
},
{
tier: 'AUGMENT',
label: 'Optimizable',
label: t('agenticReadiness.optimizable'),
emoji: '📚',
color: '#f59e0b',
bgColor: '#fef3c7',
description: 'Requiere herramientas y estandarización antes de automatizar.',
criteria: 'Score 3.5-5.5: Alta variabilidad o complejidad, necesita optimización',
recommendation: 'Desplegar KB mejorada, scripts guiados, herramientas de soporte'
description: t('agenticReadiness.optimizableDesc'),
criteria: t('agenticReadiness.optimizableCriteria'),
recommendation: t('agenticReadiness.optimizableAction')
},
{
tier: 'HUMAN-ONLY',
label: 'Solo Humano',
label: t('agenticReadiness.humanOnly'),
emoji: '👤',
color: '#6b7280',
bgColor: '#f3f4f6',
description: 'No apto para automatización: volumen insuficiente o complejidad extrema.',
criteria: 'Score <3.5 o Red Flags: CV >120%, Transfer >50%, Vol <50',
recommendation: 'Mantener gestión humana, evaluar periódicamente'
description: t('agenticReadiness.humanOnlyDesc'),
criteria: t('agenticReadiness.humanOnlyCriteria'),
recommendation: t('agenticReadiness.humanOnlyAction')
}
];