Hanye官网
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

LanguageSwitcher.vue 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <template>
  2. <div class="relative inline-block text-left " ref="dropdownContainerRef">
  3. <div
  4. @click="toggleDropdown"
  5. class="flex justify-center items-center gap-2 text-white opacity-80 text-sm"
  6. >
  7. <i class="icon-i18n"></i>
  8. {{ currentLocaleName || "Language" }}
  9. </div>
  10. <transition
  11. enter-active-class="transition ease-out duration-100"
  12. enter-from-class="transform opacity-0 scale-95"
  13. enter-to-class="transform opacity-100 scale-100"
  14. leave-active-class="transition ease-in duration-75"
  15. leave-from-class="transform opacity-100 scale-100"
  16. leave-to-class="transform opacity-0 scale-95"
  17. >
  18. <div
  19. v-if="isDropdownOpen"
  20. class="origin-top-right absolute right-0 mt-2 w-36 rounded-md shadow-lg bg-[var(--color-bg)] ring-1 ring-black ring-opacity-5 focus:outline-none z-10"
  21. role="menu"
  22. aria-orientation="vertical"
  23. aria-labelledby="options-menu"
  24. >
  25. <div class="py-1" role="none">
  26. <a
  27. v-for="locale in availableLocales"
  28. :key="locale.code"
  29. href="#"
  30. @click.prevent="selectLanguage(locale.code)"
  31. :class="[
  32. 'block px-4 py-2 text-sm opacity-80',
  33. currentLocale === locale.code
  34. ? 'text-white opacity-100 font-bold'
  35. : 'text-white hover: opacity-100',
  36. ]"
  37. role="menuitem"
  38. >
  39. {{ locale.name }}
  40. </a>
  41. </div>
  42. </div>
  43. </transition>
  44. </div>
  45. </template>
  46. <script setup lang="ts">
  47. /**
  48. * 语言切换组件 - 下拉菜单样式
  49. * 支持切换配置的语言
  50. */
  51. import { ref, computed } from "vue";
  52. import { useI18n } from "#imports"; // 修正 useI18n 导入
  53. import { onClickOutside } from "@vueuse/core"; // 导入 onClickOutside
  54. // 定义语言代码的类型,应该与 i18n 配置中的一致
  55. type LocaleCode = "zh" | "en" | "ja"; // 你需要根据你的 i18n 配置更新这个类型
  56. const { locale, locales, setLocale } = useI18n();
  57. const currentLocale = computed(() => locale.value);
  58. const isDropdownOpen = ref(false);
  59. const dropdownContainerRef = ref(null); // 创建 ref
  60. // 可用语言列表
  61. const availableLocales = computed(() => {
  62. // 确保 locales.value 是一个数组并且包含 code 和 name 属性
  63. return (
  64. (locales.value as Array<{ code: string; name: string }>) || []
  65. ).filter((l) => l.code && l.name);
  66. });
  67. // 当前选中语言的名称
  68. const currentLocaleName = computed(() => {
  69. const current = availableLocales.value.find(
  70. (l) => l.code === currentLocale.value
  71. );
  72. return current ? current.name : "";
  73. });
  74. /**
  75. * 切换下拉菜单的显示/隐藏状态
  76. */
  77. function toggleDropdown() {
  78. isDropdownOpen.value = !isDropdownOpen.value;
  79. }
  80. /**
  81. * 选择语言并关闭下拉菜单
  82. * @param {string} langCode - 选择的语言代码
  83. */
  84. async function selectLanguage(langCode: string) {
  85. if (currentLocale.value !== langCode) {
  86. try {
  87. // 使用类型断言,确保 langCode 是有效的 LocaleCode
  88. await setLocale(langCode as LocaleCode);
  89. } catch (error) {
  90. console.error("Failed to set locale:", error);
  91. // 这里可以添加用户反馈,例如显示一个错误提示
  92. }
  93. }
  94. isDropdownOpen.value = false; // 关闭下拉菜单
  95. }
  96. // 点击外部关闭下拉菜单
  97. onClickOutside(dropdownContainerRef, () => {
  98. if (isDropdownOpen.value) {
  99. isDropdownOpen.value = false;
  100. }
  101. });
  102. </script>