mirror of
https://github.com/alam00000/bentopdf.git
synced 2026-11-08 08:52:28 +01:00
feat(i18n): localize status messages and UI elements across various tools
This commit is contained in:
1 parent
651793bffa
commit
63707f0a18
19 files changed
+530
-124
No files matched your search
+21
-14
@@ -10,6 +10,7 @@ import {
|
||||
showWasmRequiredDialog,
|
||||
WasmProvider,
|
||||
} from '../utils/wasm-provider.js';
|
||||
import { t } from '../i18n/i18n';
|
||||
|
||||
const worker = new Worker(
|
||||
import.meta.env.BASE_URL + 'workers/json-to-pdf.worker.js'
|
||||
@@ -80,10 +81,12 @@ jsonFilesInput.addEventListener('change', (e) => {
|
||||
updateFileList();
|
||||
|
||||
if (selectedFiles.length === 0) {
|
||||
showStatus('Please select at least 1 JSON file', 'info');
|
||||
showStatus(t('tools:jsonToPdf.status.selectAtLeastOne'), 'info');
|
||||
} else {
|
||||
showStatus(
|
||||
`${selectedFiles.length} file(s) selected. Ready to convert!`,
|
||||
t('tools:jsonToPdf.status.selectedReady', {
|
||||
count: selectedFiles.length,
|
||||
}),
|
||||
'info'
|
||||
);
|
||||
}
|
||||
@@ -92,7 +95,7 @@ jsonFilesInput.addEventListener('change', (e) => {
|
||||
|
||||
async function convertJSONsToPDF() {
|
||||
if (selectedFiles.length === 0) {
|
||||
showStatus('Please select at least 1 JSON file', 'error');
|
||||
showStatus(t('tools:jsonToPdf.status.selectAtLeastOne'), 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -104,13 +107,13 @@ async function convertJSONsToPDF() {
|
||||
|
||||
try {
|
||||
convertBtn.disabled = true;
|
||||
showStatus('Reading files (Main Thread)...', 'info');
|
||||
showStatus(t('tools:jsonToPdf.status.readingFiles'), 'info');
|
||||
|
||||
const fileBuffers = await Promise.all(
|
||||
selectedFiles.map((file) => readFileAsArrayBuffer(file))
|
||||
);
|
||||
|
||||
showStatus('Converting JSONs to PDFs...', 'info');
|
||||
showStatus(t('tools:jsonToPdf.status.converting'), 'info');
|
||||
|
||||
worker.postMessage(
|
||||
{
|
||||
@@ -124,7 +127,9 @@ async function convertJSONsToPDF() {
|
||||
} catch (error) {
|
||||
console.error('Error reading files:', error);
|
||||
showStatus(
|
||||
`❌ Error reading files: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
t('tools:jsonToPdf.status.readError', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
}),
|
||||
'error'
|
||||
);
|
||||
convertBtn.disabled = false;
|
||||
@@ -141,7 +146,7 @@ worker.onmessage = async (e: MessageEvent) => {
|
||||
}>;
|
||||
|
||||
try {
|
||||
showStatus('Creating ZIP file...', 'info');
|
||||
showStatus(t('tools:jsonToPdf.status.creatingZip'), 'info');
|
||||
|
||||
const zip = new JSZip();
|
||||
pdfFiles.forEach(({ name, data }) => {
|
||||
@@ -157,10 +162,7 @@ worker.onmessage = async (e: MessageEvent) => {
|
||||
a.download = 'jsons-to-pdf.zip';
|
||||
downloadFile(zipBlob, 'jsons-to-pdf.zip');
|
||||
|
||||
showStatus(
|
||||
'✅ JSONs converted to PDF successfully! ZIP download started.',
|
||||
'success'
|
||||
);
|
||||
showStatus(t('tools:jsonToPdf.status.success'), 'success');
|
||||
|
||||
selectedFiles = [];
|
||||
jsonFilesInput.value = '';
|
||||
@@ -174,14 +176,19 @@ worker.onmessage = async (e: MessageEvent) => {
|
||||
} catch (error) {
|
||||
console.error('Error creating ZIP:', error);
|
||||
showStatus(
|
||||
`❌ Error creating ZIP: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
t('tools:jsonToPdf.status.zipError', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
}),
|
||||
'error'
|
||||
);
|
||||
}
|
||||
} else if (e.data.status === 'error') {
|
||||
const errorMessage = e.data.message || 'Unknown error occurred in worker.';
|
||||
console.error('Worker Error:', errorMessage);
|
||||
showStatus(`❌ Worker Error: ${errorMessage}`, 'error');
|
||||
showStatus(
|
||||
t('tools:jsonToPdf.status.workerError', { message: errorMessage }),
|
||||
'error'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -194,5 +201,5 @@ if (backToToolsBtn) {
|
||||
convertBtn.addEventListener('click', convertJSONsToPDF);
|
||||
|
||||
// Initialize
|
||||
showStatus('Select JSON files to get started', 'info');
|
||||
showStatus(t('tools:jsonToPdf.status.getStarted'), 'info');
|
||||
initializeGlobalShortcuts();
|
||||
+22
-15
@@ -12,6 +12,7 @@ import {
|
||||
WasmProvider,
|
||||
} from '../utils/wasm-provider.js';
|
||||
import { batchDecryptIfNeeded } from '../utils/password-prompt.js';
|
||||
import { t } from '../i18n/i18n';
|
||||
|
||||
const worker = new Worker(
|
||||
import.meta.env.BASE_URL + 'workers/pdf-to-json.worker.js'
|
||||
@@ -82,10 +83,12 @@ pdfFilesInput.addEventListener('change', (e) => {
|
||||
updateFileList();
|
||||
|
||||
if (selectedFiles.length === 0) {
|
||||
showStatus('Please select at least 1 PDF file', 'info');
|
||||
showStatus(t('tools:pdfToJson.status.selectAtLeastOne'), 'info');
|
||||
} else {
|
||||
showStatus(
|
||||
`${selectedFiles.length} file(s) selected. Ready to convert!`,
|
||||
t('tools:pdfToJson.status.selectedReady', {
|
||||
count: selectedFiles.length,
|
||||
}),
|
||||
'info'
|
||||
);
|
||||
}
|
||||
@@ -94,7 +97,7 @@ pdfFilesInput.addEventListener('change', (e) => {
|
||||
|
||||
async function convertPDFsToJSON() {
|
||||
if (selectedFiles.length === 0) {
|
||||
showStatus('Please select at least 1 PDF file', 'error');
|
||||
showStatus(t('tools:pdfToJson.status.selectAtLeastOne'), 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -106,17 +109,17 @@ async function convertPDFsToJSON() {
|
||||
|
||||
try {
|
||||
convertBtn.disabled = true;
|
||||
showStatus('Checking for encrypted PDFs...', 'info');
|
||||
showStatus(t('tools:pdfToJson.status.checkingEncrypted'), 'info');
|
||||
|
||||
selectedFiles = await batchDecryptIfNeeded(selectedFiles);
|
||||
|
||||
showStatus('Reading files (Main Thread)...', 'info');
|
||||
showStatus(t('tools:pdfToJson.status.readingFiles'), 'info');
|
||||
|
||||
const fileBuffers = await Promise.all(
|
||||
selectedFiles.map((file) => readFileAsArrayBuffer(file))
|
||||
);
|
||||
|
||||
showStatus('Converting PDFs to JSON..', 'info');
|
||||
showStatus(t('tools:pdfToJson.status.converting'), 'info');
|
||||
|
||||
worker.postMessage(
|
||||
{
|
||||
@@ -130,7 +133,9 @@ async function convertPDFsToJSON() {
|
||||
} catch (error) {
|
||||
console.error('Error reading files:', error);
|
||||
showStatus(
|
||||
`❌ Error reading files: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
t('tools:pdfToJson.status.readError', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
}),
|
||||
'error'
|
||||
);
|
||||
convertBtn.disabled = false;
|
||||
@@ -147,7 +152,7 @@ worker.onmessage = async (e: MessageEvent) => {
|
||||
}>;
|
||||
|
||||
try {
|
||||
showStatus('Creating ZIP file...', 'info');
|
||||
showStatus(t('tools:pdfToJson.status.creatingZip'), 'info');
|
||||
|
||||
const zip = new JSZip();
|
||||
const usedNames = new Set<string>();
|
||||
@@ -161,10 +166,7 @@ worker.onmessage = async (e: MessageEvent) => {
|
||||
const zipBlob = await zip.generateAsync({ type: 'blob' });
|
||||
downloadFile(zipBlob, 'pdfs-to-json.zip');
|
||||
|
||||
showStatus(
|
||||
'✅ PDFs converted to JSON successfully! ZIP download started.',
|
||||
'success'
|
||||
);
|
||||
showStatus(t('tools:pdfToJson.status.success'), 'success');
|
||||
|
||||
selectedFiles = [];
|
||||
pdfFilesInput.value = '';
|
||||
@@ -178,14 +180,19 @@ worker.onmessage = async (e: MessageEvent) => {
|
||||
} catch (error) {
|
||||
console.error('Error creating ZIP:', error);
|
||||
showStatus(
|
||||
`❌ Error creating ZIP: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
t('tools:pdfToJson.status.zipError', {
|
||||
message: error instanceof Error ? error.message : 'Unknown error',
|
||||
}),
|
||||
'error'
|
||||
);
|
||||
}
|
||||
} else if (e.data.status === 'error') {
|
||||
const errorMessage = e.data.message || 'Unknown error occurred in worker.';
|
||||
console.error('Worker Error:', errorMessage);
|
||||
showStatus(`❌ Worker Error: ${errorMessage}`, 'error');
|
||||
showStatus(
|
||||
t('tools:pdfToJson.status.workerError', { message: errorMessage }),
|
||||
'error'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -197,5 +204,5 @@ if (backToToolsBtn) {
|
||||
|
||||
convertBtn.addEventListener('click', convertPDFsToJSON);
|
||||
|
||||
showStatus('Select PDF files to get started', 'info');
|
||||
showStatus(t('tools:pdfToJson.status.getStarted'), 'info');
|
||||
initializeGlobalShortcuts();
|
||||
@@ -201,7 +201,7 @@
|
||||
id="save-stamped-btn"
|
||||
class="hidden btn-gradient w-full mt-6 flex items-center justify-center gap-2"
|
||||
>
|
||||
<span>Save Stamped PDF</span>
|
||||
<span data-i18n="tools:addStamps.saveButton">Save Stamped PDF</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+20
-5
@@ -169,7 +169,10 @@
|
||||
|
||||
<!-- Import Bookmarks Section -->
|
||||
<div class="mt-8 pt-6 border-t border-gray-700">
|
||||
<h3 class="text-sm font-semibold text-gray-300 mb-4">
|
||||
<h3
|
||||
class="text-sm font-semibold text-gray-300 mb-4"
|
||||
data-i18n="tools:editBookmarks.importSectionTitle"
|
||||
>
|
||||
Or Import Bookmarks
|
||||
</h3>
|
||||
|
||||
@@ -184,8 +187,14 @@
|
||||
<div class="flex flex-col items-center justify-center pt-4 pb-4">
|
||||
<i data-lucide="sheet" class="w-8 h-8 mb-2 text-gray-400"></i>
|
||||
<p class="text-xs text-gray-400">
|
||||
<span class="font-semibold">Click to upload CSV</span> or drag
|
||||
here
|
||||
<span
|
||||
class="font-semibold"
|
||||
data-i18n="tools:editBookmarks.uploadCsvAction"
|
||||
>Click to upload CSV</span
|
||||
>
|
||||
<span data-i18n="tools:editBookmarks.orDragHere"
|
||||
>or drag here</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<input
|
||||
@@ -206,8 +215,14 @@
|
||||
<div class="flex flex-col items-center justify-center pt-4 pb-4">
|
||||
<i data-lucide="braces" class="w-8 h-8 mb-2 text-gray-400"></i>
|
||||
<p class="text-xs text-gray-400">
|
||||
<span class="font-semibold">Click to upload JSON</span> or
|
||||
drag here
|
||||
<span
|
||||
class="font-semibold"
|
||||
data-i18n="tools:editBookmarks.uploadJsonAction"
|
||||
>Click to upload JSON</span
|
||||
>
|
||||
<span data-i18n="tools:editBookmarks.orDragHere"
|
||||
>or drag here</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<input
|
||||
|
||||
@@ -601,8 +601,18 @@
|
||||
class="flex flex-col items-center justify-center"
|
||||
>
|
||||
<i data-lucide="file-text" class="w-8 h-8 mb-2 text-gray-400"></i>
|
||||
<p class="text-sm text-gray-400">First PDF</p>
|
||||
<p class="text-xs text-gray-500">Click or drop</p>
|
||||
<p
|
||||
class="text-sm text-gray-400"
|
||||
data-i18n="tools:comparePdfs.firstPdf"
|
||||
>
|
||||
First PDF
|
||||
</p>
|
||||
<p
|
||||
class="text-xs text-gray-500"
|
||||
data-i18n="tools:comparePdfs.clickOrDrop"
|
||||
>
|
||||
Click or drop
|
||||
</p>
|
||||
</div>
|
||||
<input
|
||||
id="file-input-1"
|
||||
@@ -620,8 +630,18 @@
|
||||
class="flex flex-col items-center justify-center"
|
||||
>
|
||||
<i data-lucide="file-text" class="w-8 h-8 mb-2 text-gray-400"></i>
|
||||
<p class="text-sm text-gray-400">Second PDF</p>
|
||||
<p class="text-xs text-gray-500">Click or drop</p>
|
||||
<p
|
||||
class="text-sm text-gray-400"
|
||||
data-i18n="tools:comparePdfs.secondPdf"
|
||||
>
|
||||
Second PDF
|
||||
</p>
|
||||
<p
|
||||
class="text-xs text-gray-500"
|
||||
data-i18n="tools:comparePdfs.clickOrDrop"
|
||||
>
|
||||
Click or drop
|
||||
</p>
|
||||
</div>
|
||||
<input
|
||||
id="file-input-2"
|
||||
|
||||
@@ -137,10 +137,16 @@
|
||||
class="w-5 h-5 text-blue-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<div class="text-sm">
|
||||
<p class="text-blue-300 font-medium">
|
||||
<p
|
||||
class="text-blue-300 font-medium"
|
||||
data-i18n="tools:digitalSignPdf.internetRequiredTitle"
|
||||
>
|
||||
Internet connection required
|
||||
</p>
|
||||
<p class="text-blue-400/80 mt-1">
|
||||
<p
|
||||
class="text-blue-400/80 mt-1"
|
||||
data-i18n="tools:digitalSignPdf.internetRequiredDescription"
|
||||
>
|
||||
Signing may need to fetch certificate chain information from your
|
||||
certificate issuer's server to validate the signature.
|
||||
</p>
|
||||
|
||||
@@ -167,7 +167,11 @@
|
||||
<div class="w-full border-t border-gray-600"></div>
|
||||
</div>
|
||||
<div class="relative flex justify-center text-sm">
|
||||
<span class="px-4 bg-gray-800 text-gray-400 font-medium">OR</span>
|
||||
<span
|
||||
class="px-4 bg-gray-800 text-gray-400 font-medium"
|
||||
data-i18n="tools:createPdfForm.orSeparator"
|
||||
>OR</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -177,7 +181,11 @@
|
||||
class="w-full bg-gray-700 hover:bg-gray-600 text-white p-4 rounded-lg flex items-center justify-center gap-3 transition-colors"
|
||||
>
|
||||
<i data-lucide="file-plus" class="w-5 h-5"></i>
|
||||
<span class="font-semibold">Create Blank PDF</span>
|
||||
<span
|
||||
class="font-semibold"
|
||||
data-i18n="tools:createPdfForm.createBlankPdf"
|
||||
>Create Blank PDF</span
|
||||
>
|
||||
</button>
|
||||
|
||||
<div id="pageSizeSelector" class="mt-4 hidden">
|
||||
|
||||
@@ -122,7 +122,10 @@
|
||||
>
|
||||
PDF Form Filler
|
||||
</h1>
|
||||
<p class="text-gray-400 mb-4">
|
||||
<p
|
||||
class="text-gray-400 mb-4"
|
||||
data-i18n="tools:pdfFormFiller.uploadHint"
|
||||
>
|
||||
Upload a PDF with form fields. Fill them directly in the viewer below,
|
||||
then click the button to save and download the filled form. Also
|
||||
supports XFA forms.
|
||||
@@ -132,12 +135,16 @@
|
||||
class="mb-6 p-3 bg-blue-900/20 border border-blue-700/50 rounded-lg"
|
||||
>
|
||||
<p class="text-sm text-blue-300">
|
||||
<strong>Note on XFA Forms:</strong> XFA (XML Forms Architecture) is
|
||||
a legacy format that's only supported by certain PDF viewers like
|
||||
BentoPDF and Firefox. If you open an XFA PDF in other software and
|
||||
see blank pages or no form fields, it means that viewer doesn't
|
||||
support XFA. To view and fill XFA forms properly, use Firefox or
|
||||
BentoPDF's Form Filler.
|
||||
<strong data-i18n="tools:pdfFormFiller.xfaNoteTitle"
|
||||
>Note on XFA Forms:</strong
|
||||
>
|
||||
<span data-i18n="tools:pdfFormFiller.xfaNoteDescription"
|
||||
>XFA (XML Forms Architecture) is a legacy format that's only
|
||||
supported by certain PDF viewers like BentoPDF and Firefox. If you
|
||||
open an XFA PDF in other software and see blank pages or no form
|
||||
fields, it means that viewer doesn't support XFA. To view and fill
|
||||
XFA forms properly, use Firefox or BentoPDF's Form Filler.</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -121,9 +121,12 @@
|
||||
class="bg-yellow-900/30 border border-yellow-700 rounded-lg p-3 mb-6"
|
||||
>
|
||||
<p class="text-yellow-200 text-sm">
|
||||
<strong>Note:</strong> Only JSON files created by the PDF-to-JSON
|
||||
converter tool are supported. Standard JSON files from other tools
|
||||
will not work.
|
||||
<strong data-i18n="tools:jsonToPdf.noteLabel">Note:</strong>
|
||||
<span data-i18n="tools:jsonToPdf.noteText"
|
||||
>Only JSON files created by the PDF-to-JSON converter tool are
|
||||
supported. Standard JSON files from other tools will not
|
||||
work.</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -142,7 +145,12 @@
|
||||
>
|
||||
<span data-i18n="upload.orDragAndDrop">or drag and drop</span>
|
||||
</p>
|
||||
<p class="text-xs text-gray-500">Multiple JSON files</p>
|
||||
<p
|
||||
class="text-xs text-gray-500"
|
||||
data-i18n="tools:jsonToPdf.acceptedFormats"
|
||||
>
|
||||
Multiple JSON files
|
||||
</p>
|
||||
<p
|
||||
class="text-xs text-gray-500"
|
||||
data-i18n="upload.filesNeverLeave"
|
||||
@@ -162,7 +170,12 @@
|
||||
<!-- File Display Area -->
|
||||
<div id="fileList" class="mt-4 hidden"></div>
|
||||
|
||||
<button id="convertBtn" disabled class="btn-gradient w-full mt-6">
|
||||
<button
|
||||
id="convertBtn"
|
||||
disabled
|
||||
class="btn-gradient w-full mt-6"
|
||||
data-i18n="tools:convertToPdf"
|
||||
>
|
||||
Convert to PDF
|
||||
</button>
|
||||
</div>
|
||||
|
||||
+41
-12
@@ -132,29 +132,58 @@
|
||||
<!-- How it works info box -->
|
||||
<div class="p-3 bg-gray-900 rounded-lg border border-gray-700 mb-6">
|
||||
<p class="text-sm text-gray-300">
|
||||
<strong class="text-white">How it works:</strong>
|
||||
<strong class="text-white" data-i18n="tools:ocrPdf.howItWorksTitle"
|
||||
>How it works:</strong
|
||||
>
|
||||
</p>
|
||||
<ul
|
||||
class="list-disc list-inside text-xs text-gray-400 mt-1 space-y-1"
|
||||
>
|
||||
<li>
|
||||
<strong class="text-white">Extract Text:</strong> Uses Tesseract
|
||||
OCR to recognize text from scanned images or PDFs.
|
||||
<strong
|
||||
class="text-white"
|
||||
data-i18n="tools:ocrPdf.extractTextLabel"
|
||||
>Extract Text:</strong
|
||||
>
|
||||
<span data-i18n="tools:ocrPdf.extractTextDescription"
|
||||
>Uses Tesseract OCR to recognize text from scanned images or
|
||||
PDFs.</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<strong class="text-white">Searchable Output:</strong> Creates a
|
||||
new PDF with an invisible text layer, making your document fully
|
||||
searchable while preserving the original appearance.
|
||||
<strong
|
||||
class="text-white"
|
||||
data-i18n="tools:ocrPdf.searchableOutputLabel"
|
||||
>Searchable Output:</strong
|
||||
>
|
||||
<span data-i18n="tools:ocrPdf.searchableOutputDescription"
|
||||
>Creates a new PDF with an invisible text layer, making your
|
||||
document fully searchable while preserving the original
|
||||
appearance.</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<strong class="text-white">Character Filtering:</strong> Use
|
||||
whitelists to filter out unwanted characters and improve accuracy
|
||||
for specific document types (invoices, forms, etc.).
|
||||
<strong
|
||||
class="text-white"
|
||||
data-i18n="tools:ocrPdf.characterFilteringLabel"
|
||||
>Character Filtering:</strong
|
||||
>
|
||||
<span data-i18n="tools:ocrPdf.characterFilteringDescription"
|
||||
>Use whitelists to filter out unwanted characters and improve
|
||||
accuracy for specific document types (invoices, forms,
|
||||
etc.).</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<strong class="text-white">Multi-language Support:</strong> Select
|
||||
multiple languages for documents containing mixed language
|
||||
content.
|
||||
<strong
|
||||
class="text-white"
|
||||
data-i18n="tools:ocrPdf.multiLanguageSupportLabel"
|
||||
>Multi-language Support:</strong
|
||||
>
|
||||
<span data-i18n="tools:ocrPdf.multiLanguageSupportDescription"
|
||||
>Select multiple languages for documents containing mixed
|
||||
language content.</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -197,7 +197,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="process-btn" class="hidden btn-gradient w-full mt-6">
|
||||
<button
|
||||
id="process-btn"
|
||||
class="hidden btn-gradient w-full mt-6"
|
||||
data-i18n="tools:duplicateOrganize.saveChanges"
|
||||
>
|
||||
Save Changes
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -158,7 +158,12 @@
|
||||
<!-- File Display Area -->
|
||||
<div id="fileList" class="mt-4 hidden"></div>
|
||||
|
||||
<button id="convertBtn" disabled class="btn-gradient w-full mt-6">
|
||||
<button
|
||||
id="convertBtn"
|
||||
disabled
|
||||
class="btn-gradient w-full mt-6"
|
||||
data-i18n="tools:pdfToJson.convertButton"
|
||||
>
|
||||
Convert to JSON
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -130,14 +130,18 @@
|
||||
class="bg-amber-900/30 border border-amber-700/50 rounded-lg p-3 mb-6"
|
||||
>
|
||||
<p class="text-amber-200 text-sm">
|
||||
<strong>Note:</strong> This tool works ONLY with digitally created
|
||||
PDFs. For scanned documents or image-based PDFs, use our
|
||||
<strong data-i18n="tools:pdfToText.noteLabel">Note:</strong>
|
||||
<span data-i18n="tools:pdfToText.notePrefix"
|
||||
>This tool works ONLY with digitally created PDFs. For scanned
|
||||
documents or image-based PDFs, use our</span
|
||||
>
|
||||
<a
|
||||
href="ocr-pdf.html"
|
||||
class="text-indigo-400 hover:text-indigo-300 underline"
|
||||
data-i18n="tools:ocrPdf.name"
|
||||
>OCR PDF tool</a
|
||||
>
|
||||
instead.
|
||||
<span data-i18n="tools:pdfToText.noteSuffix">instead.</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -174,7 +174,11 @@
|
||||
<!-- File Display Area -->
|
||||
<div id="file-display-area" class="mt-4 space-y-2"></div>
|
||||
|
||||
<button id="process-btn" class="btn-gradient w-full mt-6 hidden">
|
||||
<button
|
||||
id="process-btn"
|
||||
class="btn-gradient w-full mt-6 hidden"
|
||||
data-i18n="tools:repairPdf.name"
|
||||
>
|
||||
Repair PDF
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -175,7 +175,10 @@
|
||||
<!-- Options Section -->
|
||||
<div class="mt-6 space-y-4">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-300 mb-2">
|
||||
<label
|
||||
class="block text-sm font-medium text-gray-300 mb-2"
|
||||
data-i18n="tools:tableOfContents.titleLabel"
|
||||
>
|
||||
TOC Title
|
||||
</label>
|
||||
<input
|
||||
@@ -184,11 +187,15 @@
|
||||
value="Table of Contents"
|
||||
class="w-full px-4 py-2 bg-gray-800 border border-gray-600 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Table of Contents"
|
||||
data-i18n-placeholder="tools:tableOfContents.name"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-300 mb-2">
|
||||
<label
|
||||
class="block text-sm font-medium text-gray-300 mb-2"
|
||||
data-i18n="tools:tableOfContents.fontSize"
|
||||
>
|
||||
Font Size
|
||||
</label>
|
||||
<select
|
||||
@@ -215,7 +222,10 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-300 mb-2">
|
||||
<label
|
||||
class="block text-sm font-medium text-gray-300 mb-2"
|
||||
data-i18n="tools:tableOfContents.fontFamily"
|
||||
>
|
||||
Font Family
|
||||
</label>
|
||||
<select
|
||||
@@ -244,7 +254,11 @@
|
||||
checked
|
||||
class="w-4 h-4 accent-blue-500"
|
||||
/>
|
||||
<label for="add-bookmark" class="text-sm text-gray-300">
|
||||
<label
|
||||
for="add-bookmark"
|
||||
class="text-sm text-gray-300"
|
||||
data-i18n="tools:tableOfContents.addBookmark"
|
||||
>
|
||||
Add bookmark for TOC page
|
||||
</label>
|
||||
</div>
|
||||
@@ -252,7 +266,11 @@
|
||||
|
||||
<!-- Generate Button -->
|
||||
<button id="generate-btn" disabled class="btn-gradient w-full mt-6">
|
||||
<span id="generate-btn-text">Generate Table of Contents</span>
|
||||
<span
|
||||
id="generate-btn-text"
|
||||
data-i18n="tools:tableOfContents.generateButton"
|
||||
>Generate Table of Contents</span
|
||||
>
|
||||
</button>
|
||||
|
||||
<!-- Status Message -->
|
||||
|
||||
@@ -134,12 +134,14 @@
|
||||
<button
|
||||
id="txt-mode-upload-btn"
|
||||
class="flex-1 btn bg-indigo-600 text-white font-semibold py-2 rounded-md"
|
||||
data-i18n="tools:textToPdf.uploadFiles"
|
||||
>
|
||||
Upload Files
|
||||
</button>
|
||||
<button
|
||||
id="txt-mode-text-btn"
|
||||
class="flex-1 btn bg-gray-700 text-gray-300 font-semibold py-2 rounded-md"
|
||||
data-i18n="tools:textToPdf.typeText"
|
||||
>
|
||||
Type Text
|
||||
</button>
|
||||
@@ -162,7 +164,12 @@
|
||||
>
|
||||
<span data-i18n="upload.orDragAndDrop">or drag and drop</span>
|
||||
</p>
|
||||
<p class="text-xs text-gray-500">Text files (.txt)</p>
|
||||
<p
|
||||
class="text-xs text-gray-500"
|
||||
data-i18n="tools:textToPdf.acceptedFormats"
|
||||
>
|
||||
Text files (.txt)
|
||||
</p>
|
||||
<p
|
||||
class="text-xs text-gray-500"
|
||||
data-i18n="upload.filesNeverLeave"
|
||||
@@ -216,6 +223,7 @@
|
||||
<label
|
||||
for="font-family"
|
||||
class="block mb-2 text-sm font-medium text-gray-300"
|
||||
data-i18n="tools:textToPdf.fontFamily"
|
||||
>Font Family</label
|
||||
>
|
||||
<select
|
||||
@@ -232,6 +240,7 @@
|
||||
<label
|
||||
for="font-size"
|
||||
class="block mb-2 text-sm font-medium text-gray-300"
|
||||
data-i18n="tools:textToPdf.fontSize"
|
||||
>Font Size</label
|
||||
>
|
||||
<input
|
||||
@@ -247,6 +256,7 @@
|
||||
<label
|
||||
for="text-color"
|
||||
class="block mb-2 text-sm font-medium text-gray-300"
|
||||
data-i18n="tools:textToPdf.textColor"
|
||||
>Text Color</label
|
||||
>
|
||||
<input type="color" id="text-color" value="#000000" />
|
||||
@@ -255,6 +265,7 @@
|
||||
<label
|
||||
for="page-size"
|
||||
class="block mb-2 text-sm font-medium text-gray-300"
|
||||
data-i18n="tools:textToPdf.pageSize"
|
||||
>Page Size</label
|
||||
>
|
||||
<select
|
||||
@@ -317,7 +328,11 @@
|
||||
and text direction is adjusted.
|
||||
</p>
|
||||
|
||||
<button id="process-btn" class="btn-gradient w-full mt-6">
|
||||
<button
|
||||
id="process-btn"
|
||||
class="btn-gradient w-full mt-6"
|
||||
data-i18n="tools:textToPdf.createButton"
|
||||
>
|
||||
Create PDF
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -79,10 +79,16 @@
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<h1 class="text-2xl font-bold text-white mb-2">
|
||||
<h1
|
||||
class="text-2xl font-bold text-white mb-2"
|
||||
data-i18n="tools:wasmSettings.title"
|
||||
>
|
||||
Advanced Features Settings
|
||||
</h1>
|
||||
<p class="text-gray-400 mb-6">
|
||||
<p
|
||||
class="text-gray-400 mb-6"
|
||||
data-i18n="tools:wasmSettings.description"
|
||||
>
|
||||
Configure external processing modules to enable advanced PDF features.
|
||||
These modules are optional and licensed separately.
|
||||
</p>
|
||||
@@ -98,10 +104,15 @@
|
||||
></i>
|
||||
<div>
|
||||
<p class="text-green-200 text-sm">
|
||||
<strong>Pre-configured and ready to use.</strong> Advanced
|
||||
processing modules are loaded automatically from CDN. You can
|
||||
override the URLs below if you need to use a custom source
|
||||
(e.g., for air-gapped or self-hosted deployments).
|
||||
<strong data-i18n="tools:wasmSettings.preconfiguredTitle"
|
||||
>Pre-configured and ready to use.</strong
|
||||
>
|
||||
<span data-i18n="tools:wasmSettings.preconfiguredDescription"
|
||||
>Advanced processing modules are loaded automatically from
|
||||
CDN. You can override the URLs below if you need to use a
|
||||
custom source (e.g., for air-gapped or self-hosted
|
||||
deployments).</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -113,16 +124,25 @@
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div>
|
||||
<h3 class="font-semibold text-white">PyMuPDF</h3>
|
||||
<p class="text-xs text-gray-400">Document Processing Engine</p>
|
||||
<p
|
||||
class="text-xs text-gray-400"
|
||||
data-i18n="tools:wasmSettings.pymupdfSubtitle"
|
||||
>
|
||||
Document Processing Engine
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
id="pymupdf-status"
|
||||
class="text-xs px-2 py-1 rounded-full bg-gray-600 text-gray-300"
|
||||
data-i18n="tools:wasmSettings.notConfigured"
|
||||
>
|
||||
Not Configured
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-400 mb-3">
|
||||
<p
|
||||
class="text-sm text-gray-400 mb-3"
|
||||
data-i18n="tools:wasmSettings.pymupdfFeatures"
|
||||
>
|
||||
Enables: PDF to Text, Markdown, SVG, DOCX, Excel • Extract
|
||||
Images/Tables • Format Conversion
|
||||
</p>
|
||||
@@ -136,12 +156,17 @@
|
||||
<button
|
||||
id="pymupdf-test"
|
||||
class="px-4 py-2 bg-gray-600 hover:bg-gray-500 text-white rounded-lg text-sm font-medium transition-colors"
|
||||
data-i18n="tools:wasmSettings.testButton"
|
||||
>
|
||||
Test
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 mt-2">
|
||||
<span class="text-xs text-gray-500">Recommended:</span>
|
||||
<span
|
||||
class="text-xs text-gray-500"
|
||||
data-i18n="tools:wasmSettings.recommendedLabel"
|
||||
>Recommended:</span
|
||||
>
|
||||
<code
|
||||
class="text-xs text-indigo-400 bg-gray-800 px-2 py-1 rounded flex-1 truncate"
|
||||
>https://cdn.jsdelivr.net/npm/@bentopdf/pymupdf-wasm@0.11.16/</code
|
||||
@@ -150,6 +175,7 @@
|
||||
data-copy="https://cdn.jsdelivr.net/npm/@bentopdf/pymupdf-wasm@0.11.16/"
|
||||
class="copy-btn p-1.5 bg-gray-600 hover:bg-gray-500 rounded text-gray-300 hover:text-white transition-colors"
|
||||
title="Copy to clipboard"
|
||||
data-i18n-title="tools:wasmSettings.copyTitle"
|
||||
>
|
||||
<i data-lucide="copy" class="w-3.5 h-3.5"></i>
|
||||
</button>
|
||||
@@ -161,16 +187,25 @@
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div>
|
||||
<h3 class="font-semibold text-white">Ghostscript</h3>
|
||||
<p class="text-xs text-gray-400">PDF/A Conversion Engine</p>
|
||||
<p
|
||||
class="text-xs text-gray-400"
|
||||
data-i18n="tools:wasmSettings.ghostscriptSubtitle"
|
||||
>
|
||||
PDF/A Conversion Engine
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
id="ghostscript-status"
|
||||
class="text-xs px-2 py-1 rounded-full bg-gray-600 text-gray-300"
|
||||
data-i18n="tools:wasmSettings.notConfigured"
|
||||
>
|
||||
Not Configured
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-400 mb-3">
|
||||
<p
|
||||
class="text-sm text-gray-400 mb-3"
|
||||
data-i18n="tools:wasmSettings.ghostscriptFeatures"
|
||||
>
|
||||
Enables: PDF/A-1b, PDF/A-2b, PDF/A-3b Conversion • Font to Outline
|
||||
</p>
|
||||
<div class="flex gap-2">
|
||||
@@ -183,12 +218,17 @@
|
||||
<button
|
||||
id="ghostscript-test"
|
||||
class="px-4 py-2 bg-gray-600 hover:bg-gray-500 text-white rounded-lg text-sm font-medium transition-colors"
|
||||
data-i18n="tools:wasmSettings.testButton"
|
||||
>
|
||||
Test
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 mt-2">
|
||||
<span class="text-xs text-gray-500">Recommended:</span>
|
||||
<span
|
||||
class="text-xs text-gray-500"
|
||||
data-i18n="tools:wasmSettings.recommendedLabel"
|
||||
>Recommended:</span
|
||||
>
|
||||
<code
|
||||
class="text-xs text-indigo-400 bg-gray-800 px-2 py-1 rounded flex-1 truncate"
|
||||
>https://cdn.jsdelivr.net/npm/@bentopdf/gs-wasm/assets/</code
|
||||
@@ -197,6 +237,7 @@
|
||||
data-copy="https://cdn.jsdelivr.net/npm/@bentopdf/gs-wasm/assets/"
|
||||
class="copy-btn p-1.5 bg-gray-600 hover:bg-gray-500 rounded text-gray-300 hover:text-white transition-colors"
|
||||
title="Copy to clipboard"
|
||||
data-i18n-title="tools:wasmSettings.copyTitle"
|
||||
>
|
||||
<i data-lucide="copy" class="w-3.5 h-3.5"></i>
|
||||
</button>
|
||||
@@ -208,16 +249,25 @@
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div>
|
||||
<h3 class="font-semibold text-white">CoherentPDF</h3>
|
||||
<p class="text-xs text-gray-400">Bookmarks & Metadata Engine</p>
|
||||
<p
|
||||
class="text-xs text-gray-400"
|
||||
data-i18n="tools:wasmSettings.cpdfSubtitle"
|
||||
>
|
||||
Bookmarks & Metadata Engine
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
id="cpdf-status"
|
||||
class="text-xs px-2 py-1 rounded-full bg-gray-600 text-gray-300"
|
||||
data-i18n="tools:wasmSettings.notConfigured"
|
||||
>
|
||||
Not Configured
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-400 mb-3">
|
||||
<p
|
||||
class="text-sm text-gray-400 mb-3"
|
||||
data-i18n="tools:wasmSettings.cpdfFeatures"
|
||||
>
|
||||
Enables: Split by Bookmarks • Edit Bookmarks • PDF Metadata
|
||||
</p>
|
||||
<div class="flex gap-2">
|
||||
@@ -230,12 +280,17 @@
|
||||
<button
|
||||
id="cpdf-test"
|
||||
class="px-4 py-2 bg-gray-600 hover:bg-gray-500 text-white rounded-lg text-sm font-medium transition-colors"
|
||||
data-i18n="tools:wasmSettings.testButton"
|
||||
>
|
||||
Test
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 mt-2">
|
||||
<span class="text-xs text-gray-500">Recommended:</span>
|
||||
<span
|
||||
class="text-xs text-gray-500"
|
||||
data-i18n="tools:wasmSettings.recommendedLabel"
|
||||
>Recommended:</span
|
||||
>
|
||||
<code
|
||||
class="text-xs text-indigo-400 bg-gray-800 px-2 py-1 rounded flex-1 truncate"
|
||||
>https://cdn.jsdelivr.net/npm/coherentpdf/dist/</code
|
||||
@@ -244,6 +299,7 @@
|
||||
data-copy="https://cdn.jsdelivr.net/npm/coherentpdf/dist/"
|
||||
class="copy-btn p-1.5 bg-gray-600 hover:bg-gray-500 rounded text-gray-300 hover:text-white transition-colors"
|
||||
title="Copy to clipboard"
|
||||
data-i18n-title="tools:wasmSettings.copyTitle"
|
||||
>
|
||||
<i data-lucide="copy" class="w-3.5 h-3.5"></i>
|
||||
</button>
|
||||
@@ -253,12 +309,17 @@
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="flex gap-3 mt-6">
|
||||
<button id="save-btn" class="btn-gradient flex-1">
|
||||
<button
|
||||
id="save-btn"
|
||||
class="btn-gradient flex-1"
|
||||
data-i18n="tools:wasmSettings.saveConfiguration"
|
||||
>
|
||||
Save Configuration
|
||||
</button>
|
||||
<button
|
||||
id="clear-btn"
|
||||
class="px-6 py-2.5 bg-red-600/20 hover:bg-red-600/30 text-red-400 rounded-lg font-medium transition-colors border border-red-600/50"
|
||||
data-i18n="tools:wasmSettings.resetDefaults"
|
||||
>
|
||||
Reset to Defaults
|
||||
</button>
|
||||
@@ -269,12 +330,19 @@
|
||||
class="mt-6 p-4 bg-gray-700/30 rounded-lg border border-gray-600/50"
|
||||
>
|
||||
<p class="text-xs text-gray-500">
|
||||
<strong class="text-gray-400">License Notice:</strong> The external
|
||||
modules (PyMuPDF, Ghostscript, CoherentPDF) are licensed under
|
||||
AGPL-3.0 or similar copyleft licenses. By configuring and using
|
||||
these modules, you agree to their respective license terms. BentoPDF
|
||||
is compatible with any Ghostscript WASM and PyMuPDF WASM
|
||||
implementation that follows the expected interface.
|
||||
<strong
|
||||
class="text-gray-400"
|
||||
data-i18n="tools:wasmSettings.licenseTitle"
|
||||
>License Notice:</strong
|
||||
>
|
||||
<span data-i18n="tools:wasmSettings.licenseDescription"
|
||||
>The external modules (PyMuPDF, Ghostscript, CoherentPDF) are
|
||||
licensed under AGPL-3.0 or similar copyleft licenses. By
|
||||
configuring and using these modules, you agree to their respective
|
||||
license terms. BentoPDF is compatible with any Ghostscript WASM
|
||||
and PyMuPDF WASM implementation that follows the expected
|
||||
interface.</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user