From 623f7b3b565e84e11e59a1ecc880434872d13fab Mon Sep 17 00:00:00 2001 From: dnviti Date: Sat, 6 Dec 2025 02:01:54 +0100 Subject: [PATCH] feat: implement global translation for HR, purchases, and core UI components --- docs/development/ZENTRAL.md | 5 +- ...-06-014000_global_translation_alignment.md | 18 ++ .../2025-12-06-014800_translate_purchases.md | 17 ++ .../2025-12-06-015500_translate_navigation.md | 21 ++ .../2025-12-06-021000_fix_tab_translation.md | 26 ++ .../public/locales/en/translation.json | 280 +++++++++++++----- .../public/locales/it/translation.json | 178 ++++++++++- .../src/apps/hr/pages/AssenzePage.tsx | 14 +- .../src/apps/hr/pages/RimborsiPage.tsx | 8 +- .../components/PurchasesStatsWidget.tsx | 11 +- .../purchases/pages/PurchaseOrderFormPage.tsx | 34 +-- .../apps/purchases/pages/SuppliersPage.tsx | 18 +- .../reportEditor/DatasetManagerDialog.tsx | 76 ++--- .../components/reportEditor/EditorToolbar.tsx | 238 +++++++-------- .../components/reportEditor/PreviewDialog.tsx | 39 +-- src/frontend/src/components/SearchBar.tsx | 57 ++-- src/frontend/src/components/Sidebar.tsx | 67 +++-- src/frontend/src/components/TabsBar.tsx | 25 +- src/frontend/src/contexts/TabContext.tsx | 18 +- 19 files changed, 789 insertions(+), 361 deletions(-) create mode 100644 docs/development/devlog/2025-12-06-014000_global_translation_alignment.md create mode 100644 docs/development/devlog/2025-12-06-014800_translate_purchases.md create mode 100644 docs/development/devlog/2025-12-06-015500_translate_navigation.md create mode 100644 docs/development/devlog/2025-12-06-021000_fix_tab_translation.md diff --git a/docs/development/ZENTRAL.md b/docs/development/ZENTRAL.md index 2a403c0..7a9cdf9 100644 --- a/docs/development/ZENTRAL.md +++ b/docs/development/ZENTRAL.md @@ -42,5 +42,8 @@ File riassuntivo dello stato di sviluppo di Zentral. - Miglioramento UX tab: chiusura con middle-click, drag & drop, gruppi di tab personalizzati. - [2025-12-06 Tab Flicker Fix](./devlog/2025-12-06-011500_tab_flicker_fix.md) - **Completato** - Risolto problema di flicker rimuovendo l'aggiornamento manuale dello stato attivo e affidandosi esclusivamente alla sincronizzazione con l'URL. -- [2025-12-06 Fix Apps Tab Translation](./devlog/2025-12-06-013500_fix_apps_tab_translation.md) - **Completato** +- [2025-12-06 02:10:00 - Fix Traduzione Tab](./devlog/2025-12-06-021000_fix_tab_translation.md) - **Completato** +- [2025-12-06 01:55:00 - Traduzione Menu, Search Bar e Tab](./devlog/2025-12-06-015500_translate_navigation.md) - **Completato** +- [2025-12-06 01:48:00 - Traduzione Modulo Acquisti](./devlog/2025-12-06-014800_translate_purchases.md) - **Completato** +- [2025-12-06 01:35:00 - Fix Traduzione Tab Applicazioni](./devlog/2025-12-06-013500_fix_apps_tab_translation.md) - **Completato** - Corretta chiave di traduzione errata per la tab "Gestione Applicazioni" e migliorata la gestione dell'aggiornamento etichette tab. diff --git a/docs/development/devlog/2025-12-06-014000_global_translation_alignment.md b/docs/development/devlog/2025-12-06-014000_global_translation_alignment.md new file mode 100644 index 0000000..003e1e3 --- /dev/null +++ b/docs/development/devlog/2025-12-06-014000_global_translation_alignment.md @@ -0,0 +1,18 @@ +# Global Translation Alignment + +## Stato +Completato + +## Descrizione +Allineamento completo delle traduzioni in tutto il gestionale. Verifica di stringhe hardcoded, chiavi mancanti e supporto accessibilità. + +## Piano di Lavoro +1. [x] Analisi struttura i18n esistente. +2. [x] Scansione frontend per stringhe hardcoded. +3. [x] Scansione backend per messaggi utente non localizzati. +4. [x] Aggiornamento file di traduzione (IT/EN). +5. [x] Verifica accessibilità (aria-labels, alt text). +6. [x] Test cambio lingua. + +## Log +- Creazione piano di lavoro. diff --git a/docs/development/devlog/2025-12-06-014800_translate_purchases.md b/docs/development/devlog/2025-12-06-014800_translate_purchases.md new file mode 100644 index 0000000..7707c68 --- /dev/null +++ b/docs/development/devlog/2025-12-06-014800_translate_purchases.md @@ -0,0 +1,17 @@ +# Traduzione Modulo Acquisti + +## Obiettivo +Tradurre completamente il modulo acquisti (Purchases) in italiano e inglese, eliminando le stringhe hardcoded. + +## File da analizzare +- `src/frontend/src/apps/purchases/pages/PurchaseOrderFormPage.tsx` +- `src/frontend/src/apps/purchases/pages/PurchaseOrdersPage.tsx` +- `src/frontend/src/apps/purchases/pages/SupplierFormPage.tsx` +- `src/frontend/src/apps/purchases/pages/SuppliersPage.tsx` +- `src/frontend/src/apps/purchases/components/PurchasesStatsWidget.tsx` + +## Piano di lavoro +1. Analizzare i file per identificare le stringhe hardcoded. +2. Aggiungere le chiavi di traduzione in `it/translation.json` e `en/translation.json`. +3. Aggiornare i componenti React per utilizzare `useTranslation`. +4. Verificare la build. diff --git a/docs/development/devlog/2025-12-06-015500_translate_navigation.md b/docs/development/devlog/2025-12-06-015500_translate_navigation.md new file mode 100644 index 0000000..2a4ee87 --- /dev/null +++ b/docs/development/devlog/2025-12-06-015500_translate_navigation.md @@ -0,0 +1,21 @@ +# Traduzione Menu, Search Bar e Tab + +## Obiettivo +Tradurre completamente i componenti di navigazione principale: Sidebar (Menu), Search Bar e TabsBar. + +## File da analizzare +- `src/frontend/src/components/Sidebar.tsx` +- `src/frontend/src/components/SearchBar.tsx` +- `src/frontend/src/components/TabsBar.tsx` + +## Piano di lavoro +1. Analizzare `Sidebar.tsx` per le voci di menu hardcoded. +2. Analizzare `SearchBar.tsx` per placeholder e testi hardcoded. +3. Analizzare `TabsBar.tsx` per i titoli delle tab e menu contestuali. +4. Aggiungere le chiavi mancanti in `it/translation.json` e `en/translation.json`. +5. Aggiornare i componenti per usare `useTranslation`. + +## Stato +- **Completato**: 2025-12-06 02:05:00 +- Aggiunte chiavi di traduzione per menu, navigazione e tab. +- Aggiornati i componenti `Sidebar.tsx`, `SearchBar.tsx` e `TabsBar.tsx`. diff --git a/docs/development/devlog/2025-12-06-021000_fix_tab_translation.md b/docs/development/devlog/2025-12-06-021000_fix_tab_translation.md new file mode 100644 index 0000000..925030c --- /dev/null +++ b/docs/development/devlog/2025-12-06-021000_fix_tab_translation.md @@ -0,0 +1,26 @@ +# Traduzione Tab + +## Problema +Le tab aperte non venivano tradotte dinamicamente al cambio lingua perché il titolo (label) veniva salvato come stringa statica nel `TabContext` (e persistito in localStorage). + +## Soluzione +1. Aggiornato `TabContext.tsx`: + - Aggiunta proprietà opzionale `translationKey` all'interfaccia `Tab`. + - Aggiornata la funzione `openTab` per accettare e salvare `translationKey`. + - Aggiornato il caricamento iniziale (default tab) per includere la chiave di traduzione. + +2. Aggiornato `Sidebar.tsx`: + - Aggiunta proprietà `translationKey` alla struttura del menu. + - Passaggio della chiave di traduzione alla funzione `openTab` al click. + +3. Aggiornato `SearchBar.tsx`: + - Aggiunta proprietà `translationKey` alle opzioni di ricerca. + - Passaggio della chiave di traduzione alla funzione `openTab` alla selezione. + +4. Aggiornato `TabsBar.tsx`: + - Utilizzo di `t(tab.translationKey)` se disponibile, altrimenti fallback su `tab.label`. + - Questo garantisce che le tab cambino lingua istantaneamente quando l'utente cambia lingua. + +## Stato +- **Completato**: 2025-12-06 02:15:00 +- Le tab ora supportano la traduzione dinamica. diff --git a/src/frontend/public/locales/en/translation.json b/src/frontend/public/locales/en/translation.json index 071ffb8..55f5f63 100644 --- a/src/frontend/public/locales/en/translation.json +++ b/src/frontend/public/locales/en/translation.json @@ -51,7 +51,32 @@ "reports": "Reports", "apps": "Apps", "autoCodes": "Auto Codes", - "customFields": "Custom Fields" + "customFields": "Custom Fields", + "suppliers": "Suppliers", + "purchaseOrders": "Purchase Orders", + "salesOrders": "Sales Orders", + "productionOrders": "Production Orders", + "bom": "Bill of Materials", + "workCenters": "Work Centers", + "cycles": "Cycles", + "mrp": "MRP", + "administration": "Administration", + "movements": "Movements", + "stock": "Stock", + "inventory": "Inventory" + }, + "navigation": { + "searchPlaceholder": "Search...", + "tabGroups": "Tab Groups", + "close": "Close", + "closeOthers": "Close Others", + "closeRight": "Close to the Right", + "saveSession": "Save Current Session", + "noSavedGroups": "No saved groups", + "saveGroupTitle": "Save Tab Group", + "groupName": "Group Name", + "save": "Save", + "cancel": "Cancel" }, "dashboard": { "title": "Dashboard", @@ -515,6 +540,135 @@ "saving": "Saving...", "save": "Save" } + }, + "elements": { + "text": "Text", + "textDesc": "Add a text field", + "image": "Image", + "imageDesc": "Insert an image", + "shape": "Shape", + "shapeDesc": "Draw a geometric shape", + "table": "Table", + "tableDesc": "Insert a data table", + "line": "Line", + "lineDesc": "Draw a line", + "add": "Add", + "insert": "Insert element" + }, + "snap": { + "grid": "Grid", + "objects": "Objects", + "borders": "Margins", + "center": "Center", + "tangent": "Edges", + "options": "Snap Options", + "all": "All", + "hideGrid": "Hide grid", + "showGrid": "Show grid", + "autoAlign": "Auto alignment" + }, + "toolbar": { + "undo": "Undo", + "redo": "Redo", + "delete": "Delete", + "preview": "Preview", + "save": "Save", + "lock": "Lock", + "unlock": "Unlock", + "duplicate": "Duplicate", + "prevPage": "Previous Page", + "nextPage": "Next Page", + "zoomIn": "Zoom in", + "zoomOut": "Zoom out", + "autoSaveOn": "Auto-save on", + "autoSaveOff": "Auto-save off", + "saving": "Saving...", + "saved": "Saved", + "unsaved": "Unsaved", + "unsavedTooltip": "Unsaved changes", + "autoSavePending": "Auto-save pending...", + "edit": "EDIT", + "history": "HISTORY", + "historyTooltip": "Change history", + "view": "VIEW", + "zoom": "ZOOM", + "fitWindow": "Fit to window", + "zoomLevel": "Zoom level", + "presets": "Presets", + "searchCommand": "Search command", + "shortcuts": "Keyboard shortcuts", + "shortcutsTitle": "Keyboard Shortcuts" + }, + "preview": { + "title": "Report Preview", + "notSelected": "Not selected", + "removeSelection": "Remove selection", + "select": "Select", + "searchPlaceholder": "Search...", + "noResults": "No results found", + "noEntities": "No entities available", + "results": "results", + "selected": "selected", + "instruction": "Select an entity for each dataset to use in the preview", + "errorLoading": "Error loading available data", + "noDatasets": "There are no datasets selected for this template. Add at least one dataset to generate the preview.", + "selectEntityInstruction": "Select an entity for each dataset", + "cancel": "Cancel", + "generating": "Generating...", + "generatePdf": "Generate PDF", + "generatePreviewPdf": "Generate PDF Preview" + }, + "datasetManager": { + "title": "Virtual Datasets", + "newDataset": "New Dataset", + "noDatasets": "No Virtual Datasets", + "noDatasetsDesc": "Create virtual datasets to combine and filter data from multiple sources.", + "createFirst": "Create the first dataset", + "editDataset": "Edit Dataset", + "newVirtualDataset": "New Virtual Dataset", + "deleteConfirm": "Delete dataset \"{{name}}\"?", + "validationError": "Validation error", + "errors": "Errors:", + "warnings": "Warnings:", + "validConfig": "Valid configuration", + "tabs": { + "info": "Info", + "sources": "Sources", + "relationships": "Relationships", + "filters": "Filters", + "fields": "Fields" + }, + "fields": { + "nameId": "Identifier Name", + "nameIdHelper": "Unique name used internally (no spaces)", + "displayName": "Display Name", + "description": "Description", + "category": "Category", + "icon": "Icon" + }, + "sources": { + "available": "Available Datasets", + "addInstruction": "Click to add a source", + "inDataset": "Sources in Dataset", + "empty": "Add at least one data source from the left panel", + "alias": "Alias", + "primary": "Primary", + "setPrimary": "Set Primary" + }, + "noDescription": "No description", + "sourcesCount": "sources" + }, + "shortcuts": { + "move1px": "Move (1px)", + "move10px": "Move (10px)", + "toggleGrid": "Toggle grid", + "zoomInOut": "Zoom in/out", + "changePage": "Change page" + }, + "time": { + "now": "Just now", + "minutesAgo": "{{count}}m ago", + "hoursAgo": "{{count}}h ago" } }, "warehouse": { @@ -1072,17 +1226,19 @@ } }, "purchases": { - "menu": { - "suppliers": "Suppliers", - "orders": "Purchase Orders" + "stats": { + "title": "Purchases", + "costsThisMonth": "Costs this month", + "pendingOrders": "{{count}} Pending Orders" }, - "suppliers": { + "supplier": { "title": "Suppliers", "newSupplier": "New Supplier", - "editSupplier": "Edit Supplier", + "createTitle": "New Supplier", + "editTitle": "Edit Supplier", "columns": { "code": "Code", - "name": "Name", + "name": "Business Name", "vatNumber": "VAT Number", "email": "Email", "phone": "Phone", @@ -1090,85 +1246,60 @@ "status": "Status" }, "fields": { - "code": "Code", "name": "Business Name", "vatNumber": "VAT Number", "fiscalCode": "Fiscal Code", - "email": "Email", - "pec": "PEC", - "phone": "Phone", - "website": "Website", "address": "Address", "city": "City", "province": "Province", "zipCode": "ZIP Code", "country": "Country", + "email": "Email", + "pec": "PEC", + "phone": "Phone", + "website": "Website", "paymentTerms": "Payment Terms", - "notes": "Notes", - "isActive": "Active" - }, - "placeholders": { - "search": "Search supplier...", - "generatedAutomatically": "Generated automatically" - }, - "deleteConfirm": "Are you sure you want to delete this supplier?" + "notes": "Notes" + } }, - "orders": { + "order": { "title": "Purchase Orders", "newOrder": "New Order", - "editOrder": "Edit Order", - "columns": { - "orderNumber": "Order Number", - "orderDate": "Date", - "supplier": "Supplier", - "status": "Status", - "total": "Total", - "deliveryDate": "Delivery Date" - }, - "fields": { - "orderNumber": "Order Number", - "orderDate": "Order Date", - "expectedDeliveryDate": "Expected Delivery", - "supplier": "Supplier", - "destinationWarehouse": "Destination Warehouse", - "notes": "Notes", - "article": "Article", - "quantity": "Quantity", - "unitPrice": "Unit Price", - "discount": "Discount %", - "taxRate": "Tax Rate %", - "lineTotal": "Total" - }, + "createTitle": "New Order", + "editTitle": "Edit Order", "status": { "Draft": "Draft", "Confirmed": "Confirmed", + "PartiallyReceived": "Partially Received", "Received": "Received", "Cancelled": "Cancelled" }, + "columns": { + "number": "Number", + "date": "Date", + "supplier": "Supplier", + "status": "Status", + "total": "Total" + }, + "fields": { + "date": "Order Date", + "expectedDate": "Expected Delivery Date", + "supplier": "Supplier", + "warehouse": "Destination Warehouse", + "notes": "Notes" + }, + "lines": { + "article": "Article", + "quantity": "Quantity", + "price": "Unit Price", + "discount": "Discount %", + "tax": "Tax %", + "total": "Total" + }, + "total": "Order Total", "actions": { - "addLine": "Add Line", "confirm": "Confirm Order", - "receive": "Receive Goods", - "view": "View", - "delete": "Delete" - }, - "totals": { - "net": "Net Total", - "tax": "Tax", - "gross": "Gross Total" - }, - "deleteConfirm": "Are you sure you want to delete this order?", - "confirmDialog": { - "title": "Confirm Order", - "content": "Are you sure you want to confirm this order? It will no longer be editable.", - "confirm": "Confirm", - "cancel": "Cancel" - }, - "receiveDialog": { - "title": "Receive Goods", - "content": "Are you sure you want to mark this order as received? This will generate stock movements.", - "confirm": "Receive", - "cancel": "Cancel" + "receive": "Receive Goods" } } }, @@ -1393,6 +1524,21 @@ "rimborsiTitle": "Reimbursement Management", "newRimborso": "New Reimbursement", "editRimborso": "Edit Reimbursement", - "descrizione": "Description" + "descrizione": "Description", + "status": { + "richiesto": "Requested", + "approvato": "Approved", + "rimborsato": "Reimbursed", + "rifiutato": "Rejected", + "richiesta": "Requested", + "approvata": "Approved", + "rifiutata": "Rejected" + }, + "assenza": { + "ferie": "Vacation", + "malattia": "Sick Leave", + "permesso": "Permit", + "altro": "Other" + } } } \ No newline at end of file diff --git a/src/frontend/public/locales/it/translation.json b/src/frontend/public/locales/it/translation.json index 294ba50..0a40c91 100644 --- a/src/frontend/public/locales/it/translation.json +++ b/src/frontend/public/locales/it/translation.json @@ -47,7 +47,32 @@ "reports": "Report", "apps": "Applicazioni", "autoCodes": "Codici Auto", - "customFields": "Campi Personalizzati" + "customFields": "Campi Personalizzati", + "suppliers": "Fornitori", + "purchaseOrders": "Ordini Acquisto", + "salesOrders": "Ordini Vendita", + "productionOrders": "Ordini Produzione", + "bom": "Distinte Base", + "workCenters": "Centri di Lavoro", + "cycles": "Cicli", + "mrp": "MRP", + "administration": "Amministrazione", + "movements": "Movimenti", + "stock": "Giacenze", + "inventory": "Inventario" + }, + "navigation": { + "searchPlaceholder": "Cerca...", + "tabGroups": "Gruppi Schede", + "close": "Chiudi", + "closeOthers": "Chiudi Altre", + "closeRight": "Chiudi a Destra", + "saveSession": "Salva Sessione Corrente", + "noSavedGroups": "Nessun gruppo salvato", + "saveGroupTitle": "Salva Gruppo Schede", + "groupName": "Nome Gruppo", + "save": "Salva", + "cancel": "Annulla" }, "dashboard": { "title": "Dashboard", @@ -591,9 +616,143 @@ "saving": "Salvataggio...", "save": "Salva" } + }, + "elements": { + "text": "Testo", + "textDesc": "Aggiungi un campo di testo", + "image": "Immagine", + "imageDesc": "Inserisci un'immagine", + "shape": "Forma", + "shapeDesc": "Disegna una forma geometrica", + "table": "Tabella", + "tableDesc": "Inserisci una tabella dati", + "line": "Linea", + "lineDesc": "Traccia una linea", + "add": "Aggiungi", + "insert": "Inserisci elemento" + }, + "snap": { + "grid": "Griglia", + "objects": "Oggetti", + "borders": "Margini", + "center": "Centro", + "tangent": "Bordi", + "options": "Opzioni Snap", + "all": "Tutti", + "hideGrid": "Nascondi griglia", + "showGrid": "Mostra griglia", + "autoAlign": "Allineamento automatico" + }, + "toolbar": { + "undo": "Annulla", + "redo": "Ripeti", + "delete": "Elimina", + "preview": "Anteprima", + "save": "Salva", + "lock": "Blocca", + "unlock": "Sblocca", + "duplicate": "Duplica", + "prevPage": "Pagina precedente", + "nextPage": "Pagina successiva", + "zoomIn": "Zoom in", + "zoomOut": "Zoom out", + "autoSaveOn": "Auto-salvataggio attivo", + "autoSaveOff": "Auto-salvataggio disattivato", + "saving": "Salvataggio in corso...", + "saved": "Salvato", + "unsaved": "Non salvato", + "unsavedTooltip": "Modifiche non salvate", + "autoSavePending": "Salvataggio automatico in attesa...", + "edit": "MODIFICA", + "history": "CRONOLOGIA", + "historyTooltip": "Cronologia modifiche", + "view": "VISTA", + "zoom": "ZOOM", + "fitWindow": "Adatta alla finestra", + "zoomLevel": "Livello zoom", + "presets": "Preset", + "searchCommand": "Cerca comando", + "shortcuts": "Scorciatoie tastiera", + "shortcutsTitle": "Scorciatoie Tastiera" + }, + "preview": { + "title": "Anteprima Report", + "notSelected": "Non selezionato", + "removeSelection": "Rimuovi selezione", + "select": "Seleziona", + "searchPlaceholder": "Cerca...", + "noResults": "Nessun risultato trovato", + "noEntities": "Nessuna entità disponibile", + "results": "risultati", + "selected": "selezionati", + "instruction": "Seleziona un'entità per ogni dataset da utilizzare nell'anteprima", + "errorLoading": "Errore nel caricamento dei dati disponibili", + "noDatasets": "Non ci sono dataset selezionati per questo template. Aggiungi almeno un dataset per poter generare l'anteprima.", + "selectEntityInstruction": "Seleziona un'entità per ogni dataset", + "cancel": "Annulla", + "generating": "Generazione...", + "generatePdf": "Genera PDF", + "generatePreviewPdf": "Genera Anteprima PDF" + }, + "datasetManager": { + "title": "Dataset Virtuali", + "newDataset": "Nuovo Dataset", + "noDatasets": "Nessun Dataset Virtuale", + "noDatasetsDesc": "Crea dataset virtuali per combinare e filtrare i dati da più sorgenti.", + "createFirst": "Crea il primo dataset", + "editDataset": "Modifica Dataset", + "newVirtualDataset": "Nuovo Dataset Virtuale", + "deleteConfirm": "Eliminare il dataset \"{{name}}\"?", + "validationError": "Errore durante la validazione", + "errors": "Errori:", + "warnings": "Avvisi:", + "validConfig": "Configurazione valida", + "tabs": { + "info": "Info", + "sources": "Sorgenti", + "relationships": "Relazioni", + "filters": "Filtri", + "fields": "Campi" + }, + "fields": { + "nameId": "Nome Identificativo", + "nameIdHelper": "Nome univoco usato internamente (senza spazi)", + "displayName": "Nome Visualizzato", + "description": "Descrizione", + "category": "Categoria", + "icon": "Icona" + }, + "sources": { + "available": "Dataset Disponibili", + "addInstruction": "Clicca per aggiungere una sorgente", + "inDataset": "Sorgenti nel Dataset", + "empty": "Aggiungi almeno una sorgente dati dal pannello a sinistra", + "alias": "Alias", + "primary": "Primario", + "setPrimary": "Imposta Primario" + }, + "noDescription": "Nessuna descrizione", + "sourcesCount": "sorgenti" + }, + "shortcuts": { + "move1px": "Sposta (1px)", + "move10px": "Sposta (10px)", + "toggleGrid": "Mostra/nascondi griglia", + "zoomInOut": "Zoom in/out", + "changePage": "Cambia pagina" + }, + "time": { + "now": "Ora", + "minutesAgo": "{{count}}m fa", + "hoursAgo": "{{count}}h fa" } }, "purchases": { + "stats": { + "title": "Acquisti", + "costsThisMonth": "Costi questo mese", + "pendingOrders": "{{count}} Ordini in attesa" + }, "supplier": { "title": "Fornitori", "newSupplier": "Nuovo Fornitore", @@ -1446,6 +1605,21 @@ "rimborsiTitle": "Gestione Rimborsi", "newRimborso": "Nuovo Rimborso", "editRimborso": "Modifica Rimborso", - "descrizione": "Descrizione" + "descrizione": "Descrizione", + "status": { + "richiesto": "Richiesto", + "approvato": "Approvato", + "rimborsato": "Rimborsato", + "rifiutato": "Rifiutato", + "richiesta": "Richiesta", + "approvata": "Approvata", + "rifiutata": "Rifiutata" + }, + "assenza": { + "ferie": "Ferie", + "malattia": "Malattia", + "permesso": "Permesso", + "altro": "Altro" + } } } \ No newline at end of file diff --git a/src/frontend/src/apps/hr/pages/AssenzePage.tsx b/src/frontend/src/apps/hr/pages/AssenzePage.tsx index cddf02e..6b7ba48 100644 --- a/src/frontend/src/apps/hr/pages/AssenzePage.tsx +++ b/src/frontend/src/apps/hr/pages/AssenzePage.tsx @@ -221,10 +221,10 @@ export default function AssenzePage() { onChange={(e) => setFormData({ ...formData, tipoAssenza: e.target.value })} required > - Ferie - Malattia - Permesso - Altro + {t('personale.assenza.ferie')} + {t('personale.assenza.malattia')} + {t('personale.assenza.permesso')} + {t('personale.assenza.altro')} @@ -236,9 +236,9 @@ export default function AssenzePage() { onChange={(e) => setFormData({ ...formData, stato: e.target.value })} required > - Richiesta - Approvata - Rifiutata + {t('personale.status.richiesta')} + {t('personale.status.approvata')} + {t('personale.status.rifiutata')} diff --git a/src/frontend/src/apps/hr/pages/RimborsiPage.tsx b/src/frontend/src/apps/hr/pages/RimborsiPage.tsx index 0b6b81b..7206e8d 100644 --- a/src/frontend/src/apps/hr/pages/RimborsiPage.tsx +++ b/src/frontend/src/apps/hr/pages/RimborsiPage.tsx @@ -243,10 +243,10 @@ export default function RimborsiPage() { onChange={(e) => setFormData({ ...formData, stato: e.target.value })} required > - Richiesto - Approvato - Rimborsato - Rifiutato + {t('personale.status.richiesto')} + {t('personale.status.approvato')} + {t('personale.status.rimborsato')} + {t('personale.status.rifiutato')} diff --git a/src/frontend/src/apps/purchases/components/PurchasesStatsWidget.tsx b/src/frontend/src/apps/purchases/components/PurchasesStatsWidget.tsx index b087773..6bdfa9c 100644 --- a/src/frontend/src/apps/purchases/components/PurchasesStatsWidget.tsx +++ b/src/frontend/src/apps/purchases/components/PurchasesStatsWidget.tsx @@ -1,19 +1,24 @@ import { Card, CardContent, Typography, Box } from '@mui/material'; import { ShoppingCart as PurchaseIcon } from '@mui/icons-material'; +import { useTranslation } from 'react-i18next'; export default function PurchasesStatsWidget() { + const { t } = useTranslation(); + return ( - Purchases + {t('purchases.stats.title')} € 8,320 - Costs this month + {t('purchases.stats.costsThisMonth')} - Pending Orders: 3 + + {t('purchases.stats.pendingOrders', { count: 3 })} + diff --git a/src/frontend/src/apps/purchases/pages/PurchaseOrderFormPage.tsx b/src/frontend/src/apps/purchases/pages/PurchaseOrderFormPage.tsx index 870c13e..7953b10 100644 --- a/src/frontend/src/apps/purchases/pages/PurchaseOrderFormPage.tsx +++ b/src/frontend/src/apps/purchases/pages/PurchaseOrderFormPage.tsx @@ -184,11 +184,11 @@ export default function PurchaseOrderFormPage() { - {isEdit ? `${t("purchases.orders.editOrder")} ${order?.orderNumber}` : t("purchases.orders.newOrder")} + {isEdit ? `${t("purchases.order.editTitle")} ${order?.orderNumber}` : t("purchases.order.newOrder")} {isEdit && order && ( confirmMutation.mutate(Number(id))} disabled={confirmMutation.isPending} > - {t("purchases.orders.actions.confirm")} + {t("purchases.order.actions.confirm")} )} @@ -218,7 +218,7 @@ export default function PurchaseOrderFormPage() { onClick={() => receiveMutation.mutate(Number(id))} disabled={receiveMutation.isPending} > - {t("purchases.orders.actions.receive")} + {t("purchases.order.actions.receive")} )} @@ -249,7 +249,7 @@ export default function PurchaseOrderFormPage() { control={control} render={({ field }: { field: any }) => ( field.onChange(date?.toISOString())} disabled={isReadOnly} @@ -264,7 +264,7 @@ export default function PurchaseOrderFormPage() { control={control} render={({ field }: { field: any }) => ( field.onChange(date?.toISOString())} disabled={isReadOnly} @@ -288,7 +288,7 @@ export default function PurchaseOrderFormPage() { renderInput={(params) => ( @@ -311,7 +311,7 @@ export default function PurchaseOrderFormPage() { renderInput={(params) => ( )} /> @@ -325,7 +325,7 @@ export default function PurchaseOrderFormPage() { render={({ field }: { field: any }) => ( @@ -337,7 +337,7 @@ export default function PurchaseOrderFormPage() { - {t("purchases.orders.fields.lineTotal")} + {t("purchases.order.lines.total")} {!isReadOnly && (