1
0
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:
Nayam Amarshe 2024-08-31 19:09:05 +05:30 committed by Aaron Liu
parent de34063565
commit 326aaca7e4
No known key found for this signature in database
GPG Key ID: 2D4DA57B12065A35
8 changed files with 2842 additions and 123 deletions

View File

@ -3,7 +3,7 @@
**/
const nextConfig = {
output: 'export',
output: "export",
images: {
unoptimized: true,
},

2873
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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",

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

View File

@ -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}

View 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
View File

@ -0,0 +1,5 @@
{
"settings": {
"language": "Change Language"
}
}

5
renderer/locales/ru.json Normal file
View File

@ -0,0 +1,5 @@
{
"settings": {
"language": "Меняй язык"
}
}