From 75e10efcbda1f794cd461a4bf7412e5d60d35649 Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com.> Date: Sun, 7 Jul 2024 22:49:21 +0100 Subject: [PATCH 01/27] auto decrypt, update discord, fix multi file support for some inputs --- .github/ISSUE_TEMPLATE/config.yml | 2 +- README.md | 2 +- .../api/security/PasswordController.java | 2 +- src/main/resources/static/js/downloader.js | 116 ++++++++++++++++-- .../convert/pdf-to-presentation.html | 2 +- .../templates/convert/pdf-to-word.html | 2 +- src/main/resources/templates/error.html | 2 +- .../templates/fragments/errorBanner.html | 2 +- .../fragments/errorBannerPerPage.html | 2 +- .../resources/templates/fragments/navbar.html | 2 +- src/main/resources/templates/home.html | 4 +- src/main/resources/templates/pipeline.html | 2 +- .../resources/templates/remove-pages.html | 2 +- .../templates/security/add-watermark.html | 4 +- .../templates/security/auto-redact.html | 6 +- 15 files changed, 125 insertions(+), 27 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 0f3580d5a84..2725e5f5a9e 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: true contact_links: - name: 💬 Discord Server - url: https://discord.gg/Cn8pWhQRxZ + url: https://discord.gg/HYmhKj45pU about: You can join our Discord server for real time discussion and support diff --git a/README.md b/README.md index 4d5eae28b4b..dbaab982245 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

Stirling-PDF

[![Docker Pulls](https://img.shields.io/docker/pulls/frooodle/s-pdf)](https://hub.docker.com/r/frooodle/s-pdf) -[![Discord](https://img.shields.io/discord/1068636748814483718?label=Discord)](https://discord.gg/Cn8pWhQRxZ) +[![Discord](https://img.shields.io/discord/1068636748814483718?label=Discord)](https://discord.gg/HYmhKj45pU) [![Docker Image Version (tag latest semver)](https://img.shields.io/docker/v/frooodle/s-pdf/latest)](https://github.com/Stirling-Tools/Stirling-PDF/) [![GitHub Repo stars](https://img.shields.io/github/stars/stirling-tools/stirling-pdf?style=social)](https://github.com/Stirling-Tools/stirling-pdf) [![Paypal Donate](https://img.shields.io/badge/Paypal%20Donate-yellow?style=flat&logo=paypal)](https://www.paypal.com/donate/?hosted_button_id=MN7JPG5G6G3JL) diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java index 84c4493314c..b8e36e0e106 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java @@ -68,7 +68,7 @@ public ResponseEntity addPassword(@ModelAttribute AddPasswordRequest req boolean canModifyAnnotations = request.isCanModifyAnnotations(); boolean canPrint = request.isCanPrint(); boolean canPrintFaithful = request.isCanPrintFaithful(); - + System.out.println(fileInput.getOriginalFilename()); PDDocument document = Loader.loadPDF(fileInput.getBytes()); AccessPermission ap = new AccessPermission(); ap.setCanAssembleDocument(!canAssembleDocument); diff --git a/src/main/resources/static/js/downloader.js b/src/main/resources/static/js/downloader.js index c955bb1bbce..07f7c5b68cc 100644 --- a/src/main/resources/static/js/downloader.js +++ b/src/main/resources/static/js/downloader.js @@ -12,7 +12,7 @@ $(document).ready(function () { event.preventDefault(); firstErrorOccurred = false; const url = this.action; - const files = $("#fileInput-input")[0].files; + var files = $("#fileInput-input")[0].files; const formData = new FormData(this); // Remove empty file entries @@ -36,6 +36,17 @@ $(document).ready(function () { }, 5000); try { + + if (!url.includes("remove-password")) { + // Check if any PDF files are encrypted and handle decryption if necessary + const decryptedFiles = await checkAndDecryptFiles(url ,files); + files = decryptedFiles + // Append decrypted files to formData + decryptedFiles.forEach((file, index) => { + formData.set(`fileInput`, file); + }); + } + if (remoteCall === true) { if (override === "multi" || (!multiple && files.length > 1 && override !== "single")) { await submitMultiPdfForm(url, files); @@ -45,24 +56,24 @@ $(document).ready(function () { } clearTimeout(timeoutId); $("#submitBtn").text(originalButtonText); - + // After process finishes, check for boredWaiting and gameDialog open status const boredWaiting = localStorage.getItem("boredWaiting") || "disabled"; const gameDialog = document.getElementById('game-container-wrapper'); if (boredWaiting === "enabled" && gameDialog && gameDialog.open) { // Display a green banner at the bottom of the screen saying "Download complete" let downloadCompleteText = "Download Complete"; - if(window.downloadCompleteText){ + if (window.downloadCompleteText) { downloadCompleteText = window.downloadCompleteText; } - $("body").append('
'+ downloadCompleteText + '
'); - setTimeout(function() { - $("#download-complete-banner").fadeOut("slow", function() { + $("body").append('
' + downloadCompleteText + '
'); + setTimeout(function () { + $("#download-complete-banner").fadeOut("slow", function () { $(this).remove(); // Remove the banner after fading out }); }, 5000); // Banner will fade out after 5 seconds } - + } catch (error) { clearTimeout(timeoutId); handleDownloadError(error); @@ -72,6 +83,97 @@ $(document).ready(function () { }); }); +async function checkAndDecryptFiles(url, files) { + const decryptedFiles = []; + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + +// Extract the base URL + const baseUrl = new URL(url); + let removePasswordUrl = `${baseUrl.origin}`; + + // Check if there's a path before /api/ + const apiIndex = baseUrl.pathname.indexOf('/api/'); + if (apiIndex > 0) { + removePasswordUrl += baseUrl.pathname.substring(0, apiIndex); + } + + // Append the new endpoint + removePasswordUrl += '/api/v1/security/remove-password'; + + console.log(`Remove password URL: ${removePasswordUrl}`); + + + for (const file of files) { + console.log(`Processing file: ${file.name}`); + if (file.type !== 'application/pdf') { + console.log(`Skipping non-PDF file: ${file.name}`); + decryptedFiles.push(file); + continue; + } + try { + const arrayBuffer = await file.arrayBuffer(); + const loadingTask = pdfjsLib.getDocument({ data: arrayBuffer }); + + console.log(`Attempting to load PDF: ${file.name}`); + const pdf = await loadingTask.promise; + console.log(`File is not encrypted: ${file.name}`); + decryptedFiles.push(file); // If no error, file is not encrypted + } catch (error) { + if (error.name === 'PasswordException' && error.code === 1) { + console.log(`PDF requires password: ${file.name}`, error); + console.log(`Attempting to remove password from PDF: ${file.name} with password.`); + const password = prompt(`This PDF (${file.name}) is encrypted. Please enter the password:`); + + if (!password) { + console.error(`No password provided for encrypted PDF: ${file.name}`); + showErrorBanner(`No password provided for encrypted PDF: ${file.name}`, 'Please enter a valid password.'); + throw error; + } + + try { + // Prepare FormData for the decryption request + const formData = new FormData(); + formData.append('fileInput', file); + formData.append('password', password); + + // Use handleSingleDownload to send the request + const decryptionResult = await fetch(removePasswordUrl, { method: "POST", body: formData }); + + if (decryptionResult && decryptionResult.blob) { + const decryptedBlob = await decryptionResult.blob(); + const decryptedFile = new File([decryptedBlob], file.name, { type: 'application/pdf' }); + + /* // Create a link element to download the file + const link = document.createElement('a'); + link.href = URL.createObjectURL(decryptedBlob); + link.download = 'test.pdf'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); +*/ + decryptedFiles.push(decryptedFile); + console.log(`Successfully decrypted PDF: ${file.name}`); + } else { + throw new Error('Decryption failed: No valid response from server'); + } + } catch (decryptError) { + console.error(`Failed to decrypt PDF: ${file.name}`, decryptError); + showErrorBanner(`Failed to decrypt PDF: ${file.name}`, 'Incorrect password or unsupported encryption.'); + throw decryptError; + } + } else { + console.log(`Error loading PDF: ${file.name}`, error); + throw error; + } + } + } + return decryptedFiles; +} + + + + + async function handleSingleDownload(url, formData, isMulti = false, isZip = false) { try { const response = await fetch(url, { method: "POST", body: formData }); diff --git a/src/main/resources/templates/convert/pdf-to-presentation.html b/src/main/resources/templates/convert/pdf-to-presentation.html index 794317609c2..ce1f455dd5d 100644 --- a/src/main/resources/templates/convert/pdf-to-presentation.html +++ b/src/main/resources/templates/convert/pdf-to-presentation.html @@ -22,8 +22,8 @@
diff --git a/src/main/resources/templates/convert/pdf-to-word.html b/src/main/resources/templates/convert/pdf-to-word.html index 7e5f96c03a9..f91b6a60e49 100644 --- a/src/main/resources/templates/convert/pdf-to-word.html +++ b/src/main/resources/templates/convert/pdf-to-word.html @@ -22,8 +22,8 @@
diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html index 314d28b3997..00f22c27b03 100644 --- a/src/main/resources/templates/error.html +++ b/src/main/resources/templates/error.html @@ -19,7 +19,7 @@

- +
diff --git a/src/main/resources/templates/fragments/errorBanner.html b/src/main/resources/templates/fragments/errorBanner.html index 32fb9019c53..d682dcb922d 100644 --- a/src/main/resources/templates/fragments/errorBanner.html +++ b/src/main/resources/templates/fragments/errorBanner.html @@ -20,7 +20,7 @@ - + diff --git a/src/main/resources/templates/pipeline.html b/src/main/resources/templates/pipeline.html index 0a1d879f2a2..1f5f1c7cb16 100644 --- a/src/main/resources/templates/pipeline.html +++ b/src/main/resources/templates/pipeline.html @@ -16,7 +16,7 @@ /> diff --git a/src/main/resources/templates/remove-pages.html b/src/main/resources/templates/remove-pages.html index 58dc18c7885..84471ef295c 100644 --- a/src/main/resources/templates/remove-pages.html +++ b/src/main/resources/templates/remove-pages.html @@ -21,7 +21,7 @@
- +
diff --git a/src/main/resources/templates/security/add-watermark.html b/src/main/resources/templates/security/add-watermark.html index 12e706e411e..71c323746d7 100644 --- a/src/main/resources/templates/security/add-watermark.html +++ b/src/main/resources/templates/security/add-watermark.html @@ -20,9 +20,7 @@
-
- -
+
diff --git a/src/main/resources/templates/security/auto-redact.html b/src/main/resources/templates/security/auto-redact.html index 7709af87ab8..5be0f0dd6d2 100644 --- a/src/main/resources/templates/security/auto-redact.html +++ b/src/main/resources/templates/security/auto-redact.html @@ -17,10 +17,8 @@
-
- -
- +
+
From f4082e3f965d037bb85f99f2508f08180cbb251b Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Sun, 7 Jul 2024 22:51:59 +0100 Subject: [PATCH 02/27] Update PasswordController.java --- .../SPDF/controller/api/security/PasswordController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java index b8e36e0e106..8a947c8e0b5 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java @@ -68,7 +68,6 @@ public ResponseEntity addPassword(@ModelAttribute AddPasswordRequest req boolean canModifyAnnotations = request.isCanModifyAnnotations(); boolean canPrint = request.isCanPrint(); boolean canPrintFaithful = request.isCanPrintFaithful(); - System.out.println(fileInput.getOriginalFilename()); PDDocument document = Loader.loadPDF(fileInput.getBytes()); AccessPermission ap = new AccessPermission(); ap.setCanAssembleDocument(!canAssembleDocument); From 4d017610b80a5c5ff763a97dbd9e5d7472b8bc37 Mon Sep 17 00:00:00 2001 From: Reece Browne Date: Fri, 6 Dec 2024 19:08:18 +0000 Subject: [PATCH 03/27] PDF decryption --- .../static/js/multitool/DecryptFiles.js | 90 +++++++++++++++++++ .../static/js/multitool/PdfContainer.js | 27 ++++-- 2 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 src/main/resources/static/js/multitool/DecryptFiles.js diff --git a/src/main/resources/static/js/multitool/DecryptFiles.js b/src/main/resources/static/js/multitool/DecryptFiles.js new file mode 100644 index 00000000000..bd7e0073a5c --- /dev/null +++ b/src/main/resources/static/js/multitool/DecryptFiles.js @@ -0,0 +1,90 @@ +export class DecryptFile { + async decryptFile(file) { + try { + const password = prompt('This file is password-protected. Please enter the password:'); + + if (password === null) { + // User cancelled + console.error(`Password prompt cancelled for PDF: ${file.name}`); + this.showErrorBanner(`Operation cancelled for PDF: ${file.name}`, 'You cancelled the decryption process.'); + return null; // No file to return + } + + if (!password) { + // No password provided + console.error(`No password provided for encrypted PDF: ${file.name}`); + this.showErrorBanner(`No password provided for encrypted PDF: ${file.name}`, 'Please enter a valid password.'); + return null; // No file to return + } + + const formData = new FormData(); + formData.append('fileInput', file); + formData.append('password', password); + + // Send decryption request + const response = await fetch('/api/v1/security/remove-password', { + method: 'POST', + body: formData, + }); + + if (response.ok) { + const decryptedBlob = await response.blob(); + this.removeErrorBanner(); + return new File([decryptedBlob], file.name, {type: 'application/pdf'}); + } else { + const errorText = await response.text(); + console.error(`Server error while decrypting: ${errorText}`); + this.showErrorBanner( + 'Please try again with the correct password.', + errorText, + `Incorrect password for PDF: ${file.name}` + ); + return null; // No file to return + } + } catch (error) { + // Handle network or unexpected errors + console.error(`Failed to decrypt PDF: ${file.name}`, error); + this.showErrorBanner( + `Decryption error for PDF: ${file.name}`, + error.message || 'Unexpected error occurred.', + 'There was an error processing the file. Please try again.' + ); + return null; // No file to return + } + } + + async checkFileEncrypted(file) { + try { + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + const arrayBuffer = await file.arrayBuffer(); // Convert file to ArrayBuffer + await pdfjsLib.getDocument({ + data: arrayBuffer, + password: '', + }).promise; + + return false; // File is not encrypted + } catch (error) { + if (error.name === 'PasswordException') { + return true; // File is encrypted + } + console.error('Error checking encryption:', error); + throw new Error('Failed to determine if the file is encrypted.'); + } + } + + showErrorBanner(message, stackTrace, error) { + const errorContainer = document.getElementById('errorContainer'); + errorContainer.style.display = 'block'; // Display the banner + errorContainer.querySelector('.alert-heading').textContent = error; + errorContainer.querySelector('p').textContent = message; + document.querySelector('#traceContent').textContent = stackTrace; + } + + removeErrorBanner() { + const errorContainer = document.getElementById('errorContainer'); + errorContainer.style.display = 'none'; // Hide the banner + errorContainer.querySelector('.alert-heading').textContent = ''; + errorContainer.querySelector('p').textContent = ''; + document.querySelector('#traceContent').textContent = ''; + } +} diff --git a/src/main/resources/static/js/multitool/PdfContainer.js b/src/main/resources/static/js/multitool/PdfContainer.js index 4eaf43f1420..f7fa2536613 100644 --- a/src/main/resources/static/js/multitool/PdfContainer.js +++ b/src/main/resources/static/js/multitool/PdfContainer.js @@ -5,6 +5,7 @@ import {SplitAllCommand} from './commands/split.js'; import {UndoManager} from './UndoManager.js'; import {PageBreakCommand} from './commands/page-break.js'; import {AddFilesCommand} from './commands/add-page.js'; +import {DecryptFile} from './DecryptFiles.js'; class PdfContainer { fileName; @@ -40,6 +41,8 @@ class PdfContainer { this.removeAllElements = this.removeAllElements.bind(this); this.resetPages = this.resetPages.bind(this); + this.decryptFile = new DecryptFile(); + this.undoManager = undoManager || new UndoManager(); this.pdfAdapters = pdfAdapters; @@ -165,7 +168,6 @@ class PdfContainer { input.click(); }); } - async addFilesFromFiles(files, nextSiblingElement, pages) { this.fileName = files[0].name; for (var i = 0; i < files.length; i++) { @@ -173,17 +175,27 @@ class PdfContainer { let processingTime, errorMessage = null, pageCount = 0; + try { - const file = files[i]; - if (file.type === 'application/pdf') { - const {renderer, pdfDocument} = await this.loadFile(file); + let decryptedFile = files[i]; + + if (decryptedFile.type === 'application/pdf' && (await this.decryptFile.checkFileEncrypted(decryptedFile))) { + decryptedFile = await this.decryptFile.decryptFile(decryptedFile); + if (!decryptedFile) { + throw new Error('File decryption failed.'); + } + } + + if (decryptedFile.type === 'application/pdf') { + const {renderer, pdfDocument} = await this.loadFile(decryptedFile); pageCount = renderer.pageCount || 0; pages = await this.addPdfFile(renderer, pdfDocument, nextSiblingElement, pages); - } else if (file.type.startsWith('image/')) { - pages = await this.addImageFile(file, nextSiblingElement, pages); + } else if (decryptedFile.type.startsWith('image/')) { + pages = await this.addImageFile(decryptedFile, nextSiblingElement, pages); } + processingTime = Date.now() - startTime; - this.captureFileProcessingEvent(true, file, processingTime, null, pageCount); + this.captureFileProcessingEvent(true, decryptedFile, processingTime, null, pageCount); } catch (error) { processingTime = Date.now() - startTime; errorMessage = error.message || 'Unknown error'; @@ -194,6 +206,7 @@ class PdfContainer { document.querySelectorAll('.enable-on-file').forEach((element) => { element.disabled = false; }); + return pages; } From 58278c07ff368fe565a6e301664408015c2827e7 Mon Sep 17 00:00:00 2001 From: Reece Browne Date: Fri, 6 Dec 2024 20:46:04 +0000 Subject: [PATCH 04/27] Translations for errors --- src/main/resources/messages_en_GB.properties | 10 ++++++++ .../static/js/multitool/DecryptFiles.js | 24 ++++++++++++------- src/main/resources/templates/multi-tool.html | 10 +++++++- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties index b8c443216cc..c5e42bff502 100644 --- a/src/main/resources/messages_en_GB.properties +++ b/src/main/resources/messages_en_GB.properties @@ -965,6 +965,16 @@ multiTool.dragDropMessage=Page(s) Selected multiTool.undo=Undo multiTool.redo=Redo +#multiTool-decrypt +multiTool.decrypt.passwordPrompt=This file is password-protected. Please enter the password: +multiTool.decrypt.cancelled=Operation cancelled for PDF: {0} +multiTool.decrypt.noPassword=No password provided for encrypted PDF: {0} +multiTool.decrypt.invalidPassword=Please try again with the correct password. +multiTool.decrypt.invalidPasswordHeader=Incorrect password for PDF: {0} +multiTool.decrypt.unexpectedError=There was an error processing the file. Please try again. +multiTool.decrypt.serverError=Server error while decrypting: {0} +multiTool.decrypt.success=File decrypted successfully. + #multiTool-advert multiTool-advert.message=This feature is also available in our multi-tool page. Check it out for enhanced page-by-page UI and additional features! diff --git a/src/main/resources/static/js/multitool/DecryptFiles.js b/src/main/resources/static/js/multitool/DecryptFiles.js index bd7e0073a5c..a9acbccc6e9 100644 --- a/src/main/resources/static/js/multitool/DecryptFiles.js +++ b/src/main/resources/static/js/multitool/DecryptFiles.js @@ -6,14 +6,22 @@ export class DecryptFile { if (password === null) { // User cancelled console.error(`Password prompt cancelled for PDF: ${file.name}`); - this.showErrorBanner(`Operation cancelled for PDF: ${file.name}`, 'You cancelled the decryption process.'); + this.showErrorBanner( + `${window.translations.cancelled.replace('{0}', file.name)}`, + '', + `${window.translations.unexpectedError}` + ); return null; // No file to return } if (!password) { // No password provided console.error(`No password provided for encrypted PDF: ${file.name}`); - this.showErrorBanner(`No password provided for encrypted PDF: ${file.name}`, 'Please enter a valid password.'); + this.showErrorBanner( + `${window.translations.noPassword.replace('{0}', file.name)}`, + '', + `${window.translations.unexpectedError}` + ); return null; // No file to return } @@ -33,11 +41,11 @@ export class DecryptFile { return new File([decryptedBlob], file.name, {type: 'application/pdf'}); } else { const errorText = await response.text(); - console.error(`Server error while decrypting: ${errorText}`); + console.error(`${window.translations.invalidPassword} ${errorText}`); this.showErrorBanner( - 'Please try again with the correct password.', + `${window.translations.invalidPassword}`, errorText, - `Incorrect password for PDF: ${file.name}` + `${window.translations.invalidPasswordHeader.replace('{0}', file.name)}` ); return null; // No file to return } @@ -45,9 +53,9 @@ export class DecryptFile { // Handle network or unexpected errors console.error(`Failed to decrypt PDF: ${file.name}`, error); this.showErrorBanner( - `Decryption error for PDF: ${file.name}`, - error.message || 'Unexpected error occurred.', - 'There was an error processing the file. Please try again.' + `${window.translations.unexpectedError.replace('{0}', file.name)}`, + `${error.message || window.translations.unexpectedError}`, + error ); return null; // No file to return } diff --git a/src/main/resources/templates/multi-tool.html b/src/main/resources/templates/multi-tool.html index 14e5a85ec03..532ca5f8193 100644 --- a/src/main/resources/templates/multi-tool.html +++ b/src/main/resources/templates/multi-tool.html @@ -162,7 +162,15 @@
multi-tool page. Check it out for enhanced page-by-page UI and additional features! diff --git a/src/main/resources/static/js/downloader.js b/src/main/resources/static/js/downloader.js index c651620e9b5..f89c28ec331 100644 --- a/src/main/resources/static/js/downloader.js +++ b/src/main/resources/static/js/downloader.js @@ -71,9 +71,6 @@ }, 5000); try { - submitButton.textContent = 'Processing...'; - submitButton.disabled = true; - if (!url.includes('remove-password')) { // Check if any PDF files are encrypted and handle decryption if necessary const decryptedFiles = await checkAndDecryptFiles(url, files); @@ -84,6 +81,9 @@ }); } + submitButton.textContent = 'Processing...'; + submitButton.disabled = true; + if (remoteCall === true) { if (override === 'multi' || (!multipleInputsForSingleRequest && files.length > 1 && override !== 'single')) { await submitMultiPdfForm(url, files); @@ -181,11 +181,14 @@ if (error.name === 'PasswordException' && error.code === 1) { console.log(`PDF requires password: ${file.name}`, error); console.log(`Attempting to remove password from PDF: ${file.name} with password.`); - const password = prompt(`This PDF (${file.name}) is encrypted. Please enter the password:`); + const password = prompt(`${window.translations.decrypt.passwordPrompt}`); if (!password) { console.error(`No password provided for encrypted PDF: ${file.name}`); - showErrorBanner(`No password provided for encrypted PDF: ${file.name}`, 'Please enter a valid password.'); + showErrorBanner( + `${window.translations.decrypt.noPassword.replace('{0}', file.name)}`, + `${window.translations.decrypt.unexpectedError}` + ); throw error; } @@ -217,7 +220,10 @@ } } catch (decryptError) { console.error(`Failed to decrypt PDF: ${file.name}`, decryptError); - showErrorBanner(`Failed to decrypt PDF: ${file.name}`, 'Incorrect password or unsupported encryption.'); + showErrorBanner( + `${window.translations.invalidPasswordHeader.replace('{0}', file.name)}`, + `${window.translations.invalidPassword}` + ); throw decryptError; } } else { diff --git a/src/main/resources/templates/fragments/common.html b/src/main/resources/templates/fragments/common.html index f372d1dd517..04a91a8dd24 100644 --- a/src/main/resources/templates/fragments/common.html +++ b/src/main/resources/templates/fragments/common.html @@ -203,7 +203,19 @@ - +
diff --git a/src/main/resources/templates/multi-tool.html b/src/main/resources/templates/multi-tool.html index 260ad74cde1..17eafedf366 100644 --- a/src/main/resources/templates/multi-tool.html +++ b/src/main/resources/templates/multi-tool.html @@ -163,17 +163,18 @@
- + + @@ -42,75 +43,6 @@ th:replace="~{fragments/common :: fileSelector(name='pdf-upload', multipleInputsForSingleRequest=false, disableMultipleFiles=true, accept='application/pdf')}">
-
- - - - -
@@ -410,35 +225,11 @@
-
- - - - @@ -447,6 +238,7 @@
+ \ No newline at end of file From 0f6f3f305a24d1aa68d8634a30a64d038e3684af Mon Sep 17 00:00:00 2001 From: thiagoor-cpu Date: Tue, 10 Dec 2024 17:40:28 -0300 Subject: [PATCH 10/27] Update messages_pt_BR.properties (#2429) Up-to-date translation PT-BR --- src/main/resources/messages_pt_BR.properties | 890 +++++++++---------- 1 file changed, 445 insertions(+), 445 deletions(-) diff --git a/src/main/resources/messages_pt_BR.properties b/src/main/resources/messages_pt_BR.properties index 1c4371f1ebd..5b9515cf434 100644 --- a/src/main/resources/messages_pt_BR.properties +++ b/src/main/resources/messages_pt_BR.properties @@ -5,14 +5,14 @@ language.direction=ltr addPageNumbers.fontSize=Tamanho da Fonte addPageNumbers.fontName=Nome da Fonte -pdfPrompt=Selecione PDF(s) -multiPdfPrompt=Selecione PDFs (2+) -multiPdfDropPrompt=Selecione (ou arraste e solte) todos os PDFs desejados +pdfPrompt=Selecione o(s) PDF(s) +multiPdfPrompt=Selecione os PDFs (2+) +multiPdfDropPrompt=Selecione (ou arraste e solte) todos os PDFs desejados: imgPrompt=Selecione a(s) Imagem(ns) genericSubmit=Enviar -processTimeWarning=Aviso: esse processo pode levar até um minuto, dependendo do tamanho do arquivo -pageOrderPrompt=Ordem de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula ou Funções como 2n+1): -pageSelectionPrompt=Seleção de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula 1,5,6 ou Funções como 2n+1) : +processTimeWarning=Aviso: Este processo pode levar até um minuto, dependendo do tamanho do arquivo +pageOrderPrompt=Ordem de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula ou funções como 2n+1): +pageSelectionPrompt=Seleção de Página Personalizada (Digite uma lista de números de páginas, separadas por vírgula como 1,5,6 ou funções como 2n+1): goToPage=Ir true=Verdadeiro false=Falso @@ -23,7 +23,7 @@ close=Fechar filesSelected=Arquivos Selecionados noFavourites=Nenhum Favorito Adicionado downloadComplete=Download Completo -bored=Entediado Esperando? +bored=Entediado? Clique aqui! alphabet=Alfabeto downloadPdf=Baixar PDF text=Texto @@ -34,7 +34,7 @@ sizes.small=Pequeno sizes.medium=Médio sizes.large=Grande sizes.x-large=Extra grande -error.pdfPassword=O documento PDF está protegido por senha e a senha não foi fornecida ou está incorreta +error.pdfPassword=O PDF está protegido por senha e a senha não foi fornecida ou está incorreta delete=Apagar username=Usuário password=Senha @@ -46,7 +46,7 @@ red=Vermelho green=Verde blue=Azul custom=Personalizado... -WorkInProgess=Trabalho em progresso, Talvez não funcione ou apresente erros, Por favor, reporte qualquer problema! +WorkInProgess=Trabalho em progresso, talvez não funcione ou apresente erros, Por favor, reporte qualquer problema! poweredBy=Distribuído por yes=Sim no=Não @@ -55,11 +55,11 @@ notAuthenticatedMessage=Usuário não autenticado. userNotFoundMessage=Usuário não encontrado. incorrectPasswordMessage=A senha atual está incorreta. usernameExistsMessage=Novo Usuário já existe. -invalidUsernameMessage=Usuário inválido, nome de usuário só pode incluir letras, números e os seguintes caracteres especiais @._+- ou deve ser um e-mail válido. +invalidUsernameMessage=Usuário inválido, nome de usuário só pode conter letras, números e os seguintes caracteres especiais @._+- ou deve ser um e-mail válido. invalidPasswordMessage=A senha não deve estar vazia e não deve conter espaços no início ou no final. confirmPasswordErrorMessage=Nova Senha e Confirmar Nova Senha devem ser iguais. deleteCurrentUserMessage=Não é possível apagar usuário conectado no momento. -deleteUsernameExistsMessage=O usuário não existe e não pode ser apagado. +deleteUsernameExistsMessage=O usuário não existe e desta forma não pode ser apagado. downgradeCurrentUserMessage=Não é possível fazer downgrade da função do usuário conectado no momento. disabledCurrentUserMessage=O usuário atual não pode ser desativado. downgradeCurrentUserLongMessage=Não é possível fazer downgrade da função do usuário atual. Portanto, o usuário atual não será mostrado. @@ -70,8 +70,8 @@ oops=Ops! help=Ajuda goHomepage=Ir para a Página Inicial joinDiscord=Junte-se ao nosso servidor Discord -seeDockerHub=Visite o Docker Hub -visitGithub=Visite o repositório no GitHub +seeDockerHub=Visite nosso Docker Hub +visitGithub=Visite nosso repositório no GitHub donate=Doar color=Cor sponsor=Patrocinador @@ -81,7 +81,7 @@ page=Página pages=Páginas loading=Carregando... addToDoc=Adicionar ao Documento -reset=Reset +reset=Reiniciar legal.privacy=Política de Privacidade legal.terms=Termos e Condições @@ -93,42 +93,42 @@ legal.impressum=Informações legais # Pipeline # ############### pipeline.header=Menu do Pipeline (Beta) -pipeline.uploadButton=Upload Personalizado +pipeline.uploadButton=Upload de Arquivo Personalizado pipeline.configureButton=Configurar -pipeline.defaultOption=Personalizado +pipeline.defaultOption=Arquivo Personalizado pipeline.submitButton=Enviar -pipeline.help=Ajuda do Pipeline -pipeline.scanHelp=Ajuda para scanner de pastas -pipeline.deletePrompt=Tem certeza de que deseja excluir o pipeline +pipeline.help=Ajuda relacionada ao Pipeline +pipeline.scanHelp=Ajuda para leitura e processamento de pastas +pipeline.deletePrompt=Tem certeza de que deseja excluir o pipeline -> ###################### # Pipeline Options # ###################### pipelineOptions.header=Configuração do Pipeline -pipelineOptions.pipelineNameLabel=Nome do Pipeline +pipelineOptions.pipelineNameLabel=Nome do Pipeline: pipelineOptions.saveSettings=Salvar Configurações da Operação -pipelineOptions.pipelineNamePrompt=Insira o nome do pipeline aqui -pipelineOptions.selectOperation=Selecione uma Operação -pipelineOptions.addOperationButton=Adicione uma Operação +pipelineOptions.pipelineNamePrompt=Insira o nome do pipeline neste campo +pipelineOptions.selectOperation=Selecione uma Operação: +pipelineOptions.addOperationButton=Adicione a Operação pipelineOptions.pipelineHeader=Pipeline: -pipelineOptions.saveButton=Baixar +pipelineOptions.saveButton=Baixar (JSON) pipelineOptions.validateButton=Validar ######################## # ENTERPRISE EDITION # ######################## -enterpriseEdition.button=Atualize para versão Pro -enterpriseEdition.warning=Esse recurso só está disponivel para usuários da versão Pro. +enterpriseEdition.button=Atualize para a versão Pro +enterpriseEdition.warning=Este recurso só está disponivel para usuários da versão Pro. enterpriseEdition.yamlAdvert=Stirling PDF Pro suporta arquivos de configuração YAML e outros recursos SSO. -enterpriseEdition.ssoAdvert=Procurando por mais recursos de controle de usuários? Veja Stirling PDF Pro +enterpriseEdition.ssoAdvert=Procurando por mais recursos de controle de usuários? Veja a versão Pro do Stirling PDF ################# # Analytics # ################# -analytics.title=Você quer melhorar Stirling PDF? +analytics.title=Você quer melhorar o Stirling PDF? analytics.paragraph1=Stirling PDF possui coleta de dados opcional para ajudar a melhorar o produto. Nós não rastreamos nenhuma informação pessoal ou conteúdo dos arquivos. -analytics.paragraph2=Por favor considere habilitar coleta de dados para ajudar Stirling-PDF a crescer e nos ajudar a entender nossos usuários melhor. +analytics.paragraph2=Por favor considere habilitar a coleta de dados para ajudar Stirling PDF a crescer e nos ajudar a entender melhor nossos usuários. analytics.enable=Habilitar coleta de dados analytics.disable=Desabilitar coleta de dados analytics.settings=Você pode alterar as configurações de coleta de dados no arquivo config/settings.yml @@ -142,13 +142,13 @@ navbar.language=Idiomas navbar.settings=Configurações navbar.allTools=Ferramentas navbar.multiTool=Multiferramentas -navbar.search=Search +navbar.search=Pesquisar navbar.sections.organize=Organizar navbar.sections.convertTo=Converter para PDF navbar.sections.convertFrom=Converter de PDF navbar.sections.security=Assinatura & Segurança navbar.sections.advance=Avançado -navbar.sections.edit=Visualizar & editar +navbar.sections.edit=Visualizar & Editar navbar.sections.popular=Populares ############# @@ -157,16 +157,16 @@ navbar.sections.popular=Populares settings.title=Configurações settings.update=Atualização disponível settings.updateAvailable={0} é a versão atualmente instalada. Uma nova versão ({1}) está disponível. -settings.appVersion=Versão do aplicativo: -settings.downloadOption.title=Escolha a opção de download (para downloads não compactados de arquivo único): +settings.appVersion=Versão do Aplicativo: +settings.downloadOption.title=Escolha a opção de download (para download de arquivo único, não compactados): settings.downloadOption.1=Abrir na mesma janela settings.downloadOption.2=Abrir em nova janela -settings.downloadOption.3=Baixar arquivo -settings.zipThreshold=Compactar arquivos quando o número de arquivos baixados exceder +settings.downloadOption.3=Baixar o arquivo +settings.zipThreshold=Compactar os arquivos quando o número baixado exceder: settings.signOut=Sair -settings.accountSettings=Configurações de conta +settings.accountSettings=Configurações da Conta settings.bored.help=Habilitar jogos secretos -settings.cacheInputs.name=Salvar entradas do formulário +settings.cacheInputs.name=Salvar entradas do formulário. settings.cacheInputs.help=Habilitar para armazenar entradas usadas anteriormente para execuções futuras changeCreds.title=Alterar Credenciais @@ -180,8 +180,8 @@ changeCreds.submit=Enviar Alterações -account.title=Configurações de Conta -account.accountSettings=Configurações de Conta +account.title=Configurações da Conta +account.accountSettings=Configurações da Conta account.adminSettings=Configurações de Administrador – Visualizar e Adicionar Usuários account.userControlSettings=Configurações de Controle de Usuário account.changeUsername=Alterar Usuário @@ -193,8 +193,8 @@ account.changePassword=Alterar a Senha account.confirmNewPassword=Confirme a Nova Senha account.signOut=Sair account.yourApiKey=Sua chave de API -account.syncTitle=Sincronize as configurações do navegador com a conta -account.settingsCompare=Comparação de Configurações: +account.syncTitle=Sincronize as configurações do navegador com sua conta: +account.settingsCompare=Comparação das Configurações: account.property=Propriedade account.webBrowserSettings=Configuração do navegador Web account.syncToBrowser=Sincronizar Conta -> Navegador @@ -217,7 +217,7 @@ adminUserSettings.apiUser=Usuário de API limitado adminUserSettings.extraApiUser=Usuário de API limitado adicional adminUserSettings.webOnlyUser=Usuário web apenas adminUserSettings.demoUser=Usuário demo (Sem configurações personalizadas) -adminUserSettings.internalApiUser=Usuário interno de API +adminUserSettings.internalApiUser=Usuário de API interno adminUserSettings.forceChange=Forçar usuário a trocar a senha ao iniciar sessão adminUserSettings.submit=Salvar Usuário adminUserSettings.changeUserRole=Alterar Função do Usuário @@ -225,22 +225,22 @@ adminUserSettings.authenticated=Autenticado adminUserSettings.editOwnProfil=Editar próprio perfil adminUserSettings.enabledUser=usuário habilitado adminUserSettings.disabledUser=usuário desabilitado -adminUserSettings.activeUsers=Usuários ativos: -adminUserSettings.disabledUsers=Usuários desabilitados: -adminUserSettings.totalUsers=Total de usuários: +adminUserSettings.activeUsers=Usuários Ativos: +adminUserSettings.disabledUsers=Usuários Desabilitados: +adminUserSettings.totalUsers=Total de Usuários: adminUserSettings.lastRequest=Última solicitação database.title=Importar/Exportar banco de dados database.header=Importar/Exportar banco de dados -database.fileName=Nome do arquivo -database.creationDate=Data de criação -database.fileSize=Tamanho do arquivo +database.fileName=Nome do Arquivo +database.creationDate=Data de Criação +database.fileSize=Tamanho do Arquivo database.deleteBackupFile=Apagar arquivo de backup database.importBackupFile=Importar arquivo de backup database.downloadBackupFile=Baixar arquivo de backup database.info_1=Ao importar dados, é crucial garantir a estrutura correta. Se você não tem certeza do que está fazendo procure auxílio de um profissional. Um erro na estrutura pode ocasionar em mau funcionamento da aplicação, incluindo a impossibilidade da aplicação ser executada. -database.info_2=O nome do arquivo não importa ao enviar. Ele será renomeado em seguida para seguir o formato backup_user_yyyyMMddHHmm.sql, garantindo uma convenção de nomes coerente. +database.info_2=O nome do arquivo não importa ao enviar. Ele será renomeado em seguida para seguir o formato backup_usuario_yyyyMMddHHmm.sql, garantindo uma convenção de nomes coerente. database.submit=Importar Backup database.importIntoDatabaseSuccessed=Importação para o banco de dados bem sucedida database.fileNotFound=Arquivo não encontrado @@ -248,29 +248,29 @@ database.fileNullOrEmpty=O arquivo não pode estar nulo ou vazio database.failedImportFile=Falha ao importar arquivo session.expired=Sua sessão expirou. Por gentileza atualize a página e tente novamente. -session.refreshPage=Refresh Page +session.refreshPage=Atualizar Página ############# # HOME-PAGE # ############# -home.desc=Seu tudo-em-um hospedado localmente para tudo relacionado a PDFs. +home.desc=Seu tudo-em-um hospedado localmente para tudo relacionado a PDFs home.searchBar=Pesquisar funcionalidades... home.viewPdf.title=Visualizar PDF -home.viewPdf.desc=Visualizar, anotar, adicionar texto ou imagens +home.viewPdf.desc=Visualizar, anotar, adicionar texto ou imagens ao PDF. viewPdf.tags=visualizar,ler,anotar,texto,imagem -home.multiTool.title=Multiferramenta de PDF -home.multiTool.desc=Mesclar, girar, reorganizar, dividir e remover páginas -multiTool.tags=Multiferramenta, múltiplas operações, Interface do Usuário, Clique e arraste, front-end, lado do cliente, interativo, intratável, movimento, excluir, migrar, dividir +home.multiTool.title=Multiferramentas de PDF +home.multiTool.desc=Mesclar, girar, reorganizar, dividir, inserir e remover páginas. +multiTool.tags=Multiferramentas,múltiplas operações,Interface do Usuário,Clique e arraste,front-end,lado do cliente,interativo,intratável,movimento,excluir,migrar,dividir home.merge.title=Mesclar home.merge.desc=Mescle facilmente vários PDFs em um só. merge.tags=mesclar,Operações de Página,Back-end,lado do servidor home.split.title=Dividir -home.split.desc=Dividir PDFs em vários documentos +home.split.desc=Dividir PDFs em vários documentos/arquivos. split.tags=Operações de Página,dividir,Múltiplas Páginas,cortar,lado do servidor home.rotate.title=Girar @@ -279,41 +279,41 @@ rotate.tags=Lado do servidor home.imageToPdf.title=Imagem para PDF -home.imageToPdf.desc=Converter uma imagem (PNG, JPEG, GIF) em PDF. +home.imageToPdf.desc=Converter uma imagem (PNG, JPG, GIF) em PDF. imageToPdf.tags=conversão,img,jpg,imagem,foto home.pdfToImage.title=PDF para Imagem -home.pdfToImage.desc=Converter um PDF em uma imagem. (PNG, JPG, GIF) +home.pdfToImage.desc=Converter PDF em uma imagem (PNG, JPG, GIF e outros). pdfToImage.tags=conversão,img,jpg,imagem,foto -home.pdfOrganiser.title=Organizar -home.pdfOrganiser.desc=Remover/reorganizar as páginas em qualquer ordem. +home.pdfOrganiser.title=Organizar Páginas +home.pdfOrganiser.desc=Remover/reorganizar as páginas de diversas formas diferentes. pdfOrganiser.tags=duplex,par,ímpar,ordenar,mover home.addImage.title=Adicionar Imagem -home.addImage.desc=Adicionar uma imagem em um local definido no PDF +home.addImage.desc=Adicionar imagens em um local definido no PDF. addImage.tags=img,jpg,imagem,foto home.watermark.title=Adicionar Marca d'água -home.watermark.desc=Adicionar uma marca d'água personalizada ao seu documento PDF. +home.watermark.desc=Adicionar uma marca d'água personalizada ao seu PDF. watermark.tags=Texto,repetindo,rótulo,próprio,direitos autorais,marca registrada,img,jpg,imagem,foto home.permissions.title=Alterar Permissões -home.permissions.desc=Alterar as permissões do seu documento PDF. +home.permissions.desc=Alterar as permissões do seu PDF. permissions.tags=leitura,escrita,edição,impressão -home.removePages.title=Remover -home.removePages.desc=Excluir as páginas indesejadas do seu documento PDF. +home.removePages.title=Remover Páginas +home.removePages.desc=Excluir páginas indesejadas do seu PDF. removePages.tags=Remover páginas,excluir páginas -home.addPassword.title=Adicionar Senha -home.addPassword.desc=Criptografar seu documento PDF com uma senha. +home.addPassword.title=Proteger PDF +home.addPassword.desc=Criptografar seu PDF com uma senha podendo realizar alterações de permissões. addPassword.tags=seguro,segurança -home.removePassword.title=Remover Senha -home.removePassword.desc=Remover a proteção por senha do seu documento PDF. +home.removePassword.title=Desproteger PDF +home.removePassword.desc=Descriptografar o PDF realizando a remoção da senha. removePassword.tags=seguro, descriptografar, segurança, remover senha home.compressPdfs.title=Comprimir @@ -322,189 +322,189 @@ compressPdfs.tags=compactar,pequeno,mínimo home.changeMetadata.title=Alterar Metadados -home.changeMetadata.desc=Alterar/remover/adicionar metadados de um documento PDF. +home.changeMetadata.desc=Alterar/remover/adicionar metadados de um PDF. changeMetadata.tags=Título,autor,data,criação,hora,editor,produtor,estatísticas home.fileToPDF.title=Converter Arquivo para PDF -home.fileToPDF.desc=Converter praticamente qualquer arquivo em PDF (DOCX, PNG, XLS, PPT, TXT e mais) +home.fileToPDF.desc=Converter praticamente qualquer arquivo em PDF (DOCX, PNG, XLS, PPT, TXT e outros). fileToPDF.tags=transformação,formato,documento,imagem,slide,texto,conversão,escritório,documentos,word,excel,powerpoint -home.ocr.title=OCR / Limpeza de Digitalizações -home.ocr.desc=A limpeza verifica e detecta texto em imagens de um PDF e o adiciona novamente como texto. +home.ocr.title=Processamento de OCR +home.ocr.desc=Reconhecimento Óptico de Caracteres transforma PDFs com imagens em documentos pesquisáveis e com texto selecionável. ocr.tags=reconhecimento,texto,imagem,digitalização,leitura,identificação,detecção,editável home.extractImages.title=Extrair Imagens -home.extractImages.desc=Extrair todas as imagens de um PDF e salvá-las em um arquivo zip. +home.extractImages.desc=Extrair as imagens de um PDF e salvá-las em um arquivo compactado. extractImages.tags=imagem,foto,salvar,arquivo,zip,captura,coleta home.pdfToPDFA.title=PDF para PDF/A -home.pdfToPDFA.desc=Converter PDF para o formato PDF/A para armazenamento a longo prazo. +home.pdfToPDFA.desc=Converter o PDF para o formato PDF/A, voltado a armazenamento a longo prazo. pdfToPDFA.tags=arquivo,longo prazo,padrão,conversão,armazenamento,preservação home.PDFToWord.title=PDF para Word -home.PDFToWord.desc=Converter PDF para formatos Word (DOC, DOCX e ODT) +home.PDFToWord.desc=Converter PDF para formatos Word (DOC, DOCX e ODT). PDFToWord.tags=doc,docx,odt,word,transformação,formato,conversão,escritório,microsoft,doc home.PDFToPresentation.title=PDF para Apresentação -home.PDFToPresentation.desc=Converter PDF para formatos de apresentação (PPT, PPTX e ODP) +home.PDFToPresentation.desc=Converter PDF para formatos de Apresentação (PPT, PPTX e ODP). PDFToPresentation.tags=slides,apresentação,escritório,microsoft -home.PDFToText.title=PDF para Texto/RTF -home.PDFToText.desc=Converter PDF em formato de texto ou RTF +home.PDFToText.title=PDF para TXT/RTF +home.PDFToText.desc=Converter PDF em formato de TXT ou RTF. PDFToText.tags=formato rich,formato richtext,formato rich text home.PDFToHTML.title=PDF para HTML -home.PDFToHTML.desc=Converter PDF para o formato HTML +home.PDFToHTML.desc=Converter PDF para o formato HTML. PDFToHTML.tags=conteúdo web,compatível com navegador home.PDFToXML.title=PDF para XML -home.PDFToXML.desc=Converter PDF para formato XML +home.PDFToXML.desc=Converter PDF para formato XML. PDFToXML.tags=extração-de-dados,conteúdo-estruturado,interoperabilidade,transformação,converter home.ScannerImageSplit.title=Detectar/Dividir Fotos Digitalizadas -home.ScannerImageSplit.desc=Divide várias fotos de dentro de uma imagem/PDF +home.ScannerImageSplit.desc=Divide várias fotos de dentro de uma imagem/PDF. ScannerImageSplit.tags=separar,detecção-automática,digitalizações,fotos-múltiplas,organizar home.sign.title=Assinar -home.sign.desc=Adicionar assinatura ao PDF por desenho, texto ou imagem +home.sign.desc=Adicionar assinatura ao PDF por desenho, texto ou imagem. sign.tags=autorizar,iniciais,assinatura-desenhada,assinatura-de-texto,assinatura-de-imagem home.flatten.title=Achatar -home.flatten.desc=Remover todos os elementos e formulários interativos de um PDF +home.flatten.desc=Combinar todos os elementos e formulários interativos de um PDF em uma única camada fixa, não editável. flatten.tags=estático,desativar,não-interativo,otimizar home.repair.title=Reparar -home.repair.desc=Tentar reparar um PDF corrompido/quebrado +home.repair.desc=Tentar reparar um PDF corrompido/quebrado. repair.tags=corrigir,restaurar,correção,recuperar home.removeBlanks.title=Remover Páginas em Branco -home.removeBlanks.desc=Detectar e remover páginas em branco de um documento +home.removeBlanks.desc=Detectar e remover páginas em branco de um PDF. removeBlanks.tags=limpeza,otimização,sem-conteúdo,organizar home.removeAnnotations.title=Remover Anotações -home.removeAnnotations.desc=Remove todos os comentários/anotações de um PDF +home.removeAnnotations.desc=Remove todos os comentários/anotações de um PDF. removeAnnotations.tags=comentários,destaque,notas,marcação,remover home.compare.title=Comparar -home.compare.desc=Comparar e mostrar as diferenças entre 2 documentos PDF +home.compare.desc=Comparar e mostrar as diferenças entre dois documentos PDF. compare.tags=diferenciar,contraste,mudanças,análise home.certSign.title=Assinar com Certificado -home.certSign.desc=Assinar um PDF com um Certificado/Chave (PEM/P12) +home.certSign.desc=Assinar PDF com um Certificado/Chave (PEM/P12/JKS). certSign.tags=autenticar,PEM,P12,oficial,criptografar home.removeCertSign.title=Remover Assinatura com Certificado -home.removeCertSign.desc=Remover assinatura com certificado de PDF +home.removeCertSign.desc=Remover assinatura com Certificado/Chave (PEM/P12/JKS) em um PDF. removeCertSign.tags=autenticar,PEM,P12,oficial,descriptografar home.pageLayout.title=Layout de Múltiplas Páginas -home.pageLayout.desc=Mesclar várias páginas de um documento PDF em uma única página +home.pageLayout.desc=Mesclar várias páginas de um documento PDF em uma única página. pageLayout.tags=mesclar,composto,vista-única,organizar -home.scalePages.title=Ajustar Tamanho/Escala de Página +home.scalePages.title=Ajustar Tamanho/Escala da Página home.scalePages.desc=Alterar o tamanho/escala da página e/ou seu conteúdo. scalePages.tags=redimensionar,modificar,dimensão,adaptar home.pipeline.title=Pipeline -home.pipeline.desc=Executar várias ações em PDFs definindo scripts de pipeline +home.pipeline.desc=Executar várias ações em PDFs seguindo scripts de operações. pipeline.tags=automatizar,sequência,scriptado,processo-em-lote home.add-page-numbers.title=Adicionar Números de Página -home.add-page-numbers.desc=Adicionar números de página em todo o documento em um local definido +home.add-page-numbers.desc=Adicionar números de página no documento, em um local definido. add-page-numbers.tags=paginar,rotular,organizar,índice -home.auto-rename.title=Renomear Automaticamente o Arquivo PDF -home.auto-rename.desc=Renomeia automaticamente um arquivo PDF com base no cabeçalho detectado +home.auto-rename.title=Renomear Automaticamente o PDF +home.auto-rename.desc=Renomeia automaticamente o PDF com base no cabeçalho detectado. auto-rename.tags=detecção-automática,baseado-em-cabeçalho,organizar,relabel -home.adjust-contrast.title=Ajustar Cores/Contraste -home.adjust-contrast.desc=Ajustar Contraste, Saturação e Brilho de um PDF +home.adjust-contrast.title=Ajuste Visual do PDF +home.adjust-contrast.desc=Ajustar Contraste, Saturação e Brilho de um PDF. adjust-contrast.tags=correção-de-cor,ajustar,modificar,realçar -home.crop.title=Cortar PDF -home.crop.desc=Cortar um PDF para reduzir o tamanho (mantém o texto!) +home.crop.title=Recortar +home.crop.desc=Recortar trecho de um PDF para reduzir o tamanho. crop.tags=aparar,encolher,editar,formato home.autoSplitPDF.title=Divisão Automática de Páginas -home.autoSplitPDF.desc=Dividir automaticamente um PDF digitalizado com separador de páginas físicas QR Code +home.autoSplitPDF.desc=Dividir automaticamente um PDF digitalizado utilizando um separador de páginas físico com QR Code. autoSplitPDF.tags=baseado-em-QR,separar,segmento-de-digitalização,organizar home.sanitizePdf.title=Higienizar -home.sanitizePdf.desc=Remover scripts e outros elementos de arquivos PDF +home.sanitizePdf.desc=Remover scripts, links, metadados e outros elementos de um PDF. sanitizePdf.tags=limpar,seguro,protegido,remover-ameaças home.URLToPDF.title=Converter URL/Site para PDF -home.URLToPDF.desc=Converte qualquer página da internet para um arquivo PDF +home.URLToPDF.desc=Converter qualquer página da internet para um PDF. URLToPDF.tags=captura-de-web,salvar-página,web-para-doc,arquivar home.HTMLToPDF.title=HTML para PDF -home.HTMLToPDF.desc=Converte qualquer arquivo HTML ou zip para PDF +home.HTMLToPDF.desc=Converter qualquer arquivo HTML ou zip para PDF. HTMLToPDF.tags=marcação,conteúdo-web,transformação,converter home.MarkdownToPDF.title=Markdown para PDF -home.MarkdownToPDF.desc=Converte qualquer arquivo Markdown para PDF +home.MarkdownToPDF.desc=Converte qualquer arquivo Markdown para PDF. MarkdownToPDF.tags=marcação,conteúdo-web,transformação,converter -home.getPdfInfo.title=Obter TODAS as Informações de um PDF -home.getPdfInfo.desc=Obtém todas as informações possíveis de um PDF +home.getPdfInfo.title=Obter Informações de um PDF +home.getPdfInfo.desc=Obtém informações (metadata) de um PDF. getPdfInfo.tags=informações,dados,estatísticas home.extractPage.title=Extrair Página(s) -home.extractPage.desc=Extrai páginas selecionadas de um PDF +home.extractPage.desc=Extrair determinadas páginas de um PDF. extractPage.tags=extrair -home.PdfToSinglePage.title=PDF para Página Única Grande -home.PdfToSinglePage.desc=Combina todas as páginas de um PDF em uma única página grande +home.PdfToSinglePage.title=PDF para Página Única +home.PdfToSinglePage.desc=Combina todas as páginas de um PDF em uma única página. PdfToSinglePage.tags=página única home.showJS.title=Mostrar Javascript -home.showJS.desc=Procura e exibe qualquer JavaScript injetado em um PDF +home.showJS.desc=Procura, exibe e extrai qualquer JavaScript injetado em um PDF. showJS.tags=JavaScript -home.autoRedact.title=Auto Ocultar -home.autoRedact.desc=Ocultação automática (escurecimento) de texto em um PDF com base no texto de entrada +home.autoRedact.title=Ocultação de Texto +home.autoRedact.desc=Ocultação automática (escurecimento) de texto em um PDF com base em texto de entrada. autoRedact.tags=Redigir,ocultar,escurecer,preto,marcador,oculto home.tableExtraxt.title=PDF para CSV -home.tableExtraxt.desc=Extrai tabelas de um PDF convertendo para CSV +home.tableExtraxt.desc=Extração de tabelas de um PDF convertendo para CSV. tableExtraxt.tags=CSV,extração de tabela,extrair,converter -home.autoSizeSplitPDF.title=Divisão automática por tamanho/contagem -home.autoSizeSplitPDF.desc=Divida um único PDF em vários documentos com base no tamanho, contagem de páginas ou contagem de documentos +home.autoSizeSplitPDF.title=Divisão Manual do PDF +home.autoSizeSplitPDF.desc=Divida um PDF em vários, com base no tamanho, contagem de páginas ou contagem de documentos. autoSizeSplitPDF.tags=pdf,divisão,documento,organização home.overlay-pdfs.title=Sobrepor PDFs -home.overlay-pdfs.desc=Sobrepõe PDFs sobre outro PDF +home.overlay-pdfs.desc=Sobrepõe PDF sobre outro PDF. overlay-pdfs.tags=Sobreposição home.split-by-sections.title=Dividir PDF por Seções -home.split-by-sections.desc=Divida cada página de um PDF em seções horizontais e verticais menores +home.split-by-sections.desc=Divida cada página de um PDF em seções horizontais e/ou verticais menores. split-by-sections.tags=Seção Dividir, Dividir, Personalizar home.AddStampRequest.title=Adicionar Carimbo ao PDF -home.AddStampRequest.desc=Adicione texto ou carimbos de imagem em locais definidos +home.AddStampRequest.desc=Adicione texto ou carimbos de imagem em locais definidos. AddStampRequest.tags=Carimbo,Adicionar imagem,centralizar imagem,Marca d'água,PDF,Incorporar,Personalizar home.PDFToBook.title=PDF para Livro -home.PDFToBook.desc=Converte PDF para formatos de livro/quadrinhos usando Calibre +home.PDFToBook.desc=Converter PDF para formatos de livro/quadrinhos usando Calibre. PDFToBook.tags=Livro,Quadrinhos,Calibre,Converter,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf home.BookToPDF.title=Livro para PDF -home.BookToPDF.desc=Converte formatos de livros/quadrinhos para PDF usando Calibre +home.BookToPDF.desc=Converter formatos de livros/quadrinhos para PDF usando Calibre. BookToPDF.tags=Livro,Quadrinhos,Calibre,Converter,manga,amazon,kindle,epub,mobi,azw3,docx,rtf,txt,html,lit,fb2,pdb,lrf home.removeImagePdf.title=Remover Imagem -home.removeImagePdf.desc=Remova a imagem do PDF para reduzir o tamanho do arquivo +home.removeImagePdf.desc=Remova imagens do PDF para reduzir o tamanho do arquivo. removeImagePdf.tags=Remover imagem,operações de página,back-end,lado do servidor @@ -512,27 +512,27 @@ home.splitPdfByChapters.title=Divide PDF por Capítulos home.splitPdfByChapters.desc=Divide um PDF em vários arquivos baseado na sua estrutura de capítulos. splitPdfByChapters.tags=dividir,capítulos,favoritos,organizar -home.validateSignature.title=Validate PDF Signature -home.validateSignature.desc=Verify digital signatures and certificates in PDF documents -validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate +home.validateSignature.title=Verificar Assinatura com Certificado +home.validateSignature.desc=Verifica assinatura digital e certificado em um PDF. +validateSignature.tags=assinatura,verificação,validação,pdf,certificado,assinatura digital,validar assinatura,validar certificado #replace-invert-color -replace-color.title=Substituir-Inverter-Cor -replace-color.header=Substitui-Inverter Cor PDF -home.replaceColorPdf.title=Substitui e Inverte Cor -home.replaceColorPdf.desc=Substitui cor de um texto e plano de fundo de um PDF e inverte a toda cor do PDF para reduzir o tamanho +replace-color.title=Substitui e Inverte Cores +replace-color.header=Substitui e Inverte Cores +home.replaceColorPdf.title=Substitui e Inverte Cores +home.replaceColorPdf.desc=Substitui cor do texto e plano de fundo de um PDF e/ou inverte a toda cor do PDF para reduzir o tamanho. replaceColorPdf.tags=Substitui Cor, Operações na Página, back end, lado do servidor -replace-color.selectText.1=Substituir ou inverter cor Opções -replace-color.selectText.2=Padrão(Padrão cores de alto constraste) -replace-color.selectText.3=Customizado(Cores customizadas) -replace-color.selectText.4=Inversão Completa(Inverte todas cores) -replace-color.selectText.5=Opções de cores de alto contraste +replace-color.selectText.1=Substituir ou inverter cores Opções: +replace-color.selectText.2=Padrão (Cores de alto constraste) +replace-color.selectText.3=Customizado (Cores customizadas) +replace-color.selectText.4=Inversão Completa (Inverte todas cores) +replace-color.selectText.5=Opções de cores de alto contraste: replace-color.selectText.6=Texto branco em um plano de fundo preto replace-color.selectText.7=Texto preto em um plano de fundo branco replace-color.selectText.8=Texto amarelo em um plano de fundo preto replace-color.selectText.9=Texto verde em um plano de fundo preto -replace-color.selectText.10=Escolha cor do texto -replace-color.selectText.11=Escolha cor do plano de fundo +replace-color.selectText.10=Escolha a cor do texto: +replace-color.selectText.11=Escolha a cor do plano de fundo: replace-color.submit=Substituir @@ -560,28 +560,28 @@ login.oauth2AccessDenied=Acesso Negado login.oauth2InvalidTokenResponse=Resposta de Token Inválida login.oauth2InvalidIdToken=Id de Token Inválido login.userIsDisabled=O usuário está desativado, o login está atualmente bloqueado com este nome de usuário. Entre em contato com o administrador. -login.alreadyLoggedIn=Você já está conectado +login.alreadyLoggedIn=Você já está conectado em login.alreadyLoggedIn2=aparelhos. Por favor saia dos aparelhos e tente novamente. login.toManySessions=Você tem muitas sessões ativas #auto-redact -autoRedact.title=Redação Automática de Dados -autoRedact.header=Redação Automática de Dados -autoRedact.colorLabel=Cor -autoRedact.textsToRedactLabel=Texto para redigir (separado por linha) -autoRedact.textsToRedactPlaceholder=por exemplo: \nConfidencial \nSecreto -autoRedact.useRegexLabel=Usar Regex (expressão regular) -autoRedact.wholeWordSearchLabel=Pesquisa de palavras inteiras -autoRedact.customPaddingLabel=Preenchimento extra personalizado -autoRedact.convertPDFToImageLabel=Converter PDF em imagem PDF (Usado para remover o texto atrás da caixa) +autoRedact.title=Ocultação de Texto +autoRedact.header=Ocultação de Texto +autoRedact.colorLabel=Cor: +autoRedact.textsToRedactLabel=Texto para ocultar (um por linha): +autoRedact.textsToRedactPlaceholder=Por exemplo: \nConfidencial \nSecreto +autoRedact.useRegexLabel=Usar Regex (expressão regular). +autoRedact.wholeWordSearchLabel=Pesquisa apenas palavras inteiras. +autoRedact.customPaddingLabel=Preenchimento extra personalizado: +autoRedact.convertPDFToImageLabel=Converter PDF em imagem PDF (Usado para remover o texto atrás da caixa). autoRedact.submitButton=Enviar #showJS -showJS.title=Exibir JavaScript -showJS.header=Exibir JavaScript +showJS.title=Mostrar JavaScript +showJS.header=Mostrar JavaScript showJS.downloadJS=Baixar JavaScript -showJS.submit=Exibir +showJS.submit=Mostrar #pdfToSinglePage @@ -591,8 +591,8 @@ pdfToSinglePage.submit=Converter para Página Única #pageExtracter -pageExtracter.title=Extrair Páginas -pageExtracter.header=Extrair Páginas +pageExtracter.title=Extrair Página(s) +pageExtracter.header=Extrair Páginas(s) pageExtracter.submit=Extrair pageExtracter.placeholder=(por exemplo 1,2,8 or 4,7,12-16 ou 2n-1) @@ -608,25 +608,25 @@ getPdfInfo.downloadJson=Baixar JSON MarkdownToPDF.title=Markdown para PDF MarkdownToPDF.header=Markdown para PDF MarkdownToPDF.submit=Converter -MarkdownToPDF.help=Em desenvolvimento -MarkdownToPDF.credit=Usa o WeasyPrint +MarkdownToPDF.help=Em desenvolvimento. +MarkdownToPDF.credit=Utiliza o WeasyPrint. #url-to-pdf -URLToPDF.title=URL para PDF -URLToPDF.header=URL para PDF +URLToPDF.title=Converter URL/Site para PDF +URLToPDF.header=Converter URL/Site para PDF URLToPDF.submit=Converter -URLToPDF.credit=Usa o WeasyPrint +URLToPDF.credit=Utiliza o WeasyPrint. #html-to-pdf HTMLToPDF.title=HTML para PDF HTMLToPDF.header=HTML para PDF -HTMLToPDF.help=Aceita arquivos HTML e ZIPs contendo html, css, imagens, etc. necessários +HTMLToPDF.help=Aceita arquivos HTML e ZIPs contendo html, css, imagens, etc. HTMLToPDF.submit=Converter -HTMLToPDF.credit=Usa o WeasyPrint -HTMLToPDF.zoom=Nível de zoom para exibição do site. +HTMLToPDF.credit=Utiliza o WeasyPrint. +HTMLToPDF.zoom=Nível de zoom para exibição do site: HTMLToPDF.pageWidth=Largura da página em centímetros. (Em branco para padrão) HTMLToPDF.pageHeight=Altura da página em centímetros. (Em branco para padrão) HTMLToPDF.marginTop=Margem superior da página em milímetros. (Em branco para padrão) @@ -642,58 +642,58 @@ HTMLToPDF.screen=Tela #AddStampRequest -AddStampRequest.header=Carimbar PDF -AddStampRequest.title=Carimbar PDF -AddStampRequest.stampType=Tipo de carimbo -AddStampRequest.stampText=Texto do carimbo -AddStampRequest.stampImage=Imagem do carimbo -AddStampRequest.alphabet=Alfabeto -AddStampRequest.fontSize=Tamanho da fonte/imagem -AddStampRequest.rotation=Rotação -AddStampRequest.opacity=Opacidade -AddStampRequest.position=Posição -AddStampRequest.overrideX=Substituir Coordenada X -AddStampRequest.overrideY=Substituir Coordenada Y -AddStampRequest.customMargin=Margem personalizada -AddStampRequest.customColor=Cor de texto personalizada +AddStampRequest.header=Adicionar Carimbo ao PDF +AddStampRequest.title=Adicionar Carimbo ao PDF +AddStampRequest.stampType=Tipo de carimbo: +AddStampRequest.stampText=Texto do carimbo: +AddStampRequest.stampImage=Imagem do carimbo: +AddStampRequest.alphabet=Alfabeto: +AddStampRequest.fontSize=Tamanho da fonte/imagem: +AddStampRequest.rotation=Rotação: +AddStampRequest.opacity=Opacidade: +AddStampRequest.position=Posição: +AddStampRequest.overrideX=Substituir coordenada X: +AddStampRequest.overrideY=Substituir coordenada Y: +AddStampRequest.customMargin=Margem personalizada: +AddStampRequest.customColor=Cor de texto personalizada: AddStampRequest.submit=Enviar #sanitizePDF -sanitizePDF.title=Higienizar PDF -sanitizePDF.header=Higienizar um arquivo PDF -sanitizePDF.selectText.1=Remover ações de JavaScript -sanitizePDF.selectText.2=Remover arquivos embutidos -sanitizePDF.selectText.3=Remover metadados -sanitizePDF.selectText.4=Remover links -sanitizePDF.selectText.5=Remover fontes +sanitizePDF.title=Higienizar +sanitizePDF.header=Higienizar +sanitizePDF.selectText.1=Remover scripts de JavaScript. +sanitizePDF.selectText.2=Remover arquivos embutidos. +sanitizePDF.selectText.3=Remover metadados. +sanitizePDF.selectText.4=Remover links. +sanitizePDF.selectText.5=Remover fontes. sanitizePDF.submit=Higienizar PDF #addPageNumbers -addPageNumbers.title=Adicionar números de página -addPageNumbers.header=Adicionar números de página +addPageNumbers.title=Adicionar Números de Página +addPageNumbers.header=Adicionar Números de Página addPageNumbers.selectText.1=Selecionar arquivo PDF: -addPageNumbers.selectText.2=Tamanho da margem -addPageNumbers.selectText.3=Posição -addPageNumbers.selectText.4=Número inicial -addPageNumbers.selectText.5=Páginas a numerar -addPageNumbers.selectText.6=Texto personalizado -addPageNumbers.customTextDesc=Texto personalizado +addPageNumbers.selectText.2=Tamanho da margem: +addPageNumbers.selectText.3=Posição: +addPageNumbers.selectText.4=Número inicial: +addPageNumbers.selectText.5=Páginas a numerar: +addPageNumbers.selectText.6=Texto personalizado: +addPageNumbers.customTextDesc=Texto personalizado: addPageNumbers.numberPagesDesc=Quais páginas numerar, padrão 'todas', também aceita 1-5 ou 2,5,9,etc. addPageNumbers.customNumberDesc=O padrão é {n}, também aceita 'Página {n} de {total}', 'Texto-{n}', '{nome do arquivo}-{n}' -addPageNumbers.submit=Adicionar números de página +addPageNumbers.submit=Adicionar Números de Página #auto-rename -auto-rename.title=Renomeação automática -auto-rename.header=Renomeação automática de PDF -auto-rename.submit=Renomeação automática +auto-rename.title=Renomear Automaticamente o PDF +auto-rename.header=Renomear Automaticamente o PDF +auto-rename.submit=Renomeação Automática #adjustContrast -adjustContrast.title=Ajustar Contraste -adjustContrast.header=Ajustar Contraste +adjustContrast.title=Ajuste Visual do PDF +adjustContrast.header=Ajuste Visual do PDF adjustContrast.contrast=Contraste: adjustContrast.brightness=Brilho: adjustContrast.saturation=Saturação: @@ -701,21 +701,21 @@ adjustContrast.download=Baixar #crop -crop.title=Cortar -crop.header=Cortar PDF +crop.title=Recortar +crop.header=Recortar crop.submit=Enviar #autoSplitPDF -autoSplitPDF.title=Divisão Automática de PDF -autoSplitPDF.header=Divisão Automática de PDF -autoSplitPDF.description=Imprima, insira, digitalize, faça o upload e deixe que a gente divida seus documentos automaticamente. Nenhuma classificação manual necessária. -autoSplitPDF.selectText.1=Imprima algumas folhas divisórias abaixo (preto e branco está bom). -autoSplitPDF.selectText.2=Digitalize todos os seus documentos de uma vez, inserindo a folha divisória entre eles. -autoSplitPDF.selectText.3=Faça o upload do único arquivo PDF grande digitalizado e deixe o Stirling PDF cuidar do resto. +autoSplitPDF.title=Divisão Automática de Páginas +autoSplitPDF.header=Divisão Automática de Páginas +autoSplitPDF.description=Imprima, insira, digitalize, faça o upload e deixe que a gente divida seus documentos automaticamente. +autoSplitPDF.selectText.1=Imprima algumas folhas divisórias, descritas abaixo (preto e branco ou colorido). +autoSplitPDF.selectText.2=Digitalize todos os seus documentos de uma vez, inserindo a folha divisória enre os documentos que deseja separar. +autoSplitPDF.selectText.3=Faça o upload do arquivo único PDF digitalizado e deixe o Stirling PDF cuidar do resto. autoSplitPDF.selectText.4=As páginas divisórias são detectadas e removidas automaticamente, garantindo um documento final organizado. autoSplitPDF.formPrompt=Enviar PDF contendo folhas divisórias Stirling-PDF: -autoSplitPDF.duplexMode=Modo Duplex (Digitalização frente e verso) +autoSplitPDF.duplexMode=Modo Duplex (Digitalização frente e verso). autoSplitPDF.dividerDownload1=Baixar 'Folha Divisória Automática (mínimo).pdf' autoSplitPDF.dividerDownload2=Baixar 'Folha Divisória Automática (com instruções).pdf' autoSplitPDF.submit=Enviar @@ -729,31 +729,31 @@ pipeline.title=Pipeline pageLayout.title=Layout de Múltiplas Páginas pageLayout.header=Layout de Múltiplas Páginas pageLayout.pagesPerSheet=Páginas por folha: -pageLayout.addBorder=Adicionar bordas +pageLayout.addBorder=Adicionar bordas. pageLayout.submit=Enviar #scalePages scalePages.title=Ajustar Tamanho/Escala da Página scalePages.header=Ajustar Tamanho/Escala da Página -scalePages.pageSize=Tamanho de uma página do documento. -scalePages.keepPageSize=Tamanho original -scalePages.scaleFactor=Fator de zoom (corte) de uma página. +scalePages.pageSize=Tamanho desejado do documento: +scalePages.keepPageSize=Tamanho Original +scalePages.scaleFactor=Fator de zoom (corte) de uma página: scalePages.submit=Enviar #certSign certSign.title=Assinatura com Certificado -certSign.header=Assine um PDF com o seu certificado (Em desenvolvimento) +certSign.header=Assinatura com Certificado (Em desenvolvimento) certSign.selectPDF=Selecione um arquivo PDF para assinatura: certSign.jksNote=Nota: Se o seu tipo de certificado não estiver listado abaixo, converta-o em um arquivo Java Keystore (.jks) usando a ferramenta de linha de comando keytool. Em seguida, escolha a opção de arquivo .jks abaixo. certSign.selectKey=Selecione o seu arquivo de chave privada (formato PKCS#8, pode ser .pem ou .der): certSign.selectCert=Selecione o seu arquivo de certificado (formato X.509, pode ser .pem ou .der): certSign.selectP12=Selecione o seu arquivo de armazenamento de chave PKCS#12 (.p12 ou .pfx) (opcional, se fornecido, deve conter a sua chave privada e certificado): certSign.selectJKS=Selecione seu arquivo Java Keystore (.jks ou .keystore): -certSign.certType=Tipo de Certificado +certSign.certType=Tipo de Certificado: certSign.password=Digite a senha do seu armazenamento de chave ou chave privada (se aplicável): -certSign.showSig=Mostrar Assinatura +certSign.showSig=Mostrar Assinatura. certSign.reason=Razão certSign.location=Localização certSign.name=Nome @@ -762,20 +762,20 @@ certSign.submit=Assinar PDF #removeCertSign -removeCertSign.title=Remover Assinatura do Certificado -removeCertSign.header=Remover o certificado digital do PDF +removeCertSign.title=Remover Assinatura com Certificado +removeCertSign.header=Remover Assinatura com Certificado removeCertSign.selectPDF=Selecione um arquivo PDF: -removeCertSign.submit=Remover assinatura +removeCertSign.submit=Remover Assinatura #removeBlanks -removeBlanks.title=Remover páginas em branco -removeBlanks.header=Remover páginas em branco +removeBlanks.title=Remover Páginas em Branco +removeBlanks.header=Remover Páginas em Branco removeBlanks.threshold=Limite de brancura de pixel: -removeBlanks.thresholdDesc=Limite para determinar o quão branco um pixel branco deve ser para ser classificado como 'Branco'. 0 = Preto, 255 branco puro. -removeBlanks.whitePercent=Porcentagem de Branco (%): -removeBlanks.whitePercentDesc=Porcentagem da página que devem ter pixels “brancos” para serem removidas -removeBlanks.submit=Remover páginas em branco +removeBlanks.thresholdDesc=Limite para determinar o quão branco um pixel branco deve ser para ser classificado como "branco", para remoção. 0 = Preto, 255 = branco puro. +removeBlanks.whitePercent=Porcentagem de branco (%): +removeBlanks.whitePercentDesc=Porcentagem da página que devem ter pixels classificados como “brancos” para serem removidas. +removeBlanks.submit=Remover Páginas em Branco #removeAnnotations @@ -786,79 +786,79 @@ removeAnnotations.submit=Remover #compare compare.title=Comparar -compare.header=Comparar PDFs +compare.header=Comparar compare.highlightColor.1=Cor de destaque 1: compare.highlightColor.2=Cor de destaque 2: -compare.document.1=Documento 1 -compare.document.2=Documento 2 +compare.document.1=Documento 1: +compare.document.2=Documento 2: compare.submit=Comparar -compare.complex.message=Um ou ambos os documentos fornecidos são arquivos grandes, a precisão da comparação pode ser reduzida -compare.large.file.message=Um ou ambos os documentos fornecidos são muito grandes para processar +compare.complex.message=Um ou ambos os documentos fornecidos são arquivos grandes, a precisão da comparação pode ser reduzida. +compare.large.file.message=Um ou ambos os documentos fornecidos são muito grandes para processar. compare.no.text.message=Um ou ambos os PDFs selecionados não possuem conteúdo de texto. Por favor, escolha PDFs com texto para comparação. #BookToPDF -BookToPDF.title=Livros e Quadrinhos para PDF +BookToPDF.title=Livro para PDF BookToPDF.header=Livro para PDF -BookToPDF.credit=Usa o Calibre +BookToPDF.credit=Utiliza o Calibre. BookToPDF.submit=Converter #PDFToBook PDFToBook.title=PDF para Livro PDFToBook.header=PDF para Livro -PDFToBook.selectText.1=Formato -PDFToBook.credit=Usa o Calibre +PDFToBook.selectText.1=Formato: +PDFToBook.credit=Utiliza o Calibre. PDFToBook.submit=Converter #sign sign.title=Assinar -sign.header=Assinar PDFs -sign.upload=Enviar imagem +sign.header=Assinar +sign.upload=Enviar Imagem sign.draw=Desenhar Assinatura -sign.text=Inserir texto +sign.text=Inserir Texto sign.clear=Limpar sign.add=Adicionar sign.saved=Assinaturas Salvas sign.save=Salvar Assinatura sign.personalSigs=Assinaturas Pessoais sign.sharedSigs=Assinaturas Compartilhadas -sign.noSavedSigs=Nenhuma assinatura salva encontrada -sign.addToAll=Add to all pages -sign.delete=Delete -sign.first=First page -sign.last=Last page -sign.next=Next page -sign.previous=Previous page +sign.noSavedSigs=Nenhuma assinatura salva encontrada. +sign.addToAll=Adicionar em todas páginas +sign.delete=Apagar +sign.first=Primeira página +sign.last=Última página +sign.next=Próxima página +sign.previous=Página anterior #repair repair.title=Reparar -repair.header=Reparar PDFs +repair.header=Reparar repair.submit=Reparar #flatten flatten.title=Achatar -flatten.header=Achatar PDFs -flatten.flattenOnlyForms=Achatar apenas formulários +flatten.header=Achatar +flatten.flattenOnlyForms=Achatar apenas formulários interativos. flatten.submit=Achatar #ScannerImageSplit -ScannerImageSplit.selectText.1=Limite de Ângulo: +ScannerImageSplit.selectText.1=Limite de ângulo: ScannerImageSplit.selectText.2=Define o ângulo absoluto mínimo necessário para que a imagem seja girada (padrão: 10). ScannerImageSplit.selectText.3=Tolerância: ScannerImageSplit.selectText.4=Determina o intervalo de variação de cor em torno da cor de fundo estimada (padrão: 30). -ScannerImageSplit.selectText.5=Área Mínima: +ScannerImageSplit.selectText.5=Área mínima: ScannerImageSplit.selectText.6=Define o limite mínimo de área para uma foto (padrão: 10000). ScannerImageSplit.selectText.7=Área mínima de contorno: -ScannerImageSplit.selectText.8=Define o limite mínimo da área de contorno para uma foto +ScannerImageSplit.selectText.8=Define o limite mínimo da área de contorno para uma foto. ScannerImageSplit.selectText.9=Tamanho da borda: ScannerImageSplit.selectText.10=Define o tamanho da borda adicionada e removida para evitar bordas brancas na saída (padrão: 1). ScannerImageSplit.info=Python não está instalado. É necessário para executar. #OCR -ocr.title=OCR / Limpeza de Digitalização -ocr.header=OCR / Limpeza de Digitalização (Reconhecimento Óptico de Caracteres) +ocr.title=Processamento de OCR +ocr.header=Processamento de OCR (Reconhecimento Óptico de Caracteres) ocr.selectText.1=Selecione os idiomas a serem detectados no PDF (os listados são os atualmente instalados): ocr.selectText.2=Criar um arquivo de texto contendo o texto OCR junto do PDF com OCR ocr.selectText.3=Páginas corretamente digitalizadas em um ângulo inclinado, gire-as de volta à posição original @@ -868,46 +868,46 @@ ocr.selectText.6=Ignorar páginas com texto interativo, processar por OCR apenas ocr.selectText.7=Forçar OCR, executar OCR em todas as páginas, removendo todos os elementos de texto originais ocr.selectText.8=Normal (gerará um erro se o PDF já contiver texto) ocr.selectText.9=Configurações Adicionais -ocr.selectText.10=Modo OCR +ocr.selectText.10=Modo OCR: ocr.selectText.11=Remover imagens após o OCR (remove TODAS as imagens, útil apenas como parte do processo de conversão) -ocr.selectText.12=Tipo de Renderização (avançado) -ocr.help=Por favor, leia a documentação sobre como usar isso para outros idiomas e/ou fora do ambiente Docker -ocr.credit=Este serviço usa qpdf e Tesseract para OCR. -ocr.submit=Processar PDF com OCR +ocr.selectText.12=Tipo de renderização (Avançado): +ocr.help=Por favor, leia a documentação abaixo para saber mais sobre OCR e sua utilização. +ocr.credit=Este serviço usa Qpdf e Tesseract para OCR. +ocr.submit=Processar OCR no PDF #extractImages extractImages.title=Extrair Imagens extractImages.header=Extrair Imagens -extractImages.selectText=Selecione o formato de imagem para converter as imagens extraídas -extractImages.allowDuplicates=Salvar imagens duplicadas +extractImages.selectText=Selecione o formato de saída das imagens extraídas: +extractImages.allowDuplicates=Salvar imagens duplicadas. extractImages.submit=Extrair #File to PDF -fileToPDF.title=Arquivo para PDF -fileToPDF.header=Converter Qualquer Arquivo para PDF -fileToPDF.credit=Este serviço usa o LibreOffice e o Unoconv para conversão de arquivos. -fileToPDF.supportedFileTypesInfo=Tipos de arquivos suportados -fileToPDF.supportedFileTypes=Os tipos de arquivo suportados devem incluir os listados abaixo. No entanto, para obter uma lista atualizada completa dos formatos suportados, consulte a documentação do LibreOffice. +fileToPDF.title=Converter Arquivo para PDF +fileToPDF.header=Converter Arquivo para PDF +fileToPDF.credit=Este serviço usa o LibreOffice e o Unoconv realizar a conversão de arquivos. +fileToPDF.supportedFileTypesInfo=Tipos de Arquivos Suportados +fileToPDF.supportedFileTypes=A listagem abaixo não é exaustiva, para obter uma lista atualizada completa dos formatos suportados, consulte a documentação do LibreOffice. fileToPDF.submit=Converter para PDF #compress compress.title=Comprimir -compress.header=Comprimir PDF -compress.credit=Este serviço usa o qpdf para compressão/otimização de PDF. -compress.selectText.1=Modo Manual - De 1 a 4 +compress.header=Comprimir +compress.credit=Este serviço usa o Qpdf para compressão/otimização de PDF. +compress.selectText.1=Modo Manual - 1 (Menos) a 9 (Mais) compress.selectText.2=Nível de Otimização: compress.selectText.3=4 (Pior para imagens de texto) -compress.selectText.4=Modo Automático - Ajusta automaticamente a qualidade para atingir o tamanho exato do PDF -compress.selectText.5=Tamanho esperado do PDF (por exemplo, 25 MB, 10,8 MB, 25 KB) +compress.selectText.4=Modo Automático - Ajusta automaticamente a qualidade para atingir o tamanho exato desejado +compress.selectText.5=Tamanho esperado do PDF (por exemplo, 25 MB, 10,8 MB, 25 KB): compress.submit=Comprimir #Add image addImage.title=Adicionar Imagem -addImage.header=Adicionar imagem ao PDF +addImage.header=Adicionar Imagem addImage.everyPage=Para cada página? addImage.upload=Enviar imagem addImage.submit=Adicionar imagem @@ -915,18 +915,18 @@ addImage.submit=Adicionar imagem #merge merge.title=Mesclar -merge.header=Mesclar vários PDFs (2+) -merge.sortByName=Classificar por nome -merge.sortByDate=Classificar por data +merge.header=Mesclar +merge.sortByName=Classificar por Nome +merge.sortByDate=Classificar por Data merge.removeCertSign=Remover a assinatura digital do arquivo mesclado? merge.submit=Mesclar #pdfOrganiser -pdfOrganiser.title=Organizador de páginas -pdfOrganiser.header=Organizador de páginas PDF -pdfOrganiser.submit=Reorganizar páginas -pdfOrganiser.mode=Modo +pdfOrganiser.title=Organizar Páginas +pdfOrganiser.header=Organizar Páginas +pdfOrganiser.submit=Reorganizar Páginas +pdfOrganiser.mode=Modo: pdfOrganiser.mode.1=Ordem de página personalizada pdfOrganiser.mode.2=Ordem inversa pdfOrganiser.mode.3=Classificação duplex @@ -941,90 +941,90 @@ pdfOrganiser.placeholder=(por exemplo 1,3,2 ou 4-8,2,10-12 ou 2n-1) #multiTool -multiTool.title=Multiferramenta de PDF -multiTool.header=Multiferramenta de PDF -multiTool.uploadPrompts=Nome do arquivo -multiTool.selectAll=Select All -multiTool.deselectAll=Deselect All -multiTool.selectPages=Page Select -multiTool.selectedPages=Selected Pages -multiTool.page=Page -multiTool.deleteSelected=Delete Selected -multiTool.downloadAll=Export -multiTool.downloadSelected=Export Selected - -multiTool.insertPageBreak=Insert Page Break -multiTool.addFile=Add File -multiTool.rotateLeft=Rotate Left -multiTool.rotateRight=Rotate Right -multiTool.split=Split -multiTool.moveLeft=Move Left -multiTool.moveRight=Move Right -multiTool.delete=Delete -multiTool.dragDropMessage=Page(s) Selected -multiTool.undo=Undo -multiTool.redo=Redo +multiTool.title=Multiferramentas de PDF +multiTool.header=Multiferramentas de PDF +multiTool.uploadPrompts=Nome do Arquivo: +multiTool.selectAll=Selecionar Tudo +multiTool.deselectAll=Desselecionar Tudo +multiTool.selectPages=Selecionar Páginas +multiTool.selectedPages=Páginas Selecionadas +multiTool.page=Página +multiTool.deleteSelected=Apagar Selecionados +multiTool.downloadAll=Exportar +multiTool.downloadSelected=Exportar Selecionados + +multiTool.insertPageBreak=Inserir Página em Branco +multiTool.addFile=Inserir Arquivo +multiTool.rotateLeft=Girar para Esquerda +multiTool.rotateRight=Girar para Direita +multiTool.split=Dividir +multiTool.moveLeft=Mover para Esquerda +multiTool.moveRight=Mover para Direita +multiTool.delete=Apagar +multiTool.dragDropMessage=Página(s) Selecionadas +multiTool.undo=Desfazer +multiTool.redo=Refazer #multiTool-advert -multiTool-advert.message=This feature is also available in our multi-tool page. Check it out for enhanced page-by-page UI and additional features! +multiTool-advert.message=Esta função também está disponível em Multiferramentas de PDF. Com uma interface mais completa e funções adicionais. #view pdf viewPdf.title=Visualizar PDF viewPdf.header=Visualizar PDF #pageRemover -pageRemover.title=Remover página -pageRemover.header=Remover páginas do PDF -pageRemover.pagesToDelete=Páginas a serem excluídas (insira uma lista separada por vírgulas de números de página): -pageRemover.submit=Excluir páginas +pageRemover.title=Remover Páginas +pageRemover.header=Remover Páginas +pageRemover.pagesToDelete=Páginas a serem excluídas (insira uma lista separada por vírgulas, com os números de páginas): +pageRemover.submit=Excluir Páginas pageRemover.placeholder=(por exemplo 1,2,6 ou 1-10,15-30) #rotate -rotate.title=Girar PDF -rotate.header=Girar PDF +rotate.title=Girar +rotate.header=Girar rotate.selectAngle=Selecione o ângulo de rotação (múltiplos de 90 graus): rotate.submit=Girar #split-pdfs -split.title=Dividir PDF -split.header=Dividir PDF -split.desc.1=Os números selecionados correspondem às páginas onde você deseja fazer a divisão. -split.desc.2=Por exemplo, selecionar 1,3,7-9 dividirá um documento de 10 páginas em 6 PDFs separados da seguinte forma: +split.title=Dividir +split.header=Dividir +split.desc.1=Os números selecionados correspondem às páginas onde você deseja realizar a divisão. +split.desc.2=Por exemplo, selecionar 1,3,7-9 dividirá um documento de 11 páginas em 6 PDFs separados, da seguinte forma: split.desc.3=Documento Nº1: Página 1 split.desc.4=Documento Nº2: Páginas 2 e 3 split.desc.5=Documento Nº3: Páginas 4, 5, 6 e 7 split.desc.6=Documento Nº4: Página 8 split.desc.7=Documento Nº5: Página 9 -split.desc.8=Documento Nº6: Página 10 +split.desc.8=Documento Nº6: Página 10 e 11 (e mais se tiver) split.splitPages=Digite as páginas para a divisão: split.submit=Dividir #merge imageToPDF.title=Imagem para PDF -imageToPDF.header=Converter imagem para PDF +imageToPDF.header=Imagem para PDF imageToPDF.submit=Converter -imageToPDF.selectLabel=Opções de ajuste de imagem -imageToPDF.fillPage=Preencher página +imageToPDF.selectLabel=Opções de ajuste da imagem: +imageToPDF.fillPage=Preencher a página imageToPDF.fitDocumentToImage=Ajustar página à imagem imageToPDF.maintainAspectRatio=Manter proporções -imageToPDF.selectText.2=Girar automaticamente -imageToPDF.selectText.3=Lógica de vários arquivos (Ativada apenas ao trabalhar com várias imagens) +imageToPDF.selectText.2=Girar automaticamente. +imageToPDF.selectText.3=Lógica de vários arquivos (Ativada apenas ao trabalhar com várias imagens): imageToPDF.selectText.4=Mesclar em um único PDF imageToPDF.selectText.5=Converter em PDFs separados #pdfToImage pdfToImage.title=PDF para Imagem -pdfToImage.header=Converter PDF para imagem -pdfToImage.selectText=Formato de imagem -pdfToImage.singleOrMultiple=Tipo de resultado de imagem -pdfToImage.single=Imagem grande única combinando todas as páginas -pdfToImage.multi=Várias imagens, uma imagem por página -pdfToImage.colorType=Tipo de cor -pdfToImage.color=Colorida +pdfToImage.header=PDF para Imagem +pdfToImage.selectText=Formato da imagem: +pdfToImage.singleOrMultiple=Resultado da conversão: +pdfToImage.single=Imagem grande única combinando todas as páginas do PDF +pdfToImage.multi=Várias imagens, uma imagem por página do PDF +pdfToImage.colorType=Cor de saída: +pdfToImage.color=Colorido pdfToImage.grey=Escala de Cinza pdfToImage.blackwhite=Preto e Branco (pode perder informações!) pdfToImage.submit=Converter @@ -1032,24 +1032,24 @@ pdfToImage.info=Python não está instalado. Necessário para conversão WebP. #addPassword -addPassword.title=Adicionar senha -addPassword.header=Adicionar Senha (Criptografar) -addPassword.selectText.1=Selecione o PDF para Criptografar -addPassword.selectText.2=Senha -addPassword.selectText.3=Tamanho da Chave de Criptografia +addPassword.title=Proteger PDF +addPassword.header=Proteger PDF (Criptografar) +addPassword.selectText.1=Selecione o PDF para Criptografar: +addPassword.selectText.2=Senha de acesso: +addPassword.selectText.3=Tamanho da chave de criptografia: addPassword.selectText.4=Valores mais altos são mais seguros, mas valores mais baixos são melhores para compatibilidade. -addPassword.selectText.5=Permissões a serem definidas (recomendado para uso junto com a senha do proprietário) -addPassword.selectText.6=Impedir a montagem do documento -addPassword.selectText.7=Impedir a extração de conteúdo -addPassword.selectText.8=Impedir a extração para acessibilidade -addPassword.selectText.9=Impedir o preenchimento do formulário -addPassword.selectText.10=Impedir modificação -addPassword.selectText.11=Impedir modificação de anotação -addPassword.selectText.12=Impedir impressão -addPassword.selectText.13=Impedir impressão de formatos diferentes -addPassword.selectText.14=Senha do proprietário -addPassword.selectText.15=Restringe o que pode ser feito com o documento depois de aberto (não suportado por todos os leitores) -addPassword.selectText.16=Restringe a abertura do próprio documento +addPassword.selectText.5=Permissões a serem definidas (recomendado para uso junto com a senha do proprietário): +addPassword.selectText.6=Impedir a montagem do documento. +addPassword.selectText.7=Impedir a extração de conteúdo. +addPassword.selectText.8=Impedir a extração para acessibilidade. +addPassword.selectText.9=Impedir o preenchimento do formulário. +addPassword.selectText.10=Impedir modificação. +addPassword.selectText.11=Impedir modificação de anotações. +addPassword.selectText.12=Impedir impressão. +addPassword.selectText.13=Impedir impressão de formatos diferentes. +addPassword.selectText.14=Senha do proprietário: +addPassword.selectText.15=Restringe o que pode ser feito com o documento depois de aberto (não suportado por todos os leitores). +addPassword.selectText.16=Restringe a abertura do próprio documento. addPassword.submit=Criptografar @@ -1061,13 +1061,13 @@ watermark.selectText.1=Selecione PDF para adicionar a marca d'água: watermark.selectText.2=Texto da marca d'água: watermark.selectText.3=Tamanho da fonte: watermark.selectText.4=Rotação (0-360): -watermark.selectText.5=Width Spacer (Espaço entre cada marca d'água horizontalmente): -watermark.selectText.6=Height Spacer (Espaço entre cada marca d'água verticalmente): +watermark.selectText.5=Espaçador de Largura (Espaço entre cada marca d'água horizontalmente): +watermark.selectText.6=Espaçador de Altura (Espaço entre cada marca d'água verticalmente): watermark.selectText.7=Opacidade (0% - 100%): watermark.selectText.8=Tipo de marca d'água: watermark.selectText.9=Imagem da marca d'água: -watermark.selectText.10=Converter PDF em imagem PDF -watermark.submit=Adicionar marca d'água +watermark.selectText.10=Converter PDF em imagem PDF. +watermark.submit=Adicionar Marca D'água watermark.type.1=Texto watermark.type.2=Imagem @@ -1075,61 +1075,61 @@ watermark.type.2=Imagem #Change permissions permissions.title=Alterar Permissões permissions.header=Alterar Permissões -permissions.warning=Aviso: para que essas permissões sejam imutáveis, é recomendável defini-las com uma senha através da página Adicionar Senha -permissions.selectText.1=Selecione o PDF para alterar as permissões -permissions.selectText.2=Permissões para definir -permissions.selectText.3=Impedir montagem do documento -permissions.selectText.4=Impedir extração de conteúdo -permissions.selectText.5=Impedir extração para acessibilidade -permissions.selectText.6=Impedir preenchimento de formulário -permissions.selectText.7=Impedir modificações -permissions.selectText.8=Impedir modificação de anotação -permissions.selectText.9=Impedir impressão -permissions.selectText.10=Impedir impressão de formatos diferentes +permissions.warning=Aviso: para que essas permissões sejam imutáveis, é recomendável defini-las com uma senha através da página "Proteger PDF". +permissions.selectText.1=Selecione o PDF para alterar as permissões: +permissions.selectText.2=Permissões para definir: +permissions.selectText.3=Impedir montagem do documento. +permissions.selectText.4=Impedir extração de conteúdo. +permissions.selectText.5=Impedir extração para acessibilidade. +permissions.selectText.6=Impedir preenchimento de formulário. +permissions.selectText.7=Impedir modificações. +permissions.selectText.8=Impedir modificação de anotações. +permissions.selectText.9=Impedir impressão. +permissions.selectText.10=Impedir impressão de formatos diferentes. permissions.submit=Alterar #remove password -removePassword.title=Remover Senha -removePassword.header=Remover senha (descriptografar) -removePassword.selectText.1=Selecione o PDF para descriptografar +removePassword.title=Desproteger PDF +removePassword.header=Desproteger PDF (descriptografar) +removePassword.selectText.1=Selecione o PDF para descriptografar: removePassword.selectText.2=Senha -removePassword.submit=Remover +removePassword.submit=Descriptografar #changeMetadata changeMetadata.title=Alterar Metadados -changeMetadata.header=Alterar metadados -changeMetadata.selectText.1=Edite as variáveis ​​que deseja alterar -changeMetadata.selectText.2=Excluir todos os metadados -changeMetadata.selectText.3=Mostrar metadados personalizados: +changeMetadata.header=Alterar Metadados +changeMetadata.selectText.1=Edite as variáveis ​​que deseja alterar. +changeMetadata.selectText.2=Excluir todos os metadados. +changeMetadata.selectText.3=Mostrar metadados personalizados. changeMetadata.author=Autor: -changeMetadata.creationDate=Data de criação (aaaa/MM/dd HH:mm:ss): +changeMetadata.creationDate=Data de criação (aaaa/mm/dd HH:mm:ss): changeMetadata.creator=Criador: changeMetadata.keywords=Palavras-chave: -changeMetadata.modDate=Data de modificação (aaaa/MM/dd HH:mm:ss): +changeMetadata.modDate=Data de modificação (aaaa/mm/dd HH:mm:ss): changeMetadata.producer=Produtor: changeMetadata.subject=Assunto: -changeMetadata.trapped=Atrapado: +changeMetadata.trapped=Metadados trapping: changeMetadata.selectText.4=Outros metadados: -changeMetadata.selectText.5=Adicionar entrada de metadados personalizada +changeMetadata.selectText.5=Adicionar Entrada de Metadados Personalizada changeMetadata.submit=Alterar #pdfToPDFA pdfToPDFA.title=PDF para PDF/A pdfToPDFA.header=PDF para PDF/A -pdfToPDFA.credit=Este serviço usa qpdf para conversão de PDF/A +pdfToPDFA.credit=Este serviço usa Qpdf para conversão para PDF/A. pdfToPDFA.submit=Converter -pdfToPDFA.tip=Atualmente não funciona para múltiplas entradas ao mesmo tempo -pdfToPDFA.outputFormat=Formato de saída +pdfToPDFA.tip=Atenção, atualmente não funciona para múltiplas entradas ao mesmo tempo. +pdfToPDFA.outputFormat=Formato de saída: pdfToPDFA.pdfWithDigitalSignature=O PDF contém uma assinatura digital. Isso será removido na próxima etapa. #PDFToWord PDFToWord.title=PDF para Word PDFToWord.header=PDF para Word -PDFToWord.selectText.1=Formato do arquivo de saída +PDFToWord.selectText.1=Formato do arquivo de saída: PDFToWord.credit=Este serviço usa o LibreOffice para conversão de arquivos. PDFToWord.submit=Converter @@ -1137,15 +1137,15 @@ PDFToWord.submit=Converter #PDFToPresentation PDFToPresentation.title=PDF para Apresentação PDFToPresentation.header=PDF para Apresentação -PDFToPresentation.selectText.1=Formato do arquivo de saída +PDFToPresentation.selectText.1=Formato do arquivo de saída: PDFToPresentation.credit=Este serviço usa o LibreOffice para conversão de arquivos. PDFToPresentation.submit=Converter #PDFToText -PDFToText.title=PDF para RTF (Texto) -PDFToText.header=PDF para RTF (Texto) -PDFToText.selectText.1=Formato do arquivo de saída +PDFToText.title=PDF para TXT/RTF +PDFToText.header=PDF para TXT/RTF +PDFToText.selectText.1=Formato do arquivo de saída: PDFToText.credit=Este serviço usa o LibreOffice para conversão de arquivos. PDFToText.submit=Converter @@ -1166,26 +1166,26 @@ PDFToXML.submit=Converter #PDFToCSV PDFToCSV.title=PDF para CSV PDFToCSV.header=PDF para CSV -PDFToCSV.prompt=Escolha a página para extrair a tabela +PDFToCSV.prompt=Escolha a página para extração da tabela: PDFToCSV.submit=Extrair #split-by-size-or-count -split-by-size-or-count.title=Divida o PDF por tamanho ou contagem -split-by-size-or-count.header=Divida o PDF por tamanho ou contagem -split-by-size-or-count.type.label=Selecione o tipo de divisão +split-by-size-or-count.title=Divisão Manual do PDF +split-by-size-or-count.header=Divisão Manual do PDF +split-by-size-or-count.type.label=Selecione o tipo de divisão: split-by-size-or-count.type.size=Por tamanho split-by-size-or-count.type.pageCount=Por contagem de páginas split-by-size-or-count.type.docCount=Por contagem de documentos -split-by-size-or-count.value.label=Insira o valor +split-by-size-or-count.value.label=Insira o valor: split-by-size-or-count.value.placeholder=Insira o tamanho (por exemplo, 2 MB ou 3 KB) ou a contagem (por exemplo, 5) split-by-size-or-count.submit=Enviar #overlay-pdfs -overlay-pdfs.header=Sobrepor Arquivos PDF -overlay-pdfs.baseFile.label=Selecione o arquivo PDF base -overlay-pdfs.overlayFiles.label=Selecione os arquivos PDF para sobreposição -overlay-pdfs.mode.label=Selecione o modo de sobreposição +overlay-pdfs.header=Sobrepor PDFs +overlay-pdfs.baseFile.label=Selecione o arquivo PDF base: +overlay-pdfs.overlayFiles.label=Selecione os arquivos PDF para sobreposição: +overlay-pdfs.mode.label=Selecione o modo de sobreposição: overlay-pdfs.mode.sequential=Sobreposição sequencial overlay-pdfs.mode.interleaved=Sobreposição intercalada overlay-pdfs.mode.fixedRepeat=Sobreposição de repetição fixa @@ -1198,14 +1198,14 @@ overlay-pdfs.submit=Enviar #split-by-sections -split-by-sections.title=Dividir PDF por seções -split-by-sections.header=Divida o PDF em seções -split-by-sections.horizontal.label=Divisões Horizontais -split-by-sections.vertical.label=Divisões Verticais +split-by-sections.title=Dividir PDF por Seções +split-by-sections.header=Dividir PDF por Seções +split-by-sections.horizontal.label=Divisões Horizontais: +split-by-sections.vertical.label=Divisões Verticais: split-by-sections.horizontal.placeholder=Insira o número de divisões horizontais split-by-sections.vertical.placeholder=Insira o número de divisões verticais -split-by-sections.submit=Dividir PDF -split-by-sections.merge=Mesclar em um PDF +split-by-sections.submit=Dividir +split-by-sections.merge=Mesclar em um PDF. #printFile @@ -1227,13 +1227,13 @@ licenses.license=Licença #survey survey.nav=Pesquisa survey.title=Pesquisa Stirling-PDF -survey.description=Stirling-PDF não tem rastreamento, então queremos ouvir nossos usuários para melhorar o Stirling-PDF! -survey.changes=Stirling-PDF mudou desde o a última pesquisa! Para saber mais acesse nosso post no blog: -survey.changes2=Com essas mudanças estamos implementando suporte empresarial pago e financeamento +survey.description=Stirling-PDF não possui rastreamento, então queremos ouvir nossos usuários para melhorar o Stirling-PDF! +survey.changes=Stirling-PDF mudou desde sua última pesquisa! Para saber mais acesse nosso blog: +survey.changes2=Com essas mudanças estamos implementando suporte empresarial pago e financeamento. survey.please=Por favor, considere responder à nossa pesquisa! survey.disabled=(O pop-up da pesquisa será desativado nas atualizações seguintes, mas estará disponível no rodapé da página) -survey.button=Responda a pesquisa -survey.dontShowAgain=Não mostre novamente +survey.button=Responder a Pesquisa +survey.dontShowAgain=Não mostre novamente. #error @@ -1252,66 +1252,66 @@ error.discordSubmit=Discord - Submeter um post de suporte #remove-image removeImage.title=Remover Imagem -removeImage.header=Remover imagem -removeImage.removeImage=Remover imagem -removeImage.submit=Remover imagem - - -splitByChapters.title=Dividir PDF por Capítulos -splitByChapters.header=Dividir PDF por Capítulos -splitByChapters.bookmarkLevel=Nível de Marcador -splitByChapters.includeMetadata=Incluir Metadados -splitByChapters.allowDuplicates=Permitir Cópias -splitByChapters.desc.1=Essa ferramenta divide um arquivo PDF em vários arquivos PDFs baseado na estrutura de cápitulos. -splitByChapters.desc.2=Nível de Marcador: Escolha o nível de marcador a ser usado para divisão (0 para o primeiro nível, 1 para o segundo nível, etc). -splitByChapters.desc.3=Incluir Metadados: Se marcado, os metadados do PDF original serão incluidos em cada divisão do PDF. +removeImage.header=Remover Imagem +removeImage.removeImage=Remover Imagem +removeImage.submit=Remover Imagem + + +splitByChapters.title=Divide PDF por Capítulos +splitByChapters.header=Divide PDF por Capítulos +splitByChapters.bookmarkLevel=Nível do Marcador: +splitByChapters.includeMetadata=Incluir Metadados. +splitByChapters.allowDuplicates=Permitir Cópias. +splitByChapters.desc.1=Essa ferramenta divide um arquivo PDF em vários arquivos PDFs baseado na estrutura de capítulos. +splitByChapters.desc.2=Nível do Marcador: Escolha o nível do marcador a ser usado para divisão (0 para o primeiro nível, 1 para o segundo nível, etc). +splitByChapters.desc.3=Incluir Metadados: Se marcado, os metadados do PDF original serão incluidos em cada arquivo gerado pela divisão do PDF. splitByChapters.desc.4=Permitir Cópias: Se marcado, habilita vários marcadores na mesma página para criar PDFs separados. -splitByChapters.submit=Dividir PDF +splitByChapters.submit=Dividir #File Chooser -fileChooser.click=Click -fileChooser.or=or -fileChooser.dragAndDrop=Drag & Drop -fileChooser.hoveredDragAndDrop=Drag & Drop file(s) here +fileChooser.click=Clique +fileChooser.or=ou +fileChooser.dragAndDrop=Arraste & Solte +fileChooser.hoveredDragAndDrop=Arraste & Solte arquivo(s) aqui #release notes -releases.footer=Releases -releases.title=Release Notes -releases.header=Release Notes -releases.current.version=Current Release -releases.note=Release notes are only available in English +releases.footer=Versões +releases.title=Notas de Lançamento +releases.header=Notas de Lançamento +releases.current.version=Versão Atual +releases.note=Notas de Lançamento estão disponíveis apenas em Inglês #Validate Signature -validateSignature.title=Validate PDF Signatures -validateSignature.header=Validate Digital Signatures -validateSignature.selectPDF=Select signed PDF file -validateSignature.submit=Validate Signatures -validateSignature.results=Validation Results -validateSignature.status=Status -validateSignature.signer=Signer -validateSignature.date=Date -validateSignature.reason=Reason -validateSignature.location=Location -validateSignature.noSignatures=No digital signatures found in this document -validateSignature.status.valid=Valid -validateSignature.status.invalid=Invalid -validateSignature.chain.invalid=Certificate chain validation failed - cannot verify signer's identity -validateSignature.trust.invalid=Certificate not in trust store - source cannot be verified -validateSignature.cert.expired=Certificate has expired -validateSignature.cert.revoked=Certificate has been revoked -validateSignature.signature.info=Signature Information -validateSignature.signature=Signature -validateSignature.signature.mathValid=Signature is mathematically valid BUT: -validateSignature.selectCustomCert=Custom Certificate File X.509 (Optional) -validateSignature.cert.info=Certificate Details -validateSignature.cert.issuer=Issuer -validateSignature.cert.subject=Subject -validateSignature.cert.serialNumber=Serial Number -validateSignature.cert.validFrom=Valid From -validateSignature.cert.validUntil=Valid Until -validateSignature.cert.algorithm=Algorithm -validateSignature.cert.keySize=Key Size -validateSignature.cert.version=Version -validateSignature.cert.keyUsage=Key Usage -validateSignature.cert.selfSigned=Self-Signed +validateSignature.title=Verificar Assinatura com Certificado +validateSignature.header=Verificar Assinatura com Certificado +validateSignature.selectPDF=Selecione PDF com assinatura por certificado: +validateSignature.submit=Verificar Assinatura +validateSignature.results=Resultados da Verificação +validateSignature.status=Situação +validateSignature.signer=Signatário +validateSignature.date=Data +validateSignature.reason=Motivo +validateSignature.location=Localização +validateSignature.noSignatures=Nenhuma assinatura digital encontrada no documento. +validateSignature.status.valid=Valido +validateSignature.status.invalid=Inválido +validateSignature.chain.invalid=Falha na validação da cadeia de certificados - não é possível verificar a identidade do signatário +validateSignature.trust.invalid=Certificado não está presente no repositório de confiança, a fonte não pode ser verificada +validateSignature.cert.expired=Certificate expirou +validateSignature.cert.revoked=Certificado foi revogado +validateSignature.signature.info=Informações da assinatura +validateSignature.signature=Assinatura +validateSignature.signature.mathValid=Assinatura é matematicamente valida PORÉM: +validateSignature.selectCustomCert=Arquivo customizado de certificado X.509 (Opcional) +validateSignature.cert.info=Detalhes do certificado +validateSignature.cert.issuer=Emissor +validateSignature.cert.subject=Assunto +validateSignature.cert.serialNumber=Número de serial +validateSignature.cert.validFrom=Valido de +validateSignature.cert.validUntil=Valido até +validateSignature.cert.algorithm=Algoritmo +validateSignature.cert.keySize=Tamanho da chave +validateSignature.cert.version=Versão +validateSignature.cert.keyUsage=Uso da chave +validateSignature.cert.selfSigned=Autoassinados validateSignature.cert.bits=bits From 64dfa4b8416aba48524137516c908f4f00674f26 Mon Sep 17 00:00:00 2001 From: Reece Browne Date: Tue, 10 Dec 2024 22:21:00 +0000 Subject: [PATCH 11/27] Tweak additional files to integrate decryption and clean up js --- src/main/resources/static/js/fileInput.js | 2 +- .../resources/static/js/pages/add-image.js | 47 ++++++ .../static/js/pages/change-metadata.js | 150 +++++++++++++++++ src/main/resources/static/js/pages/crop.js | 159 ++++++++++++++++++ .../resources/static/js/pages/pdf-to-csv.js | 138 +++++++++++++++ src/main/resources/static/js/pages/sign.js | 2 - .../templates/convert/pdf-to-csv.html | 136 +-------------- src/main/resources/templates/crop.html | 158 +---------------- .../resources/templates/misc/add-image.html | 50 +----- .../templates/misc/change-metadata.html | 135 +-------------- src/main/resources/templates/overlay-pdf.html | 1 + 11 files changed, 501 insertions(+), 477 deletions(-) create mode 100644 src/main/resources/static/js/pages/add-image.js create mode 100644 src/main/resources/static/js/pages/change-metadata.js create mode 100644 src/main/resources/static/js/pages/crop.js create mode 100644 src/main/resources/static/js/pages/pdf-to-csv.js diff --git a/src/main/resources/static/js/fileInput.js b/src/main/resources/static/js/fileInput.js index 57010b6c68b..63485c60621 100644 --- a/src/main/resources/static/js/fileInput.js +++ b/src/main/resources/static/js/fileInput.js @@ -2,7 +2,6 @@ import FileIconFactory from './file-icon-factory.js'; import FileUtils from './file-utils.js'; import UUID from './uuid.js'; import {DecryptFile} from './DecryptFiles.js'; -const decryptFile = new DecryptFile(); let isScriptExecuted = false; if (!isScriptExecuted) { isScriptExecuted = true; @@ -123,6 +122,7 @@ function setupFileInput(chooser) { return decryptedFile; } catch (error) { console.error(`Error decrypting file: ${file.name}`, error); + if (!file.uniqueId) file.uniqueId = UUID.uuidv4(); return file; } }) diff --git a/src/main/resources/static/js/pages/add-image.js b/src/main/resources/static/js/pages/add-image.js new file mode 100644 index 00000000000..5899b53f9da --- /dev/null +++ b/src/main/resources/static/js/pages/add-image.js @@ -0,0 +1,47 @@ +document.getElementById('download-pdf').addEventListener('click', async () => { + const modifiedPdf = await DraggableUtils.getOverlayedPdfDocument(); + const modifiedPdfBytes = await modifiedPdf.save(); + const blob = new Blob([modifiedPdfBytes], {type: 'application/pdf'}); + const link = document.createElement('a'); + link.href = URL.createObjectURL(blob); + link.download = originalFileName + '_addedImage.pdf'; + link.click(); +}); +let originalFileName = ''; +document.querySelector('input[name=pdf-upload]').addEventListener('change', async (event) => { + const fileInput = event.target; + fileInput.addEventListener('file-input-change', async (e) => { + const {allFiles} = e.detail; + if (allFiles && allFiles.length > 0) { + const file = allFiles[0]; + originalFileName = file.name.replace(/\.[^/.]+$/, ''); + const pdfData = await file.arrayBuffer(); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + const pdfDoc = await pdfjsLib.getDocument({data: pdfData}).promise; + await DraggableUtils.renderPage(pdfDoc, 0); + + document.querySelectorAll('.show-on-file-selected').forEach((el) => { + el.style.cssText = ''; + }); + } + }); +}); +document.addEventListener('DOMContentLoaded', () => { + document.querySelectorAll('.show-on-file-selected').forEach((el) => { + el.style.cssText = 'display:none !important'; + }); +}); + +const imageUpload = document.querySelector('input[name=image-upload]'); +imageUpload.addEventListener('change', (e) => { + if (!e.target.files) { + return; + } + for (const imageFile of e.target.files) { + var reader = new FileReader(); + reader.readAsDataURL(imageFile); + reader.onloadend = function (e) { + DraggableUtils.createDraggableCanvasFromUrl(e.target.result); + }; + } +}); diff --git a/src/main/resources/static/js/pages/change-metadata.js b/src/main/resources/static/js/pages/change-metadata.js new file mode 100644 index 00000000000..bdc5426b711 --- /dev/null +++ b/src/main/resources/static/js/pages/change-metadata.js @@ -0,0 +1,150 @@ +const deleteAllCheckbox = document.querySelector('#deleteAll'); +let inputs = document.querySelectorAll('input'); +const customMetadataDiv = document.getElementById('customMetadata'); +const otherMetadataEntriesDiv = document.getElementById('otherMetadataEntries'); + +deleteAllCheckbox.addEventListener('change', function (event) { + inputs.forEach((input) => { + // If it's the deleteAllCheckbox or any file input, skip + if (input === deleteAllCheckbox || input.type === 'file') { + return; + } + // Disable or enable based on the checkbox state + input.disabled = deleteAllCheckbox.checked; + }); +}); + +const customModeCheckbox = document.getElementById('customModeCheckbox'); +const addMetadataBtn = document.getElementById('addMetadataBtn'); +const customMetadataFormContainer = document.getElementById('customMetadataEntries'); +var count = 1; +const fileInput = document.querySelector('#fileInput-input'); +const authorInput = document.querySelector('#author'); +const creationDateInput = document.querySelector('#creationDate'); +const creatorInput = document.querySelector('#creator'); +const keywordsInput = document.querySelector('#keywords'); +const modificationDateInput = document.querySelector('#modificationDate'); +const producerInput = document.querySelector('#producer'); +const subjectInput = document.querySelector('#subject'); +const titleInput = document.querySelector('#title'); +const trappedInput = document.querySelector('#trapped'); +var lastPDFFileMeta = null; +var lastPDFFile = null; + +fileInput.addEventListener('change', async function () { + fileInput.addEventListener('file-input-change', async (e) => { + const {allFiles} = e.detail; + if (allFiles && allFiles.length > 0) { + const file = allFiles[0]; + while (otherMetadataEntriesDiv.firstChild) { + otherMetadataEntriesDiv.removeChild(otherMetadataEntriesDiv.firstChild); + } + while (customMetadataFormContainer.firstChild) { + customMetadataFormContainer.removeChild(customMetadataFormContainer.firstChild); + } + var url = URL.createObjectURL(file); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + const pdf = await pdfjsLib.getDocument(url).promise; + const pdfMetadata = await pdf.getMetadata(); + lastPDFFile = pdfMetadata?.info; + console.log(pdfMetadata); + if (!pdfMetadata?.info?.Custom || pdfMetadata?.info?.Custom.size == 0) { + customModeCheckbox.disabled = true; + customModeCheckbox.checked = false; + } else { + customModeCheckbox.disabled = false; + } + authorInput.value = pdfMetadata?.info?.Author; + creationDateInput.value = convertDateFormat(pdfMetadata?.info?.CreationDate); + creatorInput.value = pdfMetadata?.info?.Creator; + keywordsInput.value = pdfMetadata?.info?.Keywords; + modificationDateInput.value = convertDateFormat(pdfMetadata?.info?.ModDate); + producerInput.value = pdfMetadata?.info?.Producer; + subjectInput.value = pdfMetadata?.info?.Subject; + titleInput.value = pdfMetadata?.info?.Title; + console.log(pdfMetadata?.info); + const trappedValue = pdfMetadata?.info?.Trapped; + // Get all options in the select element + const options = trappedInput.options; + // Loop through all options to find the one with a matching value + for (let i = 0; i < options.length; i++) { + if (options[i].value === trappedValue) { + options[i].selected = true; + break; + } + } + addExtra(); + } + }); +}); + +addMetadataBtn.addEventListener('click', () => { + const keyInput = document.createElement('input'); + keyInput.type = 'text'; + keyInput.placeholder = 'Key'; + keyInput.className = 'form-control'; + keyInput.name = `allRequestParams[customKey${count}]`; + + const valueInput = document.createElement('input'); + valueInput.type = 'text'; + valueInput.placeholder = 'Value'; + valueInput.className = 'form-control'; + valueInput.name = `allRequestParams[customValue${count}]`; + count = count + 1; + + const formGroup = document.createElement('div'); + formGroup.className = 'mb-3'; + formGroup.appendChild(keyInput); + formGroup.appendChild(valueInput); + + customMetadataFormContainer.appendChild(formGroup); +}); +function convertDateFormat(dateTimeString) { + if (!dateTimeString || dateTimeString.length < 17) { + return dateTimeString; + } + + const year = dateTimeString.substring(2, 6); + const month = dateTimeString.substring(6, 8); + const day = dateTimeString.substring(8, 10); + const hour = dateTimeString.substring(10, 12); + const minute = dateTimeString.substring(12, 14); + const second = dateTimeString.substring(14, 16); + + return year + '/' + month + '/' + day + ' ' + hour + ':' + minute + ':' + second; +} + +function addExtra() { + const event = document.getElementById('customModeCheckbox'); + if (event.checked && lastPDFFile.Custom != null) { + customMetadataDiv.style.display = 'block'; + for (const [key, value] of Object.entries(lastPDFFile.Custom)) { + if ( + key === 'Author' || + key === 'CreationDate' || + key === 'Creator' || + key === 'Keywords' || + key === 'ModDate' || + key === 'Producer' || + key === 'Subject' || + key === 'Title' || + key === 'Trapped' + ) { + continue; + } + const entryDiv = document.createElement('div'); + entryDiv.className = 'mb-3'; + entryDiv.innerHTML = `
`; + otherMetadataEntriesDiv.appendChild(entryDiv); + } + } else { + customMetadataDiv.style.display = 'none'; + while (otherMetadataEntriesDiv.firstChild) { + otherMetadataEntriesDiv.removeChild(otherMetadataEntriesDiv.firstChild); + } + } +} + +customModeCheckbox.addEventListener('change', (event) => { + addExtra(); +}); diff --git a/src/main/resources/static/js/pages/crop.js b/src/main/resources/static/js/pages/crop.js new file mode 100644 index 00000000000..1854023a07f --- /dev/null +++ b/src/main/resources/static/js/pages/crop.js @@ -0,0 +1,159 @@ +let pdfCanvas = document.getElementById('cropPdfCanvas'); +let overlayCanvas = document.getElementById('overlayCanvas'); +let canvasesContainer = document.getElementById('canvasesContainer'); +canvasesContainer.style.display = 'none'; +let containerRect = canvasesContainer.getBoundingClientRect(); + +let context = pdfCanvas.getContext('2d'); +let overlayContext = overlayCanvas.getContext('2d'); + +overlayCanvas.width = pdfCanvas.width; +overlayCanvas.height = pdfCanvas.height; + +let isDrawing = false; // New flag to check if drawing is ongoing + +let cropForm = document.getElementById('cropForm'); +let fileInput = document.getElementById('fileInput-input'); +let xInput = document.getElementById('x'); +let yInput = document.getElementById('y'); +let widthInput = document.getElementById('width'); +let heightInput = document.getElementById('height'); + +let pdfDoc = null; +let currentPage = 1; +let totalPages = 0; + +let startX = 0; +let startY = 0; +let rectWidth = 0; +let rectHeight = 0; + +let pageScale = 1; // The scale which the pdf page renders +let timeId = null; // timeout id for resizing canvases event + +function renderPageFromFile(file) { + if (file.type === 'application/pdf') { + let reader = new FileReader(); + reader.onload = function (ev) { + let typedArray = new Uint8Array(reader.result); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + pdfjsLib.getDocument(typedArray).promise.then(function (pdf) { + pdfDoc = pdf; + totalPages = pdf.numPages; + renderPage(currentPage); + }); + }; + reader.readAsArrayBuffer(file); + } +} + +window.addEventListener('resize', function () { + clearTimeout(timeId); + + timeId = setTimeout(function () { + if (fileInput.files.length == 0) return; + let canvasesContainer = document.getElementById('canvasesContainer'); + let containerRect = canvasesContainer.getBoundingClientRect(); + + context.clearRect(0, 0, pdfCanvas.width, pdfCanvas.height); + + overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); + + pdfCanvas.width = containerRect.width; + pdfCanvas.height = containerRect.height; + + overlayCanvas.width = containerRect.width; + overlayCanvas.height = containerRect.height; + + let file = fileInput.files[0]; + renderPageFromFile(file); + }, 1000); +}); + +fileInput.addEventListener('change', function (e) { + fileInput.addEventListener('file-input-change', async (e) => { + const {allFiles} = e.detail; + if (allFiles && allFiles.length > 0) { + canvasesContainer.style.display = 'block'; // set for visual purposes + let file = allFiles[0]; + renderPageFromFile(file); + } + }); +}); + +cropForm.addEventListener('submit', function (e) { + if (xInput.value == '' && yInput.value == '' && widthInput.value == '' && heightInput.value == '') { + // Ορίστε συντεταγμένες για ολόκληρη την επιφάνεια του PDF + xInput.value = 0; + yInput.value = 0; + widthInput.value = containerRect.width; + heightInput.value = containerRect.height; + } +}); + +overlayCanvas.addEventListener('mousedown', function (e) { + // Clear previously drawn rectangle on the main canvas + context.clearRect(0, 0, pdfCanvas.width, pdfCanvas.height); + renderPage(currentPage); // Re-render the PDF + + // Clear the overlay canvas to ensure old drawings are removed + overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); + + startX = e.offsetX; + startY = e.offsetY; + isDrawing = true; +}); + +overlayCanvas.addEventListener('mousemove', function (e) { + if (!isDrawing) return; + overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); // Clear previous rectangle + + rectWidth = e.offsetX - startX; + rectHeight = e.offsetY - startY; + overlayContext.strokeStyle = 'red'; + overlayContext.strokeRect(startX, startY, rectWidth, rectHeight); +}); + +overlayCanvas.addEventListener('mouseup', function (e) { + isDrawing = false; + + rectWidth = e.offsetX - startX; + rectHeight = e.offsetY - startY; + + let flippedY = pdfCanvas.height - e.offsetY; + + xInput.value = startX / pageScale; + yInput.value = flippedY / pageScale; + widthInput.value = rectWidth / pageScale; + heightInput.value = rectHeight / pageScale; + + // Draw the final rectangle on the main canvas + context.strokeStyle = 'red'; + context.strokeRect(startX, startY, rectWidth, rectHeight); + + overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); // Clear the overlay +}); + +function renderPage(pageNumber) { + pdfDoc.getPage(pageNumber).then(function (page) { + let canvasesContainer = document.getElementById('canvasesContainer'); + let containerRect = canvasesContainer.getBoundingClientRect(); + + pageScale = containerRect.width / page.getViewport({scale: 1}).width; // The new scale + + let viewport = page.getViewport({scale: containerRect.width / page.getViewport({scale: 1}).width}); + + canvasesContainer.width = viewport.width; + canvasesContainer.height = viewport.height; + + pdfCanvas.width = viewport.width; + pdfCanvas.height = viewport.height; + + overlayCanvas.width = viewport.width; // Match overlay canvas size with PDF canvas + overlayCanvas.height = viewport.height; + + let renderContext = {canvasContext: context, viewport: viewport}; + page.render(renderContext); + pdfCanvas.classList.add('shadow-canvas'); + }); +} diff --git a/src/main/resources/static/js/pages/pdf-to-csv.js b/src/main/resources/static/js/pages/pdf-to-csv.js new file mode 100644 index 00000000000..6be3c2ed643 --- /dev/null +++ b/src/main/resources/static/js/pages/pdf-to-csv.js @@ -0,0 +1,138 @@ +let pdfCanvas = document.getElementById('cropPdfCanvas'); +let overlayCanvas = document.getElementById('overlayCanvas'); +let canvasesContainer = document.getElementById('canvasesContainer'); +canvasesContainer.style.display = 'none'; +// let paginationBtnContainer = ; + +let context = pdfCanvas.getContext('2d'); +let overlayContext = overlayCanvas.getContext('2d'); + +let btn1Object = document.getElementById('previous-page-btn'); +let btn2Object = document.getElementById('next-page-btn'); +overlayCanvas.width = pdfCanvas.width; +overlayCanvas.height = pdfCanvas.height; + +let fileInput = document.getElementById('fileInput-input'); + +let file; + +let pdfDoc = null; +let pageId = document.getElementById('pageId'); +let currentPage = 1; +let totalPages = 0; + +let startX = 0; +let startY = 0; +let rectWidth = 0; +let rectHeight = 0; + +let timeId = null; // timeout id for resizing canvases event + +btn1Object.addEventListener('click', function (e) { + if (currentPage !== 1) { + currentPage = currentPage - 1; + pageId.value = currentPage; + + if (file.type === 'application/pdf') { + let reader = new FileReader(); + reader.onload = function (ev) { + let typedArray = new Uint8Array(reader.result); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + pdfjsLib.getDocument(typedArray).promise.then(function (pdf) { + pdfDoc = pdf; + totalPages = pdf.numPages; + renderPage(currentPage); + }); + }; + reader.readAsArrayBuffer(file); + } + } +}); + +btn2Object.addEventListener('click', function (e) { + if (currentPage !== totalPages) { + currentPage = currentPage + 1; + pageId.value = currentPage; + + if (file.type === 'application/pdf') { + let reader = new FileReader(); + reader.onload = function (ev) { + let typedArray = new Uint8Array(reader.result); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + pdfjsLib.getDocument(typedArray).promise.then(function (pdf) { + pdfDoc = pdf; + totalPages = pdf.numPages; + renderPage(currentPage); + }); + }; + reader.readAsArrayBuffer(file); + } + } +}); + +function renderPageFromFile(file) { + if (file.type === 'application/pdf') { + let reader = new FileReader(); + reader.onload = function (ev) { + let typedArray = new Uint8Array(reader.result); + pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; + pdfjsLib.getDocument(typedArray).promise.then(function (pdf) { + pdfDoc = pdf; + totalPages = pdf.numPages; + renderPage(currentPage); + }); + pageId.value = currentPage; + }; + reader.readAsArrayBuffer(file); + document.getElementById('pagination-button-container').style.display = 'flex'; + document.getElementById('instruction-text').style.display = 'block'; + } +} + +window.addEventListener('resize', function () { + clearTimeout(timeId); + timeId = setTimeout(function () { + if (fileInput.files.length == 0) return; + let canvasesContainer = document.getElementById('canvasesContainer'); + let containerRect = canvasesContainer.getBoundingClientRect(); + + context.clearRect(0, 0, pdfCanvas.width, pdfCanvas.height); + + overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); + + pdfCanvas.width = containerRect.width; + pdfCanvas.height = containerRect.height; + + overlayCanvas.width = containerRect.width; + overlayCanvas.height = containerRect.height; + + let file = fileInput.files[0]; + renderPageFromFile(file); + }, 1000); +}); + +fileInput.addEventListener('change', function (e) { + fileInput.addEventListener('file-input-change', async (e) => { + const {allFiles} = e.detail; + if (allFiles && allFiles.length > 0) { + canvasesContainer.style.display = 'block'; // set for visual purposes + file = e.target.files[0]; + renderPageFromFile(file); + } + }); +}); + +function renderPage(pageNumber) { + pdfDoc.getPage(pageNumber).then(function (page) { + let viewport = page.getViewport({scale: 1.0}); + pdfCanvas.width = viewport.width; + pdfCanvas.height = viewport.height; + + overlayCanvas.width = viewport.width; // Match overlay canvas size with PDF canvas + overlayCanvas.height = viewport.height; + + let renderContext = {canvasContext: context, viewport: viewport}; + page.render(renderContext); + pdfCanvas.classList.add('shadow-canvas'); + }); +} diff --git a/src/main/resources/static/js/pages/sign.js b/src/main/resources/static/js/pages/sign.js index 411fabf4983..8d45c969729 100644 --- a/src/main/resources/static/js/pages/sign.js +++ b/src/main/resources/static/js/pages/sign.js @@ -52,8 +52,6 @@ function addSignatureFromPreview() { let originalFileName = ''; document.querySelector('input[name=pdf-upload]').addEventListener('change', async (event) => { const fileInput = event.target; - - // Wait for the second function to complete fileInput.addEventListener('file-input-change', async (e) => { const {allFiles} = e.detail; if (allFiles && allFiles.length > 0) { diff --git a/src/main/resources/templates/convert/pdf-to-csv.html b/src/main/resources/templates/convert/pdf-to-csv.html index b3dfc09cd4d..976837340f0 100644 --- a/src/main/resources/templates/convert/pdf-to-csv.html +++ b/src/main/resources/templates/convert/pdf-to-csv.html @@ -34,140 +34,8 @@ - + diff --git a/src/main/resources/templates/crop.html b/src/main/resources/templates/crop.html index e606fded576..5262f0f5936 100644 --- a/src/main/resources/templates/crop.html +++ b/src/main/resources/templates/crop.html @@ -32,163 +32,7 @@ - + diff --git a/src/main/resources/templates/misc/add-image.html b/src/main/resources/templates/misc/add-image.html index 947185a7383..6bca8ee7aa5 100644 --- a/src/main/resources/templates/misc/add-image.html +++ b/src/main/resources/templates/misc/add-image.html @@ -22,46 +22,9 @@
- - +
-
@@ -93,17 +56,6 @@
- diff --git a/src/main/resources/templates/misc/change-metadata.html b/src/main/resources/templates/misc/change-metadata.html index 50ba318bf99..2aaa47e9a77 100644 --- a/src/main/resources/templates/misc/change-metadata.html +++ b/src/main/resources/templates/misc/change-metadata.html @@ -85,140 +85,7 @@


- diff --git a/src/main/resources/templates/overlay-pdf.html b/src/main/resources/templates/overlay-pdf.html index e92e4cb0851..616e3343ac9 100644 --- a/src/main/resources/templates/overlay-pdf.html +++ b/src/main/resources/templates/overlay-pdf.html @@ -2,6 +2,7 @@ + From bb3f076e6dbb58e82f28d21d580450295e185912 Mon Sep 17 00:00:00 2001 From: Reece Browne Date: Wed, 11 Dec 2024 16:55:27 +0000 Subject: [PATCH 12/27] Final pages fixed for decryption --- src/main/resources/templates/misc/extract-images.html | 1 + src/main/resources/templates/misc/replace-color.html | 1 + src/main/resources/templates/pipeline.html | 1 + 3 files changed, 3 insertions(+) diff --git a/src/main/resources/templates/misc/extract-images.html b/src/main/resources/templates/misc/extract-images.html index d47a72d7c36..1e6268feb7f 100644 --- a/src/main/resources/templates/misc/extract-images.html +++ b/src/main/resources/templates/misc/extract-images.html @@ -2,6 +2,7 @@ + diff --git a/src/main/resources/templates/misc/replace-color.html b/src/main/resources/templates/misc/replace-color.html index 4defcff7258..4ab5460a948 100644 --- a/src/main/resources/templates/misc/replace-color.html +++ b/src/main/resources/templates/misc/replace-color.html @@ -4,6 +4,7 @@ + diff --git a/src/main/resources/templates/pipeline.html b/src/main/resources/templates/pipeline.html index eaa874639bf..dae05df2bb8 100644 --- a/src/main/resources/templates/pipeline.html +++ b/src/main/resources/templates/pipeline.html @@ -14,6 +14,7 @@ th:href="@{'/css/pipeline.css'}" th:if="${currentPage == 'pipeline'}" /> +