Merge pull request '사용자 언어 변경 시 다국어 적용 즉시 적용' (#12) from sidebar/i18n into dev
Reviewed-on: http://39.117.244.52:3000/kjs/ERP-node/pulls/12
This commit is contained in:
commit
94ec47afe7
|
|
@ -18,13 +18,12 @@ export function LanguageSelector({ className }: LanguageSelectorProps) {
|
||||||
];
|
];
|
||||||
|
|
||||||
const handleLanguageChange = (newLang: string) => {
|
const handleLanguageChange = (newLang: string) => {
|
||||||
|
console.log("🎯 LanguageSelector 언어 변경:", newLang);
|
||||||
changeLang(newLang);
|
changeLang(newLang);
|
||||||
// 언어 변경 시 메뉴 컨텍스트가 자동으로 새로고침됨
|
|
||||||
console.log("언어 변경됨:", newLang);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select value={userLang} onValueChange={handleLanguageChange}>
|
<Select value={userLang || ""} onValueChange={handleLanguageChange}>
|
||||||
<SelectTrigger className={`${className}`}>
|
<SelectTrigger className={`${className}`}>
|
||||||
<SelectValue />
|
<SelectValue />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,51 @@ import { apiClient } from "@/lib/api/client";
|
||||||
let globalUserLang = "KR";
|
let globalUserLang = "KR";
|
||||||
let globalChangeLangCallback: ((lang: string) => void) | null = null;
|
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 } = {}) => {
|
export const useMultiLang = (options: { companyCode?: string } = {}) => {
|
||||||
const [userLang, setUserLang] = useState<string | null>(null); // null로 시작
|
const [userLang, setUserLang] = useState<string | null>(null); // null로 시작
|
||||||
const companyCode = options.companyCode || "*";
|
const companyCode = options.companyCode || "*";
|
||||||
|
|
||||||
// 전역 언어 상태 동기화 (무한 루프 방지)
|
// 🎯 효율적인 언어 변경 감지 (폴링 대신 콜백 등록)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 초기 로딩 시에만 동기화
|
// 언어 변경 콜백 등록
|
||||||
if (globalUserLang && globalUserLang !== userLang) {
|
const handleLanguageChange = (newLang: string) => {
|
||||||
setUserLang(globalUserLang);
|
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(() => {
|
useEffect(() => {
|
||||||
|
|
@ -126,8 +160,10 @@ export const useMultiLang = (options: { companyCode?: string } = {}) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 언어 변경 (무한 루프 방지)
|
// 🎯 효율적인 언어 변경 함수 (콜백 방식)
|
||||||
const changeLang = async (newLang: string) => {
|
const changeLang = async (newLang: string) => {
|
||||||
|
console.log("🚀 useMultiLang changeLang 호출:", { newLang, userLang });
|
||||||
|
|
||||||
// 같은 언어로 변경하려는 경우 무시
|
// 같은 언어로 변경하려는 경우 무시
|
||||||
if (newLang === userLang) {
|
if (newLang === userLang) {
|
||||||
console.log("🔄 같은 언어로 변경 시도 무시:", newLang);
|
console.log("🔄 같은 언어로 변경 시도 무시:", newLang);
|
||||||
|
|
@ -143,19 +179,17 @@ export const useMultiLang = (options: { companyCode?: string } = {}) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
// 전역 상태 먼저 업데이트
|
// 🎯 핵심: 즉시 모든 컴포넌트에 알림 (폴링 없이!)
|
||||||
globalUserLang = newLang;
|
notifyLanguageChange(newLang);
|
||||||
// 로컬 상태 업데이트
|
|
||||||
setUserLang(newLang);
|
console.log("✅ 언어 변경 완료 및 모든 컴포넌트에 즉시 알림:", newLang);
|
||||||
console.log("✅ 사용자 로케일 변경 성공:", newLang);
|
|
||||||
} else {
|
} else {
|
||||||
console.error("❌ 사용자 로케일 변경 실패:", response.data.message);
|
console.error("❌ 사용자 로케일 변경 실패:", response.data.message);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("❌ 사용자 로케일 변경 중 오류:", error);
|
console.error("❌ 사용자 로케일 변경 중 오류:", error);
|
||||||
// 오류 시에도 로컬 상태는 변경
|
// 오류 시에도 클라이언트 상태는 변경
|
||||||
globalUserLang = newLang;
|
notifyLanguageChange(newLang);
|
||||||
setUserLang(newLang);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
|
||||||
try {
|
try {
|
||||||
const response = await apiCall("GET", "/admin/departments");
|
const response = await apiCall("GET", "/admin/departments");
|
||||||
if (response.success && response.data) {
|
if (response.success && response.data) {
|
||||||
setDepartments(response.data);
|
setDepartments(response.data as Array<{ deptCode: string; deptName: string }>);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("부서 목록 로드 실패:", error);
|
console.error("부서 목록 로드 실패:", error);
|
||||||
|
|
@ -227,17 +227,14 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
|
||||||
|
|
||||||
console.log("프로필 업데이트 응답:", response);
|
console.log("프로필 업데이트 응답:", response);
|
||||||
|
|
||||||
if (response.result) {
|
if (response.success || (response as any).result) {
|
||||||
// locale이 변경된 경우 전역 변수와 localStorage 업데이트
|
// locale이 변경된 경우 전역 변수와 localStorage 업데이트
|
||||||
const localeChanged = modalState.formData.locale && modalState.formData.locale !== user.locale;
|
const localeChanged = modalState.formData.locale && modalState.formData.locale !== user.locale;
|
||||||
if (localeChanged) {
|
if (localeChanged) {
|
||||||
if (typeof window !== "undefined") {
|
// 🎯 useMultiLang의 콜백 시스템을 사용하여 모든 컴포넌트에 즉시 알림
|
||||||
// 전역 변수 업데이트
|
const { notifyLanguageChange } = await import("@/hooks/useMultiLang");
|
||||||
(window as any).__GLOBAL_USER_LANG = modalState.formData.locale;
|
notifyLanguageChange(modalState.formData.locale);
|
||||||
// localStorage 업데이트
|
console.log("🌍 사용자 locale 업데이트 (콜백 방식):", modalState.formData.locale);
|
||||||
localStorage.setItem("userLocale", modalState.formData.locale);
|
|
||||||
console.log("🌍 사용자 locale 업데이트:", modalState.formData.locale);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 성공: 사용자 정보 새로고침
|
// 성공: 사용자 정보 새로고침
|
||||||
|
|
@ -256,7 +253,7 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
|
||||||
}));
|
}));
|
||||||
showAlert("저장 완료", "프로필이 성공적으로 업데이트되었습니다.", "success");
|
showAlert("저장 완료", "프로필이 성공적으로 업데이트되었습니다.", "success");
|
||||||
} else {
|
} else {
|
||||||
throw new Error(response.message || "프로필 업데이트 실패");
|
throw new Error((response as any).message || "프로필 업데이트 실패");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("프로필 저장 실패:", error);
|
console.error("프로필 저장 실패:", error);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue