refactor: separate story locales (public/) from UI locales (src/), async fetch for story messages
This commit is contained in:
@@ -1,29 +1,62 @@
|
||||
import { ref } from 'vue'
|
||||
import zh from '@/locales/zh.json'
|
||||
import en from '@/locales/en.json'
|
||||
import ja from '@/locales/ja.json'
|
||||
import zhUI from '@/locales/zh.json'
|
||||
import enUI from '@/locales/en.json'
|
||||
import jaUI from '@/locales/ja.json'
|
||||
|
||||
const messages = { zh, en, ja } as const
|
||||
const uiMessages = { zh: zhUI, en: enUI, ja: jaUI } as const
|
||||
type Lang = 'zh' | 'en' | 'ja'
|
||||
|
||||
const currentLang = ref<Lang>(
|
||||
(localStorage.getItem('lang') as Lang) || 'zh'
|
||||
(localStorage.getItem('lang') as Lang) || 'zh',
|
||||
)
|
||||
|
||||
export function useI18n() {
|
||||
function t(key: string): string {
|
||||
const parts = key.split('.')
|
||||
let result: any = messages[currentLang.value]
|
||||
for (const p of parts) {
|
||||
result = result?.[p]
|
||||
const storyMessages = ref<Record<string, Record<string, any>>>({})
|
||||
const storyLoading = new Set<Lang>()
|
||||
|
||||
async function loadStoryMessages(lang: Lang) {
|
||||
if (storyMessages.value[lang] || storyLoading.has(lang)) return
|
||||
storyLoading.add(lang)
|
||||
try {
|
||||
const resp = await fetch(`/locales/${lang}.json`)
|
||||
if (resp.ok) {
|
||||
storyMessages.value = {
|
||||
...storyMessages.value,
|
||||
[lang]: await resp.json(),
|
||||
}
|
||||
}
|
||||
return typeof result === 'string' ? result : key
|
||||
} catch {
|
||||
/* story locales optional */
|
||||
} finally {
|
||||
storyLoading.delete(lang)
|
||||
}
|
||||
}
|
||||
|
||||
function setLang(lang: Lang) {
|
||||
currentLang.value = lang
|
||||
localStorage.setItem('lang', lang)
|
||||
loadStoryMessages(currentLang.value)
|
||||
|
||||
function t(key: string): string {
|
||||
const parts = key.split('.')
|
||||
|
||||
let result: any = storyMessages.value[currentLang.value]
|
||||
for (const p of parts) {
|
||||
result = result?.[p]
|
||||
}
|
||||
if (typeof result === 'string') return result
|
||||
|
||||
let fallback: any = uiMessages[currentLang.value]
|
||||
for (const p of parts) {
|
||||
fallback = fallback?.[p]
|
||||
}
|
||||
if (typeof fallback === 'string') return fallback
|
||||
|
||||
return key
|
||||
}
|
||||
|
||||
async function setLang(lang: Lang) {
|
||||
await loadStoryMessages(lang)
|
||||
currentLang.value = lang
|
||||
localStorage.setItem('lang', lang)
|
||||
}
|
||||
|
||||
export function useI18n() {
|
||||
return { t, currentLang, setLang }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user