화면 다국어 처리
This commit is contained in:
@@ -553,10 +553,24 @@ export const setUserLocale = async (
|
||||
|
||||
const { locale } = req.body;
|
||||
|
||||
if (!locale || !["ko", "en", "ja", "zh"].includes(locale)) {
|
||||
if (!locale) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: "유효하지 않은 로케일입니다. (ko, en, ja, zh 중 선택)",
|
||||
message: "로케일이 필요합니다.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// language_master 테이블에서 유효한 언어 코드인지 확인
|
||||
const validLang = await queryOne<{ lang_code: string }>(
|
||||
"SELECT lang_code FROM language_master WHERE lang_code = $1 AND is_active = 'Y'",
|
||||
[locale]
|
||||
);
|
||||
|
||||
if (!validLang) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: `유효하지 않은 로케일입니다: ${locale}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -3103,6 +3117,23 @@ export const updateProfile = async (
|
||||
}
|
||||
|
||||
if (locale !== undefined) {
|
||||
// language_master 테이블에서 유효한 언어 코드인지 확인
|
||||
const validLang = await queryOne<{ lang_code: string }>(
|
||||
"SELECT lang_code FROM language_master WHERE lang_code = $1 AND is_active = 'Y'",
|
||||
[locale]
|
||||
);
|
||||
|
||||
if (!validLang) {
|
||||
res.status(400).json({
|
||||
result: false,
|
||||
error: {
|
||||
code: "INVALID_LOCALE",
|
||||
details: `유효하지 않은 로케일입니다: ${locale}`,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
updateFields.push(`locale = $${paramIndex}`);
|
||||
updateValues.push(locale);
|
||||
paramIndex++;
|
||||
|
||||
@@ -1189,6 +1189,7 @@ export class MultiLangService {
|
||||
/**
|
||||
* 배치 번역 조회 (회사별 우선순위 적용)
|
||||
* 우선순위: 회사별 키 > 공통 키(*)
|
||||
* 폴백: 요청 언어 번역이 없으면 KR 번역 사용
|
||||
*/
|
||||
async getBatchTranslations(
|
||||
params: BatchTranslationRequest
|
||||
@@ -1233,16 +1234,10 @@ export class MultiLangService {
|
||||
);
|
||||
|
||||
const result: Record<string, string> = {};
|
||||
|
||||
// 기본값으로 모든 키 설정
|
||||
params.langKeys.forEach((key) => {
|
||||
result[key] = key;
|
||||
});
|
||||
const processedKeys = new Set<string>();
|
||||
|
||||
// 우선순위 기반으로 번역 적용
|
||||
// priority가 낮은 것(회사별)이 먼저 오므로, 먼저 처리된 키는 덮어쓰지 않음
|
||||
const processedKeys = new Set<string>();
|
||||
|
||||
translations.forEach((translation) => {
|
||||
const langKey = translation.lang_key;
|
||||
if (params.langKeys.includes(langKey) && !processedKeys.has(langKey)) {
|
||||
@@ -1251,6 +1246,55 @@ export class MultiLangService {
|
||||
}
|
||||
});
|
||||
|
||||
// 번역이 없는 키들에 대해 KR 폴백 조회 (요청 언어가 KR이 아닌 경우)
|
||||
const missingKeys = params.langKeys.filter((key) => !processedKeys.has(key));
|
||||
|
||||
if (missingKeys.length > 0 && params.userLang !== "KR") {
|
||||
logger.info("KR 폴백 번역 조회 시작", { missingCount: missingKeys.length });
|
||||
|
||||
const fallbackPlaceholders = missingKeys.map((_, i) => `$${i + 3}`).join(", ");
|
||||
const fallbackTranslations = await query<{
|
||||
lang_text: string;
|
||||
lang_key: string;
|
||||
company_code: string;
|
||||
priority: number;
|
||||
}>(
|
||||
`SELECT mlt.lang_text, mlkm.lang_key, mlkm.company_code,
|
||||
CASE WHEN mlkm.company_code = $2 THEN 1 ELSE 2 END as priority
|
||||
FROM multi_lang_text mlt
|
||||
INNER JOIN multi_lang_key_master mlkm ON mlt.key_id = mlkm.key_id
|
||||
WHERE mlt.lang_code = 'KR'
|
||||
AND mlt.is_active = $1
|
||||
AND mlkm.lang_key IN (${fallbackPlaceholders})
|
||||
AND mlkm.company_code IN ($2, '*')
|
||||
AND mlkm.is_active = $1
|
||||
ORDER BY mlkm.lang_key ASC, priority ASC`,
|
||||
["Y", params.companyCode, ...missingKeys]
|
||||
);
|
||||
|
||||
// KR 폴백 적용
|
||||
const fallbackProcessed = new Set<string>();
|
||||
fallbackTranslations.forEach((translation) => {
|
||||
const langKey = translation.lang_key;
|
||||
if (!result[langKey] && !fallbackProcessed.has(langKey)) {
|
||||
result[langKey] = translation.lang_text;
|
||||
fallbackProcessed.add(langKey);
|
||||
}
|
||||
});
|
||||
|
||||
logger.info("KR 폴백 번역 조회 완료", {
|
||||
missingCount: missingKeys.length,
|
||||
foundFallback: fallbackTranslations.length,
|
||||
});
|
||||
}
|
||||
|
||||
// 여전히 없는 키는 키 자체를 반환 (최후의 폴백)
|
||||
params.langKeys.forEach((key) => {
|
||||
if (!result[key]) {
|
||||
result[key] = key;
|
||||
}
|
||||
});
|
||||
|
||||
logger.info("배치 번역 조회 완료", {
|
||||
totalKeys: params.langKeys.length,
|
||||
foundTranslations: translations.length,
|
||||
|
||||
Reference in New Issue
Block a user