Add first i18n stuff

This commit is contained in:
Lokowitz 2025-05-04 15:11:42 +00:00
parent 21f1326045
commit 7eb08474ff
35 changed files with 2629 additions and 759 deletions

View 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')}
/>
);
}

View 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>
);
}

View file

@ -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" /> */}