LanguageSwitcher.vue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. <template>
  2. <div class="relative" ref="containerRef">
  3. <Button variant="ghost" size="icon" class="gap-1.5 w-auto px-2" @click="isOpen = !isOpen" :aria-label="t('nav.changeLanguage')">
  4. <Globe class="w-4 h-4" />
  5. <span class="text-sm font-medium">{{ currentLang.flag }}</span>
  6. <ChevronDown class="w-3 h-3 text-muted-foreground/60" />
  7. </Button>
  8. <Transition
  9. enter-active-class="transition duration-150 ease-out"
  10. enter-from-class="opacity-0 scale-95 translate-y-1"
  11. enter-to-class="opacity-100 scale-100 translate-y-0"
  12. leave-active-class="transition duration-100 ease-in"
  13. leave-from-class="opacity-100 scale-100 translate-y-0"
  14. leave-to-class="opacity-0 scale-95 translate-y-1"
  15. >
  16. <div
  17. v-if="isOpen"
  18. class="absolute right-0 top-full mt-2 w-44 bg-card border border-border rounded-xl shadow-xl z-50 overflow-hidden"
  19. >
  20. <button
  21. v-for="lang in languages"
  22. :key="lang.code"
  23. class="w-full flex items-center gap-2 px-4 py-2.5 text-sm hover:bg-secondary transition-colors cursor-pointer"
  24. @click="changeLang(lang.code)"
  25. >
  26. <span>{{ lang.flag }}</span>
  27. <span>{{ lang.label }}</span>
  28. </button>
  29. </div>
  30. </Transition>
  31. </div>
  32. </template>
  33. <script setup lang="ts">
  34. import { ref, computed } from "vue";
  35. import { useRouter, useRoute } from "vue-router";
  36. import { onClickOutside } from "@vueuse/core";
  37. import { Globe, ChevronDown } from "lucide-vue-next";
  38. import Button from "./ui/button.vue";
  39. import { currentLanguage } from "@/i18n";
  40. import { useI18n } from "vue-i18n";
  41. const { t } = useI18n();
  42. const languages = [
  43. { code: "en", label: "English", flag: "🇬🇧" },
  44. { code: "ru", label: "Русский", flag: "🇷🇺" },
  45. { code: "ua", label: "Українська", flag: "🇺🇦" },
  46. { code: "me", label: "Crnogorski", flag: "🇲🇪" },
  47. ];
  48. const router = useRouter();
  49. const route = useRoute();
  50. const isOpen = ref(false);
  51. const containerRef = ref<HTMLElement | null>(null);
  52. const currentLang = computed(
  53. () => languages.find((l) => l.code === currentLanguage()) ?? languages[0]
  54. );
  55. onClickOutside(containerRef, () => (isOpen.value = false));
  56. const emit = defineEmits(["select"]);
  57. function changeLang(code: string) {
  58. isOpen.value = false;
  59. // Push the new language to the current route
  60. router.push({
  61. name: route.name || undefined,
  62. params: { ...route.params, lang: code },
  63. query: route.query,
  64. hash: route.hash
  65. });
  66. emit("select");
  67. }
  68. </script>