|
1 | 1 | <template> |
2 | | - <div class="language-switcher" v-if="availableLangs.length > 1"> |
3 | | - <div class="switcher-label">{{ t('song.language') || 'Language' }}:</div> |
4 | | - <div class="switcher-buttons"> |
5 | | - <button |
6 | | - v-for="lang in availableLangs" |
7 | | - :key="lang" |
8 | | - :class="{ |
9 | | - active: currentLang === lang, |
10 | | - unavailable: !isLangAvailable(lang) |
11 | | - }" |
12 | | - @click="switchToLang(lang)" |
13 | | - :title="getLangLabel(lang)" |
14 | | - > |
15 | | - {{ getLangCode(lang) }} |
16 | | - </button> |
17 | | - </div> |
| 2 | + <div v-if="availableLangs.length > 1" class="flex justify-center mb-4 language-switcher-wrapper" dir="rtl"> |
| 3 | + <SegmentedControl :model-value="currentLang" :options="languageOptions" size="md" |
| 4 | + @update:model-value="switchToLang" /> |
18 | 5 | </div> |
19 | 6 | </template> |
20 | 7 |
|
21 | 8 | <script setup lang="ts"> |
22 | 9 | import { computed } from 'vue' |
23 | | -import { useRoute, useRouter } from 'vue-router' |
| 10 | +import { useRouter } from 'vue-router' |
24 | 11 | import { useI18n } from 'vue-i18n' |
25 | 12 | import type { LanguageCode } from '~/constants/routes' |
26 | 13 | import { ROUTES } from '~/constants/routes' |
| 14 | +import SegmentedControl from '~/components/base/SegmentedControl.vue' |
27 | 15 |
|
28 | 16 | const props = defineProps<{ |
29 | 17 | availableLangs: LanguageCode[] |
30 | 18 | currentLang: LanguageCode |
31 | 19 | songId: string |
32 | 20 | }>() |
33 | 21 |
|
34 | | -const route = useRoute() |
35 | 22 | const router = useRouter() |
36 | 23 | const { t } = useI18n() |
37 | 24 |
|
| 25 | +const languageOptions = computed(() => { |
| 26 | + return props.availableLangs.map((lang) => ({ |
| 27 | + value: lang, |
| 28 | + label: getLangLabel(lang), |
| 29 | + })) |
| 30 | +}) |
| 31 | +
|
38 | 32 | const switchToLang = (lang: LanguageCode) => { |
39 | 33 | if (!props.availableLangs.includes(lang)) return |
40 | | - |
41 | | - const newPath = lang === 'ckb-IR' |
| 34 | +
|
| 35 | + const newPath = lang === 'ckb-IR' |
42 | 36 | ? ROUTES.TAB.DETAIL(props.songId) // Default: no lang in URL |
43 | 37 | : ROUTES.TAB.DETAIL(props.songId, lang) |
44 | | - |
45 | | - router.push(newPath) |
46 | | -} |
47 | 38 |
|
48 | | -const getLangLabel = (lang: LanguageCode) => { |
49 | | - const labels = { |
50 | | - 'ckb-IR': 'سورانی (ایران)', |
51 | | - 'ckb-Latn': 'سورانی (لاتین)', |
52 | | - 'kmr': 'کرمانجی', |
53 | | - } |
54 | | - return labels[lang] || lang |
55 | | -} |
56 | | -
|
57 | | -const getLangCode = (lang: LanguageCode) => { |
58 | | - // Show short code for UI |
59 | | - return lang.split('-')[0].toUpperCase() |
| 39 | + router.push(newPath) |
60 | 40 | } |
61 | 41 |
|
62 | | -const isLangAvailable = (lang: LanguageCode) => { |
63 | | - return props.availableLangs.includes(lang) |
| 42 | +const getLangLabel = (lang: LanguageCode): string => { |
| 43 | + const translation = t(`song.languages.${lang}`) |
| 44 | + return (translation as string) || lang |
64 | 45 | } |
65 | 46 | </script> |
66 | 47 |
|
67 | 48 | <style scoped> |
68 | | -.language-switcher { |
69 | | - display: flex; |
70 | | - align-items: center; |
71 | | - gap: 0.5rem; |
72 | | - padding: 0.75rem; |
73 | | - background: var(--surface-card, #f9fafb); |
74 | | - border-radius: 0.5rem; |
75 | | - margin-bottom: 1rem; |
76 | | -} |
77 | | -
|
78 | | -.switcher-label { |
79 | | - font-weight: 500; |
80 | | - color: var(--text-secondary, #6b7280); |
| 49 | +.language-switcher-wrapper :deep(button) { |
| 50 | + white-space: nowrap; |
| 51 | + min-width: fit-content; |
81 | 52 | } |
82 | 53 |
|
83 | | -.switcher-buttons { |
84 | | - display: flex; |
85 | | - gap: 0.25rem; |
86 | | -} |
87 | | -
|
88 | | -.switcher-buttons button { |
89 | | - padding: 0.5rem 1rem; |
90 | | - border: 1px solid var(--border, #e5e7eb); |
91 | | - background: var(--surface-base, #ffffff); |
92 | | - border-radius: 0.25rem; |
93 | | - cursor: pointer; |
94 | | - transition: all 0.2s; |
95 | | - font-weight: 500; |
96 | | -} |
97 | | -
|
98 | | -.switcher-buttons button:hover { |
99 | | - background: var(--surface-hover, #f3f4f6); |
100 | | -} |
101 | | -
|
102 | | -.switcher-buttons button.active { |
103 | | - background: var(--brand-primary, #3b82f6); |
104 | | - color: white; |
105 | | - border-color: var(--brand-primary, #3b82f6); |
106 | | -} |
107 | | -
|
108 | | -.switcher-buttons button.unavailable { |
109 | | - opacity: 0.5; |
110 | | - cursor: not-allowed; |
| 54 | +.language-switcher-wrapper :deep(span) { |
| 55 | + white-space: nowrap; |
111 | 56 | } |
112 | 57 | </style> |
113 | | - |
0 commit comments