RSS Git Download  Clone
Raw Blame History 3kB 108 lines
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { merge } from 'lodash-es'
import { getPersistentItem } from './electron-bridge'
import { detectLanguageFromLocale } from '../../core/detect-language'

// Vite glob import: lazily load all translation files
const translationModules = import.meta.glob('../../strings/*/strings.js')

const STORAGE_KEY = 'p3xr-language'
const AUTO = 'auto'

function resolveAutoLanguage(): string {
    try {
        return detectLanguageFromLocale(navigator.language)
    } catch { return 'en' }
}

function detectLanguage(): { lang: string, isAuto: boolean } {
    const stored = getPersistentItem(STORAGE_KEY)
    if (stored && stored !== AUTO) return { lang: stored, isAuto: false }
    return { lang: resolveAutoLanguage(), isAuto: true }
}

async function loadLangModule(lang: string): Promise<any> {
    const key = `../../strings/${lang}/strings.js`
    const loader = translationModules[key]
    if (!loader) return {}
    try {
        const mod: any = await loader()
        return mod.default || mod
    } catch (e) {
        console.warn(`Failed to load translation: ${lang}`, e)
        return {}
    }
}

export const useI18nStore = defineStore('i18n', () => {
    const currentLang = ref('en')
    const isAuto = ref(true)
    const strings = ref<any>({})
    const translations = ref<Record<string, any>>({})
    const loading = ref(true)
    const ready = ref(false)

    async function setLanguage(choice: string) {
        const enStrings = translations.value['en'] || {}
        const auto = choice === AUTO
        const lang = auto ? resolveAutoLanguage() : choice
        const storageValue = auto ? AUTO : lang

        if (!translations.value[lang]) {
            loading.value = true
            translations.value[lang] = await loadLangModule(lang)
        }

        const merged = merge({}, enStrings, translations.value[lang])
        try { localStorage.setItem(STORAGE_KEY, storageValue) } catch {}

        try {
            window.parent?.postMessage({ type: 'p3x-ui-storage-set', key: STORAGE_KEY, value: storageValue }, '*')
        } catch {}

        document.documentElement.lang = lang

        currentLang.value = lang
        isAuto.value = auto
        strings.value = merged
        loading.value = false
    }

    /**
     * Explicit init method -- must be called after app.use(pinia).
     * Loads English first, then detected language, sets ready = true.
     */
    async function init() {
        const enStrings = await loadLangModule('en')
        translations.value['en'] = enStrings

        const { lang: initLang, isAuto: initIsAuto } = detectLanguage()
        if (initLang !== 'en') {
            translations.value[initLang] = await loadLangModule(initLang)
        }

        const langStrings = translations.value[initLang] || {}
        const merged = merge({}, enStrings, langStrings)

        document.documentElement.lang = initLang

        currentLang.value = initLang
        isAuto.value = initIsAuto
        strings.value = merged
        loading.value = false
        ready.value = true
    }

    return {
        currentLang,
        isAuto,
        strings,
        translations,
        loading,
        ready,
        setLanguage,
        init,
    }
})