"use client"; import React, { createContext, useContext, useState, useEffect, useMemo, ReactNode } from "react"; import { apiClient } from "@/lib/api/client"; import { useMultiLang } from "@/hooks/useMultiLang"; import { ComponentData } from "@/types/screen"; interface ScreenMultiLangContextValue { translations: Record; loading: boolean; getTranslatedText: (langKey: string | undefined, fallback: string) => string; } const ScreenMultiLangContext = createContext(null); interface ScreenMultiLangProviderProps { children: ReactNode; components: ComponentData[]; companyCode?: string; } /** * 화면 컴포넌트들의 다국어 번역을 제공하는 Provider * 모든 langKey를 수집하여 한 번에 배치 조회하고, 하위 컴포넌트에서 번역 텍스트를 사용할 수 있게 함 */ export const ScreenMultiLangProvider: React.FC = ({ children, components, companyCode = "*", }) => { const { userLang } = useMultiLang(); const [translations, setTranslations] = useState>({}); const [loading, setLoading] = useState(false); // 모든 컴포넌트에서 langKey 수집 const langKeys = useMemo(() => { const keys: string[] = []; const collectLangKeys = (comps: ComponentData[]) => { comps.forEach((comp) => { // 컴포넌트 라벨의 langKey if ((comp as any).langKey) { keys.push((comp as any).langKey); } // componentConfig 내의 langKey (버튼 텍스트 등) if ((comp as any).componentConfig?.langKey) { keys.push((comp as any).componentConfig.langKey); } // properties 내의 langKey (레거시) if ((comp as any).properties?.langKey) { keys.push((comp as any).properties.langKey); } // 테이블 리스트 컬럼의 langKey 수집 if ((comp as any).componentConfig?.columns) { (comp as any).componentConfig.columns.forEach((col: any) => { if (col.langKey) { keys.push(col.langKey); } }); } // 분할패널 좌측/우측 제목 langKey 수집 const config = (comp as any).componentConfig; if (config?.leftPanel?.langKey) { keys.push(config.leftPanel.langKey); } if (config?.rightPanel?.langKey) { keys.push(config.rightPanel.langKey); } // 분할패널 좌측/우측 컬럼 langKey 수집 if (config?.leftPanel?.columns) { config.leftPanel.columns.forEach((col: any) => { if (col.langKey) { keys.push(col.langKey); } }); } if (config?.rightPanel?.columns) { config.rightPanel.columns.forEach((col: any) => { if (col.langKey) { keys.push(col.langKey); } }); } // 추가 탭 langKey 수집 if (config?.additionalTabs) { config.additionalTabs.forEach((tab: any) => { if (tab.langKey) { keys.push(tab.langKey); } if (tab.titleLangKey) { keys.push(tab.titleLangKey); } if (tab.columns) { tab.columns.forEach((col: any) => { if (col.langKey) { keys.push(col.langKey); } }); } }); } // 자식 컴포넌트 재귀 처리 if ((comp as any).children) { collectLangKeys((comp as any).children); } }); }; collectLangKeys(components); return [...new Set(keys)]; // 중복 제거 }, [components]); // langKey가 있으면 배치 조회 useEffect(() => { const loadTranslations = async () => { if (langKeys.length === 0 || !userLang) { return; } setLoading(true); try { console.log("🌐 [ScreenMultiLang] 다국어 배치 로드:", { langKeys: langKeys.length, userLang, companyCode }); const response = await apiClient.post( "/multilang/batch", { langKeys }, { params: { userLang, companyCode, }, } ); if (response.data?.success && response.data?.data) { console.log("✅ [ScreenMultiLang] 다국어 로드 완료:", Object.keys(response.data.data).length, "개"); setTranslations(response.data.data); } } catch (error) { console.error("❌ [ScreenMultiLang] 다국어 로드 실패:", error); } finally { setLoading(false); } }; loadTranslations(); }, [langKeys, userLang, companyCode]); // 번역 텍스트 가져오기 헬퍼 const getTranslatedText = (langKey: string | undefined, fallback: string): string => { if (!langKey) return fallback; return translations[langKey] || fallback; }; const value = useMemo( () => ({ translations, loading, getTranslatedText, }), [translations, loading] ); return {children}; }; /** * 화면 다국어 컨텍스트 사용 훅 */ export const useScreenMultiLang = (): ScreenMultiLangContextValue => { const context = useContext(ScreenMultiLangContext); if (!context) { // 컨텍스트가 없으면 기본값 반환 (fallback) return { translations: {}, loading: false, getTranslatedText: (_, fallback) => fallback, }; } return context; };