feat: 新增多语言文案并修复动态国际化调用问题

1. 新增多语言文件覆盖组件、页面、公共模块的翻译文案
2. 修复多处动态拼接lang key的调用,增加兜底逻辑避免空值或原始key暴露
3. 补全DIY组件、业务页面的国际化适配
4. 新增P2动态key国际化处理方案文档
This commit is contained in:
2026-06-29 15:29:24 +08:00
parent c3956f7bcd
commit c7810f16f7
115 changed files with 1343 additions and 153 deletions

View File

@@ -8,9 +8,9 @@
<!-- 空状态 -->
<view v-else-if="!content" class="empty-state">
<view class="empty-icon">📄</view>
<text class="empty-title">暂无内容</text>
<text class="empty-desc">该协议内容暂未设置</text>
<button class="empty-button" @click="getcontent">重新加载</button>
<text class="empty-title">{{ $lang('agreement.noContent') }}</text>
<text class="empty-desc">{{ $lang('agreement.noContentDesc') }}</text>
<button class="empty-button" @click="getcontent">{{ $lang('agreement.reload') }}</button>
</view>
<!-- 内容状态 -->

View File

@@ -12,24 +12,24 @@
<!-- PDF 文件预览 -->
<view v-if="fileType === 'pdf'" class="file-viewer">
<web-view v-if="fileUrl" :src="fileUrl"></web-view>
<view v-else class="error-message">文件地址不存在</view>
<view v-else class="error-message">{{ $lang('filePreview.fileUrlNotExist') }}</view>
</view>
<!-- Word 文件预览 -->
<view v-else-if="fileType === 'word'" class="file-viewer">
<web-view v-if="fileUrl" :src="fileUrl"></web-view>
<view v-else class="error-message">文件地址不存在</view>
<view v-else class="error-message">{{ $lang('filePreview.fileUrlNotExist') }}</view>
</view>
<!-- 视频文件预览 -->
<view v-else-if="fileType === 'video'" class="video-viewer">
<video v-if="fileUrl" :src="fileUrl" controls autoplay class="video-player"></video>
<view v-else class="error-message">视频地址不存在</view>
<view v-else class="error-message">{{ $lang('filePreview.videoUrlNotExist') }}</view>
</view>
<!-- 其他文件类型 -->
<view v-else class="file-viewer">
<view class="error-message">不支持的文件类型</view>
<view class="error-message">{{ $lang('filePreview.unsupportedFileType') }}</view>
</view>
</view>
</view>

View File

@@ -11,7 +11,7 @@
</uni-grid-item>
</uni-grid>
</view>
<view v-if="brandList.length == 0"><ns-empty text="暂无更多品牌,去首页看看吧"></ns-empty></view>
<view v-if="brandList.length == 0"><ns-empty :text="$lang('goods.brand.noMoreBrand')"></ns-empty></view>
</block>
</mescroll-uni>
<loading-cover ref="loadingCover"></loading-cover>

View File

@@ -2,7 +2,7 @@
<view class="page" :style="themeColor">
<view class="closeBox">
<image :src="$util.img('public/uniapp/goods/not_exist.png')" mode="widthFix" show-menu-by-longpress></image>
<text class="close-title">您查看的商品不存在,可能已下架或被删除</text>
<text class="close-title">{{ $lang('goods.notExist.message') }}</text>
</view>
</view>
</template>

View File

@@ -3,7 +3,7 @@
<view class="help-title">{{ detail.title }}</view>
<view class="help-content"><rich-text :nodes="content"></rich-text></view>
<view class="help-meta">
<text class="help-time">发表时间: {{ $util.timeStampTurnTime(detail.create_time) }}</text>
<text class="help-time">{{ $lang('help.detail.publishTimePrefix') }}{{ $util.timeStampTurnTime(detail.create_time) }}</text>
</view>
<loading-cover ref="loadingCover"></loading-cover>

View File

@@ -6,7 +6,7 @@
<view class="item-content" v-for="(s_item, s_index) in item.child_list" :key="s_index" @click="helpDetail(s_item)">{{ s_item.title }}</view>
</view>
</block>
<block v-else><ns-empty text="暂无帮助信息" :isIndex="false"></ns-empty></block>
<block v-else><ns-empty :text="$lang('help.list.noHelp')" :isIndex="false"></ns-empty></block>
<loading-cover ref="loadingCover"></loading-cover>

View File

@@ -43,7 +43,7 @@
<view v-if="showTip" class="collectPopupWindow"
:style="{ marginTop: (collectTop + statusBarHeight) * 2 + 'rpx' }">
<image :src="$util.img('public/uniapp/index/collect2.png')" mode="aspectFit" show-menu-by-longpress/>
<text @click="closeCollectPopupWindow">我知道了</text>
<text @click="closeCollectPopupWindow">{{ $lang('index.diy.iKnow') }}</text>
</view>
</uni-popup>

View File

@@ -393,11 +393,11 @@ export default {
var rule = [{
name: 'mobile',
checkType: 'required',
errorMsg: '请输入手机号'
errorMsg: this.$lang('login.login.mobileRequired')
}, {
name: 'mobile',
checkType: 'phoneno',
errorMsg: '请输入正确的手机号'
errorMsg: this.$lang('login.login.mobileFormatError')
}];
if (this.captchaConfig == 1) {
rule.push({
@@ -416,7 +416,7 @@ export default {
this.dynacodeData.isSend = true;
this.dynacodeData.timer = setInterval(() => {
this.dynacodeData.seconds--;
this.dynacodeData.codeText = this.dynacodeData.seconds + 's后可重新获取';
this.dynacodeData.codeText = this.$lang('login.login.resendAfterSeconds', { seconds: this.dynacodeData.seconds });
}, 1000);
this.$api.sendRequest({
@@ -446,7 +446,7 @@ export default {
this.dynacodeData = {
seconds: 120,
timer: null,
codeText: '获取动态码',
codeText: this.$lang('login.login.getDynacode'),
isSend: false
};
},

View File

@@ -2,11 +2,11 @@
<view class="container" :style="themeColor">
<view class="cancel-wrap">
<view class="cancel-img"><image :src="$util.img('public/uniapp/member/refuse.png')" show-menu-by-longpress></image></view>
<view class="cancel-title">您的申请已拒绝</view>
<view class="cancel-reason">拒绝理由:{{ reason }}</view>
<view class="cancel-title">{{ $lang('member.cancelrefuse.title') }}</view>
<view class="cancel-reason">{{ $lang('member.cancelrefuse.reasonPrefix') }}{{ reason }}</view>
<view class="cancel-btn">
<button type="primary" @click="toIndex">返回</button>
<button class="color-base-bg" @click="apply">重新申请</button>
<button type="primary" @click="toIndex">{{ $lang('member.cancelrefuse.back') }}</button>
<button class="color-base-bg" @click="apply">{{ $lang('member.cancelrefuse.reapply') }}</button>
</view>
</view>
</view>

View File

@@ -4,9 +4,9 @@
<view class="cancel-img">
<image :src="$util.img('public/uniapp/member/success.png')" show-menu-by-longpress></image>
</view>
<view class="cancel-title">您已成功注销账号</view>
<view class="cancel-reason">待下次与您更好的相遇,如需再次使用,请重新注册</view>
<view class="cancel-btn"><button class="color-base-bg" @click="success">完成</button></view>
<view class="cancel-title">{{ $lang('member.cancelsuccess.title') }}</view>
<view class="cancel-reason">{{ $lang('member.cancelsuccess.desc') }}</view>
<view class="cancel-btn"><button class="color-base-bg" @click="success">{{ $lang('member.cancelsuccess.done') }}</button></view>
</view>
</view>
</template>

View File

@@ -58,7 +58,7 @@
<view v-if="showTip" class="collectPopupWindow"
:style="{ marginTop: (collectTop + statusBarHeight) * 2 + 'rpx' }">
<image :src="$util.img('public/uniapp/index/collect2.png')" mode="aspectFit" show-menu-by-longpress/>
<text @tap="closeCollectPopupWindow">我知道了</text>
<text @tap="closeCollectPopupWindow">{{ $lang('member.index.iKnow') }}</text>
</view>
</uni-popup>

View File

@@ -60,8 +60,8 @@ export default {
// 提交注销申请并清理登录态(供 assets.vue 等页面调用)
submitCancelApply(options = {}) {
uni.showModal({
title: options.title || '风险提示',
content: options.content || '确定要注销当前账号吗?',
title: options.title || this.$lang('member.public.riskWarningTitle'),
content: options.content || this.$lang('member.public.cancelAccountConfirm'),
confirmColor: '#000000',
success: res => {
if (res.confirm) {

View File

@@ -2,7 +2,7 @@
<view :style="themeColor" class="page">
<view class="notice-title">{{ detail.title }}</view>
<view class="notice-meta">
<text class="notice-time">发表时间: {{ $util.timeStampTurnTime(detail.create_time) }}</text>
<text class="notice-time">{{ $lang('notice.detail.publishTimePrefix') }}{{ $util.timeStampTurnTime(detail.create_time) }}</text>
</view>
<view class="notice-content"><rich-text :nodes="content"></rich-text></view>

View File

@@ -7,7 +7,7 @@
:key="index">
<view class="title-info">
<view class="title">
<text v-if="item.is_top == 1" class="color-base-bg tag">置顶</text>
<text v-if="item.is_top == 1" class="color-base-bg tag">{{ $lang('notice.list.topTag') }}</text>
<text class="txt using-hidden">{{ item.title }}</text>
</view>
<text class="release-time">{{ $util.timeStampTurnTime(item.create_time, 1) }}</text>
@@ -15,7 +15,7 @@
</view>
</view>
</view>
<view v-else class="cart-empty"><ns-empty text="暂无公告" :isIndex="false"></ns-empty></view>
<view v-else class="cart-empty"><ns-empty :text="$lang('notice.list.noNotice')" :isIndex="false"></ns-empty></view>
</block>
</mescroll-uni>
<loading-cover ref="loadingCover"></loading-cover>

View File

@@ -13,7 +13,7 @@
<view class="payment-item" v-for="(item, index) in payTypeList" :key="index" @click="payIndex = index">
<view>
<text class="iconfont" :class="item.icon"></text>
<text class="name">{{ $lang('pay.cashier.' + item.type) }}</text>
<text class="name">{{ $lang('pay.cashier.' + item.type, item.name) }}</text>
</view>
<text class="iconfont" :class="payIndex == index ? 'icon-yuan_checked color-base-text' : 'icon-checkboxblank'"></text>
</view>

View File

@@ -13,7 +13,7 @@
</view>
</view>
<view class="order-body">
<view class="goods_info_flex"><view class="goods-name font-size-base">充值成功</view></view>
<view class="goods_info_flex"><view class="goods-name font-size-base">{{ $lang('recharge.rechargeSuccess') }}</view></view>
<view class="goods-img color-base-text">
¥
@@ -31,7 +31,7 @@
</view>
</view>
</block>
<view v-else><ns-empty :isIndex="false" text="暂无充值记录"></ns-empty></view>
<view v-else><ns-empty :isIndex="false" :text="$lang('recharge.noRecord')"></ns-empty></view>
</block>
</mescroll-uni>
<loading-cover ref="loadingCover"></loading-cover>

View File

@@ -3,13 +3,13 @@
<view class="picker-container">
<view v-for="(item, idx) in pickerList" :key="item.id" class="single-picker">
<picker mode="selector" :value="item.value" :range="item.range" range-key="name" @change="bindPickerChange($event, idx, item)">
<view class="picker">当前选择:{{item.range[item.value].name || '请选择'}}</view>
<view class="picker">{{ $lang('seal.structure.currentChoicePrefix') }}{{item.range[item.value].name || $lang('seal.structure.pleaseSelect')}}</view>
</picker>
</view>
</view>
<block v-if="answerName">
<view style="font-size:32rpx;color:#ff0000;text-align:center;">
<view style="color:#ff0000;">选型结果:</view>{{answerName}}
<view style="color:#ff0000;">{{ $lang('seal.structure.resultPrefix') }}</view>{{answerName}}
</view>
</block>
<block v-if="files_url">
@@ -20,7 +20,7 @@
<image style="width:50rpx;height:50rpx;" :src="g0" mode="widthFix" show-menu-by-longpress></image>
</view>
</view>
<view class="file_title">结果文件</view>
<view class="file_title">{{ $lang('seal.structure.resultFile') }}</view>
</view>
</view>
</block>