Files
biz-mobile-cloud-zax/scripts/generate-route-i18n.mjs
T
2026-08-27 14:29:23 +08:00

223 lines
7.3 KiB
JavaScript

import fs from "fs"
import path from "path"
import { fileURLToPath } from "url"
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const root = path.resolve(__dirname, "..")
const pagesJson = JSON.parse(fs.readFileSync(path.join(root, "src/pages.json"), "utf8"))
/** path -> 默认中文标题(pages.json + 页面内补充) */
const EXTRA_ZH = {
"pages/canteen/detail": "食堂详情",
"pages/canteen/food": "每日菜谱",
"pages/canteen/product-detail": "商品详情",
"pages/merchant/coupon-list": "优惠券",
"pages/boxes/list": "餐桌列表",
"pages/ordering-food/records": "员工报餐记录",
"pages/order/detail": "订单详情",
"pages/wallet/detail": "饭卡",
"pages/wallet/list": "我的钱包",
"pages/wallet/recharge": "充值",
"pages/wallet/recharge-done": "充值结果",
"pages/human-face/list": "人脸管理",
"pages/car/user-car/apply": "申请车辆",
"pages/car/user-car/list": "我的车辆",
"pages/pay/refund-apply": "申请售后",
"pages/pay/refund-history": "售后进度",
"pages/pay/pay-complete": "支付结果",
"pages/pay/scan-pay": "扫码支付",
"pages/pay/transfer-money": "钱包转账",
"pages/tabbar/canteen": "商家",
}
function collectRoutes() {
const map = new Map()
for (const p of pagesJson.pages || []) {
const title = p.style?.navigationBarTitleText
if (title) map.set(p.path, title)
}
for (const pkg of pagesJson.subPackages || []) {
const rootPath = pkg.root
for (const p of pkg.pages || []) {
const sub = String(p.path || "").replace(/^\//, "")
const full = `${rootPath}/${sub}`
const title = p.style?.navigationBarTitleText
if (title) map.set(full, title)
}
}
for (const [k, v] of Object.entries(EXTRA_ZH)) {
map.set(k, v)
}
return map
}
function pathToKey(routePath) {
return routePath.replace(/\//g, ".").replace(/-/g, "_")
}
function toEn(zh) {
const dict = {
我的: "Me",
食堂: "Canteen",
商家: "Merchant",
登录: "Sign In",
注册: "Register",
找回密码: "Forgot Password",
修改密码: "Change Password",
我的地址: "My Addresses",
个人信息: "Profile",
搜索地址: "Search Address",
发现: "Discover",
商城: "Shop",
喜好分析: "Preferences",
订单: "Orders",
商品详情: "Product Details",
超市详情: "Store Details",
商品搜索: "Search Products",
商品管理: "Product Management",
商品信息管理: "Product Info",
商品分类管理: "Categories",
结算: "Checkout",
订餐核销: "Order Verification",
订单确认: "Confirm Order",
后台管理: "Admin",
用户管理: "User Management",
电子钱包: "E-Wallet",
内容: "Content",
设置: "Settings",
账号设置: "Account",
外卖配送录入: "Delivery Entry",
我的外卖: "My Delivery",
报餐: "Meal Booking",
报餐记录: "Meal Records",
报餐数据统计: "Meal Statistics",
报餐详情: "Meal Details",
骑手配送: "Rider Delivery",
配送详情: "Delivery Details",
订单管理: "Order Management",
外送订单详情: "Delivery Order",
广告观看记录: "Ad History",
兑换券使用记录: "Coupon History",
兑换: "Redeem",
食堂详情: "Canteen Details",
每日菜谱: "Daily Menu",
优惠券: "Coupons",
储物柜: "Lockers",
餐桌列表: "Table List",
员工报餐记录: "Staff Meal Records",
订单详情: "Order Details",
饭卡: "Meal Card",
我的钱包: "My Wallet",
充值: "Top Up",
充值结果: "Top Up Result",
人脸管理: "Face Management",
申请车辆: "Apply Vehicle",
我的车辆: "My Vehicles",
申请售后: "Refund Request",
售后进度: "Refund Status",
支付结果: "Payment Result",
扫码支付: "Scan to Pay",
钱包转账: "Transfer",
}
if (dict[zh]) return dict[zh]
if (zh.includes("内容")) return "Content"
return zh
}
function toHk(zh) {
const dict = {
我的: "我的",
食堂: "食堂",
商家: "商家",
登录: "登入",
注册: "註冊",
找回密码: "找回密碼",
修改密码: "修改密碼",
我的地址: "我的地址",
个人信息: "個人信息",
搜索地址: "搜尋地址",
发现: "發現",
商城: "商城",
喜好分析: "喜好分析",
订单: "訂單",
商品详情: "商品詳情",
超市详情: "超市詳情",
商品搜索: "商品搜尋",
商品管理: "商品管理",
商品信息管理: "商品信息管理",
商品分类管理: "商品分類管理",
结算: "結算",
订餐核销: "訂餐核銷",
订单确认: "訂單確認",
后台管理: "後台管理",
用户管理: "用戶管理",
电子钱包: "電子錢包",
设置: "設定",
账号设置: "帳號設定",
外卖配送录入: "外賣配送錄入",
我的外卖: "我的外賣",
报餐: "報餐",
报餐记录: "報餐記錄",
报餐数据统计: "報餐數據統計",
报餐详情: "報餐詳情",
骑手配送: "騎手配送",
配送详情: "配送詳情",
订单管理: "訂單管理",
外送订单详情: "外送訂單詳情",
广告观看记录: "廣告觀看記錄",
兑换券使用记录: "兌換券使用記錄",
兑换: "兌換",
订单详情: "訂單詳情",
饭卡: "飯卡",
我的钱包: "我的錢包",
充值: "充值",
充值结果: "充值結果",
人脸管理: "人臉管理",
申请车辆: "申請車輛",
我的车辆: "我的車輛",
申请售后: "申請售後",
售后进度: "售後進度",
支付结果: "支付結果",
扫码支付: "掃碼支付",
钱包转账: "Transfer",
餐桌列表: "餐桌列表",
员工报餐记录: "員工報餐記錄",
每日菜谱: "每日菜譜",
优惠券: "優惠券",
}
return dict[zh] || zh.replace(/订单/g, "訂單").replace(/设置/g, "設定").replace(/报餐/g, "報餐")
}
const routes = collectRoutes()
const sorted = [...routes.entries()].sort((a, b) => a[0].localeCompare(b[0]))
const routeMap = {}
const zhTitles = {}
const enTitles = {}
const hkTitles = {}
for (const [routePath, zh] of sorted) {
const key = pathToKey(routePath)
routeMap[routePath] = key
zhTitles[key] = zh
enTitles[key] = toEn(zh)
hkTitles[key] = toHk(zh)
}
function emitTs(obj, exportName) {
const lines = Object.entries(obj)
.sort(([a], [b]) => a.localeCompare(b))
.map(([k, v]) => `\t\t\t${k}: ${JSON.stringify(v)},`)
return `export const ${exportName} = {\n\t\troute: {\n${lines.join("\n")}\n\t\t},\n}\n`
}
const outDir = path.join(root, "src/i18n/route-titles")
fs.mkdirSync(outDir, { recursive: true })
fs.writeFileSync(path.join(outDir, "zh-cn.ts"), `export default ${JSON.stringify({ route: zhTitles }, null, "\t").replace(/"(\w+)":/g, "$1:")}\n`)
fs.writeFileSync(path.join(outDir, "en.ts"), `export default ${JSON.stringify({ route: enTitles }, null, "\t").replace(/"(\w+)":/g, "$1:")}\n`)
fs.writeFileSync(path.join(outDir, "zh-hk.ts"), `export default ${JSON.stringify({ route: hkTitles }, null, "\t").replace(/"(\w+)":/g, "$1:")}\n`)
const mapContent = `/** 自动生成:npm run i18n:routes */\nexport const ROUTE_SUBKEY_MAP: Record<string, string> = ${JSON.stringify(routeMap, null, "\t")}\n\nexport function normalizeRoutePath(route = ""): string {\n\tif (!route) return ""\n\treturn route.startsWith("/") ? route.slice(1) : route\n}\n\nexport function resolveRouteSubKey(route = ""): string {\n\tconst path = normalizeRoutePath(route)\n\treturn ROUTE_SUBKEY_MAP[path] || ""\n}\n`
fs.writeFileSync(path.join(root, "src/i18n/route-map.ts"), mapContent)
console.log("generated", sorted.length, "route titles")