Browse Source

Merge pull request #627 from aneopsy/fix-i8n

Sync i18n locales: add 655 translated keys, remove 127 stale keys
MartinNYHC 2 months ago
parent
commit
5f8f5aae30

+ 77 - 21
frontend/src/i18n/locales/fr.ts

@@ -453,7 +453,7 @@ export default {
       firmwareVersion: 'Firmware',
       firmwareVersion: 'Firmware',
       save: 'Enregistrer',
       save: 'Enregistrer',
       clear: 'Effacer',
       clear: 'Effacer',
-      noEditPermission: "Vous n'avez pas la permission de renommer les unités AMS",
+      noEditPermission: 'Vous n\'avez pas la permission de renommer les unités AMS',
     },
     },
     // Firmware modal
     // Firmware modal
     firmwareModal: {
     firmwareModal: {
@@ -551,6 +551,10 @@ export default {
       noMatchingTimelapse: 'Pas de timelapse correspondant',
       noMatchingTimelapse: 'Pas de timelapse correspondant',
       failedScanTimelapse: 'Échec scan timelapse',
       failedScanTimelapse: 'Échec scan timelapse',
       failedAttachTimelapse: 'Échec attache timelapse',
       failedAttachTimelapse: 'Échec attache timelapse',
+      timelapseRemoved: 'Timelapse supprimé',
+      failedRemoveTimelapse: 'Échec de la suppression du timelapse',
+      timelapseUploaded: 'Timelapse importé : {{filename}}',
+      failedUploadTimelapse: 'Échec de l\'importation du timelapse',
       archiveDeleted: 'Archive supprimée',
       archiveDeleted: 'Archive supprimée',
       failedDeleteArchive: 'Échec suppression',
       failedDeleteArchive: 'Échec suppression',
       addedToFavorites: 'Ajouté aux favoris',
       addedToFavorites: 'Ajouté aux favoris',
@@ -576,6 +580,8 @@ export default {
       preview3d: 'Aperçu 3D',
       preview3d: 'Aperçu 3D',
       viewTimelapse: 'Voir le Timelapse',
       viewTimelapse: 'Voir le Timelapse',
       scanForTimelapse: 'Scanner pour Timelapse',
       scanForTimelapse: 'Scanner pour Timelapse',
+      uploadTimelapse: 'Importer un timelapse',
+      removeTimelapse: 'Supprimer le timelapse',
       downloadSource3mf: 'Télécharger Source 3MF',
       downloadSource3mf: 'Télécharger Source 3MF',
       uploadSource3mf: 'Téléverser Source 3MF',
       uploadSource3mf: 'Téléverser Source 3MF',
       replaceSource3mf: 'Remplacer Source 3MF',
       replaceSource3mf: 'Remplacer Source 3MF',
@@ -672,6 +678,8 @@ export default {
       removeButton: 'Retirer',
       removeButton: 'Retirer',
       removeF3d: 'Retirer F3D',
       removeF3d: 'Retirer F3D',
       removeF3dConfirm: 'Retirer le fichier Fusion 360 de "{{name}}" ?',
       removeF3dConfirm: 'Retirer le fichier Fusion 360 de "{{name}}" ?',
+      removeTimelapse: 'Supprimer le timelapse',
+      removeTimelapseConfirm: 'Êtes-vous sûr de vouloir supprimer la vidéo timelapse de "{{name}}" ?',
       timelapse: '{{name}} - Timelapse',
       timelapse: '{{name}} - Timelapse',
       selectTimelapse: 'Choisir un Timelapse',
       selectTimelapse: 'Choisir un Timelapse',
       selectTimelapseDesc: 'Sélectionnez manuellement le timelapse :',
       selectTimelapseDesc: 'Sélectionnez manuellement le timelapse :',
@@ -1035,7 +1043,7 @@ export default {
     avgTime: 'Moy. temps',
     avgTime: 'Moy. temps',
     filamentByPrints: 'Impressions',
     filamentByPrints: 'Impressions',
     timeframe: {
     timeframe: {
-      'today': 'Aujourd\'hui',
+      today: 'Aujourd\'hui',
       'this-week': 'Cette semaine',
       'this-week': 'Cette semaine',
       'this-month': 'Ce mois',
       'this-month': 'Ce mois',
       'last-7': '7 derniers jours',
       'last-7': '7 derniers jours',
@@ -1043,7 +1051,7 @@ export default {
       'last-90': '90 derniers jours',
       'last-90': '90 derniers jours',
       'this-year': 'Cette année',
       'this-year': 'Cette année',
       'all-time': 'Tout',
       'all-time': 'Tout',
-      'custom': 'Personnalisé',
+      custom: 'Personnalisé',
       from: 'Du',
       from: 'Du',
       to: 'Au',
       to: 'Au',
     },
     },
@@ -1095,6 +1103,7 @@ export default {
     maintenanceTypes: 'Types de maintenance',
     maintenanceTypes: 'Types de maintenance',
     maintenanceTypesDescription: 'Types système et tâches personnalisées',
     maintenanceTypesDescription: 'Types système et tâches personnalisées',
     addCustomType: 'Ajouter un type',
     addCustomType: 'Ajouter un type',
+    restoreDefaults: 'Restaurer les tâches par défaut',
     intervalType: 'Type d\'intervalle',
     intervalType: 'Type d\'intervalle',
     intervalValue: 'Intervalle ({{type}})',
     intervalValue: 'Intervalle ({{type}})',
     icon: 'Icône',
     icon: 'Icône',
@@ -1138,11 +1147,14 @@ export default {
     maintenanceComplete: 'Maintenance marquée comme faite',
     maintenanceComplete: 'Maintenance marquée comme faite',
     typeUpdated: 'Type mis à jour',
     typeUpdated: 'Type mis à jour',
     typeDeleted: 'Type supprimé',
     typeDeleted: 'Type supprimé',
+    defaultsRestored: '{{count}} tâche(s) par défaut restaurée(s)',
     printHoursUpdated: 'Heures mises à jour',
     printHoursUpdated: 'Heures mises à jour',
     printerAssigned: 'Imprimante assignée',
     printerAssigned: 'Imprimante assignée',
     printerRemoved: 'Imprimante retirée',
     printerRemoved: 'Imprimante retirée',
     // Confirmation
     // Confirmation
     deleteTypeConfirm: 'Supprimer "{{name}}" ?',
     deleteTypeConfirm: 'Supprimer "{{name}}" ?',
+    deleteSystemTypeTitle: 'Supprimer la tâche de maintenance par défaut ?',
+    deleteSystemTypeMessage: 'Êtes-vous sûr de vouloir supprimer la tâche de maintenance par défaut "{{name}}" ?',
     // Permissions
     // Permissions
     noPermissionUpdate: 'Pas d\'autorisation de mise à jour',
     noPermissionUpdate: 'Pas d\'autorisation de mise à jour',
     noPermissionPerform: 'Pas d\'autorisation d\'action',
     noPermissionPerform: 'Pas d\'autorisation d\'action',
@@ -1408,7 +1420,7 @@ export default {
     apiKeysDescription: 'Créez des clés pour webhooks et API.',
     apiKeysDescription: 'Créez des clés pour webhooks et API.',
     createKey: 'Créer une clé',
     createKey: 'Créer une clé',
     apiKeyCreated: 'Clé API créée avec succès',
     apiKeyCreated: 'Clé API créée avec succès',
-    apiKeyCopyWarning: "Copiez cette clé maintenant - elle ne sera plus affichée !",
+    apiKeyCopyWarning: 'Copiez cette clé maintenant - elle ne sera plus affichée !',
     useInApiBrowser: 'Utiliser dans l\'explorateur API',
     useInApiBrowser: 'Utiliser dans l\'explorateur API',
     createNewApiKey: 'Nouvelle clé API',
     createNewApiKey: 'Nouvelle clé API',
     keyName: 'Nom de la clé',
     keyName: 'Nom de la clé',
@@ -1773,8 +1785,8 @@ export default {
     loginFailed: 'Échec de connexion',
     loginFailed: 'Échec de connexion',
     enterCredentials: 'Entrez vos identifiants',
     enterCredentials: 'Entrez vos identifiants',
     forgotPasswordTitle: 'Mot de passe oublié',
     forgotPasswordTitle: 'Mot de passe oublié',
-    forgotPasswordMessage: "Contactez votre administrateur pour réinitialiser votre accès.",
-    forgotPasswordEmailMessage: "Entrez votre email pour recevoir un nouveau mot de passe.",
+    forgotPasswordMessage: 'Contactez votre administrateur pour réinitialiser votre accès.',
+    forgotPasswordEmailMessage: 'Entrez votre email pour recevoir un nouveau mot de passe.',
     emailAddress: 'Adresse Email',
     emailAddress: 'Adresse Email',
     emailPlaceholder: 'votre.email@exemple.com',
     emailPlaceholder: 'votre.email@exemple.com',
     cancel: 'Annuler',
     cancel: 'Annuler',
@@ -2736,6 +2748,10 @@ export default {
     table: 'Tableau',
     table: 'Tableau',
     cards: 'Cartes',
     cards: 'Cartes',
     net: 'Net',
     net: 'Net',
+    // Grouping
+    groupSimilar: 'Grouper',
+    groupedSpools: '{{count}} bobines identiques',
+    groupedRows: 'lignes',
     // Column config
     // Column config
     columns: 'Colonnes',
     columns: 'Colonnes',
     configureColumns: 'Configurer Colonnes',
     configureColumns: 'Configurer Colonnes',
@@ -3087,14 +3103,6 @@ export default {
       placeholder: 'Auto (défaut)...',
       placeholder: 'Auto (défaut)...',
       hint: 'Force l\'IP annoncée via SSDP.',
       hint: 'Force l\'IP annoncée via SSDP.',
     },
     },
-    bindIp: {
-      title: 'Interface réseau',
-      placeholder: 'Sélectionner interface...',
-      hint: 'Interface réseau sur laquelle cette imprimante virtuelle écoute. Doit être unique par imprimante.',
-    },
-    proxy: {
-      accessCodeHint: 'En mode proxy, utilisez le code d\'accès de l\'imprimante cible dans le slicer. La connexion est transmise de manière transparente à l\'imprimante réelle.',
-    },
     mode: {
     mode: {
       title: 'Mode',
       title: 'Mode',
       archive: 'Archiver',
       archive: 'Archiver',
@@ -3135,8 +3143,37 @@ export default {
       failedToUpdate: 'Échec mise à jour',
       failedToUpdate: 'Échec mise à jour',
       accessCodeRequired: 'Code d\'accès requis',
       accessCodeRequired: 'Code d\'accès requis',
       targetPrinterRequired: 'Imprimante cible requise',
       targetPrinterRequired: 'Imprimante cible requise',
+      bindIpRequired: 'Veuillez d\'abord définir une adresse IP',
       accessCodeEmpty: 'Le code ne peut pas être vide',
       accessCodeEmpty: 'Le code ne peut pas être vide',
       accessCodeLength: 'Le code doit faire 8 caractères',
       accessCodeLength: 'Le code doit faire 8 caractères',
+      created: 'Imprimante virtuelle créée',
+      failedToCreate: 'Échec de la création de l\'imprimante virtuelle',
+      deleted: 'Imprimante virtuelle supprimée',
+      failedToDelete: 'Échec de la suppression de l\'imprimante virtuelle',
+    },
+    list: {
+      title: 'Imprimantes virtuelles',
+      add: 'Ajouter',
+      addFirst: 'Ajouter une imprimante virtuelle',
+      empty: 'Aucune imprimante virtuelle configurée. Ajoutez-en une pour commencer.',
+    },
+    bindIp: {
+      title: 'Interface réseau',
+      placeholder: 'Sélectionner interface...',
+      hint: 'Interface réseau sur laquelle cette imprimante virtuelle écoute. Doit être unique par imprimante.',
+    },
+    proxy: {
+      accessCodeHint: 'En mode proxy, utilisez le code d\'accès de l\'imprimante cible dans le slicer. La connexion est transmise de manière transparente à l\'imprimante réelle.',
+    },
+    addDialog: {
+      title: 'Ajouter une imprimante virtuelle',
+      name: 'Nom',
+      hint: 'Vous pourrez configurer le code d\'accès, l\'imprimante cible et d\'autres paramètres après la création.',
+      create: 'Créer',
+    },
+    deleteConfirm: {
+      title: 'Supprimer l\'imprimante virtuelle',
+      message: 'Êtes-vous sûr de vouloir supprimer "{{name}}" ? Cela arrêtera tous les services de cette imprimante.',
     },
     },
   },
   },
 
 
@@ -3613,6 +3650,25 @@ export default {
       grossWeight: 'Poids brut',
       grossWeight: 'Poids brut',
       spoolSize: 'Taille bobine',
       spoolSize: 'Taille bobine',
       close: 'Fermer',
       close: 'Fermer',
+      currentSpool: 'Bobine actuelle',
+    },
+    modal: {
+      spoolDetected: 'Bobine détectée',
+      assignToAms: 'Assigner à l\'AMS',
+      syncWeight: 'Synchroniser le poids',
+      weightSynced: 'Synchronisé !',
+      syncing: 'Synchronisation...',
+      newTagDetected: 'Nouveau tag détecté',
+      addToInventory: 'Ajouter à l\'inventaire',
+      assignToAmsTitle: 'Assigner à l\'AMS',
+      selectSlot: 'Sélectionner un emplacement',
+      assign: 'Assigner',
+      assigning: 'Attribution...',
+      assignSuccess: 'Assigné !',
+      assignError: 'Échec de l\'attribution de la bobine. Veuillez réessayer.',
+      noPrinterSelected: 'Sélectionner une imprimante...',
+      noAmsDetected: 'Aucun AMS détecté sur cette imprimante',
+      slot: 'Emplacement',
     },
     },
     weight: {
     weight: {
       noReading: 'Pas de lecture',
       noReading: 'Pas de lecture',
@@ -3741,26 +3797,26 @@ export default {
   bugReport: {
   bugReport: {
     title: 'Signaler un bug',
     title: 'Signaler un bug',
     description: 'Description',
     description: 'Description',
-    descriptionPlaceholder: "Qu'est-ce qui n'a pas fonctionné ? Veuillez décrire le problème...",
+    descriptionPlaceholder: 'Qu\'est-ce qui n\'a pas fonctionné ? Veuillez décrire le problème...',
     email: 'E-mail (optionnel)',
     email: 'E-mail (optionnel)',
     emailPlaceholder: 'votre@email.fr',
     emailPlaceholder: 'votre@email.fr',
-    emailPrivacy: "Si fourni, votre e-mail sera inclus dans une section repliée de l'issue GitHub pour que le mainteneur puisse vous contacter.",
-    screenshot: "Capture d'écran",
+    emailPrivacy: 'Si fourni, votre e-mail sera inclus dans une section repliée de l\'issue GitHub pour que le mainteneur puisse vous contacter.',
+    screenshot: 'Capture d\'écran',
     uploadOrPaste: 'Télécharger, coller ou glisser une image',
     uploadOrPaste: 'Télécharger, coller ou glisser une image',
     dataCollectedSummary: 'Quelles données sont incluses dans le rapport ?',
     dataCollectedSummary: 'Quelles données sont incluses dans le rapport ?',
     dataIncluded: 'Inclus :',
     dataIncluded: 'Inclus :',
-    dataIncludedList: "Version de l'app, OS, architecture, version Python, statistiques de base de données (compteurs uniquement), modèles d'imprimantes, nombre de buses, versions firmware, état de connexion, état des intégrations (Spoolman, MQTT, HA), paramètres non sensibles, nombre d'interfaces réseau, détails Docker, versions des dépendances.",
+    dataIncludedList: 'Version de l\'app, OS, architecture, version Python, statistiques de base de données (compteurs uniquement), modèles d\'imprimantes, nombre de buses, versions firmware, état de connexion, état des intégrations (Spoolman, MQTT, HA), paramètres non sensibles, nombre d\'interfaces réseau, détails Docker, versions des dépendances.',
     dataNeverIncluded: 'Jamais inclus :',
     dataNeverIncluded: 'Jamais inclus :',
-    dataNeverIncludedList: "Noms d'imprimantes, numéros de série, codes d'accès, mots de passe, adresses IP, adresses e-mail, clés API, tokens, URLs de webhook, noms d'hôtes ou noms d'utilisateurs.",
+    dataNeverIncludedList: 'Noms d\'imprimantes, numéros de série, codes d\'accès, mots de passe, adresses IP, adresses e-mail, clés API, tokens, URLs de webhook, noms d\'hôtes ou noms d\'utilisateurs.',
     submit: 'Envoyer',
     submit: 'Envoyer',
     collectingLogs: 'Collecte des journaux de diagnostic...',
     collectingLogs: 'Collecte des journaux de diagnostic...',
     collectingLogsHint: 'Journalisation de débogage activée, interrogation des imprimantes pour des données fraîches.',
     collectingLogsHint: 'Journalisation de débogage activée, interrogation des imprimantes pour des données fraîches.',
     submitting: 'Envoi du rapport de bug...',
     submitting: 'Envoi du rapport de bug...',
     submitSuccess: 'Rapport de bug envoyé avec succès !',
     submitSuccess: 'Rapport de bug envoyé avec succès !',
-    submitFailed: "Échec de l'envoi du rapport de bug",
+    submitFailed: 'Échec de l\'envoi du rapport de bug',
     thankYou: 'Merci !',
     thankYou: 'Merci !',
     submitted: 'Votre rapport de bug a été soumis.',
     submitted: 'Votre rapport de bug a été soumis.',
-    viewIssue: "Voir l'issue",
+    viewIssue: 'Voir l\'issue',
     unexpectedError: 'Une erreur inattendue est survenue',
     unexpectedError: 'Une erreur inattendue est survenue',
     countdownSeconds: '{{seconds}}s',
     countdownSeconds: '{{seconds}}s',
   },
   },

+ 693 - 26
frontend/src/i18n/locales/it.ts

@@ -8,6 +8,7 @@ export default {
     profiles: 'Profili',
     profiles: 'Profili',
     maintenance: 'Manutenzione',
     maintenance: 'Manutenzione',
     projects: 'Progetti',
     projects: 'Progetti',
+    inventory: 'Filamento',
     files: 'File',
     files: 'File',
     settings: 'Impostazioni',
     settings: 'Impostazioni',
     system: 'Sistema',
     system: 'Sistema',
@@ -76,6 +77,8 @@ export default {
     dismiss: 'Chiudi',
     dismiss: 'Chiudi',
     apply: 'Applica',
     apply: 'Applica',
     reset: 'Reimposta',
     reset: 'Reimposta',
+    export: 'Esporta',
+    import: 'Importa',
     clear: 'Pulisci',
     clear: 'Pulisci',
     selectAll: 'Seleziona tutto',
     selectAll: 'Seleziona tutto',
     deselectAll: 'Deseleziona tutto',
     deselectAll: 'Deseleziona tutto',
@@ -231,6 +234,12 @@ export default {
     nozzleRack: 'Rack Ugelli',
     nozzleRack: 'Rack Ugelli',
     nozzleDocked: 'Agganciato',
     nozzleDocked: 'Agganciato',
     nozzleMounted: 'Montato',
     nozzleMounted: 'Montato',
+    nozzleActive: 'Attivo',
+    nozzleIdle: 'Inattivo',
+    nozzleDiameter: 'Diametro',
+    nozzleType: 'Tipo',
+    nozzleStatus: 'Stato',
+    nozzleFilament: 'Filamento',
     nozzleWear: 'Usura',
     nozzleWear: 'Usura',
     nozzleMaxTemp: 'Temp Max',
     nozzleMaxTemp: 'Temp Max',
     nozzleSerial: 'Seriale',
     nozzleSerial: 'Seriale',
@@ -542,6 +551,10 @@ export default {
       noMatchingTimelapse: 'Nessun timelapse corrispondente',
       noMatchingTimelapse: 'Nessun timelapse corrispondente',
       failedScanTimelapse: 'Scansione timelapse non riuscita',
       failedScanTimelapse: 'Scansione timelapse non riuscita',
       failedAttachTimelapse: 'Allegato timelapse non riuscito',
       failedAttachTimelapse: 'Allegato timelapse non riuscito',
+      timelapseRemoved: 'Timelapse rimosso',
+      failedRemoveTimelapse: 'Impossibile rimuovere il timelapse',
+      timelapseUploaded: 'Timelapse caricato: {{filename}}',
+      failedUploadTimelapse: 'Impossibile caricare il timelapse',
       archiveDeleted: 'Archivio eliminato',
       archiveDeleted: 'Archivio eliminato',
       failedDeleteArchive: 'Eliminazione archivio non riuscita',
       failedDeleteArchive: 'Eliminazione archivio non riuscita',
       addedToFavorites: 'Aggiunto ai preferiti',
       addedToFavorites: 'Aggiunto ai preferiti',
@@ -567,6 +580,8 @@ export default {
       preview3d: 'Anteprima 3D',
       preview3d: 'Anteprima 3D',
       viewTimelapse: 'Vedi Timelapse',
       viewTimelapse: 'Vedi Timelapse',
       scanForTimelapse: 'Cerca Timelapse',
       scanForTimelapse: 'Cerca Timelapse',
+      uploadTimelapse: 'Carica timelapse',
+      removeTimelapse: 'Rimuovi timelapse',
       downloadSource3mf: 'Scarica Sorgente 3MF',
       downloadSource3mf: 'Scarica Sorgente 3MF',
       uploadSource3mf: 'Carica Sorgente 3MF',
       uploadSource3mf: 'Carica Sorgente 3MF',
       replaceSource3mf: 'Sostituisci Sorgente 3MF',
       replaceSource3mf: 'Sostituisci Sorgente 3MF',
@@ -663,6 +678,8 @@ export default {
       removeButton: 'Rimuovi',
       removeButton: 'Rimuovi',
       removeF3d: 'Rimuovi F3D',
       removeF3d: 'Rimuovi F3D',
       removeF3dConfirm: 'Sei sicuro di rimuovere il file Fusion 360 da "{{name}}"?',
       removeF3dConfirm: 'Sei sicuro di rimuovere il file Fusion 360 da "{{name}}"?',
+      removeTimelapse: 'Rimuovi timelapse',
+      removeTimelapseConfirm: 'Sei sicuro di voler rimuovere il video timelapse da "{{name}}"?',
       timelapse: '{{name}} - Timelapse',
       timelapse: '{{name}} - Timelapse',
       selectTimelapse: 'Seleziona Timelapse',
       selectTimelapse: 'Seleziona Timelapse',
       selectTimelapseDesc: 'Nessun abbinamento automatico trovato. Seleziona il timelapse per questa stampa:',
       selectTimelapseDesc: 'Nessun abbinamento automatico trovato. Seleziona il timelapse per questa stampa:',
@@ -761,6 +778,10 @@ export default {
     dragToReorder: 'Trascina per riordinare (solo ASAP)',
     dragToReorder: 'Trascina per riordinare (solo ASAP)',
     reorderHint: 'La posizione influisce solo sugli elementi ASAP. Quelli programmati partono all\'orario.',
     reorderHint: 'La posizione influisce solo sugli elementi ASAP. Quelli programmati partono all\'orario.',
     addedBy: 'Aggiunto da {{name}}',
     addedBy: 'Aggiunto da {{name}}',
+    nextInQueue: 'Prossimo in coda',
+    clearPlate: 'Libera piatto e avvia il prossimo',
+    clearPlateSuccess: 'Piatto liberato — pronto per la prossima stampa',
+    plateReady: 'Piatto liberato — pronto per la prossima stampa',
     plateNumber: 'Piatto {{index}}',
     plateNumber: 'Piatto {{index}}',
     // Sections
     // Sections
     sections: {
     sections: {
@@ -1022,7 +1043,7 @@ export default {
     avgTime: 'Media tempo',
     avgTime: 'Media tempo',
     filamentByPrints: 'Stampe',
     filamentByPrints: 'Stampe',
     timeframe: {
     timeframe: {
-      'today': 'Oggi',
+      today: 'Oggi',
       'this-week': 'Questa settimana',
       'this-week': 'Questa settimana',
       'this-month': 'Questo mese',
       'this-month': 'Questo mese',
       'last-7': 'Ultimi 7 giorni',
       'last-7': 'Ultimi 7 giorni',
@@ -1030,7 +1051,7 @@ export default {
       'last-90': 'Ultimi 90 giorni',
       'last-90': 'Ultimi 90 giorni',
       'this-year': 'Quest\'anno',
       'this-year': 'Quest\'anno',
       'all-time': 'Tutto',
       'all-time': 'Tutto',
-      'custom': 'Personalizzato',
+      custom: 'Personalizzato',
       from: 'Da',
       from: 'Da',
       to: 'A',
       to: 'A',
     },
     },
@@ -1162,6 +1183,60 @@ export default {
       virtualPrinter: 'Stampante virtuale',
       virtualPrinter: 'Stampante virtuale',
       users: 'Utenti',
       users: 'Utenti',
       backup: 'Backup',
       backup: 'Backup',
+      emailAuth: 'Autenticazione Email',
+    },
+    // Email settings
+    email: {
+      smtpSettings: 'Configurazione SMTP',
+      smtpHost: 'Server SMTP',
+      smtpPort: 'Porta SMTP',
+      security: 'Sicurezza',
+      authentication: 'Autenticazione',
+      username: 'Nome utente',
+      password: 'Password',
+      fromEmail: 'Email mittente',
+      fromName: 'Nome mittente',
+      testConnection: 'Testa connessione SMTP',
+      testRecipient: 'Email destinatario test',
+      sendTest: 'Invia email di test',
+      sending: 'Invio...',
+      save: 'Salva impostazioni',
+      saving: 'Salvataggio...',
+      advancedAuth: 'Autenticazione avanzata',
+      advancedAuthEnabled: 'L\'autenticazione avanzata è abilitata',
+      advancedAuthEnabledDesc: 'Le funzionalità di gestione utenti via email sono attive. I nuovi utenti riceveranno password generate automaticamente via email e potranno reimpostare la password tramite la funzione di recupero.',
+      advancedAuthDisabled: 'L\'autenticazione avanzata è disabilitata',
+      advancedAuthDisabledDesc: 'Abilita l\'autenticazione avanzata per attivare le funzionalità email per la gestione utenti.',
+      enable: 'Abilita',
+      disable: 'Disabilita',
+      feature1: 'Le password vengono generate automaticamente e inviate via email ai nuovi utenti',
+      feature2: 'Gli utenti possono accedere con nome utente o email',
+      feature3: 'La funzione di recupero password è disponibile',
+      feature4: 'Gli amministratori possono reimpostare le password utente via email',
+      // Error messages
+      errors: {
+        requiredFields: 'Compilare tutti i campi obbligatori',
+        usernameRequired: 'Il nome utente è obbligatorio quando l\'autenticazione è abilitata',
+        enterTestEmail: 'Inserire un indirizzo email di test',
+        smtpServerAndEmail: 'Compilare Server SMTP e Email mittente prima di testare',
+        usernamePasswordRequired: 'Nome utente e password sono obbligatori quando l\'autenticazione è abilitata',
+        configureSmtpFirst: 'Configurare e testare le impostazioni SMTP prima',
+      },
+      // Success messages
+      success: {
+        settingsSaved: 'Impostazioni SMTP salvate con successo',
+      },
+      // Security options
+      securityOptions: {
+        starttls: 'STARTTLS (Porta 587)',
+        ssl: 'SSL/TLS (Porta 465)',
+        none: 'Nessuna (Porta 25)',
+      },
+      // Authentication options
+      authOptions: {
+        enabled: 'Abilitata',
+        disabled: 'Disabilitata',
+      },
     },
     },
     appearance: 'Aspetto',
     appearance: 'Aspetto',
     notifications: 'Notifiche',
     notifications: 'Notifiche',
@@ -1175,7 +1250,7 @@ export default {
     themeDark: 'Scuro',
     themeDark: 'Scuro',
     themeSystem: 'Sistema',
     themeSystem: 'Sistema',
     defaultView: 'Vista predefinita',
     defaultView: 'Vista predefinita',
-    defaultViewDescription: "Pagina da mostrare all'apertura dell'app",
+    defaultViewDescription: 'Pagina da mostrare all\'apertura dell\'app',
     checkForUpdates: 'Controlla aggiornamenti',
     checkForUpdates: 'Controlla aggiornamenti',
     autoUpdate: 'Aggiornamento automatico',
     autoUpdate: 'Aggiornamento automatico',
     currentVersion: 'Versione attuale',
     currentVersion: 'Versione attuale',
@@ -1231,11 +1306,44 @@ export default {
       turnOn: 'Accendi',
       turnOn: 'Accendi',
       turnOff: 'Spegni',
       turnOff: 'Spegni',
     },
     },
-    // Spoolman
-    spoolmanEnabled: 'Abilita integrazione Spoolman',
+    // Filament Tracking Mode
+    filamentTracking: 'Tracciamento filamento',
+    filamentTrackingDesc: 'Scegli come tracciare le bobine di filamento. Puoi usare l\'inventario integrato o collegare un server Spoolman esterno.',
+    trackingModeBuiltIn: 'Inventario integrato',
+    trackingModeBuiltInDesc: 'Riconoscimento RFID automatico e tracciamento dell\'uso inclusi',
+    trackingModeSpoolmanDesc: 'Server esterno per la gestione del filamento',
+    builtInFeatureRfid: 'Rileva automaticamente le bobine Bambu Lab RFID nell\'AMS',
+    builtInFeatureUsage: 'Traccia il consumo di filamento per stampa',
+    builtInFeatureCatalog: 'Gestisci bobine, colori e profili K-factor',
+    builtInFeatureThirdParty: 'Le bobine di terze parti possono essere assegnate alle bobine dell\'inventario',
+    amsSyncButton: 'Sincronizza pesi dall\'AMS',
+    amsSyncTitle: 'Sincronizza pesi bobine dall\'AMS',
+    amsSyncMessage: 'Questo sovrascriverà tutti i pesi delle bobine dell\'inventario con i valori attuali di percentuale rimanente dell\'AMS dalle stampanti connesse. Usa questa funzione per recuperare dati di peso corrotti. Le stampanti devono essere online.',
+    amsSyncing: 'Sincronizzazione...',
+    amsSyncSuccess: '{{synced}} bobina/e sincronizzata/e, {{skipped}} saltata/e',
+    amsSyncError: 'Impossibile sincronizzare i pesi dall\'AMS',
+    // Spoolman settings
     spoolmanUrl: 'URL Spoolman',
     spoolmanUrl: 'URL Spoolman',
+    spoolmanUrlHint: 'URL del server Spoolman (es. http://localhost:7912)',
     spoolmanConnected: 'Connesso',
     spoolmanConnected: 'Connesso',
     spoolmanDisconnected: 'Disconnesso',
     spoolmanDisconnected: 'Disconnesso',
+    status: 'Stato',
+    connect: 'Connetti',
+    disconnect: 'Disconnetti',
+    howSyncWorks: 'Come funziona la sincronizzazione',
+    syncInfoRfidOnly: 'Solo le bobine ufficiali Bambu Lab con RFID vengono sincronizzate',
+    syncInfoAutoCreate: 'Le nuove bobine vengono create automaticamente in Spoolman alla prima sincronizzazione',
+    syncInfoThirdPartySkipped: 'Le bobine non Bambu Lab (terze parti, ricaricate) vengono saltate',
+    linkingExistingSpools: 'Collegamento bobine esistenti',
+    linkingExistingSpoolsDesc: 'Per collegare le bobine Spoolman esistenti all\'AMS, passa il mouse su uno slot AMS e clicca "Collega a Spoolman".',
+    syncMode: 'Modalità sincronizzazione',
+    syncModeAuto: 'Automatica',
+    syncModeManual: 'Solo manuale',
+    syncModeAutoDesc: 'I dati AMS si sincronizzano automaticamente quando vengono rilevate modifiche',
+    syncModeManualDesc: 'Sincronizzazione solo quando attivata manualmente',
+    syncAmsData: 'Sincronizza dati AMS',
+    syncAmsDataDesc: 'Sincronizza manualmente i dati AMS della stampante su Spoolman',
+    allPrinters: 'Tutte le stampanti',
     // Default printer
     // Default printer
     noDefaultPrinter: 'Nessuna predefinita (chiedi ogni volta)',
     noDefaultPrinter: 'Nessuna predefinita (chiedi ogni volta)',
     // Sidebar
     // Sidebar
@@ -1312,7 +1420,7 @@ export default {
     apiKeysDescription: 'Crea chiavi API per integrazioni esterne e webhook.',
     apiKeysDescription: 'Crea chiavi API per integrazioni esterne e webhook.',
     createKey: 'Crea chiave',
     createKey: 'Crea chiave',
     apiKeyCreated: 'Chiave API creata con successo',
     apiKeyCreated: 'Chiave API creata con successo',
-    apiKeyCopyWarning: "Copia questa chiave ora - non verra mostrata di nuovo!",
+    apiKeyCopyWarning: 'Copia questa chiave ora - non verra mostrata di nuovo!',
     useInApiBrowser: 'Usa nel Browser API',
     useInApiBrowser: 'Usa nel Browser API',
     createNewApiKey: 'Crea nuova chiave API',
     createNewApiKey: 'Crea nuova chiave API',
     keyName: 'Nome chiave',
     keyName: 'Nome chiave',
@@ -1329,7 +1437,7 @@ export default {
     control: 'Controllo',
     control: 'Controllo',
     createFirstKey: 'Crea la tua prima chiave',
     createFirstKey: 'Crea la tua prima chiave',
     webhookEndpoints: 'Endpoint webhook',
     webhookEndpoints: 'Endpoint webhook',
-    webhookApiKeyHint: "Usa la tua chiave API nell'header X-API-Key.",
+    webhookApiKeyHint: 'Usa la tua chiave API nell\'header X-API-Key.',
     webhook: {
     webhook: {
       getAllStatus: 'Ottieni stato di tutte le stampanti',
       getAllStatus: 'Ottieni stato di tutte le stampanti',
       getSpecificStatus: 'Ottieni stato di una stampante',
       getSpecificStatus: 'Ottieni stato di una stampante',
@@ -1342,7 +1450,7 @@ export default {
     apiBrowserDescription: 'Esplora e testa tutti gli endpoint API disponibili.',
     apiBrowserDescription: 'Esplora e testa tutti gli endpoint API disponibili.',
     apiKeyForTesting: 'Chiave API per test',
     apiKeyForTesting: 'Chiave API per test',
     apiKeyPlaceholder: 'Incolla qui la tua chiave API per testare gli endpoint autenticati...',
     apiKeyPlaceholder: 'Incolla qui la tua chiave API per testare gli endpoint autenticati...',
-    apiKeyHint: "Questa chiave verra inviata come header X-API-Key.",
+    apiKeyHint: 'Questa chiave verra inviata come header X-API-Key.',
     deleteApiKeyTitle: 'Elimina chiave API',
     deleteApiKeyTitle: 'Elimina chiave API',
     deleteApiKeyMessage: 'Sei sicuro di voler eliminare questa chiave API? Le integrazioni che la usano non funzioneranno più.',
     deleteApiKeyMessage: 'Sei sicuro di voler eliminare questa chiave API? Le integrazioni che la usano non funzioneranno più.',
     deleteKey: 'Elimina chiave',
     deleteKey: 'Elimina chiave',
@@ -1404,7 +1512,7 @@ export default {
     deleteGroup: 'Elimina gruppo',
     deleteGroup: 'Elimina gruppo',
     // Modal: Disable auth
     // Modal: Disable auth
     disableAuthenticationTitle: 'Disabilita autenticazione',
     disableAuthenticationTitle: 'Disabilita autenticazione',
-    disableAuthenticationMessage: "Sei sicuro di voler disabilitare l'autenticazione? Questo renderà la tua istanza Bambuddy accessibile senza login. Tutti gli utenti resteranno nel database ma l'autenticazione sarà disabilitata.",
+    disableAuthenticationMessage: 'Sei sicuro di voler disabilitare l\'autenticazione? Questo renderà la tua istanza Bambuddy accessibile senza login. Tutti gli utenti resteranno nel database ma l\'autenticazione sarà disabilitata.',
     disableAuthentication: 'Disabilita autenticazione',
     disableAuthentication: 'Disabilita autenticazione',
     // Additional settings
     // Additional settings
     configureBambuddy: 'Configura Bambuddy',
     configureBambuddy: 'Configura Bambuddy',
@@ -1475,6 +1583,77 @@ export default {
       cameraConnected: 'Camera connessa{{resolution}}',
       cameraConnected: 'Camera connessa{{resolution}}',
     },
     },
     testConnection: 'Testa connessione',
     testConnection: 'Testa connessione',
+    catalog: {
+      spoolCatalog: 'Catalogo bobine',
+      spoolCatalogDescription: 'Pesi delle bobine vuote per marca/tipo. Utilizzato per la ricerca automatica del peso quando si aggiungono bobine.',
+      searchCatalog: 'Cerca nel catalogo...',
+      addNewEntry: 'Aggiungi nuova voce',
+      namePlaceholder: 'Nome (es. Bambu Lab - Plastica)',
+      weight: 'Peso',
+      type: 'Tipo',
+      default: 'Predefinito',
+      custom: 'Personalizzato',
+      noMatch: 'Nessuna voce corrisponde alla ricerca',
+      empty: 'Nessuna voce nel catalogo',
+      deleteEntry: 'Elimina voce',
+      deleteConfirm: 'Sei sicuro di voler eliminare "{{name}}"?',
+      resetCatalog: 'Ripristina catalogo',
+      resetConfirm: 'Ripristinare il catalogo ai valori predefiniti? Tutte le voci personalizzate verranno rimosse.',
+      loadFailed: 'Impossibile caricare il catalogo bobine',
+      nameWeightRequired: 'Nome e peso sono obbligatori',
+      entryAdded: 'Voce aggiunta',
+      addFailed: 'Impossibile aggiungere la voce',
+      entryUpdated: 'Voce aggiornata',
+      updateFailed: 'Impossibile aggiornare la voce',
+      entryDeleted: 'Voce eliminata',
+      deleteFailed: 'Impossibile eliminare la voce',
+      resetSuccess: 'Catalogo ripristinato ai valori predefiniti',
+      resetFailed: 'Impossibile ripristinare il catalogo',
+      exported: '{{count}} voci esportate',
+      imported: '{{added}} voci importate ({{skipped}} saltate)',
+      importFailed: 'Impossibile importare: formato JSON non valido',
+      exportTooltip: 'Esporta catalogo in JSON',
+      importTooltip: 'Importa catalogo da JSON',
+      resetTooltip: 'Ripristina valori predefiniti',
+    },
+    colorCatalog: {
+      title: 'Catalogo colori',
+      description: 'Colori del filamento per produttore/materiale. Utilizzato per la ricerca automatica del colore quando si aggiungono bobine.',
+      searchColors: 'Cerca colori...',
+      allManufacturers: 'Tutti i produttori',
+      addNewColor: 'Aggiungi nuovo colore',
+      manufacturer: 'Produttore',
+      colorName: 'Nome colore',
+      hex: 'Hex',
+      materialOptional: 'Materiale (opzionale)',
+      showing: 'Visualizzazione di {{filtered}} su {{total}} colori',
+      noMatch: 'Nessun colore corrisponde alla ricerca',
+      empty: 'Nessun colore nel catalogo',
+      deleteColor: 'Elimina colore',
+      deleteConfirm: 'Sei sicuro di voler eliminare "{{name}}"?',
+      resetCatalog: 'Ripristina catalogo colori',
+      resetConfirm: 'Ripristinare il catalogo ai valori predefiniti? Tutti i colori personalizzati verranno rimossi.',
+      sync: 'Sincronizza',
+      starting: 'Avvio...',
+      syncTooltip: 'Sincronizza da FilamentColors.xyz (2000+ colori, potrebbe richiedere un minuto)',
+      loadFailed: 'Impossibile caricare il catalogo colori',
+      fieldsRequired: 'Produttore, nome colore e colore hex sono obbligatori',
+      colorAdded: 'Colore aggiunto',
+      addFailed: 'Impossibile aggiungere il colore',
+      colorUpdated: 'Colore aggiornato',
+      updateFailed: 'Impossibile aggiornare il colore',
+      colorDeleted: 'Colore eliminato',
+      deleteFailed: 'Impossibile eliminare il colore',
+      resetSuccess: 'Catalogo colori ripristinato ai valori predefiniti',
+      resetFailed: 'Impossibile ripristinare il catalogo',
+      syncUpToDate: 'Già aggiornato ({{count}} colori verificati)',
+      syncComplete: '{{added}} nuovi colori aggiunti ({{skipped}} già esistenti)',
+      syncError: 'Errore di sincronizzazione',
+      syncFailed: 'Impossibile sincronizzare da FilamentColors.xyz',
+      exported: '{{count}} colori esportati',
+      imported: '{{added}} colori importati ({{skipped}} saltati)',
+      importFailed: 'Impossibile importare: formato JSON non valido',
+    },
   },
   },
 
 
   // Notifications (for push notifications)
   // Notifications (for push notifications)
@@ -1595,6 +1774,8 @@ export default {
     subtitle: 'Accedi al tuo account',
     subtitle: 'Accedi al tuo account',
     username: 'Nome utente',
     username: 'Nome utente',
     usernamePlaceholder: 'Inserisci il nome utente',
     usernamePlaceholder: 'Inserisci il nome utente',
+    usernameOrEmail: 'Nome utente o email',
+    usernameOrEmailPlaceholder: 'Nome utente o @ Email',
     password: 'Password',
     password: 'Password',
     passwordPlaceholder: 'Inserisci la password',
     passwordPlaceholder: 'Inserisci la password',
     signIn: 'Accedi',
     signIn: 'Accedi',
@@ -1605,6 +1786,12 @@ export default {
     enterCredentials: 'Inserisci nome utente e password',
     enterCredentials: 'Inserisci nome utente e password',
     forgotPasswordTitle: 'Password dimenticata',
     forgotPasswordTitle: 'Password dimenticata',
     forgotPasswordMessage: 'Se hai dimenticato la password, contatta il tuo amministratore di sistema per reimpostarla.',
     forgotPasswordMessage: 'Se hai dimenticato la password, contatta il tuo amministratore di sistema per reimpostarla.',
+    forgotPasswordEmailMessage: 'Inserisci il tuo indirizzo email e ti invieremo una nuova password.',
+    emailAddress: 'Indirizzo email',
+    emailPlaceholder: 'tua.email@esempio.com',
+    cancel: 'Annulla',
+    sending: 'Invio...',
+    sendResetEmail: 'Invia email di reimpostazione',
     howToReset: 'Come reimpostare la password:',
     howToReset: 'Come reimpostare la password:',
     resetStep1: 'Contatta il tuo amministratore Bambuddy',
     resetStep1: 'Contatta il tuo amministratore Bambuddy',
     resetStep2: 'Chiedi di reimpostare la password in Gestione utenti',
     resetStep2: 'Chiedi di reimpostare la password in Gestione utenti',
@@ -1779,10 +1966,13 @@ export default {
       creating: 'Creazione...',
       creating: 'Creazione...',
       saving: 'Salvataggio...',
       saving: 'Salvataggio...',
       saveChanges: 'Salva modifiche',
       saveChanges: 'Salva modifiche',
+      advancedAuthSubtitle: 'con autenticazione avanzata',
     },
     },
     form: {
     form: {
       username: 'Nome utente',
       username: 'Nome utente',
       usernamePlaceholder: 'Inserisci nome utente',
       usernamePlaceholder: 'Inserisci nome utente',
+      email: 'Email',
+      emailPlaceholder: 'utente@esempio.com',
       password: 'Password',
       password: 'Password',
       passwordPlaceholder: 'Inserisci password',
       passwordPlaceholder: 'Inserisci password',
       confirmPassword: 'Conferma password',
       confirmPassword: 'Conferma password',
@@ -1791,6 +1981,11 @@ export default {
       confirmNewPasswordPlaceholder: 'Conferma nuova password',
       confirmNewPasswordPlaceholder: 'Conferma nuova password',
       leaveBlankToKeep: 'lascia vuoto per mantenere attuale',
       leaveBlankToKeep: 'lascia vuoto per mantenere attuale',
       groups: 'Gruppi',
       groups: 'Gruppi',
+      optional: 'opzionale',
+      autoGeneratedPassword: 'Una password sicura verrà generata automaticamente e inviata via email all\'utente.',
+      passwordManagedByAdvancedAuth: 'La password è gestita dall\'autenticazione avanzata. Usa "Reimposta password" per inviare una nuova password all\'utente via email.',
+      resetPassword: 'Reimposta password',
+      resettingPassword: 'Reimpostazione password...',
     },
     },
     deleteModal: {
     deleteModal: {
       title: 'Elimina utente',
       title: 'Elimina utente',
@@ -2484,11 +2679,106 @@ export default {
     spoolArchived: 'Bobina archiviata',
     spoolArchived: 'Bobina archiviata',
     spoolRestored: 'Bobina ripristinata',
     spoolRestored: 'Bobina ripristinata',
     deleteConfirm: 'Sei sicuro di voler eliminare questa bobina? Questa azione non può essere annullata.',
     deleteConfirm: 'Sei sicuro di voler eliminare questa bobina? Questa azione non può essere annullata.',
+    archiveConfirm: 'Sei sicuro di voler archiviare questa bobina?',
     advancedSettings: 'Impostazioni Avanzate',
     advancedSettings: 'Impostazioni Avanzate',
-    lowStockThresholdError: 'La soglia deve essere tra 0.1 e 99.9',
+    // Tabs
+    filamentInfoTab: 'Info filamento',
+    paProfileTab: 'Profilo PA',
+    filamentInfo: 'Filamento',
+    additional: 'Aggiuntivo',
+    // Cloud
+    loadingPresets: 'Caricamento preset cloud...',
+    cloudConnected: 'Cloud connesso',
+    cloudNotConnected: 'Cloud non connesso (valori predefiniti)',
+    // Colors
+    recentColors: 'Recenti',
+    searchColors: 'Cerca colori...',
+    searchResults: 'Risultati della ricerca',
+    allColors: 'Tutti i colori',
+    commonColors: 'Colori comuni',
+    showLess: 'Mostra meno',
+    showAll: 'Mostra tutto',
+    noColorsFound: 'Nessun colore corrisponde alla ricerca',
+    noResults: 'Nessun risultato trovato',
+    // PA Profiles
+    selectMaterialFirst: 'Selezionare prima un materiale nella scheda Info filamento.',
+    noPrintersConfigured: 'Nessuna stampante configurata. Aggiungi stampanti per usare i profili PA.',
+    matchingFilter: 'Corrispondenti',
+    anyBrand: 'Qualsiasi marca',
+    anyVariant: 'Qualsiasi variante',
+    autoSelect: 'Selezione automatica',
+    matches: 'corrispondenze',
+    match: 'corrispondenza',
+    noMatches: 'Nessuna corrispondenza',
+    connected: 'Connessa',
+    offline: 'Offline',
+    printerOffline: 'La stampante è offline. Connetti per visualizzare i profili di calibrazione.',
+    noKProfilesMatch: 'Nessun profilo K corrisponde al filamento selezionato.',
+    leftNozzle: 'Ugello sinistro',
+    rightNozzle: 'Ugello destro',
+    profilesSelected: 'profili di calibrazione selezionati',
+    // Stats & enhanced table
+    totalInventory: 'Inventario totale',
+    totalConsumed: 'Totale consumato',
+    byMaterial: 'Per materiale',
+    inPrinter: 'In stampante',
+    lowStock: 'Scorta bassa',
+    sinceTracking: 'Dall\'inizio del tracciamento',
+    loadedInAms: 'Caricato in AMS/Est',
+    remaining: 'Rimanente',
     weightCheck: 'Controllo Peso',
     weightCheck: 'Controllo Peso',
     lastWeighed: 'Ultima pesatura',
     lastWeighed: 'Ultima pesatura',
     neverWeighed: 'Mai pesato',
     neverWeighed: 'Mai pesato',
+    search: 'Cerca bobine...',
+    showing: 'Visualizzazione',
+    to: 'a',
+    of: 'di',
+    show: 'Mostra',
+    spools: 'bobine',
+    spool: 'bobina',
+    page: 'Pagina',
+    noSpoolsMatch: 'Nessun risultato trovato',
+    noSpoolsMatchDesc: 'Prova a modificare la ricerca o i filtri per trovare quello che cerchi.',
+    active: 'Attive',
+    archived: 'Archiviate',
+    all: 'Tutte',
+    used: 'Usato',
+    new: 'Nuovo',
+    clearFilters: 'Cancella filtri',
+    table: 'Tabella',
+    cards: 'Schede',
+    net: 'Netto',
+    // Grouping
+    groupSimilar: 'Raggruppa',
+    groupedSpools: '{{count}} bobine identiche',
+    groupedRows: 'righe',
+    // Column config
+    columns: 'Colonne',
+    configureColumns: 'Configura colonne',
+    configureColumnsDesc: 'Trascina per riordinare le colonne o usa le frecce. Attiva/disattiva la visibilità con l\'icona dell\'occhio.',
+    visible: 'visibili',
+    reset: 'Ripristina',
+    cancel: 'Annulla',
+    applyChanges: 'Applica modifiche',
+    moveUp: 'Sposta su',
+    moveDown: 'Sposta giù',
+    hideColumn: 'Nascondi colonna',
+    showColumn: 'Mostra colonna',
+    // Tag linking
+    linkToSpool: 'Collega a bobina',
+    tagLinked: 'Tag collegato alla bobina',
+    tagLinkFailed: 'Impossibile collegare il tag',
+    tagAlreadyLinked: 'Tag già collegato a un\'altra bobina',
+    unknownTag: 'Tag RFID sconosciuto rilevato',
+    // Usage history
+    usageHistory: 'Cronologia utilizzo',
+    noUsageHistory: 'Nessun utilizzo registrato',
+    printName: 'Nome stampa',
+    weightConsumed: 'Peso consumato',
+    clearHistory: 'Cancella',
+    historyCleared: 'Cronologia utilizzo cancellata',
+    fillSourceLabel: '(Inv)',
+    lowStockThresholdError: 'La soglia deve essere tra 0.1 e 99.9',
   },
   },
 
 
   // Timelapse
   // Timelapse
@@ -2548,6 +2838,9 @@ export default {
     noPrintersAvailable: 'Nessuna stampante disponibile',
     noPrintersAvailable: 'Nessuna stampante disponibile',
     printerBusy: 'Stampante occupata',
     printerBusy: 'Stampante occupata',
     printerOffline: 'Stampante offline',
     printerOffline: 'Stampante offline',
+    sameTypeDifferentColor: 'Stesso tipo, colore diverso',
+    filamentTypeNotLoaded: 'Tipo di filamento non caricato',
+    openCalendar: 'Apri calendario',
     leftNozzle: 'L',
     leftNozzle: 'L',
     rightNozzle: 'R',
     rightNozzle: 'R',
     leftNozzleTooltip: 'Ugello sinistro',
     leftNozzleTooltip: 'Ugello sinistro',
@@ -2609,6 +2902,7 @@ export default {
   },
   },
 
 
   // Edit archive modal
   // Edit archive modal
+  // Edit Archive Modal
   editArchive: {
   editArchive: {
     title: 'Modifica archivio',
     title: 'Modifica archivio',
     name: 'Nome',
     name: 'Nome',
@@ -2809,14 +3103,6 @@ export default {
       placeholder: 'Rilevamento automatico (predefinito)...',
       placeholder: 'Rilevamento automatico (predefinito)...',
       hint: 'Sovrascrive l\'indirizzo IP pubblicizzato via SSDP e usato nel certificato TLS. Utile quando Bambuddy ha piu interfacce di rete.',
       hint: 'Sovrascrive l\'indirizzo IP pubblicizzato via SSDP e usato nel certificato TLS. Utile quando Bambuddy ha piu interfacce di rete.',
     },
     },
-    bindIp: {
-      title: 'Interfaccia di rete',
-      placeholder: 'Seleziona interfaccia...',
-      hint: 'Interfaccia di rete a cui questa stampante virtuale si collega. Deve essere unica per stampante.',
-    },
-    proxy: {
-      accessCodeHint: 'In modalita proxy, usa il codice di accesso della stampante di destinazione nello slicer. La connessione viene inoltrata in modo trasparente alla stampante reale.',
-    },
     mode: {
     mode: {
       title: 'Modalita',
       title: 'Modalita',
       archive: 'Archivio',
       archive: 'Archivio',
@@ -2857,8 +3143,37 @@ export default {
       failedToUpdate: 'Aggiornamento impostazioni fallito',
       failedToUpdate: 'Aggiornamento impostazioni fallito',
       accessCodeRequired: 'Imposta prima un codice accesso',
       accessCodeRequired: 'Imposta prima un codice accesso',
       targetPrinterRequired: 'Seleziona prima una stampante target',
       targetPrinterRequired: 'Seleziona prima una stampante target',
+      bindIpRequired: 'Impostare prima un indirizzo IP',
       accessCodeEmpty: 'Il codice accesso non può essere vuoto',
       accessCodeEmpty: 'Il codice accesso non può essere vuoto',
       accessCodeLength: 'Il codice accesso deve essere esattamente 8 caratteri',
       accessCodeLength: 'Il codice accesso deve essere esattamente 8 caratteri',
+      created: 'Stampante virtuale creata',
+      failedToCreate: 'Impossibile creare la stampante virtuale',
+      deleted: 'Stampante virtuale eliminata',
+      failedToDelete: 'Impossibile eliminare la stampante virtuale',
+    },
+    list: {
+      title: 'Stampanti virtuali',
+      add: 'Aggiungi',
+      addFirst: 'Aggiungi stampante virtuale',
+      empty: 'Nessuna stampante virtuale configurata. Aggiungine una per iniziare.',
+    },
+    bindIp: {
+      title: 'Interfaccia di rete',
+      placeholder: 'Seleziona interfaccia...',
+      hint: 'Interfaccia di rete a cui questa stampante virtuale si collega. Deve essere unica per stampante.',
+    },
+    proxy: {
+      accessCodeHint: 'In modalita proxy, usa il codice di accesso della stampante di destinazione nello slicer. La connessione viene inoltrata in modo trasparente alla stampante reale.',
+    },
+    addDialog: {
+      title: 'Aggiungi stampante virtuale',
+      name: 'Nome',
+      hint: 'Potrai configurare il codice di accesso, la stampante di destinazione e altre impostazioni dopo la creazione.',
+      create: 'Crea',
+    },
+    deleteConfirm: {
+      title: 'Elimina stampante virtuale',
+      message: 'Sei sicuro di voler eliminare "{{name}}"? Tutti i servizi di questa stampante verranno interrotti.',
     },
     },
   },
   },
 
 
@@ -2912,6 +3227,205 @@ export default {
     lubricateLeftNozzleRail: 'Lubrifica guida ugello sinistro (serie H2)',
     lubricateLeftNozzleRail: 'Lubrifica guida ugello sinistro (serie H2)',
   },
   },
 
 
+  // Smart Plugs
+  smartPlugs: {
+    offline: 'Offline',
+    admin: 'Amministrazione',
+    openPlugAdminPage: 'Apri pagina amministrazione presa',
+    deleteSmartPlug: 'Elimina presa smart',
+    turnOnSmartPlug: 'Accendi presa smart',
+    turnOffSmartPlug: 'Spegni presa smart',
+    turnOn: 'Accendi',
+    turnOff: 'Spegni',
+    addSmartPlug: {
+      scanningNetwork: 'Scansione rete...',
+      chooseEntity: 'Scegli un\'entità...',
+      connectionFailed: 'Connessione fallita',
+      searchEntities: 'Cerca entità...',
+      searchPowerSensors: 'Cerca sensori di potenza...',
+      searchEnergySensors: 'Cerca sensori di energia...',
+      placeholders: {
+        plugName: 'Presa soggiorno',
+        mqttStateOnValue: 'ON, true, 1',
+        mqttSameAsPower: 'Stesso del topic potenza, o diverso',
+      },
+    },
+  },
+
+  // Rich Text Editor
+  richTextEditor: {
+    bold: 'Grassetto',
+    italic: 'Corsivo',
+    underline: 'Sottolineato',
+    bulletList: 'Elenco puntato',
+    numberedList: 'Elenco numerato',
+    alignLeft: 'Allinea a sinistra',
+    alignCenter: 'Allinea al centro',
+    alignRight: 'Allinea a destra',
+    addLink: 'Aggiungi link',
+    removeLink: 'Rimuovi link',
+  },
+
+  // External Links
+  externalLinks: {
+    noLinksConfigured: 'Nessun link esterno configurato',
+    deleteLink: 'Elimina link',
+    removeCustomIcon: 'Rimuovi icona personalizzata',
+    openInNewTab: 'Apri in nuova scheda',
+    placeholders: {
+      linkName: 'Il mio link',
+    },
+  },
+
+  // Keyboard Shortcuts Modal
+  keyboardShortcuts: {
+    title: 'Scorciatoie da tastiera',
+    navigation: 'Navigazione',
+    archivesSection: 'Archivi',
+    kProfilesSection: 'Profili K',
+    generalSection: 'Generale',
+    shortcuts: {
+      goToPrinters: 'Vai a Stampanti',
+      goToArchives: 'Vai ad Archivi',
+      goToQueue: 'Vai a Coda',
+      goToStats: 'Vai a Statistiche',
+      goToProfiles: 'Vai a Profili cloud',
+      goToSettings: 'Vai a Impostazioni',
+      focusSearch: 'Vai alla ricerca',
+      openUploadModal: 'Apri finestra di caricamento',
+      clearSelection: 'Cancella selezione / deseleziona input',
+      contextMenu: 'Menu contestuale sulle schede',
+      refreshProfiles: 'Aggiorna profili',
+      newProfile: 'Nuovo profilo',
+      exitSelectionMode: 'Esci dalla modalità selezione',
+      showHelp: 'Mostra questa guida',
+    },
+    footer: 'Premi Esc o clicca fuori per chiudere',
+  },
+
+  // Notification Log
+  notificationLog: {
+    title: 'Registro notifiche',
+    events: {
+      printStarted: 'Stampa avviata',
+      printComplete: 'Stampa completata',
+      printFailed: 'Stampa fallita',
+      printStopped: 'Stampa interrotta',
+      progress: 'Avanzamento',
+      printerOffline: 'Stampante offline',
+      printerError: 'Errore stampante',
+      lowFilament: 'Filamento in esaurimento',
+      maintenanceDue: 'Manutenzione in scadenza',
+      test: 'Test',
+    },
+    timeAgo: {
+      justNow: 'Adesso',
+      minutesAgo: '{{minutes}} min fa',
+      hoursAgo: '{{hours}} ore fa',
+    },
+  },
+
+  // Restore/Backup Modal
+  restoreBackup: {
+    title: 'Ripristina backup',
+    restoring: 'Ripristino...',
+    restoreComplete: 'Ripristino completato',
+    restoreFailed: 'Ripristino fallito',
+    importSettings: 'Importa impostazioni da un file di backup',
+    pleaseWait: 'Attendere il ripristino dei dati',
+    clickToSelect: 'Clicca per selezionare il file di backup (.json o .zip)',
+    howDuplicateHandling: 'Come funziona la gestione dei duplicati:',
+    categories: {
+      printers: 'Stampanti',
+      smartPlugs: 'Prese smart',
+      notificationProviders: 'Provider di notifica',
+      filaments: 'Filamenti',
+      archives: 'Archivi',
+      pendingUploads: 'Caricamenti in sospeso',
+      settingsTemplates: 'Impostazioni e modelli',
+    },
+    matchingInfo: {
+      printers: 'abbinati per numero di serie',
+      smartPlugs: 'abbinati per indirizzo IP',
+      notificationProviders: 'abbinati per nome',
+      filaments: 'abbinati per nome + tipo + marca',
+      archives: 'abbinati per hash del contenuto',
+      pendingUploads: 'abbinati per nome file',
+      settingsTemplates: 'sempre sovrascritti',
+    },
+    replaceExisting: 'Sostituisci dati esistenti',
+    keepExisting: 'Mantieni dati esistenti',
+    replaceDescription: 'Sovrascrivi gli elementi già esistenti con i dati del backup',
+    keepDescription: 'Ripristina solo gli elementi che non esistono già',
+    caution: 'Attenzione:',
+    cautionText: 'La sovrascrittura sostituirà le configurazioni attuali con i dati del backup. I codici di accesso delle stampanti non vengono mai sovrascritti per sicurezza.',
+    itemsRestored: 'Elementi ripristinati',
+    itemsSkipped: 'Elementi saltati',
+    restored: 'Ripristinati',
+    skipped: 'Saltati (già esistenti)',
+    filesLabel: 'File (3MF, miniature, ecc.)',
+    newApiKeysGenerated: 'Nuove chiavi API generate',
+    newApiKeysWarning: 'Queste chiavi vengono mostrate una sola volta. Copiale adesso!',
+    processingBackup: 'Elaborazione file di backup...',
+    noDataFound: 'Nessun dato trovato da ripristinare nel file di backup.',
+    failedToRestore: 'Impossibile ripristinare il backup. Verificare il formato del file.',
+  },
+
+  // Backup Export Modal
+  backupExport: {
+    title: 'Esporta backup',
+    selectData: 'Seleziona i dati da includere',
+    selectAll: 'Seleziona tutto',
+    selectNone: 'Deseleziona tutto',
+    categoryDescriptions: {
+      settings: 'Lingua, tema, preferenze di aggiornamento',
+      notifications: 'ntfy, Pushover, Discord, ecc.',
+      templates: 'Modelli di messaggi personalizzati',
+      smartPlugs: 'Configurazioni prese Tasmota',
+      externalLinks: 'Link della barra laterale a servizi esterni',
+      printers: 'Info stampanti (codici di accesso esclusi)',
+      plateDetection: 'Immagini di riferimento piatto vuoto',
+      filaments: 'Tipi di filamento e costi',
+      maintenance: 'Programmi di manutenzione personalizzati',
+      archives: 'Tutti i dati di stampa + file (3MF, miniature, foto)',
+      projects: 'Progetti, elementi BOM e allegati',
+      pendingUploads: 'Caricamenti della stampante virtuale in attesa di revisione',
+      apiKeys: 'Chiavi API webhook (nuove chiavi generate all\'importazione)',
+    },
+    requiresPrinters: 'Richiede la selezione di Stampanti',
+    zipFileWarning: 'Verrà creato un file ZIP.',
+    zipFileDescription: 'Include tutti i file 3MF, miniature, timelapse e foto. Potrebbe richiedere tempo e produrre un file di grandi dimensioni.',
+    includeAccessCodes: 'Includi codici di accesso',
+    includeAccessCodesDescription: 'Per il trasferimento su un\'altra macchina',
+    includeAccessCodesWarning: 'I codici di accesso saranno inclusi in testo semplice. Mantieni sicuro questo file di backup!',
+    categoriesSelected: '{{selectedCount}} categorie selezionate',
+  },
+
+  // Pending Uploads Panel
+  pendingUploads: {
+    placeholders: {
+      notes: 'Aggiungi note su questa stampa...',
+    },
+    discardUpload: 'Scarta caricamento',
+    archiveAllUploads: 'Archivia tutti i caricamenti',
+    discardAllUploads: 'Scarta tutti i caricamenti',
+    archive: 'Archivia',
+    timeAgo: {
+      justNow: 'Adesso',
+      minutesAgo: '{{minutes}} min fa',
+      hoursAgo: '{{hours}} ore fa',
+      daysAgo: '{{days}} giorni fa',
+    },
+  },
+
+  // API Browser
+  apiBrowser: {
+    placeholders: {
+      requestBody: 'Corpo della richiesta JSON...',
+      searchEndpoints: 'Cerca endpoint...',
+    },
+  },
+
   // Configure AMS Slot Modal
   // Configure AMS Slot Modal
   configureAmsSlot: {
   configureAmsSlot: {
     title: 'Configura Slot AMS',
     title: 'Configura Slot AMS',
@@ -2947,6 +3461,140 @@ export default {
     configureSlot: 'Configura slot',
     configureSlot: 'Configura slot',
   },
   },
 
 
+  // GitHub Backup Settings
+  githubBackup: {
+    title: 'Backup GitHub',
+    history: 'Cronologia',
+    downloadBackup: 'Scarica backup',
+    restoreBackup: 'Ripristina backup',
+    noBackupsYet: 'Nessun backup ancora',
+  },
+
+  // Email Settings
+  emailSettings: {
+    placeholders: {
+      fromName: 'BamBuddy',
+    },
+  },
+
+  // Tag Management Modal
+  tagManagement: {
+    searchTags: 'Cerca tag...',
+    renameTag: 'Rinomina tag',
+    deleteTag: 'Elimina tag',
+  },
+
+  // Notification Template Editor
+  notificationTemplates: {
+    placeholders: {
+      title: 'Titolo notifica...',
+      body: 'Corpo notifica...',
+    },
+  },
+
+  // Batch Tag Modal
+  batchTag: {
+    placeholders: {
+      newTag: 'Inserisci nuovo tag...',
+    },
+  },
+
+  // Photo Gallery Modal
+  photoGallery: {
+    deletePhoto: 'Elimina foto',
+  },
+
+  // Filament Hover Card
+  filamentHoverCard: {
+    copySpoolUuid: 'Copia UUID bobina',
+  },
+
+  // K Profiles View
+  kProfilesView: {
+    hasNote: 'Ha una nota',
+    copyProfile: 'Copia profilo',
+  },
+
+  // Layout/Navigation
+  layout: {
+    openMenu: 'Apri menu',
+    noPermissionSystemInfo: 'Non hai il permesso di visualizzare le informazioni di sistema',
+  },
+
+  // Dashboard
+  dashboard: {
+    dragToReorder: 'Trascina per riordinare',
+    hideWidget: 'Nascondi widget',
+  },
+
+  // Notification Provider Card
+  notificationProviderCard: {
+    deleteNotificationProvider: 'Elimina provider di notifica',
+  },
+
+  // File Manager Modal
+  fileManagerModal: {
+    closeFileManager: 'Chiudi gestore file',
+    sortFiles: 'Ordina file',
+    goToParentFolder: 'Vai alla cartella superiore',
+    threeView: 'Vista 3D',
+  },
+
+  // Embedded Camera Viewer
+  embeddedCameraViewer: {
+    refreshStream: 'Aggiorna stream',
+    close: 'Chiudi',
+    zoomOut: 'Rimpicciolisci',
+    resetZoom: 'Reimposta zoom',
+    zoomIn: 'Ingrandisci',
+    dragToResize: 'Trascina per ridimensionare',
+  },
+
+  // Timelapse Viewer
+  timelapseViewer: {
+    skipBack5s: 'Indietro 5s',
+    skipForward5s: 'Avanti 5s',
+  },
+
+  // Notification Providers
+  notificationProviders: {
+    descriptions: {
+      email: 'Notifiche email via SMTP',
+      telegram: 'Notifiche tramite bot Telegram',
+      discord: 'Invia a canale Discord tramite webhook',
+      ntfy: 'Notifiche push gratuite e self-hostabili',
+      pushover: 'Notifiche push semplici e affidabili',
+      callmebot: 'Notifiche WhatsApp gratuite tramite CallMeBot',
+      webhook: 'POST HTTP generico a qualsiasi URL',
+    },
+  },
+
+  // Log Viewer
+  logViewer: {
+    searchPlaceholder: 'Cerca messaggio o nome logger...',
+    noLogEntries: 'Nessuna voce di log trovata',
+  },
+
+  // Switchbar Popover
+  switchbarPopover: {
+    noSwitchesInSwitchbar: 'Nessun interruttore nella barra',
+  },
+
+  // Project Page Modal
+  projectPageModal: {
+    placeholders: {
+      title: 'Titolo',
+      designer: 'Designer',
+      license: 'Licenza',
+      description: 'Inserisci descrizione...',
+      profileTitle: 'Titolo profilo',
+      profileDescription: 'Descrizione profilo...',
+    },
+  },
+
+  // Spoolman Settings
+  spoolmanSettings: {},
+
   // Time
   // Time
   time: {
   time: {
     unknown: '-',
     unknown: '-',
@@ -3002,6 +3650,25 @@ export default {
       grossWeight: 'Peso lordo',
       grossWeight: 'Peso lordo',
       spoolSize: 'Dimensione bobina',
       spoolSize: 'Dimensione bobina',
       close: 'Chiudi',
       close: 'Chiudi',
+      currentSpool: 'Bobina attuale',
+    },
+    modal: {
+      spoolDetected: 'Bobina rilevata',
+      assignToAms: 'Assegna all\'AMS',
+      syncWeight: 'Sincronizza peso',
+      weightSynced: 'Sincronizzato!',
+      syncing: 'Sincronizzazione...',
+      newTagDetected: 'Nuovo tag rilevato',
+      addToInventory: 'Aggiungi all\'inventario',
+      assignToAmsTitle: 'Assegna all\'AMS',
+      selectSlot: 'Seleziona uno slot',
+      assign: 'Assegna',
+      assigning: 'Assegnazione...',
+      assignSuccess: 'Assegnato!',
+      assignError: 'Impossibile assegnare la bobina. Riprovare.',
+      noPrinterSelected: 'Seleziona una stampante...',
+      noAmsDetected: 'Nessun AMS rilevato su questa stampante',
+      slot: 'Slot',
     },
     },
     weight: {
     weight: {
       noReading: 'Nessuna lettura',
       noReading: 'Nessuna lettura',
@@ -3041,12 +3708,12 @@ export default {
       addSpool: 'Aggiungi bobina',
       addSpool: 'Aggiungi bobina',
     },
     },
     settings: {
     settings: {
-      // Schede
+      // Tabs
       tabDevice: 'Dispositivo',
       tabDevice: 'Dispositivo',
       tabDisplay: 'Display',
       tabDisplay: 'Display',
       tabScale: 'Bilancia',
       tabScale: 'Bilancia',
       tabUpdates: 'Aggiornamenti',
       tabUpdates: 'Aggiornamenti',
-      // Scheda dispositivo
+      // Device tab
       nfcReader: 'Lettore NFC',
       nfcReader: 'Lettore NFC',
       type: 'Tipo',
       type: 'Tipo',
       connection: 'Connessione',
       connection: 'Connessione',
@@ -3054,14 +3721,14 @@ export default {
       deviceInfo: 'Info dispositivo',
       deviceInfo: 'Info dispositivo',
       hostname: 'Host',
       hostname: 'Host',
       uptime: 'Tempo di attività',
       uptime: 'Tempo di attività',
-      // Scheda display
+      // Display tab
       brightness: 'Luminosità',
       brightness: 'Luminosità',
       saved: 'Salvato',
       saved: 'Salvato',
       noBacklight: 'Nessuna retroilluminazione DSI rilevata. Il controllo luminosità richiede un display DSI.',
       noBacklight: 'Nessuna retroilluminazione DSI rilevata. Il controllo luminosità richiede un display DSI.',
       screenBlank: 'Timeout spegnimento schermo',
       screenBlank: 'Timeout spegnimento schermo',
       screenBlankDesc: 'Lo schermo si spegne dopo inattività. Tocca per riattivare.',
       screenBlankDesc: 'Lo schermo si spegne dopo inattività. Tocca per riattivare.',
       displayNote: 'La luminosità viene applicata come filtro software.',
       displayNote: 'La luminosità viene applicata come filtro software.',
-      // Scheda bilancia
+      // Scale tab
       scaleCalibration: 'Calibrazione bilancia',
       scaleCalibration: 'Calibrazione bilancia',
       currentWeight: 'Peso attuale',
       currentWeight: 'Peso attuale',
       tareOffset: 'Tara',
       tareOffset: 'Tara',
@@ -3083,7 +3750,7 @@ export default {
       firmware: 'Firmware',
       firmware: 'Firmware',
       scale: 'Bilancia',
       scale: 'Bilancia',
       noDevice: 'Nessun dispositivo SpoolBuddy trovato',
       noDevice: 'Nessun dispositivo SpoolBuddy trovato',
-      // Scheda aggiornamenti
+      // Updates tab
       daemonVersion: 'Versione daemon',
       daemonVersion: 'Versione daemon',
       currentVersion: 'Attuale',
       currentVersion: 'Attuale',
       versionPending: 'In attesa del daemon...',
       versionPending: 'In attesa del daemon...',
@@ -3130,7 +3797,7 @@ export default {
   bugReport: {
   bugReport: {
     title: 'Segnala un bug',
     title: 'Segnala un bug',
     description: 'Descrizione',
     description: 'Descrizione',
-    descriptionPlaceholder: "Cosa è andato storto? Descrivi il problema...",
+    descriptionPlaceholder: 'Cosa è andato storto? Descrivi il problema...',
     email: 'Email (opzionale)',
     email: 'Email (opzionale)',
     emailPlaceholder: 'tua@email.it',
     emailPlaceholder: 'tua@email.it',
     emailPrivacy: 'Se fornita, la tua email sarà inclusa in una sezione compressa dell\'issue GitHub per permettere al manutentore di contattarti.',
     emailPrivacy: 'Se fornita, la tua email sarà inclusa in una sezione compressa dell\'issue GitHub per permettere al manutentore di contattarti.',
@@ -3146,10 +3813,10 @@ export default {
     collectingLogsHint: 'Registrazione debug attivata, interrogazione delle stampanti per dati aggiornati.',
     collectingLogsHint: 'Registrazione debug attivata, interrogazione delle stampanti per dati aggiornati.',
     submitting: 'Invio segnalazione bug...',
     submitting: 'Invio segnalazione bug...',
     submitSuccess: 'Segnalazione bug inviata con successo!',
     submitSuccess: 'Segnalazione bug inviata con successo!',
-    submitFailed: "Impossibile inviare la segnalazione bug",
+    submitFailed: 'Impossibile inviare la segnalazione bug',
     thankYou: 'Grazie!',
     thankYou: 'Grazie!',
     submitted: 'La tua segnalazione bug è stata inviata.',
     submitted: 'La tua segnalazione bug è stata inviata.',
-    viewIssue: "Vedi issue",
+    viewIssue: 'Vedi issue',
     unexpectedError: 'Si è verificato un errore imprevisto',
     unexpectedError: 'Si è verificato un errore imprevisto',
     countdownSeconds: '{{seconds}}s',
     countdownSeconds: '{{seconds}}s',
   },
   },

File diff suppressed because it is too large
+ 222 - 279
frontend/src/i18n/locales/ja.ts


+ 80 - 22
frontend/src/i18n/locales/pt-BR.ts

@@ -1043,7 +1043,7 @@ export default {
     avgTime: 'Méd. tempo',
     avgTime: 'Méd. tempo',
     filamentByPrints: 'Impressões',
     filamentByPrints: 'Impressões',
     timeframe: {
     timeframe: {
-      'today': 'Hoje',
+      today: 'Hoje',
       'this-week': 'Esta semana',
       'this-week': 'Esta semana',
       'this-month': 'Este mês',
       'this-month': 'Este mês',
       'last-7': 'Últimos 7 dias',
       'last-7': 'Últimos 7 dias',
@@ -1051,7 +1051,7 @@ export default {
       'last-90': 'Últimos 90 dias',
       'last-90': 'Últimos 90 dias',
       'this-year': 'Este ano',
       'this-year': 'Este ano',
       'all-time': 'Todo o período',
       'all-time': 'Todo o período',
-      'custom': 'Personalizado',
+      custom: 'Personalizado',
       from: 'De',
       from: 'De',
       to: 'Até',
       to: 'Até',
     },
     },
@@ -1420,7 +1420,7 @@ export default {
     apiKeysDescription: 'Crie chaves API para integrações externas e webhooks.',
     apiKeysDescription: 'Crie chaves API para integrações externas e webhooks.',
     createKey: 'Criar Chave',
     createKey: 'Criar Chave',
     apiKeyCreated: 'Chave API criada com sucesso',
     apiKeyCreated: 'Chave API criada com sucesso',
-    apiKeyCopyWarning: "Copie esta chave agora - ela não será exibida novamente!",
+    apiKeyCopyWarning: 'Copie esta chave agora - ela não será exibida novamente!',
     useInApiBrowser: 'Usar no Navegador API',
     useInApiBrowser: 'Usar no Navegador API',
     createNewApiKey: 'Criar Nova Chave API',
     createNewApiKey: 'Criar Nova Chave API',
     keyName: 'Nome da Chave',
     keyName: 'Nome da Chave',
@@ -1785,8 +1785,8 @@ export default {
     loginFailed: 'Falha no login',
     loginFailed: 'Falha no login',
     enterCredentials: 'Por favor, insira nome de usuário e senha',
     enterCredentials: 'Por favor, insira nome de usuário e senha',
     forgotPasswordTitle: 'Esqueceu a Senha',
     forgotPasswordTitle: 'Esqueceu a Senha',
-    forgotPasswordMessage: "Se você esqueceu sua senha, entre em contato com o administrador do sistema para redefini-la.",
-    forgotPasswordEmailMessage: "Digite seu endereço de email e enviaremos uma nova senha.",
+    forgotPasswordMessage: 'Se você esqueceu sua senha, entre em contato com o administrador do sistema para redefini-la.',
+    forgotPasswordEmailMessage: 'Digite seu endereço de email e enviaremos uma nova senha.',
     emailAddress: 'Endereço de Email',
     emailAddress: 'Endereço de Email',
     emailPlaceholder: 'seu.email@exemplo.com',
     emailPlaceholder: 'seu.email@exemplo.com',
     cancel: 'Cancelar',
     cancel: 'Cancelar',
@@ -2368,7 +2368,7 @@ export default {
     description: 'Descrição',
     description: 'Descrição',
     noProjects: 'Nenhum projeto ainda',
     noProjects: 'Nenhum projeto ainda',
     noProjectsFiltered: 'Nenhum projeto {{status}}',
     noProjectsFiltered: 'Nenhum projeto {{status}}',
-    noProjectsFilteredHelp: "Você não tem nenhum projeto {{status}}. Os projetos aparecerão aqui quando seu status mudar.",
+    noProjectsFilteredHelp: 'Você não tem nenhum projeto {{status}}. Os projetos aparecerão aqui quando seu status mudar.',
     createFirst: 'Crie seu primeiro projeto para começar a organizar impressões relacionadas, acompanhar o progresso e gerenciar suas construções.',
     createFirst: 'Crie seu primeiro projeto para começar a organizar impressões relacionadas, acompanhar o progresso e gerenciar suas construções.',
     createFirstButton: 'Crie Seu Primeiro Projeto',
     createFirstButton: 'Crie Seu Primeiro Projeto',
     create: 'Criar',
     create: 'Criar',
@@ -2612,7 +2612,7 @@ export default {
     weight: 'Peso',
     weight: 'Peso',
     remaining: 'Restante',
     remaining: 'Restante',
     disableWeightSync: 'Desativar Sincronização de Peso Estimado do AMS',
     disableWeightSync: 'Desativar Sincronização de Peso Estimado do AMS',
-    disableWeightSyncDesc: "Não atualize a capacidade restante a partir das estimativas do AMS. Use isso se preferir o rastreamento de uso do Spoolman em vez das estimativas baseadas em porcentagem do AMS. Novos carretéis ainda usarão a estimativa do AMS como seu peso inicial.",
+    disableWeightSyncDesc: 'Não atualize a capacidade restante a partir das estimativas do AMS. Use isso se preferir o rastreamento de uso do Spoolman em vez das estimativas baseadas em porcentagem do AMS. Novos carretéis ainda usarão a estimativa do AMS como seu peso inicial.',
     reportPartialUsage: 'Relatar Uso Parcial para Impressões Falhadas',
     reportPartialUsage: 'Relatar Uso Parcial para Impressões Falhadas',
     reportPartialUsageDesc: 'Quando uma impressão falha ou é cancelada, relate o filamento estimado usado até aquele ponto com base no progresso das camadas.',
     reportPartialUsageDesc: 'Quando uma impressão falha ou é cancelada, relate o filamento estimado usado até aquele ponto com base no progresso das camadas.',
   },
   },
@@ -2748,6 +2748,10 @@ export default {
     table: 'Tabela',
     table: 'Tabela',
     cards: 'Cartões',
     cards: 'Cartões',
     net: 'Líquido',
     net: 'Líquido',
+    // Grouping
+    groupSimilar: 'Agrupar',
+    groupedSpools: '{{count}} carretéis idênticos',
+    groupedRows: 'linhas',
     // Column config
     // Column config
     columns: 'Colunas',
     columns: 'Colunas',
     configureColumns: 'Configurar Colunas',
     configureColumns: 'Configurar Colunas',
@@ -2810,6 +2814,8 @@ export default {
     kFactor: 'Fator K',
     kFactor: 'Fator K',
     fill: 'Preencher',
     fill: 'Preencher',
     configure: 'Configurar',
     configure: 'Configurar',
+    used: 'usado',
+    remainingUnit: 'restante',
   },
   },
 
 
   // Print modal
   // Print modal
@@ -3115,19 +3121,9 @@ export default {
     },
     },
     howItWorks: {
     howItWorks: {
       title: 'Como funciona',
       title: 'Como funciona',
-      titleProxy: 'Como funciona (Modo Proxy)',
       step1: 'Complete o guia de configuração para sua plataforma',
       step1: 'Complete o guia de configuração para sua plataforma',
       step2: 'Ative a impressora virtual e defina um código de acesso',
       step2: 'Ative a impressora virtual e defina um código de acesso',
       step3: 'No Bambu Studio ou OrcaSlicer, vá para "Adicionar Impressora"',
       step3: 'No Bambu Studio ou OrcaSlicer, vá para "Adicionar Impressora"',
-      step4: 'A impressora "Bambuddy" deve aparecer na lista de descoberta',
-      step5: 'Conecte-se usando o código de acesso que você definiu',
-      step6: 'Quando você "imprimir" para o Bambuddy, o arquivo 3MF será arquivado em vez disso',
-      proxyStep1: 'Selecione a impressora alvo (deve estar no modo LAN)',
-      proxyStep2: 'Para rede cruzada: selecione a interface de rede do slicer',
-      proxyStep3: 'Ative o proxy - a impressora aparece na descoberta do slicer via SSDP',
-      proxyStep4: 'Conecte-se usando o código de acesso da impressora',
-      proxyStep5: 'Imprima normalmente - o tráfego é retransmitido pelo Bambuddy',
-      proxyStep6: 'O streaming da câmera requer NAT/encaminhamento de IP (veja a documentação)',
     },
     },
     status: {
     status: {
       title: 'Detalhes do Status',
       title: 'Detalhes do Status',
@@ -3147,8 +3143,37 @@ export default {
       failedToUpdate: 'Falha ao atualizar as configurações',
       failedToUpdate: 'Falha ao atualizar as configurações',
       accessCodeRequired: 'Defina um código de acesso primeiro',
       accessCodeRequired: 'Defina um código de acesso primeiro',
       targetPrinterRequired: 'Selecione uma impressora alvo primeiro',
       targetPrinterRequired: 'Selecione uma impressora alvo primeiro',
+      bindIpRequired: 'Defina um IP de ligação primeiro',
       accessCodeEmpty: 'O código de acesso não pode estar vazio',
       accessCodeEmpty: 'O código de acesso não pode estar vazio',
       accessCodeLength: 'O código de acesso deve ter exatamente 8 caracteres',
       accessCodeLength: 'O código de acesso deve ter exatamente 8 caracteres',
+      created: 'Impressora virtual criada',
+      failedToCreate: 'Falha ao criar impressora virtual',
+      deleted: 'Impressora virtual excluída',
+      failedToDelete: 'Falha ao excluir impressora virtual',
+    },
+    list: {
+      title: 'Impressoras Virtuais',
+      add: 'Adicionar',
+      addFirst: 'Adicionar Impressora Virtual',
+      empty: 'Nenhuma impressora virtual configurada. Adicione uma para começar.',
+    },
+    bindIp: {
+      title: 'Interface de Rede',
+      placeholder: 'Selecionar interface...',
+      hint: 'Interface de rede para esta impressora virtual. Deve ser única por impressora.',
+    },
+    proxy: {
+      accessCodeHint: 'No modo proxy, use o código de acesso da impressora alvo no slicer. A conexão é encaminhada de forma transparente para a impressora real.',
+    },
+    addDialog: {
+      title: 'Adicionar Impressora Virtual',
+      name: 'Nome',
+      hint: 'Você pode configurar o código de acesso, impressora alvo e outras configurações após a criação.',
+      create: 'Criar',
+    },
+    deleteConfirm: {
+      title: 'Excluir Impressora Virtual',
+      message: 'Tem certeza que deseja excluir "{{name}}"? Isso irá parar todos os serviços desta impressora.',
     },
     },
   },
   },
 
 
@@ -3570,6 +3595,20 @@ export default {
   // Spoolman Settings
   // Spoolman Settings
   spoolmanSettings: {},
   spoolmanSettings: {},
 
 
+  // Time
+  time: {
+    unknown: '-',
+    waiting: 'Aguardando',
+    justNow: 'Agora mesmo',
+    now: 'Agora',
+    minsAgo: '{{count}}min atrás',
+    inMins: 'em {{count}}min',
+    hoursAgo: '{{count}}h atrás',
+    inHours: 'em {{count}}h',
+    daysAgo: '{{count}}d atrás',
+    inDays: 'em {{count}}d',
+  },
+
   // SpoolBuddy Kiosk
   // SpoolBuddy Kiosk
   spoolbuddy: {
   spoolbuddy: {
     nav: {
     nav: {
@@ -3611,6 +3650,25 @@ export default {
       grossWeight: 'Peso bruto',
       grossWeight: 'Peso bruto',
       spoolSize: 'Tamanho do carretel',
       spoolSize: 'Tamanho do carretel',
       close: 'Fechar',
       close: 'Fechar',
+      currentSpool: 'Carretel Atual',
+    },
+    modal: {
+      spoolDetected: 'Carretel Detectado',
+      assignToAms: 'Atribuir ao AMS',
+      syncWeight: 'Sincronizar Peso',
+      weightSynced: 'Sincronizado!',
+      syncing: 'Sincronizando...',
+      newTagDetected: 'Nova Tag Detectada',
+      addToInventory: 'Adicionar ao Inventário',
+      assignToAmsTitle: 'Atribuir ao AMS',
+      selectSlot: 'Selecionar um slot',
+      assign: 'Atribuir',
+      assigning: 'Atribuindo...',
+      assignSuccess: 'Atribuído!',
+      assignError: 'Falha ao atribuir carretel. Tente novamente.',
+      noPrinterSelected: 'Selecionar uma impressora...',
+      noAmsDetected: 'Nenhum AMS detectado nesta impressora',
+      slot: 'Slot',
     },
     },
     weight: {
     weight: {
       noReading: 'Sem leitura',
       noReading: 'Sem leitura',
@@ -3650,12 +3708,12 @@ export default {
       addSpool: 'Adicionar carretel',
       addSpool: 'Adicionar carretel',
     },
     },
     settings: {
     settings: {
-      // Abas
+      // Tabs
       tabDevice: 'Dispositivo',
       tabDevice: 'Dispositivo',
       tabDisplay: 'Tela',
       tabDisplay: 'Tela',
       tabScale: 'Balança',
       tabScale: 'Balança',
       tabUpdates: 'Atualizações',
       tabUpdates: 'Atualizações',
-      // Aba dispositivo
+      // Device tab
       nfcReader: 'Leitor NFC',
       nfcReader: 'Leitor NFC',
       type: 'Tipo',
       type: 'Tipo',
       connection: 'Conexão',
       connection: 'Conexão',
@@ -3663,14 +3721,14 @@ export default {
       deviceInfo: 'Info do dispositivo',
       deviceInfo: 'Info do dispositivo',
       hostname: 'Host',
       hostname: 'Host',
       uptime: 'Tempo de atividade',
       uptime: 'Tempo de atividade',
-      // Aba tela
+      // Display tab
       brightness: 'Brilho',
       brightness: 'Brilho',
       saved: 'Salvo',
       saved: 'Salvo',
       noBacklight: 'Nenhuma retroiluminação DSI detectada. O controle de brilho requer uma tela DSI.',
       noBacklight: 'Nenhuma retroiluminação DSI detectada. O controle de brilho requer uma tela DSI.',
       screenBlank: 'Tempo para desligar tela',
       screenBlank: 'Tempo para desligar tela',
       screenBlankDesc: 'A tela desliga após inatividade. Toque para despertar.',
       screenBlankDesc: 'A tela desliga após inatividade. Toque para despertar.',
       displayNote: 'O brilho é aplicado como filtro de software.',
       displayNote: 'O brilho é aplicado como filtro de software.',
-      // Aba balança
+      // Scale tab
       scaleCalibration: 'Calibração da balança',
       scaleCalibration: 'Calibração da balança',
       currentWeight: 'Peso atual',
       currentWeight: 'Peso atual',
       tareOffset: 'Tara',
       tareOffset: 'Tara',
@@ -3692,7 +3750,7 @@ export default {
       firmware: 'Firmware',
       firmware: 'Firmware',
       scale: 'Balança',
       scale: 'Balança',
       noDevice: 'Nenhum dispositivo SpoolBuddy encontrado',
       noDevice: 'Nenhum dispositivo SpoolBuddy encontrado',
-      // Aba atualizações
+      // Updates tab
       daemonVersion: 'Versão do daemon',
       daemonVersion: 'Versão do daemon',
       currentVersion: 'Atual',
       currentVersion: 'Atual',
       versionPending: 'Aguardando daemon...',
       versionPending: 'Aguardando daemon...',

+ 139 - 5
frontend/src/i18n/locales/zh-CN.ts

@@ -201,6 +201,7 @@ export default {
     chamberLightOn: '打开腔室灯',
     chamberLightOn: '打开腔室灯',
     chamberLightOff: '关闭腔室灯',
     chamberLightOff: '关闭腔室灯',
     // Files
     // Files
+    files: '文件',
     browseFiles: '浏览打印机文件',
     browseFiles: '浏览打印机文件',
     // Smart plug
     // Smart plug
     autoOffAfterPrint: '打印后自动关机',
     autoOffAfterPrint: '打印后自动关机',
@@ -216,6 +217,19 @@ export default {
     skipObject: '跳过对象',
     skipObject: '跳过对象',
     reconnect: '重新连接',
     reconnect: '重新连接',
     mqttDebug: 'MQTT 调试',
     mqttDebug: 'MQTT 调试',
+    printerInformation: '打印机信息',
+    copyToClipboard: '复制',
+    copied: '已复制!',
+    state: '状态',
+    wifiSignalLabel: 'WiFi 信号',
+    developerMode: '开发者模式',
+    enabled: '已启用',
+    disabled: '已禁用',
+    addedOn: '添加日期',
+    sdCard: 'SD 卡',
+    inserted: '已插入',
+    notInserted: '未插入',
+    totalPrintHours: '打印时长',
     activeNozzle: '当前:{{nozzle}} 喷嘴',
     activeNozzle: '当前:{{nozzle}} 喷嘴',
     nozzleRack: '喷嘴架',
     nozzleRack: '喷嘴架',
     nozzleDocked: '已停靠',
     nozzleDocked: '已停靠',
@@ -431,6 +445,16 @@ export default {
     clickToViewHmsErrors: '点击查看 HMS 错误',
     clickToViewHmsErrors: '点击查看 HMS 错误',
     estimatedCompletion: '预计完成时间',
     estimatedCompletion: '预计完成时间',
     slotOptions: '槽位选项',
     slotOptions: '槽位选项',
+    // AMS hover popup
+    amsPopup: {
+      friendlyName: 'AMS 名称',
+      friendlyNamePlaceholder: '例如 AMS 友好名称',
+      serialNumber: '序列号',
+      firmwareVersion: '固件',
+      save: '保存',
+      clear: '清除',
+      noEditPermission: '您没有重命名 AMS 单元的权限',
+    },
     // Firmware modal
     // Firmware modal
     firmwareModal: {
     firmwareModal: {
       title: '固件更新',
       title: '固件更新',
@@ -464,6 +488,8 @@ export default {
     },
     },
     developerModeWarning: '以下打印机未启用开发者局域网模式:{{names}}。某些功能可能无法使用。',
     developerModeWarning: '以下打印机未启用开发者局域网模式:{{names}}。某些功能可能无法使用。',
     howToEnable: '如何启用',
     howToEnable: '如何启用',
+    incompatibleFile: '此文件是为 {{slicedFor}} 切片的,但该打印机是 {{printerModel}}',
+    dropNotPrintable: '只能打印 .gcode 和 .gcode.3mf 文件',
     dropToPrint: '拖放以打印',
     dropToPrint: '拖放以打印',
     cannotPrint: '打印机忙碌',
     cannotPrint: '打印机忙碌',
   },
   },
@@ -724,6 +750,7 @@ export default {
     title: '打印队列',
     title: '打印队列',
     subtitle: '排程和管理您的打印任务',
     subtitle: '排程和管理您的打印任务',
     addToQueue: '添加到队列',
     addToQueue: '添加到队列',
+    // Print modal
     print: '打印',
     print: '打印',
     reprint: '重新打印',
     reprint: '重新打印',
     schedulePrint: '排程打印',
     schedulePrint: '排程打印',
@@ -756,11 +783,13 @@ export default {
     clearPlateSuccess: '打印板已清理 — 准备进行下一个打印',
     clearPlateSuccess: '打印板已清理 — 准备进行下一个打印',
     plateReady: '打印板已清理 — 准备进行下一个打印',
     plateReady: '打印板已清理 — 准备进行下一个打印',
     plateNumber: '板 {{index}}',
     plateNumber: '板 {{index}}',
+    // Sections
     sections: {
     sections: {
       currentlyPrinting: '正在打印',
       currentlyPrinting: '正在打印',
       queued: '排队中',
       queued: '排队中',
       history: '历史',
       history: '历史',
     },
     },
+    // Status
     status: {
     status: {
       pending: '等待中',
       pending: '等待中',
       waiting: '等待中',
       waiting: '等待中',
@@ -771,6 +800,7 @@ export default {
       skipped: '已跳过',
       skipped: '已跳过',
       cancelled: '已取消',
       cancelled: '已取消',
     },
     },
+    // Summary cards
     summary: {
     summary: {
       printing: '打印中',
       printing: '打印中',
       queued: '排队中',
       queued: '排队中',
@@ -778,6 +808,7 @@ export default {
       totalWeight: '总队列重量',
       totalWeight: '总队列重量',
       history: '历史',
       history: '历史',
     },
     },
+    // Filters
     filter: {
     filter: {
       allPrinters: '所有打印机',
       allPrinters: '所有打印机',
       unassigned: '未分配',
       unassigned: '未分配',
@@ -785,6 +816,7 @@ export default {
       allLocations: '所有位置',
       allLocations: '所有位置',
       any: '任意',
       any: '任意',
     },
     },
+    // Sort
     sort: {
     sort: {
       byPosition: '按位置排序',
       byPosition: '按位置排序',
       byName: '按名称排序',
       byName: '按名称排序',
@@ -794,15 +826,18 @@ export default {
       ascendingOldest: '升序(最旧优先)',
       ascendingOldest: '升序(最旧优先)',
       descendingNewest: '降序(最新优先)',
       descendingNewest: '降序(最新优先)',
     },
     },
+    // Badges
     badges: {
     badges: {
       staged: '已暂存',
       staged: '已暂存',
       requiresPrevious: '需要前一个成功',
       requiresPrevious: '需要前一个成功',
       autoPowerOff: '自动关机',
       autoPowerOff: '自动关机',
     },
     },
+    // Empty state
     empty: {
     empty: {
       title: '没有排程的打印',
       title: '没有排程的打印',
       description: '从归档页面使用右键菜单中的"排程"选项来排程打印,或拖放文件开始。',
       description: '从归档页面使用右键菜单中的"排程"选项来排程打印,或拖放文件开始。',
     },
     },
+    // Time
     time: {
     time: {
       asap: '尽快',
       asap: '尽快',
       overdue: '已逾期',
       overdue: '已逾期',
@@ -811,11 +846,13 @@ export default {
       inMinutes: '{{count}} 分钟后',
       inMinutes: '{{count}} 分钟后',
       inHours: '{{count}} 小时后',
       inHours: '{{count}} 小时后',
     },
     },
+    // Actions
     actions: {
     actions: {
       stopPrint: '停止打印',
       stopPrint: '停止打印',
       startPrint: '开始打印',
       startPrint: '开始打印',
       requeue: '重新排队',
       requeue: '重新排队',
     },
     },
+    // Bulk edit
     bulkEdit: {
     bulkEdit: {
       title: '编辑 {{count}} 个项目',
       title: '编辑 {{count}} 个项目',
       title_plural: '编辑 {{count}} 个项目',
       title_plural: '编辑 {{count}} 个项目',
@@ -840,6 +877,7 @@ export default {
       editSelected: '编辑所选',
       editSelected: '编辑所选',
       cancelSelected: '取消所选',
       cancelSelected: '取消所选',
     },
     },
+    // Confirmations
     confirm: {
     confirm: {
       cancelTitle: '取消排程打印',
       cancelTitle: '取消排程打印',
       cancelMessage: '确定要取消"{{name}}"吗?',
       cancelMessage: '确定要取消"{{name}}"吗?',
@@ -854,6 +892,7 @@ export default {
       thisPrint: '此打印',
       thisPrint: '此打印',
       thisItem: '此项目',
       thisItem: '此项目',
     },
     },
+    // Toast messages
     toast: {
     toast: {
       cancelled: '队列项目已取消',
       cancelled: '队列项目已取消',
       cancelFailed: '取消项目失败',
       cancelFailed: '取消项目失败',
@@ -870,6 +909,7 @@ export default {
       bulkCancelled: '已取消 {{count}} 个项目',
       bulkCancelled: '已取消 {{count}} 个项目',
       bulkCancelFailed: '批量取消项目失败',
       bulkCancelFailed: '批量取消项目失败',
     },
     },
+    // Permissions
     permissions: {
     permissions: {
       noStopPrint: '您没有停止打印的权限',
       noStopPrint: '您没有停止打印的权限',
       noStartPrint: '您没有开始打印的权限',
       noStartPrint: '您没有开始打印的权限',
@@ -935,6 +975,7 @@ export default {
     last30Days: '最近 30 天',
     last30Days: '最近 30 天',
     last90Days: '最近 90 天',
     last90Days: '最近 90 天',
     allTime: '全部时间',
     allTime: '全部时间',
+    // Widgets
     quickStats: '快速统计',
     quickStats: '快速统计',
     printActivity: '打印活动',
     printActivity: '打印活动',
     filamentTypes: '耗材类型',
     filamentTypes: '耗材类型',
@@ -953,6 +994,7 @@ export default {
     topFailureReasons: '主要失败原因',
     topFailureReasons: '主要失败原因',
     failedPrintsCount: '{{failed}} / {{total}} 次打印失败',
     failedPrintsCount: '{{failed}} / {{total}} 次打印失败',
     lastWeekRate: '上周:{{rate}}%',
     lastWeekRate: '上周:{{rate}}%',
+    // Actions
     resetLayout: '重置布局',
     resetLayout: '重置布局',
     recalculateCosts: '重新计算成本',
     recalculateCosts: '重新计算成本',
     recalculateCostsHint: '使用当前耗材价格重新计算所有归档成本',
     recalculateCostsHint: '使用当前耗材价格重新计算所有归档成本',
@@ -960,12 +1002,15 @@ export default {
     exportAsCsv: '导出为 CSV',
     exportAsCsv: '导出为 CSV',
     exportAsExcel: '导出为 Excel',
     exportAsExcel: '导出为 Excel',
     hiddenCount: '{{count}} 个已隐藏',
     hiddenCount: '{{count}} 个已隐藏',
+    // Toast
     exportDownloaded: '导出已下载',
     exportDownloaded: '导出已下载',
     exportFailed: '导出失败',
     exportFailed: '导出失败',
     layoutReset: '布局已重置',
     layoutReset: '布局已重置',
     recalculatedCosts: '已为 {{count}} 个归档重新计算成本',
     recalculatedCosts: '已为 {{count}} 个归档重新计算成本',
     recalculateFailed: '重新计算成本失败',
     recalculateFailed: '重新计算成本失败',
+    // Loading
     loadingStats: '加载统计数据中...',
     loadingStats: '加载统计数据中...',
+    // Permissions
     noPermissionResetLayout: '您没有重置布局的权限',
     noPermissionResetLayout: '您没有重置布局的权限',
     noPermissionRecalculate: '您没有重新计算成本的权限',
     noPermissionRecalculate: '您没有重新计算成本的权限',
     noPrintDataInRange: '所选范围内无打印数据',
     noPrintDataInRange: '所选范围内无打印数据',
@@ -998,7 +1043,7 @@ export default {
     avgTime: '平均时间',
     avgTime: '平均时间',
     filamentByPrints: '打印次数',
     filamentByPrints: '打印次数',
     timeframe: {
     timeframe: {
-      'today': '今天',
+      today: '今天',
       'this-week': '本周',
       'this-week': '本周',
       'this-month': '本月',
       'this-month': '本月',
       'last-7': '最近 7 天',
       'last-7': '最近 7 天',
@@ -1006,7 +1051,7 @@ export default {
       'last-90': '最近 90 天',
       'last-90': '最近 90 天',
       'this-year': '今年',
       'this-year': '今年',
       'all-time': '全部时间',
       'all-time': '全部时间',
-      'custom': '自定义范围',
+      custom: '自定义范围',
       from: '从',
       from: '从',
       to: '到',
       to: '到',
     },
     },
@@ -1035,8 +1080,10 @@ export default {
     noHistory: '无维护历史',
     noHistory: '无维护历史',
     editPrintHours: '编辑打印时间',
     editPrintHours: '编辑打印时间',
     currentHours: '当前小时数',
     currentHours: '当前小时数',
+    // Tabs
     statusTab: '状态',
     statusTab: '状态',
     settingsTab: '设置',
     settingsTab: '设置',
+    // Status
     overdueCount: '{{count}} 个逾期',
     overdueCount: '{{count}} 个逾期',
     dueSoonCount: '{{count}} 个即将到期',
     dueSoonCount: '{{count}} 个即将到期',
     dueSoon: '即将到期',
     dueSoon: '即将到期',
@@ -1044,6 +1091,7 @@ export default {
     overdueBy: '逾期 {{duration}}',
     overdueBy: '逾期 {{duration}}',
     dueIn: '{{duration}} 后到期',
     dueIn: '{{duration}} 后到期',
     timeLeft: '剩余 {{duration}}',
     timeLeft: '剩余 {{duration}}',
+    // Duration formats
     day: '1 天',
     day: '1 天',
     days: '{{count}} 天',
     days: '{{count}} 天',
     week: '1 周',
     week: '1 周',
@@ -1051,6 +1099,7 @@ export default {
     month: '1 个月',
     month: '1 个月',
     months: '{{count}} 个月',
     months: '{{count}} 个月',
     year: '1 年',
     year: '1 年',
+    // Settings
     maintenanceTypes: '维护类型',
     maintenanceTypes: '维护类型',
     maintenanceTypesDescription: '系统类型和您的自定义维护任务',
     maintenanceTypesDescription: '系统类型和您的自定义维护任务',
     addCustomType: '添加自定义类型',
     addCustomType: '添加自定义类型',
@@ -1068,13 +1117,16 @@ export default {
     exampleName: '例如:更换 HEPA 过滤器',
     exampleName: '例如:更换 HEPA 过滤器',
     viewDocumentation: '查看文档',
     viewDocumentation: '查看文档',
     timeBasedInterval: '基于时间的间隔',
     timeBasedInterval: '基于时间的间隔',
+    // Interval overrides
     intervalOverrides: '间隔覆盖',
     intervalOverrides: '间隔覆盖',
     intervalOverridesDescription: '为特定打印机自定义间隔',
     intervalOverridesDescription: '为特定打印机自定义间隔',
+    // Printer assignment
     assignedToPrinters: '已分配给打印机:',
     assignedToPrinters: '已分配给打印机:',
     noPrintersAssigned: '未分配打印机',
     noPrintersAssigned: '未分配打印机',
     addPrinterShort: '添加:',
     addPrinterShort: '添加:',
     printersAssignedClick: '已分配 {{count}} 台打印机 - 点击管理',
     printersAssignedClick: '已分配 {{count}} 台打印机 - 点击管理',
     removeFromPrinter: '从此打印机移除',
     removeFromPrinter: '从此打印机移除',
+    // Types
     types: {
     types: {
       lubricateCarbonRods: '润滑碳纤维杆',
       lubricateCarbonRods: '润滑碳纤维杆',
       lubricateRails: '润滑线性导轨',
       lubricateRails: '润滑线性导轨',
@@ -1091,6 +1143,7 @@ export default {
       replaceCarbonFilter: '更换活性炭过滤器',
       replaceCarbonFilter: '更换活性炭过滤器',
       lubricateLeftNozzleRail: '润滑左喷嘴导轨',
       lubricateLeftNozzleRail: '润滑左喷嘴导轨',
     },
     },
+    // Toast
     maintenanceComplete: '维护已标记为完成',
     maintenanceComplete: '维护已标记为完成',
     typeUpdated: '维护类型已更新',
     typeUpdated: '维护类型已更新',
     typeDeleted: '维护类型已删除',
     typeDeleted: '维护类型已删除',
@@ -1098,9 +1151,11 @@ export default {
     printHoursUpdated: '打印小时数已更新',
     printHoursUpdated: '打印小时数已更新',
     printerAssigned: '打印机已分配',
     printerAssigned: '打印机已分配',
     printerRemoved: '打印机已移除',
     printerRemoved: '打印机已移除',
+    // Confirmation
     deleteTypeConfirm: '删除"{{name}}"?',
     deleteTypeConfirm: '删除"{{name}}"?',
     deleteSystemTypeTitle: '删除默认维护任务?',
     deleteSystemTypeTitle: '删除默认维护任务?',
     deleteSystemTypeMessage: '确定要删除默认维护任务"{{name}}"吗?',
     deleteSystemTypeMessage: '确定要删除默认维护任务"{{name}}"吗?',
+    // Permissions
     noPermissionUpdate: '您没有更新维护项目的权限',
     noPermissionUpdate: '您没有更新维护项目的权限',
     noPermissionPerform: '您没有执行维护的权限',
     noPermissionPerform: '您没有执行维护的权限',
     noPermissionEditTypes: '您没有编辑维护类型的权限',
     noPermissionEditTypes: '您没有编辑维护类型的权限',
@@ -1109,6 +1164,7 @@ export default {
     noPermissionRemovePrinter: '您没有移除打印机分配的权限',
     noPermissionRemovePrinter: '您没有移除打印机分配的权限',
     noPermissionAssignPrinter: '您没有分配打印机的权限',
     noPermissionAssignPrinter: '您没有分配打印机的权限',
     noPermissionEditIntervals: '您没有编辑间隔的权限',
     noPermissionEditIntervals: '您没有编辑间隔的权限',
+    // Configure link
     configureSettings: '配置维护类型和间隔',
     configureSettings: '配置维护类型和间隔',
   },
   },
 
 
@@ -1116,6 +1172,7 @@ export default {
   settings: {
   settings: {
     title: '设置',
     title: '设置',
     general: '通用',
     general: '通用',
+    // Tab names
     tabs: {
     tabs: {
       general: '通用',
       general: '通用',
       smartPlugs: '智能插座',
       smartPlugs: '智能插座',
@@ -1128,6 +1185,7 @@ export default {
       backup: '备份',
       backup: '备份',
       emailAuth: '邮箱认证',
       emailAuth: '邮箱认证',
     },
     },
+    // Email settings
     email: {
     email: {
       smtpSettings: 'SMTP 配置',
       smtpSettings: 'SMTP 配置',
       smtpHost: 'SMTP 服务器',
       smtpHost: 'SMTP 服务器',
@@ -1155,6 +1213,7 @@ export default {
       feature2: '用户可以使用用户名或邮箱登录',
       feature2: '用户可以使用用户名或邮箱登录',
       feature3: '忘记密码功能可用',
       feature3: '忘记密码功能可用',
       feature4: '管理员可以通过邮件重置用户密码',
       feature4: '管理员可以通过邮件重置用户密码',
+      // Error messages
       errors: {
       errors: {
         requiredFields: '请填写所有必填字段',
         requiredFields: '请填写所有必填字段',
         usernameRequired: '启用认证时需要用户名',
         usernameRequired: '启用认证时需要用户名',
@@ -1163,14 +1222,17 @@ export default {
         usernamePasswordRequired: '启用认证时需要用户名和密码',
         usernamePasswordRequired: '启用认证时需要用户名和密码',
         configureSmtpFirst: '请先配置并测试 SMTP 设置',
         configureSmtpFirst: '请先配置并测试 SMTP 设置',
       },
       },
+      // Success messages
       success: {
       success: {
         settingsSaved: 'SMTP 设置保存成功',
         settingsSaved: 'SMTP 设置保存成功',
       },
       },
+      // Security options
       securityOptions: {
       securityOptions: {
         starttls: 'STARTTLS(端口 587)',
         starttls: 'STARTTLS(端口 587)',
         ssl: 'SSL/TLS(端口 465)',
         ssl: 'SSL/TLS(端口 465)',
         none: '无(端口 25)',
         none: '无(端口 25)',
       },
       },
+      // Authentication options
       authOptions: {
       authOptions: {
         enabled: '已启用',
         enabled: '已启用',
         disabled: '已禁用',
         disabled: '已禁用',
@@ -1195,6 +1257,7 @@ export default {
     latestVersion: '最新版本',
     latestVersion: '最新版本',
     upToDate: '已是最新版本',
     upToDate: '已是最新版本',
     updateAvailable: '有可用更新',
     updateAvailable: '有可用更新',
+    // Notifications
     notificationLanguage: '通知语言',
     notificationLanguage: '通知语言',
     notificationLanguageDescription: '推送通知的语言',
     notificationLanguageDescription: '推送通知的语言',
     bedCooledThreshold: '热床冷却阈值',
     bedCooledThreshold: '热床冷却阈值',
@@ -1224,6 +1287,7 @@ export default {
       maintenanceDue: '维护到期',
       maintenanceDue: '维护到期',
       maintenanceDueDescription: '需要维护时通知',
       maintenanceDueDescription: '需要维护时通知',
     },
     },
+    // Smart Plugs
     smartPlug: {
     smartPlug: {
       title: '智能插座',
       title: '智能插座',
       add: '添加智能插座',
       add: '添加智能插座',
@@ -1242,6 +1306,7 @@ export default {
       turnOn: '开启',
       turnOn: '开启',
       turnOff: '关闭',
       turnOff: '关闭',
     },
     },
+    // Filament Tracking Mode
     filamentTracking: '耗材追踪',
     filamentTracking: '耗材追踪',
     filamentTrackingDesc: '选择如何追踪您的耗材。您可以使用内置库存或连接外部 Spoolman 服务器。',
     filamentTrackingDesc: '选择如何追踪您的耗材。您可以使用内置库存或连接外部 Spoolman 服务器。',
     trackingModeBuiltIn: '内置库存',
     trackingModeBuiltIn: '内置库存',
@@ -1257,6 +1322,7 @@ export default {
     amsSyncing: '同步中...',
     amsSyncing: '同步中...',
     amsSyncSuccess: '已同步 {{synced}} 个耗材,跳过 {{skipped}} 个',
     amsSyncSuccess: '已同步 {{synced}} 个耗材,跳过 {{skipped}} 个',
     amsSyncError: '从 AMS 同步重量失败',
     amsSyncError: '从 AMS 同步重量失败',
+    // Spoolman settings
     spoolmanUrl: 'Spoolman URL',
     spoolmanUrl: 'Spoolman URL',
     spoolmanUrlHint: 'Spoolman 服务器的 URL(例如 http://localhost:7912)',
     spoolmanUrlHint: 'Spoolman 服务器的 URL(例如 http://localhost:7912)',
     spoolmanConnected: '已连接',
     spoolmanConnected: '已连接',
@@ -1278,51 +1344,69 @@ export default {
     syncAmsData: '同步 AMS 数据',
     syncAmsData: '同步 AMS 数据',
     syncAmsDataDesc: '手动将打印机 AMS 数据同步到 Spoolman',
     syncAmsDataDesc: '手动将打印机 AMS 数据同步到 Spoolman',
     allPrinters: '所有打印机',
     allPrinters: '所有打印机',
+    // Default printer
     noDefaultPrinter: '无默认(每次询问)',
     noDefaultPrinter: '无默认(每次询问)',
+    // Sidebar
     sidebarOrder: '侧边栏顺序',
     sidebarOrder: '侧边栏顺序',
+    // Camera
     saveThumbnails: '保存缩略图',
     saveThumbnails: '保存缩略图',
     captureFinishPhoto: '拍摄完成照片',
     captureFinishPhoto: '拍摄完成照片',
     noPrintersConfigured: '未配置打印机',
     noPrintersConfigured: '未配置打印机',
+    // Archive settings
     archiveMode: {
     archiveMode: {
       always: '始终创建归档条目',
       always: '始终创建归档条目',
       never: '从不创建归档条目',
       never: '从不创建归档条目',
       ask: '每次询问',
       ask: '每次询问',
     },
     },
+    // Updates
     checkForUpdatesLabel: '检查更新',
     checkForUpdatesLabel: '检查更新',
     checkPrinterFirmware: '检查打印机固件',
     checkPrinterFirmware: '检查打印机固件',
     includeBetaUpdates: '包含测试版本',
     includeBetaUpdates: '包含测试版本',
     includeBetaUpdatesDesc: '检查更新时通知测试版和预发布版本',
     includeBetaUpdatesDesc: '检查更新时通知测试版和预发布版本',
+    // Queue
     enableRetry: '启用重试',
     enableRetry: '启用重试',
+    // Home Assistant
     homeAssistantDescription: '通过 Home Assistant 控制智能插座',
     homeAssistantDescription: '通过 Home Assistant 控制智能插座',
     environmentManagedLabel: '(环境变量管理)',
     environmentManagedLabel: '(环境变量管理)',
     autoEnabledViaEnv: '通过环境变量自动启用',
     autoEnabledViaEnv: '通过环境变量自动启用',
     urlFromEnvReadOnly: '值由 HA_URL 环境变量设置(只读)',
     urlFromEnvReadOnly: '值由 HA_URL 环境变量设置(只读)',
     tokenFromEnvReadOnly: '值由 HA_TOKEN 环境变量设置(只读)',
     tokenFromEnvReadOnly: '值由 HA_TOKEN 环境变量设置(只读)',
+    // MQTT
     mqttConnectedTo: '已连接到',
     mqttConnectedTo: '已连接到',
+    // Prometheus
     prometheusDescription: '以 Prometheus 格式暴露打印机数据',
     prometheusDescription: '以 Prometheus 格式暴露打印机数据',
+    // Smart plugs empty state
     noSmartPlugsTitle: '未配置智能插座',
     noSmartPlugsTitle: '未配置智能插座',
     noSmartPlugsDescription: '添加基于 Tasmota 的智能插座以追踪能耗并自动化电源控制。',
     noSmartPlugsDescription: '添加基于 Tasmota 的智能插座以追踪能耗并自动化电源控制。',
+    // Notifications empty state
     noProvidersTitle: '未配置提供商',
     noProvidersTitle: '未配置提供商',
     noProvidersDescription: '添加提供商以接收警报。',
     noProvidersDescription: '添加提供商以接收警报。',
     noTemplatesAvailable: '无可用模板。重启后端以加载默认模板。',
     noTemplatesAvailable: '无可用模板。重启后端以加载默认模板。',
+    // API permissions
     apiPermissionView: '查看打印机状态和队列',
     apiPermissionView: '查看打印机状态和队列',
     apiPermissionEdit: '添加和移除打印队列中的项目',
     apiPermissionEdit: '添加和移除打印队列中的项目',
+    // API keys
     apiKeysEmptyTitle: '无 API 密钥',
     apiKeysEmptyTitle: '无 API 密钥',
     apiKeysEmptyDescription: '创建 API 密钥以与外部服务集成。',
     apiKeysEmptyDescription: '创建 API 密钥以与外部服务集成。',
+    // Users
     noUsersFound: '未找到用户',
     noUsersFound: '未找到用户',
     noGroupsFound: '未找到组',
     noGroupsFound: '未找到组',
     noGroupsAvailable: '无可用组',
     noGroupsAvailable: '无可用组',
     passwordsDoNotMatch: '密码不匹配',
     passwordsDoNotMatch: '密码不匹配',
     systemGroupWarning: '系统组名称不可更改',
     systemGroupWarning: '系统组名称不可更改',
+    // Auth disabled
     authDisabledTitle: '身份验证已禁用',
     authDisabledTitle: '身份验证已禁用',
     authDisabledFeature1: '需要登录才能访问系统',
     authDisabledFeature1: '需要登录才能访问系统',
     authDisabledFeature2: '创建多个用户并基于组的权限管理',
     authDisabledFeature2: '创建多个用户并基于组的权限管理',
     authDisabledFeature3: '使用 50+ 个细粒度权限控制访问',
     authDisabledFeature3: '使用 50+ 个细粒度权限控制访问',
+    // User deletion
     userHasCreated: '此用户已创建:',
     userHasCreated: '此用户已创建:',
     userItemsQuestion: '您想如何处理这些项目?',
     userItemsQuestion: '您想如何处理这些项目?',
     deleteUserConfirm: '确定要删除此用户吗?',
     deleteUserConfirm: '确定要删除此用户吗?',
     actionCannotBeUndone: '此操作无法撤销。',
     actionCannotBeUndone: '此操作无法撤销。',
+    // Smart plugs
     addFirstSmartPlug: '添加您的第一个智能插座',
     addFirstSmartPlug: '添加您的第一个智能插座',
+    // Notifications
     providers: '提供商',
     providers: '提供商',
     log: '日志',
     log: '日志',
     testAll: '全部测试',
     testAll: '全部测试',
@@ -1331,6 +1415,7 @@ export default {
     testFailedCount: '{{count}} 个失败',
     testFailedCount: '{{count}} 个失败',
     messageTemplates: '消息模板',
     messageTemplates: '消息模板',
     messageTemplatesDescription: '自定义每个事件的通知消息。',
     messageTemplatesDescription: '自定义每个事件的通知消息。',
+    // API Keys section
     apiKeys: 'API 密钥',
     apiKeys: 'API 密钥',
     apiKeysDescription: '创建 API 密钥用于外部集成和 Webhook。',
     apiKeysDescription: '创建 API 密钥用于外部集成和 Webhook。',
     createKey: '创建密钥',
     createKey: '创建密钥',
@@ -1369,6 +1454,7 @@ export default {
     deleteApiKeyTitle: '删除 API 密钥',
     deleteApiKeyTitle: '删除 API 密钥',
     deleteApiKeyMessage: '确定要删除此 API 密钥吗?使用此密钥的所有集成将停止工作。',
     deleteApiKeyMessage: '确定要删除此 API 密钥吗?使用此密钥的所有集成将停止工作。',
     deleteKey: '删除密钥',
     deleteKey: '删除密钥',
+    // Filament tab
     amsDisplayThresholds: 'AMS 显示阈值',
     amsDisplayThresholds: 'AMS 显示阈值',
     amsThresholdsDescription: '配置 AMS 湿度和温度指示器的颜色阈值。',
     amsThresholdsDescription: '配置 AMS 湿度和温度指示器的颜色阈值。',
     humidity: '湿度',
     humidity: '湿度',
@@ -1384,6 +1470,7 @@ export default {
     printModal: '打印对话框',
     printModal: '打印对话框',
     expandCustomMapping: '默认展开自定义映射',
     expandCustomMapping: '默认展开自定义映射',
     expandCustomMappingDescription: '打印到多台打印机时,默认展开显示每台打印机的 AMS 映射',
     expandCustomMappingDescription: '打印到多台打印机时,默认展开显示每台打印机的 AMS 映射',
+    // User management
     authentication: '身份验证',
     authentication: '身份验证',
     authEnabledDescription: '您的实例已通过用户身份验证保护',
     authEnabledDescription: '您的实例已通过用户身份验证保护',
     authDisabledDescription: '启用以要求登录并管理用户访问',
     authDisabledDescription: '启用以要求登录并管理用户访问',
@@ -1407,21 +1494,27 @@ export default {
     enterPassword: '输入密码(至少 6 个字符)',
     enterPassword: '输入密码(至少 6 个字符)',
     confirmPassword: '确认密码',
     confirmPassword: '确认密码',
     confirmPasswordPlaceholder: '确认密码',
     confirmPasswordPlaceholder: '确认密码',
+    // Title tooltips
     viewReleaseOnGitHub: '在 GitHub 上查看发布',
     viewReleaseOnGitHub: '在 GitHub 上查看发布',
     turnAllPlugsOn: '开启所有插座',
     turnAllPlugsOn: '开启所有插座',
     turnAllPlugsOff: '关闭所有插座',
     turnAllPlugsOff: '关闭所有插座',
+    // Modal: Clear logs
     clearNotificationLogs: '清除通知日志',
     clearNotificationLogs: '清除通知日志',
     clearLogsMessage: '这将永久删除所有 30 天前的通知日志。此操作无法撤销。',
     clearLogsMessage: '这将永久删除所有 30 天前的通知日志。此操作无法撤销。',
     clearLogs: '清除日志',
     clearLogs: '清除日志',
+    // Modal: Reset UI
     resetUiPreferences: '重置 UI 偏好',
     resetUiPreferences: '重置 UI 偏好',
     resetUiPreferencesMessage: '这将重置所有 UI 偏好为默认值:侧边栏顺序、主题、仪表板布局、视图模式和排序偏好。您的打印机、归档和服务器设置不会受到影响。清除后页面将重新加载。',
     resetUiPreferencesMessage: '这将重置所有 UI 偏好为默认值:侧边栏顺序、主题、仪表板布局、视图模式和排序偏好。您的打印机、归档和服务器设置不会受到影响。清除后页面将重新加载。',
     resetPreferences: '重置偏好',
     resetPreferences: '重置偏好',
+    // Modal: Delete group
     deleteGroupTitle: '删除组',
     deleteGroupTitle: '删除组',
     deleteGroupMessage: '确定要删除此组吗?此组中的用户将失去这些权限。',
     deleteGroupMessage: '确定要删除此组吗?此组中的用户将失去这些权限。',
     deleteGroup: '删除组',
     deleteGroup: '删除组',
+    // Modal: Disable auth
     disableAuthenticationTitle: '禁用身份验证',
     disableAuthenticationTitle: '禁用身份验证',
     disableAuthenticationMessage: '确定要禁用身份验证吗?这将使您的 Bambuddy 实例无需登录即可访问。所有用户将保留在数据库中但身份验证将被禁用。',
     disableAuthenticationMessage: '确定要禁用身份验证吗?这将使您的 Bambuddy 实例无需登录即可访问。所有用户将保留在数据库中但身份验证将被禁用。',
     disableAuthentication: '禁用身份验证',
     disableAuthentication: '禁用身份验证',
+    // Additional settings
     configureBambuddy: '配置 Bambuddy',
     configureBambuddy: '配置 Bambuddy',
     systemDefault: '系统默认',
     systemDefault: '系统默认',
     archiveSettings: '归档设置',
     archiveSettings: '归档设置',
@@ -1452,6 +1545,7 @@ export default {
     editUser: '编辑用户',
     editUser: '编辑用户',
     deleteUserTitle: '删除用户',
     deleteUserTitle: '删除用户',
     groupName: '组名称',
     groupName: '组名称',
+    // Placeholders
     leaveEmptyForAnonymous: '留空为匿名',
     leaveEmptyForAnonymous: '留空为匿名',
     leaveEmptyForNoAuth: '留空为无认证',
     leaveEmptyForNoAuth: '留空为无认证',
     enterNewPassword: '输入新密码',
     enterNewPassword: '输入新密码',
@@ -1648,7 +1742,7 @@ export default {
     all: '全部',
     all: '全部',
   },
   },
 
 
-  // Printer File Manager modal
+  // Printer File Manager modal (printer internal storage)
   printerFiles: {
   printerFiles: {
     title: '文件管理器',
     title: '文件管理器',
     storageUsed: '已用:',
     storageUsed: '已用:',
@@ -2035,16 +2129,19 @@ export default {
       customizeSettings: '自定义新预设的设置',
       customizeSettings: '自定义新预设的设置',
       compareWithBase: '与基础预设比较',
       compareWithBase: '与基础预设比较',
       compare: '比较',
       compare: '比较',
+      // CreatePresetModal - Basic Info
       basePreset: '基础预设',
       basePreset: '基础预设',
       selectBasePreset: '选择基础预设...',
       selectBasePreset: '选择基础预设...',
       presetName: '预设名称',
       presetName: '预设名称',
       myCustomPreset: '我的自定义预设',
       myCustomPreset: '我的自定义预设',
       inheritsFrom: '继承自',
       inheritsFrom: '继承自',
       dropJsonToImport: '拖放 JSON 以导入',
       dropJsonToImport: '拖放 JSON 以导入',
+      // CreatePresetModal - Tabs
       tabs: {
       tabs: {
         common: '常用',
         common: '常用',
         allFields: '所有字段',
         allFields: '所有字段',
       },
       },
+      // CreatePresetModal - All Fields Tab
       availableFields: '可用字段',
       availableFields: '可用字段',
       searchFieldsPlaceholder: '搜索字段...',
       searchFieldsPlaceholder: '搜索字段...',
       noMatchingFields: '没有匹配的字段',
       noMatchingFields: '没有匹配的字段',
@@ -2062,15 +2159,18 @@ export default {
       refresh: '刷新',
       refresh: '刷新',
       newPreset: '新建预设',
       newPreset: '新建预设',
       clearFilters: '清除筛选',
       clearFilters: '清除筛选',
+      // Compare mode
       compareMode: '比较模式',
       compareMode: '比较模式',
       selectAnotherPreset: '选择另一个 {{type}} 预设',
       selectAnotherPreset: '选择另一个 {{type}} 预设',
       clickTwoPresets: '点击两个相同类型的预设进行比较',
       clickTwoPresets: '点击两个相同类型的预设进行比较',
       selectFirst: '1. 选择第一个',
       selectFirst: '1. 选择第一个',
       selectSecond: '2. 选择第二个',
       selectSecond: '2. 选择第二个',
       compareNow: '立即比较',
       compareNow: '立即比较',
+      // Status row
       lastSynced: '上次同步:',
       lastSynced: '上次同步:',
       showingCount: '显示 {{showing}} / {{total}} 个预设',
       showingCount: '显示 {{showing}} / {{total}} 个预设',
       noPresetsFound: '未找到预设',
       noPresetsFound: '未找到预设',
+      // Column headers
       columns: {
       columns: {
         filament: '耗材',
         filament: '耗材',
         process: '工艺',
         process: '工艺',
@@ -2079,6 +2179,7 @@ export default {
       noFilamentPresets: '无耗材预设',
       noFilamentPresets: '无耗材预设',
       noProcessPresets: '无工艺预设',
       noProcessPresets: '无工艺预设',
       noPrinterPresets: '无打印机预设',
       noPrinterPresets: '无打印机预设',
+      // Filters
       filters: {
       filters: {
         type: '类型',
         type: '类型',
         owner: '所有者',
         owner: '所有者',
@@ -2091,6 +2192,7 @@ export default {
         builtIn: '内置',
         builtIn: '内置',
         process: '工艺',
         process: '工艺',
       },
       },
+      // Permissions
       noTemplatesPermission: '您没有管理模板的权限',
       noTemplatesPermission: '您没有管理模板的权限',
       noRefreshPermission: '您没有刷新配置文件的权限',
       noRefreshPermission: '您没有刷新配置文件的权限',
       noCreatePermission: '您没有创建预设的权限',
       noCreatePermission: '您没有创建预设的权限',
@@ -2170,6 +2272,7 @@ export default {
     filesExtracted: '已解压 {{count}} 个文件',
     filesExtracted: '已解压 {{count}} 个文件',
     uploadComplete: '上传完成:{{succeeded}} 个成功',
     uploadComplete: '上传完成:{{succeeded}} 个成功',
     uploadFailed: '{{count}} 个失败',
     uploadFailed: '{{count}} 个失败',
+    zipFilesFailed: '{{count}} 个文件失败',
     uploading: '上传中...',
     uploading: '上传中...',
     changeLink: '更改链接...',
     changeLink: '更改链接...',
     linkTo: '链接到...',
     linkTo: '链接到...',
@@ -2278,6 +2381,7 @@ export default {
     addFiles: '添加文件',
     addFiles: '添加文件',
     removeFile: '移除文件',
     removeFile: '移除文件',
     viewDetails: '查看详情',
     viewDetails: '查看详情',
+    // Modal fields
     namePlaceholder: '例如:Voron 2.4 构建',
     namePlaceholder: '例如:Voron 2.4 构建',
     descriptionPlaceholder: '可选描述...',
     descriptionPlaceholder: '可选描述...',
     color: '颜色',
     color: '颜色',
@@ -2295,6 +2399,7 @@ export default {
     priorityNormal: '普通',
     priorityNormal: '普通',
     priorityHigh: '高',
     priorityHigh: '高',
     priorityUrgent: '紧急',
     priorityUrgent: '紧急',
+    // Status
     statusActive: '进行中',
     statusActive: '进行中',
     statusCompleted: '已完成',
     statusCompleted: '已完成',
     statusArchived: '已归档',
     statusArchived: '已归档',
@@ -2303,19 +2408,23 @@ export default {
     failed: '失败',
     failed: '失败',
     inQueue: '队列中',
     inQueue: '队列中',
     noPrintsYet: '暂无打印',
     noPrintsYet: '暂无打印',
+    // Footer stats
     printJobs: '打印任务(板)',
     printJobs: '打印任务(板)',
     partsPrinted: '已打印零件',
     partsPrinted: '已打印零件',
     failedParts: '失败零件',
     failedParts: '失败零件',
+    // Actions
     import: '导入',
     import: '导入',
     export: '导出',
     export: '导出',
     importProject: '导入项目',
     importProject: '导入项目',
     exportAll: '导出所有项目',
     exportAll: '导出所有项目',
     loading: '加载项目中...',
     loading: '加载项目中...',
+    // Permissions
     noEditPermission: '您没有编辑项目的权限',
     noEditPermission: '您没有编辑项目的权限',
     noDeletePermission: '您没有删除项目的权限',
     noDeletePermission: '您没有删除项目的权限',
     noCreatePermission: '您没有创建项目的权限',
     noCreatePermission: '您没有创建项目的权限',
     noImportPermission: '您没有导入项目的权限',
     noImportPermission: '您没有导入项目的权限',
     noExportPermission: '您没有导出项目的权限',
     noExportPermission: '您没有导出项目的权限',
+    // Toast
     toast: {
     toast: {
       created: '项目已创建',
       created: '项目已创建',
       updated: '项目已更新',
       updated: '项目已更新',
@@ -2572,13 +2681,16 @@ export default {
     deleteConfirm: '确定要删除此耗材吗?此操作无法撤销。',
     deleteConfirm: '确定要删除此耗材吗?此操作无法撤销。',
     archiveConfirm: '确定要归档此耗材吗?',
     archiveConfirm: '确定要归档此耗材吗?',
     advancedSettings: '高级设置',
     advancedSettings: '高级设置',
+    // Tabs
     filamentInfoTab: '耗材信息',
     filamentInfoTab: '耗材信息',
     paProfileTab: 'PA 配置',
     paProfileTab: 'PA 配置',
     filamentInfo: '耗材',
     filamentInfo: '耗材',
     additional: '附加',
     additional: '附加',
+    // Cloud
     loadingPresets: '加载云端预设中...',
     loadingPresets: '加载云端预设中...',
     cloudConnected: '云端已连接',
     cloudConnected: '云端已连接',
     cloudNotConnected: '云端未连接(使用默认值)',
     cloudNotConnected: '云端未连接(使用默认值)',
+    // Colors
     recentColors: '最近',
     recentColors: '最近',
     searchColors: '搜索颜色...',
     searchColors: '搜索颜色...',
     searchResults: '搜索结果',
     searchResults: '搜索结果',
@@ -2588,6 +2700,7 @@ export default {
     showAll: '显示全部',
     showAll: '显示全部',
     noColorsFound: '没有颜色匹配您的搜索',
     noColorsFound: '没有颜色匹配您的搜索',
     noResults: '未找到匹配项',
     noResults: '未找到匹配项',
+    // PA Profiles
     selectMaterialFirst: '请先在耗材信息选项卡中选择材料。',
     selectMaterialFirst: '请先在耗材信息选项卡中选择材料。',
     noPrintersConfigured: '未配置打印机。添加打印机以使用 PA 配置。',
     noPrintersConfigured: '未配置打印机。添加打印机以使用 PA 配置。',
     matchingFilter: '匹配',
     matchingFilter: '匹配',
@@ -2604,6 +2717,7 @@ export default {
     leftNozzle: '左喷嘴',
     leftNozzle: '左喷嘴',
     rightNozzle: '右喷嘴',
     rightNozzle: '右喷嘴',
     profilesSelected: '个校准配置已选择',
     profilesSelected: '个校准配置已选择',
+    // Stats & enhanced table
     totalInventory: '总库存',
     totalInventory: '总库存',
     totalConsumed: '总消耗',
     totalConsumed: '总消耗',
     byMaterial: '按材料',
     byMaterial: '按材料',
@@ -2612,7 +2726,6 @@ export default {
     sinceTracking: '自开始追踪',
     sinceTracking: '自开始追踪',
     loadedInAms: '已装载到 AMS/外置',
     loadedInAms: '已装载到 AMS/外置',
     remaining: '剩余',
     remaining: '剩余',
-    lowStockThreshold: '剩余 <20%',
     weightCheck: '重量检查',
     weightCheck: '重量检查',
     lastWeighed: '上次称量',
     lastWeighed: '上次称量',
     neverWeighed: '从未称量',
     neverWeighed: '从未称量',
@@ -2635,9 +2748,11 @@ export default {
     table: '表格',
     table: '表格',
     cards: '卡片',
     cards: '卡片',
     net: '净重',
     net: '净重',
+    // Grouping
     groupSimilar: '分组',
     groupSimilar: '分组',
     groupedSpools: '{{count}} 个相同耗材',
     groupedSpools: '{{count}} 个相同耗材',
     groupedRows: '行',
     groupedRows: '行',
+    // Column config
     columns: '列',
     columns: '列',
     configureColumns: '配置列',
     configureColumns: '配置列',
     configureColumnsDesc: '拖动以重新排序列或使用箭头。使用眼睛图标切换可见性。',
     configureColumnsDesc: '拖动以重新排序列或使用箭头。使用眼睛图标切换可见性。',
@@ -2649,11 +2764,13 @@ export default {
     moveDown: '下移',
     moveDown: '下移',
     hideColumn: '隐藏列',
     hideColumn: '隐藏列',
     showColumn: '显示列',
     showColumn: '显示列',
+    // Tag linking
     linkToSpool: '链接到耗材',
     linkToSpool: '链接到耗材',
     tagLinked: '标签已链接到耗材',
     tagLinked: '标签已链接到耗材',
     tagLinkFailed: '链接标签失败',
     tagLinkFailed: '链接标签失败',
     tagAlreadyLinked: '标签已链接到其他耗材',
     tagAlreadyLinked: '标签已链接到其他耗材',
     unknownTag: '检测到未知 RFID 标签',
     unknownTag: '检测到未知 RFID 标签',
+    // Usage history
     usageHistory: '使用历史',
     usageHistory: '使用历史',
     noUsageHistory: '暂无使用记录',
     noUsageHistory: '暂无使用记录',
     printName: '打印名称',
     printName: '打印名称',
@@ -2661,6 +2778,7 @@ export default {
     clearHistory: '清除',
     clearHistory: '清除',
     historyCleared: '使用历史已清除',
     historyCleared: '使用历史已清除',
     fillSourceLabel: '(库存)',
     fillSourceLabel: '(库存)',
+    lowStockThresholdError: '阈值必须在 0.1 到 99.9 之间',
   },
   },
 
 
   // Timelapse
   // Timelapse
@@ -2783,6 +2901,7 @@ export default {
     uploadFailed: '上传失败',
     uploadFailed: '上传失败',
   },
   },
 
 
+  // Edit archive modal
   // Edit Archive Modal
   // Edit Archive Modal
   editArchive: {
   editArchive: {
     title: '编辑归档',
     title: '编辑归档',
@@ -2812,6 +2931,7 @@ export default {
     photosHelp: '点击 + 添加打印成品照片',
     photosHelp: '点击 + 添加打印成品照片',
     printResult: '打印成品',
     printResult: '打印成品',
     saving: '保存中...',
     saving: '保存中...',
+    // Failure reasons
     failureReasons: {
     failureReasons: {
       adhesionFailure: '附着力失败',
       adhesionFailure: '附着力失败',
       spaghettiDetached: '拉丝 / 脱落',
       spaghettiDetached: '拉丝 / 脱落',
@@ -2825,6 +2945,7 @@ export default {
       userCancelled: '用户取消',
       userCancelled: '用户取消',
       other: '其他',
       other: '其他',
     },
     },
+    // Archive statuses
     statuses: {
     statuses: {
       completed: '已完成',
       completed: '已完成',
       failed: '失败',
       failed: '失败',
@@ -2848,6 +2969,7 @@ export default {
     noKProfiles: '无 K 值配置',
     noKProfiles: '无 K 值配置',
     noKProfilesDesc: '未找到 {{diameter}}mm 喷嘴的压力推进配置',
     noKProfilesDesc: '未找到 {{diameter}}mm 喷嘴的压力推进配置',
     createFirstProfile: '创建第一个配置',
     createFirstProfile: '创建第一个配置',
+    // Controls
     printer: '打印机',
     printer: '打印机',
     nozzle: '喷嘴',
     nozzle: '喷嘴',
     refresh: '刷新',
     refresh: '刷新',
@@ -2857,6 +2979,7 @@ export default {
     select: '选择',
     select: '选择',
     selectAll: '全选',
     selectAll: '全选',
     delete: '删除',
     delete: '删除',
+    // Filters
     searchPlaceholder: '按名称或耗材搜索...',
     searchPlaceholder: '按名称或耗材搜索...',
     allExtruders: '所有挤出机',
     allExtruders: '所有挤出机',
     leftOnly: '仅左侧',
     leftOnly: '仅左侧',
@@ -2867,8 +2990,10 @@ export default {
     sortName: '排序:名称',
     sortName: '排序:名称',
     sortKValue: '排序:K 值',
     sortKValue: '排序:K 值',
     sortFilament: '排序:耗材',
     sortFilament: '排序:耗材',
+    // Dual extruder labels
     leftExtruder: '左挤出机',
     leftExtruder: '左挤出机',
     rightExtruder: '右挤出机',
     rightExtruder: '右挤出机',
+    // Modal
     modal: {
     modal: {
       addTitle: '添加 K 值配置',
       addTitle: '添加 K 值配置',
       editTitle: '编辑 K 值配置',
       editTitle: '编辑 K 值配置',
@@ -2895,16 +3020,19 @@ export default {
       savingExtruder: '保存到挤出机 {{current}}/{{total}}...',
       savingExtruder: '保存到挤出机 {{current}}/{{total}}...',
       pleaseWait: '请稍候',
       pleaseWait: '请稍候',
     },
     },
+    // Delete confirmation
     deleteConfirm: {
     deleteConfirm: {
       title: '删除配置',
       title: '删除配置',
       cannotUndo: '此操作无法撤销',
       cannotUndo: '此操作无法撤销',
       message: '确定要从打印机删除"{{name}}"吗?',
       message: '确定要从打印机删除"{{name}}"吗?',
     },
     },
+    // Bulk delete
     bulkDelete: {
     bulkDelete: {
       title: '删除配置',
       title: '删除配置',
       cannotUndo: '此操作无法撤销',
       cannotUndo: '此操作无法撤销',
       message: '确定要从打印机删除 {{count}} 个选中的配置吗?',
       message: '确定要从打印机删除 {{count}} 个选中的配置吗?',
     },
     },
+    // Toast
     toast: {
     toast: {
       profileSaved: 'K 值配置已保存',
       profileSaved: 'K 值配置已保存',
       profilesSaved: 'K 值配置已保存到 {{count}} 个挤出机',
       profilesSaved: 'K 值配置已保存到 {{count}} 个挤出机',
@@ -2920,6 +3048,7 @@ export default {
       noteSaved: '备注已保存',
       noteSaved: '备注已保存',
       failedToSaveNote: '保存备注失败',
       failedToSaveNote: '保存备注失败',
     },
     },
+    // Permissions
     permission: {
     permission: {
       noRead: '您没有刷新配置的权限',
       noRead: '您没有刷新配置的权限',
       noCreate: '您没有添加配置的权限',
       noCreate: '您没有添加配置的权限',
@@ -3080,7 +3209,7 @@ export default {
     },
     },
   },
   },
 
 
-  // Maintenance type descriptions
+  // Maintenance type descriptions (built-in)
   maintenanceDescriptions: {
   maintenanceDescriptions: {
     lubricateCarbonRods: '在碳纤维杆上涂抹润滑剂以确保顺畅运动',
     lubricateCarbonRods: '在碳纤维杆上涂抹润滑剂以确保顺畅运动',
     lubricateRails: '在线性导轨上涂抹润滑剂以确保顺畅运动',
     lubricateRails: '在线性导轨上涂抹润滑剂以确保顺畅运动',
@@ -3579,10 +3708,12 @@ export default {
       addSpool: '添加耗材',
       addSpool: '添加耗材',
     },
     },
     settings: {
     settings: {
+      // Tabs
       tabDevice: '设备',
       tabDevice: '设备',
       tabDisplay: '显示',
       tabDisplay: '显示',
       tabScale: '秤',
       tabScale: '秤',
       tabUpdates: '更新',
       tabUpdates: '更新',
+      // Device tab
       nfcReader: 'NFC 读卡器',
       nfcReader: 'NFC 读卡器',
       type: '类型',
       type: '类型',
       connection: '连接',
       connection: '连接',
@@ -3590,12 +3721,14 @@ export default {
       deviceInfo: '设备信息',
       deviceInfo: '设备信息',
       hostname: '主机',
       hostname: '主机',
       uptime: '运行时间',
       uptime: '运行时间',
+      // Display tab
       brightness: '亮度',
       brightness: '亮度',
       saved: '已保存',
       saved: '已保存',
       noBacklight: '未检测到 DSI 背光。亮度控制需要 DSI 显示屏。',
       noBacklight: '未检测到 DSI 背光。亮度控制需要 DSI 显示屏。',
       screenBlank: '屏幕熄灭超时',
       screenBlank: '屏幕熄灭超时',
       screenBlankDesc: '不活动后屏幕关闭。触摸唤醒。',
       screenBlankDesc: '不活动后屏幕关闭。触摸唤醒。',
       displayNote: '亮度作为软件滤镜应用。',
       displayNote: '亮度作为软件滤镜应用。',
+      // Scale tab
       scaleCalibration: '秤校准',
       scaleCalibration: '秤校准',
       currentWeight: '当前重量',
       currentWeight: '当前重量',
       tareOffset: '去皮',
       tareOffset: '去皮',
@@ -3617,6 +3750,7 @@ export default {
       firmware: '固件',
       firmware: '固件',
       scale: '秤',
       scale: '秤',
       noDevice: '未找到 SpoolBuddy 设备',
       noDevice: '未找到 SpoolBuddy 设备',
+      // Updates tab
       daemonVersion: '守护进程版本',
       daemonVersion: '守护进程版本',
       currentVersion: '当前',
       currentVersion: '当前',
       versionPending: '等待守护进程...',
       versionPending: '等待守护进程...',

Some files were not shown because too many files changed in this diff