feat: Add i18n support for AI insights with structured reasoning

Complete i18n implementation for internal service reasoning:
- Update AIInsight interface to include reasoning_data field
- Integrate useReasoningTranslation hook in AI Insights page
- Add translation keys for safety stock, price forecaster, and optimization

Translation coverage (EN/ES/EU):
- Safety Stock: statistical z-score, advanced variability, fixed percentage, errors
- Price Forecaster: price change predictions, volatility alerts, buying recommendations
- Optimization: EOQ calculations, MOQ/max constraints, tier pricing

Benefits:
- AI insights now display in user's preferred language
- Consistent with PO/Batch reasoning translation pattern
- Structured parameters enable rich, contextualized translations
- Falls back gracefully to description field if translation missing

Implementation:
- frontend/src/api/services/aiInsights.ts: Add reasoning_data to interface
- frontend/src/pages/app/analytics/ai-insights/AIInsightsPage.tsx: Translate insights
- frontend/src/locales/*/reasoning.json: Add safetyStock, priceForecaster, optimization keys

This completes the full i18n implementation for the bakery AI system.
This commit is contained in:
Claude
2025-11-07 19:25:08 +00:00
parent 9d284cae46
commit 5dacb939c9
5 changed files with 103 additions and 1 deletions

View File

@@ -6,12 +6,14 @@ import { useCurrentTenant } from '../../../../stores/tenant.store';
import { useAuthUser } from '../../../../stores/auth.store';
import { useAIInsights, useAIInsightStats, useApplyInsight, useDismissInsight } from '../../../../api/hooks/aiInsights';
import { AIInsight } from '../../../../api/services/aiInsights';
import { useReasoningTranslation } from '../../../../hooks/useReasoningTranslation';
const AIInsightsPage: React.FC = () => {
const [selectedCategory, setSelectedCategory] = useState('all');
const currentTenant = useCurrentTenant();
const user = useAuthUser();
const tenantId = currentTenant?.id || user?.tenant_id;
const { t } = useReasoningTranslation();
// Fetch real insights from API
const { data: insightsData, isLoading, refetch } = useAIInsights(
@@ -118,6 +120,32 @@ const AIInsightsPage: React.FC = () => {
}
};
/**
* Get translated description for an insight
* Uses reasoning_data if available, otherwise falls back to description field
*/
const getInsightDescription = (insight: AIInsight): string => {
if (insight.reasoning_data?.type) {
// Determine the category prefix based on source
let category = 'aiInsights';
if (insight.source_model === 'safety_stock_calculator') {
category = 'safetyStock';
} else if (insight.source_model === 'price_forecaster') {
category = 'priceForecaster';
} else if (insight.source_model === 'optimization') {
category = 'optimization';
}
try {
return t(`${category}.${insight.reasoning_data.type}`, insight.reasoning_data.parameters);
} catch (e) {
// Fall back to description if translation key not found
return insight.description;
}
}
return insight.description;
};
return (
<AnalyticsPageLayout
title="Inteligencia Artificial"
@@ -224,7 +252,7 @@ const AIInsightsPage: React.FC = () => {
</div>
<h3 className="text-lg font-semibold text-[var(--text-primary)] mb-2">{insight.title}</h3>
<p className="text-[var(--text-secondary)] mb-3">{insight.description}</p>
<p className="text-[var(--text-secondary)] mb-3">{getInsightDescription(insight)}</p>
<p className="text-sm font-medium text-[var(--color-success)] mb-4">{insight.impact}</p>
{/* Metrics */}