- Updated TypeScript types to support reasoning_data field - Integrated useReasoningTranslation hook in all dashboard components: * ActionQueueCard: Translates PO reasoning_data and UI text * ProductionTimelineCard: Translates batch reasoning_data and UI text * OrchestrationSummaryCard: Translates all hardcoded English text * HealthStatusCard: Translates all hardcoded English text - Added missing translation keys to all language files (EN, ES, EU): * health_status: never, critical_issues, actions_needed * action_queue: total, critical, important * orchestration_summary: ready_to_plan, run_info, took, show_more/less * production_timeline: Complete rebuild with new keys - Components now support fallback for deprecated text fields - Full multilingual support: English, Spanish, Basque Dashboard is now fully translatable and will display reasoning in user's language.
11 KiB
Reasoning i18n Implementation - Complete Summary
✅ Completed Implementation
1. Backend: Structured Reasoning Data Generation
Created Standard Reasoning Types (shared/schemas/reasoning_types.py)
# Purchase Order Types
- low_stock_detection
- forecast_demand
- safety_stock_replenishment
- supplier_contract
- seasonal_demand
- production_requirement
- manual_request
# Production Batch Types
- forecast_demand
- customer_order
- stock_replenishment
- seasonal_preparation
- promotion_event
- urgent_order
- regular_schedule
Helper Functions
create_po_reasoning_low_stock()
create_po_reasoning_forecast_demand()
create_batch_reasoning_forecast_demand()
create_batch_reasoning_customer_order()
2. Backend: Services Updated
✅ Production Service
File: services/production/app/services/production_service.py:1839-1867
- Generates
reasoning_datawhen creating production batches - Includes: product_name, predicted_demand, current_stock, confidence_score
Example Output:
{
"type": "forecast_demand",
"parameters": {
"product_name": "Croissant",
"predicted_demand": 500,
"current_stock": 120,
"production_needed": 380,
"confidence_score": 87
},
"urgency": {
"level": "normal",
"ready_by_time": "08:00"
},
"metadata": {
"trigger_source": "orchestrator_auto",
"ai_assisted": true
}
}
✅ Procurement Service
File: services/procurement/app/services/procurement_service.py:874-1040
- NEW: Implemented actual PO creation (replaced placeholder!)
- Groups requirements by supplier
- Intelligently chooses reasoning type based on context
- Generates comprehensive reasoning_data
Example Output:
{
"type": "low_stock_detection",
"parameters": {
"supplier_name": "Harinas del Norte",
"product_names": ["Flour Type 55", "Flour Type 45"],
"current_stock": 45.5,
"required_stock": 200,
"days_until_stockout": 3,
"stock_percentage": 22.8
},
"consequence": {
"type": "stockout_risk",
"severity": "high",
"impact_days": 3,
"affected_products": ["Baguette", "Croissant"],
"estimated_lost_orders": 15
},
"metadata": {
"trigger_source": "orchestrator_auto",
"forecast_confidence": 0.85,
"ai_assisted": true
}
}
✅ Dashboard Service
File: services/orchestrator/app/services/dashboard_service.py
- Returns
reasoning_datainstead of TEXT fields - Creates defaults if missing
- Both PO actions and production timeline use structured data
3. Backend: Database Schema
✅ Models Updated
- PurchaseOrder: Removed
reasoning,consequenceTEXT columns - ProductionBatch: Removed
reasoningTEXT column - Both use only
reasoning_data(JSONB/JSON)
✅ Unified Schemas Updated
services/procurement/migrations/001_unified_initial_schema.pyservices/production/migrations/001_unified_initial_schema.py- No separate migration needed - updated initial schema
4. Frontend: i18n Translation System
✅ Translation Files Created
Languages: English (EN), Spanish (ES), Basque/Euskara (EU)
Files:
frontend/src/locales/en/reasoning.jsonfrontend/src/locales/es/reasoning.jsonfrontend/src/locales/eu/reasoning.json
Translation Coverage:
- ✅ All purchase order reasoning types
- ✅ All production batch reasoning types
- ✅ All consequence types
- ✅ Severity levels
- ✅ Error codes
- ✅ Complete JTBD dashboard UI text
Example Translations:
| Language | Translation |
|---|---|
| 🇬🇧 EN | "Low stock for {{supplier_name}}. Stock runs out in {{days_until_stockout}} days." |
| 🇪🇸 ES | "Stock bajo para {{supplier_name}}. Se agota en {{days_until_stockout}} días." |
| 🇪🇺 EU | "{{supplier_name}}-rentzat stock baxua. {{days_until_stockout}} egunetan amaituko da." |
✅ Translation Hook Created
File: frontend/src/hooks/useReasoningTranslation.ts
Functions:
translatePOReasonng(reasoningData) // Purchase orders
translateBatchReasoning(reasoningData) // Production batches
translateConsequence(consequenceData) // Consequences
translateSeverity(severity) // Severity levels
translateTrigger(trigger) // Trigger sources
translateError(errorCode) // Error codes
// High-level formatters
formatPOAction(reasoningData) // Complete PO formatting
formatBatchAction(reasoningData) // Complete batch formatting
Usage Example:
import { useReasoningFormatter } from '@/hooks/useReasoningTranslation';
function ActionQueueCard({ action }) {
const { formatPOAction } = useReasoningFormatter();
const { reasoning, consequence, severity } = formatPOAction(action.reasoning_data);
return (
<div>
<p>{reasoning}</p> {/* Translated! */}
<p>{consequence}</p> {/* Translated! */}
</div>
);
}
🔄 Remaining Work
1. Frontend Components Need Updates
❌ ActionQueueCard.tsx
Current: Expects reasoning and consequence TEXT fields
Needed: Use useReasoningFormatter() to translate reasoning_data
Change Required:
// BEFORE
<p>{action.reasoning}</p>
<p>{action.consequence}</p>
// AFTER
import { useReasoningFormatter } from '@/hooks/useReasoningTranslation';
const { formatPOAction } = useReasoningFormatter();
const { reasoning, consequence } = formatPOAction(action.reasoning_data);
<p>{reasoning}</p>
<p>{consequence}</p>
❌ ProductionTimelineCard.tsx
Needed: Use formatBatchAction() to translate batch reasoning
❌ OrchestrationSummaryCard.tsx
Needed: Replace hardcoded English text with i18n keys:
- "Last Night I Planned Your Day" →
t('reasoning:jtbd.orchestration_summary.title') - "All caught up!" →
t('reasoning:jtbd.action_queue.all_caught_up') - etc.
❌ HealthStatusCard.tsx
Needed: Replace hardcoded text with i18n
2. Backend Services Need Error Code Updates
❌ Safety Stock Calculator
File: services/procurement/app/services/safety_stock_calculator.py
Current:
reasoning='Lead time or demand std dev is zero or negative'
reasoning='Insufficient historical demand data...'
Needed:
reasoning_data={
"type": "error",
"code": "LEAD_TIME_INVALID",
"parameters": {}
}
❌ Replenishment Planning Service
File: services/procurement/app/services/replenishment_planning_service.py
Current:
reasoning='Insufficient data for safety stock calculation'
Needed:
reasoning_data={
"type": "error",
"code": "INSUFFICIENT_DATA",
"parameters": {}
}
3. Demo Seed Scripts Need Updates
❌ Purchase Orders Seed
File: services/procurement/scripts/demo/seed_demo_purchase_orders.py
Current (lines 126-127):
reasoning_text = f"Low stock detected for {supplier.name} items..."
consequence_text = f"Stock-out risk in {days_until_delivery + 2} days..."
Needed:
from shared.schemas.reasoning_types import create_po_reasoning_low_stock
reasoning_data = create_po_reasoning_low_stock(
supplier_name=supplier.name,
product_names=[...],
current_stock=...,
required_stock=...,
days_until_stockout=days_until_delivery + 2
)
❌ Production Batches Seed
File: services/production/scripts/demo/seed_demo_batches.py
Needed: Similar update using create_batch_reasoning_*() functions
📋 Quick Implementation Checklist
High Priority (Breaks Current Functionality)
- Update
ActionQueueCard.tsxto use reasoning translation - Update
ProductionTimelineCard.tsxto use reasoning translation - Update demo seed scripts to use structured reasoning_data
Medium Priority (Improves UX)
- Update
OrchestrationSummaryCard.tsxwith i18n - Update
HealthStatusCard.tsxwith i18n - Update
InsightsGrid.tsxwith i18n (if needed)
Low Priority (Code Quality)
- Update safety stock calculator with error codes
- Update replenishment service with error codes
- Audit ML services for hardcoded text
🎯 Example Implementation for ActionQueueCard
// frontend/src/components/dashboard/ActionQueueCard.tsx
import { useReasoningFormatter } from '@/hooks/useReasoningTranslation';
import { useTranslation } from 'react-i18next';
function ActionItemCard({ action, onApprove, onViewDetails, onModify }: ...) {
const { formatPOAction } = useReasoningFormatter();
const { t } = useTranslation('reasoning');
// Translate reasoning_data
const { reasoning, consequence, severity } = formatPOAction(action.reasoning_data);
return (
<div className={`...`}>
{/* Reasoning (always visible) */}
<div className="bg-white rounded-md p-3 mb-3">
<p className="text-sm font-medium text-gray-700 mb-1">
{t('jtbd.action_queue.why_needed')}
</p>
<p className="text-sm text-gray-600">{reasoning}</p>
</div>
{/* Consequence (expandable) */}
<button onClick={() => setExpanded(!expanded)} className="...">
{t('jtbd.action_queue.what_if_not')}
</button>
{expanded && (
<div className="bg-amber-50 border border-amber-200 rounded-md p-3 mb-3">
<p className="text-sm text-amber-900">{consequence}</p>
{severity && (
<span className="text-xs font-semibold">{severity}</span>
)}
</div>
)}
</div>
);
}
🚀 Benefits Achieved
-
✅ Multilingual Support
- Dashboard works in EN, ES, and EU
- Easy to add more languages (CA, FR, etc.)
-
✅ Maintainability
- Backend: One place to define reasoning logic
- Frontend: Translations in organized JSON files
- No hardcoded text scattered across code
-
✅ Consistency
- Same reasoning type always translates the same way
- Centralized terminology
-
✅ Flexibility
- Can change wording without touching code
- Can A/B test different phrasings
- Translators can work independently
-
✅ Type Safety
- TypeScript interfaces for reasoning_data
- Compile-time checks for translation keys
📚 Documentation
- Reasoning Types:
shared/schemas/reasoning_types.py - Translation Hook:
frontend/src/hooks/useReasoningTranslation.ts - Translation Files:
frontend/src/locales/{en,es,eu}/reasoning.json - Audit Report:
REASONING_I18N_AUDIT.md
Next Steps
-
Update frontend components (30-60 min)
- Replace TEXT field usage with reasoning_data translation
- Use
useReasoningFormatter()hook - Replace hardcoded strings with
t()calls
-
Update demo seed scripts (15-30 min)
- Replace hardcoded text with helper functions
- Test demo data generation
-
Update backend services (15-30 min)
- Replace hardcoded error messages with error codes
- Frontend will translate error codes
-
Test (30 min)
- Switch between EN, ES, EU
- Verify all reasoning types display correctly
- Check mobile responsiveness
Total Estimated Time: 2-3 hours for complete implementation