20260917212907
This commit is contained in:
1 parent
6fa3d8535e
commit
5cbf745bbf
115 files changed
+4104
-85
No files matched your search
@@ -1,6 +1,22 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { loadDataApi } from '@/services/api'
|
||||
import { BUILTIN_MESSAGES } from '@/i18n/builtin-messages'
|
||||
|
||||
/** SQL 字符串字面量转义(b_locale 来自 s_i18n_type,仍按不可信输入处理) */
|
||||
function sqlQuote(value) {
|
||||
return `N'${String(value).replace(/'/g, "''")}'`
|
||||
}
|
||||
|
||||
// 已加载的语言译文缓存:locale -> { key: value }(只存库表译文,内置兜底在合并时再加)
|
||||
const messageCache = new Map()
|
||||
// 同一语言的并发请求复用同一个 Promise,避免切换语言瞬间打出一串相同请求
|
||||
const pendingMessages = new Map()
|
||||
|
||||
function clearMessageCache() {
|
||||
messageCache.clear()
|
||||
pendingMessages.clear()
|
||||
}
|
||||
|
||||
// UI 翻译运行时与业务语言清单共用一个入口。
|
||||
const localeRef = ref('zh-CN')
|
||||
@@ -24,6 +40,7 @@ export function setMessages(messages, locale = undefined) {
|
||||
|
||||
export function clearMessages() {
|
||||
messagesRef.value = {}
|
||||
clearMessageCache()
|
||||
}
|
||||
|
||||
export const useI18nStore = defineStore('i18n', () => {
|
||||
@@ -78,6 +95,49 @@ export const useI18nStore = defineStore('i18n', () => {
|
||||
return loadLanguages(true)
|
||||
}
|
||||
|
||||
/* ---------- 译文(s_i18n) ---------- */
|
||||
// 把某份语言的译文写进运行时;库表译文覆盖前端内置兜底文案
|
||||
function applyMessages(locale) {
|
||||
// 异步请求回来时语言可能又被切走了,只认当前语言,避免串台
|
||||
if (String(localeRef.value) !== String(locale)) return
|
||||
setMessages({ ...BUILTIN_MESSAGES[locale], ...messageCache.get(locale) }, locale)
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载指定语言的译文;不传则取当前语言。
|
||||
* 已加载过直接复用缓存(无请求),并发复用同一个 Promise,失败不抛出(界面回落内置/兜底文案)。
|
||||
*/
|
||||
async function loadMessages(locale = localeRef.value, force = false) {
|
||||
const target = String(locale || '').trim()
|
||||
if (!target) return {}
|
||||
if (!force && messageCache.has(target)) {
|
||||
applyMessages(target)
|
||||
return messageCache.get(target)
|
||||
}
|
||||
if (pendingMessages.has(target)) return pendingMessages.get(target)
|
||||
|
||||
const task = loadDataApi('s_i18n', `b_canuse = 1 and b_locale = ${sqlQuote(target)}`, 'b_key ASC')
|
||||
.then((res) => {
|
||||
const map = {}
|
||||
for (const row of res.data || []) {
|
||||
if (row.b_key) map[String(row.b_key)] = row.b_value == null ? '' : String(row.b_value)
|
||||
}
|
||||
messageCache.set(target, map)
|
||||
applyMessages(target)
|
||||
return map
|
||||
})
|
||||
.catch((e) => {
|
||||
error.value = e?.message || String(e)
|
||||
return {}
|
||||
})
|
||||
.finally(() => {
|
||||
pendingMessages.delete(target)
|
||||
})
|
||||
|
||||
pendingMessages.set(target, task)
|
||||
return task
|
||||
}
|
||||
|
||||
function toggleLocale() {
|
||||
setLocale(localeRef.value === 'zh-CN' ? 'en-US' : 'zh-CN')
|
||||
}
|
||||
@@ -98,6 +158,7 @@ export const useI18nStore = defineStore('i18n', () => {
|
||||
clearMessages,
|
||||
toggleLocale,
|
||||
loadLanguages,
|
||||
loadMessages,
|
||||
refresh,
|
||||
}
|
||||
}, {
|
||||
|
||||
Reference in new issue
Block a user