forked from baron/baron-sso
feat: i18n 개선 및 userfront 로그인/로케일 보완
This commit is contained in:
57
devfront/src/components/common/LanguageSelector.tsx
Normal file
57
devfront/src/components/common/LanguageSelector.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import { useState } from "react";
|
||||
import { t } from "../../lib/i18n";
|
||||
|
||||
const LOCALE_STORAGE_KEY = "locale";
|
||||
const SUPPORTED_LOCALES = ["ko", "en"] as const;
|
||||
|
||||
type Locale = (typeof SUPPORTED_LOCALES)[number];
|
||||
|
||||
function resolveLocale(): Locale {
|
||||
if (typeof window === "undefined") {
|
||||
return "ko";
|
||||
}
|
||||
|
||||
const stored = window.localStorage.getItem(LOCALE_STORAGE_KEY);
|
||||
if (stored === "ko" || stored === "en") {
|
||||
return stored;
|
||||
}
|
||||
|
||||
const pathLocale = window.location.pathname.split("/")[1];
|
||||
if (pathLocale === "ko" || pathLocale === "en") {
|
||||
return pathLocale;
|
||||
}
|
||||
|
||||
const browserLang = window.navigator.language.toLowerCase();
|
||||
return browserLang.startsWith("ko") ? "ko" : "en";
|
||||
}
|
||||
|
||||
function LanguageSelector() {
|
||||
const [locale, setLocale] = useState<Locale>(resolveLocale());
|
||||
|
||||
const handleChange = (next: Locale) => {
|
||||
if (next === locale) {
|
||||
return;
|
||||
}
|
||||
window.localStorage.setItem(LOCALE_STORAGE_KEY, next);
|
||||
setLocale(next);
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
return (
|
||||
<select
|
||||
value={locale}
|
||||
onChange={(event) => handleChange(event.target.value as Locale)}
|
||||
className="rounded-full border border-border bg-transparent px-3 py-2 text-sm text-muted-foreground transition hover:bg-muted/20"
|
||||
aria-label={t("ui.common.language", "언어")}
|
||||
>
|
||||
<option value="ko">
|
||||
{t("ui.common.language_ko", "한국어")}
|
||||
</option>
|
||||
<option value="en">
|
||||
{t("ui.common.language_en", "English")}
|
||||
</option>
|
||||
</select>
|
||||
);
|
||||
}
|
||||
|
||||
export default LanguageSelector;
|
||||
@@ -2,6 +2,7 @@ import { BadgeCheck, Moon, ShieldHalf, Sun } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { NavLink, Outlet } from "react-router-dom";
|
||||
import { t } from "../../lib/i18n";
|
||||
import LanguageSelector from "../common/LanguageSelector";
|
||||
import { Toaster } from "../ui/toaster";
|
||||
|
||||
const navItems = [
|
||||
@@ -105,6 +106,7 @@ function AppLayout() {
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<LanguageSelector />
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleTheme}
|
||||
|
||||
Reference in New Issue
Block a user