mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-12-29 16:16:02 +00:00
feat: add internationalization support
This commit is contained in:
@@ -1,24 +1,26 @@
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import { compressPdf } from './service';
|
||||
import { InitialValuesType, CompressionLevel } from './types';
|
||||
import ToolPdfInput from '@components/input/ToolPdfInput';
|
||||
import { GetGroupsType } from '@components/options/ToolOptions';
|
||||
import ToolFileResult from '@components/result/ToolFileResult';
|
||||
import SimpleRadio from '@components/options/SimpleRadio';
|
||||
import { CardExampleType } from '@components/examples/ToolExamples';
|
||||
import { PDFDocument } from 'pdf-lib';
|
||||
import { CompressionLevel, InitialValuesType } from './types';
|
||||
import { compressPdf } from './service';
|
||||
import SimpleRadio from '@components/options/SimpleRadio';
|
||||
import { CustomSnackBarContext } from '../../../../contexts/CustomSnackBarContext';
|
||||
import { CustomSnackBarContext } from '@contexts/CustomSnackBarContext';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const initialValues: InitialValuesType = {
|
||||
compressionLevel: 'medium'
|
||||
compressionLevel: 'low'
|
||||
};
|
||||
|
||||
const exampleCards: CardExampleType<InitialValuesType>[] = [
|
||||
{
|
||||
title: 'Low Compression',
|
||||
description: 'Slightly reduce file size with minimal quality loss',
|
||||
description: 'Minimal quality loss with slight file size reduction',
|
||||
sampleText: '',
|
||||
sampleResult: '',
|
||||
sampleOptions: {
|
||||
@@ -49,6 +51,7 @@ export default function CompressPdf({
|
||||
title,
|
||||
longDescription
|
||||
}: ToolComponentProps) {
|
||||
const { t } = useTranslation();
|
||||
const [input, setInput] = useState<File | null>(null);
|
||||
const [result, setResult] = useState<File | null>(null);
|
||||
const [resultSize, setResultSize] = useState<string>('');
|
||||
@@ -77,10 +80,7 @@ export default function CompressPdf({
|
||||
} catch (error) {
|
||||
console.error('Error getting PDF info:', error);
|
||||
setFileInfo(null);
|
||||
showSnackBar(
|
||||
'Error reading PDF file. Please make sure it is a valid PDF.',
|
||||
'error'
|
||||
);
|
||||
showSnackBar(t('pdf.compressPdf.errorReadingPdf'), 'error');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -112,9 +112,9 @@ export default function CompressPdf({
|
||||
} catch (error) {
|
||||
console.error('Error compressing PDF:', error);
|
||||
showSnackBar(
|
||||
`Failed to compress PDF: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
t('pdf.compressPdf.errorCompressingPdf', {
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
}),
|
||||
'error'
|
||||
);
|
||||
setResult(null);
|
||||
@@ -130,18 +130,18 @@ export default function CompressPdf({
|
||||
}[] = [
|
||||
{
|
||||
value: 'low',
|
||||
label: 'Low Compression',
|
||||
description: 'Slightly reduce file size with minimal quality loss'
|
||||
label: t('pdf.compressPdf.lowCompression'),
|
||||
description: t('pdf.compressPdf.lowCompressionDescription')
|
||||
},
|
||||
{
|
||||
value: 'medium',
|
||||
label: 'Medium Compression',
|
||||
description: 'Balance between file size and quality'
|
||||
label: t('pdf.compressPdf.mediumCompression'),
|
||||
description: t('pdf.compressPdf.mediumCompressionDescription')
|
||||
},
|
||||
{
|
||||
value: 'high',
|
||||
label: 'High Compression',
|
||||
description: 'Maximum file size reduction with some quality loss'
|
||||
label: t('pdf.compressPdf.highCompression'),
|
||||
description: t('pdf.compressPdf.highCompressionDescription')
|
||||
}
|
||||
];
|
||||
|
||||
@@ -157,26 +157,26 @@ export default function CompressPdf({
|
||||
value={input}
|
||||
onChange={setInput}
|
||||
accept={['application/pdf']}
|
||||
title={'Input PDF'}
|
||||
title={t('pdf.compressPdf.inputTitle')}
|
||||
/>
|
||||
}
|
||||
resultComponent={
|
||||
<ToolFileResult
|
||||
title={'Compressed PDF'}
|
||||
title={t('pdf.compressPdf.resultTitle')}
|
||||
value={result}
|
||||
extension={'pdf'}
|
||||
loading={isProcessing}
|
||||
loadingText={'Compressing PDF'}
|
||||
loadingText={t('pdf.compressPdf.compressingPdf')}
|
||||
/>
|
||||
}
|
||||
getGroups={({ values, updateField }) => [
|
||||
{
|
||||
title: 'Compression Settings',
|
||||
title: t('pdf.compressPdf.compressionSettings'),
|
||||
component: (
|
||||
<Box>
|
||||
<Box>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
Compression Level
|
||||
{t('pdf.compressPdf.compressionLevel')}
|
||||
</Typography>
|
||||
|
||||
{compressionOptions.map((option) => (
|
||||
@@ -201,14 +201,17 @@ export default function CompressPdf({
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2">
|
||||
File size: <strong>{fileInfo.size}</strong>
|
||||
{t('pdf.compressPdf.fileSize')}:{' '}
|
||||
<strong>{fileInfo.size}</strong>
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
Pages: <strong>{fileInfo.pages}</strong>
|
||||
{t('pdf.compressPdf.pages')}:{' '}
|
||||
<strong>{fileInfo.pages}</strong>
|
||||
</Typography>
|
||||
{resultSize && (
|
||||
<Typography variant="body2">
|
||||
Compressed file size: <strong>{resultSize}</strong>
|
||||
{t('pdf.compressPdf.compressedFileSize')}:{' '}
|
||||
<strong>{resultSize}</strong>
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
@@ -24,5 +24,10 @@ export const tool = defineTool('pdf', {
|
||||
],
|
||||
longDescription:
|
||||
'Compress PDF files securely in your browser using Ghostscript. Your files never leave your device, ensuring complete privacy while reducing file sizes for email sharing, uploading to websites, or saving storage space. Powered by WebAssembly technology.',
|
||||
component: lazy(() => import('./index'))
|
||||
component: lazy(() => import('./index')),
|
||||
i18n: {
|
||||
name: 'pdf.compressPdf.name',
|
||||
description: 'pdf.compressPdf.description',
|
||||
shortDescription: 'pdf.compressPdf.shortDescription'
|
||||
}
|
||||
});
|
||||
|
||||
72
src/pages/tools/pdf/i18n/en.json
Normal file
72
src/pages/tools/pdf/i18n/en.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"mergePdf": {
|
||||
"title": "Merge PDF",
|
||||
"description": "Combine multiple PDF files into a single document.",
|
||||
"inputTitle": "Input PDFs",
|
||||
"resultTitle": "Merged PDF",
|
||||
"mergingPdfs": "Merging PDFs",
|
||||
"pdfOptions": "PDF Options",
|
||||
"sortByFileName": "Sort by file name",
|
||||
"sortByFileNameDescription": "Sort PDFs alphabetically by file name",
|
||||
"sortByUploadOrder": "Sort by upload order",
|
||||
"sortByUploadOrderDescription": "Keep PDFs in the order they were uploaded",
|
||||
"toolInfo": {
|
||||
"title": "Merge PDF Files",
|
||||
"description": "This tool allows you to combine multiple PDF files into a single document. You can choose how to sort the PDFs and the tool will merge them in the specified order."
|
||||
}
|
||||
},
|
||||
"compressPdf": {
|
||||
"title": "Compress PDF",
|
||||
"description": "Reduce PDF file size while maintaining quality.",
|
||||
"inputTitle": "Input PDF",
|
||||
"resultTitle": "Compressed PDF",
|
||||
"compressingPdf": "Compressing PDF",
|
||||
"compressionOptions": "Compression Options",
|
||||
"qualityDescription": "Compression quality (1-100)",
|
||||
"qualityPlaceholder": "Quality",
|
||||
"toolInfo": {
|
||||
"title": "Compress PDF",
|
||||
"description": "This tool allows you to compress PDF files to reduce their size while maintaining acceptable quality. You can adjust the compression level to balance between file size and quality."
|
||||
}
|
||||
},
|
||||
"splitPdf": {
|
||||
"title": "Split PDF",
|
||||
"description": "Extract specific pages from a PDF document.",
|
||||
"inputTitle": "Input PDF",
|
||||
"resultTitle": "Extracted PDF",
|
||||
"extractingPages": "Extracting pages",
|
||||
"pageSelection": "Page Selection",
|
||||
"pdfPageCount": "PDF has {{count}} page{{count !== 1 ? 's' : ''}}",
|
||||
"pageRangesDescription": "Enter page numbers or ranges separated by commas (e.g., 1,3,5-7)",
|
||||
"pageRangesPlaceholder": "e.g., 1,5-8",
|
||||
"pageExtractionPreview": "{{count}} page{{count !== 1 ? 's' : ''}} will be extracted",
|
||||
"toolInfo": {
|
||||
"title": "Split PDF",
|
||||
"description": "This tool allows you to extract specific pages from a PDF document. You can specify individual pages or ranges of pages to extract."
|
||||
}
|
||||
},
|
||||
"rotatePdf": {
|
||||
"title": "Rotate PDF",
|
||||
"description": "Rotate pages in a PDF document.",
|
||||
"inputTitle": "Input PDF",
|
||||
"resultTitle": "Rotated PDF",
|
||||
"rotatingPages": "Rotating pages",
|
||||
"rotationSettings": "Rotation Settings",
|
||||
"rotationAngle": "Rotation Angle",
|
||||
"angleOptions": {
|
||||
"clockwise90": "90° Clockwise",
|
||||
"upsideDown180": "180° (Upside down)",
|
||||
"counterClockwise270": "270° (90° Counter-clockwise)"
|
||||
},
|
||||
"applyToAllPages": "Apply to all pages",
|
||||
"pdfPageCount": "PDF has {{count}} page{{count !== 1 ? 's' : ''}}",
|
||||
"pageRangesDescription": "Enter page numbers or ranges separated by commas (e.g., 1,3,5-7)",
|
||||
"pageRangesPlaceholder": "e.g., 1,5-8",
|
||||
"allPagesWillBeRotated": "All {{count}} pages will be rotated",
|
||||
"pagesWillBeRotated": "{{count}} page{{count !== 1 ? 's' : ''}} will be rotated",
|
||||
"toolInfo": {
|
||||
"title": "How to Use the Rotate PDF Tool",
|
||||
"description": "This tool allows you to rotate pages in a PDF document. You can rotate all pages or specify individual pages to rotate. Choose a rotation angle: 90° Clockwise, 180° (Upside down), or 270° (90° Counter-clockwise). To rotate specific pages, uncheck \"Apply to all pages\" and enter page numbers or ranges separated by commas (e.g., 1,3,5-7)."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,10 @@ import { mergePdf } from './service';
|
||||
import ToolMultiPdfInput, {
|
||||
MultiPdfInput
|
||||
} from '@components/input/ToolMultiplePdfInput';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function MergePdf({ title }: ToolComponentProps) {
|
||||
const { t } = useTranslation();
|
||||
const [input, setInput] = useState<MultiPdfInput[]>([]);
|
||||
const [result, setResult] = useState<File | null>(null);
|
||||
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
||||
@@ -42,24 +44,23 @@ export default function MergePdf({ title }: ToolComponentProps) {
|
||||
setInput(pdfInputs);
|
||||
}}
|
||||
accept={['application/pdf']}
|
||||
title={'Input PDF'}
|
||||
title={t('pdf.merge.inputTitle')}
|
||||
type="pdf"
|
||||
/>
|
||||
}
|
||||
getGroups={null}
|
||||
resultComponent={
|
||||
<ToolFileResult
|
||||
title={'Output merged PDF'}
|
||||
title={t('pdf.merge.resultTitle')}
|
||||
value={result}
|
||||
extension={'pdf'}
|
||||
loading={isProcessing}
|
||||
loadingText={'Extracting pages'}
|
||||
loadingText={t('pdf.merge.loadingText')}
|
||||
/>
|
||||
}
|
||||
toolInfo={{
|
||||
title: 'How to Use the Merge PDF Tool?',
|
||||
description: `This tool allows you to merge multiple PDF files into a single document.
|
||||
To use the tool, simply upload the PDF files you want to merge. The tool will then combine all pages from the input files into a single PDF document.`
|
||||
title: t('pdf.merge.toolInfo.title'),
|
||||
description: t('pdf.merge.toolInfo.description')
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -8,5 +8,10 @@ export const meta = defineTool('pdf', {
|
||||
icon: 'material-symbols-light:merge',
|
||||
component: lazy(() => import('./index')),
|
||||
keywords: ['pdf', 'merge', 'extract', 'pages', 'combine', 'document'],
|
||||
path: 'merge-pdf'
|
||||
path: 'merge-pdf',
|
||||
i18n: {
|
||||
name: 'pdf.mergePdf.name',
|
||||
description: 'pdf.mergePdf.description',
|
||||
shortDescription: 'pdf.mergePdf.shortDescription'
|
||||
}
|
||||
});
|
||||
|
||||
@@ -9,5 +9,10 @@ export const meta = defineTool('pdf', {
|
||||
icon: 'material-symbols:import-contacts',
|
||||
component: lazy(() => import('./index')),
|
||||
keywords: ['pdf', 'epub', 'convert', 'ebook'],
|
||||
path: 'pdf-to-epub'
|
||||
path: 'pdf-to-epub',
|
||||
i18n: {
|
||||
name: 'pdf.pdfToEpub.name',
|
||||
description: 'pdf.pdfToEpub.description',
|
||||
shortDescription: 'pdf.pdfToEpub.shortDescription'
|
||||
}
|
||||
});
|
||||
|
||||
@@ -23,5 +23,10 @@ export const tool = defineTool('pdf', {
|
||||
],
|
||||
longDescription:
|
||||
'Add password protection to your PDF files securely in your browser. Your files never leave your device, ensuring complete privacy while securing your documents with password encryption. Perfect for protecting sensitive information, confidential documents, or personal data.',
|
||||
component: lazy(() => import('./index'))
|
||||
component: lazy(() => import('./index')),
|
||||
i18n: {
|
||||
name: 'pdf.protectPdf.name',
|
||||
description: 'pdf.protectPdf.description',
|
||||
shortDescription: 'pdf.protectPdf.shortDescription'
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { Box, FormControlLabel, Switch, Typography } from '@mui/material';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Box, Typography, FormControlLabel, Switch } from '@mui/material';
|
||||
import { useEffect, useState } from 'react';
|
||||
import ToolFileResult from '@components/result/ToolFileResult';
|
||||
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
|
||||
import ToolContent from '@components/ToolContent';
|
||||
import { ToolComponentProps } from '@tools/defineTool';
|
||||
import ToolPdfInput from '@components/input/ToolPdfInput';
|
||||
import ToolFileResult from '@components/result/ToolFileResult';
|
||||
import { parsePageRanges, rotatePdf } from './service';
|
||||
import { CardExampleType } from '@components/examples/ToolExamples';
|
||||
import { PDFDocument } from 'pdf-lib';
|
||||
import { InitialValuesType, RotationAngle } from './types';
|
||||
import { parsePageRanges, rotatePdf } from './service';
|
||||
import ToolPdfInput from '@components/input/ToolPdfInput';
|
||||
import SimpleRadio from '@components/options/SimpleRadio';
|
||||
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
|
||||
import { isArray } from 'lodash';
|
||||
import { InitialValuesType, RotationAngle } from './types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const initialValues: InitialValuesType = {
|
||||
rotationAngle: 90,
|
||||
@@ -21,7 +21,7 @@ const initialValues: InitialValuesType = {
|
||||
const exampleCards: CardExampleType<InitialValuesType>[] = [
|
||||
{
|
||||
title: 'Rotate All Pages 90°',
|
||||
description: 'Rotate all pages in the document 90 degrees clockwise',
|
||||
description: 'Rotate all pages in the PDF by 90 degrees clockwise',
|
||||
sampleText: '',
|
||||
sampleResult: '',
|
||||
sampleOptions: {
|
||||
@@ -32,7 +32,7 @@ const exampleCards: CardExampleType<InitialValuesType>[] = [
|
||||
},
|
||||
{
|
||||
title: 'Rotate Specific Pages 180°',
|
||||
description: 'Rotate only pages 1 and 3 by 180 degrees',
|
||||
description: 'Rotate pages 1 and 3 by 180 degrees',
|
||||
sampleText: '',
|
||||
sampleResult: '',
|
||||
sampleOptions: {
|
||||
@@ -58,6 +58,7 @@ export default function RotatePdf({
|
||||
title,
|
||||
longDescription
|
||||
}: ToolComponentProps) {
|
||||
const { t } = useTranslation();
|
||||
const [input, setInput] = useState<File | null>(null);
|
||||
const [result, setResult] = useState<File | null>(null);
|
||||
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
||||
@@ -90,7 +91,9 @@ export default function RotatePdf({
|
||||
|
||||
if (applyToAllPages) {
|
||||
setPageRangePreview(
|
||||
totalPages > 0 ? `All ${totalPages} pages will be rotated` : ''
|
||||
totalPages > 0
|
||||
? t('pdf.rotatePdf.allPagesWillBeRotated', { count: totalPages })
|
||||
: ''
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -102,9 +105,7 @@ export default function RotatePdf({
|
||||
|
||||
try {
|
||||
const count = parsePageRanges(pageRanges, totalPages).length;
|
||||
setPageRangePreview(
|
||||
`${count} page${count !== 1 ? 's' : ''} will be rotated`
|
||||
);
|
||||
setPageRangePreview(t('pdf.rotatePdf.pagesWillBeRotated', { count }));
|
||||
} catch (error) {
|
||||
setPageRangePreview('');
|
||||
}
|
||||
@@ -124,9 +125,9 @@ export default function RotatePdf({
|
||||
}
|
||||
};
|
||||
const angleOptions: { value: RotationAngle; label: string }[] = [
|
||||
{ value: 90, label: '90° Clockwise' },
|
||||
{ value: 180, label: '180° (Upside down)' },
|
||||
{ value: 270, label: '270° (90° Counter-clockwise)' }
|
||||
{ value: 90, label: t('pdf.rotatePdf.angleOptions.clockwise90') },
|
||||
{ value: 180, label: t('pdf.rotatePdf.angleOptions.upsideDown180') },
|
||||
{ value: 270, label: t('pdf.rotatePdf.angleOptions.counterClockwise270') }
|
||||
];
|
||||
return (
|
||||
<ToolContent
|
||||
@@ -141,25 +142,25 @@ export default function RotatePdf({
|
||||
value={input}
|
||||
onChange={setInput}
|
||||
accept={['application/pdf']}
|
||||
title={'Input PDF'}
|
||||
title={t('pdf.rotatePdf.inputTitle')}
|
||||
/>
|
||||
}
|
||||
resultComponent={
|
||||
<ToolFileResult
|
||||
title={'Rotated PDF'}
|
||||
title={t('pdf.rotatePdf.resultTitle')}
|
||||
value={result}
|
||||
extension={'pdf'}
|
||||
loading={isProcessing}
|
||||
loadingText={'Rotating pages'}
|
||||
loadingText={t('pdf.rotatePdf.rotatingPages')}
|
||||
/>
|
||||
}
|
||||
getGroups={({ values, updateField }) => [
|
||||
{
|
||||
title: 'Rotation Settings',
|
||||
title: t('pdf.rotatePdf.rotationSettings'),
|
||||
component: (
|
||||
<Box>
|
||||
<Typography variant="subtitle2" sx={{ mb: 1 }}>
|
||||
Rotation Angle
|
||||
{t('pdf.rotatePdf.rotationAngle')}
|
||||
</Typography>
|
||||
{angleOptions.map((angleOption) => (
|
||||
<SimpleRadio
|
||||
@@ -182,7 +183,7 @@ export default function RotatePdf({
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label="Apply to all pages"
|
||||
label={t('pdf.rotatePdf.applyToAllPages')}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -190,7 +191,7 @@ export default function RotatePdf({
|
||||
<Box sx={{ mt: 2 }}>
|
||||
{totalPages > 0 && (
|
||||
<Typography variant="body2" sx={{ mb: 1 }}>
|
||||
PDF has {totalPages} page{totalPages !== 1 ? 's' : ''}
|
||||
{t('pdf.rotatePdf.pdfPageCount', { count: totalPages })}
|
||||
</Typography>
|
||||
)}
|
||||
<TextFieldWithDesc
|
||||
@@ -198,10 +199,8 @@ export default function RotatePdf({
|
||||
onOwnChange={(val) => {
|
||||
updateField('pageRanges', val);
|
||||
}}
|
||||
description={
|
||||
'Enter page numbers or ranges separated by commas (e.g., 1,3,5-7)'
|
||||
}
|
||||
placeholder={'e.g., 1,5-8'}
|
||||
description={t('pdf.rotatePdf.pageRangesDescription')}
|
||||
placeholder={t('pdf.rotatePdf.pageRangesPlaceholder')}
|
||||
/>
|
||||
{pageRangePreview && (
|
||||
<Typography
|
||||
@@ -219,24 +218,8 @@ export default function RotatePdf({
|
||||
]}
|
||||
onValuesChange={onValuesChange}
|
||||
toolInfo={{
|
||||
title: 'How to Use the Rotate PDF Tool',
|
||||
description: `This tool allows you to rotate pages in a PDF document. You can rotate all pages or specify individual pages to rotate.
|
||||
|
||||
Choose a rotation angle:
|
||||
- 90° Clockwise
|
||||
- 180° (Upside down)
|
||||
- 270° (90° Counter-clockwise)
|
||||
|
||||
To rotate specific pages:
|
||||
1. Uncheck "Apply to all pages"
|
||||
2. Enter page numbers or ranges separated by commas (e.g., 1,3,5-7)
|
||||
|
||||
Examples:
|
||||
- "1,5,9" rotates pages 1, 5, and 9
|
||||
- "1-5" rotates pages 1 through 5
|
||||
- "1,3-5,8-10" rotates pages 1, 3, 4, 5, 8, 9, and 10
|
||||
|
||||
${longDescription}`
|
||||
title: t('pdf.rotatePdf.toolInfo.title'),
|
||||
description: t('pdf.rotatePdf.toolInfo.description')
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { parsePageRanges, splitPdf } from './service';
|
||||
import { CardExampleType } from '@components/examples/ToolExamples';
|
||||
import { PDFDocument } from 'pdf-lib';
|
||||
import ToolPdfInput from '@components/input/ToolPdfInput';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type InitialValuesType = {
|
||||
pageRanges: string;
|
||||
@@ -48,6 +49,7 @@ const exampleCards: CardExampleType<InitialValuesType>[] = [
|
||||
];
|
||||
|
||||
export default function SplitPdf({ title }: ToolComponentProps) {
|
||||
const { t } = useTranslation();
|
||||
const [input, setInput] = useState<File | null>(null);
|
||||
const [result, setResult] = useState<File | null>(null);
|
||||
const [isProcessing, setIsProcessing] = useState<boolean>(false);
|
||||
@@ -83,9 +85,7 @@ export default function SplitPdf({ title }: ToolComponentProps) {
|
||||
}
|
||||
try {
|
||||
const count = parsePageRanges(pageRanges, totalPages).length;
|
||||
setPageRangePreview(
|
||||
`${count} page${count !== 1 ? 's' : ''} will be extracted`
|
||||
);
|
||||
setPageRangePreview(t('pdf.splitPdf.pageExtractionPreview', { count }));
|
||||
} catch (error) {
|
||||
setPageRangePreview('');
|
||||
}
|
||||
@@ -118,26 +118,26 @@ export default function SplitPdf({ title }: ToolComponentProps) {
|
||||
value={input}
|
||||
onChange={setInput}
|
||||
accept={['application/pdf']}
|
||||
title={'Input PDF'}
|
||||
title={t('pdf.splitPdf.inputTitle')}
|
||||
/>
|
||||
}
|
||||
resultComponent={
|
||||
<ToolFileResult
|
||||
title={'Output PDF with selected pages'}
|
||||
title={t('pdf.splitPdf.resultTitle')}
|
||||
value={result}
|
||||
extension={'pdf'}
|
||||
loading={isProcessing}
|
||||
loadingText={'Extracting pages'}
|
||||
loadingText={t('pdf.splitPdf.extractingPages')}
|
||||
/>
|
||||
}
|
||||
getGroups={({ values, updateField }) => [
|
||||
{
|
||||
title: 'Page Selection',
|
||||
title: t('pdf.splitPdf.pageSelection'),
|
||||
component: (
|
||||
<Box>
|
||||
{totalPages > 0 && (
|
||||
<Typography variant="body2" sx={{ mb: 1 }}>
|
||||
PDF has {totalPages} page{totalPages !== 1 ? 's' : ''}
|
||||
{t('pdf.splitPdf.pdfPageCount', { count: totalPages })}
|
||||
</Typography>
|
||||
)}
|
||||
<TextFieldWithDesc
|
||||
@@ -145,10 +145,8 @@ export default function SplitPdf({ title }: ToolComponentProps) {
|
||||
onOwnChange={(val) => {
|
||||
updateField('pageRanges', val);
|
||||
}}
|
||||
description={
|
||||
'Enter page numbers or ranges separated by commas (e.g., 1,3,5-7)'
|
||||
}
|
||||
placeholder={'e.g., 1,5-8'}
|
||||
description={t('pdf.splitPdf.pageRangesDescription')}
|
||||
placeholder={t('pdf.splitPdf.pageRangesPlaceholder')}
|
||||
/>
|
||||
{pageRangePreview && (
|
||||
<Typography
|
||||
@@ -164,15 +162,8 @@ export default function SplitPdf({ title }: ToolComponentProps) {
|
||||
]}
|
||||
onValuesChange={onValuesChange}
|
||||
toolInfo={{
|
||||
title: 'How to Use the Split PDF Tool',
|
||||
description: `This tool allows you to extract specific pages from a PDF document. You can specify individual page numbers (e.g., 1,3,5) or page ranges (e.g., 2-6) or a combination of both (e.g., 1,3-5,8).
|
||||
|
||||
Leave the page ranges field empty to include all pages from the PDF.
|
||||
|
||||
Examples:
|
||||
- "1,5,9" extracts pages 1, 5, and 9
|
||||
- "1-5" extracts pages 1 through 5
|
||||
- "1,3-5,8-10" extracts pages 1, 3, 4, 5, 8, 9, and 10`
|
||||
title: t('pdf.splitPdf.toolInfo.title'),
|
||||
description: t('pdf.splitPdf.toolInfo.description')
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -9,5 +9,10 @@ export const meta = defineTool('pdf', {
|
||||
icon: 'material-symbols-light:call-split-rounded',
|
||||
component: lazy(() => import('./index')),
|
||||
keywords: ['pdf', 'split', 'extract', 'pages', 'range', 'document'],
|
||||
path: 'split-pdf'
|
||||
path: 'split-pdf',
|
||||
i18n: {
|
||||
name: 'pdf.splitPdf.name',
|
||||
description: 'pdf.splitPdf.description',
|
||||
shortDescription: 'pdf.splitPdf.shortDescription'
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user