chore: initial import

This commit is contained in:
liangjian
2026-06-29 09:42:53 +08:00
commit 9fea127de1
241 changed files with 82767 additions and 0 deletions

View File

@@ -0,0 +1,314 @@
const fs = require('fs')
const path = require('path')
const vm = require('vm')
const projectRoot = path.resolve(__dirname, '..')
const messagesFile = path.join(projectRoot, 'locales', 'messages.js')
const targetRoots = [
path.join(projectRoot, 'pages'),
path.join(projectRoot, 'pkgAccount'),
path.join(projectRoot, 'pkgBooking'),
path.join(projectRoot, 'pkgExplore'),
path.join(projectRoot, 'pkgService')
]
const ignoredPaths = ['.history', 'unpackage', 'node_modules']
function walk(dir, files = []) {
const entries = fs.readdirSync(dir, { withFileTypes: true })
for (const entry of entries) {
const fullPath = path.join(dir, entry.name)
if (ignoredPaths.some((segment) => fullPath.includes(`${path.sep}${segment}${path.sep}`))) {
continue
}
if (entry.isDirectory()) {
walk(fullPath, files)
continue
}
if (entry.isFile() && fullPath.endsWith('.vue')) {
files.push(fullPath)
}
}
return files
}
function createBaseMessages() {
return {
zh: {
navigation: {
routes: {
'pages/index/index': '绿居公寓',
'pkgAccount/login/login': '登录',
'pkgAccount/register/register': '注册账号',
'pkgAccount/auth_result/auth_result': '实名结果',
'pkgAccount/registration_records/registration_records': '注册记录',
'pkgBooking/book_viewing/book_viewing': '预约看房',
'pkgBooking/book/book': '预订确认',
'pkgBooking/pay/pay': '在线支付',
'pkgBooking/booking_detail/booking_detail': '预订详情',
'pkgBooking/booking_list/booking_list': '预订记录',
'pkgService/application_detail/application_detail': '申请详情',
'pkgService/my_application/my_application': '我的申请',
'pkgService/my_contract/my_contract': '我的合同',
'pkgService/contract_detail/contract_detail': '合同详情',
'pkgService/contract_sign/contract_sign': '合同签约',
'pkgService/message_detail/message_detail': '消息详情',
'pkgService/submit_request/submit_request': '我要提交',
'pkgService/service_stub/service_stub': '业务办理',
'pkgService/utility_recharge/utility_recharge': '水电充值',
'pkgService/smart_control/smart_control': '智能控制',
'pkgService/device_control/device_control': '设备控制',
'pkgExplore/filter/filter': '数据筛选',
'pkgExplore/sign/sign': '签到打卡',
'pkgExplore/download/download': '资料图库',
'pkgExplore/room_detail/room_detail': '房型详情',
'pkgExplore/store_detail/store_detail': '小区详情',
'pkgExplore/vr_preview/vr_preview': 'VR看房'
}
},
pkgAccount: {
registration_records: {
navTitle: '注册记录',
providerUnavailableTitle: '当前无法获取微信身份',
providerUnavailableDesc: '请在微信小程序中打开后,再查看当前微信账号提交的注册记录。',
registrationFallbackTitle: '人员注册申请',
accountLabel: '注册账号',
phoneLabel: '手机号',
idNumberLabel: '证件号',
submittedAtLabel: '提交时间',
approvedAtLabel: '审批时间',
rejectReasonLabel: '驳回原因',
approvalRemarkLabel: '审批意见',
loadingMore: '加载中...',
noMore: '没有更多记录了',
pullUpMore: '上拉加载更多',
emptyTitle: '暂无注册记录',
emptyDesc: '当前微信账号还没有提交过人员注册申请。',
goRegister: '去提交注册申请',
loadingTitle: '注册记录加载中',
loadingDesc: '正在同步当前微信账号提交的注册申请记录,请稍候。',
statusAll: '全部',
statusPending: '审核中',
statusApproved: '已通过',
statusRejected: '已驳回',
statusProcessing: '处理中',
loadError: '注册记录加载失败'
}
}
},
en: {
navigation: {
routes: {
'pages/index/index': 'Luju Apartments',
'pkgAccount/login/login': 'Sign In',
'pkgAccount/register/register': 'Register',
'pkgAccount/auth_result/auth_result': 'Verification Result',
'pkgAccount/registration_records/registration_records': 'Registration Records',
'pkgBooking/book_viewing/book_viewing': 'Book Viewing',
'pkgBooking/book/book': 'Booking Confirm',
'pkgBooking/pay/pay': 'Online Payment',
'pkgBooking/booking_detail/booking_detail': 'Booking Detail',
'pkgBooking/booking_list/booking_list': 'Booking Records',
'pkgService/application_detail/application_detail': 'Application Detail',
'pkgService/my_application/my_application': 'My Applications',
'pkgService/my_contract/my_contract': 'My Contracts',
'pkgService/contract_detail/contract_detail': 'Contract Detail',
'pkgService/contract_sign/contract_sign': 'Contract Signing',
'pkgService/message_detail/message_detail': 'Message Detail',
'pkgService/submit_request/submit_request': 'Submit Request',
'pkgService/service_stub/service_stub': 'Service Center',
'pkgService/utility_recharge/utility_recharge': 'Utility Recharge',
'pkgService/smart_control/smart_control': 'Smart Control',
'pkgService/device_control/device_control': 'Device Control',
'pkgExplore/filter/filter': 'Filter',
'pkgExplore/sign/sign': 'Check In',
'pkgExplore/download/download': 'Gallery',
'pkgExplore/room_detail/room_detail': 'Room Detail',
'pkgExplore/store_detail/store_detail': 'Community Detail',
'pkgExplore/vr_preview/vr_preview': 'VR Viewing'
}
},
pkgAccount: {
registration_records: {
navTitle: 'Registration Records',
providerUnavailableTitle: 'Unable to access Wechat identity',
providerUnavailableDesc: 'Please open this page in Wechat Mini Program to view registration records submitted by this Wechat account.',
registrationFallbackTitle: 'Registration Application',
accountLabel: 'Account',
phoneLabel: 'Phone',
idNumberLabel: 'ID Number',
submittedAtLabel: 'Submitted At',
approvedAtLabel: 'Approved At',
rejectReasonLabel: 'Rejection Reason',
approvalRemarkLabel: 'Review Notes',
loadingMore: 'Loading...',
noMore: 'No more records',
pullUpMore: 'Pull up to load more',
emptyTitle: 'No registration records',
emptyDesc: 'This Wechat account has not submitted any registration application yet.',
goRegister: 'Submit Registration',
loadingTitle: 'Loading registration records',
loadingDesc: 'Syncing registration records submitted by this Wechat account. Please wait.',
statusAll: 'All',
statusPending: 'Under Review',
statusApproved: 'Approved',
statusRejected: 'Rejected',
statusProcessing: 'Processing',
loadError: 'Failed to load registration records'
}
}
}
}
}
function extractObjectLiteral(source, startIndex) {
const objectStart = source.indexOf('{', startIndex)
if (objectStart < 0) {
return ''
}
let depth = 0
let inString = false
let stringQuote = ''
let escaped = false
for (let index = objectStart; index < source.length; index += 1) {
const char = source[index]
if (inString) {
if (escaped) {
escaped = false
} else if (char === '\\') {
escaped = true
} else if (char === stringQuote) {
inString = false
stringQuote = ''
}
continue
}
if (char === '\'' || char === '"' || char === '`') {
inString = true
stringQuote = char
continue
}
if (char === '{') {
depth += 1
continue
}
if (char === '}') {
depth -= 1
if (depth === 0) {
return source.slice(objectStart, index + 1)
}
}
}
return ''
}
function extractI18nObject(source) {
const marker = 'i18n:'
const markerIndex = source.indexOf(marker)
if (markerIndex < 0) {
return null
}
const objectLiteral = extractObjectLiteral(source, markerIndex)
if (!objectLiteral) {
return null
}
try {
return vm.runInNewContext(`(${objectLiteral})`)
} catch (error) {
return null
}
}
function setNestedValue(target, namespace, value) {
const segments = namespace.split('.').filter(Boolean)
const lastSegment = segments.pop()
let current = target
for (const segment of segments) {
if (!current[segment] || typeof current[segment] !== 'object') {
current[segment] = {}
}
current = current[segment]
}
current[lastSegment] = value
}
function getNamespace(filePath) {
const relativePath = path.relative(projectRoot, filePath).replace(/\\/g, '/')
return relativePath.replace(/\.vue$/, '').replace(/\//g, '.')
}
function updateTranslatorMethod(source, namespace) {
return source
.replace(
/t\s*\(\s*key\s*,\s*params\s*\)\s*\{\s*return this\.\$translate\(this\.i18n,\s*key,\s*params\)\s*\}/m,
`t(key, params) {\n return this.$tm('${namespace}', key, params)\n }`
)
.replace(
/t\s*\(\s*key\s*\)\s*\{\s*return this\.\$translate\(this\.i18n,\s*key\)\s*\}/m,
`t(key) {\n return this.$tm('${namespace}', key)\n }`
)
}
function sortObject(value) {
if (Array.isArray(value)) {
return value.map(sortObject)
}
if (!value || typeof value !== 'object') {
return value
}
return Object.keys(value).sort().reduce((result, key) => {
result[key] = sortObject(value[key])
return result
}, {})
}
function toJsLiteral(value, indent = 0) {
const spaces = ' '.repeat(indent)
const childSpaces = ' '.repeat(indent + 1)
if (Array.isArray(value)) {
if (!value.length) {
return '[]'
}
return `[\n${value.map(item => `${childSpaces}${toJsLiteral(item, indent + 1)}`).join(',\n')}\n${spaces}]`
}
if (value && typeof value === 'object') {
const entries = Object.entries(value)
if (!entries.length) {
return '{}'
}
return `{\n${entries.map(([key, child]) => {
const renderedKey = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : JSON.stringify(key)
return `${childSpaces}${renderedKey}: ${toJsLiteral(child, indent + 1)}`
}).join(',\n')}\n${spaces}}`
}
return JSON.stringify(value)
}
function writeMessagesModule(filePath, messages) {
const content = `const messages = ${toJsLiteral(sortObject(messages))}\n\nexport default messages\n`
fs.writeFileSync(filePath, content, 'utf8')
}
function main() {
const messages = createBaseMessages()
const files = targetRoots.flatMap(root => walk(root))
for (const filePath of files) {
const source = fs.readFileSync(filePath, 'utf8')
const i18nObject = extractI18nObject(source)
if (!i18nObject || !i18nObject.zh || !i18nObject.en) {
continue
}
const namespace = getNamespace(filePath)
setNestedValue(messages.zh, namespace, i18nObject.zh)
setNestedValue(messages.en, namespace, i18nObject.en)
const nextSource = updateTranslatorMethod(source, namespace)
if (nextSource !== source) {
fs.writeFileSync(filePath, nextSource, 'utf8')
}
}
writeMessagesModule(messagesFile, messages)
}
main()