Completes full internationalization coverage for the webmail application with enhanced language support: - Replace all remaining hardcoded English strings with translation keys - Add timezone auto-detection to prevent hydration mismatches - Enable instant client-side language switching without page reload - Add 60+ new translation keys in English and French locales - Improve language switcher component with proper state management - Add health check endpoint for container orchestration All user-facing text now supports English and French with no hardcoded fallbacks, providing a fully localized experience.
64 lines
1.8 KiB
TypeScript
64 lines
1.8 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from 'react';
|
|
import { NextIntlClientProvider } from 'next-intl';
|
|
import { useLocaleStore } from '@/stores/locale-store';
|
|
import enMessages from '@/locales/en/common.json';
|
|
import frMessages from '@/locales/fr/common.json';
|
|
|
|
// Pre-loaded translations (loaded at build time, not runtime)
|
|
const ALL_MESSAGES = {
|
|
en: enMessages,
|
|
fr: frMessages,
|
|
};
|
|
|
|
interface IntlProviderProps {
|
|
locale: string;
|
|
messages: Record<string, unknown>;
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export function IntlProvider({ locale: initialLocale, children }: IntlProviderProps) {
|
|
const currentLocale = useLocaleStore((state) => state.locale);
|
|
const setLocale = useLocaleStore((state) => state.setLocale);
|
|
const [activeLocale, setActiveLocale] = useState(currentLocale || initialLocale);
|
|
const [timeZone, setTimeZone] = useState<string>('UTC');
|
|
|
|
// Detect user's timezone on mount
|
|
useEffect(() => {
|
|
try {
|
|
const detectedTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
setTimeZone(detectedTimeZone);
|
|
} catch (error) {
|
|
// Fallback to UTC if detection fails
|
|
console.warn('Failed to detect timezone, using UTC:', error);
|
|
setTimeZone('UTC');
|
|
}
|
|
}, []);
|
|
|
|
// Sync initial locale with store on first mount only
|
|
useEffect(() => {
|
|
if (!currentLocale) {
|
|
setLocale(initialLocale);
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
|
|
// Switch locale immediately when store changes
|
|
useEffect(() => {
|
|
if (currentLocale) {
|
|
setActiveLocale(currentLocale);
|
|
}
|
|
}, [currentLocale]);
|
|
|
|
return (
|
|
<NextIntlClientProvider
|
|
locale={activeLocale}
|
|
messages={ALL_MESSAGES[activeLocale as keyof typeof ALL_MESSAGES]}
|
|
timeZone={timeZone}
|
|
>
|
|
{children}
|
|
</NextIntlClientProvider>
|
|
);
|
|
}
|