Update sitemaps and improve language handling

- Updated last modification dates in static and tools sitemaps to 2026-04-01.
- Enhanced language switching in the Header component to ensure language resources are loaded before changing the language.
- Added language resource loading logic in i18n configuration to support dynamic loading of language files.
- Improved SEO route page to ensure correct language is set based on URL parameters.
- Adjusted global CSS for deferred sections to optimize rendering.
- Configured Nginx to enable Brotli compression for better performance.
This commit is contained in:
Your Name
2026-04-01 07:25:24 +02:00
parent eb8d6463c5
commit 568446697c
13 changed files with 378 additions and 273 deletions

View File

@@ -3,8 +3,57 @@ import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import en from './en.json';
import ar from './ar.json';
import fr from './fr.json';
type SupportedLanguage = 'en' | 'ar' | 'fr';
const loadedLanguages = new Set<SupportedLanguage>(['en']);
const languageLoaders: Record<Exclude<SupportedLanguage, 'en'>, () => Promise<{ default: Record<string, unknown> }>> = {
ar: () => import('./ar.json'),
fr: () => import('./fr.json'),
};
function normalizeLanguage(language?: string): SupportedLanguage {
const base = (language || '').split('-')[0];
return base === 'ar' || base === 'fr' ? base : 'en';
}
function getInitialLanguage(): SupportedLanguage {
if (typeof window === 'undefined') {
return 'en';
}
const htmlLanguage = normalizeLanguage(document.documentElement.lang);
if (htmlLanguage !== 'en') {
return htmlLanguage;
}
try {
const stored = localStorage.getItem('i18nextLng');
const fromStorage = normalizeLanguage(stored || undefined);
if (fromStorage !== 'en') {
return fromStorage;
}
} catch {
// no-op
}
return normalizeLanguage(navigator.language);
}
export async function ensureLanguageResources(language: string) {
const normalized = normalizeLanguage(language);
if (normalized === 'en' || loadedLanguages.has(normalized)) {
return normalized;
}
const module = await languageLoaders[normalized]();
i18n.addResourceBundle(normalized, 'translation', module.default, true, true);
loadedLanguages.add(normalized);
return normalized;
}
const initialLanguage = getInitialLanguage();
i18n
.use(LanguageDetector)
@@ -12,11 +61,11 @@ i18n
.init({
resources: {
en: { translation: en },
ar: { translation: ar },
fr: { translation: fr },
},
lng: initialLanguage,
fallbackLng: 'en',
supportedLngs: ['en', 'ar', 'fr'],
load: 'languageOnly',
interpolation: {
escapeValue: false,
},
@@ -26,4 +75,12 @@ i18n
},
});
if (initialLanguage !== 'en') {
void ensureLanguageResources(initialLanguage).then((resolved) => {
if (i18n.language !== resolved) {
void i18n.changeLanguage(resolved);
}
});
}
export default i18n;