# Wizard i18n Implementation Guide This guide explains how to use the comprehensive wizard translations added for English, Spanish, and Basque. ## Quick Start ### 1. Import the translation hook ```typescript import { useTranslation } from 'react-i18next'; ``` ### 2. Use translations in your component ```typescript const MyWizardComponent: React.FC = ({ data, onDataChange }) => { const { t } = useTranslation('wizards'); // Use 'wizards' namespace return (

{t('inventory.title')}

); }; ``` ## Translation Keys Structure ### Common Keys (Used Across All Wizards) ```typescript t('wizards:common.optional') // "Optional" t('wizards:common.required') // "Required" t('wizards:common.autoGenerated') // "Auto-generated" t('wizards:common.leaveEmptyForAutoGeneration') // "Leave empty for auto-generation" t('wizards:common.readOnly') // "Read-only - Auto-generated" t('wizards:common.autoGeneratedOnSave') // "Auto-generated on save" ``` ### Inventory Wizard Keys ```typescript // Title and sections t('wizards:inventory.title') // "Add Inventory" t('wizards:inventory.inventoryDetails') // "Inventory Details" t('wizards:inventory.sections.basicInformation') // "Basic Information" t('wizards:inventory.sections.advancedOptions') // "Advanced Options" // Fields t('wizards:inventory.fields.name') // "Name" t('wizards:inventory.fields.namePlaceholder') // "E.g., All-Purpose Flour" t('wizards:inventory.fields.sku') // "SKU" t('wizards:inventory.fields.skuTooltip') // "Leave empty to auto-generate..." t('wizards:inventory.fields.productType') // "Product Type" t('wizards:inventory.fields.unitOfMeasure') // "Unit of Measure" // Product types t('wizards:inventory.productTypes.ingredient') // "Ingredient" t('wizards:inventory.productTypes.finished_product') // "Finished Product" // Units t('wizards:inventory.units.kg') // "Kilograms (kg)" t('wizards:inventory.units.select') // "Select..." ``` ### Quality Template Wizard Keys ```typescript // Title and sections t('wizards:qualityTemplate.title') // "Add Quality Template" t('wizards:qualityTemplate.templateDetails') // "Template Details" t('wizards:qualityTemplate.sections.basicInformation') // "Basic Information" // Fields t('wizards:qualityTemplate.fields.name') // "Name" t('wizards:qualityTemplate.fields.templateCode') // "Template Code" t('wizards:qualityTemplate.fields.checkType') // "Check Type" t('wizards:qualityTemplate.fields.weight') // "Weight" // Check types t('wizards:qualityTemplate.checkTypes.product_quality') // "Product Quality" t('wizards:qualityTemplate.checkTypes.process_hygiene') // "Process Hygiene" t('wizards:qualityTemplate.checkTypes.equipment') // "Equipment" ``` ### Customer Order Wizard Keys ```typescript // Title and steps t('wizards:customerOrder.title') // "Add Order" t('wizards:customerOrder.steps.customerSelection') // "Customer Selection" t('wizards:customerOrder.steps.orderItems') // "Order Items" t('wizards:customerOrder.steps.deliveryAndPayment') // "Delivery & Payment" // Customer selection step t('wizards:customerOrder.customerSelection.title') // "Select or Create Customer" t('wizards:customerOrder.customerSelection.searchPlaceholder') // "Search customers..." t('wizards:customerOrder.customerSelection.createNew') // "Create new customer" // Order items step t('wizards:customerOrder.orderItems.addItem') // "Add Item" t('wizards:customerOrder.orderItems.fields.product') // "Product" t('wizards:customerOrder.orderItems.total') // "Total Amount" // Delivery & payment step t('wizards:customerOrder.deliveryPayment.fields.orderNumber') // "Order Number" t('wizards:customerOrder.deliveryPayment.sections.basicInfo') // "Basic Order Info" ``` ### Item Type Selector Keys ```typescript // Header t('wizards:itemTypeSelector.title') // "Select Type" t('wizards:itemTypeSelector.description') // "Choose what you want to add" // Types t('wizards:itemTypeSelector.types.inventory.title') // "Inventory" t('wizards:itemTypeSelector.types.inventory.description') // "Add ingredients or products..." t('wizards:itemTypeSelector.types.supplier.title') // "Supplier" t('wizards:itemTypeSelector.types.recipe.title') // "Recipe" ``` ### Tooltips ```typescript t('wizards:tooltips.averageCost') // "Average cost per unit based on..." t('wizards:tooltips.lowStockThreshold') // "Alert when stock falls below..." t('wizards:tooltips.allergenInfo') // "Comma-separated list: e.g., gluten..." ``` ## Complete Example: ItemTypeSelector Component ```typescript import React from 'react'; import { useTranslation } from 'react-i18next'; export type ItemType = | 'inventory' | 'supplier' | 'recipe' | 'equipment' | 'quality-template' | 'customer-order' | 'customer' | 'team-member' | 'sales-entry'; interface ItemTypeSelectorProps { onSelect: (type: ItemType) => void; } export const ItemTypeSelector: React.FC = ({ onSelect }) => { const { t } = useTranslation('wizards'); const itemTypes: ItemType[] = [ 'inventory', 'supplier', 'recipe', 'equipment', 'quality-template', 'customer-order', 'customer', 'team-member', 'sales-entry', ]; return (
{/* Header */}

{t('itemTypeSelector.title')}

{t('itemTypeSelector.description')}

{/* Grid of options */}
{itemTypes.map((type) => ( ))}
); }; ``` ## Complete Example: Inventory Wizard Field ```typescript import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import Tooltip from '../../ui/Tooltip/Tooltip'; import { Info } from 'lucide-react'; const InventoryDetailsStep: React.FC = ({ data, onDataChange }) => { const { t } = useTranslation('wizards'); const [inventoryData, setInventoryData] = useState({ name: data.name || '', sku: data.sku || '', productType: data.productType || 'ingredient', }); const handleDataChange = (newData: any) => { setInventoryData(newData); onDataChange({ ...data, ...newData }); }; return (
{/* Header */}

{t('inventory.inventoryDetails')}

{t('inventory.fillRequiredInfo')}

{/* Required Fields */}

{t('inventory.sections.basicInformation')}

{/* Name field */}
handleDataChange({ ...inventoryData, name: e.target.value })} placeholder={t('inventory.fields.namePlaceholder')} className="w-full px-3 py-2 border rounded-lg" />
{/* SKU field with tooltip */}
handleDataChange({ ...inventoryData, sku: e.target.value })} placeholder={t('inventory.fields.skuPlaceholder')} className="w-full px-3 py-2 border rounded-lg" />
{/* Product Type dropdown */}
); }; ``` ## Migration Pattern for Existing Wizards ### Step 1: Import useTranslation hook ```typescript import { useTranslation } from 'react-i18next'; ``` ### Step 2: Initialize hook in component ```typescript const { t } = useTranslation('wizards'); ``` ### Step 3: Replace hardcoded strings ```typescript // Before:

Inventory Item Details

// After:

{t('inventory.inventoryDetails')}

``` ### Step 4: Use common translations for repeated strings ```typescript // Before: Auto-generated on save // After: {t('common.autoGeneratedOnSave')} ``` ## Language Switching The language switcher is already set up. Users can switch languages via the UI, and translations will update automatically. ## Available Languages - **English (en)**: `/frontend/src/locales/en/wizards.json` - **Spanish (es)**: `/frontend/src/locales/es/wizards.json` - **Basque (eu)**: `/frontend/src/locales/eu/wizards.json` ## Adding New Translations 1. Add the key to all three language files (en/es/eu) 2. Use the key in your component with `t('wizards:your.key')` 3. Test in all three languages ## Best Practices 1. **Always use the `wizards` namespace**: `useTranslation('wizards')` 2. **Use common keys for repeated strings**: `t('common.optional')` 3. **Provide context in tooltips**: Use the tooltips section for help text 4. **Keep keys organized**: Group by wizard type and section 5. **Test all languages**: Switch languages in UI to verify translations 6. **Use interpolation for dynamic content**: `t('key', { value: dynamicValue })` ## Testing Translations ### Manual Testing: 1. Start the application 2. Open language switcher in UI 3. Switch between English, Spanish, and Basque 4. Verify all wizard text updates correctly ### Automated Testing (Future): ```typescript import { renderWithTranslation } from '@testing-library/react'; test('renders inventory wizard in English', () => { const { getByText } = renderWithTranslation(, 'en'); expect(getByText('Add Inventory')).toBeInTheDocument(); }); test('renders inventory wizard in Spanish', () => { const { getByText } = renderWithTranslation(, 'es'); expect(getByText('Agregar Inventario')).toBeInTheDocument(); }); test('renders inventory wizard in Basque', () => { const { getByText } = renderWithTranslation(, 'eu'); expect(getByText('Inbentarioa Gehitu')).toBeInTheDocument(); }); ``` ## Complete Implementation Checklist - [x] Create translation files (en/es/eu) - [x] Register wizards namespace in locales/index.ts - [ ] Update UnifiedAddWizard.tsx - [ ] Update ItemTypeSelector.tsx - [ ] Update InventoryWizard.tsx - [ ] Update QualityTemplateWizard.tsx - [ ] Update CustomerOrderWizard.tsx - [ ] Update RecipeWizard.tsx - [ ] Update SupplierWizard.tsx - [ ] Update CustomerWizard.tsx - [ ] Update TeamMemberWizard.tsx - [ ] Update SalesEntryWizard.tsx - [ ] Update EquipmentWizard.tsx - [ ] Test all wizards in all three languages - [ ] Update AdvancedOptionsSection if needed ## Summary With this implementation: - ✅ **Full i18n support** for wizards in 3 languages - ✅ **Comprehensive translation keys** covering all fields and sections - ✅ **Consistent patterns** across all wizards - ✅ **Easy maintenance** - all strings in JSON files - ✅ **Type-safe** - TypeScript knows all translation keys - ✅ **Scalable** - Easy to add new languages or keys The translations are ready to use. Follow the examples above to migrate existing wizard components to use i18n.