mirror of
https://github.com/upscayl/upscayl.git
synced 2024-11-23 23:21:05 +01:00
Add Language Switcher (#950)
* Remove circle bar * Add initial language switcher support
This commit is contained in:
parent
de34063565
commit
326aaca7e4
@ -3,7 +3,7 @@
|
||||
**/
|
||||
|
||||
const nextConfig = {
|
||||
output: 'export',
|
||||
output: "export",
|
||||
images: {
|
||||
unoptimized: true,
|
||||
},
|
||||
|
2873
package-lock.json
generated
2873
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -213,12 +213,12 @@
|
||||
"daisyui": "^4.10.2",
|
||||
"electron": "^27.3.10",
|
||||
"electron-builder": "^24.13.3",
|
||||
"next": "^14.1.1",
|
||||
"next": "^14.2.7",
|
||||
"postcss": "^8.4.31",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-plugin-tailwindcss": "^0.4.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"tailwindcss": "^3.3.5",
|
||||
"typescript": "^4.8.4"
|
||||
},
|
||||
@ -236,6 +236,7 @@
|
||||
"electron-next": "^3.1.5",
|
||||
"electron-settings": "^4.0.3",
|
||||
"electron-updater": "^6.3.0",
|
||||
"eslint-config-next": "^14.2.7",
|
||||
"firebase": "^10.11.0",
|
||||
"gray-matter": "^4.0.3",
|
||||
"jotai": "^2.2.2",
|
||||
|
34
renderer/atoms/translations-atom.ts
Normal file
34
renderer/atoms/translations-atom.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { atom } from "jotai";
|
||||
import en from "../locales/en.json";
|
||||
import ru from "../locales/ru.json";
|
||||
import { atomWithStorage } from "jotai/utils";
|
||||
|
||||
// Define the shape of the translations
|
||||
type Translations = typeof en;
|
||||
type Locales = "en" | "ru";
|
||||
|
||||
// Utility function to access nested translation keys
|
||||
const getNestedTranslation = (obj: Translations, key: string): string => {
|
||||
return (
|
||||
key.split(".").reduce((acc, part) => acc && (acc as any)[part], obj) || key
|
||||
);
|
||||
};
|
||||
|
||||
// Atom to store the current locale
|
||||
export const localeAtom = atomWithStorage<Locales>("language", "en");
|
||||
|
||||
// Atom to get the translation function based on the current locale
|
||||
export const translationAtom = atom((get) => {
|
||||
const locale = get(localeAtom);
|
||||
const translations: Record<Locales, Translations> = { en, ru };
|
||||
|
||||
return (key: string, params: Record<string, string> = {}): string => {
|
||||
const template = getNestedTranslation(translations[locale], key);
|
||||
|
||||
// Replace placeholders with parameters, e.g., {name} => John
|
||||
return Object.keys(params).reduce(
|
||||
(str, paramKey) => str.replace(`{${paramKey}}`, params[paramKey]),
|
||||
template,
|
||||
);
|
||||
};
|
||||
});
|
@ -21,6 +21,7 @@ import TurnOffNotificationsToggle from "./TurnOffNotificationsToggle";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { CustomResolutionInput } from "./CustomResolutionInput";
|
||||
import { TileSizeInput } from "./TileSizeInput";
|
||||
import LanguageSwitcher from "./language-switcher";
|
||||
|
||||
interface IProps {
|
||||
batchMode: boolean;
|
||||
@ -212,6 +213,8 @@ function SettingsTab({
|
||||
{/* THEME SELECTOR */}
|
||||
<ThemeSelect />
|
||||
|
||||
<LanguageSwitcher />
|
||||
|
||||
{/* IMAGE FORMAT BUTTONS */}
|
||||
<ImageFormatSelect
|
||||
batchMode={batchMode}
|
||||
|
36
renderer/components/settings-tab/language-switcher.tsx
Normal file
36
renderer/components/settings-tab/language-switcher.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import { localeAtom, translationAtom } from "@/atoms/translations-atom";
|
||||
import { useAtomValue, useSetAtom } from "jotai";
|
||||
|
||||
const locales = {
|
||||
en: "English",
|
||||
ru: "Русский",
|
||||
};
|
||||
|
||||
const LanguageSwitcher = () => {
|
||||
const setLocale = useSetAtom(localeAtom);
|
||||
const t = useAtomValue(translationAtom);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<p className="text-sm font-medium">{t("settings.language")}</p>
|
||||
<select
|
||||
data-choose-theme
|
||||
className="select select-primary"
|
||||
onChange={(e) => setLocale(e.target.value as any)}
|
||||
>
|
||||
{Object.entries(locales).map((entry) => {
|
||||
const [locale, label] = entry;
|
||||
return (
|
||||
<option value={locale} key={locale}>
|
||||
{label.toLocaleUpperCase()}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LanguageSwitcher;
|
5
renderer/locales/en.json
Normal file
5
renderer/locales/en.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"settings": {
|
||||
"language": "Change Language"
|
||||
}
|
||||
}
|
5
renderer/locales/ru.json
Normal file
5
renderer/locales/ru.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"settings": {
|
||||
"language": "Меняй язык"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user