Feature: 添加更多语言支持

This commit is contained in:
2025-07-18 11:36:08 +08:00
parent 1733d2ae5b
commit c85afc9bde
3 changed files with 305 additions and 1 deletions

View File

@ -17,7 +17,76 @@
<v-spacer />
<v-btn icon="mdi-translate" @click="toggleLanguage" />
<v-menu
v-model="languageMenu"
:close-on-content-click="true"
location="bottom end"
offset="8"
>
<template #activator="{ props }">
<v-btn
v-bind="props"
:icon="$vuetify.display.xs"
:prepend-icon="$vuetify.display.xs ? undefined : 'mdi-translate'"
:size="$vuetify.display.xs ? 'default' : 'large'"
variant="text"
>
<v-icon v-if="$vuetify.display.xs">mdi-translate</v-icon>
<span v-else class="text-button">{{ currentLanguage.label }}</span>
</v-btn>
</template>
<!-- <v-list
class="language-menu"
density="compact"
min-width="160"
>
<v-list-item
v-for="lang in availableLanguages"
:key="lang.code"
:activate="locale === lang.code"
:title="lang.label"
@click="changeLanguage(lang.code)"
>
<template #append>
<v-icon
v-if="locale === lang.code"
class="text-primary"
icon="mdi-check"
/>
</template>
</v-list-item>
</v-list> -->
<div class="language-pill-container">
<v-chip-group
v-model="selectedLanguageIndex"
direction="vertical"
selected-class="text-primary"
@update:model-value="handleLanguageChange"
>
<v-chip
v-for="(lang, index) in availableLanguages"
:key="lang.code"
class="language-pill-large"
:color="locale === lang.code ? 'primary' : undefined"
label
rounded="xl"
size="large"
:value="index"
:variant="locale === lang.code ? 'flat' : 'outlined'"
>
<v-icon
v-if="locale === lang.code"
class="mr-2"
icon="mdi-check"
size="small"
/>
{{ lang.label }}
</v-chip>
</v-chip-group>
</div>
</v-menu>
</v-app-bar>
<v-navigation-drawer
@ -166,6 +235,7 @@
const windowWidth = ref(typeof window === 'undefined' ? 1200 : window.innerWidth)
const showAboutDialog = ref(false)
const languageMenu = ref(false)
// 应用信息
const appInfo = computed(() => {
@ -254,6 +324,42 @@
})
})
const availableLanguages = [
{
code: 'zh',
label: '中文(简体)',
},
{
code: 'en',
label: 'English',
},
{
code: 'ru',
label: 'Русский(Developing)',
},
// {
// code: 'sp',
// label: 'Español',
// },
]
const currentLanguage = computed(() => {
return availableLanguages.find(lang => lang.code === locale.value) || availableLanguages[0]
})
const selectedLanguageIndex = computed(() => {
return availableLanguages.findIndex(lang => lang.code === locale.value)
})
function changeLanguage (langCode: string) {
locale.value = langCode
}
function handleLanguageChange (index: number) {
if (index !== undefined && index >= 0 && index < availableLanguages.length) {
locale.value = availableLanguages[index].code
}
}
function toggleLanguage () {
locale.value = locale.value === 'zh' ? 'en' : 'zh'
}
@ -360,4 +466,125 @@
margin: 2px 4px !important;
}
}
/* 无背景的语言选择器容器 */
.language-pill-container {
padding: 8px;
min-width: 180px;
max-width: 320px;
}
/* 大尺寸语言药丸样式 */
.language-pill-large {
margin: 4px 0;
padding: 12px 20px;
height: 48px;
font-size: 1rem;
font-weight: 500;
transition: all 0.3s ease;
border-radius: 24px;
width: 100%;
/* 文本居中 */
display: flex !important;
justify-content: center !important;
align-items: center !important;
}
.language-pill-large:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
/* chip内容居中对齐 */
.language-pill-large .v-chip__content {
display: flex !important;
justify-content: center !important;
align-items: center !important;
width: 100% !important;
font-weight: 500;
}
/* 响应式药丸样式 */
@media (max-width: 599px) {
.language-pill-container {
min-width: 160px;
max-width: 280px;
padding: 6px;
}
.language-pill-large {
margin: 2px 0;
padding: 8px 16px;
height: 40px;
font-size: 0.875rem;
}
.text-button {
font-size: 0.75rem !important;
}
}
@media (min-width: 600px) and (max-width: 959px) {
.language-pill-large {
padding: 10px 18px;
height: 44px;
font-size: 0.9375rem;
}
}
/* 药丸选中状态 */
.v-chip--variant-flat {
background: rgb(var(--v-theme-primary)) !important;
color: rgb(var(--v-theme-surface)) !important;
box-shadow: 0 2px 8px rgba(var(--v-theme-primary), 0.1);
}
/* 药丸未选中状态 */
.v-chip--variant-outlined {
border: 1px solid rgba(var(--v-theme-info), 0.3);
color: rgb(var(--v-theme-info));
background: rgba(var(--v-theme-surface), 1);
}
.v-chip--variant-outlined:hover {
background: rgba(var(--v-theme-info), 0.08);
border-color: rgba(var(--v-theme-info), 0.5);
}
/* 选中状态的图标 */
.language-pill-large .v-icon {
opacity: 1;
}
/* 字体权重调整 */
.language-pill-large .v-chip__content {
font-weight: 500;
}
.language-pill {
margin: 2px 4px;
transition: all 0.2s ease;
}
.language-pill:hover {
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
/* 响应式药丸样式 */
@media (max-width: 599px) {
.language-pill-menu {
min-width: 160px;
max-width: 250px;
}
.language-pill {
margin: 1px 2px;
}
.text-button {
font-size: 0.75rem !important;
}
}
</style>