feat(i18n): 管理端与玩家端三语支持(中/英/马来语)
- 管理后台 adminT 文案库、结算与代理端页面、表单校验 - 玩家端 vue-i18n 补全首页/公告/串关与 ms 文案 - Element Plus ms 语言包与共享 locale 工具
This commit is contained in:
@@ -6,33 +6,26 @@ import { useBetSlipStore } from '../stores/betSlip';
|
||||
import BetSlipDrawer from '../components/BetSlipDrawer.vue';
|
||||
import CashBalanceChip from '../components/CashBalanceChip.vue';
|
||||
import UserAvatarMenu from '../components/UserAvatarMenu.vue';
|
||||
import LocaleFlag from '../components/LocaleFlag.vue';
|
||||
import LocaleSwitcher from '../components/LocaleSwitcher.vue';
|
||||
import { useAppLocale } from '../composables/useAppLocale';
|
||||
import AnnouncementMarquee from '../components/AnnouncementMarquee.vue';
|
||||
import BottomNavIcon from '../components/BottomNavIcon.vue';
|
||||
import { computed, onMounted } from 'vue';
|
||||
import { getLocaleDisplay } from '../utils/localeDisplay';
|
||||
import { useAnnouncements } from '../composables/useAnnouncements';
|
||||
|
||||
const { t, locale } = useI18n();
|
||||
const { t } = useI18n();
|
||||
const auth = useAuthStore();
|
||||
const { initFromUser } = useAppLocale();
|
||||
const route = useRoute();
|
||||
const slip = useBetSlipStore();
|
||||
|
||||
const locales = [
|
||||
{ code: 'zh-CN', label: '中文' },
|
||||
{ code: 'en-US', label: 'EN' },
|
||||
{ code: 'ms-MY', label: 'BM' },
|
||||
];
|
||||
|
||||
const showAnnouncement = computed(() => !route.path.startsWith('/profile'));
|
||||
const { items: announcements, load: loadAnnouncements } = useAnnouncements();
|
||||
|
||||
onMounted(loadAnnouncements);
|
||||
|
||||
function setLocale(code: string) {
|
||||
locale.value = code;
|
||||
localStorage.setItem('locale', code);
|
||||
}
|
||||
onMounted(() => {
|
||||
loadAnnouncements();
|
||||
if (auth.user?.locale) initFromUser(auth.user.locale);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -40,14 +33,7 @@ function setLocale(code: string) {
|
||||
<header class="header">
|
||||
<img src="/logo.png" alt="TheBet365" class="logo" />
|
||||
<div class="header-actions">
|
||||
<div class="lang-select-wrap">
|
||||
<LocaleFlag :locale="locale" :size="18" />
|
||||
<select :value="locale" @change="setLocale(($event.target as HTMLSelectElement).value)" class="lang-select">
|
||||
<option v-for="l in locales" :key="l.code" :value="l.code">
|
||||
{{ getLocaleDisplay(l.code).label }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<LocaleSwitcher />
|
||||
<CashBalanceChip v-if="auth.user" />
|
||||
<UserAvatarMenu v-if="auth.user" />
|
||||
</div>
|
||||
@@ -115,25 +101,20 @@ function setLocale(code: string) {
|
||||
height: 36px; width: auto; display: block;
|
||||
filter: drop-shadow(0 0 4px rgba(212, 175, 55, 0.2));
|
||||
}
|
||||
.header-actions { display: flex; gap: 6px; align-items: center; }
|
||||
.lang-select-wrap {
|
||||
.header-actions {
|
||||
--header-chip-h: 36px;
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 3px 6px 3px 5px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
background: #0d0d0d;
|
||||
}
|
||||
.lang-select {
|
||||
background: transparent;
|
||||
color: var(--primary-light);
|
||||
border: none;
|
||||
padding: 2px 2px 2px 0;
|
||||
width: auto;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
outline: none;
|
||||
.header-actions :deep(.locale-switch:not(.compact)),
|
||||
.header-actions :deep(.cash-chip),
|
||||
.header-actions :deep(.avatar-btn) {
|
||||
height: var(--header-chip-h);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.header-actions :deep(.avatar-btn) {
|
||||
width: var(--header-chip-h);
|
||||
}
|
||||
.announce-strip {
|
||||
flex-shrink: 0;
|
||||
|
||||
Reference in New Issue
Block a user