Files
uni-fans-score/utils/i18n.js
T
2026-06-12 16:08:00 +08:00

88 lines
2.2 KiB
JavaScript

// i18n工具函数 - 用于在 Vue 3 setup 中安全获取 $t
import { getCurrentInstance } from 'vue'
import zhCN from '../locale/zh-CN.js'
import enUS from '../locale/en-US.js'
import idID from '../locale/id-ID.js'
const MESSAGE_MAP = {
'zh-CN': zhCN,
'en-US': enUS,
'id-ID': idID
}
const LANGUAGE_STORAGE_KEY = 'language'
export function getAppLocale() {
try {
const lang = uni.getStorageSync(LANGUAGE_STORAGE_KEY)
if (lang && MESSAGE_MAP[lang]) return lang
} catch (_) {}
return 'zh-CN'
}
function lookupMessage(locale, key) {
const segments = String(key).split('.')
let node = MESSAGE_MAP[locale]
for (const seg of segments) {
if (node == null || typeof node !== 'object') return null
node = node[seg]
}
return typeof node === 'string' ? node : null
}
/** 非 Vue 组件场景下的文案翻译 */
export function translate(key, values) {
const locale = getAppLocale()
let text = lookupMessage(locale, key) ?? lookupMessage('zh-CN', key) ?? key
if (values && typeof values === 'object') {
Object.entries(values).forEach(([k, v]) => {
text = text.split(`{${k}}`).join(String(v))
})
}
return text
}
/** uni.showModal 封装:默认使用多语言取消/确认按钮 */
export function showModalI18n(options = {}) {
const { cancelText, confirmText, showCancel = true, ...rest } = options
const modalOptions = {
...rest,
showCancel,
confirmText: confirmText ?? translate('common.confirm')
}
if (showCancel !== false) {
modalOptions.cancelText = cancelText ?? translate('common.cancel')
}
return uni.showModal(modalOptions)
}
/**
* 在 setup 中使用 i18n
* @returns {{ t: Function, locale: string, i18n: object }}
*/
export function useI18n() {
const instance = getCurrentInstance()
if (!instance || !instance.proxy) {
return {
t: (key) => key,
locale: 'en_US',
i18n: null
}
}
const proxy = instance.proxy
// 返回一个函数,每次调用时动态获取 $t(确保 $t 已经注入)
return {
t: (key, ...args) => {
if (proxy.$t && typeof proxy.$t === 'function') {
return proxy.$t(key, ...args)
}
return key
},
locale: proxy.$i18n?.locale || 'en_US',
i18n: proxy.$i18n
}
}