From 3139e213a76d0237faa708bf128e250d34cb2a56 Mon Sep 17 00:00:00 2001 From: king Date: Thu, 11 Jun 2026 18:14:42 +0900 Subject: [PATCH] =?UTF-8?q?feat(malaysia):=20=EC=A0=84=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=ED=95=9C=EA=B8=80/=EC=98=81=EB=AC=B8=20=EC=8B=A4?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=ED=86=A0=EA=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - static/malaysia.js: KO_EN 사전 + 토글(localStorage 기억, 새로고침 없이 즉시) - _i18n.html 공용 include(ENG/한글 버튼 + 스크립트), 전 화면 상단 삽입 - UI 고정 문구는 사전 치환(제목/헤더/버튼/라벨/배지/옵션/안내) - 상품/콤보명은 data-en(영문, malaysia_items)·data-ko(itemcode_db 한글) 동시 렌더 - _base_ctx 에 ko_names(itemcode_db name_map) 주입 Co-Authored-By: Claude Opus 4.8 --- app/modules/malaysia/router.py | 3 + .../malaysia/templates/malaysia/_i18n.html | 5 + .../malaysia/templates/malaysia/index.html | 7 +- .../templates/malaysia/movements.html | 7 +- .../templates/malaysia/stocktake_detail.html | 7 +- .../templates/malaysia/stocktakes.html | 5 +- app/static/malaysia.js | 130 ++++++++++++++++++ 7 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 app/modules/malaysia/templates/malaysia/_i18n.html create mode 100644 app/static/malaysia.js diff --git a/app/modules/malaysia/router.py b/app/modules/malaysia/router.py index 904895f..2607899 100644 --- a/app/modules/malaysia/router.py +++ b/app/modules/malaysia/router.py @@ -121,6 +121,8 @@ def _base_ctx(request: Request, user: dict[str, Any], st: Any, *, wh: str) -> di from app.main import build_erp_nav # noqa: WPS433 from app.store import is_admin # noqa: WPS433 + reader = _reader(request) + ko_names = reader.name_map() if reader else {} return { "user": user, "is_admin": is_admin(user), @@ -128,6 +130,7 @@ def _base_ctx(request: Request, user: dict[str, Any], st: Any, *, wh: str) -> di "nav_items": build_erp_nav(user, active="malaysia"), "warehouses": st.list_warehouses(), "selected_wh": wh, + "ko_names": ko_names, } diff --git a/app/modules/malaysia/templates/malaysia/_i18n.html b/app/modules/malaysia/templates/malaysia/_i18n.html new file mode 100644 index 0000000..014fbe5 --- /dev/null +++ b/app/modules/malaysia/templates/malaysia/_i18n.html @@ -0,0 +1,5 @@ +{# 한글/영문 토글 버튼 + i18n 스크립트. 모든 말레이시아 화면 상단에 include. #} +
+ +
+ diff --git a/app/modules/malaysia/templates/malaysia/index.html b/app/modules/malaysia/templates/malaysia/index.html index ceca8fb..eb17565 100644 --- a/app/modules/malaysia/templates/malaysia/index.html +++ b/app/modules/malaysia/templates/malaysia/index.html @@ -11,6 +11,7 @@ {% block content %}
+ {% include "malaysia/_i18n.html" %} {% set active_tab = 'status' %} {% include "malaysia/_nav.html" %} @@ -19,7 +20,7 @@
-

전산 재고 현황 — 낱개 기준 ({{ rows|length }})

+

전산 재고 현황 — 낱개 기준 ({{ rows|length }})

현재고 = 입고 − 출고 + 조정 + 재고조사반영 (콤보는 낱개로 분해 반영됨)
@@ -37,7 +38,7 @@ {% for r in rows %} {{ r.item_code }} - {{ r.item_name }} + {{ r.item_name }} {{ r.current_qty }} {{ r.last_stocktake_date or '—' }} {{ r.last_qty if r.last_qty is not none else '—' }} @@ -67,7 +68,7 @@ {% for s in set_rows %} {{ s.set_code }} - {{ s.set_name }} + {{ s.set_name }} {{ s.qty }} {% endfor %} diff --git a/app/modules/malaysia/templates/malaysia/movements.html b/app/modules/malaysia/templates/malaysia/movements.html index e1775ac..3c03443 100644 --- a/app/modules/malaysia/templates/malaysia/movements.html +++ b/app/modules/malaysia/templates/malaysia/movements.html @@ -14,6 +14,7 @@ {% block content %}
+ {% include "malaysia/_i18n.html" %} {% set active_tab = 'move' %} {% include "malaysia/_nav.html" %} @@ -53,7 +54,7 @@ {% for it in individual_items %} {{ it.item_code }} - {{ it.item_name }} + {{ it.item_name }} {% endfor %} @@ -72,7 +73,7 @@ {% for it in set_items %} {{ it.item_code }} - {{ it.item_name }} + {{ it.item_name }} {% endfor %} @@ -86,7 +87,7 @@
-

이동 이력{% if filter_date %} · {{ filter_date }}{% endif %}

+

이동 이력{% if filter_date %} · {{ filter_date }}{% endif %}

diff --git a/app/modules/malaysia/templates/malaysia/stocktake_detail.html b/app/modules/malaysia/templates/malaysia/stocktake_detail.html index 630f5a8..1e3aa0a 100644 --- a/app/modules/malaysia/templates/malaysia/stocktake_detail.html +++ b/app/modules/malaysia/templates/malaysia/stocktake_detail.html @@ -14,6 +14,7 @@ {% block content %}
+ {% include "malaysia/_i18n.html" %} @@ -23,7 +24,7 @@
-

재고조사 #{{ stocktake.id }}

+

재고조사 #{{ stocktake.id }}

날짜
{{ stocktake.stocktake_date }}
창고
{{ stocktake.warehouse_code }}
@@ -56,7 +57,7 @@ {% for it in individual_items %} {{ it.item_code }} - {{ it.item_name }} + {{ it.item_name }} @@ -76,7 +77,7 @@ {% for it in set_items %} {{ it.item_code }} - {{ it.item_name }} + {{ it.item_name }} diff --git a/app/modules/malaysia/templates/malaysia/stocktakes.html b/app/modules/malaysia/templates/malaysia/stocktakes.html index bb6c0e1..95bc1b7 100644 --- a/app/modules/malaysia/templates/malaysia/stocktakes.html +++ b/app/modules/malaysia/templates/malaysia/stocktakes.html @@ -1,7 +1,8 @@ {% extends "erp_base.html" %} {% block content %} -
+
+ {% include "malaysia/_i18n.html" %} {% set active_tab = 'stocktake' %} {% include "malaysia/_nav.html" %} @@ -23,7 +24,7 @@
-

조사 목록 ({{ stocktakes|length }})

+

조사 목록 ({{ stocktakes|length }})

diff --git a/app/static/malaysia.js b/app/static/malaysia.js new file mode 100644 index 0000000..9b163ac --- /dev/null +++ b/app/static/malaysia.js @@ -0,0 +1,130 @@ +/* 말레이시아 재고관리 — 화면 한글/영문 실시간 토글. + * + * - UI 고정 문구: 아래 KO_EN 사전으로 치환(요소 텍스트 = 한글 키). + * 대상 셀렉터는 UI 크롬(제목/헤더/버튼/라벨/배지/옵션/안내문)으로 한정 → + * 데이터 셀(상품코드/수량)은 건드리지 않음. + * - 상품명: 서버가 data-ko / data-en 을 함께 렌더 → 언어에 맞게 textContent 교체. + * - 선택값은 localStorage('mys_lang') 에 저장, 모든 화면 공통 적용. + */ +(function () { + "use strict"; + + var KO_EN = { + // 탭 / 공통 + "재고 현황": "Stock Status", + "입출고": "In / Out", + "일일 재고조사": "Daily Stocktake", + "창고": "Warehouse", + "날짜": "Date", + "메모": "Memo", + "상태": "Status", + // 재고현황 + "전산 재고 현황 — 낱개 기준": "System Stock — by Single", + "현재고 = 입고 − 출고 + 조정 + 재고조사반영 (콤보는 낱개로 분해 반영됨)": + "Current = IN − OUT + ADJUST + Stocktake (combos exploded to singles)", + "전산재고": "System Qty", + "조사수량": "Stocktake Qty", + "차이": "Diff", + "콤보 재고 (세트 단위)": "Combo Stock (by set)", + "재고조사 입력 없음": "No stocktake input", + "표시할 재고가 없습니다.": "No stock to display.", + "콤보 재고 입력이 없습니다.": "No combo stock input.", + // 입출고 + "등록 옵션": "Options", + "이동 종류 (낱개)": "Type (single)", + "IN (입고)": "IN (In)", + "OUT (출고)": "OUT (Out)", + "ADJUST (조정 ±)": "ADJUST (±)", + "일괄 적용": "Apply All", + "낱개 상품": "Single Products", + "콤보 상품": "Combo Products", + "이동 이력": "Movement History", + "전체": "All", + "날짜해제": "Clear date", + "이동 이력이 없습니다.": "No movements.", + // 재고조사 목록 + "재고조사 생성": "New Stocktake", + "조사 날짜": "Date", + "생성": "Create", + "생성 후 상세에서 낱개/세트 수량을 입력하고 확정하세요.": + "After creating, enter single/set qty in detail and finalize.", + "조사 목록": "Stocktake List", + "열기": "Open", + "삭제": "Delete", + "재고조사가 없습니다.": "No stocktakes.", + "확정": "Final", + "취소": "Cancel", + "작성중": "Draft", + // 재고조사 상세 + "재고조사": "Stocktake", + "◀◀ 조사 목록": "◀◀ List", + "확정시각": "Finalized at", + "입력 저장": "Save", + "확정 (전산 반영)": "Finalize (apply)", + "삭제 (슈퍼관리자)": "Delete (super)", + "최종 계산 (낱개 기준)": "Final Calc (by single)", + "total_qty = direct_qty(낱개 직접) + from_set_qty(콤보 분해)": + "total_qty = direct_qty (single) + from_set_qty (combo)", + "입력된 수량이 없습니다.": "No quantities entered.", + // 표 헤더(한글만) + "이동일": "Date", + }; + + var EN_KO = {}; + Object.keys(KO_EN).forEach(function (k) { EN_KO[KO_EN[k]] = k; }); + + var SEL = [ + ".mys h1", ".mys h2", ".mys h3", + ".mys th", + ".mys label > span", + ".mys button", + ".mys a.erp-btn", + ".mys .erp-muted", + ".mys option", + ".mys .erp-badge", + ".mys .i18n", + ].join(","); + + function applyLang(lang) { + // 1) 상품명(한/영 동시 보유) + document.querySelectorAll(".mys [data-ko][data-en]").forEach(function (el) { + el.textContent = (lang === "en") ? el.getAttribute("data-en") + : el.getAttribute("data-ko"); + }); + // 2) UI 고정 문구 + document.querySelectorAll(SEL).forEach(function (el) { + // 자식 요소가 있는 컨테이너는 건너뜀(.i18n 로 명시한 경우만 허용) + if (el.children.length && !el.classList.contains("i18n")) return; + if (el.hasAttribute("data-ko") && el.hasAttribute("data-en")) return; // 이미 처리됨 + if (el.getAttribute("data-o") === null) { + el.setAttribute("data-o", (el.textContent || "").trim()); + } + var ko = el.getAttribute("data-o"); + if (lang === "en") { + if (KO_EN[ko] !== undefined) el.textContent = KO_EN[ko]; + } else { + el.textContent = ko; + } + }); + // 3) 토글 버튼 라벨 + var btn = document.getElementById("mys-lang-toggle"); + if (btn) btn.textContent = (lang === "en") ? "한글" : "ENG"; + document.documentElement.setAttribute("data-mys-lang", lang); + } + + function current() { + return localStorage.getItem("mys_lang") === "en" ? "en" : "ko"; + } + + function toggle() { + var next = current() === "en" ? "ko" : "en"; + localStorage.setItem("mys_lang", next); + applyLang(next); + } + + document.addEventListener("DOMContentLoaded", function () { + var btn = document.getElementById("mys-lang-toggle"); + if (btn) btn.addEventListener("click", toggle); + applyLang(current()); + }); +})();
#DateWarehouseStatusBy