/* ============================================================================= * M01_MasterData_UI_Test_Text.ts * 로직 테스트 컨테이너 글자 — [한국어, 영어] · 틀과 방식 파일(A·B·C)이 같이 씀 * ========================================================================== */ import { currentLanguageIndex } from "@ui/ui_template_locale"; const TEXT = { Title: ["일위대가 로직 테스트", "Logic test"], Pick_Logic: ["공종 고르기", "Pick a job"], Tab_A: ["A 질문·답", "A Wizard"], Tab_B: ["B 호표 + 설명", "B Table + notes"], Tab_C: ["C 흐름 그림", "C Flow"], Soon: ["준비 중", "Coming soon"], New_Logic: ["새로 만들기", "Create new"], Loading: ["불러오는 중", "Loading"], Failed: ["불러오지 못함", "Load failed"], Read_Only: ["시험 계산만 — 저장하지 않음", "Trial only — nothing is saved"], Step: ["{n} / {total}", "{n} / {total}"], Back: ["이전", "Back"], Next: ["다음", "Next"], Again: ["처음부터", "Start over"], Job_Title: ["이 공종의 단가를 셈합니다", "Price this job"], Job_Note: [ "몇 가지만 물어봅니다 — 답을 마치면 결과 표가 나옵니다", "A few questions, then the result table", ], Ask_Pick: ["「{name}」 — 어느 것으로 할까요?", "「{name}」 — which one?"], Ask_Number: ["「{name}」 값을 넣어 주세요{unit}", "Enter 「{name}」{unit}"], Ask_Range: ["범위 {min} ∼ {max}", "Range {min} ∼ {max}"], Mat_Title: ["쓰이는 재료·기계", "Materials and machines"], Mat_Note: [ "기본은 원문 그대로 — 바꿔 보면 결과가 달라짐(저장 안 함) · 값이 여럿이면 그중 낮은 값으로 셈", "Default is the source as is — swapping only changes this trial; the lowest listed price is used", ], Mat_None: ["이 공종은 재료·기계를 따로 고르지 않습니다", "No materials or machines to pick"], Mat_Default: ["기본 (원문 그대로)", "Default (as in source)"], Pick_All: ["(전체)", "(All)"], Use_Of: ["이 표의 용도", "Used for"], Mat_Price: ["단가", "Unit price"], Mat_NoPrice: ["단가 없음", "No price"], Stop_Missing: [ "「{name}」 값을 아직 안 넣었습니다 — 값을 넣으면 계산됩니다", "「{name}」 is empty — enter it to calculate", ], Stop_NoRow: [ "넣은 값에 맞는 표 줄이 없습니다 — 값을 바꿔 보세요", "No table row fits these values — try other values", ], Stop_Spec: [ "「{name}」 규격이 여럿이라 정하지 못함 — 위 「쓰이는 재료·기계」에서 하나를 골라 주세요", "「{name}」 has several specs — pick one in the materials list above", ], Stop_NoPrice: [ "「{name}」 단가가 자료에 비어 있어 셈하지 못함 — 자료를 채워야 함", "「{name}」 has no price in the data yet", ], Guide_A: [ "한 번에 하나씩 묻는 대로 답하면 끝에 결과 표가 나옴|값을 잘못 넣었으면 「이전」으로 돌아가 고침|재료·기계를 바꿔 보는 칸은 뒤쪽 단계에 있음", "Answer one question at a time; the result table comes last|Use Back to fix a value|Swap materials in a later step", ], Guide_B: [ "위쪽 칸에 값을 넣으면 아래 호표(재료·인력·기계 줄)의 수량과 금액이 바로 바뀜|줄을 누르면 오른쪽에 그 수량이 어디서 왔는지 나옴|맨 아래 「합계」가 최종 금액", "Type values above and the table below updates at once|Click a row to see where its quantity comes from|The last row is the total", ], Guide_C: [ "왼쪽 「설계 값」을 넣으면 오른쪽으로 수량 → 단가 → 합계 순으로 흐름이 이어짐|상자를 누르면 값과 출처가 펼쳐짐|빨간 글이 뜨면 그 까닭 그대로 값을 채우거나 바꿈", "Enter design values on the left; quantity, price and total follow to the right|Click a box for details|Red text says what is missing", ], Enter_Value: ["값을 넣어 주세요", "Enter a value"], Result_Title: ["결과", "Result"], Result_Stopped: ["계산이 멈춤", "Calculation stopped"], Col_Name: ["이름", "Name"], Col_Qty: ["수량", "Qty"], Col_Amount: ["금액", "Amount"], Sum_Total: ["합계", "Total"], Sum_Result: ["결과 값", "Result"], } as const satisfies Record; export type TestTextKey = keyof typeof TEXT; /** 엔진이 멈춘 까닭을 설계자 말로 — 모르는 글은 그대로 */ export function plainReason(reason: string): string { const missing = /입력 「([^」]+)」 없음/.exec(reason); if (missing) return tt("Stop_Missing", { name: missing[1] }); if (/맞는 줄 0개/.test(reason)) return tt("Stop_NoRow"); const spec = /「([^」]+)」 후보 여럿/.exec(reason); if (spec) return tt("Stop_Spec", { name: spec[1] }); const noPrice = /「([^」]+)」 값 없음/.exec(reason); if (noPrice) return tt("Stop_NoPrice", { name: noPrice[1] }); return reason; } /** 방식 첫 화면 「이 방식은 이렇게 씀」 — 줄 목록 */ export const guideLines = (id: "A" | "B" | "C"): string[] => tt(`Guide_${id}` as TestTextKey).split("|"); export function tt(key: TestTextKey, fill: Record = {}): string { const entry = TEXT[key]; const text: string = entry[currentLanguageIndex as 0 | 1] ?? entry[0]; return text.replace(/\{(\w+)\}/g, (m, k: string) => (k in fill ? String(fill[k]) : m)); }