mirror of
https://github.com/fosrl/pangolin.git
synced 2025-07-30 07:35:15 +02:00
Add first i18n stuff
This commit is contained in:
parent
21f1326045
commit
7eb08474ff
35 changed files with 2629 additions and 759 deletions
24
src/components/LocaleSwitcher.tsx
Normal file
24
src/components/LocaleSwitcher.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { useLocale, useTranslations } from 'next-intl';
|
||||
import LocaleSwitcherSelect from './LocaleSwitcherSelect';
|
||||
|
||||
export default function LocaleSwitcher() {
|
||||
const t = useTranslations('locales');
|
||||
const locale = useLocale();
|
||||
|
||||
return (
|
||||
<LocaleSwitcherSelect
|
||||
defaultValue={locale}
|
||||
items={[
|
||||
{
|
||||
value: 'en-US',
|
||||
label: t('en-US')
|
||||
},
|
||||
{
|
||||
value: 'de-DE',
|
||||
label: t('de-DE')
|
||||
}
|
||||
]}
|
||||
label={t('label')}
|
||||
/>
|
||||
);
|
||||
}
|
72
src/components/LocaleSwitcherSelect.tsx
Normal file
72
src/components/LocaleSwitcherSelect.tsx
Normal file
|
@ -0,0 +1,72 @@
|
|||
'use client';
|
||||
|
||||
import { CheckIcon, LanguageIcon } from '@heroicons/react/24/solid';
|
||||
import * as Select from '@radix-ui/react-select';
|
||||
import clsx from 'clsx';
|
||||
import { useTransition } from 'react';
|
||||
import { Locale } from '@/i18n/config';
|
||||
import { setUserLocale } from '@/services/locale';
|
||||
|
||||
type Props = {
|
||||
defaultValue: string;
|
||||
items: Array<{value: string; label: string}>;
|
||||
label: string;
|
||||
};
|
||||
|
||||
export default function LocaleSwitcherSelect({
|
||||
defaultValue,
|
||||
items,
|
||||
label
|
||||
}: Props) {
|
||||
const [isPending, startTransition] = useTransition();
|
||||
|
||||
function onChange(value: string) {
|
||||
const locale = value as Locale;
|
||||
startTransition(() => {
|
||||
setUserLocale(locale);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<Select.Root defaultValue={defaultValue} onValueChange={onChange}>
|
||||
<Select.Trigger
|
||||
aria-label={label}
|
||||
className={clsx(
|
||||
'rounded-sm p-2 transition-colors hover:bg-slate-200',
|
||||
isPending && 'pointer-events-none opacity-60'
|
||||
)}
|
||||
>
|
||||
<Select.Icon>
|
||||
<LanguageIcon className="h-6 w-6 text-slate-600 transition-colors group-hover:text-slate-900" />
|
||||
</Select.Icon>
|
||||
</Select.Trigger>
|
||||
<Select.Portal>
|
||||
<Select.Content
|
||||
align="end"
|
||||
className="min-w-[8rem] overflow-hidden rounded-sm bg-white py-1 shadow-md"
|
||||
position="popper"
|
||||
>
|
||||
<Select.Viewport>
|
||||
{items.map((item) => (
|
||||
<Select.Item
|
||||
key={item.value}
|
||||
className="flex cursor-default items-center px-3 py-2 text-base data-[highlighted]:bg-slate-100"
|
||||
value={item.value}
|
||||
>
|
||||
<div className="mr-2 w-[1rem]">
|
||||
{item.value === defaultValue && (
|
||||
<CheckIcon className="h-5 w-5 text-slate-600" />
|
||||
)}
|
||||
</div>
|
||||
<span className="text-slate-900">{item.label}</span>
|
||||
</Select.Item>
|
||||
))}
|
||||
</Select.Viewport>
|
||||
<Select.Arrow className="fill-white text-white" />
|
||||
</Select.Content>
|
||||
</Select.Portal>
|
||||
</Select.Root>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -23,6 +23,8 @@ import Disable2FaForm from "./Disable2FaForm";
|
|||
import Enable2FaForm from "./Enable2FaForm";
|
||||
import SupporterStatus from "./SupporterStatus";
|
||||
import { UserType } from "@server/types/UserTypes";
|
||||
import LocaleSwitcher from '@app/components/LocaleSwitcher';
|
||||
|
||||
|
||||
export default function ProfileIcon() {
|
||||
const { setTheme, theme } = useTheme();
|
||||
|
@ -157,6 +159,10 @@ export default function ProfileIcon() {
|
|||
</DropdownMenuItem>
|
||||
)
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
<div>
|
||||
<LocaleSwitcher />
|
||||
</div>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={() => logout()}>
|
||||
{/* <LogOut className="mr-2 h-4 w-4" /> */}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue