230 lines
6.5 KiB
JavaScript
230 lines
6.5 KiB
JavaScript
import App from './App'
|
||
import { orderMonitor } from './utils/orderMonitor.js'
|
||
import { createSSRApp } from 'vue'
|
||
import { createI18n } from 'vue-i18n'
|
||
import zhCN from './locale/zh-CN.js'
|
||
import enUS from './locale/en-US.js'
|
||
import idID from './locale/id-ID.js'
|
||
import uView from '@climblee/uv-ui'
|
||
import { initConsoleControl } from './config/console.js'
|
||
import { getSystemConfig } from './config/api/system.js'
|
||
|
||
// #ifdef H5
|
||
// 兼容部分依赖/构建产物在浏览器环境访问 process.env 的场景
|
||
if (typeof globalThis !== 'undefined' && typeof globalThis.process === 'undefined') {
|
||
globalThis.process = { env: {} }
|
||
}
|
||
if (typeof globalThis !== 'undefined' && globalThis.process && !globalThis.process.env) {
|
||
globalThis.process.env = {}
|
||
}
|
||
// #endif
|
||
|
||
// 初始化 console 控制
|
||
initConsoleControl()
|
||
|
||
const LANGUAGE_STORAGE_KEY = 'language'
|
||
const SUPPORTED_LANGUAGES = ['zh-CN', 'en-US', 'id-ID']
|
||
|
||
const LANGUAGE_ALIASES = {
|
||
zh: 'zh-CN',
|
||
'zh-cn': 'zh-CN',
|
||
'zh_cn': 'zh-CN',
|
||
en: 'en-US',
|
||
'en-us': 'en-US',
|
||
'en_us': 'en-US',
|
||
id: 'id-ID',
|
||
'id-id': 'id-ID',
|
||
'id_id': 'id-ID',
|
||
in: 'id-ID',
|
||
'in-id': 'id-ID',
|
||
'in_id': 'id-ID'
|
||
}
|
||
|
||
const normalizeLanguage = (lang) => {
|
||
if (!lang || typeof lang !== 'string') return ''
|
||
const cleaned = lang.trim()
|
||
if (!cleaned) return ''
|
||
const lower = cleaned.toLowerCase()
|
||
if (LANGUAGE_ALIASES[lower]) return LANGUAGE_ALIASES[lower]
|
||
if (SUPPORTED_LANGUAGES.includes(cleaned)) return cleaned
|
||
return ''
|
||
}
|
||
|
||
// 检测是否为 H5 环境
|
||
const isH5Platform = () => {
|
||
try {
|
||
const systemInfo = uni.getSystemInfoSync()
|
||
return systemInfo.platform === 'web' || systemInfo.uniPlatform === 'web' ||
|
||
(typeof window !== 'undefined' && typeof document !== 'undefined')
|
||
} catch (e) {
|
||
// 如果获取系统信息失败,尝试通过全局对象判断
|
||
return typeof window !== 'undefined' && typeof document !== 'undefined'
|
||
}
|
||
}
|
||
|
||
// 获取系统语言
|
||
const getSystemLanguage = () => {
|
||
let language = 'zh-CN'
|
||
try {
|
||
const systemInfo = uni.getSystemInfoSync() || {}
|
||
const systemLanguage = normalizeLanguage(systemInfo.language)
|
||
if (systemLanguage) {
|
||
language = systemLanguage
|
||
} else if (isH5Platform() && typeof navigator !== 'undefined') {
|
||
const browserLanguage = normalizeLanguage(navigator.language || '')
|
||
if (browserLanguage) language = browserLanguage
|
||
}
|
||
} catch (e) {
|
||
console.error('获取系统语言失败:', e)
|
||
language = 'zh-CN'
|
||
}
|
||
return language
|
||
}
|
||
|
||
const extractLanguageFromConfig = (data) => {
|
||
if (!data) return ''
|
||
|
||
if (typeof data === 'string') {
|
||
return normalizeLanguage(data)
|
||
}
|
||
|
||
if (Array.isArray(data)) {
|
||
for (const item of data) {
|
||
const fromItem = extractLanguageFromConfig(item)
|
||
if (fromItem) return fromItem
|
||
}
|
||
return ''
|
||
}
|
||
|
||
if (typeof data === 'object') {
|
||
const direct = normalizeLanguage(
|
||
data.language || data.lang || data.locale || data.defaultLanguage || data.defaultLang
|
||
)
|
||
if (direct) return direct
|
||
|
||
for (const [key, value] of Object.entries(data)) {
|
||
const keyLower = String(key).toLowerCase()
|
||
if (keyLower.includes('lang') || keyLower.includes('locale')) {
|
||
const parsed = extractLanguageFromConfig(value)
|
||
if (parsed) return parsed
|
||
}
|
||
}
|
||
}
|
||
|
||
return ''
|
||
}
|
||
|
||
// 获取用户选择的语言
|
||
const getSavedLanguage = () => {
|
||
try {
|
||
const savedLang = normalizeLanguage(uni.getStorageSync(LANGUAGE_STORAGE_KEY))
|
||
if (savedLang) {
|
||
return savedLang
|
||
}
|
||
const systemLang = getSystemLanguage()
|
||
uni.setStorageSync(LANGUAGE_STORAGE_KEY, systemLang)
|
||
return systemLang
|
||
} catch (e) {
|
||
console.error('语言设置出错:', e)
|
||
return 'zh-CN'
|
||
}
|
||
}
|
||
|
||
// 创建 i18n 实例(Vue 3)
|
||
let i18nInstance = null
|
||
|
||
function getI18nInstance() {
|
||
// 每次都重新读取当前语言
|
||
const currentLang = getSavedLanguage()
|
||
|
||
|
||
// 检查是否需要更新语言
|
||
if (i18nInstance && i18nInstance.global.locale !== currentLang) {
|
||
console.log('=== 检测到语言变化,强制更新 ===')
|
||
console.log('旧语言:', i18nInstance.global.locale)
|
||
console.log('新语言:', currentLang)
|
||
|
||
// 直接更新 locale(这应该会触发所有组件重新渲染)
|
||
i18nInstance.global.locale = currentLang
|
||
|
||
return i18nInstance
|
||
}
|
||
|
||
// 首次创建实例
|
||
if (!i18nInstance) {
|
||
i18nInstance = createI18n({
|
||
legacy: true, // 使用 Legacy API 模式,支持全局 $t
|
||
locale: currentLang,
|
||
fallbackLocale: 'zh-CN',
|
||
messages: {
|
||
'zh-CN': zhCN,
|
||
'en-US': enUS,
|
||
'id-ID': idID
|
||
},
|
||
silentTranslationWarn: true,
|
||
silentFallbackWarn: true
|
||
})
|
||
|
||
}
|
||
|
||
return i18nInstance
|
||
}
|
||
|
||
const syncLanguageFromRemoteConfig = async (i18n) => {
|
||
if (!isH5Platform()) return
|
||
|
||
try {
|
||
const res = await getSystemConfig()
|
||
if (!res || res.code !== 200) return
|
||
|
||
const remoteLang = extractLanguageFromConfig(res.data)
|
||
if (!remoteLang) return
|
||
|
||
const current = normalizeLanguage(i18n?.global?.locale || '')
|
||
if (current !== remoteLang) {
|
||
uni.setStorageSync(LANGUAGE_STORAGE_KEY, remoteLang)
|
||
i18n.global.locale = remoteLang
|
||
console.log('H5 语言已按系统配置更新为:', remoteLang)
|
||
}
|
||
} catch (e) {
|
||
console.warn('读取系统配置语言失败,使用本地语言设置:', e)
|
||
}
|
||
}
|
||
|
||
export function createApp() {
|
||
|
||
const app = createSSRApp(App)
|
||
|
||
// 使用 uView
|
||
app.use(uView)
|
||
|
||
// 获取或更新 i18n 实例
|
||
const i18n = getI18nInstance()
|
||
|
||
// 使用 i18n
|
||
app.use(i18n)
|
||
|
||
// H5 端通过系统配置同步语言(异步,不阻塞应用启动)
|
||
syncLanguageFromRemoteConfig(i18n)
|
||
|
||
// 手动注入 $i18n 到全局属性(确保组件可以访问)
|
||
app.config.globalProperties.$i18n = i18n.global
|
||
|
||
// 注册全局订单监控服务
|
||
app.config.globalProperties.$orderMonitor = orderMonitor
|
||
|
||
// 注册全局语言切换方法(注意:建议使用 reLaunch 来切换语言以确保完全刷新)
|
||
app.config.globalProperties.$setLanguage = (lang) => {
|
||
console.log('$setLanguage 被调用,语言:', lang)
|
||
uni.setStorageSync('language', lang)
|
||
// 更新 i18n 实例的语言
|
||
if (i18n && i18n.global) {
|
||
i18n.global.locale = lang
|
||
console.log('i18n.global.locale 已更新为:', i18n.global.locale)
|
||
}
|
||
}
|
||
|
||
return {
|
||
app
|
||
}
|
||
} |