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

@@ -7,7 +7,7 @@
:customBackStyle="navBarBackStyle"
:fixed="true"
>
<view class="tn-text-bold tn-text-xl tn-color-black" :style="{ opacity: navTitleOpacity }">{{ t('navTitle') }}</view>
<view class="tn-text-bold tn-text-xl tn-color-black" :style="{ opacity: navTitleOpacity }">{{ $tr('失物拾物') }}</view>
</tn-nav-bar>
<scroll-view class="page-scroll" scroll-y :show-scrollbar="false" @scroll="handleScroll">
@@ -15,76 +15,76 @@
<view class="hero-header tn-margin-bottom-xl">
<view class="hero-badge">
<text class="badge-dot"></text>
<text>{{ t('heroBadge') }}</text>
<text>{{ $tr('社区服务') }}</text>
</view>
<view class="hero-title">{{ t('heroTitle') }}</view>
<view class="hero-desc">{{ t('heroDesc') }}</view>
<view class="hero-title">{{ $tr('发布失物或招领信息') }}</view>
<view class="hero-desc">{{ $tr('将失物或拾获信息同步给社区,方便后续核实与快速匹配。') }}</view>
</view>
<view class="form-card">
<view class="block-title">{{ t('formTitle') }}</view>
<view class="block-subtitle">{{ t('formDesc') }}</view>
<view class="block-title">{{ $tr('物品信息') }}</view>
<view class="block-subtitle">{{ $tr('请补充关键字段,必填项越完整,越方便他人联系与认领。') }}</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('typeLabel') }}</view>
<view class="form-label">{{ $tr('发布类型') }}</view>
<picker mode="selector" :range="typeLabels" @change="handleTypeChange">
<view class="form-picker">
{{ selectedTypeLabel || t('typePlaceholder') }}
{{ selectedTypeLabel || $tr('请选择失物或招领') }}
</view>
</picker>
</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('itemTypeLabel') }}</view>
<input v-model="form.itemType" class="form-input" :placeholder="t('itemTypePlaceholder')" maxlength="40" />
<view class="form-label">{{ $tr('物品类型') }}</view>
<input v-model="form.itemType" class="form-input" :placeholder="$tr('例如证件、钥匙、电子设备')" maxlength="40" />
</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('itemNameLabel') }}</view>
<input v-model="form.itemName" class="form-input" :placeholder="t('itemNamePlaceholder')" maxlength="60" />
<view class="form-label">{{ $tr('物品名称') }}</view>
<input v-model="form.itemName" class="form-input" :placeholder="$tr('请输入物品名称')" maxlength="60" />
</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('placeLabel') }}</view>
<input v-model="form.place" class="form-input" :placeholder="t('placePlaceholder')" maxlength="100" />
<view class="form-label">{{ $tr('地点') }}</view>
<input v-model="form.place" class="form-input" :placeholder="$tr('请输入丢失或拾取地点')" maxlength="100" />
</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('whenLabel') }}</view>
<view class="form-label">{{ $tr('时间') }}</view>
<view class="picker-row">
<picker mode="date" :value="form.whenDate" @change="handleDateChange">
<view class="form-picker">{{ form.whenDate || t('selectDate') }}</view>
<view class="form-picker">{{ form.whenDate || $tr('选择日期') }}</view>
</picker>
<picker mode="time" :value="form.whenTime" @change="handleTimeChange">
<view class="form-picker form-picker--time">{{ form.whenTime || t('selectTime') }}</view>
<view class="form-picker form-picker--time">{{ form.whenTime || $tr('选择时间') }}</view>
</picker>
</view>
<view class="field-tip">{{ t('whenTip') }}</view>
<view class="field-tip">{{ $tr('可选,若已知大致时间可一并填写。') }}</view>
</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('contractLabel') }}</view>
<input v-model="form.contract" class="form-input" :placeholder="t('contractPlaceholder')" maxlength="40" />
<view class="form-label">{{ $tr('联系人') }}</view>
<input v-model="form.contract" class="form-input" :placeholder="$tr('请输入联系人')" maxlength="40" />
</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('contractPhoneLabel') }}</view>
<input v-model="form.contractPhone" class="form-input" :placeholder="t('contractPhonePlaceholder')" maxlength="30" />
<view class="form-label">{{ $tr('联系电话') }}</view>
<input v-model="form.contractPhone" class="form-input" :placeholder="$tr('请输入联系电话')" maxlength="30" />
</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('remarkLabel') }}</view>
<view class="form-label">{{ $tr('备注') }}</view>
<textarea
v-model="form.remark"
class="form-textarea"
:placeholder="t('remarkPlaceholder')"
:placeholder="$tr('可补充外观特征、认领说明或其他辅助信息')"
maxlength="300"
></textarea>
<view class="field-counter">{{ (form.remark || '').length }}/300</view>
</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('imagesLabel') }}</view>
<view class="form-label">{{ $tr('现场图片') }}</view>
<tn-image-upload
:key="uploadInstanceKey"
:fileList="form.photos"
@@ -104,11 +104,11 @@
<template #addBtn>
<view class="upload-trigger">
<text class="tn-icon-camera-fill upload-trigger__icon"></text>
<view class="upload-trigger__text">{{ t('uploadImage') }}</view>
<view class="upload-trigger__text">{{ $tr('上传图片') }}</view>
</view>
</template>
</tn-image-upload>
<view class="field-tip">{{ t('imagesTip') }}</view>
<view class="field-tip">{{ $tr('可选,上传现场图或物品图可提升识别效率。') }}</view>
</view>
</view>
</view>
@@ -116,9 +116,9 @@
<view class="floating-submit-bar">
<view class="floating-submit-bar__inner">
<view class="floating-submit-tip">{{ t('submitTip') }}</view>
<view class="floating-submit-tip">{{ $tr('发布前请确认信息准确,系统会按当前语言提交接口。') }}</view>
<view class="submit-btn btn-primary" :class="{ 'submit-btn--disabled': isSubmitting }" @click="submitForm">
<text class="tn-text-bold">{{ isSubmitting ? t('submitting') : t('submitButton') }}</text>
<text class="tn-text-bold">{{ isSubmitting ? $tr('发布中...') : $tr('立即发布') }}</text>
</view>
</view>
</view>
@@ -180,8 +180,8 @@ export default {
},
typeOptions() {
return [
{ value: 1, label: this.t('typeLost'), labelEn: this.t('typeLost') },
{ value: 2, label: this.t('typeFound'), labelEn: this.t('typeFound') }
{ value: 1, label: this.$tr('失物'), labelEn: this.$tr('失物') },
{ value: 2, label: this.$tr('招领'), labelEn: this.$tr('招领') }
]
},
typeLabels() {
@@ -211,9 +211,6 @@ export default {
this.prefillContact()
},
methods: {
t(key, params) {
return this.$tm('pkgService.lost_found_publish.lost_found_publish', key, params)
},
createDefaultForm() {
return {
type: 1,
@@ -288,20 +285,20 @@ export default {
this.form.imageUrls.splice(index, 1)
},
onUploadError() {
uni.showToast({ title: this.t('uploadFailed'), icon: 'none' })
uni.showToast({ title: this.$tr('图片上传失败'), icon: 'none' })
},
onUploadOversize() {
uni.showToast({ title: this.t('uploadOversize'), icon: 'none' })
uni.showToast({ title: this.$tr('单张图片不能超过 5 MB'), icon: 'none' })
},
onUploadExceed() {
uni.showToast({ title: this.t('uploadExceed'), icon: 'none' })
uni.showToast({ title: this.$tr('最多上传 6 张图片'), icon: 'none' })
},
getValidationMessage() {
if (!String(this.form.itemType || '').trim()) return this.t('validateItemType')
if (!String(this.form.itemName || '').trim()) return this.t('validateItemName')
if (!String(this.form.place || '').trim()) return this.t('validatePlace')
if (!String(this.form.contract || '').trim()) return this.t('validateContract')
if (!String(this.form.contractPhone || '').trim()) return this.t('validateContractPhone')
if (!String(this.form.itemType || '').trim()) return this.$tr('请输入物品类型')
if (!String(this.form.itemName || '').trim()) return this.$tr('请输入物品名称')
if (!String(this.form.place || '').trim()) return this.$tr('请输入地点')
if (!String(this.form.contract || '').trim()) return this.$tr('请输入联系人')
if (!String(this.form.contractPhone || '').trim()) return this.$tr('请输入联系电话')
return ''
},
buildSubmitPayload() {
@@ -335,7 +332,7 @@ export default {
lostAndFoundPublish(this.buildSubmitPayload(), this.language)
.then(() => {
uni.showToast({
title: this.t('submitSuccess'),
title: this.$tr('发布成功'),
icon: 'success'
})
this.resetForm()
@@ -347,7 +344,7 @@ export default {
})
.catch((error) => {
uni.showToast({
title: (error && (error.message || error.msg)) || this.t('submitFailed'),
title: (error && (error.message || error.msg)) || this.$tr('发布失败'),
icon: 'none'
})
})