mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-10-28 12:45:47 +00:00
feat: add language selector
This commit is contained in:
40
site/src/components/language-selector/language-selector.tsx
Normal file
40
site/src/components/language-selector/language-selector.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { ComboboxItem, Select } from "@mantine/core";
|
||||||
|
import { useState } from "react";
|
||||||
|
import i18n from "../../lib/i18n/i18n";
|
||||||
|
import {
|
||||||
|
SupportedLanguage,
|
||||||
|
getLanguageName,
|
||||||
|
languages,
|
||||||
|
} from "../../lib/i18n/locales";
|
||||||
|
|
||||||
|
export const LanguageSelector = () => {
|
||||||
|
const [language, setLanguage] = useState<ComboboxItem>({
|
||||||
|
value: i18n.language,
|
||||||
|
label: getLanguageName(i18n.language as SupportedLanguage),
|
||||||
|
});
|
||||||
|
|
||||||
|
const languageOptions = Object.entries(languages).map(([code, name]) => ({
|
||||||
|
value: code,
|
||||||
|
label: name,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const handleLanguageChange = (option: string) => {
|
||||||
|
i18n.changeLanguage(option as SupportedLanguage);
|
||||||
|
setLanguage({
|
||||||
|
value: option,
|
||||||
|
label: getLanguageName(option as SupportedLanguage),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
data={languageOptions}
|
||||||
|
value={language ? language.value : null}
|
||||||
|
onChange={(_value, option) => handleLanguageChange(option.value)}
|
||||||
|
allowDeselect={false}
|
||||||
|
pos="absolute"
|
||||||
|
right={10}
|
||||||
|
top={10}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
import { Center, Flex } from "@mantine/core";
|
import { Center, Flex } from "@mantine/core";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
import { LanguageSelector } from "../language-selector/language-selector";
|
||||||
|
|
||||||
export const Layout = ({ children }: { children: ReactNode }) => {
|
export const Layout = ({ children }: { children: ReactNode }) => {
|
||||||
return (
|
return (
|
||||||
<Center style={{ minHeight: "100vh" }}>
|
<>
|
||||||
<Flex direction="column" flex="1" maw={350}>
|
<LanguageSelector />
|
||||||
{children}
|
<Center style={{ minHeight: "100vh" }}>
|
||||||
</Flex>
|
<Flex direction="column" flex="1" maw={340}>
|
||||||
</Center>
|
{children}
|
||||||
|
</Flex>
|
||||||
|
</Center>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,5 +16,4 @@ i18n
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export default i18n;
|
export default i18n;
|
||||||
36
site/src/lib/i18n/locales.ts
Normal file
36
site/src/lib/i18n/locales.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
export const languages = {
|
||||||
|
"af-ZA": "Afrikaans",
|
||||||
|
"ar-SA": "العربية",
|
||||||
|
"ca-ES": "Català",
|
||||||
|
"cs-CZ": "Čeština",
|
||||||
|
"da-DK": "Dansk",
|
||||||
|
"de-DE": "Deutsch",
|
||||||
|
"el-GR": "Ελληνικά",
|
||||||
|
"en-US": "English",
|
||||||
|
"es-ES": "Español",
|
||||||
|
"fi-FI": "Suomi",
|
||||||
|
"fr-FR": "Français",
|
||||||
|
"he-IL": "עברית",
|
||||||
|
"hu-HU": "Magyar",
|
||||||
|
"it-IT": "Italiano",
|
||||||
|
"ja-JP": "日本語",
|
||||||
|
"ko-KR": "한국어",
|
||||||
|
"nl-NL": "Nederlands",
|
||||||
|
"no-NO": "Norsk",
|
||||||
|
"pl-PL": "Polski",
|
||||||
|
"pt-BR": "Português",
|
||||||
|
"pt-PT": "Português",
|
||||||
|
"ro-RO": "Română",
|
||||||
|
"ru-RU": "Русский",
|
||||||
|
"sr-SP": "Српски",
|
||||||
|
"sv-SE": "Svenska",
|
||||||
|
"tr-TR": "Türkçe",
|
||||||
|
"uk-UA": "Українська",
|
||||||
|
"vi-VN": "Tiếng Việt",
|
||||||
|
"zh-CN": "中文",
|
||||||
|
"zh-TW": "中文"
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SupportedLanguage = keyof typeof languages;
|
||||||
|
|
||||||
|
export const getLanguageName = (language: SupportedLanguage): string => languages[language];
|
||||||
Reference in New Issue
Block a user