import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import path from "node:path"; import * as dictionaries from "../src/utils/dictionaries.js"; const root = process.cwd(); function readSource(relativePath) { return readFileSync(path.join(root, relativePath), "utf8"); } function assertFormatter(name, samples) { assert.equal(typeof dictionaries[name], "function", `${name} should be exported`); samples.forEach(([value, expected]) => { assert.equal(dictionaries[name](value), expected, `${name} should translate ${value}`); }); } function assertNoRawEnumFallback(name) { const rawCode = "UNTRANSLATED_SAMPLE_ENUM"; assert.notEqual(dictionaries[name](rawCode), rawCode, `${name} must not render raw English enum fallbacks`); assert.match(dictionaries[name](rawCode), /未识别/, `${name} fallback should be Chinese`); } assertFormatter("formatInventoryTxnTypeLabel", [ ["OPENING_IN", "期初入库"], ["PRODUCTION_SURPLUS_IN", "生产余料入库"], ["OUTSOURCING_SURPLUS_IN", "委外余料入库"], ["WIP_IN", "产中入库"], ["WIP_OUT", "产中出库"], ["PRODUCTION_FINISHED_IN", "生产入库"], ["STOCKTAKE_GAIN", "盘库盘盈"], ["STOCKTAKE_LOSS", "盘库盘亏"], ["STOCKTAKE_NEW_LOT", "盘库新增批次"] ]); assertNoRawEnumFallback("formatInventoryTxnTypeLabel"); assertFormatter("formatSourceDocTypeLabel", [ ["OPENING_STOCK", "期初入库"], ["STOCKTAKE", "盘库"], ["PRODUCTION_OUT", "生产出库"], ["OUTSOURCING_OUT", "委外出库"], ["RETURN_OUT", "返工出库"] ]); assertNoRawEnumFallback("formatSourceDocTypeLabel"); assertFormatter("formatWarehouseTypeLabel", [ ["RAW", "原材料库"], ["SEMI", "半成品库"], ["FINISHED", "成品库"], ["AUX", "辅料库"], ["SCRAP", "废料库"], ["RETURN", "退货库"] ]); assertNoRawEnumFallback("formatWarehouseTypeLabel"); assertFormatter("formatItemTypeLabel", [ ["RAW_MATERIAL", "原材料"], ["FINISHED_GOOD", "成品"], ["PRODUCT", "产品"] ]); assertNoRawEnumFallback("formatItemTypeLabel"); assertFormatter("formatPurchaseSourceTypeLabel", [ ["SALES_ORDER", "销售订单采购"], ["STOCKING", "备料采购"] ]); assertNoRawEnumFallback("formatPurchaseSourceTypeLabel"); assertFormatter("formatMiniappRoleLabel", [ ["worker", "员工"], ["manager", "经理"], ["admin", "管理员"] ]); assertNoRawEnumFallback("formatMiniappRoleLabel"); assertFormatter("formatMaintenanceTypeLabel", [ ["PERIODIC", "周期保养"], ["REPAIR", "维修保养"], ["INSPECTION", "点检保养"] ]); assertNoRawEnumFallback("formatMaintenanceTypeLabel"); assertFormatter("formatStocktakeRowStatusLabel", [ ["READY", "可确认"], ["ERROR", "异常"], ["IGNORED", "已忽略"] ]); assertNoRawEnumFallback("formatStocktakeRowStatusLabel"); const dictionarySource = readSource("src/utils/dictionaries.js"); assert.match(dictionarySource, /function normalizeDictionaryKey/, "dictionary lookup should normalize keys"); assert.match(dictionarySource, /function isEnumLikeValue/, "dictionary lookup should identify enum-like fallbacks"); assert.match(dictionarySource, /未识别/, "dictionary fallback should be Chinese"); const tableControlsSource = readSource("src/utils/tableControls.js"); [ "WAREHOUSE_TYPE_LABELS", "ITEM_TYPE_LABELS", "PURCHASE_SOURCE_TYPE_LABELS", "MAINTENANCE_TYPE_LABELS", "MINIAPP_ROLE_LABELS", "STOCKTAKE_ROW_STATUS_LABELS" ].forEach((mapName) => { assert.match(tableControlsSource, new RegExp(mapName), `TableControls search should include ${mapName}`); }); const inventorySource = readSource("src/views/InventoryLedgerView.vue"); assert.match(inventorySource, /formatWarehouseTypeLabel/, "inventory view should use warehouse type formatter"); assert.match(inventorySource, /formatItemTypeLabel/, "inventory view should use item type formatter"); assert.doesNotMatch(inventorySource, /placeholder="如 SALES_OUT、RETURN_IN"/, "inventory ledger filter should not show English examples"); const equipmentSource = readSource("src/views/EquipmentManagementView.vue"); assert.match(equipmentSource, /formatMaintenanceTypeLabel/, "equipment view should translate maintenance types"); assert.doesNotMatch(equipmentSource, /\{\{\s*order\.maintenance_type\s*\}\}/, "equipment view must not render raw maintenance_type"); const employeeSource = readSource("src/views/EmployeeManagementView.vue"); assert.match(employeeSource, /formatPersonRoles/, "employee view should centralize role display formatting"); assert.match(employeeSource, /formatMiniappRoleLabel/, "employee view should translate miniapp role codes"); assert.doesNotMatch(employeeSource, /personnel \/ person_roles/, "employee view should not show raw table names"); const stocktakeSource = readSource("src/components/StocktakeDialog.vue"); assert.match(stocktakeSource, /formatStocktakeRowStatusLabel/, "stocktake dialog should have row status formatter available"); const purchaseSource = readSource("src/views/PurchaseOrderView.vue"); assert.match(purchaseSource, /formatPurchaseSourceTypeLabel/, "purchase order view should translate source_type"); assert.doesNotMatch(purchaseSource, /"source_type",\s*$/m, "purchase order search should not rely on raw source_type only"); console.log("dictionary localization checks passed");