feat: configurable locales path per story, dynamic language switching from story data

This commit is contained in:
2026-06-10 12:17:52 +08:00
parent 4cf2263c78
commit 86a0aebdc8
10 changed files with 64 additions and 28 deletions

View File

@@ -161,6 +161,7 @@ export function useGameEngine(videoEls: () => [HTMLVideoElement | null, HTMLVide
engine.achievementSystem.init(data.achievements || [], achieved)
store.setEndings(data.endings || [])
store.setStoryLocales(data.locales)
const visitedIds = await saveSystem.getVisitedSceneIds()
store.setVisitedSceneIds(visitedIds)

View File

@@ -4,20 +4,28 @@ import enUI from '@/locales/en.json'
import jaUI from '@/locales/ja.json'
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',
)
type Lang = string
const currentLang = ref<Lang>(localStorage.getItem('lang') || 'zh')
const storyMessages = ref<Record<string, Record<string, any>>>({})
const storyLoading = new Set<Lang>()
const storyLoading = new Set<string>()
let localesPath = ''
async function loadStoryMessages(lang: Lang) {
if (storyMessages.value[lang] || storyLoading.has(lang)) return
function resolveLocalePath(lang: string): string {
const base = localesPath.endsWith('/') ? localesPath : localesPath + '/'
return base + lang + '.json'
}
export async function initStoryLocales(path: string, lang?: string) {
localesPath = path
return loadStoryMessages(lang || currentLang.value)
}
async function loadStoryMessages(lang: string) {
if (!localesPath || storyMessages.value[lang] || storyLoading.has(lang)) return
storyLoading.add(lang)
try {
const resp = await fetch(`/locales/${lang}.json`)
const resp = await fetch(resolveLocalePath(lang))
if (resp.ok) {
storyMessages.value = {
...storyMessages.value,
@@ -31,8 +39,6 @@ async function loadStoryMessages(lang: Lang) {
}
}
loadStoryMessages(currentLang.value)
function t(key: string): string {
const parts = key.split('.')
@@ -42,7 +48,8 @@ function t(key: string): string {
}
if (typeof result === 'string') return result
let fallback: any = uiMessages[currentLang.value]
const uiLang = currentLang.value as keyof typeof uiMessages
let fallback: any = (uiMessages as any)[uiLang] || uiMessages.zh
for (const p of parts) {
fallback = fallback?.[p]
}
@@ -51,7 +58,7 @@ function t(key: string): string {
return key
}
async function setLang(lang: Lang) {
async function setLang(lang: string) {
await loadStoryMessages(lang)
currentLang.value = lang
localStorage.setItem('lang', lang)