mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-10 04:22:09 +10:00
* feat: add new language selector in footer, add pirate language * fix: translations in title bar not updating * chore: refactor into separate component * fix: update translate url * fix: update pirate translation to use "ship" instead of "plank" for platform a very very necessary change
This commit is contained in:
142
components/LanguageSelector.vue
Normal file
142
components/LanguageSelector.vue
Normal file
@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div>
|
||||
<Listbox v-model="wiredLocale" as="div">
|
||||
<ListboxLabel class="block text-sm/6 font-medium text-zinc-400">{{
|
||||
$t("selectLanguage")
|
||||
}}</ListboxLabel>
|
||||
<div class="relative mt-2">
|
||||
<ListboxButton
|
||||
class="grid w-full cursor-default grid-cols-1 rounded-md bg-zinc-900 py-1.5 pr-2 pl-3 text-left text-zinc-300 outline-1 -outline-offset-1 outline-zinc-700 focus:outline-2 focus:-outline-offset-2 focus:outline-blue-600 sm:text-sm/6"
|
||||
>
|
||||
<span class="col-start-1 row-start-1 flex items-center gap-3 pr-6">
|
||||
<span alt="" class="-mt-0.5 shrink-0 rounded-full">{{
|
||||
localeToEmoji(wiredLocale)
|
||||
}}</span>
|
||||
<span class="block truncate">{{
|
||||
currentLocaleInformation?.name ?? wiredLocale
|
||||
}}</span>
|
||||
</span>
|
||||
<ChevronUpDownIcon
|
||||
class="col-start-1 row-start-1 size-5 self-center justify-self-end text-gray-500 sm:size-4"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</ListboxButton>
|
||||
|
||||
<transition
|
||||
leave-active-class="transition ease-in duration-100"
|
||||
leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0"
|
||||
>
|
||||
<ListboxOptions
|
||||
class="absolute z-10 mt-1 max-h-56 w-full overflow-auto rounded-md bg-zinc-900 py-1 text-base shadow-lg ring-1 ring-black/5 focus:outline-hidden sm:text-sm"
|
||||
>
|
||||
<ListboxOption
|
||||
v-for="listLocale in locales"
|
||||
:key="listLocale.code"
|
||||
v-slot="{ active, selected }"
|
||||
as="template"
|
||||
:value="listLocale.code"
|
||||
>
|
||||
<li
|
||||
:class="[
|
||||
active
|
||||
? 'bg-blue-600 text-white outline-hidden'
|
||||
: 'text-zinc-300',
|
||||
'relative cursor-default py-2 pr-9 pl-3 select-none',
|
||||
]"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<span class="-mt-0.5 shrink-0 rounded-full">
|
||||
{{ localeToEmoji(listLocale.code) }}
|
||||
</span>
|
||||
<span
|
||||
:class="[
|
||||
selected ? 'font-semibold' : 'font-normal',
|
||||
'ml-3 block truncate',
|
||||
]"
|
||||
>{{ listLocale.name }}</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<span
|
||||
v-if="selected"
|
||||
:class="[
|
||||
active ? 'text-white' : 'text-blue-600',
|
||||
'absolute inset-y-0 right-0 flex items-center pr-4',
|
||||
]"
|
||||
>
|
||||
<CheckIcon class="size-5" aria-hidden="true" />
|
||||
</span>
|
||||
</li>
|
||||
</ListboxOption>
|
||||
</ListboxOptions>
|
||||
</transition>
|
||||
</div>
|
||||
</Listbox>
|
||||
<NuxtLink
|
||||
class="mt-1 transition text-blue-500 hover:text-blue-600 text-sm"
|
||||
to="https://translate.droposs.org/projects/drop/"
|
||||
target="_blank"
|
||||
>
|
||||
<i18n-t
|
||||
keypath="helpUsTranslate"
|
||||
tag="span"
|
||||
scope="global"
|
||||
class="inline-flex items-center gap-x-1 hover:underline"
|
||||
>
|
||||
<template #arrow>
|
||||
<ArrowTopRightOnSquareIcon class="size-4" />
|
||||
</template>
|
||||
</i18n-t>
|
||||
</NuxtLink>
|
||||
|
||||
<DevOnly
|
||||
><h1 class="mt-3 text-sm text-gray-500">{{ $t("welcome") }}</h1>
|
||||
</DevOnly>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
Listbox,
|
||||
ListboxButton,
|
||||
ListboxLabel,
|
||||
ListboxOption,
|
||||
ListboxOptions,
|
||||
} from "@headlessui/vue";
|
||||
import { ChevronUpDownIcon } from "@heroicons/vue/16/solid";
|
||||
import { ArrowTopRightOnSquareIcon } from "@heroicons/vue/24/outline";
|
||||
|
||||
const { locales, locale, setLocale } = useI18n();
|
||||
|
||||
function localeToEmoji(local: string): string {
|
||||
switch (local) {
|
||||
case "en":
|
||||
case "en-gb":
|
||||
case "en-ca":
|
||||
case "en-au":
|
||||
case "en-us": {
|
||||
return "🇺🇸";
|
||||
}
|
||||
case "en-pirate": {
|
||||
return "🏴☠️";
|
||||
}
|
||||
|
||||
default: {
|
||||
return "❓";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wiredLocale = computed({
|
||||
get() {
|
||||
return locale.value;
|
||||
},
|
||||
set(v) {
|
||||
setLocale(v);
|
||||
},
|
||||
});
|
||||
const currentLocaleInformation = computed(() =>
|
||||
locales.value.find((e) => e.code == wiredLocale.value),
|
||||
);
|
||||
</script>
|
||||
@ -13,7 +13,7 @@
|
||||
name="search"
|
||||
autocomplete="off"
|
||||
class="block w-full rounded-md bg-zinc-900 py-2 pl-9 pr-2 text-sm text-zinc-100 outline outline-1 -outline-offset-1 outline-zinc-700 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-blue-600"
|
||||
placeholder="$t('library.search')"
|
||||
:placeholder="$t('library.search')"
|
||||
/>
|
||||
<MagnifyingGlassIcon
|
||||
class="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-zinc-400"
|
||||
|
||||
@ -8,6 +8,9 @@
|
||||
<p class="text-sm leading-6 text-zinc-300">
|
||||
{{ $t("drop.desc") }}
|
||||
</p>
|
||||
|
||||
<LanguageSelector />
|
||||
|
||||
<div class="flex space-x-6">
|
||||
<NuxtLink
|
||||
v-for="item in navigation.social"
|
||||
@ -90,6 +93,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { IconsDiscordLogo, IconsGithubLogo } from "#components";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const navigation = {
|
||||
|
||||
@ -54,7 +54,6 @@
|
||||
</transition>
|
||||
</Menu>
|
||||
</li>
|
||||
<UserHeaderSelectLang />
|
||||
<UserHeaderUserWidget />
|
||||
</ol>
|
||||
</div>
|
||||
@ -176,9 +175,7 @@
|
||||
</UserHeaderWidget>
|
||||
</li>
|
||||
<li class="w-full">
|
||||
<UserHeaderWidget class="w-full">
|
||||
<UserHeaderSelectLang />
|
||||
</UserHeaderWidget>
|
||||
<UserHeaderWidget class="w-full" />
|
||||
</li>
|
||||
</div>
|
||||
</nav>
|
||||
@ -209,7 +206,7 @@ const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
|
||||
const homepageURL = "/store";
|
||||
const navigation: Array<NavigationItem> = [
|
||||
const navigation: Ref<Array<NavigationItem>> = computed(() => [
|
||||
{
|
||||
prefix: "/store",
|
||||
route: "/store",
|
||||
@ -230,9 +227,9 @@ const navigation: Array<NavigationItem> = [
|
||||
route: "/news",
|
||||
label: t("userHeader.links.news"),
|
||||
},
|
||||
];
|
||||
]);
|
||||
|
||||
const currentPageIndex = useCurrentNavigationIndex(navigation);
|
||||
const currentPageIndex = useCurrentNavigationIndex(navigation.value);
|
||||
|
||||
const notifications = useNotifications();
|
||||
const unreadNotifications = computed(() =>
|
||||
|
||||
@ -1,78 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { Menu, MenuButton, MenuItems, MenuItem } from "@headlessui/vue";
|
||||
import { ChevronDownIcon } from "@heroicons/vue/16/solid";
|
||||
|
||||
const { locales, locale: currLocale, setLocale } = useI18n();
|
||||
|
||||
function localToEmoji(local: string): string {
|
||||
switch (local) {
|
||||
case "en":
|
||||
case "en-gb":
|
||||
case "en-ca":
|
||||
case "en-au":
|
||||
case "en-us": {
|
||||
return "🇺🇸";
|
||||
}
|
||||
case "en-pirate": {
|
||||
return "🏴☠️";
|
||||
}
|
||||
|
||||
default: {
|
||||
return "❓";
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Menu as="div" class="relative inline-block">
|
||||
<MenuButton>
|
||||
<UserHeaderWidget>
|
||||
<div
|
||||
class="inline-flex items-center text-zinc-300 hover:text-white h-5"
|
||||
>
|
||||
<EmojiText :emoji="localToEmoji(currLocale)" />
|
||||
<!-- <span class="ml-2 text-sm font-bold">{{ locale }}</span> -->
|
||||
<ChevronDownIcon class="ml-3 h-4" />
|
||||
</div>
|
||||
</UserHeaderWidget>
|
||||
</MenuButton>
|
||||
|
||||
<transition
|
||||
enter-active-class="transition ease-out duration-100"
|
||||
enter-from-class="transform opacity-0 scale-95"
|
||||
enter-to-class="transform opacity-100 scale-100"
|
||||
leave-active-class="transition ease-in duration-75"
|
||||
leave-from-class="transform opacity-100 scale-100"
|
||||
leave-to-class="transform opacity-0 scale-95"
|
||||
>
|
||||
<MenuItems
|
||||
class="absolute right-0 top-10 z-50 w-56 origin-top-right focus:outline-none shadow-md"
|
||||
>
|
||||
<PanelWidget class="flex-col gap-y-2">
|
||||
<div class="flex flex-col">
|
||||
<MenuItem
|
||||
v-for="locale in locales"
|
||||
:key="locale.code"
|
||||
hydrate-on-visible
|
||||
as="div"
|
||||
>
|
||||
<button @click="setLocale(locale.code)">
|
||||
<EmojiText :emoji="localToEmoji(locale.code)" />
|
||||
{{ locale.name }}
|
||||
</button>
|
||||
</MenuItem>
|
||||
</div>
|
||||
</PanelWidget>
|
||||
</MenuItems>
|
||||
</transition>
|
||||
</Menu>
|
||||
</template>
|
||||
<style scoped>
|
||||
img.emoji {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
margin: 0 0.05em 0 0.1em;
|
||||
vertical-align: -0.1em;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user