Files
thebet365/apps/player/src/composables/useAppLocale.ts
Mars cbfa18d1d3 feat(i18n): 管理端与玩家端三语支持(中/英/马来语)
- 管理后台 adminT 文案库、结算与代理端页面、表单校验
- 玩家端 vue-i18n 补全首页/公告/串关与 ms 文案
- Element Plus ms 语言包与共享 locale 工具
2026-06-03 15:05:36 +08:00

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 };
}