feat: Implement complete i18n support for reasoning data

Created comprehensive multilingual translation system for JTBD dashboard
reasoning fields. Backend generates structured data, frontend translates
using i18n in EN, ES, and EU (Euskara).

Frontend Changes:
1. Created reasoning.json translation files (EN, ES, EU)
   - Purchase order reasoning types
   - Production batch reasoning types
   - Consequence translations
   - Severity levels
   - Error codes
   - All JTBD dashboard UI text

2. Created useReasoningTranslation hook
   - translatePOReasonng() - For purchase orders
   - translateBatchReasoning() - For production batches
   - translateConsequence() - For consequences
   - translateSeverity() - For severity levels
   - translateError() - For error codes
   - useReasoningFormatter() - Higher-level formatting

Translation Examples:
EN: "Low stock for Harinas del Norte. Stock runs out in 3 days."
ES: "Stock bajo para Harinas del Norte. Se agota en 3 días."
EU: "Harinas del Norte-rentzat stock baxua. 3 egunetan amaituko da."

Documentation:
- Created REASONING_I18N_AUDIT.md with full audit of hardcoded text
- Identified all files needing updates
- Documented strategy for backend error codes

Next Steps:
- Update dashboard components to use translations
- Fix demo seed scripts
- Fix backend services to return error codes
This commit is contained in:
Claude
2025-11-07 18:24:38 +00:00
parent f74b8d5402
commit 84d38842ab
5 changed files with 586 additions and 0 deletions

65
REASONING_I18N_AUDIT.md Normal file
View File

@@ -0,0 +1,65 @@
# Reasoning i18n Audit Report
## Files with Hardcoded English Reasoning Text
### ✅ Already Fixed
1. **services/orchestrator/app/services/dashboard_service.py** - Now returns reasoning_data
2. **services/procurement/app/services/procurement_service.py** - Generates structured reasoning_data
3. **services/production/app/services/production_service.py** - Generates structured reasoning_data
### ❌ Needs Fixing
#### 1. Demo Seed Scripts
**File:** `services/procurement/scripts/demo/seed_demo_purchase_orders.py`
- Line 126: `"Low stock detected for {supplier.name} items..."`
- Line 127: `"Stock-out risk in {days_until_delivery + 2} days..."`
- Line 135: `"Auto-approved based on supplier trust score..."`
**File:** `services/production/scripts/demo/seed_demo_batches.py`
- Similar hardcoded text (needs check)
**Fix:** Use `create_po_reasoning_*()` helper functions
#### 2. Safety Stock Calculator
**File:** `services/procurement/app/services/safety_stock_calculator.py`
- Line 111: `'Lead time or demand std dev is zero or negative'`
- Line 163: `'Insufficient historical demand data (need at least 2 data points)'`
**Fix:** Return structured error codes instead of English text
#### 3. Replenishment Planning Service
**File:** `services/procurement/app/services/replenishment_planning_service.py`
- Line 376: `'Insufficient data for safety stock calculation'`
**Fix:** Return structured error codes
#### 4. ML Services
**File:** `services/procurement/app/ml/price_forecaster.py`
- Needs audit for hardcoded reasoning text
#### 5. Frontend Components
**File:** `frontend/src/components/dashboard/OrchestrationSummaryCard.tsx`
- Hardcoded English text: "Last Night I Planned Your Day", "All caught up!", etc.
**File:** `frontend/src/components/dashboard/HealthStatusCard.tsx`
- Hardcoded English text
**File:** `frontend/src/components/dashboard/ActionQueueCard.tsx`
- Hardcoded English text: "What Needs Your Attention", "Why this is needed:", etc.
**File:** `frontend/src/components/dashboard/ProductionTimelineCard.tsx`
- Hardcoded English text
**File:** `frontend/src/components/dashboard/InsightsGrid.tsx`
- Uses backend labels (good) but needs i18n setup
## Strategy
### Backend
- Return structured error codes: `{"type": "error", "code": "INSUFFICIENT_DATA", "params": {...}}`
- Frontend translates based on code
### Frontend
- Setup `react-i18next`
- Create translation files for EN, ES, CA
- Update all dashboard components to use `t()` function

View File

@@ -0,0 +1,165 @@
/**
* Hook for translating reasoning_data structures
*
* Handles translation of structured backend reasoning data into
* user-friendly, multilingual text for the JTBD dashboard.
*/
import { useTranslation } from 'react-i18next';
export interface ReasoningData {
type: string;
parameters: Record<string, any>;
consequence?: {
type: string;
severity?: string;
impact_days?: number;
[key: string]: any;
};
urgency?: {
level?: string;
[key: string]: any;
};
metadata?: Record<string, any>;
}
export function useReasoningTranslation() {
const { t } = useTranslation('reasoning');
/**
* Translate purchase order reasoning
*/
const translatePOReasonng = (reasoningData: ReasoningData): string => {
if (!reasoningData || !reasoningData.type) {
return t('purchaseOrder.low_stock_detection', {
supplier_name: 'Unknown',
product_names_joined: 'Items',
days_until_stockout: 7
});
}
const { type, parameters } = reasoningData;
// Join product names if array
const params = {
...parameters,
product_names_joined: Array.isArray(parameters.product_names)
? parameters.product_names.join(', ')
: parameters.product_names || 'Items'
};
return t(`purchaseOrder.${type}`, params);
};
/**
* Translate production batch reasoning
*/
const translateBatchReasoning = (reasoningData: ReasoningData): string => {
if (!reasoningData || !reasoningData.type) {
return t('productionBatch.forecast_demand', {
product_name: 'Product',
predicted_demand: 0,
current_stock: 0,
confidence_score: 85
});
}
const { type, parameters } = reasoningData;
return t(`productionBatch.${type}`, parameters);
};
/**
* Translate consequence text
*/
const translateConsequence = (consequenceData?: any): string => {
if (!consequenceData || !consequenceData.type) {
return '';
}
const params = {
...consequenceData,
affected_products_joined: Array.isArray(consequenceData.affected_products)
? consequenceData.affected_products.join(', ')
: consequenceData.affected_products || 'products'
};
return t(`consequence.${consequenceData.type}`, params);
};
/**
* Translate severity level
*/
const translateSeverity = (severity?: string): string => {
if (!severity) return '';
return t(`severity.${severity}`);
};
/**
* Translate trigger source
*/
const translateTrigger = (trigger?: string): string => {
if (!trigger) return '';
return t(`triggers.${trigger}`);
};
/**
* Translate error code
*/
const translateError = (errorCode: string): string => {
return t(`errors.${errorCode}`, { defaultValue: errorCode });
};
return {
translatePOReasonng,
translateBatchReasoning,
translateConsequence,
translateSeverity,
translateTrigger,
translateError,
t, // Expose the raw t function for direct access
};
}
/**
* Format reasoning data for display
* Combines reasoning and consequence into a cohesive message
*/
export function useReasoningFormatter() {
const translation = useReasoningTranslation();
const formatPOAction = (reasoningData?: ReasoningData) => {
if (!reasoningData) {
return {
reasoning: translation.translatePOReasonng({} as ReasoningData),
consequence: '',
severity: ''
};
}
return {
reasoning: translation.translatePOReasonng(reasoningData),
consequence: translation.translateConsequence(reasoningData.consequence),
severity: translation.translateSeverity(reasoningData.consequence?.severity)
};
};
const formatBatchAction = (reasoningData?: ReasoningData) => {
if (!reasoningData) {
return {
reasoning: translation.translateBatchReasoning({} as ReasoningData),
urgency: ''
};
}
return {
reasoning: translation.translateBatchReasoning(reasoningData),
urgency: reasoningData.urgency?.level || 'normal'
};
};
return {
formatPOAction,
formatBatchAction,
...translation
};
}

View File

@@ -0,0 +1,118 @@
{
"purchaseOrder": {
"low_stock_detection": "Low stock for {{supplier_name}}. Current stock of {{product_names_joined}} will run out in {{days_until_stockout}} days.",
"forecast_demand": "Order scheduled based on {{forecast_period_days}}-day demand forecast for {{product_names_joined}} from {{supplier_name}}.",
"safety_stock_replenishment": "Replenishing safety stock for {{product_names_joined}} from {{supplier_name}}.",
"supplier_contract": "Scheduled order per contract with {{supplier_name}}.",
"seasonal_demand": "Seasonal demand preparation for {{product_names_joined}} from {{supplier_name}}.",
"production_requirement": "Required for upcoming production batches from {{supplier_name}}.",
"manual_request": "Manual purchase request for {{product_names_joined}} from {{supplier_name}}."
},
"productionBatch": {
"forecast_demand": "Scheduled based on forecast: {{predicted_demand}} {{product_name}} needed (current stock: {{current_stock}}). Confidence: {{confidence_score}}%.",
"customer_order": "Customer order for {{customer_name}}: {{order_quantity}} {{product_name}} (Order #{{order_number}}) - delivery {{delivery_date}}.",
"stock_replenishment": "Stock replenishment for {{product_name}} - current level below minimum.",
"seasonal_preparation": "Seasonal preparation batch for {{product_name}}.",
"promotion_event": "Production for promotional event - {{product_name}}.",
"urgent_order": "Urgent order requiring immediate production of {{product_name}}.",
"regular_schedule": "Regular scheduled production of {{product_name}}."
},
"consequence": {
"stockout_risk": "Stock-out risk in {{impact_days}} days. Products affected: {{affected_products_joined}}.",
"insufficient_supply": "Insufficient supply for {{impact_days}}-day period.",
"production_delay": "Potential production delay of {{delay_hours}} hours.",
"customer_commitment": "Customer delivery commitment at risk.",
"quality_issue": "Quality standards may be compromised.",
"cost_increase": "Material costs may increase by {{percentage}}%."
},
"severity": {
"critical": "Critical",
"high": "High",
"medium": "Medium",
"low": "Low"
},
"triggers": {
"orchestrator_auto": "Automatic (Orchestrator)",
"manual": "Manual Request",
"customer_order": "Customer Order",
"forecast": "Demand Forecast",
"inventory_alert": "Inventory Alert"
},
"errors": {
"INSUFFICIENT_DATA": "Insufficient historical data for accurate calculation",
"INVALID_PARAMETERS": "Invalid parameters provided",
"LEAD_TIME_INVALID": "Lead time or demand deviation is zero or negative",
"NO_DEMAND_DATA": "No historical demand data available (minimum 2 data points required)"
},
"jtbd": {
"health_status": {
"green": "Everything is running smoothly",
"yellow": "Some items need attention",
"red": "Critical issues require immediate action",
"last_updated": "Last updated",
"next_check": "Next check"
},
"action_queue": {
"title": "What Needs Your Attention",
"why_needed": "Why this is needed:",
"what_if_not": "What happens if I don't do this?",
"estimated_time": "Estimated time: {{minutes}} min",
"all_caught_up": "All caught up!",
"no_actions": "No actions requiring your attention right now.",
"show_more": "Show {{count}} More Action{{plural}}",
"show_less": "Show Less",
"critical_badge": "{{count}} critical",
"important_badge": "{{count}} important"
},
"orchestration_summary": {
"title": "Last Night I Planned Your Day",
"no_runs": "Ready to Plan Your Bakery Day",
"no_runs_message": "The system hasn't run daily planning yet. Click 'Run Daily Planning' to generate your first plan.",
"run_number": "Orchestration run #{{number}}",
"duration": "Took {{seconds}}s",
"pos_created": "Created {{count}} purchase order{{plural}}",
"batches_created": "Scheduled {{count}} production batch{{plural}}",
"no_actions": "No new actions needed - everything is on track!",
"based_on": "Based on:",
"customer_orders": "{{count}} customer order{{plural}}",
"historical_demand": "Historical demand",
"inventory_levels": "Inventory levels",
"ai_optimization": "AI optimization",
"actions_required": "{{count}} item{{plural}} need{{verb}} your approval before proceeding"
},
"production_timeline": {
"title": "Today's Production Timeline",
"no_batches": "No production batches scheduled for today",
"status": {
"pending": "Pending",
"in_progress": "In Progress",
"completed": "Completed",
"cancelled": "Cancelled"
},
"ready_by": "Ready by {{time}}",
"priority": {
"low": "Low Priority",
"normal": "Normal",
"high": "High Priority",
"urgent": "Urgent"
}
},
"insights": {
"savings": "Savings This Week",
"inventory": "Inventory Status",
"waste": "Waste Reduction",
"deliveries": "On-Time Deliveries"
},
"actions": {
"approve": "Approve",
"view_details": "View Details",
"modify": "Modify",
"start_batch": "Start Batch",
"pause_batch": "Pause",
"complete_setup": "Complete Setup",
"dismiss": "Dismiss",
"view_alert": "View Details",
"run_planning": "Run Daily Planning"
}
}
}

View File

@@ -0,0 +1,118 @@
{
"purchaseOrder": {
"low_stock_detection": "Stock bajo para {{supplier_name}}. El stock actual de {{product_names_joined}} se agotará en {{days_until_stockout}} días.",
"forecast_demand": "Pedido programado basado en pronóstico de demanda de {{forecast_period_days}} días para {{product_names_joined}} de {{supplier_name}}.",
"safety_stock_replenishment": "Reposición de stock de seguridad para {{product_names_joined}} de {{supplier_name}}.",
"supplier_contract": "Pedido programado según contrato con {{supplier_name}}.",
"seasonal_demand": "Preparación de demanda estacional para {{product_names_joined}} de {{supplier_name}}.",
"production_requirement": "Requerido para próximos lotes de producción de {{supplier_name}}.",
"manual_request": "Solicitud de compra manual para {{product_names_joined}} de {{supplier_name}}."
},
"productionBatch": {
"forecast_demand": "Programado según pronóstico: {{predicted_demand}} {{product_name}} necesarios (stock actual: {{current_stock}}). Confianza: {{confidence_score}}%.",
"customer_order": "Pedido de cliente para {{customer_name}}: {{order_quantity}} {{product_name}} (Pedido #{{order_number}}) - entrega {{delivery_date}}.",
"stock_replenishment": "Reposición de stock para {{product_name}} - nivel actual por debajo del mínimo.",
"seasonal_preparation": "Lote de preparación estacional para {{product_name}}.",
"promotion_event": "Producción para evento promocional - {{product_name}}.",
"urgent_order": "Pedido urgente que requiere producción inmediata de {{product_name}}.",
"regular_schedule": "Producción programada regular de {{product_name}}."
},
"consequence": {
"stockout_risk": "Riesgo de desabastecimiento en {{impact_days}} días. Productos afectados: {{affected_products_joined}}.",
"insufficient_supply": "Suministro insuficiente para período de {{impact_days}} días.",
"production_delay": "Posible retraso en producción de {{delay_hours}} horas.",
"customer_commitment": "Compromiso de entrega al cliente en riesgo.",
"quality_issue": "Los estándares de calidad pueden verse comprometidos.",
"cost_increase": "Los costos de materiales pueden aumentar un {{percentage}}%."
},
"severity": {
"critical": "Crítico",
"high": "Alto",
"medium": "Medio",
"low": "Bajo"
},
"triggers": {
"orchestrator_auto": "Automático (Orquestador)",
"manual": "Solicitud Manual",
"customer_order": "Pedido de Cliente",
"forecast": "Pronóstico de Demanda",
"inventory_alert": "Alerta de Inventario"
},
"errors": {
"INSUFFICIENT_DATA": "Datos históricos insuficientes para un cálculo preciso",
"INVALID_PARAMETERS": "Parámetros proporcionados no válidos",
"LEAD_TIME_INVALID": "El tiempo de entrega o la desviación de la demanda es cero o negativo",
"NO_DEMAND_DATA": "No hay datos históricos de demanda disponibles (se requieren mínimo 2 puntos de datos)"
},
"jtbd": {
"health_status": {
"green": "Todo funciona correctamente",
"yellow": "Algunos elementos necesitan atención",
"red": "Problemas críticos requieren acción inmediata",
"last_updated": "Última actualización",
"next_check": "Próxima verificación"
},
"action_queue": {
"title": "Qué Necesita Tu Atención",
"why_needed": "Por qué es necesario esto:",
"what_if_not": "¿Qué pasa si no hago esto?",
"estimated_time": "Tiempo estimado: {{minutes}} min",
"all_caught_up": "¡Todo al día!",
"no_actions": "No hay acciones que requieran tu atención en este momento.",
"show_more": "Mostrar {{count}} Acción{{plural}} Más",
"show_less": "Mostrar Menos",
"critical_badge": "{{count}} crítico{{plural}}",
"important_badge": "{{count}} importante{{plural}}"
},
"orchestration_summary": {
"title": "Anoche Planifiqué Tu Día",
"no_runs": "Listo para Planificar Tu Día en la Panadería",
"no_runs_message": "El sistema aún no ha ejecutado la planificación diaria. Haz clic en 'Ejecutar Planificación Diaria' para generar tu primer plan.",
"run_number": "Ejecución de orquestación #{{number}}",
"duration": "Tardó {{seconds}}s",
"pos_created": "Creé {{count}} orden{{plural}} de compra",
"batches_created": "Programé {{count}} lote{{plural}} de producción",
"no_actions": "¡No se necesitan nuevas acciones - todo está en marcha!",
"based_on": "Basado en:",
"customer_orders": "{{count}} pedido{{plural}} de cliente{{plural}}",
"historical_demand": "Demanda histórica",
"inventory_levels": "Niveles de inventario",
"ai_optimization": "Optimización con IA",
"actions_required": "{{count}} elemento{{plural}} necesita{{verb}} tu aprobación antes de proceder"
},
"production_timeline": {
"title": "Línea de Tiempo de Producción de Hoy",
"no_batches": "No hay lotes de producción programados para hoy",
"status": {
"pending": "Pendiente",
"in_progress": "En Proceso",
"completed": "Completado",
"cancelled": "Cancelado"
},
"ready_by": "Listo para {{time}}",
"priority": {
"low": "Prioridad Baja",
"normal": "Normal",
"high": "Prioridad Alta",
"urgent": "Urgente"
}
},
"insights": {
"savings": "Ahorros Esta Semana",
"inventory": "Estado del Inventario",
"waste": "Reducción de Desperdicio",
"deliveries": "Entregas a Tiempo"
},
"actions": {
"approve": "Aprobar",
"view_details": "Ver Detalles",
"modify": "Modificar",
"start_batch": "Iniciar Lote",
"pause_batch": "Pausar",
"complete_setup": "Completar Configuración",
"dismiss": "Descartar",
"view_alert": "Ver Detalles",
"run_planning": "Ejecutar Planificación Diaria"
}
}
}

View File

@@ -0,0 +1,120 @@
{
"purchaseOrder": {
"low_stock_detection": "{{supplier_name}}-rentzat stock baxua. {{product_names_joined}}-ren egungo stocka {{days_until_stockout}} egunetan amaitu
ko da.",
"forecast_demand": "{{supplier_name}}-ren {{product_names_joined}}-rentzat {{forecast_period_days}} eguneko eskaera aurreikuspenean oinarritutako eskaera programatua.",
"safety_stock_replenishment": "{{supplier_name}}-ren {{product_names_joined}}-rentzat segurtasun stockaren birjartzea.",
"supplier_contract": "{{supplier_name}}-rekin kontratuaren arabera programatutako eskaera.",
"seasonal_demand": "{{supplier_name}}-ren {{product_names_joined}}-rentzat denboraldiko eskaeraren prestaketa.",
"production_requirement": "{{supplier_name}}-ren hurrengo ekoizpen loteetarako beharrezkoa.",
"manual_request": "{{supplier_name}}-ren {{product_names_joined}}-rentzat eskuzko erosketa eskaera."
},
"productionBatch": {
"forecast_demand": "Aurreikuspenen arabera programatua: {{predicted_demand}} {{product_name}} behar dira (egungo stocka: {{current_stock}}). Konfiantza: {{confidence_score}}%.",
"customer_order": "{{customer_name}}-rentzat bezeroaren eskaera: {{order_quantity}} {{product_name}} (Eskaera #{{order_number}}) - entrega {{delivery_date}}.",
"stock_replenishment": "{{product_name}}-rentzat stockaren birjartzea - egungo maila minimoa baino txikiagoa.",
"seasonal_preparation": "{{product_name}}-rentzat denboraldiko prestaketa lotea.",
"promotion_event": "Promozio ekitaldirako ekoizpena - {{product_name}}.",
"urgent_order": "{{product_name}}-ren berehalako ekoizpena behar duen eskaera larria.",
"regular_schedule": "{{product_name}}-ren ohiko ekoizpen programatua."
},
"consequence": {
"stockout_risk": "Stock amaitzeko arriskua {{impact_days}} egunetan. Produktu kaltetuak: {{affected_products_joined}}.",
"insufficient_supply": "{{impact_days}} eguneko aldirako hornidura ez nahikoa.",
"production_delay": "{{delay_hours}} orduko ekoizpen atzerapena posiblea.",
"customer_commitment": "Bezeroari entregatzeko konpromisoa arriskuan.",
"quality_issue": "Kalitate estandarrak arriskuan egon daitezke.",
"cost_increase": "Materialen kostuak %{{percentage}} gehitu daitezke."
},
"severity": {
"critical": "Kritikoa",
"high": "Altua",
"medium": "Ertaina",
"low": "Baxua"
},
"triggers": {
"orchestrator_auto": "Automatikoa (Orkestatzailea)",
"manual": "Eskuzko Eskaera",
"customer_order": "Bezeroaren Eskaera",
"forecast": "Eskaeraren Aurreikuspena",
"inventory_alert": "Inbentarioaren Alerta"
},
"errors": {
"INSUFFICIENT_DATA": "Datu historiko ez nahikoa kalkulu zehatzerako",
"INVALID_PARAMETERS": "Emandako parametroak ez baliodunak",
"LEAD_TIME_INVALID": "Entrega denbora edo eskaeraren desbideratzea zero edo negatiboa da",
"NO_DEMAND_DATA": "Ez dago eskaeraren datu historikorik eskuragarri (gutxienez 2 datu puntu behar dira)"
},
"jtbd": {
"health_status": {
"green": "Dena ondo dabil",
"yellow": "Elementu batzuek arreta behar dute",
"red": "Arazo kritikoek ekintza berehalakoa behar dute",
"last_updated": "Azken eguneratzea",
"next_check": "Hurrengo egiaztapena"
},
"action_queue": {
"title": "Zer Behar Du Zure Arreta",
"why_needed": "Zergatik behar da hau:",
"what_if_not": "Zer gertatzen da hau egiten ez badut?",
"estimated_time": "Estimatutako denbora: {{minutes}} min",
"all_caught_up": "Dena egunean!",
"no_actions": "Ez dago une honetan zure arreta behar duen ekintzarik.",
"show_more": "Erakutsi {{count}} Ekintza{{plural}} Gehiago",
"show_less": "Erakutsi Gutxiago",
"critical_badge": "{{count}} kritiko{{plural}}",
"important_badge": "{{count}} garrantzitsu{{plural}}"
},
"orchestration_summary": {
"title": "Bart Gauean Zure Eguna Planifikatu Nuen",
"no_runs": "Zure Okindegiko Eguna Planifikatzeko Prest",
"no_runs_message": "Sistemak oraindik ez du eguneko plangintza exekutatu. Egin klik 'Exekutatu Eguneko Plangintza'-n zure lehen plana sortzeko.",
"run_number": "Orkestazio exekuzioa #{{number}}",
"duration": "{{seconds}}s behar izan zituen",
"pos_created": "{{count}} erosketa agindu{{plural}} sortu nituen",
"batches_created": "{{count}} ekoizpen lote{{plural}} programatu nituen",
"no_actions": "Ez dira ekintza berriak behar - dena bidean dago!",
"based_on": "Oinarrituta:",
"customer_orders": "{{count}} bezero eskaera{{plural}}",
"historical_demand": "Eskaera historikoa",
"inventory_levels": "Inbentario mailak",
"ai_optimization": "IA optimizazioa",
"actions_required": "{{count}} elementu{{plural}}k zure onespena behar du{{verb}} aurrera jarraitu aurretik"
},
"production_timeline": {
"title": "Gaurko Ekoizpen Denbora-lerroa",
"no_batches": "Ez dago ekoizpen loterik programatuta gaurko",
"status": {
"pending": "Zain",
"in_progress": "Prozesuan",
"completed": "Osatua",
"cancelled": "Bertan behera utzita"
},
"ready_by": "{{time}}rako prest",
"priority": {
"low": "Lehentasun Baxua",
"normal": "Normala",
"high": "Lehentasun Altua",
"urgent": "Larria"
}
},
"insights": {
"savings": "Aste Honetako Aurrezkiak",
"inventory": "Inbentarioaren Egoera",
"waste": "Hondakinen Murrizketa",
"deliveries": "Garaiz Entregatutakoak"
},
"actions": {
"approve": "Onetsi",
"view_details": "Ikusi Xehetasunak",
"modify": "Aldatu",
"start_batch": "Hasi Lotea",
"pause_batch": "Pausatu",
"complete_setup": "Osatu Konfigurazioa",
"dismiss": "Baztertu",
"view_alert": "Ikusi Xehetasunak",
"run_planning": "Exekutatu Eguneko Plangintza"
}
}
}