fix(버튼): 357-3 서술형 버튼 이름 → 명사형 · 「단추」 → 「버튼」 (A06 · A07 · B01 · B03 · B09 · B11 · M01 · 열린 물음 · 스프레드시트 · 도움말)

- 저장 후 넘어감 → 저장 · 버리고 넘어감 → 폐기 · 다시 불러오기 → 새로고침 · 지우기 → 삭제 등
- test_303 · test_ui_loading 글 맞춤

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013QyNXY2TUKXCFMwAca2APG
This commit is contained in:
2026-10-16 20:38:55 +09:00
co-authored by Claude Sonnet 5.5
parent cadff2af90
commit 2a378eb5c8
42 changed files with 76 additions and 76 deletions
+3 -3
View File
@@ -1,7 +1,7 @@
/* =============================================================================
* A00_Common/design/design_leave.ts
* B05 · B06 떠남 확인(346-4) — 저장 안 한 조작(초안 통)이 있으면 탭 닫기 · 다른 페이지로 갈 때
* 공용 물음(`ui_template_leave_dialog` · [취소] [버리고 넘어감] [저장 후 넘어감]).
* 공용 물음(`ui_template_leave_dialog` · [취소] [폐기] [저장]).
*
* 고침 = 초안 통 칸 중 고침이 아닌 칸(고름 · 관 id 장부 · 종류 캐시 · 고른 구조물 넘김) ·
* 다른 페이지 칸(b08 · b09) · 저장 뒤에도 남기는 표준 횡단면(std-cross)을 뺀 것.
@@ -24,7 +24,7 @@ import {
} from "../b_page_state";
import { currentRoute, setLeaveGuard } from "../router";
/** 초안 통이지만 고침으로 안 보는 칸 — 묻지 않고 [버리고 넘어감]에도 안 지움. */
/** 초안 통이지만 고침으로 안 보는 칸 — 묻지 않고 [폐기]에도 안 지움. */
const NOT_EDITS = new Set<StateName>([
"selection",
"pipe-ids",
@@ -81,7 +81,7 @@ export function designDirty(projectId: string): boolean {
return cleanMarks.get(projectId) !== digest(signature);
}
/** [버리고 넘어감] — 고침 칸만 지움(모든 노선). */
/** [폐기] — 고침 칸만 지움(모든 노선). */
export function discardDesignEdits(projectId: string): void {
editDraftNames().forEach((name) => clearState(name, projectId));
}
@@ -23,7 +23,7 @@ const TEXT = {
freezeAt: "지금 칸 기준 고정",
unfreeze: "틀 고정 풀기",
insert: "칸 넣기…(Ctrl+Shift++)",
remove: "칸 지우기…(Ctrl+-)",
remove: "칸 삭제…(Ctrl+-)",
split: "텍스트 나누기…",
dedupe: "중복된 항목 제거…",
series: "연속 데이터 채우기…",
@@ -249,7 +249,7 @@ export function createCondFmtPanel(ctx: SpreadsheetContext): PartHandle {
moveCondFmtRule(ctx, rule.id, 1);
render();
});
const del = createButton({ label: "지움", variant: "danger" });
const del = createButton({ label: "삭제", variant: "danger" });
del.addEventListener("click", () => {
removeCondFmtRule(ctx, rule.id);
render();
@@ -44,7 +44,7 @@ const TEXT = {
Then: ["→", "→"],
Otherwise: ["아니면 →", "Otherwise →"],
AddElseIf: ["+ 아니면 만약", "+ Else if"],
Remove: ["지움", "Remove"],
Remove: ["삭제", "Remove"],
Make: ["만들기", "Make"],
Cancel: ["취소", "Cancel"],
Close: ["닫기", "Close"],
@@ -66,7 +66,7 @@ const TEXT = {
left: "왼",
right: "오른",
fillColor: "채움색",
clear: "지움",
clear: "삭제",
protectNote: "칸 잠금 · 숨김은 자리만 둠(시트 보호 자체가 아직 없음)",
lock: "잠금",
hidden: "수식 숨김",
+1 -1
View File
@@ -190,7 +190,7 @@ export function createNameManagerPanel(ctx: SpreadsheetContext): PartHandle {
input.focus();
input.select();
});
const del = createButton({ label: "지움", variant: "danger" });
const del = createButton({ label: "삭제", variant: "danger" });
del.addEventListener("click", () => {
deleteName(ctx, 이름);
render();
@@ -76,7 +76,7 @@ export function createSheetExtraPanel(ctx: SpreadsheetContext): PartHandle {
colorInput.addEventListener("change", () =>
setSheetTabColor(ctx, sheet.id, colorInput.value),
);
const colorClear = createButton({ label: "색 지움", variant: "ghost" });
const colorClear = createButton({ label: "색 삭제", variant: "ghost" });
colorClear.addEventListener("click", () => {
setSheetTabColor(ctx, sheet.id, null);
render();
+4 -4
View File
@@ -25,7 +25,7 @@ const TEXT = {
Strike: ["취소선", "Strikethrough"],
TextColor: ["글자색", "Text color"],
FillColor: ["채움색", "Fill color"],
ColorClear: ["지움", "Clear"],
ColorClear: ["색 삭제", "Clear color"],
HAlign: ["가로 정렬", "Horizontal align"],
VAlign: ["세로 정렬", "Vertical align"],
Align_general: ["일반", "General"],
@@ -70,7 +70,7 @@ const TEXT = {
],
SheetAdd: ["시트 추가", "Add sheet"],
SheetRename: ["이름 바꾸기", "Rename"],
SheetDelete: ["지우기", "Delete"],
SheetDelete: ["삭제", "Delete"],
SheetDuplicate: ["복사", "Duplicate"],
SheetRenamePrompt: ["새 시트 이름", "New sheet name"],
SheetDeleteConfirm: [
@@ -84,9 +84,9 @@ const TEXT = {
MenuCopy: ["복사", "Copy"],
MenuPasteHint: ["Ctrl+V 를 쓸 것", "Use Ctrl+V"],
MenuInsertRow: ["행 넣기", "Insert row"],
MenuDeleteRow: ["행 지우기", "Delete row"],
MenuDeleteRow: ["행 삭제", "Delete row"],
MenuInsertCol: ["열 넣기", "Insert column"],
MenuDeleteCol: ["열 지우기", "Delete column"],
MenuDeleteCol: ["열 삭제", "Delete column"],
MenuHide: ["숨기기", "Hide"],
MenuUnhide: ["숨김 취소", "Unhide"],
MenuClearContent: ["내용 지우기", "Clear content"],
@@ -183,7 +183,7 @@ export function createValidationPanel(ctx: SpreadsheetContext): PartHandle {
const label = el("span", {
text: `${rule.범위.map(rangeToA1).join(", ")} — ${kindText(rule.규칙)}(${rule.어기면})`,
});
const del = createButton({ label: "지움", variant: "danger" });
const del = createButton({ label: "삭제", variant: "danger" });
del.addEventListener("click", () => {
removeValidationRule(ctx, rule.id);
render();
@@ -58,7 +58,7 @@ export function buildAddressField(initial: string | null): AddressFieldHandle {
placeholder: "도로명·지번·건물명 일부 (예: 판교역로 235)",
});
const findBtn = createButton({
label: "주소 찾기",
label: "주소 검색",
variant: "ghost",
onClick: () => void runSearch(),
});
@@ -70,7 +70,7 @@ export function createAssetField(
const fallback = options.fallback ?? null;
const reset = createButton({
label: "기본으로",
label: "기본값 복원",
variant: "ghost",
onClick: () => {
selected = null;
@@ -173,7 +173,7 @@ function createSignaturePad(): { root: HTMLDivElement; toFile: () => Promise<Fil
canvas.addEventListener("pointercancel", stop);
const clear = createButton({
label: "지우기",
label: "삭제",
variant: "ghost",
onClick: () => {
context?.clearRect(0, 0, canvas.width, canvas.height);
@@ -312,7 +312,7 @@ function openAssetPickerModal(
);
const pad = kind === "SIGNATURE" ? createSignaturePad() : null;
const add = createButton({
label: "파일 올리고 이 프로젝트에 쓰기",
label: "파일 업로드",
onClick: async () => {
if (!label.input.value.trim()) return label.setError("이름을 넣어 주세요.");
const chosen = file.input.files?.[0] ?? (await pad?.toFile()) ?? null;
+3 -3
View File
@@ -461,7 +461,7 @@ export function openCreateCompanyModal(): void {
const matches = document.createElement("div");
matches.className = "b01-dashboard__actions";
const findBtn = createButton({
label: "이미 있는 회사인지 찾기",
label: "회사 검색",
variant: "ghost",
onClick: async function onB01_Company_Duplicate_Click() {
matches.innerHTML = "";
@@ -589,7 +589,7 @@ export function openAddMemberModal(
companyId?: number | null,
): void {
const query = createInputField({
label: "이름 또는 이메일로 찾기",
label: "이름 · 이메일 검색",
placeholder: "두 글자 이상",
});
const results = document.createElement("div");
@@ -632,7 +632,7 @@ export function openAddMemberModal(
});
const invite = createButton({
label: "가입 안내 메일 보내기",
label: "초대 메일 발송",
variant: "ghost",
onClick: async function onB01_Member_Invite_Click() {
const text = query.input.value.trim();
@@ -43,7 +43,7 @@ export const VIEW_COMMANDS: CadCommand[] = [
label: '범위 줌',
aliases: ['Z'],
glyph: '⛶',
hint: '범위(E) · 전체(A) · 이전(P) · 윈도우(W) · 2X — 오토캐드 ZOOM(⛶ 단추 = 바로 범위)',
hint: '범위(E) · 전체(A) · 이전(P) · 윈도우(W) · 2X — 오토캐드 ZOOM(⛶ 버튼 = 바로 범위)',
run: () => {
startZoomPrompt(); // 덧물음 — 명령 중 'Z 도 같은 길
return '';
+1 -1
View File
@@ -144,7 +144,7 @@ export function openRowPopup(o: PopupOpen): void {
title.className = "b09-popup__title";
title.textContent = tabName(tab);
const goButton = createButton({
label: "탭으로",
label: "탭 이동",
variant: "ghost",
size: "sm",
onClick: () => {
@@ -59,7 +59,7 @@ export function openQuotes(key: string, label: string, onChange: (names: string[
onClick: () => void download(key, f.name).catch(fail),
}),
createButton({
label: "지우기",
label: "삭제",
variant: "danger",
size: "sm",
onClick: () =>
@@ -28,7 +28,7 @@ const ACTS: [string, string][] = [
["↓ 아래로", "아래로 ↓"],
];
const GUIDE = "줄 누르고 단추 · 방향키 ←→ 레벨 · ↑↓ 자리 · 줄 끌기 · 더블클릭 · Enter · F2 입력";
const GUIDE = "줄 누르고 버튼 · 방향키 ←→ 레벨 · ↑↓ 자리 · 줄 끌기 · 더블클릭 · Enter · F2 입력";
let picked: string | null = null;
/** 242-1 이동해 온 범위 [첫 줄, 끝 줄] — 고름과 한때 하나 */
+3 -3
View File
@@ -178,7 +178,7 @@ export function renderB09Print(root: HTMLElement): MountedPage {
};
const pdfBtn = createButton({
label: "PDF 내려받기",
label: "PDF 다운로드",
onClick: () => {
if (!shown) return;
const name = `${label()}.pdf`;
@@ -190,7 +190,7 @@ export function renderB09Print(root: HTMLElement): MountedPage {
});
pdfBtn.dataset.b09PrintPdf = "";
const xlsxBtn = createButton({
label: "엑셀 내려받기",
label: "엑셀 다운로드",
variant: "ghost",
onClick: () => {
const ids = picked();
@@ -205,7 +205,7 @@ export function renderB09Print(root: HTMLElement): MountedPage {
});
xlsxBtn.dataset.b09PrintXlsx = "";
const back = createButton({
label: "B09 로 돌아가기",
label: "B09 복귀",
variant: "ghost",
onClick: () => navigateTo(ROUTES.B09_ESTIMATION),
});
@@ -18,7 +18,7 @@ const TEXT = {
List_New: ["새것", "New"],
List_Deleted: ["지움", "Deleted"],
Bar_Back: ["← 로직 목록", "← Logics"],
Bar_Delete: ["로직 지우기", "Delete logic"],
Bar_Delete: ["로직 삭제", "Delete logic"],
Bar_Save: ["저장", "Save"],
Bar_Discard: ["캐시 삭제", "Clear cache"],
Bar_Pending: ["저장 안 한 로직 {n} 개", "{n} unsaved logics"],
@@ -57,7 +57,7 @@ const TEXT = {
Rounding: ["끝수", "Rounding"],
Formula: ["식", "Formula"],
AddRow: ["줄 추가", "Add line"],
DeleteRow: ["줄 지우기", "Delete line"],
DeleteRow: ["줄 삭제", "Delete line"],
Calc_Title: ["시험 계산", "Test calculation"],
Calc_Run: ["계산", "Calculate"],
Calc_NoInputs: ["받을 값 없음", "No inputs"],
@@ -60,7 +60,7 @@ export const TEXT = {
],
LineOf: ["선 · {a} → {b}", "Line · {a} → {b}"],
Hint: [
"상자 머리를 끌어 옮김 · 가운데 단추(또는 Space + 끌기)로 판 옮김 · 휠로 확대",
"상자 머리를 끌어 옮김 · 가운데 버튼(또는 Space + 끌기)로 판 옮김 · 휠로 확대",
"Drag a head to move · middle button (or Space + drag) to pan · wheel to zoom",
],
Break: ["끊긴 곳", "Break"],
@@ -65,7 +65,7 @@ export const CARD_HELP: Record<"structure" | "labor" | "area", CardHelp> = {
["로직 줄 누름", "넣을 값 창 — 그 로직의 넣을 값 고침"],
["수량산출 칸", "수기 입력 · 면적산출 칸 고르기"],
["별칭 칸", "줄에 따로 이름 붙임"],
["줄 끝 단추", "그 줄을 뺌"],
["줄 끝 버튼", "그 줄을 뺌"],
["자재 추가", "자재를 골라 자재목록에 넣음"],
FOLD,
],
@@ -23,7 +23,7 @@ const TEXT = {
Zoom_Out: ["작게", "Zoom out"],
Fit: ["한눈에", "Fit"],
Hint: [
"가운데 단추 또는 Space + 끌기로 판 옮김 · Ctrl + 휠로 확대",
"가운데 버튼 또는 Space + 끌기로 판 옮김 · Ctrl + 휠로 확대",
"Middle button or Space + drag to move · Ctrl + wheel to zoom",
],
None: ["단가산출 로직이 없음", "No logics yet"],
+1 -1
View File
@@ -4,6 +4,6 @@
## 작업 순서
## 단추
## 버튼
## 주의할 점
+1 -1
View File
@@ -4,6 +4,6 @@
## 작업 순서
## 단추
## 버튼
## 주의할 점
+1 -1
View File
@@ -4,6 +4,6 @@
## 작업 순서
## 단추
## 버튼
## 주의할 점
+1 -1
View File
@@ -4,6 +4,6 @@
## 작업 순서
## 단추
## 버튼
## 주의할 점
+1 -1
View File
@@ -4,6 +4,6 @@
## 작업 순서
## 단추
## 버튼
## 주의할 점
+1 -1
View File
@@ -4,6 +4,6 @@
## 작업 순서
## 단추
## 버튼
## 주의할 점
+1 -1
View File
@@ -4,6 +4,6 @@
## 작업 순서
## 단추
## 버튼
## 주의할 점
+1 -1
View File
@@ -4,6 +4,6 @@
## 작업 순서
## 단추
## 버튼
## 주의할 점
+2 -2
View File
@@ -249,7 +249,7 @@ def test_창_열_제목_강조_줄_자리():
)
assert out["boxes"] == ["bill"] and out["n"] == 1
assert out["cls"] == "b09-estimation b09-popup ui-popup" # 창 안 = b09 표 꼴(빨강 테두리)
assert out["head"] == ["설계내역서", "탭으로", "×"]
assert out["head"] == ["설계내역서", "탭 이동", "×"]
assert out["rows"] == ["b1", "b2", "b3"] # 그 줄 + 자손
assert out["rowCls"] == ["is-title is-pick is-pick-top", "is-pick", "is-pick is-pick-end"]
assert out["columns"] is True and out["caption"] == "설계내역서" # 열 제목(머리 여러 줄) 그대로
@@ -291,7 +291,7 @@ def test_닫기_탭으로_새_누름_주소():
"\nconst a = boxes();"
"\nopen(); tables[2].onCellClick(0, 'name'); open('b4');" # 화면 새 누름 = 있던 창 모두 닫고 새로
"\nconst b = [boxes(), rows(4)];"
"\nhead(0)[1].click();" # [탭으로] = 옮기고 모두 닫음
"\nhead(0)[1].click();" # [탭 이동] = 옮기고 모두 닫음
"\nconst c = [boxes(), [...gone]];"
"\nopen(); hashFns.forEach((f) => f());"
"\nconst d = boxes();"
+3 -3
View File
@@ -1,9 +1,9 @@
"""저장 안 한 고침 3단추 물음(PLAN 86-1 · `ui_template_leave_dialog.ts`) — Node 로 TS 를 돌려 판정.
못박는 것
- 단추 순서 [취소] [버리고 넘어감] [저장 후 넘어감] · 기본 초점 = 취소 · Esc = 취소.
- 저장 후 넘어감: 저장 성공 + 고침 없음 = saved / 저장 던짐 · 고침 남음 = stay(머묾).
- 버리고 넘어감: discard 갈고리 호출 · 취소: 아무것도 안 부름.
- 단추 순서 [취소] [폐기] [저장] · 기본 초점 = 취소 · Esc = 취소.
- 저장: 저장 성공 + 고침 없음 = saved / 저장 던짐 · 고침 남음 = stay(머묾).
- 폐기: discard 갈고리 호출 · 취소: 아무것도 안 부름.
- M02 자리(UI_Main · Structure · ItemCards)가 이 물음을 씀.
"""
+2 -2
View File
@@ -2,7 +2,7 @@
① `delayedShow` 를 Node 로 가짜 시계로 돌림 — 0.3초 전에 끝나면 안 보임(깜빡임 없음) · 넘으면 보이고
끝나면 걷힘 · 끝낸 뒤 시계가 와도 안 보임.
② 실패 자리 = 까닭 글(「불러오지 못함 — 까닭」) + [다시 불러오기] · 화면 전체 잠금 안 씀.
② 실패 자리 = 까닭 글(「불러오지 못함 — 까닭」) + [새로고침] · 화면 전체 잠금 안 씀.
③ M02 나무 · 상세(표 · 도면) · 조합 목록 · 조합 상세 · 항목 카드가 이 부품을 씀.
"""
@@ -70,7 +70,7 @@ def test_실패_글과_다시_불러오기_M02_자리():
assert "clear: (id) => clearTimeout(id)," in src
locale = _text(ROOT / "ui_template" / "ui_template_locale_common.ts")
assert 'Common_Load_Failed: ["불러오지 못함"' in locale
assert 'Common_Reload: ["다시 불러오기"' in locale
assert 'Common_Reload: ["새로고침"' in locale
tree = _text(M02 / "M02_MasterTemplete_TreePanel.ts")
assert "const stop = showLoading(body);" in tree
assert "loadingError(why(error), () => void refresh())" in tree
+1 -1
View File
@@ -93,7 +93,7 @@ export function createFrameTemplateEditor<D extends CadHostDrawing>(
* 되돌릴 길이 없으면 도각을 한 번 잘못 저장한 것만으로 도면이 열리지 않는다.
*/
const resetButton = createButton({
label: "기본 도각으로",
label: "기본 도각 복원",
variant: "ghost",
onClick: () => void resetToDefault(),
});
+2 -2
View File
@@ -72,10 +72,10 @@ export interface CadTabs<D> {
const TEXT = {
add: "새 장",
rename: "두 번 눌러 이름 바꾸기",
remove: "장 지우기",
remove: "장 삭제",
close: "닫기",
removeAsk: "「{name}」 장을 지울까요? 저장하면 되돌릴 수 없음",
removeOk: "지우기",
removeOk: "삭제",
closeAsk: "「{name}」 에 저장 안 한 고침이 있음 — 버리고 닫을까요?",
closeOk: "버리고 닫기",
emptyName: "장 이름을 넣을 것",
+1 -1
View File
@@ -7,7 +7,7 @@ import { currentLanguageIndex } from "@ui/ui_template_locale";
const TEXT = {
Col_Add: ["열 추가", "Add column"],
Col_Delete: ["열 지우기", "Delete column"],
Col_Delete: ["열 삭제", "Delete column"],
Col_New: ["새 열", "New column"],
Row_Unit: ["단위", "Unit"],
Row_Unit_Price: ["일위대가", "Unit price"],
+2 -2
View File
@@ -1,6 +1,6 @@
/* =============================================================================
* ui_template_leave_dialog.ts
* 저장 안 한 고침이 있을 때 넘어가기 전 물음 — 단추 셋: [취소] [버리고 넘어감] [저장 후 넘어감](주 단추).
* 저장 안 한 고침이 있을 때 넘어가기 전 물음 — 버튼 셋: [취소] [폐기] [저장](주 버튼).
* 기본 초점 = 취소 · Esc = 취소 · 저장이 실패하거나 고침이 남으면 머묾.
* 몸은 공용 확인 창(`showConfirmDialog`)과 같은 틀(.ui-confirm).
* ========================================================================== */
@@ -57,7 +57,7 @@ export interface LeaveHooks {
save: () => Promise<unknown>;
/** 저장 뒤에도 고침이 남았나 — 남으면 머묾 */
stillDirty: () => boolean;
/** [버리고 넘어감] 때 */
/** [폐기] 때 */
discard?: () => void | Promise<void>;
}
+3 -3
View File
@@ -181,11 +181,11 @@ export const ui_locales_a = {
A06_Login_Error_Email: ["이메일 형식이 올바르지 않습니다.", "Invalid email format."],
A06_Login_Field_Otp: ["이메일 인증 코드", "Email verification code"],
A06_Login_Field_Otp_Placeholder: ["6자리 코드를 입력하세요", "Enter the 6-digit code"],
A06_Login_Verify: ["인증하고 로그인", "Verify and sign in"],
A06_Login_Verify: ["인증", "Verify"],
A06_Login_OtpSent: ["인증 코드를 이메일로 발송했습니다.", "A verification code was emailed."],
A06_Login_OtpResend: ["인증 코드 재발송", "Resend verification code"],
A06_Login_OtpResendCountdown: ["{seconds}초 후 재발송", "Resend in {seconds}s"],
A06_Login_OtpBack: ["이메일/비밀번호 다시 입력", "Re-enter email/password"],
A06_Login_OtpBack: ["재입력", "Re-enter"],
A06_Login_Success: ["로그인되었습니다.", "Signed in."],
A06_Login_Error_Request: ["로그인 요청에 실패했습니다.", "Sign-in request failed."],
@@ -209,7 +209,7 @@ export const ui_locales_a = {
A07_Register_Field_Phone: ["전화번호", "Phone number"],
A07_Register_Field_Phone_Placeholder: ["010-1234-5678", "010-1234-5678"],
A07_Register_Submit: ["회원가입", "Sign up"],
A07_Register_ToLogin: ["이미 계정이 있으신가요? 로그인", "Already have an account? Sign in"],
A07_Register_ToLogin: ["로그인", "Sign in"],
A07_Register_Error_Required: [
"모든 필수 항목을 입력하세요.",
"Please fill in all required fields.",
+4 -4
View File
@@ -21,7 +21,7 @@ export const ui_locales_b1 = {
"프로젝트가 없어졌습니다 · 대시보드에서 다시 고르세요.",
"This project no longer exists. Choose a project again on the dashboard.",
],
B_Project_Gone_ToDashboard: ["대시보드로", "Go to dashboard"],
B_Project_Gone_ToDashboard: ["대시보드", "Dashboard"],
/* --- B01_Dashboard 계정 관리 공통 문구 --- */
B01_Account_Title: ["내 계정", "My Account"],
@@ -62,7 +62,7 @@ export const ui_locales_b1 = {
B01_Dashboard_Company: ["회사 정보", "Company"],
B01_Dashboard_NoCompany: ["회사 미연결", "No company linked"],
B01_Dashboard_CreateCompany: ["회사 생성", "Create company"],
B01_Dashboard_FindCompany: ["회사 찾기", "Find company"],
B01_Dashboard_FindCompany: ["회사 검색", "Find company"],
B01_Dashboard_JoinCompany: ["가입 신청", "Request to join"],
B01_Dashboard_Members: ["팀원 관리", "Team members"],
B01_Dashboard_AddMember: ["팀원 추가", "Add member"],
@@ -352,7 +352,7 @@ export const ui_locales_b1 = {
B03_File_Status_Detected: ["중단된 업로드 감지", "Paused upload detected"],
B03_File_Restore_State: ["저장된 업로드/분석 상태 복구", "Restored upload/analysis state"],
B03_File_Resume_Button: ["업로드 재개", "Resume upload"],
B03_File_New_Button: ["새 파일로 시작", "Start new file"],
B03_File_New_Button: ["새 파일", "New file"],
B03_File_Overview_Complete: [
"필수 파일 업로드와 지표면 분석이 모두 완료된 프로젝트입니다. 파일을 다시 올리면 기존 결과가 교체됩니다.",
"All required files are uploaded and surface analysis is complete. Re-uploading replaces existing results.",
@@ -366,7 +366,7 @@ export const ui_locales_b1 = {
"이 슬롯에는 이미 업로드된 파일이 있습니다. 새 파일을 올리면 기존 파일과 그에 따른 분석 결과(지표면 모델 등)가 교체됩니다. 계속하시겠습니까?",
"This slot already has an uploaded file. Uploading a new one replaces the existing file and derived analysis results (surface model, etc.). Continue?",
],
B03_File_Replace_Confirm: ["교체하고 계속", "Replace and continue"],
B03_File_Replace_Confirm: ["교체", "Replace"],
B03_File_Replace_Cancel: ["취소", "Cancel"],
B03_File_ServiceWorker_Ready: [
"백그라운드 업로드 준비가 완료되었습니다.",
+3 -3
View File
@@ -1031,9 +1031,9 @@ export const ui_locales_b2 = {
"아직 확정된 지표면이 없습니다. 필수 파일을 올리면 지표면 분석이 자동으로 진행되고, 끝나면 이 화면이 자료를 준비합니다.",
"No confirmed surface yet. Upload the required files — the surface analysis runs automatically, and this screen prepares the data once it finishes.",
],
B11_Loading_Btn_FileInput: ["파일 입력 화면으로", "Go to file input"],
B11_Loading_Btn_Continue: ["그래도 화면으로 이동", "Continue anyway"],
B11_Loading_Btn_Dashboard: ["대시보드로", "Back to dashboard"],
B11_Loading_Btn_FileInput: ["파일 입력", "File input"],
B11_Loading_Btn_Continue: ["계속", "Continue"],
B11_Loading_Btn_Dashboard: ["대시보드", "Dashboard"],
B11_Status_Flow_Title: ["결재 진행 상태", "Payment Progress"],
B11_Status_Step_Request: ["발행 요청", "Invoice Requested"],
B11_Status_Step_Issue: ["세금계산서 발행", "Invoice Issued"],
+2 -2
View File
@@ -32,7 +32,7 @@ export const ui_locales_b3 = {
"사유는 아래 단계(수량·단가)가 낸 것을 그대로 옮김 — 여기서 새로 짓지 않음",
"Reasons are passed through from the quantity/price step as-is",
],
B09_Sheet_Reload: ["다시 불러오기", "Reload"],
B09_Sheet_Reload: ["새로고침", "Reload"],
B09_Sheet_Level: ["보이는 레벨", "Show levels"],
B09_Sheet_Level_All: ["모두", "All"],
B09_Sheet_Level_Upto: ["레벨까지", " level(s)"],
@@ -145,7 +145,7 @@ export const ui_locales_b3 = {
B01_Dashboard_PermCompanyRead: ["회사 읽기", "Company read"],
B01_Dashboard_PermCompanyWrite: ["회사 수정", "Company edit"],
B01_Dashboard_PermPersonalWrite: ["개인 수정", "Personal edit"],
B01_Dashboard_PickCompany: ["회사 고르기", "Pick company"],
B01_Dashboard_PickCompany: ["회사 선택", "Pick company"],
B01_Dashboard_PickCompanyHint: ["회사 이름 · 사업자번호", "Company name · business number"],
B01_Dashboard_PickCompanyCount: ["{count}곳", "{count} companies"],
B01_Dashboard_PickCompanyMore: [
+7 -7
View File
@@ -10,7 +10,7 @@ export const ui_locales_m1 = {
M01_AdminOnly: ["시스템 관리자만 볼 수 있음", "System administrators only"],
M01_LoadFailed: ["마스터 요소를 못 읽음", "Failed to load master elements"],
M01_PickFile: ["왼쪽에서 그룹과 파일을 고를 것", "Pick a group and a file on the left"],
M01_Search: ["이름 찾기", "Find by name"],
M01_Search: ["이름 검색", "Find by name"],
M01_WideHint: ["표가 넓음 — 옆으로 밀어서 볼 것", "Wide table — swipe sideways"],
M01_Prev: ["이전", "Prev"],
M01_Next: ["다음", "Next"],
@@ -18,7 +18,7 @@ export const ui_locales_m1 = {
M01_Rows: ["줄", "rows"],
M01_NoRows: ["줄 없음", "No rows"],
M01_RowAdd: ["줄 추가", "Add row"],
M01_RowDelete: ["지우기", "Delete"],
M01_RowDelete: ["삭제", "Delete"],
M01_RowRestore: ["되살리기", "Restore"],
M01_RowRemove: ["빼기", "Remove"],
M01_BackToTables: ["← 표 목록", "← Tables"],
@@ -35,25 +35,25 @@ export const ui_locales_m1 = {
"그 사이 파일이 바뀜({value}) — 고친 것을 버리고 다시 읽은 뒤 다시 고칠 것",
"Files changed meanwhile ({value}) — discard and reload, then edit again",
],
M01_StaleReload: ["버리고 다시 읽기", "Discard and reload"],
M01_StaleReload: ["새로고침", "Reload"],
M01_FileStale: [
"고치기 시작한 뒤 이 파일이 바뀜 — 저장하면 막힘",
"This file changed after you started editing — saving will be refused",
],
M01_CheckErrors: ["검사에 걸림", "Validation failed"],
M01_ProcureSearch: ["이름·규격 찾기", "Find by name or spec"],
M01_ProcureSearch: ["이름·규격 검색", "Find by name or spec"],
M01_ProcureCut: ["연결 끊기", "Unlink"],
M01_ProcureClose: ["닫기", "Close"],
M01_PriceFind: ["가격 연결", "Link price"],
M01_PriceTitle: ["가격 연결 고르기", "Pick price source"],
M01_PriceCol: ["가격 연결", "Price link"],
M01_PriceCond: ["후보 조건으로 연결 (지역은 입력)", "Link by condition (region as input)"],
M01_PriceCond: ["조건 연결 (지역은 입력)", "Link by condition (region as input)"],
M01_PriceCondName: ["이름", "Name"],
M01_PriceCondSpec: ["규격", "Spec"],
M01_PriceCondUsed: ["후보 조건", "Condition"],
M01_Govt: ["관급", "Govt"],
M01_OnlyUnlinked: ["못 이은 줄만 보기", "Unlinked only"],
M01_JobFind: ["직종 고르기", "Pick job"],
M01_OnlyUnlinked: ["미연결만", "Unlinked only"],
M01_JobFind: ["직종 선택", "Pick job"],
M01_JobTitle: ["준용 직종 고르기", "Pick substitute job"],
M01_JobCol: ["준용", "Substitute"],
M01_All: ["전체", "All"],
+3 -3
View File
@@ -101,7 +101,7 @@ export const ui_locales_m2 = {
M02_SourcePractice: ["실무문서", "Practice documents"],
M02_PeopleEmpty: ["비어 있음", "empty"],
M02_TreeEmptyEdit: [
"항목이 없음 — 빈 자리 오른쪽 클릭 또는 층 단추 옆 「+」 로 폴더 · 항목을 더함",
"항목이 없음 — 빈 자리 오른쪽 클릭 또는 층 버튼 옆 「+」 로 폴더 · 항목을 더함",
"No items — right-click an empty area or use + beside the layer buttons to add",
],
M02_TreeAddTop: ["맨 위에 폴더 · 항목 추가", "Add folder or item at top"],
@@ -155,8 +155,8 @@ export const ui_locales_m2 = {
"저장 안 한 표 고침이 있음 — 나무를 고치기 전에 처리",
"Unsaved table edits — settle them before changing the tree",
],
M02_TreeSaveGo: ["저장 후 넘어감", "Save and continue"],
M02_TreeDiscardGo: ["버리고 넘어감", "Discard and continue"],
M02_TreeSaveGo: ["저장", "Save"],
M02_TreeDiscardGo: ["폐기", "Discard"],
M02_TreeDone: ["나무를 고침", "Tree updated"],
M02_TreeRenamed: [
"나무를 고침 — 같은 이름이 있어 「{value}」 로 저장",