From 3291e8c6f9bbcab6b37c6eeac719ce2d62d17b33 Mon Sep 17 00:00:00 2001 From: Wesley Silva Date: Tue, 17 Feb 2026 19:49:08 +0000 Subject: [PATCH] Added translation to Brazilian Portuguese on existing strings. --- CONTRIBUTING.md | 1 + frontend/src/i18n/index.ts | 5 +- frontend/src/i18n/locales/pt-BR.ts | 3442 ++++++++++++++++++++++++++++ 3 files changed, 3447 insertions(+), 1 deletion(-) create mode 100644 frontend/src/i18n/locales/pt-BR.ts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c3a92023e..2dcb7ad16 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -168,6 +168,7 @@ Translations live in `frontend/src/i18n/locales/`: | `de.ts` | German | | `fr.ts` | French | | `ja.ts` | Japanese | +| `pt-BR.ts` | Brazilian Portguese | ### Adding New Strings diff --git a/frontend/src/i18n/index.ts b/frontend/src/i18n/index.ts index a16b4f24b..b961913ca 100644 --- a/frontend/src/i18n/index.ts +++ b/frontend/src/i18n/index.ts @@ -8,6 +8,7 @@ import de from './locales/de'; import fr from './locales/fr'; import ja from './locales/ja'; import it from './locales/it'; +import ptBR from './locales/pt-BR'; const resources = { en: { translation: en }, @@ -15,6 +16,7 @@ const resources = { fr: { translation: fr }, ja: { translation: ja }, it: { translation: it }, + 'pt-BR': { translation: ptBR }, }; i18n @@ -23,7 +25,7 @@ i18n .init({ resources, fallbackLng: 'en', - supportedLngs: ['en', 'de', 'fr', 'ja', 'it'], + supportedLngs: ['en', 'de', 'fr', 'ja', 'it', 'pt-BR'], detection: { // Order of detection methods @@ -52,4 +54,5 @@ export const availableLanguages = [ { code: 'fr', name: 'French', nativeName: 'Français' }, { code: 'ja', name: 'Japanese', nativeName: '日本語' }, { code: 'it', name: 'Italian', nativeName: 'Italiano' }, + { code: 'pt-BR', name: 'Portuguese (Brazil)', nativeName: 'Português (Brasil)' }, ]; diff --git a/frontend/src/i18n/locales/pt-BR.ts b/frontend/src/i18n/locales/pt-BR.ts new file mode 100644 index 000000000..9bf280604 --- /dev/null +++ b/frontend/src/i18n/locales/pt-BR.ts @@ -0,0 +1,3442 @@ +export default { + // Navigation + nav: { + printers: 'Impressoras', + archives: 'Arquivos', + queue: 'Fila', + stats: 'Estatísticas', + profiles: 'Perfis', + maintenance: 'Manutenção', + projects: 'Projetos', + inventory: 'Inventário', + files: 'Gerenciador de Arquivos', + settings: 'Configurações', + system: 'Sistema', + collapseSidebar: 'Recolher barra lateral', + expandSidebar: 'Expandir barra lateral', + update: 'Atualizar', + updateAvailable: 'Atualização disponível: v{{version}}', + updateAvailableBanner: 'Versão {{version}} está disponível!', + viewUpdate: 'Ver atualização', + viewOnGithub: 'Ver no GitHub', + keyboardShortcuts: 'Atalhos de teclado (?)', + switchToLight: 'Mudar para modo claro', + switchToDark: 'Mudar para modo escuro', + smartSwitches: 'Interruptores inteligentes', + logout: 'Sair', + }, + + // Common + common: { + save: 'Salvar', + saving: 'Salvando...', + cancel: 'Cancelar', + delete: 'Excluir', + edit: 'Editar', + add: 'Adicionar', + close: 'Fechar', + confirm: 'Confirmar', + loading: 'Carregando...', + error: 'Erro', + success: 'Sucesso', + warning: 'Aviso', + enabled: 'Ativado', + disabled: 'Desativado', + yes: 'Sim', + no: 'ão', + on: 'Ligado', + off: 'Desligado', + all: 'Todos', + none: 'Nenhum', + search: 'Pesquisar', + filter: 'Filtrar', + sort: 'Ordenar', + refresh: 'Atualizar', + download: 'Baixar', + upload: 'Enviar', + actions: 'Ações', + status: 'Status', + name: 'Nome', + description: 'Descrição', + date: 'Data', + time: 'Hora', + hours: 'Horas', + minutes: 'Minutos', + seconds: 'Segundos', + days: 'Dias', + enable: 'Ativar', + disable: 'Desativar', + permissions: 'Permissões', + noPrinters: 'Nenhuma impressora configurada', + noData: 'Nenhum dado disponível', + linkNotFound: 'Link não encontrado', + required: 'Obrigatório', + optional: 'Opcional', + dismiss: 'Dispensar', + apply: 'Aplicar', + reset: 'Redefinir', + export: 'Exportar', + import: 'Importar', + clear: 'Limpar', + selectAll: 'Selecionar tudo', + deselectAll: 'Desmarcar tudo', + noChange: '— Sem alterações —', + unchanged: 'Inalterado', + unassigned: 'Não atribuído', + unknown: 'Desconhecido', + unknownError: 'Erro desconhecido', + today: 'Hoje', + tomorrow: 'Amanhã', + asap: 'O mais rápido possível', + overdue: 'Atrasado', + now: 'Agora', + collapse: 'Recolher', + expand: 'Expandir', + viewArchive: 'Ver arquivo', + viewInFileManager: 'Ver no Gerenciador de Arquivos', + addedBy: 'Adicionado por {{username}}', + prints: 'impressões', + more: '+{{count}} mais', + ascending: 'Crescente', + descending: 'Decrescente', + printer: 'Impressora', + remove: 'Remover', + type: 'Tipo', + print: 'Imprimir', + rename: 'Renomear', + move: 'Mover', + create: 'Criar', + duplicate: 'Duplicar', + left: 'Esquerda', + right: 'Direita', + }, + + // Printers page + printers: { + title: 'Impressoras', + addPrinter: 'Adicionar Impressora', + editPrinter: 'Editar Impressora', + deletePrinter: 'Excluir Impressora', + printerName: 'Nome da Impressora', + serialNumber: 'Número de Série', + ipAddress: 'Endereço IP / Nome do Host', + accessCode: 'Código de Acesso', + model: 'Modelo', + nozzleCount: 'Número de Bicos', + autoArchive: 'Arquivamento Automático', + status: { + available: 'Disponível', + idle: 'Ocioso', + printing: 'Imprimindo', + paused: 'Pausado', + offline: 'Offline', + error: 'Erro', + finished: 'Concluído', + unknown: 'Desconhecido', + }, + temperatures: { + nozzle: 'Bico', + bed: 'Cama', + chamber: 'Câmara', + }, + progress: '{{percent}}% concluído', + timeRemaining: '{{time}} restante', + deleteConfirm: 'Tem certeza de que deseja excluir "{{name}}"?', + maintenanceOk: 'Manutenção OK', + maintenanceWarning: '{{count}} aviso', + maintenanceWarning_plural: '{{count}} avisos', + maintenanceDue: '{{count}} devido', + maintenanceDue_plural: '{{count}} devido', + // Sort options + sort: { + name: 'Nome', + status: 'Status', + model: 'Modelo', + location: 'Localização', + ascending: 'Ordem crescente', + descending: 'Ordem decrescente', + }, + // Card size + cardSize: { + small: 'Cartões pequenos', + medium: 'Cartões médios', + large: 'Cartões grandes', + extraLarge: 'Cartões extra grandes', + }, + // Controls + hideOffline: 'Ocultar offline', + nextAvailable: 'Próximo disponível', + powerOn: 'Ligar', + offlinePrintersWithPlugs: 'Impressoras offline com tomadas inteligentes', + noPrintersConfigured: 'Nenhuma impressora configurada ainda', + // Printer card + readyToPrint: 'Pronto para imprimir', + external: 'Externo', + extL: 'Ext-L', + extR: 'Ext-R', + deleteArchives: 'Excluir arquivos de impressão', + noLabel: 'Sem etiqueta', + printPreview: 'Pré-visualização de impressão', + width: 'Largura', + height: 'Altura', + noObjectsFound: 'Nenhum objeto encontrado', + objectsLoadedOnPrintStart: 'Objetos são carregados quando uma impressão começa', + willBeSkipped: 'Será ignorado', + name: 'Nome', + serialCannotBeChanged: 'Número de série não pode ser alterado', + locationHelp: 'Usado para agrupar impressoras e filtrar trabalhos na fila', + // WiFi signal strength + wifiSignal: { + veryWeak: 'Muito fraco', + weak: 'Fraco', + fair: 'Regular', + good: 'Bom', + excellent: 'Excelente', + }, + // Maintenance + maintenanceUpToDate: 'Toda a manutenção está em dia - Clique para ver', + // Chamber light + chamberLightOn: 'Ligar luz da câmara', + chamberLightOff: 'Desligar luz da câmara', + // Files + browseFiles: 'Procurar arquivos da impressora', + // Smart plug + autoOffAfterPrint: 'Desligamento automático após impressão', + autoOffExecuted: 'Desligamento automático executado - ligue a impressora para reiniciar', + // HMS errors + hmsErrors: 'Erros HMS', + viewHmsErrors: 'Ver {{count}} erro(s) HMS', + // Actions + resume: 'Retomar', + pause: 'Pausar', + stop: 'Parar', + camera: 'âmera', + skipObject: 'Ignorar objeto', + reconnect: 'Reconectar', + mqttDebug: 'Depuração MQTT', + activeNozzle: 'Ativo: {{nozzle}} bico', + nozzleRack: 'Suporte de bicos', + nozzleDocked: 'Acoplado', + nozzleMounted: 'Montado', + nozzleActive: 'Ativo', + nozzleIdle: 'Ocioso', + nozzleDiameter: 'Diâmetro', + nozzleType: 'Tipo', + nozzleStatus: 'Status', + nozzleFilament: 'Filamento', + nozzleWear: 'Desgaste', + nozzleMaxTemp: 'Temp Máx', + nozzleSerial: 'Serial', + nozzleHardenedSteel: 'Aço Endurecido', + nozzleStainlessSteel: 'Aço Inoxidável', + nozzleTungstenCarbide: 'Carboneto de Tungstênio', + nozzleFlow: 'Fluxo', + nozzleHighFlow: 'Alto Fluxo', + nozzleStandardFlow: 'Fluxo Padrão', + // Firmware + firmwareUpdate: 'Atualização de Firmware', + firmwareInstructions: 'No visor da impressora, vá para', + firmwareNav: 'Navegar para', + settings: 'Configurações', + firmware: 'Firmware', + // Discovery + discoverPrinters: 'Descobrir Impressoras', + searching: 'Procurando...', + manualEntry: 'Entrada Manual', + addFromCloud: 'Adicionar da Nuvem', + // Toast messages + toast: { + printerDeleted: 'Impressora excluída', + printerAdded: 'Impressora adicionada', + printerUpdated: 'Impressora atualizada', + failedToDelete: 'Falha ao excluir impressora', + failedToAdd: 'Falha ao adicionar impressora', + failedToUpdate: 'Falha ao atualizar impressora', + commandSent: 'Comando enviado', + failedToSendCommand: 'Falha ao enviar comando', + turnedOn: '{{name}} ligado', + failedToPowerOn: 'Falha ao ligar {{name}}', + scriptTriggered: 'Script acionado', + printStopped: 'Impressão parada', + printPaused: 'Impressão pausada', + printResumed: 'Impressão retomada', + referenceDeleted: 'Referência excluída', + detectionAreaSaved: 'Área de detecção salva', + failedToRunScript: 'Falha ao executar script', + failedToStopPrint: 'Falha ao parar impressão', + failedToPausePrint: 'Falha ao pausar impressão', + failedToResumePrint: 'Falha ao retomar impressão', + failedToControlChamberLight: 'Falha ao controlar a luz da câmara', + failedToUpdateSetting: 'Falha ao atualizar configuração', + failedToSkipObjects: 'Falha ao ignorar objetos', + failedToRereadRfid: 'Falha ao reler RFID', + failedToCheckPlate: 'Falha ao verificar a placa', + failedToUpdateLabel: 'Falha ao atualizar etiqueta', + failedToDeleteReference: 'Falha ao excluir referência', + failedToSaveDetectionArea: 'Falha ao salvar área de detecção', + plateCheckEnabled: 'Verificação da placa ativada', + plateCheckDisabled: 'Verificação da placa desativada', + calibrationSaved: 'Calibração salva!', + calibrationFailed: 'Falha na calibração', + rfidRereadInitiated: 'Releitura de RFID iniciada', + }, + // Connection status + connection: { + connected: 'Conectado', + offline: 'Offline', + }, + // Queue info + queue: { + inQueue: '{{count}} impressão na fila', + inQueue_plural: '{{count}} impressões na fila', + }, + // Controls section + controls: 'Controles', + // RFID + rfid: { + reread: 'Releitura de RFID', + }, + // Permissions + permission: { + noAdd: 'Você não tem permissão para adicionar impressoras', + noEdit: 'Você não tem permissão para editar impressoras', + noDelete: 'Você não tem permissão para excluir impressoras', + noControl: 'Você não tem permissão para controlar impressoras', + noFiles: 'Você não tem permissão para acessar arquivos de impressora', + noAmsRfid: 'Você não tem permissão para reler RFID AMS', + noSmartPlugControl: 'Você não tem permissão para controlar tomadas inteligentes', + }, + // Add/Edit modal + modal: { + addTitle: 'Adicionar Impressora', + editTitle: 'Editar Impressora', + myPrinter: 'Minha Impressora', + selectModel: 'Selecionar modelo...', + locationGroup: 'Localização / Grupo (opcional)', + locationPlaceholder: 'ex.: Oficina, Escritório, Porão', + autoArchiveLabel: 'Arquivar automaticamente impressões concluídas', + fromPrinterSettings: 'A partir das configurações da impressora', + modelOptional: 'Modelo (opcional)', + saveChanges: 'Salvar alterações', + }, + // Skip objects + skipObjects: { + tooltip: 'Ignorar objetos', + onlyWhilePrinting: 'Ignorar objetos (apenas durante a impressão)', + requiresMultiple: 'Ignorar objetos (requer 2+ objetos)', + title: 'Ignorar Objetos', + matchIdsInfo: 'Correspondência de IDs com o display da sua impressora', + printerShowsIds: 'A tela da impressora mostra os IDs dos objetos na placa de construção', + skipSelected: 'Ignorar Selecionados', + skipping: 'Ignorando...', + noObjectsSelected: 'Nenhum objeto selecionado', + selectObjectsToSkip: 'Selecione os objetos que deseja ignorar na impressão atual', + skipped: 'Ignorado', + objectsSkipped: 'Objetos ignorados', + activeCount: '{{count}} ativo', + waitForLayer: 'Aguarde a camada 2+ para ignorar objetos (atualmente na camada {{layer}})', + skip: 'Ignorar', + confirmTitle: 'Ignorar Objeto?', + confirmMessage: 'Tem certeza de que deseja ignorar "{{name}}"? Isso não pode ser desfeito.', + }, + // Confirm modals + confirm: { + deleteTitle: 'Excluir Impressora', + deleteMessage: 'Tem certeza de que deseja excluir "{{name}}"? Isso removerá todas as configurações de conexão.', + deleteArchivesNote: 'Todo o histórico de impressão desta impressora será permanentemente excluído.', + keepArchivesNote: 'O histórico de impressão será mantido, mas não estará mais associado a esta impressora.', + stopTitle: 'Parar Impressão', + stopMessage: 'Tem certeza de que deseja parar a impressão atual em "{{name}}"? Isso cancelará o trabalho de impressão.', + stopButton: 'Parar Impressão', + pauseTitle: 'Pausar Impressão', + pauseMessage: 'Tem certeza de que deseja pausar a impressão atual em "{{name}}"?', + pauseButton: 'Pausar Impressão', + resumeTitle: 'Retomar Impressão', + resumeMessage: 'Tem certeza de que deseja retomar a impressão em "{{name}}"?', + resumeButton: 'Retomar Impressão', + powerOnTitle: 'Ligar Impressora', + powerOnMessage: 'Tem certeza de que deseja ligar a impressora "{{name}}"?', + powerOnButton: 'Ligar', + powerOffTitle: 'Desligar Impressora', + powerOffMessage: 'Tem certeza de que deseja desligar a impressora "{{name}}"?', + powerOffWarning: 'AVISO: "{{name}}" está imprimindo no momento! Tem certeza de que deseja desligar a impressora? Isso interromperá a impressão e pode danificar a impressora.', + powerOffButton: 'Desligar', + }, + // Discovery + discovery: { + title: 'Descobrir Impressoras', + searching: 'Procurando...', + scanning: 'Escaneando...', + scanProgress: 'Escaneando... {{scanned}}/{{total}}', + foundPrinters: '{{count}} impressora(s) encontrada(s)', + noPrintersFound: 'Nenhuma impressora encontrada', + noPrintersFoundSubnet: 'Nenhuma impressora encontrada na sub-rede especificada.', + noPrintersFoundNetwork: 'Nenhuma impressora encontrada na rede.', + allConfigured: 'Todas as impressoras descobertas já estão configuradas.', + alreadyAdded: 'Já adicionada', + select: 'Selecionar', + manualEntry: 'Entrada Manual', + addFromCloud: 'Adicionar da Nuvem', + subnetToScan: 'Sub-rede para escanear', + dockerNote: 'Docker detectado. Insira a sub-rede da sua impressora em notação CIDR. Requer network_mode: host no docker-compose.yml.', + scanSubnet: 'Escanear Sub-rede para Impressoras', + discoverNetwork: 'Descobrir Impressoras na Rede', + scanningSubnet: 'Escaneando sub-rede para impressoras Bambu...', + scanningNetwork: 'Escaneando rede...', + serialRequired: 'Serial necessário', + unknown: 'Desconhecido', + failedToStart: 'Falha ao iniciar a descoberta', + }, + // Filaments section + filaments: 'Filamentos', + // Camera + openCameraOverlay: 'Abrir sobreposição da câmera', + openCameraWindow: 'Abrir câmera em nova janela', + // Firmware + firmwareUpdateAvailable: 'Atualização de firmware disponível: {{current}} → {{latest}}', + firmwareUpToDate: 'Firmware {{version}} — Atualizado', + firmwareUpdateButton: 'Atualizar', + // Plate detection + plateDetection: { + noPermission: 'Você não tem permissão para atualizar impressoras', + enabledClick: 'Verificação da placa ativada - Clique para desativar', + disabledClick: 'Verificação da placa desativada - Clique para ativar', + manageCalibration: 'Gerenciar calibração da detecção da placa', + calibrationRequired: 'Calibração necessária', + calibrationInstructions: 'Certifique-se de que a placa de construção esteja completamente vazia, em seguida clique em Calibrar.', + calibrationDescription: 'A calibração captura uma imagem de referência da placa vazia. Verificações futuras compararão com esta referência para detectar objetos.', + calibrationTip: 'Dica: Você pode armazenar até 5 calibrações para diferentes placas. O sistema usa automaticamente a melhor correspondência ao verificar.', + plateEmpty: 'A placa parece vazia', + objectsDetected: 'Objetos detectados na placa', + confidence: 'Confiança', + difference: 'Diferença', + analysisPreview: 'Pré-visualização da análise:', + analysisLegend: 'Caixa verde = área de detecção, Sobreposição vermelha = diferenças em relação à calibração', + savedReferences: 'Referências salvas ({{count}}/{{max}})', + deleteReference: 'Excluir referência', + labelPlaceholder: 'Etiqueta...', + clickToEdit: '{{label}} - Clique para editar', + clickToAddLabel: 'Clique para adicionar etiqueta', + }, + // Fans + fans: { + partCooling: 'Ventilador de resfriamento da peça', + auxiliary: 'Ventilador auxiliar', + chamber: 'Ventilador da câmara', + }, + // HMS errors + clickToViewHmsErrors: 'Clique para ver erros do HMS', + estimatedCompletion: 'Tempo estimado de conclusão', + slotOptions: 'Opções de slot', + // Firmware modal + firmwareModal: { + title: 'Atualização de Firmware', + titleUpToDate: 'Informações do Firmware', + currentVersion: 'Atual:', + latestVersion: 'Última:', + releaseNotes: 'Notas de Lançamento', + checkingPrereqs: 'Verificando pré-requisitos...', + sdCardReady: 'Cartão SD pronto. Clique abaixo para enviar o firmware.', + uploadedSuccess: 'Firmware enviado para o cartão SD!', + applyInstructions: 'Para aplicar a atualização na sua impressora:', + step1: 'Na tela sensível ao toque da impressora, vá para Configurações', + step2: 'Navegue até Firmware', + step3: 'Selecione Atualizar a partir do cartão SD', + step4: 'A atualização levará de 10 a 20 minutos', + done: 'Concluído', + starting: 'Iniciando...', + uploadFirmware: 'Enviar Firmware', + uploadFailed: 'Falha ao iniciar o envio: {{error}}', + uploadedToast: 'Firmware enviado! Inicie a atualização na tela da impressora.', + }, + accessCodePlaceholder: 'Deixe vazio para manter o atual', + // ROI editor + roi: { + title: 'Área de Detecção (ROI)', + xStart: 'Início X', + yStart: 'Início Y', + width: 'Largura', + height: 'Altura', + instruction: 'Ajuste a área de detecção para focar na placa de construção. A caixa verde na pré-visualização mostra a área atual.', + }, + }, + + // Archives page + archives: { + title: 'Arquivos de Impressão', + searchPlaceholder: 'Pesquisar arquivos...', + filterByPrinter: 'Filtrar por impressora', + filterByStatus: 'Filtrar por status', + sortBy: 'Ordenar por', + sortNewest: 'Mais recentes primeiro', + sortOldest: 'Mais antigos primeiro', + sortName: 'Nome', + sortDuration: 'Duração', + sortLargest: 'Maiores primeiro', + sortSmallest: 'Menores primeiro', + sortSize: 'Tamanho', + noArchives: 'Nenhum arquivo encontrado', + noArchivesSearch: 'Nenhum arquivo corresponde à sua pesquisa', + noArchivesYet: 'Ainda não há arquivos', + loadingArchives: 'Carregando arquivos...', + releaseToUpload: 'Solte para enviar', + showAll: 'Mostrar todos', + showFavoritesOnly: 'Mostrar apenas favoritos', + gridView: 'Visualização em grade', + listView: 'Visualização em lista', + calendarView: 'Visualização em calendário', + logView: 'Registro de impressão', + manageTags: 'Gerenciar etiquetas', + showFailedPrints: 'Mostrar impressões falhas', + hideFailedPrints: 'Ocultar impressões falhas', + printTime: 'Tempo de impressão', + filamentUsed: 'Filamento usado', + cost: 'Custo', + reprint: 'Reimprimir', + preview: 'Pré-visualizar', + deleteArchive: 'Excluir arquivo', + deleteConfirm: 'Tem certeza de que deseja excluir este arquivo?', + favorite: 'Favorito', + unfavorite: 'Remover dos favoritos', + viewDetails: 'Ver detalhes', + status: { + completed: 'Concluído', + failed: 'Falhou', + stopped: 'Parado', + }, + toast: { + source3mfAttached: 'Arquivo de origem 3MF anexado: {{filename}}', + failedUploadSource3mf: 'Falha ao enviar arquivo de origem 3MF', + source3mfRemoved: 'Arquivo de origem 3MF removido', + failedRemoveSource3mf: 'Falha ao remover arquivo de origem 3MF', + f3dAttached: 'F3D anexado: {{filename}}', + failedUploadF3d: 'Falha ao enviar F3D', + f3dRemoved: 'F3D removido', + failedRemoveF3d: 'Falha ao remover F3D', + timelapseAttached: 'Timelapse anexado: {{filename}}', + timelapseAlreadyAttached: 'Timelapse já anexado', + noMatchingTimelapse: 'Nenhum timelapse correspondente encontrado', + failedScanTimelapse: 'Falha ao escanear timelapse', + failedAttachTimelapse: 'Falha ao anexar timelapse', + timelapseRemoved: 'Timelapse removido', + failedRemoveTimelapse: 'Falha ao remover timelapse', + timelapseUploaded: 'Timelapse enviado: {{filename}}', + failedUploadTimelapse: 'Falha ao enviar timelapse', + archiveDeleted: 'Arquivo excluído', + failedDeleteArchive: 'Falha ao excluir arquivo', + addedToFavorites: 'Adicionado aos favoritos', + removedFromFavorites: 'Removido dos favoritos', + projectUpdated: 'Projeto atualizado', + failedUpdateProject: 'Falha ao atualizar projeto', + linkCopied: 'Link copiado para a área de transferência', + failedCopyLink: 'Falha ao copiar link', + photoDeleted: 'Foto excluída', + failedDeletePhoto: 'Falha ao excluir foto', + failedDeleteArchives: 'Falha ao excluir arquivos', + failedUpdateFavorites: 'Falha ao atualizar favoritos', + exportDownloaded: 'Exportação baixada', + exportFailed: 'Falha na exportação', + }, + menu: { + print: 'Imprimir', + schedule: 'Agendar', + openInBambuStudio: 'Abrir no Slicer', + slice: 'Fatiar', + externalLink: 'Link externo', + viewOnMakerWorld: 'Ver no MakerWorld', + preview3d: 'Pré-visualização 3D', + viewTimelapse: 'Ver Timelapse', + scanForTimelapse: 'Escanear Timelapse', + uploadTimelapse: 'Enviar Timelapse', + removeTimelapse: 'Remover Timelapse', + downloadSource3mf: 'Baixar Source 3MF', + uploadSource3mf: 'Enviar Source 3MF', + replaceSource3mf: 'Substituir Source 3MF', + removeSource3mf: 'Remover Source 3MF', + uploadF3d: 'Enviar F3D', + replaceF3d: 'Substituir F3D', + downloadF3d: 'Baixar F3D', + removeF3d: 'Remover F3D', + download: 'Baixar', + copyDownloadLink: 'Copiar link de download', + qrCode: 'Qr Code', + viewPhotos: 'Ver fotos', + viewPhotosCount: 'Ver fotos ({{count}})', + projectPage: 'Página do projeto', + addToFavorites: 'Adicionar aos favoritos', + removeFromFavorites: 'Remover dos favoritos', + edit: 'Editar', + goToProject: 'Ir para o projeto: {{name}}', + addToProject: 'Adicionar ao projeto', + removeFromProject: 'Remover do projeto', + loading: 'Carregando...', + noProjectsAvailable: 'Nenhum projeto disponível', + select: 'Selecionar', + deselect: 'Desmarcar', + delete: 'Excluir', + }, + permission: { + noReprint: 'Você não tem permissão para reimprimir este arquivo', + noAddToQueue: 'Você não tem permissão para adicionar à fila', + noUpdateArchives: 'Você não tem permissão para atualizar arquivos', + noUploadFiles: 'Você não tem permissão para enviar arquivos', + noDownload: 'Você não tem permissão para baixar arquivos', + noCopyLink: 'Você não tem permissão para copiar links de download', + noDelete: 'Você não tem permissão para excluir este arquivo', + noCreate: 'Você não tem permissão para criar arquivos', + }, + card: { + previousPlate: 'Placa anterior', + nextPlate: 'Próxima placa', + plateNumber: 'Placa {{index}}', + moreOptions: 'Clique com o botão direito para mais opções', + addToFavorites: 'Adicionar aos favoritos', + removeFromFavorites: 'Remover dos favoritos', + cancelled: 'cancelado', + failed: 'falha', + duplicate: 'duplicado', + duplicateTitle: 'Este modelo já foi impresso antes', + openSource3mf: 'Abrir source 3MF no Bambu Studio (clique com o botão direito para mais opções)', + downloadF3d: 'Baixar arquivo de design do Fusion 360', + viewTimelapse: 'Ver timelapse', + viewPhoto: 'Ver 1 foto', + viewPhotos: 'Ver {{count}} fotos', + openFolder: 'Abrir pasta: {{name}}', + slicedFile: 'Arquivo fatiado - pronto para imprimir', + sourceFile: 'Apenas arquivo fonte - nenhum mapeamento AMS disponível', + gcode: 'GCODE', + source: 'SOURCE', + project: 'Projeto: {{name}}', + estimated: 'Estimado: {{time}}', + actual: 'Real: {{time}}', + accuracy: 'Precisão: {{percent}}%', + filament: '{{weight}}g', + layer: '{{count}} camada', + layers: '{{count}} camadas', + object: '{{count}} objeto', + objects: '{{count}} objetos', + slicedFor: 'Fatiado para {{model}}', + uploadedBy: 'Enviado por', + noPermissionReprint: 'Você não tem permissão para reimprimir', + noFileForReprint: 'Nenhum arquivo 3MF disponível — o arquivo não pôde ser baixado da impressora quando a impressão foi registrada', + noPermissionEdit: 'Você não tem permissão para editar arquivos', + noPermissionDelete: 'Você não tem permissão para excluir arquivos', + reprint: 'Reimprimir', + schedulePrint: 'Agendar impressão', + schedule: 'Agendar', + openInBambuStudio: 'Abrir no Bambu Studio', + openInBambuStudioToSlice: 'Abrir no Bambu Studio para fatiar', + slice: 'Fatiar', + externalLink: 'Link externo', + makerWorld: 'MakerWorld: {{designer}}', + viewProject: 'Ver projeto', + noExternalLink: 'Nenhum link externo', + preview3d: 'Visualização 3D', + download: 'Baixar', + edit: 'Editar', + delete: 'Excluir', + }, + modal: { + deleteArchive: 'Excluir Arquivo', + deleteConfirm: 'Tem certeza de que deseja excluir "{{name}}"? Esta ação não pode ser desfeita.', + deleteButton: 'Excluir', + removeSource3mf: 'Remover Source 3MF', + removeSource3mfConfirm: 'Tem certeza de que deseja remover o arquivo source 3MF de "{{name}}"? Isso excluirá o arquivo original do projeto do fatiador.', + removeButton: 'Remover', + removeF3d: 'Remover F3D', + removeF3dConfirm: 'Tem certeza de que deseja remover o arquivo de design do Fusion 360 de "{{name}}"?', + removeTimelapse: 'Remover Timelapse', + removeTimelapseConfirm: 'Tem certeza de que deseja remover o vídeo timelapse de "{{name}}"?', + timelapse: '{{name}} - Timelapse', + selectTimelapse: 'Selecionar Timelapse', + selectTimelapseDesc: 'Nenhuma correspondência automática encontrada. Selecione o timelapse para esta impressão:', + deleteArchives: 'Excluir Arquivos', + deleteArchivesConfirm: 'Tem certeza de que deseja excluir {{count}} arquivo(s)? Esta ação não pode ser desfeita.', + deleteCount: 'Excluir {{count}}', + }, + page: { + title: 'Arquivos', + printsCount: '{{filtered}} de {{total}} impressões', + dropFilesHere: 'Solte arquivos .3mf aqui', + releaseToUpload: 'Solte para enviar', + only3mfSupported: 'Apenas arquivos .3mf são suportados', + close: 'Fechar', + selected: '{{count}} selecionado(s)', + selectAll: 'Selecionar Todos', + tags: 'Tags', + project: 'Projeto', + favorite: 'Favorito', + delete: 'Excluir', + toggledFavorites: 'Favoritos alternados para {{count}} arquivo(s)', + failedUpdateFavorites: 'Falha ao atualizar favoritos', + archivesDeleted: '{{count}} arquivo(s) excluído(s)', + failedDeleteArchives: 'Falha ao excluir arquivos', + photoDeleted: 'Foto excluída', + failedDeletePhoto: 'Falha ao excluir foto', + }, + list: { + name: 'Nome', + printer: 'Impressora', + date: 'Data', + size: 'Tamanho', + actions: 'Ações', + hasTimelapse: 'Possui timelapse', + }, + log: { + date: 'Data', + printName: 'Nome da Impressão', + printer: 'Impressora', + user: 'Usuário', + status: 'Status', + duration: 'Duração', + filament: 'Filamento', + allPrinters: 'Todas as Impressoras', + allUsers: 'Todos os Usuários', + allStatuses: 'Todos os Status', + cancelled: 'Cancelado', + skipped: 'Ignorado', + dateFrom: 'De', + dateTo: 'Até', + noEntries: 'Nenhuma entrada de registro de impressão encontrada', + showing: 'Mostrando {{count}} de {{total}} entradas', + rowsPerPage: 'Linhas', + page: 'Página', + prev: 'Anterior', + next: 'Próxima', + clearLog: 'Limpar Registro', + clearLogTitle: 'Limpar Registro de Impressão', + clearLogConfirm: 'Todas as entradas do registro de impressão serão permanentemente excluídas. Arquivos e itens da fila não serão afetados. Esta ação não pode ser desfeita. Tem certeza?', + clearLogButton: 'Limpar Tudo', + cleared: '{{count}} entradas do registro de impressão limpas', + clearFailed: 'Falha ao limpar o registro de impressão', + }, + }, + + // Queue page + queue: { + title: 'Fila de Impressão', + subtitle: 'Agende e gerencie seus trabalhos de impressão', + addToQueue: 'Adicionar à Fila', + // Print modal + print: 'Imprimir', + reprint: 'Reimprimir', + schedulePrint: 'Agendar Impressão', + editQueueItem: 'Editar Item da Fila', + printToPrinters: 'Imprimir para {{count}} Impressoras', + queueToPrinters: 'Adicionar à Fila para {{count}} Impressoras', + sending: 'Enviando...', + sendingProgress: 'Enviando {{current}}/{{total}}...', + adding: 'Adicionando...', + addingProgress: 'Adicionando {{current}}/{{total}}...', + savingProgress: 'Salvando {{current}}/{{total}}...', + clearQueue: 'Limpar Fila', + clearHistory: 'Limpar Histórico', + emptyQueue: 'Fila vazia', + position: 'Posição', + scheduledTime: 'Hora Agendada', + moveUp: 'Mover para Cima', + moveDown: 'Mover para Baixo', + startNow: 'Iniciar Agora', + printingInProgress: 'Impressão em andamento...', + viewArchive: 'Ver Arquivo', + viewInFileManager: 'Ver no Gerenciador de Arquivos', + itemCount: '{{count}} item', + itemCount_plural: '{{count}} items', + dragToReorder: 'Arraste para reordenar (apenas ASAP)', + reorderHint: 'A posição afeta apenas itens ASAP. Itens agendados são executados no horário definido.', + addedBy: 'Adicionado por {{name}}', + nextInQueue: 'Próximo na fila', + clearPlate: 'Limpar Placa e Iniciar Próximo', + clearPlateSuccess: 'Placa limpa — pronta para a próxima impressão', + plateReady: 'Placa limpa — pronta para a próxima impressão', + plateNumber: 'Placa {{index}}', + // Sections + sections: { + currentlyPrinting: 'Imprimindo Atualmente', + queued: 'Na Fila', + history: 'Histórico', + }, + // Status + status: { + pending: 'Pendente', + waiting: 'Aguardando', + printing: 'Imprimindo', + paused: 'Pausado', + completed: 'Concluído', + failed: 'Falhou', + skipped: 'Ignorado', + cancelled: 'Cancelado', + }, + // Summary cards + summary: { + printing: 'Imprimindo', + queued: 'Na Fila', + totalTime: 'Tempo Total da Fila', + totalWeight: 'Peso Total da Fila', + history: 'Histórico', + }, + // Filters + filter: { + allPrinters: 'Todas as Impressoras', + unassigned: 'Não Atribuído', + allStatus: 'Todos os Status', + allLocations: 'Todos os Locais', + any: 'Qualquer', + }, + // Sort + sort: { + byPosition: 'Ordenar por Posição', + byName: 'Ordenar por Nome', + byPrinter: 'Ordenar por Impressora', + bySchedule: 'Ordenar por Agendamento', + byDate: 'Ordenar por Data', + ascendingOldest: 'Crescente (mais antigo primeiro)', + descendingNewest: 'Decrescente (mais recente primeiro)', + }, + // Badges + badges: { + staged: 'Preparado (início manual)', + requiresPrevious: 'Requer sucesso anterior', + autoPowerOff: 'Desligamento automático', + }, + // Empty state + empty: { + title: 'Nenhuma impressão agendada', + description: 'Agende uma impressão a partir da página de Arquivos usando a opção "Agendar" no menu de contexto, ou arraste e solte arquivos para começar.', + }, + // Time + time: { + asap: 'ASAP', + overdue: 'Atrasado', + now: 'Agora', + lessThanMinute: 'Em menos de um minuto', + inMinutes: 'Em {{count}} min', + inHours: 'Em {{count}} horas', + }, + // Actions + actions: { + stopPrint: 'Parar Impressão', + startPrint: 'Iniciar Impressão', + requeue: 'Reenfileirar', + }, + // Bulk edit + bulkEdit: { + title: 'Editar {{count}} Item', + title_plural: 'Editar {{count}} Items', + description: 'Apenas as configurações alteradas serão aplicadas aos itens selecionados.', + printer: 'Impressora', + noChange: '— Sem alterações —', + queueOptions: 'Opções de Fila', + staged: 'Preparado (início manual)', + autoPowerOff: 'Desligamento automático após impressão', + requirePrevious: 'Requer sucesso anterior', + printOptions: 'Opções de Impressão', + bedLevelling: 'Nivelamento da Mesa', + flowCalibration: 'Calibração de Fluxo', + vibrationCalibration: 'Calibração de Vibração', + layerInspection: 'Inspeção da Primeira Camada', + timelapse: 'Timelapse', + useAms: 'Usar AMS', + applyChanges: 'Aplicar Alterações', + selectAll: 'Selecionar Todos', + deselectAll: 'Desmarcar Todos', + selected: '{{count}} selecionado(s)', + editSelected: 'Editar Selecionados', + cancelSelected: 'Cancelar Selecionados', + }, + // Confirmations + confirm: { + cancelTitle: 'Cancelar Impressão Agendada', + cancelMessage: 'Tem certeza de que deseja cancelar "{{name}}"?', + stopTitle: 'Parar Impressão', + stopMessage: 'Tem certeza de que deseja parar a impressão atual "{{name}}"? Isso cancelará o trabalho de impressão na impressora.', + removeTitle: 'Remover do Histórico', + removeMessage: 'Tem certeza de que deseja remover "{{name}}" do histórico da fila?', + clearHistoryTitle: 'Limpar Histórico', + clearHistoryMessage: 'Tem certeza de que deseja remover todos os {{count}} itens do histórico?', + cancelButton: 'Cancelar Impressão', + stopButton: 'Parar Impressão', + thisPrint: 'esta impressão', + thisItem: 'este item', + }, + // Toast messages + toast: { + cancelled: 'Item da fila cancelado', + cancelFailed: 'Falha ao cancelar item', + removed: 'Item da fila removido', + removeFailed: 'Falha ao remover item', + stopped: 'Impressão parada', + stopFailed: 'Falha ao parar impressão', + released: 'Impressão liberada para a fila', + startFailed: 'Falha ao iniciar impressão', + reorderFailed: 'Falha ao reordenar fila', + historyCleared: 'Limpar {{count}} item(s) do histórico', + clearHistoryFailed: 'Falha ao limpar histórico', + updateFailed: 'Falha ao atualizar itens', + bulkCancelled: 'Cancelado {{count}} item(s)', + bulkCancelFailed: 'Falha ao cancelar itens', + }, + // Permissions + permissions: { + noStopPrint: 'Você não tem permissão para parar impressões', + noStartPrint: 'Você não tem permissão para iniciar impressões', + noEdit: 'Você não tem permissão para editar este item da fila', + noCancel: 'Você não tem permissão para cancelar este item da fila', + noRequeue: 'Você não tem permissão para reenfileirar itens', + noRemove: 'Você não tem permissão para remover este item da fila', + noClearHistory: 'Você não tem permissão para limpar todo o histórico', + noEditItems: 'Você não tem permissão para editar itens da fila', + noCancelItems: 'Você não tem permissão para cancelar itens da fila', + }, + }, + + // Statistics page + stats: { + title: 'Dashboard', + subtitle: 'Arraste os widgets para reorganizar. Clique no ícone de olho para ocultar.', + overview: 'Visão Geral', + totalPrints: 'Total de Impressões', + successRate: 'Taxa de Sucesso', + totalPrintTime: 'Tempo Total de Impressão', + printTime: 'Tempo de Impressão', + totalFilament: 'Filamento Total Utilizado', + filamentUsed: 'Filamento Utilizado', + filamentCost: 'Custo do Filamento', + totalCost: 'Custo Total', + energyUsed: 'Energia Utilizada', + energyCost: 'Custo da Energia', + averagePrintTime: 'Tempo Médio de Impressão', + printsPerDay: 'Impressões por Dia', + byPrinter: 'Por Impressora', + printsByPrinter: 'Impressões por Impressora', + byMaterial: 'Por Material', + byMonth: 'Por Mês', + last7Days: 'Últimos 7 Dias', + last30Days: 'Últimos 30 Dias', + last90Days: 'Últimos 90 Dias', + allTime: 'Todo o Tempo', + // Widgets + quickStats: 'Estatísticas Rápidas', + printActivity: 'Atividade de Impressão', + filamentTypes: 'Tipos de Filamento', + filamentTrends: 'Tendências de Filamento', + failureAnalysis: 'Análise de Falhas', + timeAccuracy: 'Precisão do Tempo', + successful: 'Bem-sucedido:', + failed: 'Falhou:', + perfectEstimate: '100% = estimativa perfeita', + noTimeAccuracyData: 'Nenhum dado de precisão de tempo disponível', + noFilamentData: 'Nenhum dado de filamento disponível', + noPrinterData: 'Nenhum dado de impressora disponível', + noPrintData: 'Nenhum dado de impressão disponível', + noPrintDataLast30Days: 'Nenhum dado de impressão nos últimos 30 dias', + failureReasons: 'Razões de Falha', + topFailureReasons: 'Principais Razões de Falha', + failedPrintsCount: '{{failed}} / {{total}} impressões falharam', + lastWeekRate: 'Última semana: {{rate}}%', + // Actions + resetLayout: 'Redefinir Layout', + recalculateCosts: 'Recalcular Custos', + recalculateCostsHint: 'Recalcular todos os custos do arquivo usando os preços atuais do filamento', + exportStats: 'Exportar Estatísticas', + exportAsCsv: 'Exportar como CSV', + exportAsExcel: 'Exportar como Excel', + hiddenCount: '{{count}} Oculto', + // Toast + exportDownloaded: 'Exportação baixada', + exportFailed: 'Falha na exportação', + layoutReset: 'Layout redefinido', + recalculatedCosts: 'Custos recalculados para {{count}} arquivos', + recalculateFailed: 'Falha ao recalcular custos', + // Loading + loadingStats: 'Carregando estatísticas...', + // Permissions + noPermissionResetLayout: 'Você não tem permissão para redefinir o layout', + noPermissionRecalculate: 'Você não tem permissão para recalcular custos', + }, + + // Maintenance page + maintenance: { + title: 'Manutenção', + overview: 'Visão Geral', + allOk: 'Todas as manutenções estão em dia', + dueCount: '{{count}} item pendente', + dueCount_plural: '{{count}} itens pendentes', + warningCount: '{{count}} aviso', + warningCount_plural: '{{count}} avisos', + totalPrintTime: 'Tempo Total de Impressão', + nextMaintenance: 'Próxima Manutenção', + nothingDue: 'Nada pendente', + tasks: 'Tarefas', + lastPerformed: 'Última execução', + interval: 'Intervalo', + hoursRemaining: '{{hours}}h restantes', + hoursOverdue: '{{hours}}h atrasadas', + markDone: 'Marcar como Concluída', + performMaintenance: 'Realizar Manutenção', + history: 'Histórico', + noHistory: 'Nenhum histórico de manutenção', + editPrintHours: 'Editar Horas de Impressão', + currentHours: 'Horas Atuais', + // Tabs + statusTab: 'Status', + settingsTab: 'Configurações', + // Status + overdueCount: '{{count}} atrasado', + dueSoonCount: '{{count}} prestes a vencer', + dueSoon: 'Prestes a vencer', + allGood: 'Tudo certo', + overdueBy: 'Atrasado por {{duration}}', + dueIn: 'Vence em {{duration}}', + timeLeft: '{{duration}} restantes', + // Duration formats + day: '1 dia', + days: '{{count}} dias', + week: '1 semana', + weeks: '{{count}} semanas', + month: '1 mês', + months: '{{count}} meses', + year: '1 ano', + years: '{{count}} anos', + // Settings + maintenanceTypes: 'Tipos de Manutenção', + maintenanceTypesDescription: 'Tipos de sistema e suas tarefas de manutenção personalizadas', + addCustomType: 'Adicionar Tipo Personalizado', + restoreDefaults: 'Restaurar Tarefas Padrão', + intervalType: 'Tipo de Intervalo', + intervalValue: 'Intervalo ({{type}})', + icon: 'Icon', + documentationLink: 'Link da Documentação (opcional)', + assignToPrinters: 'Atribuir a Impressoras', + selectAtLeastOnePrinter: 'Selecione pelo menos uma impressora', + addType: 'Adicionar Tipo', + custom: 'Personalizado', + printHours: 'Horas de Impressão', + calendarDays: 'Dias de Calendário', + exampleName: 'ex., Substituir Filtro HEPA', + viewDocumentation: 'Ver documentação', + timeBasedInterval: 'Intervalo baseado em tempo', + // Interval overrides + intervalOverrides: 'Substituições de Intervalo', + intervalOverridesDescription: 'Personalize os intervalos para impressoras específicas', + // Printer assignment + assignedToPrinters: 'Atribuído a impressoras:', + noPrintersAssigned: 'Nenhuma impressora atribuída', + addPrinterShort: 'Adicionar:', + printersAssignedClick: '{{count}} impressora(s) atribuída(s) - clique para gerenciar', + removeFromPrinter: 'Remover desta impressora', + // Types + types: { + lubricateCarbonRods: 'Lubricar Barras de Carbono', + lubricateRails: 'Lubricar Trilhos Lineares', + cleanNozzle: 'Limpar Bico/Hotend', + checkBelts: 'Verificar Tensão das Correias', + cleanBuildPlate: 'Limpar Plataforma de Impressão', + checkExtruder: 'Verificar Engrenagens do Extrusor', + checkCooling: 'Verificar Ventiladores de Resfriamento', + generalInspection: 'Inspeção Geral', + cleanCarbonRods: 'Limpar Barras de Carbono', + cleanLinearRails: 'Limpar Trilhos Lineares', + checkPtfeTube: 'Verificar Tubo PTFE', + replaceHepaFilter: 'Substituir Filtro HEPA', + replaceCarbonFilter: 'Substituir Filtro de Carbono', + lubricateLeftNozzleRail: 'Lubrificar Trilho do Bico Esquerdo', + }, + // Toast + maintenanceComplete: 'Manutenção marcada como concluída', + typeUpdated: 'Tipo de manutenção atualizado', + typeDeleted: 'Tipo de manutenção excluído', + defaultsRestored: 'Restauradas {{count}} tarefa(s) padrão', + printHoursUpdated: 'Horas de impressão atualizadas', + printerAssigned: 'Impressora atribuída', + printerRemoved: 'Impressora removida', + // Confirmation + deleteTypeConfirm: 'Excluir "{{name}}"?', + deleteSystemTypeTitle: 'Excluir tarefa de manutenção padrão?', + deleteSystemTypeMessage: 'Tem certeza de que deseja excluir a tarefa de manutenção padrão "{{name}}"?', + // Permissions + noPermissionUpdate: 'Você não tem permissão para atualizar itens de manutenção', + noPermissionPerform: 'Você não tem permissão para realizar manutenção', + noPermissionEditTypes: 'Você não tem permissão para editar tipos de manutenção', + noPermissionDeleteTypes: 'Você não tem permissão para excluir tipos de manutenção', + noPermissionEditHours: 'Você não tem permissão para editar horas de impressão', + noPermissionRemovePrinter: 'Você não tem permissão para remover atribuições de impressora', + noPermissionAssignPrinter: 'Você não tem permissão para atribuir impressoras', + noPermissionEditIntervals: 'Você não tem permissão para editar intervalos', + // Configure link + configureSettings: 'Configure tipos de manutenção e intervalos', + }, + + // Settings page + settings: { + title: 'Configurações', + general: 'Geral', + // Tab names + tabs: { + general: 'Geral', + smartPlugs: 'Tomadas Inteligentes', + notifications: 'Notificações', + filament: 'Filamento', + network: 'Rede', + apiKeys: 'Chaves API', + virtualPrinter: 'Impressora Virtual', + users: 'Autenticação', + backup: 'Backup', + emailAuth: 'Autenticação por Email', + }, + // Email settings + email: { + smtpSettings: 'Configuração SMTP', + smtpHost: 'Servidor SMTP', + smtpPort: 'Porta SMTP', + security: 'Segurança', + authentication: 'Autenticação', + username: 'Nome de Usuário', + password: 'Senha', + fromEmail: 'Email de Remetente', + fromName: 'Nome de Remetente', + testConnection: 'Testar Conexão SMTP', + testRecipient: 'Email de Teste', + sendTest: 'Enviar Email de Teste', + sending: 'Enviando...', + save: 'Salvar Configurações', + saving: 'Salvando...', + advancedAuth: 'Autenticação Avançada', + advancedAuthEnabled: 'Autenticação Avançada está habilitada', + advancedAuthEnabledDesc: 'Recursos de gerenciamento de usuários baseados em email estão ativos. Novos usuários receberão senhas geradas automaticamente por email, e os usuários podem redefinir suas senhas através do recurso de esqueci minha senha.', + advancedAuthDisabled: 'Autenticação Avançada está desabilitada', + advancedAuthDisabledDesc: 'Habilite a autenticação avançada para ativar recursos baseados em email para gerenciamento de usuários.', + enable: 'Habilitar', + disable: 'Desabilitar', + feature1: 'Senhas são geradas automaticamente e enviadas por email para novos usuários', + feature2: 'Usuários podem fazer login com nome de usuário ou email', + feature3: 'Recurso de esqueci minha senha está disponível', + feature4: 'Administradores podem redefinir senhas de usuários via email', + // Error messages + errors: { + requiredFields: 'Por favor, preencha todos os campos obrigatórios', + usernameRequired: 'Nome de usuário é obrigatório quando a autenticação está habilitada', + enterTestEmail: 'Por favor, insira um endereço de email de teste', + smtpServerAndEmail: 'Por favor, preencha o servidor SMTP e o email de remetente antes de testar', + usernamePasswordRequired: 'Nome de usuário e senha são obrigatórios quando a autenticação está habilitada', + configureSmtpFirst: 'Por favor, configure e teste as configurações SMTP primeiro', + }, + // Success messages + success: { + settingsSaved: 'Configurações SMTP salvas com sucesso', + }, + // Security options + securityOptions: { + starttls: 'STARTTLS (Port 587)', + ssl: 'SSL/TLS (Port 465)', + none: 'None (Port 25)', + }, + // Authentication options + authOptions: { + enabled: 'Habilitado', + disabled: 'Desabilitado', + }, + }, + appearance: 'Aparência', + notifications: 'Notificações', + smartPlugs: 'Tomadas Inteligentes', + spoolman: 'Spoolman', + updates: 'Atualizações', + language: 'Idioma', + languageDescription: 'Selecione seu idioma preferido', + theme: 'Tema', + themeLight: 'Claro', + themeDark: 'Escuro', + themeSystem: 'Sistema', + defaultView: 'Visualização Padrão', + defaultViewDescription: 'Página a ser exibida ao abrir o aplicativo', + checkForUpdates: 'Verificar Atualizações', + autoUpdate: 'Atualização Automática', + currentVersion: 'Versão Atual', + latestVersion: 'Última Versão', + upToDate: 'Você está atualizado', + updateAvailable: 'Atualização disponível', + // Notifications + notificationLanguage: 'Idioma das Notificações', + notificationLanguageDescription: 'Idioma para notificações push', + bedCooledThreshold: 'Limite de Resfriamento da Cama', + bedCooledThresholdDescription: 'Temperatura abaixo da qual a cama é considerada resfriada após uma impressão', + notificationProviders: 'Provedores de Notificação', + addProvider: 'Adicionar Provedor', + editProvider: 'Editar Provedor', + providerType: 'Tipo de Provedor', + testNotification: 'Testar Notificação', + testSuccess: 'Notificação de teste enviada com sucesso', + testFailed: 'Falha ao enviar notificação de teste', + quietHours: 'Horas de Silêncio', + quietHoursDescription: 'Não perturbe durante essas horas', + quietHoursStart: 'Início', + quietHoursEnd: 'Fim', + events: { + title: 'Eventos de Notificação', + printStart: 'Impressão Iniciada', + printComplete: 'Impressão Concluída', + printFailed: 'Falha na Impressão', + printStopped: 'Impressão Interrompida', + printProgress: 'Marcos de Progresso', + printProgressDescription: 'Notificar em 25%, 50%, 75%', + printerOffline: 'Impressora Offline', + printerError: 'Erro na Impressora', + filamentLow: 'Filamento Baixo', + maintenanceDue: 'Manutenção Pendente', + maintenanceDueDescription: 'Notificar quando a manutenção for necessária', + }, + // Smart Plugs + smartPlug: { + title: 'Tomadas Inteligentes', + add: 'Adicionar Tomada Inteligente', + edit: 'Editar Tomada Inteligente', + name: 'Nome', + ipAddress: 'Endereço IP', + linkedPrinter: 'Impressora Vinculada', + autoOn: 'Ligar Automaticamente', + autoOnDescription: 'Ligar quando a impressão começar', + autoOff: 'Desligar Automaticamente', + autoOffDescription: 'Desligar após a conclusão da impressão', + offDelay: 'Atraso para Desligar', + offDelayMinutes: 'Minutos após a impressão', + offDelayTemp: 'Quando o bico estiver abaixo da temperatura', + currentState: 'Estado Atual', + turnOn: 'Ligar', + turnOff: 'Desligar', + }, + // Filament Tracking Mode + filamentTracking: 'Rastreamento de Filamento', + filamentTrackingDesc: 'Escolha como rastrear seus rolos de filamento. Você pode usar o inventário interno ou conectar a um servidor Spoolman externo.', + trackingModeBuiltIn: 'Inventário Interno', + trackingModeBuiltInDesc: 'Correspondência automática de RFID e rastreamento de uso incluídos', + trackingModeSpoolmanDesc: 'Servidor de gerenciamento de filamento externo', + builtInFeatureRfid: 'Detecta automaticamente rolos RFID da Bambu Lab no AMS', + builtInFeatureUsage: 'Rastreia o consumo de filamento por impressão', + builtInFeatureCatalog: 'Gerencia rolos, cores e perfis de fator K', + builtInFeatureThirdParty: 'Rolos de terceiros podem ser atribuídos aos rolos do inventário', + amsSyncButton: 'Sincronizar Pesos do AMS', + amsSyncTitle: 'Sincronizar Pesos dos Rolos do AMS', + amsSyncMessage: 'Isso substituirá todos os pesos dos rolos do inventário pelos valores atuais de % restante do AMS das impressoras conectadas. Use isso para recuperar dados de peso corrompidos. As impressoras devem estar online.', + amsSyncing: 'Sincronizando...', + amsSyncSuccess: '{{synced}} rolo(s) sincronizado(s), {{skipped}} ignorado(s)', + amsSyncError: 'Falha ao sincronizar pesos do AMS', + // Spoolman settings + spoolmanUrl: 'Spoolman URL', + spoolmanUrlHint: 'URL do seu servidor Spoolman (por exemplo, http://localhost:7912)', + spoolmanConnected: 'Conectado', + spoolmanDisconnected: 'Desconectado', + status: 'Status', + connect: 'Conectar', + disconnect: 'Desconectar', + howSyncWorks: 'Como a Sincronização Funciona', + syncInfoRfidOnly: 'Apenas rolos oficiais da Bambu Lab com RFID são sincronizados', + syncInfoAutoCreate: 'Novos rolos são criados automaticamente no Spoolman na primeira sincronização', + syncInfoThirdPartySkipped: 'Rolos não oficiais da Bambu Lab (terceiros, reabastecidos) são ignorados', + linkingExistingSpools: 'Vinculando Rolos Existentes', + linkingExistingSpoolsDesc: 'Para vincular rolos existentes do Spoolman ao seu AMS, passe o mouse sobre um slot do AMS e clique em "Vincular ao Spoolman".', + syncMode: 'Modo de Sincronização', + syncModeAuto: 'Automático', + syncModeManual: 'Apenas Manual', + syncModeAutoDesc: 'Os dados do AMS são sincronizados automaticamente quando alterações são detectadas', + syncModeManualDesc: 'Somente sincronize quando acionado manualmente', + syncAmsData: 'Sincronizar Dados do AMS', + syncAmsDataDesc: 'Sincronize manualmente os dados do AMS da impressora com o Spoolman', + allPrinters: 'Todas as Impressoras', + // Default printer + noDefaultPrinter: 'Sem padrão (perguntar a cada vez)', + // Sidebar + sidebarOrder: 'Ordem da barra lateral', + // Camera + saveThumbnails: 'Salvar miniaturas', + captureFinishPhoto: 'Capturar foto de conclusão', + noPrintersConfigured: 'Nenhuma impressora configurada', + // Archive settings + archiveMode: { + always: 'Sempre criar entrada de arquivo', + never: 'Nunca criar entrada de arquivo', + ask: 'Perguntar a cada vez', + }, + // Updates + checkForUpdatesLabel: 'Verificar atualizações', + checkPrinterFirmware: 'Verificar firmware da impressora', + // Queue + enableRetry: 'Habilitar tentativa', + // Home Assistant + homeAssistantDescription: 'Controlar tomadas inteligentes via Home Assistant', + environmentManagedLabel: '(Gerenciado pelo Ambiente)', + autoEnabledViaEnv: 'Habilitado automaticamente via variáveis de ambiente', + urlFromEnvReadOnly: 'Valor definido pela variável de ambiente HA_URL (somente leitura)', + tokenFromEnvReadOnly: 'Valor definido pela variável de ambiente HA_TOKEN (somente leitura)', + // MQTT + mqttConnectedTo: 'Conectado a', + // Prometheus + prometheusDescription: 'Expor dados da impressora no formato Prometheus', + // Smart plugs empty state + noSmartPlugsTitle: 'Nenhuma tomada inteligente configurada', + noSmartPlugsDescription: 'Adicione uma tomada inteligente baseada em Tasmota para monitorar o consumo de energia e automatizar o controle de energia.', + // Notifications empty state + noProvidersTitle: 'Nenhum provedor configurado', + noProvidersDescription: 'Adicione um provedor para receber alertas.', + noTemplatesAvailable: 'Nenhum modelo disponível. Reinicie o backend para gerar os modelos padrão.', + // API permissions + apiPermissionView: 'Visualizar status da impressora e fila', + apiPermissionEdit: 'Adicionar e remover itens da fila de impressão', + // API keys + apiKeysEmptyTitle: 'Nenhuma chave API', + apiKeysEmptyDescription: 'Crie uma chave API para integrar com serviços externos.', + // Users + noUsersFound: 'Nenhum usuário encontrado', + noGroupsFound: 'Nenhum grupo encontrado', + noGroupsAvailable: 'Nenhum grupo disponível', + passwordsDoNotMatch: 'As senhas não coincidem', + systemGroupWarning: 'Os nomes dos grupos do sistema não podem ser alterados', + // Auth disabled + authDisabledTitle: 'Autenticação Desativada', + authDisabledFeature1: 'Exigir login para acessar o sistema', + authDisabledFeature2: 'Criar múltiplos usuários com permissões baseadas em grupos', + authDisabledFeature3: 'Controlar acesso com mais de 50 permissões granulares', + // User deletion + userHasCreated: 'Este usuário criou:', + userItemsQuestion: 'O que você gostaria de fazer com esses itens?', + deleteUserConfirm: 'Tem certeza de que deseja excluir este usuário?', + actionCannotBeUndone: 'Esta ação não pode ser desfeita.', + // Smart plugs + addFirstSmartPlug: 'Adicione sua primeira tomada inteligente', + // Notifications + providers: 'Provedores', + log: 'Registro', + testAll: 'Testar tudo', + testResults: 'Resultados do teste', + testPassedCount: '{{count}} aprovado', + testFailedCount: '{{count}} falhou', + messageTemplates: 'Modelos de mensagem', + messageTemplatesDescription: 'Personalize as mensagens de notificação para cada evento.', + // API Keys section + apiKeys: 'Chaves API', + apiKeysDescription: 'Crie chaves API para integrações externas e webhooks.', + createKey: 'Criar Chave', + apiKeyCreated: 'Chave API criada com sucesso', + apiKeyCopyWarning: "Copie esta chave agora - ela não será exibida novamente!", + useInApiBrowser: 'Usar no Navegador API', + createNewApiKey: 'Criar Nova Chave API', + keyName: 'Nome da Chave', + keyNamePlaceholder: 'e.g., Home Assistant, OctoPrint', + readStatus: 'Status de Leitura', + readStatusDescription: 'Visualizar status da impressora e fila', + manageQueue: 'Gerenciar Fila', + manageQueueDescription: 'Adicionar e remover itens da fila de impressão', + controlPrinter: 'Controlar Impressora', + controlPrinterDescription: 'Pausar, retomar e parar impressões', + unnamedKey: 'Chave Sem Nome', + lastUsed: 'Último uso', + read: 'Ler', + control: 'Controlar', + createFirstKey: 'Crie sua primeira chave', + webhookEndpoints: 'Endpoints de Webhook', + webhookApiKeyHint: 'Use sua chave API no cabeçalho X-API-Key.', + webhook: { + getAllStatus: 'Obter status de todas as impressoras', + getSpecificStatus: 'Obter status de uma impressora específica', + addToQueue: 'Adicionar à fila de impressão', + pausePrint: 'Pausar impressão', + resumePrint: 'Retomar impressão', + stopPrint: 'Parar impressão', + }, + apiBrowser: 'Navegador API', + apiBrowserDescription: 'Explore e teste todos os endpoints de API disponíveis.', + apiKeyForTesting: 'Chave API para Teste', + apiKeyPlaceholder: 'Cole sua chave API aqui para testar endpoints autenticados...', + apiKeyHint: 'Esta chave será enviada como cabeçalho X-API-Key nas solicitações.', + deleteApiKeyTitle: 'Excluir Chave API', + deleteApiKeyMessage: 'Tem certeza de que deseja excluir esta chave API? Quaisquer integrações usando esta chave deixarão de funcionar.', + deleteKey: 'Excluir Chave', + // Filament tab + amsDisplayThresholds: 'Limiares de Exibição AMS', + amsThresholdsDescription: 'Configure os limiares de cores para os indicadores de umidade e temperatura do AMS.', + humidity: 'Umidade', + goodGreen: 'Bom (verde)', + fairOrange: 'Razoável (laranja)', + aboveFairBad: 'Acima do limiar razoável mostra como vermelho (ruim)', + temperature: 'Temperatura', + goodBlue: 'Bom (azul)', + aboveFairHot: 'Acima do limiar razoável mostra como vermelho (quente)', + historyRetention: 'Retenção de Histórico', + keepSensorHistory: 'Manter histórico do sensor por', + historyRetentionDescription: 'Dados antigos de umidade e temperatura serão automaticamente excluídos', + printModal: 'Modal de Impressão', + expandCustomMapping: 'Expandir mapeamento personalizado por padrão', + expandCustomMappingDescription: 'Ao imprimir em várias impressoras, mostrar o mapeamento AMS por impressora expandido', + // User management + authentication: 'Autenticação', + authEnabledDescription: 'Sua instância está protegida com autenticação de usuário', + authDisabledDescription: 'Ative para exigir login e gerenciar o acesso dos usuários', + authDisabledMessage: 'Ative a autenticação para criar contas de usuário, gerenciar permissões e proteger sua instância do Bambuddy.', + enableAuthentication: 'Ativar Autenticação', + currentUser: 'Usuário Atual', + changePassword: 'Alterar Senha', + admin: 'Administrador', + users: 'Usuários', + addUser: 'Adicionar Usuário', + groups: 'Grupos', + addGroup: 'Adicionar Grupo', + system: 'Sistema', + noDescription: 'Sem descrição', + userCount: '{{count}} usuários', + permissionCount: '{{count}} permissões', + createUser: 'Criar Usuário', + username: 'Nome de Usuário', + enterUsername: 'Digite o nome de usuário', + password: 'Senha', + enterPassword: 'Digite a senha (mínimo 6 caracteres)', + confirmPassword: 'Confirmar Senha', + confirmPasswordPlaceholder: 'Confirme a senha', + // Title tooltips + viewReleaseOnGitHub: 'Ver lançamento no GitHub', + turnAllPlugsOn: 'Ligar todas as tomadas', + turnAllPlugsOff: 'Desligar todas as tomadas', + // Modal: Clear logs + clearNotificationLogs: 'Limpar Logs de Notificação', + clearLogsMessage: 'Isso excluirá permanentemente todos os logs de notificação com mais de 30 dias. Esta ação não pode ser desfeita.', + clearLogs: 'Limpar Logs', + // Modal: Reset UI + resetUiPreferences: 'Redefinir Preferências de UI', + resetUiPreferencesMessage: 'Isso redefinirá todas as preferências de UI para os padrões: ordem da barra lateral, tema, layout do painel, modos de exibição e preferências de classificação. Suas impressoras, arquivos e configurações do servidor NÃO serão afetados. A página será recarregada após a limpeza.', + resetPreferences: 'Redefinir Preferências', + // Modal: Delete group + deleteGroupTitle: 'Excluir Grupo', + deleteGroupMessage: 'Tem certeza de que deseja excluir este grupo? Usuários neste grupo perderão essas permissões.', + deleteGroup: 'Excluir Grupo', + // Modal: Disable auth + disableAuthenticationTitle: 'Desativar Autenticação', + disableAuthenticationMessage: 'Tem certeza de que deseja desativar a autenticação? Isso tornará sua instância do Bambuddy acessível sem login. Todos os usuários permanecerão no banco de dados, mas a autenticação será desativada.', + disableAuthentication: 'Desativar Autenticação', + // Additional settings + configureBambuddy: 'Configurar Bambuddy', + systemDefault: 'Padrão do Sistema', + archiveSettings: 'Configurações de Arquivo', + newWindow: 'Nova Janela', + embeddedOverlay: 'Sobreposição Incorporada', + preferredSlicer: 'Fatiador Preferido', + preferredSlicerDescription: 'Escolha qual aplicativo de fatiamento abrirá os arquivos', + externalCameras: 'Câmeras Externas', + costTracking: 'Rastreamento de Custos', + printsOnly: 'Apenas Impressões', + totalConsumption: 'Consumo Total', + dataManagement: 'Gerenciamento de Dados', + storageUsage: 'Uso de Armazenamento', + storageUsageDescription: 'Detalhamento do uso de dados por categoria', + storageUsageTotal: 'Total', + storageUsageErrors: 'Erros', + storageUsageOtherBreakdown: 'Outros (inclui ativos estáticos, scripts e arquivos de configuração)', + storageUsageSystem: 'Sistema', + storageUsageData: 'Dados', + storageUsageUnavailable: 'Informações de uso de armazenamento indisponíveis', + clearNotificationLogsDescription: 'Excluir logs de notificação com mais de 30 dias', + resetUiPreferencesDescription: 'Redefinir ordem da barra lateral, tema, modos de exibição e preferências de layout. Impressoras, arquivos e configurações não são afetados.', + enableHomeAssistant: 'Ativar Home Assistant', + enableMqtt: 'Ativar MQTT', + useTls: 'Usar TLS', + enableMetricsEndpoint: 'Ativar Endpoint de Métricas', + availableMetrics: 'Métricas Disponíveis', + editUser: 'Editar Usuário', + deleteUserTitle: 'Excluir Usuário', + groupName: 'Nome do Grupo', + // Placeholders + leaveEmptyForAnonymous: 'Deixe vazio para anônimo', + leaveEmptyForNoAuth: 'Deixe vazio para sem autenticação', + enterNewPassword: 'Digite a nova senha', + confirmNewPassword: 'Confirme a nova senha', + enterGroupName: 'Digite o nome do grupo', + enterDescriptionOptional: 'Digite a descrição (opcional)', + enterCurrentPassword: 'Digite a senha atual', + enterNewPasswordMin6: 'Digite a nova senha (mínimo 6 caracteres)', + toast: { + keyCopied: 'Chave copiada para a área de transferência', + copyFailed: 'Falha ao copiar a chave', + keyAddedToBrowser: 'Chave adicionada ao Navegador de API', + clearLogsFailed: 'Falha ao limpar logs', + uiPreferencesReset: 'Preferências de UI redefinidas. Atualizando...', + authDisabled: 'Autenticação desativada com sucesso', + authDisableFailed: 'Falha ao desativar a autenticação', + apiKeyCreated: 'Chave de API criada', + apiKeyDeleted: 'Chave de API excluída', + userCreated: 'Usuário criado com sucesso', + userUpdated: 'Usuário atualizado com sucesso', + userDeleted: 'Usuário excluído com sucesso', + groupCreated: 'Grupo criado com sucesso', + groupUpdated: 'Grupo atualizado com sucesso', + groupDeleted: 'Grupo excluído com sucesso', + fillRequiredFields: 'Por favor, preencha todos os campos obrigatórios', + passwordsDoNotMatch: 'As senhas não coincidem', + passwordTooShort: 'A senha deve ter pelo menos 6 caracteres', + enterGroupName: 'Por favor, insira um nome de grupo', + settingsSaved: 'Configurações salvas', + cameraSettingsSaved: 'Configurações da câmera salvas', + enterCameraUrl: 'Por favor, insira a URL da câmera', + passwordChanged: 'Senha alterada com sucesso', + connectionFailed: 'Falha na conexão', + testFailed: 'Falha no teste', + cameraConnected: 'Câmera conectada{{resolution}}', + }, + testConnection: 'Testar Conexão', + catalog: { + spoolCatalog: 'Catálogo de Carretéis', + spoolCatalogDescription: 'Pesos de carretéis vazios por marca/tipo. Usado para pesquisa automática de peso ao adicionar carretéis.', + searchCatalog: 'Pesquisar no catálogo...', + addNewEntry: 'Adicionar Nova Entrada', + namePlaceholder: 'Nome (ex.: Bambu Lab - Plástico)', + weight: 'Peso', + type: 'Tipo', + default: 'Padrão', + custom: 'Personalizado', + noMatch: 'Nenhuma entrada corresponde à sua pesquisa', + empty: 'Nenhuma entrada no catálogo', + deleteEntry: 'Excluir Entrada', + deleteConfirm: 'Tem certeza de que deseja excluir "{{name}}"?', + resetCatalog: 'Redefinir Catálogo', + resetConfirm: 'Redefinir catálogo para os padrões? Isso removerá todas as entradas personalizadas.', + loadFailed: 'Falha ao carregar o catálogo de carretéis', + nameWeightRequired: 'Nome e peso são obrigatórios', + entryAdded: 'Entrada adicionada', + addFailed: 'Falha ao adicionar entrada', + entryUpdated: 'Entrada atualizada', + updateFailed: 'Falha ao atualizar entrada', + entryDeleted: 'Entrada excluída', + deleteFailed: 'Falha ao excluir entrada', + resetSuccess: 'Catálogo redefinido para os padrões', + resetFailed: 'Falha ao redefinir catálogo', + exported: 'Exportadas {{count}} entradas', + imported: 'Importadas {{added}} entradas ({{skipped}} ignoradas)', + importFailed: 'Falha ao importar: formato JSON inválido', + exportTooltip: 'Exportar catálogo para JSON', + importTooltip: 'Importar catálogo de JSON', + resetTooltip: 'Redefinir para os padrões', + }, + colorCatalog: { + title: 'Catálogo de Cores', + description: 'Cores de filamento por fabricante/material. Usado para pesquisa automática de cores ao adicionar carretéis.', + searchColors: 'Pesquisar cores...', + allManufacturers: 'Todos os fabricantes', + addNewColor: 'Adicionar Nova Cor', + manufacturer: 'Fabricante', + colorName: 'Nome da Cor', + hex: 'Hex', + materialOptional: 'Material (opcional)', + showing: 'Mostrando {{filtered}} de {{total}} cores', + noMatch: 'Nenhuma cor corresponde à sua pesquisa', + empty: 'Nenhuma cor no catálogo', + deleteColor: 'Excluir Cor', + deleteConfirm: 'Tem certeza de que deseja excluir "{{name}}"?', + resetCatalog: 'Redefinir Catálogo de Cores', + resetConfirm: 'Redefinir catálogo para os padrões? Isso removerá todas as cores personalizadas.', + sync: 'Sincronizar', + starting: 'Iniciando...', + syncTooltip: 'Sincronizar do FilamentColors.xyz (2000+ cores, pode levar um minuto)', + loadFailed: 'Falha ao carregar o catálogo de cores', + fieldsRequired: 'Fabricante, nome da cor e cor hex são obrigatórios', + colorAdded: 'Cor adicionada', + addFailed: 'Falha ao adicionar cor', + colorUpdated: 'Cor atualizada', + updateFailed: 'Falha ao atualizar cor', + colorDeleted: 'Cor excluída', + deleteFailed: 'Falha ao excluir cor', + resetSuccess: 'Catálogo de cores redefinido para os padrões', + resetFailed: 'Falha ao redefinir catálogo', + syncUpToDate: 'Já está atualizado ({{count}} cores verificadas)', + syncComplete: 'Adicionadas {{added}} novas cores ({{skipped}} já existiam)', + syncError: 'Erro de sincronização', + syncFailed: 'Falha ao sincronizar do FilamentColors.xyz', + exported: 'Exportadas {{count}} cores', + imported: 'Importadas {{added}} cores ({{skipped}} ignoradas)', + importFailed: 'Falha ao importar: formato JSON inválido', + }, + }, + + // Notifications (for push notifications) + notification: { + printStarted: { + title: 'Impressão Iniciada', + body: '{{printer}}: {{filename}} iniciou a impressão', + }, + printCompleted: { + title: 'Impressão Concluída', + body: '{{printer}}: {{filename}} foi concluída com sucesso', + }, + printFailed: { + title: 'Falha na Impressão', + body: '{{printer}}: {{filename}} falhou', + }, + printStopped: { + title: 'Impressão Interrompida', + body: '{{printer}}: {{filename}} foi interrompida', + }, + printProgress: { + title: 'Progresso da Impressão', + body: '{{printer}}: {{filename}} está {{percent}}% concluída', + }, + printerOffline: { + title: 'Impressora Offline', + body: '{{printer}} está offline', + }, + printerError: { + title: 'Erro na Impressora', + body: '{{printer}}: {{error}}', + }, + filamentLow: { + title: 'Filamento Baixo', + body: '{{printer}}: O filamento está acabando', + }, + maintenanceDue: { + title: 'Manutenção Pendente', + body: '{{printer}}: {{items}} precisam de atenção', + }, + }, + + // Errors + errors: { + generic: 'Algo deu errado', + networkError: 'Erro de rede. Por favor, verifique sua conexão.', + notFound: 'Não encontrado', + unauthorized: 'Não autorizado', + serverError: 'Erro no servidor', + validationError: 'Por favor, verifique sua entrada', + printerConnectionFailed: 'Falha ao conectar à impressora', + saveFailed: 'Falha ao salvar alterações', + deleteFailed: 'Falha ao excluir', + loadFailed: 'Falha ao carregar dados', + }, + + // HMS Errors modal + hmsErrors: { + title: 'Erros - {{name}}', + noErrors: 'Nenhum erro', + viewOnWiki: 'Ver no Bambu Lab Wiki', + clearInstructions: 'Limpe os erros na impressora para descartá-los aqui.', + clearErrors: 'Limpar Erros', + clearSuccess: 'Erros HMS limpos', + clearFailed: 'Falha ao limpar erros HMS', + }, + + // MQTT Debug modal + mqttDebug: { + title: 'MQTT Log de Depuração', + searchPlaceholder: 'Pesquisar tópico ou payload...', + noMessages: 'Nenhuma mensagem registrada ainda', + startLoggingHint: 'Clique em "Iniciar Registro" para começar a capturar mensagens MQTT', + noMessagesMatch: 'Nenhuma mensagem corresponde ao seu filtro', + adjustFilterHint: 'Tente ajustar seus critérios de pesquisa ou filtro', + incoming: 'Entrada', + outgoing: 'Saída', + loggingStopped: 'Registro interrompido', + loggingActive: 'Registro ativo - as mensagens serão atualizadas automaticamente', + startLogging: 'Iniciar Registro', + stopLogging: 'Parar Registro', + clearLog: 'Limpar Registro', + topic: 'ópico', + timestamp: 'Carimbo de Data/Hora', + direction: 'Direção', + all: 'Todos', + }, + + // Printer File Manager modal (printer internal storage) + printerFiles: { + title: 'Gerenciador de Arquivos', + storageUsed: 'Usado:', + storageFree: 'Livre:', + filterPlaceholder: 'Filtrar arquivos...', + deleteButton: 'Excluir', + deleteFiles: 'Excluir {{count}} arquivos', + deleteFileConfirm: 'Excluir "{{name}}"? Isso não pode ser desfeito.', + deleteFilesConfirm: 'Excluir {{count}} arquivos selecionados? Isso não pode ser desfeito.', + noFiles: 'Nenhum arquivo na impressora', + loadingFiles: 'Carregando arquivos...', + failedToLoad: 'Falha ao carregar arquivos', + toast: { + filesDeleted: 'Arquivos excluídos: {{count}}', + deleteFailed: 'Falha ao excluir: {{error}}', + }, + }, + + // Confirmations + confirm: { + delete: 'Tem certeza de que deseja excluir isso?', + unsavedChanges: 'Você tem alterações não salvas. Tem certeza de que deseja sair?', + clearQueue: 'Tem certeza de que deseja limpar a fila?', + }, + + // Login page + login: { + title: 'Bambuddy Login', + subtitle: 'Faça login na sua conta', + username: 'Nome de usuário', + usernamePlaceholder: 'Digite seu nome de usuário', + usernameOrEmail: 'Nome de usuário ou Email', + usernameOrEmailPlaceholder: 'Nome de usuário ou Email', + password: 'Senha', + passwordPlaceholder: 'Digite sua senha', + signIn: 'Entrar', + signingIn: 'Entrando...', + forgotPassword: 'Esqueceu sua senha?', + loginSuccess: 'Login realizado com sucesso', + loginFailed: 'Falha no login', + enterCredentials: 'Por favor, insira nome de usuário e 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.", + emailAddress: 'Endereço de Email', + emailPlaceholder: 'seu.email@exemplo.com', + cancel: 'Cancelar', + sending: 'Enviando...', + sendResetEmail: 'Enviar Email de Redefinição', + howToReset: 'Como redefinir sua senha:', + resetStep1: 'Entre em contato com o administrador do Bambuddy', + resetStep2: 'Peça para redefinir sua senha na Gestão de Usuários', + resetStep3: 'Eles podem definir uma nova senha temporária para você', + resetStep4: 'Faça login com a nova senha e altere-a nas Configurações', + gotIt: 'Entendi', + }, + + // Setup page + setup: { + title: 'Bambuddy Configuração', + subtitle: 'Configure a autenticação para sua instância do Bambuddy', + enableAuth: 'Ativar Autenticação', + adminAccount: 'Conta de Administrador', + adminAccountDesc: 'Se usuários administradores já existirem, a autenticação será ativada usando as contas de administrador existentes. Deixe os campos abaixo vazios para usar os administradores existentes ou insira novas credenciais para criar um novo usuário administrador.', + adminUsername: 'Nome de usuário do administrador', + adminPassword: 'Senha do administrador', + optionalIfAdminExists: '(opcional se usuários administradores existirem)', + adminUsernamePlaceholder: 'Digite o nome de usuário do administrador (opcional)', + adminPasswordPlaceholder: 'Digite a senha do administrador (opcional)', + confirmPassword: 'Confirmar Senha', + confirmPasswordPlaceholder: 'Confirme a senha do administrador', + settingUp: 'Configurando...', + completeSetup: 'Concluir Configuração', + toast: { + authEnabledAdminCreated: 'Autenticação ativada e usuário administrador criado', + authEnabledExistingAdmins: 'Autenticação ativada usando usuários administradores existentes', + setupCompleted: 'Configuração concluída', + enterBothCredentials: 'Por favor, insira o nome de usuário e a senha do administrador, ou deixe ambos vazios para usar os usuários administradores existentes', + passwordsDoNotMatch: 'As senhas não coincidem', + passwordTooShort: 'A senha deve ter pelo menos 6 caracteres', + }, + }, + + // Password change + changePassword: { + title: 'Alterar Senha', + currentPassword: 'Senha Atual', + currentPasswordPlaceholder: 'Digite a senha atual', + newPassword: 'Nova Senha', + newPasswordPlaceholder: 'Digite a nova senha (mínimo 6 caracteres)', + confirmPassword: 'Confirmar Senha', + confirmPasswordPlaceholder: 'Confirme a nova senha', + passwordsDoNotMatch: 'As senhas não coincidem', + passwordTooShort: 'A senha deve ter pelo menos 6 caracteres', + changing: 'Alterando...', + success: 'Senha alterada com sucesso', + failed: 'Falha ao alterar a senha', + }, + + // Plate detection alert + plateAlert: { + title: 'Impressão Pausada!', + message: 'Objetos detectados na mesa de impressão. A impressão foi automaticamente pausada. Por favor, limpe a mesa e retome a impressão.', + understand: 'Entendi', + }, + + // Camera page + camera: { + title: 'Visualização da Câmera', + invalidPrinterId: 'ID da impressora inválido', + live: 'Ao Vivo', + snapshot: 'Captura', + restartStream: 'Reiniciar transmissão', + refreshSnapshot: 'Atualizar captura', + fullscreen: 'Tela Cheia', + exitFullscreen: 'Sair da Tela Cheia', + connectingToCamera: 'Conectando à câmera...', + capturingSnapshot: 'Capturando imagem...', + connectionLost: 'Conexão perdida', + connectionFailed: 'Falha na conexão com a câmera', + reconnecting: 'Reconectando em {{countdown}}s... (tentativa {{attempt}}/{{max}})', + reconnectNow: 'Reconectar agora', + cameraUnavailable: 'Câmera indisponível', + cameraUnavailableDesc: 'Certifique-se de que a impressora está ligada e conectada.', + noCamera: 'Nenhuma câmera disponível', + retry: 'Tentar novamente', + cameraStream: 'Transmissão da câmera', + zoomOut: 'Reduzir zoom', + zoomIn: 'Aumentar zoom', + resetZoom: 'Redefinir zoom', + recording: 'Gravando', + startRecording: 'Iniciar gravação', + stopRecording: 'Parar gravação', + chamberLight: 'Alternar luz da câmara', + }, + + // Groups management + groups: { + title: 'Gerenciamento de Grupos', + subtitle: 'Gerenciar grupos de permissão para controle de acesso', + backToSettings: 'Voltar para Configurações', + createGroup: 'Criar Grupo', + noPermission: 'Você não tem permissão para acessar esta página.', + system: 'Sistema', + noDescription: 'Sem descrição', + usersCount: '{{count}} usuários', + permissionsCount: '{{count}} permissões', + edit: 'Editar', + delete: 'Excluir', + toast: { + created: 'Grupo criado com sucesso', + updated: 'Grupo atualizado com sucesso', + deleted: 'Grupo excluído com sucesso', + enterGroupName: 'Por favor, insira um nome para o grupo', + }, + modal: { + editGroup: 'Editar Grupo', + createGroup: 'Criar Grupo', + cancel: 'Cancelar', + saving: 'Salvando...', + creating: 'Criando...', + saveChanges: 'Salvar Alterações', + }, + form: { + groupName: 'Nome do Grupo', + groupNamePlaceholder: 'Insira o nome do grupo', + systemGroupWarning: 'Os nomes dos grupos do sistema não podem ser alterados', + description: 'Descrição', + descriptionPlaceholder: 'Insira a descrição (opcional)', + permissions: 'Permissões ({{count}} selecionadas)', + }, + deleteModal: { + title: 'Excluir Grupo', + message: 'Tem certeza de que deseja excluir este grupo? Os usuários deste grupo perderão essas permissões.', + confirm: 'Excluir Grupo', + }, + }, + + // Users management + users: { + title: 'Gerenciamento de Usuários', + subtitle: 'Gerenciar usuários e seu acesso à sua instância do Bambuddy', + backToSettings: 'Voltar para Configurações', + createUser: 'Criar Usuário', + noPermission: 'Você não tem permissão para acessar esta página.', + admin: 'Admin', + noGroups: 'Sem grupos', + active: 'Ativo', + inactive: 'Inativo', + edit: 'Editar', + delete: 'Excluir', + system: 'Sistema', + noGroupsAvailable: 'Nenhum grupo disponível', + table: { + username: 'Nome de Usuário', + groups: 'Grupos', + status: 'Status', + actions: 'Ações', + }, + toast: { + created: 'Usuário criado com sucesso', + updated: 'Usuário atualizado com sucesso', + deleted: 'Usuário excluído com sucesso', + fillRequired: 'Por favor, preencha todos os campos obrigatórios', + passwordsDoNotMatch: 'As senhas não coincidem', + passwordTooShort: 'A senha deve ter pelo menos 6 caracteres', + }, + modal: { + createUser: 'Criar Usuário', + editUser: 'Editar Usuário', + cancel: 'Cancelar', + creating: 'Criando...', + saving: 'Salvando...', + saveChanges: 'Salvar Alterações', + advancedAuthSubtitle: 'com Autenticação Avançada', + }, + form: { + username: 'Nome de Usuário', + usernamePlaceholder: 'Insira o nome de usuário', + email: 'Email', + emailPlaceholder: 'user@example.com', + password: 'Senha', + passwordPlaceholder: 'Insira a senha', + confirmPassword: 'Confirmar Senha', + confirmPasswordPlaceholder: 'Confirme a senha', + newPasswordPlaceholder: 'Insira a nova senha', + confirmNewPasswordPlaceholder: 'Confirme a nova senha', + leaveBlankToKeep: 'deixe em branco para manter a atual', + groups: 'Grupos', + optional: 'opcional', + autoGeneratedPassword: 'Uma senha segura será gerada automaticamente e enviada por e-mail ao usuário.', + passwordManagedByAdvancedAuth: 'A senha é gerenciada pela Autenticação Avançada. Use "Redefinir Senha" para enviar uma nova senha ao usuário por e-mail.', + resetPassword: 'Redefinir Senha', + resettingPassword: 'Redefinindo Senha...', + }, + deleteModal: { + title: 'Excluir Usuário', + message: 'Tem certeza de que deseja excluir este usuário? Esta ação não pode ser desfeita.', + confirm: 'Excluir Usuário', + }, + }, + + // Stream overlay + streamOverlay: { + title: 'Stream Overlay', + invalidPrinterId: 'ID da impressora inválido', + cameraStream: 'Transmissão da câmera', + progress: 'Progresso da impressão', + eta: 'ETA', + printerIdle: 'Impressora ociosa', + printerOffline: 'Impressora offline', + status: { + printing: 'Imprimindo', + paused: 'Pausado', + finished: 'Concluído', + failed: 'Falhou', + idle: 'Ocioso', + unknown: 'Desconhecido', + }, + }, + + // Profiles + profiles: { + title: 'Perfis', + subtitle: 'Gerencie seus presets de fatiador e calibrações de avanço de pressão', + tabs: { + cloud: 'Perfis na Nuvem', + local: 'Perfis Locais', + kprofiles: 'K-Perfis', + }, + localProfiles: { + title: 'Perfis Locais', + subtitle: 'Importe e gerencie presets de fatiador do OrcaSlicer', + import: 'Importar Perfis', + importDesc: 'Solte arquivos .bbscfg, .bbsflmt, .orca_filament, .zip ou .json aqui', + importing: 'Importando...', + search: 'Pesquisar presets locais...', + noPresets: 'Nenhum preset local ainda', + badge: 'Local', + edit: 'Editar', + delete: 'Excluir', + cancel: 'Cancelar', + deleteConfirmTitle: 'Excluir Preset', + deleteConfirm: 'Tem certeza de que deseja excluir este preset? Esta ação não pode ser desfeita.', + source: 'Fonte', + inheritsFrom: 'Herdado de', + filamentType: 'Tipo', + vendor: 'Fornecedor', + compatiblePrinters: 'Impressoras Compatíveis', + nozzleTemp: 'Temperatura do Bico', + cost: 'Custo', + density: 'Densidade', + pressureAdvance: 'Avanço de Pressão', + filament: 'Filamento', + process: 'Processo', + printer: 'Impressora', + toast: { + importSuccess: '{{count}} preset(s) importada(s)', + importSkipped: '{{count}} preset(s) ignorada(s) (duplicadas)', + importError: '{{count}} erro(s) durante a importação', + deleted: 'Preset excluído', + updated: 'Preset atualizado', + }, + }, + connectedAs: 'Conectado como', + logout: 'Sair', + noLogoutPermission: 'Você não tem permissão para sair', + failedToLoad: 'Falha ao carregar perfis', + retry: 'Tentar novamente', + time: { + justNow: 'Agora mesmo', + minsAgo: 'há {{count}} minutos', + hoursAgo: 'há {{count}} horas', + daysAgo: 'há {{count}} dias', + }, + toast: { + loggedOut: 'Desconectado', + }, + login: { + title: 'Conectar ao Bambu Cloud', + subtitle: 'Sincronize seus presets de fatiador entre dispositivos', + email: 'Email', + password: 'Senha', + region: 'Região', + regionGlobal: 'Global', + regionChina: 'China', + verificationCode: 'Código de Verificação', + totpCode: 'Código do Autenticador', + checkEmail: 'Verifique seu email ({{email}}) para um código de 6 dígitos', + enterTotpHint: 'Digite o código de 6 dígitos do seu aplicativo autenticador', + accessToken: 'Token de Acesso', + accessTokenHint: 'Cole seu token de acesso Bambu Lab (do Bambu Studio)', + back: 'Voltar', + loginButton: 'Entrar', + verifyButton: 'Verificar', + setTokenButton: 'Definir Token', + useToken: 'Usar token de acesso em vez disso', + useEmail: 'Entrar com email em vez disso', + toast: { + loggedIn: 'Conectado com sucesso', + codeSent: 'Código de verificação enviado para seu email', + enterTotp: 'Digite o código do seu aplicativo autenticador', + tokenSet: 'Token definido com sucesso', + }, + }, + presets: { + myPreset: 'Meu preset (editável)', + duplicate: 'Duplicar', + editable: 'Editável', + failedToLoadDetails: 'Falha ao carregar detalhes do preset', + deleteConfirm: 'Excluir este preset?', + deleteWarning: 'Isso excluirá permanentemente "{{name}}" do Bambu Cloud. Esta ação não pode ser desfeita.', + noDuplicatePermission: 'Você não tem permissão para duplicar presets', + noEditPermission: 'Você não tem permissão para editar presets', + noDeletePermission: 'Você não tem permissão para excluir presets', + types: { + filament: 'Preset de filamento', + printer: 'Preset de impressora', + process: 'Preset de processo', + }, + toast: { + deleted: 'Preset excluído', + created: 'Preset criado', + updated: 'Preset atualizado', + duplicated: 'Preset duplicado', + fieldAdded: 'Campo "{{key}}" adicionado', + exported: 'Preset exportado', + }, + baseLabel: 'Base: {{name}}', + currentLabel: 'Atual: {{name}}', + newPreset: 'Novo Preset', + editPreset: 'Editar Preset', + duplicatePreset: 'Duplicar Preset', + createNewPreset: 'Criar Novo Preset', + customizeSettings: 'Personalizar configurações para seu novo preset', + compareWithBase: 'Comparar com o preset base', + compare: 'Comparar', + // CreatePresetModal - Basic Info + basePreset: 'Preset Base', + selectBasePreset: 'Selecionar preset base...', + presetName: 'Nome do Preset', + myCustomPreset: 'Meu preset personalizado', + inheritsFrom: 'Herdado de', + dropJsonToImport: 'Solte o arquivo JSON para importar', + // CreatePresetModal - Tabs + tabs: { + common: 'Comum', + allFields: 'Todos os Campos', + }, + // CreatePresetModal - All Fields Tab + availableFields: 'Campos Disponíveis', + searchFieldsPlaceholder: 'Pesquisar campos...', + noMatchingFields: 'Nenhum campo correspondente', + allFieldsAdded: 'Todos os campos adicionados', + addCustomField: 'Adicionar campo personalizado', + yourOverrides: 'Suas Substituições', + noOverridesYet: 'Nenhuma substituição ainda', + clickFieldsToAdd: 'Clique nos campos à esquerda para adicioná-los', + saveAsTemplate: 'Salvar como modelo', + jsonTip: 'Dica: Arraste e solte um arquivo .json em qualquer lugar deste modal para importar configurações', + }, + cloudView: { + searchPlaceholder: 'Pesquisar presets...', + templates: 'Modelos', + refresh: 'Atualizar', + newPreset: 'Novo Preset', + clearFilters: 'Limpar filtros', + // Compare mode + compareMode: 'Modo de Comparação', + selectAnotherPreset: 'Selecionar outro preset {{type}}', + clickTwoPresets: 'Clique em dois presets do mesmo tipo para comparar', + selectFirst: '1. Selecionar primeiro', + selectSecond: '2. Selecionar segundo', + compareNow: 'Comparar Agora', + // Status row + lastSynced: 'Última sincronização:', + showingCount: 'Mostrando {{showing}} de {{total}} presets', + noPresetsFound: 'Nenhum preset encontrado', + // Column headers + columns: { + filament: 'Filamento', + process: 'Processo', + printer: 'Impressora', + }, + noFilamentPresets: 'Nenhum preset de filamento', + noProcessPresets: 'Nenhum preset de processo', + noPrinterPresets: 'Nenhum preset de impressora', + // Filters + filters: { + type: 'Tipo', + owner: 'Proprietário', + printer: 'Impressora', + nozzle: 'Bico', + filament: 'Filamento', + layer: 'Camada', + all: 'Todos', + myPresets: 'Meus Presets', + builtIn: 'Integrado', + process: 'Processo', + }, + // Permissions + noTemplatesPermission: 'Você não tem permissão para gerenciar modelos', + noRefreshPermission: 'Você não tem permissão para atualizar perfis', + noCreatePermission: 'Você não tem permissão para criar presets', + }, + templates: { + title: 'Modelos Rápidos', + noTemplates: 'Nenhum modelo ainda', + createFirst: 'Crie modelos a partir do editor de presets', + typeFilter: 'Tipo:', + deleteTitle: 'Excluir Modelo', + deleteWarning: 'Esta ação não pode ser desfeita', + deleteConfirm: 'Tem certeza de que deseja excluir "{{name}}"?', + namePlaceholder: 'Nome do modelo', + descriptionPlaceholder: 'Descrição', + settingsJson: 'Configurações (JSON)', + fieldsCount: '{{count}} campos', + shownInModals: 'Exibido em modais', + hiddenInModals: 'Oculto em modais', + apply: 'Aplicar', + toast: { + deleted: 'Modelo excluído', + updated: 'Modelo atualizado', + created: 'Modelo criado', + applied: 'Modelo aplicado', + }, + }, + }, + + // Support/Debug + support: { + debugLoggingActive: 'Registro de depuração ativo', + manageLogs: 'Gerenciar', + collectItem7: 'Conectividade da impressora e versões de firmware', + collectItem8: 'Status de integração (Spoolman, MQTT, HA)', + collectItem9: 'Interfaces de rede (somente sub-redes)', + collectItem10: 'Versões de pacotes Python', + collectItem11: 'Verificações de integridade do banco de dados', + collectItem12: 'Detalhes do ambiente Docker', + }, + + // File manager + fileManager: { + title: 'Gerenciador de Arquivos', + subtitle: 'Organize e gerencie seus arquivos de impressão', + uploadFiles: 'Enviar Arquivos', + newFolder: 'Nova Pasta', + folderName: 'Nome da Pasta', + folderNamePlaceholder: 'ex.: Peças Funcionais', + renameFile: 'Renomear Arquivo', + renameFolder: 'Renomear Pasta', + moveFiles: 'Mover {{count}} Arquivo(s)', + rootNoFolder: 'Raiz (Sem Pasta)', + current: 'Atual', + linkFolder: 'Vincular Pasta', + linkFolderDescription: 'Vincular "{{name}}" a um projeto ou arquivo para acesso rápido.', + project: 'Projeto', + archive: 'Arquivo', + noProjectsFound: 'Nenhum projeto encontrado', + noArchivesFound: 'Nenhum arquivo encontrado', + unlink: 'Desvincular', + link: 'Vincular', + dragDropFiles: 'Arraste e solte os arquivos aqui', + dropFilesHere: 'Solte os arquivos aqui', + orClickToBrowse: 'ou clique para procurar', + allFileTypesSupported: 'Todos os tipos de arquivos são suportados. Arquivos ZIP serão extraídos.', + zipFilesDetected: 'Arquivos ZIP detectados', + zipExtractOptions: 'Arquivos ZIP serão extraídos. Escolha como lidar com a estrutura de pastas:', + preserveZipStructure: 'Preservar estrutura de pastas do ZIP', + createFolderFromZip: 'Criar pasta a partir do nome do arquivo ZIP', + stlThumbnailGeneration: 'Geração de miniaturas STL', + zipMayContainStl: 'Arquivos ZIP podem conter arquivos STL. Miniaturas podem ser geradas durante a extração.', + thumbnailsCanBeGenerated: 'Miniaturas podem ser geradas para arquivos STL. Modelos grandes podem levar mais tempo para processar.', + generateThumbnailsForStl: 'Gerar miniaturas para arquivos STL', + threemfDetected: 'Arquivos 3MF detectados', + threemfExtractionInfo: 'Modelo da impressora, material, cor e configurações de impressão serão extraídos automaticamente dos arquivos 3MF.', + willBeExtracted: 'Será extraído', + filesExtracted: '{{count}} arquivos extraídos', + uploadComplete: 'Upload concluído: {{succeeded}} bem-sucedidos', + uploadFailed: '{{count}} falhou', + uploading: 'Enviando...', + changeLink: 'Alterar link...', + linkTo: 'Vincular a...', + linkToProjectOrArchive: 'Vincular a projeto ou arquivo', + addToQueue: 'Adicionar à fila', + schedulePrint: 'Agendar impressão', + generateThumbnail: 'Gerar miniatura', + generateThumbnails: 'Gerar miniaturas', + generateThumbnailsForMissing: 'Gerar miniaturas para arquivos STL que não possuem', + gridView: 'Visualização em grade', + listView: 'Visualização em lista', + lowDiskSpaceWarning: 'Aviso de pouco espaço em disco', + lowDiskSpaceDetails: 'Apenas {{free}} livres de {{total}} no total. O limite está definido para {{threshold}} GB nas configurações.', + files: 'Arquivos', + folders: 'Pastas', + size: 'Tamanho', + free: 'Livre', + allFiles: 'Todos os arquivos', + wrap: 'Quebrar texto', + enableTextWrapping: 'Ativar quebra de texto', + disableTextWrapping: 'Desativar quebra de texto', + dragToResizeTooltip: 'Arraste para redimensionar, clique duas vezes para redefinir', + searchFiles: 'Pesquisar arquivos...', + allTypes: 'Todos os tipos', + prints: 'Impressões', + ascending: 'Crescente', + descending: 'Decrescente', + resultsCount: '{{showing}} de {{total}} arquivos', + selectAll: 'Selecionar tudo', + deselectAll: 'Desmarcar tudo', + selected: '{{count}} selecionado(s)', + adding: 'Adicionando...', + loadingFiles: 'Carregando arquivos...', + folderIsEmpty: 'A pasta está vazia', + noFilesYet: 'Nenhum arquivo ainda', + folderEmptyDescription: 'Envie arquivos ou mova arquivos para esta pasta para começar.', + noFilesDescription: 'Envie arquivos para começar a organizar seus arquivos relacionados à impressão.', + noMatchingFiles: 'Nenhum arquivo correspondente', + noMatchingFilesDescription: 'Nenhum arquivo corresponde aos seus critérios de pesquisa ou filtro.', + clearFilters: 'Limpar filtros', + printedCount: 'Impresso {{count}}x', + uploadedBy: 'Enviado por', + deleteFolder: 'Excluir pasta', + deleteFile: 'Excluir arquivo', + deleteFilesCount: 'Excluir {{count}} arquivos', + deleteFolderConfirm: 'Tem certeza de que deseja excluir esta pasta? Todos os arquivos dentro também serão excluídos.', + deleteFileConfirm: 'Tem certeza de que deseja excluir este arquivo?', + deleteFilesConfirm: 'Tem certeza de que deseja excluir {{count}} arquivos selecionados? Esta ação não pode ser desfeita.', + deleting: 'Excluindo...', + noPermissionRenameFolder: 'Você não tem permissão para renomear pastas', + noPermissionLinkFolder: 'Você não tem permissão para vincular pastas', + noPermissionDeleteFolder: 'Você não tem permissão para excluir pastas', + noPermissionPrint: 'Você não tem permissão para imprimir', + noPermissionAddToQueue: 'Você não tem permissão para adicionar à fila', + noPermissionDownload: 'Você não tem permissão para baixar arquivos', + noPermissionRenameFile: 'Você não tem permissão para renomear este arquivo', + noPermissionGenerateThumbnail: 'Você não tem permissão para gerar miniaturas', + noPermissionDeleteFile: 'Você não tem permissão para excluir este arquivo', + noPermissionCreateFolder: 'Você não tem permissão para criar pastas', + noPermissionUpload: 'Você não tem permissão para enviar arquivos', + noPermissionMoveFiles: 'Você não tem permissão para mover arquivos', + noPermissionDeleteFiles: 'Você não tem permissão para excluir arquivos', + toast: { + folderCreated: 'Pasta criada', + folderDeleted: 'Pasta excluída', + fileDeleted: 'Arquivo excluído', + filesDeleted: 'Excluídos {{count}} arquivos', + filesMoved: 'Arquivos movidos', + folderLinked: 'Pasta vinculada', + folderUnlinked: 'Pasta desvinculada', + addedToQueue: 'Adicionado {{count}} arquivo(s) à fila', + addedToQueuePartial: 'Adicionado {{added}} arquivo(s), {{failed}} falharam', + failedToAddToQueue: 'Falha ao adicionar arquivos: {{error}}', + fileRenamed: 'Arquivo renomeado', + folderRenamed: 'Pasta renomeada', + thumbnailsGenerated: 'Geradas {{count}} miniatura(s)', + thumbnailsGeneratedPartial: 'Geradas {{succeeded}} miniatura(s), {{failed}} falharam', + noStlMissingThumbnails: 'Nenhum arquivo STL sem miniatura', + failedToGenerateThumbnails: 'Falha ao gerar miniaturas: {{error}}', + thumbnailGenerated: 'Miniatura gerada', + failedToGenerateThumbnail: 'Falha ao gerar miniatura: {{error}}', + }, + }, + + // Projects + projects: { + title: 'Projetos', + subtitle: 'Organize e acompanhe seus projetos de impressão 3D', + newProject: 'Novo Projeto', + editProject: 'Editar Projeto', + deleteProject: 'Excluir Projeto', + projectName: 'Nome do Projeto', + description: 'Descrição', + noProjects: 'Nenhum projeto ainda', + noProjectsFiltered: 'Nenhum projeto {{status}}', + 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.', + createFirstButton: 'Crie Seu Primeiro Projeto', + create: 'Criar', + files: 'Arquivos', + prints: 'Impressões', + plates: 'Placas', + parts: 'Peças', + lastModified: 'Última Modificação', + deleteConfirm: 'Tem certeza de que deseja excluir este projeto? Arquivos e itens da fila serão desvinculados, mas não excluídos.', + addFiles: 'Adicionar Arquivos', + removeFile: 'Remover Arquivo', + viewDetails: 'Ver Detalhes', + // Modal fields + namePlaceholder: 'ex., Voron 2.4 Build', + descriptionPlaceholder: 'Descrição opcional...', + color: 'Cor', + targetPlates: 'Placas Alvo', + targetPlatesPlaceholder: 'ex., 25', + targetPlatesHelp: 'Número de trabalhos de impressão', + targetParts: 'Peças Alvo', + targetPartsPlaceholder: 'ex., 150', + targetPartsHelp: 'Total de objetos necessários', + tagsLabel: 'Tags (separadas por vírgula)', + tagsPlaceholder: 'ex., voron, funcional, presente', + dueDate: 'Data de Vencimento', + priority: 'Prioridade', + priorityLow: 'Baixa', + priorityNormal: 'Normal', + priorityHigh: 'Alta', + priorityUrgent: 'Urgente', + // Status + statusActive: 'Ativo', + statusCompleted: 'Concluído', + statusArchived: 'Arquivado', + done: 'Concluído', + completed: 'Concluído', + failed: 'Falhou', + inQueue: 'Na fila', + noPrintsYet: 'Nenhuma impressão ainda', + // Footer stats + printJobs: 'Trabalhos de impressão (placas)', + partsPrinted: 'Peças impressas', + failedParts: 'Peças falhadas', + // Actions + import: 'Importar', + export: 'Exportar', + importProject: 'Importar projeto', + exportAll: 'Exportar todos os projetos', + loading: 'Carregando projetos...', + // Permissions + noEditPermission: 'Você não tem permissão para editar projetos', + noDeletePermission: 'Você não tem permissão para excluir projetos', + noCreatePermission: 'Você não tem permissão para criar projetos', + noImportPermission: 'Você não tem permissão para importar projetos', + noExportPermission: 'Você não tem permissão para exportar projetos', + // Toast + toast: { + created: 'Projeto criado', + updated: 'Projeto atualizado', + deleted: 'Projeto excluído', + imported: 'Projeto importado', + multipleImported: '{{count}} projetos importados', + importFailed: 'Falha na importação', + exported: 'Projetos exportados (apenas metadados)', + }, + }, + + // Project detail page + projectDetail: { + notFound: 'Projeto não encontrado', + backToProjects: 'Voltar para Projetos', + export: 'Exportar', + exportProject: 'Exportar projeto', + noExportPermission: 'Você não tem permissão para exportar projetos', + noEditPermission: 'Você não tem permissão para editar projetos', + partOf: 'Parte de:', + priorityLabel: 'Prioridade:', + noPrints: 'Nenhuma impressão neste projeto ainda', + status: { + active: 'Ativo', + completed: 'Concluído', + archived: 'Arquivado', + }, + priority: { + low: 'Baixa', + normal: 'Normal', + high: 'Alta', + urgent: 'Urgente', + }, + dueDate: { + overdue: 'Atrasado', + today: 'Vence hoje', + daysLeft: '{{count}} dias restantes', + }, + progress: { + platesProgress: 'Progresso das Placas', + partsProgress: 'Progresso das Peças', + printJobs: 'Trabalhos de Impressão', + parts: 'Peças', + percentComplete: '{{percent}}% concluído', + remaining: '{{count}} restantes', + }, + stats: { + printJobs: 'Trabalhos de Impressão', + total: 'total', + failed: '{{count}} falhou', + partsPrinted: '{{count}} peças impressas', + printTime: 'Tempo de Impressão', + filamentUsed: 'Filamento Usado', + }, + cost: { + title: 'Rastreamento de Custos', + filamentCost: 'Custo do Filamento', + energy: 'Energia', + budget: 'Orçamento', + remaining: 'Restante', + }, + subProjects: { + title: 'Sub-projetos ({{count}})', + }, + notes: { + title: 'Notas', + noEditPermission: 'Você não tem permissão para editar notas', + placeholder: 'Adicione notas sobre este projeto...', + empty: 'Nenhuma nota ainda. Clique em Editar para adicionar notas.', + }, + files: { + title: 'Arquivos', + linkFolders: 'Vincular pastas do Gerenciador de Arquivos', + forQuickAccess: 'a este projeto para acesso rápido.', + fileCount: '{{count}} arquivo(s)', + empty: 'Nenhuma pasta vinculada. Vá para o Gerenciador de Arquivos e vincule uma pasta a este projeto.', + }, + bom: { + title: 'Lista de Materiais', + acquired: '{{completed}}/{{total}} adquiridos', + showAll: 'Mostrar todos', + hideDone: 'Ocultar concluídos', + addPart: 'Adicionar Peça', + noAddPermission: 'Você não tem permissão para adicionar peças', + partNamePlaceholder: 'Nome da peça (ex.: parafusos M3x8)', + partName: 'Nome da peça', + qty: 'Quantidade', + price: 'Preço ({{currency}})', + sourcingUrlPlaceholder: 'URL de fornecimento (opcional)', + remarksPlaceholder: 'Observações (opcional)', + deletePart: 'Excluir Peça', + deleteConfirm: 'Tem certeza de que deseja excluir "{{name}}"?', + noUpdatePermission: 'Você não tem permissão para atualizar peças', + noEditPermission: 'Você não tem permissão para editar peças', + noDeletePermission: 'Você não tem permissão para excluir peças', + totalCost: 'Custo total:', + empty: 'Nenhuma peça na lista de materiais. Adicione hardware, eletrônicos ou outros componentes para rastrear o que precisa ser adquirido.', + }, + timeline: { + title: 'Linha do Tempo de Atividades', + empty: 'Nenhuma atividade ainda.', + }, + template: { + saveAsTemplate: 'Salvar como Modelo', + noCreatePermission: 'Você não tem permissão para criar modelos', + }, + queue: { + title: 'Fila', + viewAll: 'Ver todos', + printing: '{{count}} imprimindo', + queued: '{{count}} na fila', + }, + prints: { + title: 'Impressões ({{count}})', + }, + toast: { + projectUpdated: 'Projeto atualizado', + partAdded: 'Peça adicionada', + partRemoved: 'Peça removida', + exportFailed: 'Falha na exportação', + projectExported: 'Projeto exportado', + templateCreated: 'Modelo criado', + }, + }, + + // System info + system: { + title: 'Informações do Sistema', + version: 'Versão', + uptime: 'Tempo de Atividade', + cpuUsage: 'Uso da CPU', + memoryUsage: 'Uso da Memória', + diskUsage: 'Uso do Disco', + networkInfo: 'Informações de Rede', + logs: 'Logs', + debugMode: 'Modo de Depuração', + enableDebug: 'Ativar Registro de Depuração', + disableDebug: 'Desativar Registro de Depuração', + downloadLogs: 'Baixar Logs', + clearLogs: 'Limpar Logs', + dockerInfo: 'Informações do Docker', + containerName: 'Nome do Contêiner', + imageName: 'Nome da Imagem', + platform: 'Plataforma', + architecture: 'Arquitetura', + }, + + // Library (K Profiles) + library: { + title: 'Biblioteca de Filamentos', + addFilament: 'Adicionar Filamento', + editFilament: 'Editar Filamento', + deleteFilament: 'Excluir Filamento', + vendor: 'Fornecedor', + material: 'Material', + color: 'Cor', + kFactor: 'Fator K', + temperature: 'Temperatura', + noFilaments: 'Nenhum filamento na biblioteca', + deleteConfirm: 'Tem certeza de que deseja excluir este filamento?', + importFromPrinter: 'Importar da Impressora', + exportToFile: 'Exportar para Arquivo', + }, + + // Spoolman + spoolman: { + title: 'Integração com Spoolman', + enabled: 'Spoolman Ativado', + url: 'URL do Spoolman', + connected: 'Conectado', + disconnected: 'Não Conectado', + testConnection: 'Testar Conexão', + sync: 'Sincronizar', + syncing: 'Sincronizando...', + lastSync: 'Última Sincronização', + linkToSpoolman: 'Vincular ao Spoolman', + openInSpoolman: 'Abrir no Spoolman', + unlinkSpool: 'Desvincular Carretel', + selectSpool: 'Selecionar Carretel', + noUnlinkedSpools: 'Nenhum carretel desvinculado disponível', + linkSuccess: 'Carretel vinculado ao Spoolman com sucesso', + linkFailed: 'Falha ao vincular carretel', + spoolId: 'Carretel ID (Spool ID)', + fillSourceLabel: '(Spoolman)', + weight: 'Peso', + remaining: 'Restante', + 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.", + 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.', + }, + + // Inventory + inventory: { + title: 'Inventário de Carretéis', + addSpool: 'Adicionar Carretel', + editSpool: 'Editar Carretel', + material: 'Material', + selectMaterial: 'Selecionar material...', + subtype: 'Subtipo', + brand: 'Marca', + searchBrand: 'Pesquisar marca...', + useCustomBrand: 'Usar "{{brand}}"', + colorName: 'Nome da Cor', + colorNamePlaceholder: 'Jade White, Fire Red...', + color: 'Cor', + hexColor: 'Cor Hexadecimal', + pickColor: 'Escolher cor personalizada', + labelWeight: 'Peso da Etiqueta', + coreWeight: 'Peso do Carretel Vazio', + searchSpoolWeight: 'Pesquisar peso do carretel...', + weightUsed: 'Usado', + currentWeight: 'Peso Restante', + measuredWeight: 'Peso Medido', + measuredWeightError: 'O peso medido deve estar entre {{min}}g e {{max}}g.', + slicerFilament: 'Filamento do Fatiador', + slicerFilamentName: 'Nome do Predefinido do Fatiador', + slicerPreset: 'Predefinido do Fatiador', + searchPresets: 'Pesquisar predefinições de filamento...', + selectedPreset: 'Selecionado', + noPresetsFound: 'Nenhuma predefinição encontrada', + tempOverrides: 'Substituições de Temperatura', + note: 'Nota', + notePlaceholder: 'Quaisquer notas adicionais sobre este spool...', + archive: 'Arquivar', + restore: 'Restaurar', + noSpools: 'Nenhum carretel ainda. Adicione seu primeiro carretel para começar.', + noManualSpools: 'Nenhum carretel adicionado manualmente disponível. Adicione um carretel ao seu inventário primeiro.', + kProfiles: 'K-Perfis', + addKProfile: 'Adicionar K-Perfil', + assignSpool: 'Atribuir Carretel', + unassignSpool: 'Desatribuir', + assignSuccess: 'Carretel atribuído e slot AMS configurado', + assignFailed: 'Falha ao atribuir carretel', + selectSpool: 'Selecione um carretel para atribuir a este slot', + assigned: 'Atribuído', + assigning: 'Atribuindo...', + searchSpools: 'Pesquisar carretéis...', + allMaterials: 'Todos os Materiais', + filterByBrand: 'Filtrar por marca...', + showArchived: 'Mostrar arquivados', + spoolCreated: 'Carretel criado', + spoolUpdated: 'Carretel atualizado', + spoolDeleted: 'Carretel excluído', + spoolArchived: 'Carretel arquivado', + spoolRestored: 'Carretel restaurado', + deleteConfirm: 'Tem certeza de que deseja excluir este carretel? Esta ação não pode ser desfeita.', + archiveConfirm: 'Tem certeza de que deseja arquivar este carretel?', + advancedSettings: 'Configurações Avançadas', + // Tabs + filamentInfoTab: 'Informações do Filamento', + paProfileTab: 'Perfil PA', + filamentInfo: 'Filamento', + additional: 'Adicional', + // Cloud + loadingPresets: 'Carregando predefinições da nuvem...', + cloudConnected: 'Nuvem conectada', + cloudNotConnected: 'Nuvem não conectada (usando padrões)', + // Colors + recentColors: 'Recentes', + searchColors: 'Pesquisar cores...', + searchResults: 'Resultados da pesquisa', + allColors: 'Todas as cores', + commonColors: 'Cores comuns', + showLess: 'Mostrar menos', + showAll: 'Mostrar tudo', + noColorsFound: 'Nenhuma cor corresponde à sua pesquisa', + noResults: 'Nenhum resultado encontrado', + // PA Profiles + selectMaterialFirst: 'Por favor, selecione um material primeiro na aba Informações do Filamento.', + noPrintersConfigured: 'Nenhuma impressora configurada. Adicione impressoras para usar perfis PA.', + matchingFilter: 'Correspondente', + anyBrand: 'Qualquer marca', + anyVariant: 'Qualquer variante', + autoSelect: 'Seleção automática', + matches: 'correspondências', + match: 'correspondência', + noMatches: 'Nenhuma correspondência', + connected: 'Conectado', + offline: 'Offline', + printerOffline: 'A impressora está offline. Conecte-se para visualizar os perfis de calibração.', + noKProfilesMatch: 'Nenhum K-perfil corresponde ao filamento selecionado.', + leftNozzle: 'Bico Esquerdo', + rightNozzle: 'Bico Direito', + profilesSelected: 'perfil(is) de calibração selecionado(s)', + // Stats & enhanced table + totalInventory: 'Inventário Total', + totalConsumed: 'Total Consumido', + byMaterial: 'Por Material', + inPrinter: 'Na Impressora', + lowStock: 'Estoque Baixo', + sinceTracking: 'Desde o início do rastreamento', + loadedInAms: 'Carregado no AMS/Ext', + remaining: 'Restante', + lowStockThreshold: '<20% restante', + search: 'Pesquisar carretéis...', + showing: 'Mostrando', + to: 'até', + of: 'de', + show: 'Mostrar', + spools: 'carretéis', + spool: 'carretel', + page: 'Página', + noSpoolsMatch: 'Nenhum resultado encontrado', + noSpoolsMatchDesc: 'Tente ajustar sua pesquisa ou filtros para encontrar o que você está procurando.', + active: 'Ativo', + archived: 'Arquivado', + all: 'Todos', + used: 'Usado', + new: 'Novo', + clearFilters: 'Limpar filtros', + table: 'Tabela', + cards: 'Cartões', + net: 'Líquido', + // Column config + columns: 'Colunas', + configureColumns: 'Configurar Colunas', + configureColumnsDesc: 'Arraste para reordenar as colunas ou use as setas. Alterne a visibilidade com o ícone de olho.', + visible: 'Visível', + reset: 'Redefinir', + cancel: 'Cancelar', + applyChanges: 'Aplicar Alterações', + moveUp: 'Mover para cima', + moveDown: 'Mover para baixo', + hideColumn: 'Ocultar coluna', + showColumn: 'Mostrar coluna', + // Tag linking + linkToSpool: 'Vincular ao Carretel', + tagLinked: 'Tag vinculada ao carretel', + tagLinkFailed: 'Falha ao vincular tag', + tagAlreadyLinked: 'Tag já vinculada a outro carretel', + unknownTag: 'Tag RFID desconhecida detectada', + // Usage history + usageHistory: 'Histórico de Uso', + noUsageHistory: 'Nenhum uso registrado ainda', + printName: 'Nome da Impressão', + weightConsumed: 'Peso Consumido', + clearHistory: 'Limpar', + historyCleared: 'Histórico de uso limpo', + fillSourceLabel: '(Inv)', + }, + + // Timelapse + timelapse: { + title: 'Timelapse', + create: 'Criar Timelapse', + download: 'Baixar', + delete: 'Excluir', + preview: 'Visualizar', + frameRate: 'Taxa de Quadros', + quality: 'Qualidade', + processing: 'Processando...', + noTimelapses: 'Nenhum timelapse disponível', + }, + + // AMS + ams: { + title: 'AMS', + slot: 'Slot', + empty: 'Vazio', + emptySlot: 'Slot vazio', + unknown: 'Desconhecido', + humidity: 'Umidade', + temperature: 'Temperatura', + filamentType: 'Tipo de Filamento', + filamentColor: 'Cor', + remaining: 'Restante', + history: 'Histórico do AMS', + noHistory: 'Nenhum histórico disponível', + configureSlot: 'Configurar Slot', + externalSpool: 'Carretel Externo', + profile: 'Perfil', + kFactor: 'Fator K', + fill: 'Preencher', + configure: 'Configurar', + }, + + // Print modal + printModal: { + title: 'Iniciar Impressão', + selectPrinter: 'Selecionar Impressora', + selectPlate: 'Selecionar Placa', + filamentMapping: 'Mapeamento de Filamento', + printSettings: 'Configurações de Impressão', + bedLeveling: 'Nivelamento da Mesa', + flowCalibration: 'Calibração de Fluxo', + vibrationCalibration: 'Calibração de Vibração', + layerInspection: 'Inspeção da Primeira Camada', + timelapse: 'Timelapse', + startPrint: 'Iniciar Impressão', + addToQueue: 'Adicionar à Fila', + cancel: 'Cancelar', + noPrintersAvailable: 'Nenhuma impressora disponível', + printerBusy: 'Impressora ocupada', + printerOffline: 'Impressora offline', + sameTypeDifferentColor: 'Mesmo tipo, cor diferente', + filamentTypeNotLoaded: 'Tipo de filamento não carregado', + openCalendar: 'Abrir calendário', + leftNozzle: 'L', + rightNozzle: 'R', + leftNozzleTooltip: 'Bico esquerdo', + rightNozzleTooltip: 'Bico direito', + }, + + // Backup + backup: { + title: 'Bakup e Restauração', + createBackup: 'Criar Backup', + restoreBackup: 'Restaurar Backup', + restoreDescription: 'Substituir todos os dados a partir de um arquivo de backup', + downloadBackup: 'Baixar Backup', + uploadBackup: 'Enviar Backup', + lastBackup: 'Último Backup', + autoBackup: 'Auto Backup', + backupNow: 'Fazer Backup Agora', + restoreWarning: 'Aviso: Restaurar um backup substituirá todos os dados atuais.', + includeArchives: 'Incluir Arquivos', + includeSettings: 'Incluir Configurações', + includeProfiles: 'Incluir Perfis', + backupSuccess: 'Backup criado com sucesso', + restoreSuccess: 'Backup restaurado com sucesso', + backupFailed: 'Falha ao criar backup', + restoreFailed: 'Falha ao restaurar backup', + restoreNote: 'A impressora virtual será parada durante a restauração', + }, + + // Tags + tags: { + title: 'Tags', + addTag: 'Adicionar Tag', + editTag: 'Editar Tag', + deleteTag: 'Excluir Tag', + tagName: 'Nome da Tag', + tagColor: 'Cor da Tag', + noTags: 'Nenhuma tag', + deleteConfirm: 'Tem certeza de que deseja excluir esta tag?', + manageTags: 'Gerenciar Tags', + }, + + // Upload modal (archives) + uploadModal: { + title: 'Upload Arquivos 3MF', + dragDrop: 'Arraste e solte arquivos .3mf aqui', + or: 'ou', + browseFiles: 'Procurar Arquivos', + extractionInfo: 'O modelo da impressora será extraído automaticamente dos metadados do arquivo 3MF.', + uploaded: 'enviado', + failed: 'falhou', + uploading: 'Enviando...', + upload: 'Enviar', + uploadFailed: 'Falha no envio', + }, + + // Edit archive modal + // Edit Archive Modal + editArchive: { + title: 'Editar Arquivo', + name: 'Nome', + namePlaceholder: 'Nome da impressão', + printer: 'Impressora', + noPrinter: 'Nenhuma impressora', + project: 'Projeto', + noProject: 'Nenhum projeto', + itemsPrinted: 'Itens Impressos', + itemsPrintedHelp: 'Número de itens produzidos neste trabalho de impressão', + notes: 'Notas', + notesPlaceholder: 'Adicione notas sobre esta impressão...', + externalLink: 'Link Externo', + externalLinkPlaceholder: 'https://printables.com/model/...', + externalLinkHelp: 'Link para Printables, Thingiverse ou outra fonte', + tags: 'Tags', + tagsPlaceholder: 'Adicionar tags...', + addMoreTags: 'Adicionar mais tags...', + matchingTags: 'Correspondendo "{{query}}"', + existingTags: 'Tags existentes', + clickToAdd: '(clique para adicionar)', + status: 'Status', + failureReason: 'Motivo da Falha', + selectReason: 'Selecione o motivo...', + photos: 'Fotos do Resultado da Impressão', + photosHelp: 'Clique em + para adicionar fotos do seu resultado impresso', + printResult: 'Resultado da Impressão', + saving: 'Salvando...', + // Failure reasons + failureReasons: { + adhesionFailure: 'Falha de adesão', + spaghettiDetached: 'Spaghetti / Destacado', + layerShift: 'Deslocamento de camada', + cloggedNozzle: 'Bico entupido', + filamentRunout: 'Fim do filamento', + warping: 'Warping', + stringing: 'Stringing', + underExtrusion: 'Under-extrusion', + powerFailure: 'Falha de energia', + userCancelled: 'Cancelado pelo usuário', + other: 'Outro', + }, + // Archive statuses + statuses: { + completed: 'Concluído', + failed: 'Falhou', + aborted: 'Cancelado', + printing: 'Imprimindo', + }, + }, + + // K-Profiles + kProfiles: { + title: 'K-Profiles', + noPrintersConfigured: 'Nenhuma impressora configurada', + addPrinterInSettings: 'Adicione uma impressora nas Configurações para gerenciar K-profiles', + noActivePrinters: 'Nenhuma impressora ativa', + enablePrinterConnection: 'Ative a conexão da impressora para visualizar seus K-profiles', + loadingProfiles: 'Carregando K-Profiles...', + printerOffline: 'Impressora Offline', + printerOfflineDesc: 'A impressora selecionada não está conectada. Ligue-a para visualizar os K-profiles.', + noMatchingProfiles: 'Nenhum Perfil Correspondente', + noMatchingProfilesDesc: 'Nenhum perfil corresponde aos seus critérios de pesquisa', + noKProfiles: 'Nenhum K-Profile', + noKProfilesDesc: 'Nenhum perfil de avanço de pressão encontrado para bico de {{diameter}}mm', + createFirstProfile: 'Criar Primeiro Perfil', + // Controls + printer: 'Impressora', + nozzle: 'Bico', + refresh: 'Atualizar', + addProfile: 'Adicionar Perfil', + export: 'Exportar', + import: 'Importar', + select: 'Selecionar', + selectAll: 'Selecionar Todos', + delete: 'Excluir', + // Filters + searchPlaceholder: 'Pesquisar por nome ou filamento...', + allExtruders: 'Todos os Extrusores', + leftOnly: 'Apenas Esquerdo', + rightOnly: 'Apenas Direito', + allFlow: 'Todo Fluxo', + hfOnly: 'Apenas HF', + sOnly: 'Apenas S', + sortName: 'Ordenar: Nome', + sortKValue: 'Ordenar: Valor K', + sortFilament: 'Ordenar: Filamento', + // Dual extruder labels + leftExtruder: 'Extrusor Esquerdo', + rightExtruder: 'Extrusor Direito', + // Modal + modal: { + addTitle: 'Adicionar K-Profile', + editTitle: 'Editar K-Profile', + profileName: 'Nome do Perfil', + profileNamePlaceholder: 'Meu Perfil PLA', + kValue: 'Valor K', + kValuePlaceholder: '0.020', + kValueHelp: 'Faixa típica: 0.01 - 0.06 para PLA, 0.02 - 0.10 para PETG', + filament: 'Filamento', + selectFilament: 'Selecionar filamento...', + noFilamentsHelp: 'Nenhum filamento encontrado. Crie um K-profile no Bambu Studio primeiro.', + flowType: 'Tipo de Fluxo', + highFlow: 'Alto Fluxo', + standard: 'Padrão', + nozzleSize: 'Tamanho do Bico', + extruder: 'Extrusor', + extruders: 'Extrusores', + left: 'Esquerdo', + right: 'Direito', + notes: 'Notas (armazenadas localmente)', + notesPlaceholder: 'Adicione notas sobre este perfil...', + notesHelp: 'As notas são salvas no Bambuddy, não na impressora', + syncing: 'Sincronizando com a impressora...', + savingExtruder: 'Salvando no extrusor {{current}}/{{total}}...', + pleaseWait: 'Por favor, aguarde', + }, + // Delete confirmation + deleteConfirm: { + title: 'Excluir Perfil', + cannotUndo: 'Isso não pode ser desfeito', + message: 'Tem certeza de que deseja excluir "{{name}}" da impressora?', + }, + // Bulk delete + bulkDelete: { + title: 'Excluir Perfis', + cannotUndo: 'Isso não pode ser desfeito', + message: 'Tem certeza de que deseja excluir {{count}} perfis selecionados da impressora?', + }, + // Toast + toast: { + profileSaved: 'K-profile salvo', + profilesSaved: 'K-profile salvo em {{count}} extrusores', + selectAtLeastOneExtruder: 'Por favor, selecione pelo menos um extrusor', + profileDeleted: 'K-profile excluído', + profilesDeleted: '{{count}} perfis excluídos', + exportedProfiles: '{{count}} perfis exportados', + importedProfiles: '{{count}} de {{total}} perfis importados', + noProfilesToExport: 'Nenhum perfil para exportar', + invalidFileFormat: 'Formato de arquivo inválido', + failedToParseImport: 'Falha ao analisar o arquivo de importação', + failedToSaveBatch: 'Falha ao salvar K-profiles', + noteSaved: 'Nota salva', + failedToSaveNote: 'Falha ao salvar nota', + }, + // Permissions + permission: { + noRead: 'Você não tem permissão para atualizar perfis', + noCreate: 'Você não tem permissão para adicionar perfis', + noUpdate: 'Você não tem permissão para atualizar K-profiles', + noDelete: 'Você não tem permissão para excluir K-profiles', + noExport: 'Você não tem permissão para exportar perfis', + noImport: 'Você não tem permissão para importar perfis', + }, + }, + + // Virtual Printer + virtualPrinter: { + title: 'Impressora Virtual', + running: 'Em execução', + stopped: 'Parada', + description: { + default: 'Ative uma impressora virtual que aparece no Bambu Studio e no OrcaSlicer. Os arquivos enviados para esta impressora serão arquivados diretamente sem impressão.', + proxy: 'Ative um proxy que retransmite o tráfego do slicer para uma impressora real, permitindo impressão remota em qualquer rede.', + }, + enable: { + title: 'Ativar Impressora Virtual', + visibleInSlicer: 'Visível como "Bambuddy" na descoberta do slicer', + proxyingTo: 'Proxy para {{name}}', + notActive: 'Não ativo', + }, + model: { + title: 'Modelo da Impressora', + description: 'Selecione qual modelo de impressora emular.', + restartWarning: 'Alterar o modelo reiniciará a impressora virtual', + }, + accessCode: { + title: 'Código de acesso', + isSet: 'O código de acesso está definido', + notSet: 'Nenhum código de acesso definido — necessário para ativar.', + placeholder: 'Digite um código de 8 caracteres', + placeholderChange: 'Digite um novo código para alterar', + hint: 'Deve ter exatamente 8 caracteres. Usado pelos slicers para autenticação.', + charCount: '({{count}}/8)', + }, + targetPrinter: { + title: 'Impressora Alvo', + configured: 'Proxy alvo configurado', + notConfigured: 'Nenhuma impressora alvo selecionada - necessário para o modo proxy', + placeholder: 'Selecione uma impressora...', + hint: 'Selecione a impressora para a qual o tráfego do slicer será enviado. A impressora deve estar no modo LAN.', + noPrinters: 'Nenhuma impressora configurada. Adicione uma impressora primeiro para usar o modo proxy.', + }, + remoteInterface: { + title: 'Substituição da Interface de Rede', + configured: 'Substituição da interface ativa', + optional: 'Opcional - use se o IP detectado automaticamente estiver errado (por exemplo, várias NICs, Docker, VPN)', + placeholder: 'Detecção automática (padrão)...', + hint: 'Substitua o endereço IP anunciado via SSDP e usado no certificado TLS. Útil quando o Bambuddy possui várias interfaces de rede.', + }, + mode: { + title: 'Modo', + archive: 'Arquivar', + archiveDesc: 'Arquivar arquivos imediatamente', + review: 'Revisar', + reviewDesc: 'Revisar antes de arquivar', + queue: 'Fila', + queueDesc: 'Arquivar e adicionar à fila', + proxy: 'Proxy', + proxyDesc: 'Retransmitir para impressora real', + }, + setupRequired: { + title: 'Configuração Necessária', + description: 'O recurso de impressora virtual requer configuração adicional do sistema antes de funcionar. Isso inclui encaminhamento de portas, regras de firewall e configurações específicas da plataforma.', + readGuide: 'Leia o guia de configuração antes de ativar', + }, + howItWorks: { + title: 'Como funciona', + titleProxy: 'Como funciona (Modo Proxy)', + step1: 'Complete o guia de configuração para sua plataforma', + step2: 'Ative a impressora virtual e defina um código de acesso', + 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: { + title: 'Detalhes do Status', + printerName: 'Nome da Impressora', + model: 'Modelo', + serialNumber: 'Número de Série', + mode: 'Modo', + pendingFiles: 'Arquivos Pendentes', + targetPrinter: 'Impressora Alvo', + ftpPort: 'Porta FTP', + mqttPort: 'Porta MQTT', + ftpConnections: 'Conexões FTP', + mqttConnections: 'Conexões MQTT', + }, + toast: { + updated: 'Configurações da impressora virtual atualizadas', + failedToUpdate: 'Falha ao atualizar as configurações', + accessCodeRequired: 'Defina um código de acesso primeiro', + targetPrinterRequired: 'Selecione uma impressora alvo primeiro', + accessCodeEmpty: 'O código de acesso não pode estar vazio', + accessCodeLength: 'O código de acesso deve ter exatamente 8 caracteres', + }, + }, + + // Model Viewer + modelViewer: { + openInSlicer: 'Abrir no Slicer', + tabs: { + model: 'Modelo 3D', + gcode: 'Pré-visualização G-code', + }, + notAvailable: 'Não disponível', + notSliced: 'Não fatiado', + plates: 'Placas', + allPlates: 'Todas as Placas', + plateNumber: 'Placa {{number}}', + plateCount: '{{count}} placa', + plateCount_other: '{{count}} placas', + objectCount: '{{count}} objeto', + objectCount_other: '{{count}} objetos', + filamentCount: '{{count}} filamento', + filamentCount_other: '{{count}} filamentos', + eta: 'ETA {{minutes}} min', + noPreview: 'Pré-visualização não disponível para este arquivo', + pagination: { + pageOf: 'Página {{current}} de {{total}}', + prev: 'Anterior', + next: 'Próximo', + }, + errors: { + failedToLoad: 'Falha ao carregar o arquivo', + noMeshes: 'Nenhuma malha encontrada no arquivo 3MF', + unsupportedFormat: 'Formato de arquivo não suportado', + }, + }, + + // Maintenance type descriptions (built-in) + maintenanceDescriptions: { + lubricateCarbonRods: 'Aplique lubrificante nos eixos de carbono para um movimento suave', + lubricateRails: 'Aplique lubrificante nos trilhos lineares para um movimento suave', + cleanNozzle: 'Limpe o hotend e o bico para evitar entupimentos', + checkBelts: 'Verifique a tensão das correias para impressões precisas', + cleanBuildPlate: 'Limpe a placa de construção para melhor adesão', + checkExtruder: 'Verifique as engrenagens do extrusor quanto ao desgaste', + checkCooling: 'Verifique se os ventiladores de resfriamento estão funcionando corretamente', + generalInspection: 'Inspeção geral da impressora', + cleanCarbonRods: 'Limpe os eixos de carbono para reduzir o atrito', + cleanLinearRails: 'Limpe os trilhos lineares para remover poeira e detritos', + checkPtfeTube: 'Verifique o tubo PTFE quanto ao desgaste ou danos', + replaceHepaFilter: 'Substitua o filtro HEPA para qualidade do ar', + replaceCarbonFilter: 'Substitua o filtro de carbono ativado', + lubricateLeftNozzleRail: 'Lubrifique o trilho do bico esquerdo (série H2)', + }, + + // Smart Plugs + smartPlugs: { + offline: 'Offline', + admin: 'Admin', + openPlugAdminPage: 'Abrir o painel de administração da tomada inteligente', + deleteSmartPlug: 'Excluir Tomada Inteligente', + turnOnSmartPlug: 'Ligar Tomada Inteligente', + turnOffSmartPlug: 'Desligar Tomada Inteligente', + turnOn: 'Ligar', + turnOff: 'Desligar', + addSmartPlug: { + scanningNetwork: 'Procurando na rede...', + chooseEntity: 'Escolha uma entidade...', + connectionFailed: 'Falha na conexão', + searchEntities: 'Pesquisar entidades...', + searchPowerSensors: 'Pesquisar sensores de energia...', + searchEnergySensors: 'Pesquisar sensores de energia...', + placeholders: { + plugName: 'Tomada da Sala', + mqttStateOnValue: 'ON, true, 1', + mqttSameAsPower: 'Mesmo que o tópico de energia, ou diferente', + }, + }, + }, + + // Rich Text Editor + richTextEditor: { + bold: 'Negrito', + italic: 'Itálico', + underline: 'Sublinhado', + bulletList: 'Lista com marcadores', + numberedList: 'Lista numerada', + alignLeft: 'Alinhar à esquerda', + alignCenter: 'Centralizar', + alignRight: 'Alinhar à direita', + addLink: 'Adicionar link', + removeLink: 'Remover link', + }, + + // External Links + externalLinks: { + noLinksConfigured: 'Nenhum link externo configurado', + deleteLink: 'Excluir link', + removeCustomIcon: 'Remover ícone personalizado', + openInNewTab: 'Abrir em nova aba', + placeholders: { + linkName: 'Meu Link', + }, + }, + + // Keyboard Shortcuts Modal + keyboardShortcuts: { + title: 'Atalhos de Teclado', + navigation: 'Navegação', + archivesSection: 'Arquivos', + kProfilesSection: 'K-Profiles', + generalSection: 'Geral', + shortcuts: { + goToPrinters: 'Ir para Impressoras', + goToArchives: 'Ir para Arquivos', + goToQueue: 'Ir para Fila', + goToStats: 'Ir para Estatísticas', + goToProfiles: 'Ir para Perfis na Nuvem', + goToSettings: 'Ir para Configurações', + focusSearch: 'Focar na pesquisa', + openUploadModal: 'Abrir modal de upload', + clearSelection: 'Limpar seleção / desfocar input', + contextMenu: 'Menu de contexto nos cartões', + refreshProfiles: 'Atualizar perfis', + newProfile: 'Novo perfil', + exitSelectionMode: 'Sair do modo de seleção', + showHelp: 'Mostrar esta ajuda', + }, + footer: 'Pressione Esc ou clique fora para fechar', + }, + + // Notification Log + notificationLog: { + title: 'Registro de Notificações', + events: { + printStarted: 'Impressão Iniciada', + printComplete: 'Impressão Concluída', + printFailed: 'Impressão Falhou', + printStopped: 'Impressão Interrompida', + progress: 'Progresso', + printerOffline: 'Impressora Offline', + printerError: 'Erro na Impressora', + lowFilament: 'Filamento Baixo', + maintenanceDue: 'Manutenção Pendente', + test: 'Teste', + }, + timeAgo: { + justNow: 'Agora mesmo', + minutesAgo: 'há {{minutes}} minutos', + hoursAgo: 'há {{hours}} horas', + }, + }, + + // Restore/Backup Modal + restoreBackup: { + title: 'Restaurar Backup', + restoring: 'Restaurando...', + restoreComplete: 'Restauração Concluída', + restoreFailed: 'Falha na Restauração', + importSettings: 'Importar configurações de um arquivo de backup', + pleaseWait: 'Aguarde enquanto seus dados estão sendo restaurados', + clickToSelect: 'Clique para selecionar o arquivo de backup (.json ou .zip)', + howDuplicateHandling: 'Como funciona o tratamento de duplicatas:', + categories: { + printers: 'Impressoras', + smartPlugs: 'Tomadas Inteligentes', + notificationProviders: 'Provedores de Notificação', + filaments: 'Filamentos', + archives: 'Arquivos', + pendingUploads: 'Uploads Pendentes', + settingsTemplates: 'Configurações e Modelos', + }, + matchingInfo: { + printers: 'correspondem pelo número de série', + smartPlugs: 'correspondem pelo endereço IP', + notificationProviders: 'correspondem pelo nome', + filaments: 'correspondem pelo nome + tipo + marca', + archives: 'correspondem pelo hash do conteúdo', + pendingUploads: 'correspondem pelo nome do arquivo', + settingsTemplates: 'sempre sobrescrito', + }, + replaceExisting: 'Substituir dados existentes', + keepExisting: 'Manter dados existentes', + replaceDescription: 'Substituir itens que já existem com os dados do backup', + keepDescription: 'Restaurar apenas itens que não existem', + caution: 'Atenção:', + cautionText: 'Sobrescrever substituirá suas configurações atuais pelos dados do backup. Os códigos de acesso da impressora nunca são sobrescritos por segurança.', + itemsRestored: 'Itens Restaurados', + itemsSkipped: 'Itens Ignorados', + restored: 'Restaurado', + skipped: 'Ignorado (já existe)', + filesLabel: 'Arquivos (3MF, miniaturas, etc.)', + newApiKeysGenerated: 'Novas Chaves API Geradas', + newApiKeysWarning: 'Essas chaves são exibidas apenas uma vez. Copie-as agora!', + processingBackup: 'Processando arquivo de backup...', + noDataFound: 'Nenhum dado foi encontrado para restaurar no arquivo de backup.', + failedToRestore: 'Falha ao restaurar o backup. Verifique o formato do arquivo.', + }, + + // Backup Export Modal + backupExport: { + title: 'Exportar Backup', + selectData: 'Selecione os dados a incluir', + selectAll: 'Selecionar Todos', + selectNone: 'Selecionar Nenhum', + categoryDescriptions: { + settings: 'Idioma, tema, preferências de atualização', + notifications: 'ntfy, Pushover, Discord, etc.', + templates: 'Modelos de mensagens personalizadas', + smartPlugs: 'Configurações de tomadas Tasmota', + externalLinks: 'Links da barra lateral para serviços externos', + printers: 'Informações da impressora (códigos de acesso excluídos)', + plateDetection: 'Imagens de referência de placa vazia', + filaments: 'Tipos e custos de filamento', + maintenance: 'Cronogramas de manutenção personalizados', + archives: 'Todos os dados de impressão + arquivos (3MF, miniaturas, fotos)', + projects: 'Projetos, itens de BOM e anexos', + pendingUploads: 'Uploads de impressora virtual aguardando revisão', + apiKeys: 'Chaves API de webhook (novas chaves geradas na importação)', + }, + requiresPrinters: 'Requer que as impressoras sejam selecionadas', + zipFileWarning: 'Um arquivo ZIP será criado.', + zipFileDescription: 'Inclui todos os arquivos 3MF, miniaturas, timelapses e fotos. Isso pode levar algum tempo e resultar em um arquivo grande.', + includeAccessCodes: 'Incluir Códigos de Acesso', + includeAccessCodesDescription: 'Para transferir para outra máquina', + includeAccessCodesWarning: 'Os códigos de acesso serão incluídos em texto simples. Mantenha este arquivo de backup seguro!', + categoriesSelected: '{{selectedCount}} categorias selecionadas', + }, + + // Pending Uploads Panel + pendingUploads: { + placeholders: { + notes: 'Adicione notas sobre esta impressão...', + }, + discardUpload: 'Descartar Upload', + archiveAllUploads: 'Arquivar Todos os Uploads', + discardAllUploads: 'Descartar Todos os Uploads', + archive: 'Arquivar', + timeAgo: { + justNow: 'Agora mesmo', + minutesAgo: 'há {{minutes}} minutos', + hoursAgo: 'há {{hours}} horas', + daysAgo: 'há {{days}} dias', + }, + }, + + // API Browser + apiBrowser: { + placeholders: { + requestBody: 'Corpo da requisição JSON...', + searchEndpoints: 'Pesquisar endpoints...', + }, + }, + + // Configure AMS Slot Modal + configureAmsSlot: { + title: 'Configurar Slot AMS', + slotConfigured: 'Slot Configurado!', + configuringSlot: 'Configurando slot:', + slotLabel: '{{ams}} Slot {{slot}}', + searchPresets: 'Pesquisar predefinições...', + colorPlaceholder: 'Nome da cor ou hex (ex.: marrom, FF8800)', + clearCustomColor: 'Limpar cor personalizada', + noCloudPresets: 'Nenhuma predefinição na nuvem. Faça login no Bambu Cloud para sincronizar.', + noPresetsAvailable: 'Nenhuma predefinição disponível. Faça login no Bambu Cloud ou importe perfis locais.', + noMatchingPresets: 'Nenhuma predefinição correspondente encontrada.', + custom: 'Personalizado', + builtin: 'Integrado', + settingsSentToPrinter: 'Configurações enviadas para a impressora', + filamentProfile: 'Perfil de Filamento', + kProfileLabel: 'Perfil K (Avanço de Pressão)', + filteringFor: 'Filtrando por: {{material}}', + noKProfile: 'Nenhum perfil K (usar padrão 0.020)', + noMatchingKProfiles: 'Nenhum perfil K correspondente encontrado. O K padrão=0.020 será usado.', + selectFilamentFirst: 'Selecione um perfil de filamento primeiro', + kFromCalibration: 'K={{value}} da calibração da impressora', + customColorLabel: 'Cor Personalizada (opcional)', + presetColors: 'Cores de {{name}}:', + showLessColors: 'Mostrar menos cores', + showMoreColors: 'Mostrar mais cores', + clear: 'Limpar', + hexLabel: 'Hex: #{{hex}}', + resetting: 'Redefinindo...', + resetSlot: 'Redefinir Slot', + cancel: 'Cancelar', + configuring: 'Configurando...', + configureSlot: 'Configurar Slot', + }, + + // GitHub Backup Settings + githubBackup: { + title: 'Backup do GitHub', + history: 'Histórico', + downloadBackup: 'Baixar Backup', + restoreBackup: 'Restaurar Backup', + noBackupsYet: 'Nenhum backup ainda', + }, + + // Email Settings + emailSettings: { + placeholders: { + fromName: 'BamBuddy', + }, + }, + + // Tag Management Modal + tagManagement: { + searchTags: 'Pesquisar tags...', + renameTag: 'Renomear tag', + deleteTag: 'Excluir tag', + }, + + // Notification Template Editor + notificationTemplates: { + placeholders: { + title: 'Título da notificação...', + body: 'Corpo da notificação...', + }, + }, + + // Batch Tag Modal + batchTag: { + placeholders: { + newTag: 'Digite uma nova tag...', + }, + }, + + // Photo Gallery Modal + photoGallery: { + deletePhoto: 'Excluir foto', + }, + + // Filament Hover Card + filamentHoverCard: { + copySpoolUuid: 'Copiar UUID do carretel', + }, + + // K Profiles View + kProfilesView: { + hasNote: 'Possui nota', + copyProfile: 'Copiar perfil', + }, + + // Layout/Navigation + layout: { + openMenu: 'Abrir menu', + noPermissionSystemInfo: 'Você não tem permissão para visualizar informações do sistema', + }, + + // Dashboard + dashboard: { + dragToReorder: 'Arrastar para reordenar', + hideWidget: 'Ocultar widget', + }, + + // Notification Provider Card + notificationProviderCard: { + deleteNotificationProvider: 'Excluir provedor de notificação', + }, + + // File Manager Modal + fileManagerModal: { + closeFileManager: 'Fechar gerenciador de arquivos', + sortFiles: 'Ordenar arquivos', + goToParentFolder: 'Ir para a pasta pai', + threeView: 'Visualização 3D', + }, + + // Embedded Camera Viewer + embeddedCameraViewer: { + refreshStream: 'Atualizar stream', + close: 'Fechar', + zoomOut: 'Reduzir zoom', + resetZoom: 'Redefinir zoom', + zoomIn: 'Aumentar zoom', + dragToResize: 'Arrastar para redimensionar', + }, + + // Timelapse Viewer + timelapseViewer: { + skipBack5s: 'Voltar 5s', + skipForward5s: 'Avançar 5s', + }, + + // Notification Providers + notificationProviders: { + descriptions: { + email: 'Notificações por email SMTP', + telegram: 'Notificações via bot do Telegram', + discord: 'Enviar para canal do Discord via webhook', + ntfy: 'Notificações push gratuitas e auto-hospedáveis', + pushover: 'Notificações push simples e confiáveis', + callmebot: 'Notificações gratuitas via WhatsApp pelo CallMeBot', + webhook: 'POST HTTP genérico para qualquer URL', + }, + }, + + // Log Viewer + logViewer: { + searchPlaceholder: 'Pesquisar mensagem ou nome do logger...', + noLogEntries: 'Nenhuma entrada de log encontrada', + }, + + // Switchbar Popover + switchbarPopover: { + noSwitchesInSwitchbar: 'Nenhum switch na barra de switches', + }, + + // Project Page Modal + projectPageModal: { + placeholders: { + title: 'Título', + designer: 'Designer', + license: 'Licença', + description: 'Digite a descrição...', + profileTitle: 'Título do perfil', + profileDescription: 'Descrição do perfil...', + }, + }, + + // Spoolman Settings + spoolmanSettings: {}, +};