ERP-node/backend-node/src/services/multilangService.ts

869 lines
26 KiB
TypeScript
Raw Normal View History

import { query, queryOne, transaction } from "../database/db";
2025-08-25 15:12:31 +09:00
import { logger } from "../utils/logger";
import {
Language,
LangKey,
LangText,
CreateLanguageRequest,
UpdateLanguageRequest,
CreateLangKeyRequest,
UpdateLangKeyRequest,
SaveLangTextsRequest,
GetLangKeysParams,
GetUserTextParams,
BatchTranslationRequest,
ApiResponse,
} from "../types/multilang";
2025-09-01 11:00:38 +09:00
export class MultiLangService {
constructor() {}
2025-08-25 15:12:31 +09:00
/**
*
*/
async getLanguages(): Promise<Language[]> {
try {
logger.info("언어 목록 조회 시작");
const languages = await query<{
lang_code: string;
lang_name: string;
lang_native: string | null;
is_active: string | null;
sort_order: number | null;
created_date: Date | null;
created_by: string | null;
updated_date: Date | null;
updated_by: string | null;
}>(
`SELECT lang_code, lang_name, lang_native, is_active, sort_order,
created_date, created_by, updated_date, updated_by
FROM language_master
ORDER BY sort_order ASC, lang_code ASC`
);
2025-09-01 11:00:38 +09:00
const mappedLanguages: Language[] = languages.map((lang) => ({
langCode: lang.lang_code,
langName: lang.lang_name,
langNative: lang.lang_native || "",
2025-09-01 11:00:38 +09:00
isActive: lang.is_active || "N",
sortOrder: lang.sort_order ?? undefined,
createdDate: lang.created_date || undefined,
createdBy: lang.created_by || undefined,
updatedDate: lang.updated_date || undefined,
updatedBy: lang.updated_by || undefined,
2025-08-25 15:12:31 +09:00
}));
2025-09-01 11:00:38 +09:00
logger.info(`언어 목록 조회 완료: ${mappedLanguages.length}`);
return mappedLanguages;
2025-08-25 15:12:31 +09:00
} catch (error) {
logger.error("언어 목록 조회 중 오류 발생:", error);
throw new Error(
`언어 목록 조회 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async createLanguage(languageData: CreateLanguageRequest): Promise<Language> {
try {
logger.info("언어 생성 시작", { languageData });
// 중복 체크
const existingLanguage = await queryOne<{ lang_code: string }>(
`SELECT lang_code FROM language_master WHERE lang_code = $1`,
[languageData.langCode]
);
2025-09-01 11:00:38 +09:00
if (existingLanguage) {
2025-08-25 15:12:31 +09:00
throw new Error(
`이미 존재하는 언어 코드입니다: ${languageData.langCode}`
);
}
// 언어 생성
const createdLanguage = await queryOne<{
lang_code: string;
lang_name: string;
lang_native: string | null;
is_active: string | null;
sort_order: number | null;
created_date: Date | null;
created_by: string | null;
updated_date: Date | null;
updated_by: string | null;
}>(
`INSERT INTO language_master
(lang_code, lang_name, lang_native, is_active, sort_order, created_by, updated_by)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING *`,
[
languageData.langCode,
languageData.langName,
languageData.langNative,
languageData.isActive || "Y",
languageData.sortOrder || 0,
languageData.createdBy || "system",
languageData.updatedBy || "system",
]
);
2025-08-25 15:12:31 +09:00
logger.info("언어 생성 완료", { langCode: createdLanguage!.lang_code });
2025-08-25 15:12:31 +09:00
return {
langCode: createdLanguage!.lang_code,
langName: createdLanguage!.lang_name,
langNative: createdLanguage!.lang_native || "",
isActive: createdLanguage!.is_active || "N",
sortOrder: createdLanguage!.sort_order ?? undefined,
createdDate: createdLanguage!.created_date || undefined,
createdBy: createdLanguage!.created_by || undefined,
updatedDate: createdLanguage!.updated_date || undefined,
updatedBy: createdLanguage!.updated_by || undefined,
2025-08-25 15:12:31 +09:00
};
} catch (error) {
logger.error("언어 생성 중 오류 발생:", error);
throw new Error(
`언어 생성 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async updateLanguage(
langCode: string,
languageData: UpdateLanguageRequest
): Promise<Language> {
try {
logger.info("언어 수정 시작", { langCode, languageData });
// 기존 언어 확인
const existingLanguage = await queryOne<{ lang_code: string }>(
`SELECT lang_code FROM language_master WHERE lang_code = $1`,
[langCode]
);
2025-08-25 15:12:31 +09:00
2025-09-01 11:00:38 +09:00
if (!existingLanguage) {
2025-08-25 15:12:31 +09:00
throw new Error(`언어를 찾을 수 없습니다: ${langCode}`);
}
// 동적 UPDATE 쿼리 생성
const updates: string[] = [];
const values: any[] = [];
let paramIndex = 1;
if (languageData.langName) {
updates.push(`lang_name = $${paramIndex++}`);
values.push(languageData.langName);
}
if (languageData.langNative) {
updates.push(`lang_native = $${paramIndex++}`);
values.push(languageData.langNative);
}
if (languageData.isActive) {
updates.push(`is_active = $${paramIndex++}`);
values.push(languageData.isActive);
}
if (languageData.sortOrder !== undefined) {
updates.push(`sort_order = $${paramIndex++}`);
values.push(languageData.sortOrder);
}
updates.push(`updated_by = $${paramIndex++}`);
values.push(languageData.updatedBy || "system");
values.push(langCode); // WHERE 조건용
2025-08-25 15:12:31 +09:00
// 언어 수정
const updatedLanguage = await queryOne<{
lang_code: string;
lang_name: string;
lang_native: string | null;
is_active: string | null;
sort_order: number | null;
created_date: Date | null;
created_by: string | null;
updated_date: Date | null;
updated_by: string | null;
}>(
`UPDATE language_master SET ${updates.join(", ")}
WHERE lang_code = $${paramIndex}
RETURNING *`,
values
);
2025-08-25 15:12:31 +09:00
logger.info("언어 수정 완료", { langCode });
return {
langCode: updatedLanguage!.lang_code,
langName: updatedLanguage!.lang_name,
langNative: updatedLanguage!.lang_native || "",
isActive: updatedLanguage!.is_active || "N",
sortOrder: updatedLanguage!.sort_order ?? undefined,
createdDate: updatedLanguage!.created_date || undefined,
createdBy: updatedLanguage!.created_by || undefined,
updatedDate: updatedLanguage!.updated_date || undefined,
updatedBy: updatedLanguage!.updated_by || undefined,
2025-08-25 15:12:31 +09:00
};
} catch (error) {
logger.error("언어 수정 중 오류 발생:", error);
throw new Error(
`언어 수정 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async toggleLanguage(langCode: string): Promise<string> {
try {
logger.info("언어 상태 토글 시작", { langCode });
2025-09-01 11:00:38 +09:00
// 현재 언어 조회
const currentLanguage = await queryOne<{ is_active: string | null }>(
`SELECT is_active FROM language_master WHERE lang_code = $1`,
[langCode]
);
2025-08-25 15:12:31 +09:00
2025-09-01 11:00:38 +09:00
if (!currentLanguage) {
2025-08-25 15:12:31 +09:00
throw new Error(`언어를 찾을 수 없습니다: ${langCode}`);
}
2025-09-01 11:00:38 +09:00
const newStatus = currentLanguage.is_active === "Y" ? "N" : "Y";
2025-08-25 15:12:31 +09:00
// 상태 업데이트
await query(
`UPDATE language_master
SET is_active = $1, updated_by = $2
WHERE lang_code = $3`,
[newStatus, "system", langCode]
);
2025-08-25 15:12:31 +09:00
const result = newStatus === "Y" ? "활성화" : "비활성화";
logger.info("언어 상태 토글 완료", { langCode, result });
return result;
} catch (error) {
logger.error("언어 상태 토글 중 오류 발생:", error);
throw new Error(
`언어 상태 토글 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async getLangKeys(params: GetLangKeysParams): Promise<LangKey[]> {
try {
logger.info("다국어 키 목록 조회 시작", { params });
const whereConditions: string[] = [];
const values: any[] = [];
let paramIndex = 1;
2025-08-25 15:12:31 +09:00
// 회사 코드 필터
if (params.companyCode) {
whereConditions.push(`company_code = $${paramIndex++}`);
values.push(params.companyCode);
2025-08-25 15:12:31 +09:00
}
// 메뉴 코드 필터
if (params.menuCode) {
whereConditions.push(`menu_name = $${paramIndex++}`);
values.push(params.menuCode);
2025-08-25 15:12:31 +09:00
}
// 검색 조건 (OR)
2025-08-25 15:12:31 +09:00
if (params.searchText) {
whereConditions.push(
`(lang_key ILIKE $${paramIndex} OR description ILIKE $${paramIndex} OR menu_name ILIKE $${paramIndex})`
);
values.push(`%${params.searchText}%`);
paramIndex++;
2025-08-25 15:12:31 +09:00
}
const whereClause =
whereConditions.length > 0
? `WHERE ${whereConditions.join(" AND ")}`
: "";
const langKeys = await query<{
key_id: number;
company_code: string;
menu_name: string | null;
lang_key: string;
description: string | null;
is_active: string | null;
created_date: Date | null;
created_by: string | null;
updated_date: Date | null;
updated_by: string | null;
}>(
`SELECT key_id, company_code, menu_name, lang_key, description, is_active,
created_date, created_by, updated_date, updated_by
FROM multi_lang_key_master
${whereClause}
ORDER BY company_code ASC, menu_name ASC, lang_key ASC`,
values
);
2025-08-25 15:12:31 +09:00
2025-09-01 11:00:38 +09:00
const mappedKeys: LangKey[] = langKeys.map((key) => ({
keyId: key.key_id,
companyCode: key.company_code,
menuName: key.menu_name || undefined,
langKey: key.lang_key,
description: key.description || undefined,
isActive: key.is_active || "Y",
createdDate: key.created_date || undefined,
createdBy: key.created_by || undefined,
updatedDate: key.updated_date || undefined,
updatedBy: key.updated_by || undefined,
2025-08-25 15:12:31 +09:00
}));
2025-09-01 11:00:38 +09:00
logger.info(`다국어 키 목록 조회 완료: ${mappedKeys.length}`);
return mappedKeys;
2025-08-25 15:12:31 +09:00
} catch (error) {
logger.error("다국어 키 목록 조회 중 오류 발생:", error);
throw new Error(
`다국어 키 목록 조회 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async getLangTexts(keyId: number): Promise<LangText[]> {
try {
logger.info("다국어 텍스트 조회 시작", { keyId });
const langTexts = await query<{
text_id: number;
key_id: number;
lang_code: string;
lang_text: string;
is_active: string | null;
created_date: Date | null;
created_by: string | null;
updated_date: Date | null;
updated_by: string | null;
}>(
`SELECT text_id, key_id, lang_code, lang_text, is_active,
created_date, created_by, updated_date, updated_by
FROM multi_lang_text
WHERE key_id = $1 AND is_active = $2
ORDER BY lang_code ASC`,
[keyId, "Y"]
);
2025-09-01 11:00:38 +09:00
const mappedTexts: LangText[] = langTexts.map((text) => ({
textId: text.text_id,
keyId: text.key_id,
langCode: text.lang_code,
langText: text.lang_text,
isActive: text.is_active || "Y",
createdDate: text.created_date || undefined,
createdBy: text.created_by || undefined,
updatedDate: text.updated_date || undefined,
updatedBy: text.updated_by || undefined,
2025-08-25 15:12:31 +09:00
}));
2025-09-01 11:00:38 +09:00
logger.info(`다국어 텍스트 조회 완료: ${mappedTexts.length}`);
return mappedTexts;
2025-08-25 15:12:31 +09:00
} catch (error) {
logger.error("다국어 텍스트 조회 중 오류 발생:", error);
throw new Error(
`다국어 텍스트 조회 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async createLangKey(keyData: CreateLangKeyRequest): Promise<number> {
try {
logger.info("다국어 키 생성 시작", { keyData });
// 중복 체크
const existingKey = await queryOne<{ key_id: number }>(
`SELECT key_id FROM multi_lang_key_master
WHERE company_code = $1 AND lang_key = $2`,
[keyData.companyCode, keyData.langKey]
);
2025-09-01 11:00:38 +09:00
if (existingKey) {
2025-08-25 15:12:31 +09:00
throw new Error(
`동일한 회사에 이미 존재하는 언어키입니다: ${keyData.langKey}`
);
}
// 다국어 키 생성
const createdKey = await queryOne<{ key_id: number }>(
`INSERT INTO multi_lang_key_master
(company_code, menu_name, lang_key, description, is_active, created_by, updated_by)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING key_id`,
[
keyData.companyCode,
keyData.menuName || null,
keyData.langKey,
keyData.description || null,
keyData.isActive || "Y",
keyData.createdBy || "system",
keyData.updatedBy || "system",
]
);
2025-09-01 11:00:38 +09:00
logger.info("다국어 키 생성 완료", {
keyId: createdKey!.key_id,
2025-09-01 11:00:38 +09:00
langKey: keyData.langKey,
});
return createdKey!.key_id;
2025-08-25 15:12:31 +09:00
} catch (error) {
logger.error("다국어 키 생성 중 오류 발생:", error);
throw new Error(
`다국어 키 생성 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async updateLangKey(
keyId: number,
keyData: UpdateLangKeyRequest
): Promise<void> {
try {
logger.info("다국어 키 수정 시작", { keyId, keyData });
// 기존 키 확인
const existingKey = await queryOne<{ key_id: number }>(
`SELECT key_id FROM multi_lang_key_master WHERE key_id = $1`,
[keyId]
);
2025-08-25 15:12:31 +09:00
2025-09-01 11:00:38 +09:00
if (!existingKey) {
2025-08-25 15:12:31 +09:00
throw new Error(`다국어 키를 찾을 수 없습니다: ${keyId}`);
}
// 중복 체크 (자신을 제외하고)
if (keyData.companyCode && keyData.langKey) {
const duplicateKey = await queryOne<{ key_id: number }>(
`SELECT key_id FROM multi_lang_key_master
WHERE company_code = $1 AND lang_key = $2 AND key_id != $3`,
[keyData.companyCode, keyData.langKey, keyId]
);
2025-09-01 11:00:38 +09:00
if (duplicateKey) {
2025-08-25 15:12:31 +09:00
throw new Error(
`동일한 회사에 이미 존재하는 언어키입니다: ${keyData.langKey}`
);
}
}
// 동적 UPDATE 쿼리 생성
const updates: string[] = [];
const values: any[] = [];
let paramIndex = 1;
if (keyData.companyCode) {
updates.push(`company_code = $${paramIndex++}`);
values.push(keyData.companyCode);
}
if (keyData.menuName !== undefined) {
updates.push(`menu_name = $${paramIndex++}`);
values.push(keyData.menuName);
}
if (keyData.langKey) {
updates.push(`lang_key = $${paramIndex++}`);
values.push(keyData.langKey);
}
if (keyData.description !== undefined) {
updates.push(`description = $${paramIndex++}`);
values.push(keyData.description);
}
updates.push(`updated_by = $${paramIndex++}`);
values.push(keyData.updatedBy || "system");
values.push(keyId); // WHERE 조건용
2025-08-25 15:12:31 +09:00
// 다국어 키 수정
await query(
`UPDATE multi_lang_key_master SET ${updates.join(", ")}
WHERE key_id = $${paramIndex}`,
values
);
2025-08-25 15:12:31 +09:00
logger.info("다국어 키 수정 완료", { keyId });
} catch (error) {
logger.error("다국어 키 수정 중 오류 발생:", error);
throw new Error(
`다국어 키 수정 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async deleteLangKey(keyId: number): Promise<void> {
try {
logger.info("다국어 키 삭제 시작", { keyId });
// 기존 키 확인
const existingKey = await queryOne<{ key_id: number }>(
`SELECT key_id FROM multi_lang_key_master WHERE key_id = $1`,
[keyId]
);
2025-08-25 15:12:31 +09:00
2025-09-01 11:00:38 +09:00
if (!existingKey) {
2025-08-25 15:12:31 +09:00
throw new Error(`다국어 키를 찾을 수 없습니다: ${keyId}`);
}
2025-09-01 11:00:38 +09:00
// 트랜잭션으로 키와 연관된 텍스트 모두 삭제
await transaction(async (client) => {
2025-08-25 15:12:31 +09:00
// 관련된 다국어 텍스트 삭제
await client.query(`DELETE FROM multi_lang_text WHERE key_id = $1`, [
keyId,
]);
2025-08-25 15:12:31 +09:00
// 다국어 키 삭제
await client.query(
`DELETE FROM multi_lang_key_master WHERE key_id = $1`,
[keyId]
);
2025-09-01 11:00:38 +09:00
});
logger.info("다국어 키 삭제 완료", { keyId });
2025-08-25 15:12:31 +09:00
} catch (error) {
logger.error("다국어 키 삭제 중 오류 발생:", error);
throw new Error(
`다국어 키 삭제 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async toggleLangKey(keyId: number): Promise<string> {
try {
logger.info("다국어 키 상태 토글 시작", { keyId });
2025-09-01 11:00:38 +09:00
// 현재 키 조회
const currentKey = await queryOne<{ is_active: string | null }>(
`SELECT is_active FROM multi_lang_key_master WHERE key_id = $1`,
[keyId]
);
2025-08-25 15:12:31 +09:00
2025-09-01 11:00:38 +09:00
if (!currentKey) {
2025-08-25 15:12:31 +09:00
throw new Error(`다국어 키를 찾을 수 없습니다: ${keyId}`);
}
2025-09-01 11:00:38 +09:00
const newStatus = currentKey.is_active === "Y" ? "N" : "Y";
2025-08-25 15:12:31 +09:00
// 상태 업데이트
await query(
`UPDATE multi_lang_key_master
SET is_active = $1, updated_by = $2
WHERE key_id = $3`,
[newStatus, "system", keyId]
);
2025-08-25 15:12:31 +09:00
const result = newStatus === "Y" ? "활성화" : "비활성화";
logger.info("다국어 키 상태 토글 완료", { keyId, result });
return result;
} catch (error) {
logger.error("다국어 키 상태 토글 중 오류 발생:", error);
throw new Error(
`다국어 키 상태 토글 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
* /
*/
async saveLangTexts(
keyId: number,
textData: SaveLangTextsRequest
): Promise<void> {
try {
logger.info("다국어 텍스트 저장 시작", {
keyId,
textCount: textData.texts.length,
});
// 기존 키 확인
const existingKey = await queryOne<{ key_id: number }>(
`SELECT key_id FROM multi_lang_key_master WHERE key_id = $1`,
[keyId]
);
2025-08-25 15:12:31 +09:00
2025-09-01 11:00:38 +09:00
if (!existingKey) {
2025-08-25 15:12:31 +09:00
throw new Error(`다국어 키를 찾을 수 없습니다: ${keyId}`);
}
2025-09-01 11:00:38 +09:00
// 트랜잭션으로 기존 텍스트 삭제 후 새로 생성
await transaction(async (client) => {
2025-08-25 15:12:31 +09:00
// 기존 텍스트 삭제
await client.query(`DELETE FROM multi_lang_text WHERE key_id = $1`, [
keyId,
]);
2025-08-25 15:12:31 +09:00
// 새로운 텍스트 삽입
2025-09-01 11:00:38 +09:00
if (textData.texts.length > 0) {
for (const text of textData.texts) {
await client.query(
`INSERT INTO multi_lang_text
(key_id, lang_code, lang_text, is_active, created_by, updated_by)
VALUES ($1, $2, $3, $4, $5, $6)`,
[
keyId,
text.langCode,
text.langText,
text.isActive || "Y",
text.createdBy || "system",
text.updatedBy || "system",
]
);
}
2025-08-25 15:12:31 +09:00
}
2025-09-01 11:00:38 +09:00
});
2025-08-25 15:12:31 +09:00
2025-09-01 11:00:38 +09:00
logger.info("다국어 텍스트 저장 완료", {
keyId,
savedCount: textData.texts.length,
});
2025-08-25 15:12:31 +09:00
} catch (error) {
logger.error("다국어 텍스트 저장 중 오류 발생:", error);
throw new Error(
`다국어 텍스트 저장 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async getUserText(params: GetUserTextParams): Promise<string> {
try {
logger.info("사용자별 다국어 텍스트 조회 시작", { params });
const result = await queryOne<{ lang_text: string }>(
`SELECT mlt.lang_text
FROM multi_lang_text mlt
INNER JOIN multi_lang_key_master mlkm ON mlt.key_id = mlkm.key_id
WHERE mlt.lang_code = $1
AND mlt.is_active = $2
AND mlkm.company_code = $3
AND mlkm.menu_name = $4
AND mlkm.lang_key = $5
AND mlkm.is_active = $6`,
[
params.userLang,
"Y",
params.companyCode,
params.menuCode,
params.langKey,
"Y",
]
);
2025-09-01 11:00:38 +09:00
if (!result) {
2025-08-25 15:12:31 +09:00
logger.warn("사용자별 다국어 텍스트를 찾을 수 없음", { params });
return params.langKey; // 기본값으로 키 반환
}
2025-09-01 11:00:38 +09:00
logger.info("사용자별 다국어 텍스트 조회 완료", {
params,
langText: result.lang_text,
});
2025-08-25 15:12:31 +09:00
2025-09-01 11:00:38 +09:00
return result.lang_text;
2025-08-25 15:12:31 +09:00
} catch (error) {
logger.error("사용자별 다국어 텍스트 조회 중 오류 발생:", error);
throw new Error(
`사용자별 다국어 텍스트 조회 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async getLangText(
companyCode: string,
langKey: string,
langCode: string
): Promise<string> {
try {
logger.info("특정 키의 다국어 텍스트 조회 시작", {
companyCode,
langKey,
langCode,
});
const result = await queryOne<{ lang_text: string }>(
`SELECT mlt.lang_text
FROM multi_lang_text mlt
INNER JOIN multi_lang_key_master mlkm ON mlt.key_id = mlkm.key_id
WHERE mlt.lang_code = $1
AND mlt.is_active = $2
AND mlkm.company_code = $3
AND mlkm.lang_key = $4
AND mlkm.is_active = $5`,
[langCode, "Y", companyCode, langKey, "Y"]
);
2025-08-25 15:12:31 +09:00
2025-09-01 11:00:38 +09:00
if (!result) {
2025-08-25 15:12:31 +09:00
logger.warn("특정 키의 다국어 텍스트를 찾을 수 없음", {
companyCode,
langKey,
langCode,
});
return langKey; // 기본값으로 키 반환
}
logger.info("특정 키의 다국어 텍스트 조회 완료", {
companyCode,
langKey,
langCode,
2025-09-01 11:00:38 +09:00
langText: result.lang_text,
2025-08-25 15:12:31 +09:00
});
2025-09-01 11:00:38 +09:00
return result.lang_text;
2025-08-25 15:12:31 +09:00
} catch (error) {
logger.error("특정 키의 다국어 텍스트 조회 중 오류 발생:", error);
throw new Error(
`특정 키의 다국어 텍스트 조회 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
*
*/
async getBatchTranslations(
params: BatchTranslationRequest
): Promise<Record<string, string>> {
try {
logger.info("배치 번역 조회 시작", {
companyCode: params.companyCode,
menuCode: params.menuCode,
userLang: params.userLang,
keyCount: params.langKeys.length,
});
if (params.langKeys.length === 0) {
return {};
}
2025-09-01 11:00:38 +09:00
// 모든 키에 대한 번역 조회
const placeholders = params.langKeys
.map((_, i) => `$${i + 4}`)
.join(", ");
const translations = await query<{
lang_text: string;
lang_key: string;
company_code: string;
}>(
`SELECT mlt.lang_text, mlkm.lang_key, mlkm.company_code
FROM multi_lang_text mlt
INNER JOIN multi_lang_key_master mlkm ON mlt.key_id = mlkm.key_id
WHERE mlt.lang_code = $1
AND mlt.is_active = $2
AND mlkm.lang_key IN (${placeholders})
AND mlkm.company_code IN ($3, '*')
AND mlkm.is_active = $2
ORDER BY mlkm.company_code ASC`,
[params.userLang, "Y", params.companyCode, ...params.langKeys]
);
2025-08-25 15:12:31 +09:00
const result: Record<string, string> = {};
2025-09-01 11:00:38 +09:00
// 기본값으로 모든 키 설정
params.langKeys.forEach((key) => {
2025-08-25 15:12:31 +09:00
result[key] = key;
});
2025-09-01 11:00:38 +09:00
// 실제 번역으로 덮어쓰기 (회사별 우선)
translations.forEach((translation) => {
const langKey = translation.lang_key;
2025-09-01 11:00:38 +09:00
if (params.langKeys.includes(langKey)) {
result[langKey] = translation.lang_text;
}
});
2025-08-25 15:12:31 +09:00
logger.info("배치 번역 조회 완료", {
totalKeys: params.langKeys.length,
2025-09-01 11:00:38 +09:00
foundTranslations: translations.length,
2025-08-25 15:12:31 +09:00
resultKeys: Object.keys(result).length,
});
return result;
} catch (error) {
logger.error("배치 번역 조회 중 오류 발생:", error);
throw new Error(
`배치 번역 조회 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
2025-08-29 10:44:55 +09:00
/**
*
*/
async deleteLanguage(langCode: string): Promise<void> {
try {
logger.info("언어 삭제 시작", { langCode });
// 기존 언어 확인
const existingLanguage = await queryOne<{ lang_code: string }>(
`SELECT lang_code FROM language_master WHERE lang_code = $1`,
[langCode]
);
2025-08-29 10:44:55 +09:00
2025-09-01 11:00:38 +09:00
if (!existingLanguage) {
2025-08-29 10:44:55 +09:00
throw new Error(`언어를 찾을 수 없습니다: ${langCode}`);
}
2025-09-01 11:00:38 +09:00
// 트랜잭션으로 언어와 관련 텍스트 삭제
await transaction(async (client) => {
2025-09-01 11:00:38 +09:00
// 해당 언어의 다국어 텍스트 삭제
const deleteResult = await client.query(
`DELETE FROM multi_lang_text WHERE lang_code = $1`,
[langCode]
);
2025-08-29 10:44:55 +09:00
logger.info(`삭제된 다국어 텍스트 수: ${deleteResult.rowCount}`, {
langCode,
});
2025-08-29 10:44:55 +09:00
// 언어 마스터 삭제
await client.query(`DELETE FROM language_master WHERE lang_code = $1`, [
langCode,
]);
2025-09-01 11:00:38 +09:00
});
logger.info("언어 삭제 완료", { langCode });
2025-08-29 10:44:55 +09:00
} catch (error) {
logger.error("언어 삭제 중 오류 발생:", error);
throw new Error(
`언어 삭제 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
2025-08-25 15:12:31 +09:00
}