사용자 언어 변경 시 다국어 적용 즉시 적용

This commit is contained in:
hyeonsu 2025-09-01 17:07:50 +09:00
parent e18c78f40d
commit a91310d258
3 changed files with 57 additions and 27 deletions

View File

@ -18,13 +18,12 @@ export function LanguageSelector({ className }: LanguageSelectorProps) {
];
const handleLanguageChange = (newLang: string) => {
console.log("🎯 LanguageSelector 언어 변경:", newLang);
changeLang(newLang);
// 언어 변경 시 메뉴 컨텍스트가 자동으로 새로고침됨
console.log("언어 변경됨:", newLang);
};
return (
<Select value={userLang} onValueChange={handleLanguageChange}>
<Select value={userLang || ""} onValueChange={handleLanguageChange}>
<SelectTrigger className={`${className}`}>
<SelectValue />
</SelectTrigger>

View File

@ -5,17 +5,51 @@ import { apiClient } from "@/lib/api/client";
let globalUserLang = "KR";
let globalChangeLangCallback: ((lang: string) => void) | null = null;
// 🎯 효율적인 언어 변경 알림 시스템
const languageChangeCallbacks = new Set<(newLang: string) => void>();
// 전역 언어 변경 함수 (외부에서 호출 가능하도록 export)
export const notifyLanguageChange = (newLang: string) => {
globalUserLang = newLang;
(window as any).__GLOBAL_USER_LANG = newLang;
localStorage.setItem("userLocale", newLang);
localStorage.setItem("userLocaleLoaded", "true");
(window as any).__GLOBAL_USER_LOCALE_LOADED = true;
// 🗑️ 번역 캐시 초기화
(window as any).__TRANSLATION_CACHE = {};
// 모든 컴포넌트에 즉시 알림 (폴링 없이!)
languageChangeCallbacks.forEach((callback) => callback(newLang));
console.log("🔄 모든 컴포넌트에 언어 변경 알림:", newLang);
};
export const useMultiLang = (options: { companyCode?: string } = {}) => {
const [userLang, setUserLang] = useState<string | null>(null); // null로 시작
const companyCode = options.companyCode || "*";
// 전역 언어 상태 동기화 (무한 루프 방지)
// 🎯 효율적인 언어 변경 감지 (폴링 대신 콜백 등록)
useEffect(() => {
// 초기 로딩 시에만 동기화
if (globalUserLang && globalUserLang !== userLang) {
setUserLang(globalUserLang);
// 언어 변경 콜백 등록
const handleLanguageChange = (newLang: string) => {
console.log("🔄 언어 변경 감지 (즉시):", { from: userLang, to: newLang });
setUserLang(newLang);
};
languageChangeCallbacks.add(handleLanguageChange);
// 초기 언어 설정
const currentLang = (window as any).__GLOBAL_USER_LANG || localStorage.getItem("userLocale") || globalUserLang;
if (currentLang && currentLang !== userLang) {
setUserLang(currentLang);
}
}, []); // 의존성 배열을 비워서 한 번만 실행
// 클린업: 콜백 제거
return () => {
languageChangeCallbacks.delete(handleLanguageChange);
};
}, []); // 한 번만 등록
// 언어 변경 시 전역 콜백 호출 (무한 루프 방지)
useEffect(() => {
@ -126,8 +160,10 @@ export const useMultiLang = (options: { companyCode?: string } = {}) => {
}
};
// 언어 변경 (무한 루프 방지)
// 🎯 효율적인 언어 변경 함수 (콜백 방식)
const changeLang = async (newLang: string) => {
console.log("🚀 useMultiLang changeLang 호출:", { newLang, userLang });
// 같은 언어로 변경하려는 경우 무시
if (newLang === userLang) {
console.log("🔄 같은 언어로 변경 시도 무시:", newLang);
@ -143,19 +179,17 @@ export const useMultiLang = (options: { companyCode?: string } = {}) => {
});
if (response.data.success) {
// 전역 상태 먼저 업데이트
globalUserLang = newLang;
// 로컬 상태 업데이트
setUserLang(newLang);
console.log("✅ 사용자 로케일 변경 성공:", newLang);
// 🎯 핵심: 즉시 모든 컴포넌트에 알림 (폴링 없이!)
notifyLanguageChange(newLang);
console.log("✅ 언어 변경 완료 및 모든 컴포넌트에 즉시 알림:", newLang);
} else {
console.error("❌ 사용자 로케일 변경 실패:", response.data.message);
}
} catch (error) {
console.error("❌ 사용자 로케일 변경 중 오류:", error);
// 오류 시에도 로컬 상태는 변경
globalUserLang = newLang;
setUserLang(newLang);
// 오류 시에도 클라이언트 상태는 변경
notifyLanguageChange(newLang);
}
};

View File

@ -68,7 +68,7 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
try {
const response = await apiCall("GET", "/admin/departments");
if (response.success && response.data) {
setDepartments(response.data);
setDepartments(response.data as Array<{ deptCode: string; deptName: string }>);
}
} catch (error) {
console.error("부서 목록 로드 실패:", error);
@ -227,17 +227,14 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
console.log("프로필 업데이트 응답:", response);
if (response.result) {
if (response.success || (response as any).result) {
// locale이 변경된 경우 전역 변수와 localStorage 업데이트
const localeChanged = modalState.formData.locale && modalState.formData.locale !== user.locale;
if (localeChanged) {
if (typeof window !== "undefined") {
// 전역 변수 업데이트
(window as any).__GLOBAL_USER_LANG = modalState.formData.locale;
// localStorage 업데이트
localStorage.setItem("userLocale", modalState.formData.locale);
console.log("🌍 사용자 locale 업데이트:", modalState.formData.locale);
}
// 🎯 useMultiLang의 콜백 시스템을 사용하여 모든 컴포넌트에 즉시 알림
const { notifyLanguageChange } = await import("@/hooks/useMultiLang");
notifyLanguageChange(modalState.formData.locale);
console.log("🌍 사용자 locale 업데이트 (콜백 방식):", modalState.formData.locale);
}
// 성공: 사용자 정보 새로고침
@ -256,7 +253,7 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
}));
showAlert("저장 완료", "프로필이 성공적으로 업데이트되었습니다.", "success");
} else {
throw new Error(response.message || "프로필 업데이트 실패");
throw new Error((response as any).message || "프로필 업데이트 실패");
}
} catch (error) {
console.error("프로필 저장 실패:", error);