feat(i18n): Complete internationalization with timezone fixes and language switching

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.
This commit is contained in:
Matthieu MALVACHE
2026-01-08 04:29:19 +01:00
committed by Matthieu MALVACHE
parent b2b479359f
commit 0d68851b63
20 changed files with 638 additions and 192 deletions
+4 -5
View File
@@ -1,7 +1,7 @@
"use client";
import { useState, useEffect, useRef } from "react";
import { useRouter, useParams } from "next/navigation";
import { useRouter } from "@/i18n/navigation";
import { useTranslations } from "next-intl";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
@@ -11,7 +11,6 @@ import { Mail, AlertCircle, Loader2, X } from "lucide-react";
export default function LoginPage() {
const router = useRouter();
const params = useParams();
const t = useTranslations("login");
const { login, isLoading, error, clearError, isAuthenticated } = useAuthStore();
const { appName, jmapServerUrl: serverUrl, isLoading: configLoading, error: configError } = useConfig();
@@ -53,9 +52,9 @@ export default function LoginPage() {
useEffect(() => {
if (isAuthenticated) {
router.push(`/${params.locale}`);
router.push('/');
}
}, [isAuthenticated, router, params.locale]);
}, [isAuthenticated, router]);
useEffect(() => {
clearError();
@@ -229,7 +228,7 @@ export default function LoginPage() {
if (success) {
saveUsername(formData.username);
router.push(`/${params.locale}`);
router.push('/');
}
};