mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-22 04:09:22 +00:00
Bug/v2/reduce console pollution (#4212)
# Description of Changes <!-- Fixes the issues with I18 that were causing lots of console errors. Fixes mime type error Closes #(issue_number) --> --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: stirlingbot[bot] <stirlingbot[bot]@users.noreply.github.com> Co-authored-by: Ludy <Ludy87@users.noreply.github.com> Co-authored-by: Dario Ghunney Ware <dariogware@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: EthanHealy01 <80844253+EthanHealy01@users.noreply.github.com> Co-authored-by: Ethan <ethan@MacBook-Pro.local> Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com> Co-authored-by: albanobattistella <34811668+albanobattistella@users.noreply.github.com>
This commit is contained in:
parent
129e4d00e9
commit
7e60eb40b4
@ -10,7 +10,8 @@
|
|||||||
"Bash(npm test)",
|
"Bash(npm test)",
|
||||||
"Bash(npm test:*)",
|
"Bash(npm test:*)",
|
||||||
"Bash(ls:*)",
|
"Bash(ls:*)",
|
||||||
"Bash(npx tsc:*)"
|
"Bash(npx tsc:*)",
|
||||||
|
"Bash(sed:*)"
|
||||||
],
|
],
|
||||||
"deny": []
|
"deny": []
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en-GB">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
@ -383,14 +383,6 @@
|
|||||||
"title": "Remove",
|
"title": "Remove",
|
||||||
"desc": "Delete unwanted pages from your PDF document."
|
"desc": "Delete unwanted pages from your PDF document."
|
||||||
},
|
},
|
||||||
"addPassword": {
|
|
||||||
"title": "Add Password",
|
|
||||||
"desc": "Encrypt your PDF document with a password."
|
|
||||||
},
|
|
||||||
"changePermissions": {
|
|
||||||
"title": "Change Permissions",
|
|
||||||
"desc": "Change document restrictions and permissions."
|
|
||||||
},
|
|
||||||
"removePassword": {
|
"removePassword": {
|
||||||
"title": "Remove Password",
|
"title": "Remove Password",
|
||||||
"desc": "Remove password protection from your PDF document."
|
"desc": "Remove password protection from your PDF document."
|
||||||
@ -399,10 +391,6 @@
|
|||||||
"title": "Compress",
|
"title": "Compress",
|
||||||
"desc": "Compress PDFs to reduce their file size."
|
"desc": "Compress PDFs to reduce their file size."
|
||||||
},
|
},
|
||||||
"sanitize": {
|
|
||||||
"title": "Sanitise",
|
|
||||||
"desc": "Remove potentially harmful elements from PDF files."
|
|
||||||
},
|
|
||||||
"unlockPDFForms": {
|
"unlockPDFForms": {
|
||||||
"title": "Unlock PDF Forms",
|
"title": "Unlock PDF Forms",
|
||||||
"desc": "Remove read-only property of form fields in a PDF document."
|
"desc": "Remove read-only property of form fields in a PDF document."
|
||||||
@ -1751,6 +1739,8 @@
|
|||||||
"approximateSize": "Approximate size"
|
"approximateSize": "Approximate size"
|
||||||
},
|
},
|
||||||
"sanitize": {
|
"sanitize": {
|
||||||
|
"title": "Sanitise",
|
||||||
|
"desc": "Remove potentially harmful elements from PDF files.",
|
||||||
"submit": "Sanitise PDF",
|
"submit": "Sanitise PDF",
|
||||||
"completed": "Sanitisation completed successfully",
|
"completed": "Sanitisation completed successfully",
|
||||||
"error.generic": "Sanitisation failed",
|
"error.generic": "Sanitisation failed",
|
||||||
@ -1783,6 +1773,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"addPassword": {
|
"addPassword": {
|
||||||
|
"title": "Add Password",
|
||||||
|
"desc": "Encrypt your PDF document with a password.",
|
||||||
"completed": "Password protection applied",
|
"completed": "Password protection applied",
|
||||||
"submit": "Encrypt",
|
"submit": "Encrypt",
|
||||||
"filenamePrefix": "encrypted",
|
"filenamePrefix": "encrypted",
|
||||||
@ -1835,6 +1827,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"changePermissions": {
|
"changePermissions": {
|
||||||
|
"title": "Change Permissions",
|
||||||
|
"desc": "Change document restrictions and permissions.",
|
||||||
"completed": "Permissions changed",
|
"completed": "Permissions changed",
|
||||||
"submit": "Change Permissions",
|
"submit": "Change Permissions",
|
||||||
"title": "Document Permissions",
|
"title": "Document Permissions",
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"convert": {
|
|
||||||
"selectSourceFormat": "Select source file format",
|
|
||||||
"selectTargetFormat": "Select target file format",
|
|
||||||
"selectFirst": "Select a source format first",
|
|
||||||
"imageOptions": "Image Options:",
|
|
||||||
"emailOptions": "Email Options:",
|
|
||||||
"colorType": "Color Type",
|
|
||||||
"dpi": "DPI",
|
|
||||||
"singleOrMultiple": "Output",
|
|
||||||
"emailNote": "Email attachments and embedded images will be included"
|
|
||||||
},
|
|
||||||
"common": {
|
|
||||||
"color": "Color",
|
|
||||||
"grayscale": "Grayscale",
|
|
||||||
"blackWhite": "Black & White",
|
|
||||||
"single": "Single Image",
|
|
||||||
"multiple": "Multiple Images"
|
|
||||||
},
|
|
||||||
"groups": {
|
|
||||||
"document": "Document",
|
|
||||||
"spreadsheet": "Spreadsheet",
|
|
||||||
"presentation": "Presentation",
|
|
||||||
"image": "Image",
|
|
||||||
"web": "Web",
|
|
||||||
"text": "Text",
|
|
||||||
"email": "Email"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { Suspense } from 'react';
|
||||||
import { RainbowThemeProvider } from './components/shared/RainbowThemeProvider';
|
import { RainbowThemeProvider } from './components/shared/RainbowThemeProvider';
|
||||||
import { FileContextProvider } from './contexts/FileContext';
|
import { FileContextProvider } from './contexts/FileContext';
|
||||||
import { FilesModalProvider } from './contexts/FilesModalContext';
|
import { FilesModalProvider } from './contexts/FilesModalContext';
|
||||||
@ -8,14 +8,30 @@ import HomePage from './pages/HomePage';
|
|||||||
import './styles/tailwind.css';
|
import './styles/tailwind.css';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
|
// Loading component for i18next suspense
|
||||||
|
const LoadingFallback = () => (
|
||||||
|
<div style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
height: '100vh',
|
||||||
|
fontSize: '18px',
|
||||||
|
color: '#666'
|
||||||
|
}}>
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<RainbowThemeProvider>
|
<Suspense fallback={<LoadingFallback />}>
|
||||||
<FileContextProvider enableUrlSync={true} enablePersistence={true}>
|
<RainbowThemeProvider>
|
||||||
<FilesModalProvider>
|
<FileContextProvider enableUrlSync={true} enablePersistence={true}>
|
||||||
<HomePage />
|
<FilesModalProvider>
|
||||||
</FilesModalProvider>
|
<HomePage />
|
||||||
</FileContextProvider>
|
</FilesModalProvider>
|
||||||
</RainbowThemeProvider>
|
</FileContextProvider>
|
||||||
|
</RainbowThemeProvider>
|
||||||
|
</Suspense>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ const FileManager: React.FC<FileManagerProps> = ({ selectedTool }) => {
|
|||||||
className="overflow-hidden p-0"
|
className="overflow-hidden p-0"
|
||||||
withCloseButton={false}
|
withCloseButton={false}
|
||||||
styles={{
|
styles={{
|
||||||
content: {
|
content: {
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
margin: isMobile ? '1rem' : '2rem'
|
margin: isMobile ? '1rem' : '2rem'
|
||||||
},
|
},
|
||||||
@ -116,12 +116,12 @@ const FileManager: React.FC<FileManagerProps> = ({ selectedTool }) => {
|
|||||||
header: { display: 'none' }
|
header: { display: 'none' }
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{
|
<div style={{
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
height: modalHeight,
|
height: modalHeight,
|
||||||
width: modalWidth,
|
width: modalWidth,
|
||||||
maxWidth: modalMaxWidth,
|
maxWidth: modalMaxWidth,
|
||||||
maxHeight: modalMaxHeight,
|
maxHeight: modalMaxHeight,
|
||||||
minWidth: modalMinWidth,
|
minWidth: modalMinWidth,
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
overflow: 'hidden'
|
overflow: 'hidden'
|
||||||
@ -130,11 +130,11 @@ const FileManager: React.FC<FileManagerProps> = ({ selectedTool }) => {
|
|||||||
onDrop={handleNewFileUpload}
|
onDrop={handleNewFileUpload}
|
||||||
onDragEnter={() => setIsDragging(true)}
|
onDragEnter={() => setIsDragging(true)}
|
||||||
onDragLeave={() => setIsDragging(false)}
|
onDragLeave={() => setIsDragging(false)}
|
||||||
accept={["*/*"]}
|
accept={["*/*"] as any}
|
||||||
multiple={true}
|
multiple={true}
|
||||||
activateOnClick={false}
|
activateOnClick={false}
|
||||||
style={{
|
style={{
|
||||||
height: '100%',
|
height: '100%',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '30px',
|
borderRadius: '30px',
|
||||||
@ -158,11 +158,11 @@ const FileManager: React.FC<FileManagerProps> = ({ selectedTool }) => {
|
|||||||
{isMobile ? <MobileLayout /> : <DesktopLayout />}
|
{isMobile ? <MobileLayout /> : <DesktopLayout />}
|
||||||
</FileManagerProvider>
|
</FileManagerProvider>
|
||||||
</Dropzone>
|
</Dropzone>
|
||||||
|
|
||||||
<DragOverlay isVisible={isDragging} />
|
<DragOverlay isVisible={isDragging} />
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FileManager;
|
export default FileManager;
|
||||||
|
@ -664,7 +664,6 @@ const FileEditor = ({
|
|||||||
return (
|
return (
|
||||||
<Dropzone
|
<Dropzone
|
||||||
onDrop={handleFileUpload}
|
onDrop={handleFileUpload}
|
||||||
accept={["*/*"]}
|
|
||||||
multiple={true}
|
multiple={true}
|
||||||
maxSize={2 * 1024 * 1024 * 1024}
|
maxSize={2 * 1024 * 1024 * 1024}
|
||||||
style={{
|
style={{
|
||||||
|
@ -9,7 +9,7 @@ const HiddenFileInput: React.FC = () => {
|
|||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
type="file"
|
type="file"
|
||||||
multiple={true}
|
multiple={true}
|
||||||
accept="*/*"
|
accept={["*/*"] as any}
|
||||||
onChange={onFileInputChange}
|
onChange={onFileInputChange}
|
||||||
style={{ display: 'none' }}
|
style={{ display: 'none' }}
|
||||||
data-testid="file-input"
|
data-testid="file-input"
|
||||||
@ -17,4 +17,4 @@ const HiddenFileInput: React.FC = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HiddenFileInput;
|
export default HiddenFileInput;
|
||||||
|
@ -33,7 +33,7 @@ const LandingPage = () => {
|
|||||||
{/* White PDF Page Background */}
|
{/* White PDF Page Background */}
|
||||||
<Dropzone
|
<Dropzone
|
||||||
onDrop={handleFileDrop}
|
onDrop={handleFileDrop}
|
||||||
accept={["application/pdf", "application/zip", "application/x-zip-compressed"]}
|
accept={["*/*"] as any}
|
||||||
multiple={true}
|
multiple={true}
|
||||||
className="w-4/5 flex items-center justify-center h-[95vh]"
|
className="w-4/5 flex items-center justify-center h-[95vh]"
|
||||||
style={{
|
style={{
|
||||||
@ -116,7 +116,7 @@ const LandingPage = () => {
|
|||||||
>
|
>
|
||||||
<AddIcon className="text-[var(--accent-interactive)]" />
|
<AddIcon className="text-[var(--accent-interactive)]" />
|
||||||
<span>
|
<span>
|
||||||
{t('fileUpload.addFiles', 'Add Files')}
|
{t('fileUpload.uploadFiles', 'Upload Files')}
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ const LandingPage = () => {
|
|||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
type="file"
|
type="file"
|
||||||
multiple
|
multiple
|
||||||
accept=".pdf,.zip"
|
accept="*/*"
|
||||||
onChange={handleFileSelect}
|
onChange={handleFileSelect}
|
||||||
style={{ display: 'none' }}
|
style={{ display: 'none' }}
|
||||||
/>
|
/>
|
||||||
@ -137,7 +137,7 @@ const LandingPage = () => {
|
|||||||
className="text-[var(--accent-interactive)]"
|
className="text-[var(--accent-interactive)]"
|
||||||
style={{ fontSize: '.8rem' }}
|
style={{ fontSize: '.8rem' }}
|
||||||
>
|
>
|
||||||
{t('fileUpload.dragFilesInOrClick', 'Drag files in or click "Add Files" to browse')}
|
{t('fileUpload.dropFilesHere', 'Drop files here or click to upload')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Dropzone>
|
</Dropzone>
|
||||||
@ -145,4 +145,4 @@ const LandingPage = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LandingPage;
|
export default LandingPage;
|
||||||
|
@ -142,9 +142,9 @@ export const useToolManagement = (): ToolManagementResult => {
|
|||||||
const toolDef = toolDefinitions[toolKey];
|
const toolDef = toolDefinitions[toolKey];
|
||||||
availableTools[toolKey] = {
|
availableTools[toolKey] = {
|
||||||
...toolDef,
|
...toolDef,
|
||||||
name: t(`home.${toolKey}.title`, toolKey.charAt(0).toUpperCase() + toolKey.slice(1)),
|
name: t(`${toolKey}.title`, toolKey.charAt(0).toUpperCase() + toolKey.slice(1)),
|
||||||
title: t(`home.${toolKey}.title`, toolDef.description || toolKey),
|
title: t(`${toolKey}.title`, toolDef.description || toolKey),
|
||||||
description: t(`home.${toolKey}.desc`, toolDef.description || `${toolKey} tool`)
|
description: t(`${toolKey}.desc`, toolDef.description || `${toolKey} tool`)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -5,6 +5,7 @@ import Backend from 'i18next-http-backend';
|
|||||||
|
|
||||||
// Define supported languages (based on your existing translations)
|
// Define supported languages (based on your existing translations)
|
||||||
export const supportedLanguages = {
|
export const supportedLanguages = {
|
||||||
|
'en': 'English',
|
||||||
'en-GB': 'English (UK)',
|
'en-GB': 'English (UK)',
|
||||||
'en-US': 'English (US)',
|
'en-US': 'English (US)',
|
||||||
'ar-AR': 'العربية',
|
'ar-AR': 'العربية',
|
||||||
@ -57,26 +58,42 @@ i18n
|
|||||||
.use(initReactI18next)
|
.use(initReactI18next)
|
||||||
.init({
|
.init({
|
||||||
fallbackLng: 'en-GB',
|
fallbackLng: 'en-GB',
|
||||||
|
supportedLngs: Object.keys(supportedLanguages),
|
||||||
|
nonExplicitSupportedLngs: false,
|
||||||
debug: process.env.NODE_ENV === 'development',
|
debug: process.env.NODE_ENV === 'development',
|
||||||
|
|
||||||
|
// Ensure synchronous loading to prevent timing issues
|
||||||
|
initImmediate: false,
|
||||||
|
|
||||||
interpolation: {
|
interpolation: {
|
||||||
escapeValue: false, // React already escapes values
|
escapeValue: false, // React already escapes values
|
||||||
},
|
},
|
||||||
|
|
||||||
backend: {
|
backend: {
|
||||||
loadPath: '/locales/{{lng}}/{{ns}}.json',
|
loadPath: (lngs: string[], namespaces: string[]) => {
|
||||||
|
// Map 'en' to 'en-GB' for loading translations
|
||||||
|
const lng = lngs[0] === 'en' ? 'en-GB' : lngs[0];
|
||||||
|
return `/locales/${lng}/${namespaces[0]}.json`;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
detection: {
|
detection: {
|
||||||
order: ['localStorage', 'navigator', 'htmlTag'],
|
order: ['localStorage', 'navigator', 'htmlTag'],
|
||||||
caches: ['localStorage'],
|
caches: ['localStorage'],
|
||||||
|
convertDetectedLanguage: (lng: string) => lng === 'en' ? 'en-GB' : lng,
|
||||||
},
|
},
|
||||||
|
|
||||||
react: {
|
react: {
|
||||||
useSuspense: false, // Set to false to avoid suspense issues with SSR
|
useSuspense: true, // Enable suspense to prevent premature rendering
|
||||||
|
bindI18n: 'languageChanged loaded',
|
||||||
|
bindI18nStore: 'added removed',
|
||||||
|
transEmptyNodeValue: '', // Return empty string for missing keys instead of key name
|
||||||
|
transSupportBasicHtmlNodes: true,
|
||||||
|
transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p'],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Set document direction based on language
|
// Set document direction based on language
|
||||||
i18n.on('languageChanged', (lng) => {
|
i18n.on('languageChanged', (lng) => {
|
||||||
const isRTL = rtlLanguages.includes(lng);
|
const isRTL = rtlLanguages.includes(lng);
|
||||||
@ -84,4 +101,4 @@ i18n.on('languageChanged', (lng) => {
|
|||||||
document.documentElement.lang = lng;
|
document.documentElement.lang = lng;
|
||||||
});
|
});
|
||||||
|
|
||||||
export default i18n;
|
export default i18n;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user