2026-06-30 14:14:12 +08:00
|
|
|
<template>
|
|
|
|
|
<DropdownMenu>
|
|
|
|
|
<DropdownMenuTrigger as-child>
|
|
|
|
|
<button
|
2026-09-07 08:53:51 +08:00
|
|
|
class="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg text-muted-foreground transition hover:bg-muted/50 hover:text-foreground"
|
2026-06-30 14:14:12 +08:00
|
|
|
:aria-label="t('common.language')"
|
|
|
|
|
:title="t('common.language')"
|
|
|
|
|
type="button"
|
|
|
|
|
>
|
|
|
|
|
<Languages class="h-4 w-4" />
|
|
|
|
|
</button>
|
|
|
|
|
</DropdownMenuTrigger>
|
|
|
|
|
<DropdownMenuContent
|
|
|
|
|
align="end"
|
|
|
|
|
class="min-w-36"
|
|
|
|
|
>
|
|
|
|
|
<DropdownMenuItem
|
|
|
|
|
v-for="option in options"
|
|
|
|
|
:key="option.value"
|
|
|
|
|
class="justify-between gap-3"
|
2026-09-07 08:53:51 +08:00
|
|
|
:lang="option.value"
|
2026-06-30 14:14:12 +08:00
|
|
|
@select="setLocale(option.value)"
|
|
|
|
|
>
|
|
|
|
|
<span>{{ option.label }}</span>
|
|
|
|
|
<Check
|
|
|
|
|
v-if="locale === option.value"
|
2026-09-07 08:53:51 +08:00
|
|
|
class="h-4 w-4 shrink-0 text-primary"
|
2026-06-30 14:14:12 +08:00
|
|
|
/>
|
|
|
|
|
</DropdownMenuItem>
|
|
|
|
|
</DropdownMenuContent>
|
|
|
|
|
</DropdownMenu>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { computed } from 'vue'
|
|
|
|
|
import { Check, Languages } from 'lucide-vue-next'
|
|
|
|
|
import {
|
|
|
|
|
DropdownMenu,
|
|
|
|
|
DropdownMenuContent,
|
|
|
|
|
DropdownMenuItem,
|
|
|
|
|
DropdownMenuTrigger,
|
|
|
|
|
} from '@/components/ui/dropdown-menu'
|
|
|
|
|
import { useI18n, useLocaleOptions, type Locale } from '@/i18n'
|
|
|
|
|
|
|
|
|
|
const { t } = useI18n()
|
|
|
|
|
const { locale, setLocale } = useLocaleOptions()
|
|
|
|
|
|
|
|
|
|
const options = computed<Array<{ value: Locale; label: string }>>(() => [
|
|
|
|
|
{ value: 'zh-CN', label: t('common.chinese') },
|
|
|
|
|
{ value: 'en-US', label: t('common.english') },
|
|
|
|
|
])
|
|
|
|
|
</script>
|