refactor(i18n): 重构国际化拉取失败的提示逻辑

将i18n失败提示从lang:fallback事件监听迁移到boot返回值判断中,移除冗余的事件监听代码,修复事件监听时机和去重的问题,统一提示逻辑和防刷机制
This commit is contained in:
2026-07-02 17:07:48 +08:00
parent 0cdb956065
commit cf6b683ffc

53
App.vue
View File

@@ -68,8 +68,34 @@
// A) 主题第一次 apply — 走 preset,失败静默走默认
this.$store.dispatch('applyThemeWithRemote', presetName)
.catch(e => console.warn('[theme] pre-apply fail', e)),
// B) Lang boot
langBoot.catch(e => console.warn('[i18n] boot fail', e)),
// B) Lang boot — 直接根据返回值判断 toast,不走 lang:fallback 事件
// 为什么不走事件:
// 1) lang:fallback 受 setRemoteStatus 内部去重影响(fail→fail 不 emit),不可靠
// 2) 监听器注册时机晚于 boot 完成,首次失败收不到
// 3) boot() 返回值已经包含了 status/reason,直接判断更清晰
// 触发条件:
// - status === 'fail': 远端拉取失败(包含"无缓存兜底"和"有缓存兜底"两种)
// - reason !== 'unknown': 排除业务主动设置的未知错误
// 防刷: 进程内全局标志,只弹一次
// 延迟弹出: uni.showToast 会覆盖当前 toast,1500ms ≈ 默认 toast duration,
// 等启动期其他 toast / 模态弹窗先消失再弹,降低被覆盖风险
langBoot.then((res) => {
if (res && res.status === 'fail' && res.reason && res.reason !== 'unknown') {
if (globalThis.__i18nFallbackToastShown) return;
globalThis.__i18nFallbackToastShown = true;
setTimeout(() => {
try {
uni.showToast({
title: `Failed to load i18n. ${res.reason} Please check your network and try again.`,
icon: 'none',
duration: 10000,
});
} catch (e) {}
}, 3000);
}
}, (e) => {
console.warn('[i18n] boot fail', e);
}),
// C) ThemeOverride boot(brand/light/dark 三桶,bootTimeout=2000ms)
ThemeOverride.boot().catch(e => console.warn('[theme] boot fail', e)),
]);
@@ -115,27 +141,8 @@
uni.$on && uni.$on('uniacid:changed', () => {
try { ThemeOverride.onUniacidChange(); } catch (e) {}
});
// 监听国际化远端拉取失败: 给用户英文 toast 提示
// 触发时机: lang.js setRemoteStatus('fail', ...) 时
// 设计: 用 setRemoteStatus 内部归一化后的 reason 决定文案
// - 'timeout' / 'network' / 'http' / 'parse' / 'exception' 都弹同一句英文说明
// - 'unknown' 不弹(可能是业务主动设置,不是真失败)
// 防刷: 同一进程内只弹一次(避免重试时反复刷屏)
if (!globalThis.__i18nFallbackToastShown) {
uni.$on && uni.$on('lang:fallback', (detail) => {
const r = detail && detail.reason;
if (r === 'unknown' || r === undefined || r === null) return;
if (globalThis.__i18nFallbackToastShown) return;
globalThis.__i18nFallbackToastShown = true;
try {
uni.showToast({
title: 'Failed to load i18n. Please check your network and try again.',
icon: 'none',
duration: 4000,
});
} catch (e) {}
});
}
// i18n 远端拉取失败的 toast 提示已迁移到上方 boot() 完成的 then() 中,
// 直接根据 boot 返回值判断,不再依赖 lang:fallback 事件
uni.hideTabBar();
// #ifdef MP