import { BrowserRouter as Router, Routes, Route, useLocation, useNavigate } from 'react-router-dom'; import React, { Suspense, lazy, useEffect } from 'react'; import ErrorBoundary from './utils/errorBoundary'; import Header from './components/Header'; import AnalyticsInitializer from './components/AnalyticsInitializer'; import ReferralInitializer from './components/ReferralInitializer'; import Hero from './components/Hero'; import { useConsent } from './hooks/useConsent'; import { I18nProvider } from './context/I18nContext'; import { resolveLocaleFromPath } from './i18n'; // Lazy-load heavy routes const Trade = lazy(() => import('./pages/Trade')); const AboutUs = lazy(() => import('./pages/AboutUs')); const ContactUs = lazy(() => import('./pages/ContactUs')); const Security = lazy(() => import('./pages/Security')); const CookiePolicy = lazy(() => import('./pages/CookiePolicy')); const ReverseSolicitation = lazy(() => import('./pages/ReverseSolicitation')); const OtherDocuments = lazy(() => import('./pages/OtherDocuments')); const BecomePartner = lazy(() => import('./pages/BecomePartner')); const AccountTypes = lazy(() => import('./pages/AccountTypes')); const Forbidden = lazy(() => import('./pages/Forbidden')); // Lazy-load below-the-fold home components and footer const Features = lazy(() => import('./components/Features')); const HowToStart = lazy(() => import('./components/HowToStart')); const About = lazy(() => import('./components/About')); const Footer = lazy(() => import('./components/Footer')); const LazyConsentPopup = lazy(() => import('./components/ConsentPopup')); // Redirect helper to ensure language prefix in URL based on selected language const LanguageRedirector = () => { const location = useLocation(); const navigate = useNavigate(); useEffect(() => { try { const stored = localStorage.getItem('finprime_language'); const raw = stored ? (JSON.parse(stored) as string) : 'en'; const storedLang: 'en' | 'es' | 'cs' | 'ar' | 'tr' | 'fr' | 'hu' = raw === 'cz' ? 'cs' : (raw === 'en' || raw === 'es' || raw === 'cs' || raw === 'ar' || raw === 'tr' || raw === 'fr' || raw === 'hu' ? (raw as 'en' | 'es' | 'cs' | 'ar' | 'tr' | 'fr' | 'hu') : 'en'); const path = location.pathname; const langToPrefix: Record<'en' | 'es' | 'cs' | 'ar' | 'tr' | 'fr' | 'hu', '/en' | '/es' | '/cz' | '/ar' | '/tr' | '/fr' | '/hu'> = { en: '/en', es: '/es', cs: '/cz', ar: '/ar', tr: '/tr', fr: '/fr', hu: '/hu', }; const prefixToLang: Record<'/en' | '/es' | '/cz' | '/ar' | '/tr' | '/fr' | '/hu', 'en' | 'es' | 'cs' | 'ar' | 'tr' | 'fr' | 'hu'> = { '/en': 'en', '/es': 'es', '/cz': 'cs', '/ar': 'ar', '/tr': 'tr', '/fr': 'fr', '/hu': 'hu', }; const knownPrefixes = ['/en', '/es', '/cz', '/ar', '/tr', '/fr', '/hu']; const supportedPaths = new Set([ '/', '/trade', '/about-us', '/help-center', '/security', '/cookie-policy', '/reverse-solicitation', '/privacy-policy', '/other-documents', '/become-partner', '/account-types', '/forbidden', ]); const hasAnyPrefix = knownPrefixes.some(p => path === p || path.startsWith(`${p}/`)); const currentPrefix = knownPrefixes.find(p => path === p || path.startsWith(`${p}/`)) as '/en' | '/es' | '/cz' | '/ar' | undefined; // If URL already specifies a language prefix, honor it and sync localStorage if (hasAnyPrefix && currentPrefix) { const urlLang = prefixToLang[currentPrefix]; if (storedLang !== urlLang) { localStorage.setItem('finprime_language', JSON.stringify(urlLang)); } return; // Do not rewrite user's chosen prefixed URL } // If on unprefixed known path, add the stored language prefix const isKnownUnprefixedPath = supportedPaths.has(path); if (!hasAnyPrefix && isKnownUnprefixedPath) { const targetPrefix = langToPrefix[storedLang] || '/en'; const newPath = path === '/' ? targetPrefix : `${targetPrefix}${path}`; navigate({ pathname: newPath, search: location.search, hash: location.hash }, { replace: true }); } } catch { // ignore parsing issues } }, [location.pathname, location.search, location.hash, navigate]); return null; }; const ScrollToTop = () => { const location = useLocation(); useEffect(() => { if (typeof window !== 'undefined') { window.scrollTo({ top: 0, left: 0, behavior: 'instant' as ScrollBehavior }); } }, [location.pathname, location.search, location.hash]); return null; }; function App() { // Manage consent at the app level to gate heavy initializers const { showConsentPopup, handleConsentAccepted, consentData } = useConsent(); // Render-time consent manager so we can access location (inside Router) const ConsentManager: React.FC = () => { const loc = useLocation(); const isReverseSolicitationPage = loc.pathname === '/reverse-solicitation' || loc.pathname.endsWith('/reverse-solicitation'); if (isReverseSolicitationPage) return null; return showConsentPopup ? ( ) : null; }; // Minimal disclaimer for Czech and Hungarian locales const CzechDisclaimerBanner: React.FC = () => { const loc = useLocation(); const locale = resolveLocaleFromPath(loc.pathname); if (locale !== 'cs' && locale !== 'hu') return null; return (
This language version is AI translated, and have not been verified for accuracy. Consider using official translation.
); }; const I18nRouterProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const loc = useLocation(); const locale = resolveLocaleFromPath(loc.pathname); return {children}; }; return ( {consentData ? : null}
} /> {/* English-prefixed aliases */} } /> {/* Spanish-prefixed aliases */} } /> {/* Czech-prefixed aliases (using /cz; support /cs via redirect) */} } /> {/* Redirect /cs to /cz for production environments that might link /cs */} } /> {/* Arabic-prefixed aliases */} } /> {/* Turkish-prefixed aliases */} } /> {/* French-prefixed aliases */} } /> {/* Hungarian-prefixed aliases */} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } />
); } export default App;