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:
Reece Browne 2025-08-15 13:15:21 +01:00 committed by GitHub
parent 129e4d00e9
commit 7e60eb40b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 79 additions and 81 deletions

View File

@ -10,7 +10,8 @@
"Bash(npm test)",
"Bash(npm test:*)",
"Bash(ls:*)",
"Bash(npx tsc:*)"
"Bash(npx tsc:*)",
"Bash(sed:*)"
],
"deny": []
}

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en-GB">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />

View File

@ -383,14 +383,6 @@
"title": "Remove",
"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": {
"title": "Remove Password",
"desc": "Remove password protection from your PDF document."
@ -399,10 +391,6 @@
"title": "Compress",
"desc": "Compress PDFs to reduce their file size."
},
"sanitize": {
"title": "Sanitise",
"desc": "Remove potentially harmful elements from PDF files."
},
"unlockPDFForms": {
"title": "Unlock PDF Forms",
"desc": "Remove read-only property of form fields in a PDF document."
@ -1751,6 +1739,8 @@
"approximateSize": "Approximate size"
},
"sanitize": {
"title": "Sanitise",
"desc": "Remove potentially harmful elements from PDF files.",
"submit": "Sanitise PDF",
"completed": "Sanitisation completed successfully",
"error.generic": "Sanitisation failed",
@ -1783,6 +1773,8 @@
}
},
"addPassword": {
"title": "Add Password",
"desc": "Encrypt your PDF document with a password.",
"completed": "Password protection applied",
"submit": "Encrypt",
"filenamePrefix": "encrypted",
@ -1835,6 +1827,8 @@
}
},
"changePermissions": {
"title": "Change Permissions",
"desc": "Change document restrictions and permissions.",
"completed": "Permissions changed",
"submit": "Change Permissions",
"title": "Document Permissions",

View File

@ -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"
}
}

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { Suspense } from 'react';
import { RainbowThemeProvider } from './components/shared/RainbowThemeProvider';
import { FileContextProvider } from './contexts/FileContext';
import { FilesModalProvider } from './contexts/FilesModalContext';
@ -8,14 +8,30 @@ import HomePage from './pages/HomePage';
import './styles/tailwind.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() {
return (
<RainbowThemeProvider>
<FileContextProvider enableUrlSync={true} enablePersistence={true}>
<FilesModalProvider>
<HomePage />
</FilesModalProvider>
</FileContextProvider>
</RainbowThemeProvider>
<Suspense fallback={<LoadingFallback />}>
<RainbowThemeProvider>
<FileContextProvider enableUrlSync={true} enablePersistence={true}>
<FilesModalProvider>
<HomePage />
</FilesModalProvider>
</FileContextProvider>
</RainbowThemeProvider>
</Suspense>
);
}

View File

@ -108,7 +108,7 @@ const FileManager: React.FC<FileManagerProps> = ({ selectedTool }) => {
className="overflow-hidden p-0"
withCloseButton={false}
styles={{
content: {
content: {
position: 'relative',
margin: isMobile ? '1rem' : '2rem'
},
@ -116,12 +116,12 @@ const FileManager: React.FC<FileManagerProps> = ({ selectedTool }) => {
header: { display: 'none' }
}}
>
<div style={{
position: 'relative',
height: modalHeight,
width: modalWidth,
maxWidth: modalMaxWidth,
maxHeight: modalMaxHeight,
<div style={{
position: 'relative',
height: modalHeight,
width: modalWidth,
maxWidth: modalMaxWidth,
maxHeight: modalMaxHeight,
minWidth: modalMinWidth,
margin: '0 auto',
overflow: 'hidden'
@ -130,11 +130,11 @@ const FileManager: React.FC<FileManagerProps> = ({ selectedTool }) => {
onDrop={handleNewFileUpload}
onDragEnter={() => setIsDragging(true)}
onDragLeave={() => setIsDragging(false)}
accept={["*/*"]}
accept={["*/*"] as any}
multiple={true}
activateOnClick={false}
style={{
height: '100%',
style={{
height: '100%',
width: '100%',
border: 'none',
borderRadius: '30px',
@ -158,11 +158,11 @@ const FileManager: React.FC<FileManagerProps> = ({ selectedTool }) => {
{isMobile ? <MobileLayout /> : <DesktopLayout />}
</FileManagerProvider>
</Dropzone>
<DragOverlay isVisible={isDragging} />
</div>
</Modal>
);
};
export default FileManager;
export default FileManager;

View File

@ -664,7 +664,6 @@ const FileEditor = ({
return (
<Dropzone
onDrop={handleFileUpload}
accept={["*/*"]}
multiple={true}
maxSize={2 * 1024 * 1024 * 1024}
style={{

View File

@ -9,7 +9,7 @@ const HiddenFileInput: React.FC = () => {
ref={fileInputRef}
type="file"
multiple={true}
accept="*/*"
accept={["*/*"] as any}
onChange={onFileInputChange}
style={{ display: 'none' }}
data-testid="file-input"
@ -17,4 +17,4 @@ const HiddenFileInput: React.FC = () => {
);
};
export default HiddenFileInput;
export default HiddenFileInput;

View File

@ -33,7 +33,7 @@ const LandingPage = () => {
{/* White PDF Page Background */}
<Dropzone
onDrop={handleFileDrop}
accept={["application/pdf", "application/zip", "application/x-zip-compressed"]}
accept={["*/*"] as any}
multiple={true}
className="w-4/5 flex items-center justify-center h-[95vh]"
style={{
@ -116,7 +116,7 @@ const LandingPage = () => {
>
<AddIcon className="text-[var(--accent-interactive)]" />
<span>
{t('fileUpload.addFiles', 'Add Files')}
{t('fileUpload.uploadFiles', 'Upload Files')}
</span>
</Button>
@ -125,7 +125,7 @@ const LandingPage = () => {
ref={fileInputRef}
type="file"
multiple
accept=".pdf,.zip"
accept="*/*"
onChange={handleFileSelect}
style={{ display: 'none' }}
/>
@ -137,7 +137,7 @@ const LandingPage = () => {
className="text-[var(--accent-interactive)]"
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>
</div>
</Dropzone>
@ -145,4 +145,4 @@ const LandingPage = () => {
);
};
export default LandingPage;
export default LandingPage;

View File

@ -142,9 +142,9 @@ export const useToolManagement = (): ToolManagementResult => {
const toolDef = toolDefinitions[toolKey];
availableTools[toolKey] = {
...toolDef,
name: t(`home.${toolKey}.title`, toolKey.charAt(0).toUpperCase() + toolKey.slice(1)),
title: t(`home.${toolKey}.title`, toolDef.description || toolKey),
description: t(`home.${toolKey}.desc`, toolDef.description || `${toolKey} tool`)
name: t(`${toolKey}.title`, toolKey.charAt(0).toUpperCase() + toolKey.slice(1)),
title: t(`${toolKey}.title`, toolDef.description || toolKey),
description: t(`${toolKey}.desc`, toolDef.description || `${toolKey} tool`)
};
}
});

View File

@ -5,6 +5,7 @@ import Backend from 'i18next-http-backend';
// Define supported languages (based on your existing translations)
export const supportedLanguages = {
'en': 'English',
'en-GB': 'English (UK)',
'en-US': 'English (US)',
'ar-AR': 'العربية',
@ -57,26 +58,42 @@ i18n
.use(initReactI18next)
.init({
fallbackLng: 'en-GB',
supportedLngs: Object.keys(supportedLanguages),
nonExplicitSupportedLngs: false,
debug: process.env.NODE_ENV === 'development',
// Ensure synchronous loading to prevent timing issues
initImmediate: false,
interpolation: {
escapeValue: false, // React already escapes values
},
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: {
order: ['localStorage', 'navigator', 'htmlTag'],
caches: ['localStorage'],
convertDetectedLanguage: (lng: string) => lng === 'en' ? 'en-GB' : lng,
},
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
i18n.on('languageChanged', (lng) => {
const isRTL = rtlLanguages.includes(lng);
@ -84,4 +101,4 @@ i18n.on('languageChanged', (lng) => {
document.documentElement.lang = lng;
});
export default i18n;
export default i18n;