refactor: 国际化文本迁移至全局 locales/messages.js

将组件级 i18n 对象重构为统一由全局 locales/messages.js 管理,确保中英文语言切换时正确显示对应文本。

- 新增 utils/i18n.js 国际化工具函数
- 更新 store/$t.mixin.js 翻译混入逻辑
- 迁移 pkgService、pkgBooking、pkgAccount、pkgExplore、pages 等共 58 个组件的中英文文本至全局消息表
This commit is contained in:
liangjian
2026-07-24 13:43:41 +08:00
parent 445bd850f4
commit 6e721ccc7e
58 changed files with 1810 additions and 4065 deletions

View File

@@ -1,12 +1,12 @@
<template>
<view class="message-page tn-safe-area-inset-bottom">
<tn-nav-bar :isBack="false" :bottomShadow="false" backgroundColor="transparent" :customBackStyle="{ transition: 'all 0.3s ease' }">
<view class="tn-text-bold tn-text-xl tn-color-black">{{ t('title') }}</view>
<view class="tn-text-bold tn-text-xl tn-color-black">{{ $tr('消息中心') }}</view>
</tn-nav-bar>
<view class="message-content tn-padding" :style="{ paddingTop: vuex_custom_bar_height + 'px' }">
<view class="page-header tn-margin-bottom-xl">
<view class="tn-text-bold tn-color-black page-title">{{ t('title') }}</view>
<view class="tn-text-bold tn-color-black page-title">{{ $tr('消息中心') }}</view>
<view class="tn-color-gray tn-text-sm tn-margin-top-xs">{{ subtitleText }}</view>
</view>
@@ -16,31 +16,31 @@
<text class="tn-icon-notice-fill tn-text-xxl"></text>
<view v-if="stats.systemUnread" class="badge tn-flex tn-flex-col-center tn-flex-row-center">{{ stats.systemUnread }}</view>
</view>
<view class="tn-text-sm tn-margin-top-sm tn-text-bold tn-color-black">{{ t('system') }}</view>
<view class="tn-text-sm tn-margin-top-sm tn-text-bold tn-color-black">{{ $tr('系统通知') }}</view>
</view>
<view class="category-item tn-flex tn-flex-direction-column tn-flex-col-center">
<view class="category-icon-box normal-box">
<text class="tn-icon-coupon-fill tn-text-xxl"></text>
<view v-if="stats.paymentUnread" class="badge tn-flex tn-flex-col-center tn-flex-row-center">{{ stats.paymentUnread }}</view>
</view>
<view class="tn-text-sm tn-margin-top-sm tn-text-bold tn-color-gray">{{ t('payment') }}</view>
<view class="tn-text-sm tn-margin-top-sm tn-text-bold tn-color-gray">{{ $tr('缴费账单') }}</view>
</view>
<view class="category-item tn-flex tn-flex-direction-column tn-flex-col-center">
<view class="category-icon-box normal-box">
<text class="tn-icon-service-fill tn-text-xxl"></text>
<view v-if="stats.butlerUnread" class="badge tn-flex tn-flex-col-center tn-flex-row-center">{{ stats.butlerUnread }}</view>
</view>
<view class="tn-text-sm tn-margin-top-sm tn-text-bold tn-color-gray">{{ t('butler') }}</view>
<view class="tn-text-sm tn-margin-top-sm tn-text-bold tn-color-gray">{{ $tr('管家消息') }}</view>
</view>
</view>
<view v-if="inspectionList.length" class="section-card tn-margin-bottom">
<view class="section-head">
<view>
<view class="section-title">{{ t('inspectionTitle') }}</view>
<view class="section-desc">{{ t('inspectionDesc') }}</view>
<view class="section-title">{{ $tr('巡查提醒') }}</view>
<view class="section-desc">{{ $tr('根据当前入住订单自动汇总巡查提醒记录') }}</view>
</view>
<view class="section-chip is-primary">{{ inspectionReminderCount }} {{ t('inspectionCountUnit') }}</view>
<view class="section-chip is-primary">{{ inspectionReminderCount }} {{ $tr('条提醒') }}</view>
</view>
<view
@@ -56,7 +56,7 @@
</view>
<view class="inspection-main">
<view class="inspection-title">{{ record.typeText }}</view>
<view class="inspection-meta">{{ record.roomCode || t('unassignedRoom') }} · {{ record.timeText }}</view>
<view class="inspection-meta">{{ record.roomCode || $tr('未关联房间') }} · {{ record.timeText }}</view>
</view>
</view>
<view class="inspection-chips">
@@ -66,23 +66,23 @@
</view>
<view class="inspection-desc">{{ record.summaryText }}</view>
<view class="inspection-footer">
<view class="inspection-footer-text">{{ t('checkerLabel') }}{{ record.checkerUserCode || '--' }}</view>
<view class="inspection-action">{{ t('viewDetail') }}</view>
<view class="inspection-footer-text">{{ $tr('检查人:') }}{{ record.checkerUserCode || '--' }}</view>
<view class="inspection-action">{{ $tr('查看详情') }}</view>
</view>
</view>
</view>
<view class="tn-flex tn-flex-row-between tn-flex-col-bottom tn-margin-bottom">
<view class="tn-text-bold tn-text-lg tn-color-black">{{ t('recentMessages') }}</view>
<view class="tn-text-bold tn-text-lg tn-color-black">{{ $tr('近期消息') }}</view>
<view class="tn-text-sm tn-color-gray" @click="handleReadAll">
<text class="tn-icon-delete tn-margin-right-xs"></text>{{ t('markNotificationRead') }}
<text class="tn-icon-delete tn-margin-right-xs"></text>{{ $tr('通知已读') }}
</view>
</view>
<view class="msg-list">
<view v-if="loading" class="empty-card">
<view class="tn-text-bold tn-text-lg tn-color-black">{{ t('loadingTitle') }}</view>
<view class="tn-color-gray tn-text-sm tn-margin-top-xs">{{ t('loadingDesc') }}</view>
<view class="tn-text-bold tn-text-lg tn-color-black">{{ $tr('消息加载中') }}</view>
<view class="tn-color-gray tn-text-sm tn-margin-top-xs">{{ $tr('正在同步系统通知和巡查提醒,请稍候。') }}</view>
</view>
<view
v-for="(msg, index) in messages"
@@ -103,8 +103,8 @@
</view>
</view>
<view v-if="!loading && !messages.length && !inspectionList.length" class="empty-card">
<view class="tn-text-bold tn-text-lg tn-color-black">{{ t('emptyTitle') }}</view>
<view class="tn-color-gray tn-text-sm tn-margin-top-xs">{{ t('emptyDesc') }}</view>
<view class="tn-text-bold tn-text-lg tn-color-black">{{ $tr('暂无消息') }}</view>
<view class="tn-color-gray tn-text-sm tn-margin-top-xs">{{ $tr('系统通知和巡查提醒会在这里显示。') }}</view>
</view>
</view>
@@ -117,7 +117,7 @@
<view class="inspect-popup-head">
<view>
<view class="inspect-popup-title">{{ activeInspectionRecord.typeText }}</view>
<view class="inspect-popup-subtitle">{{ activeInspectionRecord.roomCode || t('unassignedRoom') }} · {{ activeInspectionRecord.timeText }}</view>
<view class="inspect-popup-subtitle">{{ activeInspectionRecord.roomCode || $tr('未关联房间') }} · {{ activeInspectionRecord.timeText }}</view>
</view>
<view class="inspect-popup-close" @click="closeInspectionPopup">
<text class="tn-icon-close"></text>
@@ -127,39 +127,39 @@
<scroll-view scroll-y class="inspect-popup-body">
<view class="inspect-detail-card">
<view class="inspect-detail-row">
<text class="inspect-detail-label">{{ t('inspectionChecker') }}</text>
<text class="inspect-detail-label">{{ $tr('检查人') }}</text>
<text class="inspect-detail-value">{{ activeInspectionRecord.checkerUserCode || '--' }}</text>
</view>
<view class="inspect-detail-row">
<text class="inspect-detail-label">{{ t('inspectionResult') }}</text>
<text class="inspect-detail-label">{{ $tr('检查结果') }}</text>
<text class="inspect-detail-value">{{ activeInspectionRecord.resultText }}</text>
</view>
<view class="inspect-detail-row">
<text class="inspect-detail-label">{{ t('inspectionStatus') }}</text>
<text class="inspect-detail-label">{{ $tr('当前状态') }}</text>
<text class="inspect-detail-value">{{ activeInspectionRecord.statusText }}</text>
</view>
</view>
<view v-if="activeInspectionRecord.remark" class="inspect-block">
<view class="inspect-block-title">{{ t('inspectionRemarkTitle') }}</view>
<view class="inspect-block-title">{{ $tr('检查备注') }}</view>
<view class="inspect-block-content">{{ activeInspectionRecord.remark }}</view>
</view>
<view v-if="activeInspectionRecord.items.length" class="inspect-block">
<view class="inspect-block-title">{{ t('inspectionItemsTitle') }}</view>
<view class="inspect-block-title">{{ $tr('检查项明细') }}</view>
<view
v-for="(detail, index) in activeInspectionRecord.items"
:key="detail.code || index"
class="inspect-item"
>
<view class="inspect-item-head">
<view class="inspect-item-title">{{ t('inspectionItemPrefix', { index: index + 1 }) }}</view>
<view class="inspect-item-title">{{ $tr('检查项 {index}', { index: index + 1 }) }}</view>
<view class="inspect-item-tag">{{ getCheckTypeLabel(detail.checkType) }}</view>
</view>
<view v-if="detail.problemDescription" class="inspect-item-text">{{ t('problemLabel') }}{{ detail.problemDescription }}</view>
<view v-if="detail.remark" class="inspect-item-text">{{ t('remarkLabel') }}{{ detail.remark }}</view>
<view v-if="detail.problemDescription" class="inspect-item-text">{{ $tr('问题:') }}{{ detail.problemDescription }}</view>
<view v-if="detail.remark" class="inspect-item-text">{{ $tr('备注:') }}{{ detail.remark }}</view>
<view v-if="detail.compensationAmount !== '' && detail.compensationAmount !== null && detail.compensationAmount !== undefined" class="inspect-item-text">
{{ t('compensationLabel') }}{{ detail.compensationAmount }}
{{ $tr('赔付金额:') }}{{ detail.compensationAmount }}
</view>
<view v-if="detail.imageUrls.length" class="inspect-image-list">
<image
@@ -176,7 +176,7 @@
</scroll-view>
<view class="inspect-popup-foot">
<view class="inspect-popup-btn" @click="closeInspectionPopup">{{ t('acknowledged') }}</view>
<view class="inspect-popup-btn" @click="closeInspectionPopup">{{ $tr('我知道了') }}</view>
</view>
</view>
</view>
@@ -214,104 +214,6 @@ export default {
paymentUnread: 0,
butlerUnread: 0
},
i18n: {
zh: {
title: '消息中心',
subtitle: '你有 {count} 条未读消息待处理',
system: '系统通知',
payment: '缴费账单',
butler: '管家消息',
inspectionTitle: '巡查提醒',
inspectionDesc: '根据当前入住订单自动汇总巡查提醒记录',
inspectionCountUnit: '条提醒',
recentMessages: '近期消息',
markNotificationRead: '通知已读',
loadingTitle: '消息加载中',
loadingDesc: '正在同步系统通知和巡查提醒,请稍候。',
emptyTitle: '暂无消息',
emptyDesc: '系统通知和巡查提醒会在这里显示。',
noUnreadNotification: '暂无未读通知',
inspectionNeedManualHandle: '巡查提醒需单独查看处理',
remoteMarkedRead: '系统通知已全部标记为已读',
remoteMarkedReadWithInspection: '系统通知已标记,巡查提醒需单独处理',
unassignedRoom: '未关联房间',
checkerLabel: '检查人:',
viewDetail: '查看详情',
inspectionChecker: '检查人',
inspectionResult: '检查结果',
inspectionStatus: '当前状态',
inspectionRemarkTitle: '检查备注',
inspectionItemsTitle: '检查项明细',
inspectionItemPrefix: '检查项 {index}',
problemLabel: '问题:',
remarkLabel: '备注:',
compensationLabel: '赔付金额:',
acknowledged: '我知道了',
notificationFallbackTitle: '系统通知',
notificationFallbackDesc: '您有一条新的系统消息',
inspectionSummaryFallback: '巡查提醒,请查看详情',
checkTypeRoutine: '日常检查',
checkTypeCheckout: '退房检查',
checkTypeSpecial: '专项检查',
checkTypeDefault: '检查记录',
checkStatusPending: '待确认',
checkStatusProcessing: '处理中',
checkStatusDone: '已完成',
checkStatusDefault: '状态待定',
checkResultNormal: '正常',
checkResultFix: '需整改',
checkResultReview: '待复核',
checkResultDefault: '检查结果'
},
en: {
title: 'Messages',
subtitle: 'You have {count} unread messages',
system: 'System',
payment: 'Payment',
butler: 'Butler',
inspectionTitle: 'Inspection',
inspectionDesc: 'Inspection reminders are summarized automatically.',
inspectionCountUnit: 'alerts',
recentMessages: 'Recent',
markNotificationRead: 'Read Notifications',
loadingTitle: 'Loading Messages',
loadingDesc: 'Syncing notifications and inspections.',
emptyTitle: 'No Messages',
emptyDesc: 'Notifications and inspection reminders will appear here.',
noUnreadNotification: 'No unread notifications',
inspectionNeedManualHandle: 'Inspection reminders need manual handling',
remoteMarkedRead: 'Notifications marked as read',
remoteMarkedReadWithInspection: 'Notifications marked as read, inspection reminders still need handling',
unassignedRoom: 'Room Unlinked',
checkerLabel: 'Inspector: ',
viewDetail: 'Details',
inspectionChecker: 'Inspector',
inspectionResult: 'Result',
inspectionStatus: 'Status',
inspectionRemarkTitle: 'Inspection Remark',
inspectionItemsTitle: 'Inspection Items',
inspectionItemPrefix: 'Item {index}',
problemLabel: 'Problem: ',
remarkLabel: 'Remark: ',
compensationLabel: 'Compensation: ',
acknowledged: 'Got It',
notificationFallbackTitle: 'System Notification',
notificationFallbackDesc: 'You have a new system message',
inspectionSummaryFallback: 'Inspection reminder, tap to view details.',
checkTypeRoutine: 'Routine Check',
checkTypeCheckout: 'Checkout Check',
checkTypeSpecial: 'Special Check',
checkTypeDefault: 'Inspection Record',
checkStatusPending: 'Pending',
checkStatusProcessing: 'Processing',
checkStatusDone: 'Completed',
checkStatusDefault: 'Status Pending',
checkResultNormal: 'Normal',
checkResultFix: 'Needs Fix',
checkResultReview: 'Pending Review',
checkResultDefault: 'Inspection Result'
}
}
}
},
computed: {
@@ -319,7 +221,7 @@ export default {
return this.$getLanguage()
},
subtitleText() {
const text = this.t('subtitle').replace('{count}', this.stats.totalUnread)
const text = this.$tr('你有 {count} 条未读消息待处理').replace('{count}', this.stats.totalUnread)
return this.language === 'en' ? compactEnglishText(text, 48) : text
},
inspectionReminderCount() {
@@ -338,9 +240,6 @@ export default {
load(force = false) {
return this.refreshMessages(force)
},
t(key, params) {
return this.$tm('pages.index.component.MessageCenterTab', key, params)
},
getStoreUser() {
return (this.$store && this.$store.state && this.$store.state.vuex_user) || {}
},
@@ -471,15 +370,15 @@ export default {
id: item.code || item.id || `remote-${Date.now()}`,
code: item.code || '',
category: this.resolveRemoteCategory(item, title, desc),
titleZh: rawTitleZh || this.t('notificationFallbackTitle'),
titleEn: rawTitleEn || this.t('notificationFallbackTitle'),
descZh: rawDescZh || this.t('notificationFallbackDesc'),
descEn: rawDescEn || this.t('notificationFallbackDesc'),
contentZh: rawDescZh || this.t('notificationFallbackDesc'),
contentEn: rawDescEn || this.t('notificationFallbackDesc'),
title: title || this.t('notificationFallbackTitle'),
desc: desc || this.t('notificationFallbackDesc'),
content: desc || this.t('notificationFallbackDesc'),
titleZh: rawTitleZh || this.$tr('系统通知'),
titleEn: rawTitleEn || this.$tr('系统通知'),
descZh: rawDescZh || this.$tr('您有一条新的系统消息'),
descEn: rawDescEn || this.$tr('您有一条新的系统消息'),
contentZh: rawDescZh || this.$tr('您有一条新的系统消息'),
contentEn: rawDescEn || this.$tr('您有一条新的系统消息'),
title: title || this.$tr('系统通知'),
desc: desc || this.$tr('您有一条新的系统消息'),
content: desc || this.$tr('您有一条新的系统消息'),
time: formatMessageDateTime(item.createTime || item.updateTime || ''),
rawTime: item.createTime || item.updateTime || '',
unread: item.isRead !== true,
@@ -501,7 +400,7 @@ export default {
}))
: []
const issueTexts = items.map(item => item.problemDescription || item.remark || '').filter(Boolean)
const summaryText = record.remark || issueTexts[0] || this.t('inspectionSummaryFallback')
const summaryText = record.remark || issueTexts[0] || this.$tr('巡查提醒,请查看详情')
return {
code: record.code || '',
roomCode: record.roomCode || '',
@@ -545,27 +444,27 @@ export default {
},
getCheckTypeLabel(value) {
const map = {
0: this.t('checkTypeRoutine'),
1: this.t('checkTypeCheckout'),
2: this.t('checkTypeSpecial')
0: this.$tr('日常检查'),
1: this.$tr('退房检查'),
2: this.$tr('专项检查')
}
return map[Number(value)] || this.t('checkTypeDefault')
return map[Number(value)] || this.$tr('检查记录')
},
getCheckRecordStatusLabel(value) {
const map = {
0: this.t('checkStatusPending'),
1: this.t('checkStatusProcessing'),
2: this.t('checkStatusDone')
0: this.$tr('待确认'),
1: this.$tr('处理中'),
2: this.$tr('已完成')
}
return map[Number(value)] || this.t('checkStatusDefault')
return map[Number(value)] || this.$tr('状态待定')
},
getCheckResultStatusLabel(value) {
const map = {
0: this.t('checkResultNormal'),
1: this.t('checkResultFix'),
2: this.t('checkResultReview')
0: this.$tr('正常'),
1: this.$tr('需整改'),
2: this.$tr('待复核')
}
return map[Number(value)] || this.t('checkResultDefault')
return map[Number(value)] || this.$tr('检查结果')
},
getCheckResultStatusClass(value) {
const map = {
@@ -618,8 +517,8 @@ export default {
if (!unreadRemoteCodes.length) {
uni.showToast({
title: this.inspectionReminderCount
? this.t('inspectionNeedManualHandle')
: this.t('noUnreadNotification'),
? this.$tr('巡查提醒需单独查看处理')
: this.$tr('暂无未读通知'),
icon: 'none'
})
return
@@ -642,8 +541,8 @@ export default {
this.buildMessageView()
uni.showToast({
title: this.inspectionReminderCount
? this.t('remoteMarkedReadWithInspection')
: this.t('remoteMarkedRead'),
? this.$tr('系统通知已标记,巡查提醒需单独处理')
: this.$tr('系统通知已全部标记为已读'),
icon: 'none'
})
},