Dynamic Language Switching
User harus bisa mengganti bahasa kapan saja tanpa reload halaman. Pilihan bahasa harus di-persist agar tidak hilang saat kembali.
Language Switcher Component
import { useTranslation } from "react-i18next";
const LANGUAGES = [
{ code: "id", label: "Bahasa Indonesia", flag: "🇮🇩" },
{ code: "en", label: "English", flag: "🇺🇸" },
{ code: "ja", label: "日本語", flag: "🇯🇵" },
{ code: "ar", label: "العربية", flag: "🇸🇦" },
];
function LanguageSwitcher() {
const { i18n } = useTranslation();
const changeLanguage = async (code) => {
await i18n.changeLanguage(code);
document.documentElement.lang = code;
document.documentElement.dir =
["ar", "he", "fa"].includes(code) ? "rtl" : "ltr";
localStorage.setItem("preferred-language", code);
};
return (
<select
value={i18n.language}
onChange={(e) => changeLanguage(e.target.value)}
>
{LANGUAGES.map(({ code, label, flag }) => (
<option key={code} value={code}>
{flag} {label}
</option>
))}
</select>
);
}
Persistence Strategy
// Urutan deteksi bahasa (priority)
// 1. URL parameter (?lng=id)
// 2. localStorage
// 3. Cookie
// 4. Navigator language (browser setting)
// 5. Fallback language
// i18next LanguageDetector sudah handle ini
i18n.use(LanguageDetector).init({
detection: {
order: ["querystring", "localStorage", "cookie", "navigator"],
lookupQuerystring: "lng",
lookupLocalStorage: "i18nextLng",
lookupCookie: "i18next",
caches: ["localStorage", "cookie"],
},
});
URL-based Language (Next.js)
// Strategi URL: /en/about, /id/about
// next.config.js
module.exports = {
i18n: {
locales: ["en", "id", "ja"],
defaultLocale: "id",
localeDetection: true,
},
};
// Middleware: redirect berdasarkan Accept-Language
// middleware.ts
import createMiddleware from "next-intl/middleware";
export default createMiddleware({
locales: ["en", "id", "ja"],
defaultLocale: "id",
localePrefix: "as-needed", // /about untuk default, /en/about untuk lainnya
});
Sync Language ke Server
// Kirim preferensi bahasa ke backend untuk
// email notifications, push notifications, dll
async function updateUserLanguage(locale) {
// Update frontend
await i18n.changeLanguage(locale);
// Persist ke server
await fetch("/api/user/preferences", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ locale }),
});
}
// Laravel: simpan di users table
// migration: $table->string("locale")->default("id");
// Middleware: App::setLocale($user->locale);
Loading State saat Switch
function LanguageSwitcher() {
const { i18n } = useTranslation();
const [loading, setLoading] = useState(false);
const changeLanguage = async (code) => {
setLoading(true);
try {
await i18n.changeLanguage(code);
} finally {
setLoading(false);
}
};
return (
<select disabled={loading} onChange={(e) => changeLanguage(e.target.value)}>
{/* options */}
</select>
);
}