- 管理后台 adminT 文案库、结算与代理端页面、表单校验 - 玩家端 vue-i18n 补全首页/公告/串关与 ms 文案 - Element Plus ms 语言包与共享 locale 工具
52 lines
1.5 KiB
TypeScript
52 lines
1.5 KiB
TypeScript
import { useI18n } from 'vue-i18n';
|
|
import { SUPPORTED_LOCALES, LOCALE_UI_LABELS } from '@thebet365/shared';
|
|
import api from '../api';
|
|
import { useAuthStore } from '../stores/auth';
|
|
|
|
const STORAGE_KEY = 'locale';
|
|
const COOKIE_MAX_AGE = 365 * 24 * 60 * 60;
|
|
|
|
export const APP_LOCALES = SUPPORTED_LOCALES.map((code) => ({
|
|
code,
|
|
label: LOCALE_UI_LABELS[code] ?? code,
|
|
}));
|
|
|
|
function persistLocale(code: string) {
|
|
localStorage.setItem(STORAGE_KEY, code);
|
|
document.cookie = `${STORAGE_KEY}=${encodeURIComponent(code)};path=/;max-age=${COOKIE_MAX_AGE};SameSite=Lax`;
|
|
}
|
|
|
|
export function useAppLocale() {
|
|
const { locale } = useI18n();
|
|
const auth = useAuthStore();
|
|
|
|
function applyLocale(code: string) {
|
|
if (!(SUPPORTED_LOCALES as readonly string[]).includes(code)) return;
|
|
locale.value = code;
|
|
persistLocale(code);
|
|
}
|
|
|
|
async function setLocale(code: string) {
|
|
applyLocale(code);
|
|
if (auth.token) {
|
|
try {
|
|
await api.post('/player/language', { locale: code });
|
|
if (auth.user) {
|
|
auth.user = { ...auth.user, locale: code };
|
|
localStorage.setItem('user', JSON.stringify(auth.user));
|
|
}
|
|
} catch {
|
|
/* 离线或 token 过期时仍保留本地语言 */
|
|
}
|
|
}
|
|
}
|
|
|
|
function initFromUser(userLocale?: string | null) {
|
|
if (userLocale && (SUPPORTED_LOCALES as readonly string[]).includes(userLocale)) {
|
|
applyLocale(userLocale);
|
|
}
|
|
}
|
|
|
|
return { locales: APP_LOCALES, setLocale, applyLocale, initFromUser };
|
|
}
|