Enhance i18n configuration with synchronous loading and enable suspense for improved rendering

Refactor App component to include loading fallback for i18next suspense
This commit is contained in:
Reece Browne 2025-08-14 20:36:19 +01:00
parent b1fd8d9bea
commit fdb564b929
3 changed files with 35 additions and 21 deletions

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

@ -118,7 +118,7 @@ interface ToolManagementResult {
}
export const useToolManagement = (): ToolManagementResult => {
const { t, ready } = useTranslation();
const { t } = useTranslation();
const [selectedToolKey, setSelectedToolKey] = useState<string | null>(null);
const [toolSelectedFileIds, setToolSelectedFileIds] = useState<string[]>([]);
@ -136,10 +136,6 @@ export const useToolManagement = (): ToolManagementResult => {
}, [endpointsLoading, endpointStatus]);
const toolRegistry: ToolRegistry = useMemo(() => {
if (!ready) {
return {};
}
const availableTools: ToolRegistry = {};
Object.keys(toolDefinitions).forEach(toolKey => {
if (isToolAvailable(toolKey)) {
@ -151,7 +147,7 @@ export const useToolManagement = (): ToolManagementResult => {
}
});
return availableTools;
}, [t, isToolAvailable, ready]);
}, [t, isToolAvailable]);
useEffect(() => {
if (!endpointsLoading && selectedToolKey && !toolRegistry[selectedToolKey]) {

View File

@ -61,6 +61,9 @@ i18n
nonExplicitSupportedLngs: false,
debug: process.env.NODE_ENV === 'development',
// Ensure synchronous loading to prevent timing issues
initImmediate: false,
interpolation: {
escapeValue: false, // React already escapes values
},
@ -75,16 +78,15 @@ i18n
},
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'],
},
});
// Map base language codes to specific locales
i18n.services.languageUtils.formatLanguageCode = (lng) => {
if (lng === 'en') return 'en-GB';
return lng;
};
// Set document direction based on language
i18n.on('languageChanged', (lng) => {
const isRTL = rtlLanguages.includes(lng);