Hanye官网
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

LanguageSwitcher.vue 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <template>
  2. <div class="relative inline-block text-left" ref="dropdownContainerRef" @mouseleave="handleMouseLeave">
  3. <div
  4. @mouseenter="handleMouseEnter"
  5. class="flex items-center gap-1 text-white opacity-80 text-sm hover:opacity-100 cursor-pointer py-2 transition-opacity"
  6. >
  7. <i class="icon-i18n mr-1"></i>
  8. <span>{{ currentLocaleName || "Language" }}</span>
  9. <svg
  10. class="h-3 w-3 text-white/60 transition-transform duration-200"
  11. :class="{'rotate-180': isDropdownOpen}"
  12. fill="none" viewBox="0 0 24 24" stroke="currentColor"
  13. >
  14. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M19 9l-7 7-7-7" />
  15. </svg>
  16. </div>
  17. <transition name="fade-down">
  18. <div
  19. v-if="isDropdownOpen"
  20. @mouseenter="handleMouseEnter"
  21. class="absolute right-0 top-full mt-1 w-max min-w-[120px] bg-slate-800/90 backdrop-blur-md rounded-lg shadow-xl p-2 z-10"
  22. >
  23. <ul class="space-y-1">
  24. <li v-for="locale in availableLocales" :key="locale.code">
  25. <button
  26. @click="selectLanguage(locale.code)"
  27. class="block w-full text-left text-base text-gray-200 hover:text-white hover:bg-white/10 transition-all duration-150 rounded px-3 py-1.5"
  28. :class="[ locale.code === currentLocale ? 'font-bold opacity-100 bg-white/15' : '' ]"
  29. >
  30. {{ locale.name }}
  31. </button>
  32. </li>
  33. </ul>
  34. </div>
  35. </transition>
  36. </div>
  37. </template>
  38. <script setup lang="ts">
  39. /**
  40. * 语言切换组件 - 下拉菜单样式
  41. * 支持切换配置的语言
  42. */
  43. import { ref, computed } from "vue";
  44. import { useI18n } from "#imports"; // 修正 useI18n 导入
  45. // 定义语言代码的类型,应该与 i18n 配置中的一致
  46. type LocaleCode = "zh" | "en" | "ja"; // 你需要根据你的 i18n 配置更新这个类型
  47. const { locale, locales, setLocale } = useI18n();
  48. const currentLocale = computed(() => locale.value);
  49. const isDropdownOpen = ref(false);
  50. const dropdownContainerRef = ref(null); // 保留 ref,虽然 onClickOutside 移除了,但未来可能有用
  51. let leaveTimeout: ReturnType<typeof setTimeout> | null = null; // Timeout for mouseleave delay
  52. // 可用语言列表
  53. const availableLocales = computed(() => {
  54. // 确保 locales.value 是一个数组并且包含 code 和 name 属性
  55. return (
  56. (locales.value as Array<{ code: string; name: string }>) || []
  57. ).filter((l) => l.code && l.name);
  58. });
  59. // 当前选中语言的名称
  60. const currentLocaleName = computed(() => {
  61. const current = availableLocales.value.find((l: { code: string; name: string }) =>
  62. l.code === locale.value
  63. );
  64. return current ? current.name : "";
  65. });
  66. /**
  67. * 选择语言并关闭下拉菜单
  68. * @param {string} langCode - 选择的语言代码
  69. */
  70. async function selectLanguage(langCode: string) {
  71. if (currentLocale.value !== langCode) {
  72. try {
  73. // 使用类型断言,确保 langCode 是有效的 LocaleCode
  74. await setLocale(langCode as LocaleCode);
  75. window.location.reload();
  76. } catch (error) {
  77. console.error("Failed to set locale:", error);
  78. // 这里可以添加用户反馈,例如显示一个错误提示
  79. }
  80. }
  81. handleMouseLeave(); // 使用 handleMouseLeave 关闭
  82. }
  83. // --- Dropdown Logic (like Products dropdown) ---
  84. function handleMouseEnter() {
  85. if (leaveTimeout) {
  86. clearTimeout(leaveTimeout);
  87. leaveTimeout = null;
  88. }
  89. isDropdownOpen.value = true;
  90. }
  91. function handleMouseLeave() {
  92. // Delay closing the dropdown slightly
  93. leaveTimeout = setTimeout(() => {
  94. isDropdownOpen.value = false;
  95. }, 150); // 150ms delay
  96. }
  97. // --- End Dropdown Logic ---
  98. </script>