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: {},
+};